Skip to content

Commit

Permalink
PHP Demo - Integration Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mwarzybok-sumoheavy committed Mar 23, 2023
1 parent 9ff1775 commit 7640459
Show file tree
Hide file tree
Showing 19 changed files with 303 additions and 51 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.phpunit.cache
/codeCoverage
/node_modules
/public/build
/public/hot
Expand Down
16 changes: 8 additions & 8 deletions app/Features/Invoice/UpdateInvoice/UpdateInvoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ public function usingBitPayUpdateResponse(string $uuid, array $data): Invoice
throw new MissingInvoice('Missing invoice');
}

$client = $this->bitPayClientFactory->create();
$bitPayInvoice = $client->getInvoice(
$invoice->bitpay_id,
$this->bitPayConfiguration->getFacade(),
$this->bitPayConfiguration->isSignRequest()
);

try {
$client = $this->bitPayClientFactory->create();
$bitPayInvoice = $client->getInvoice(
$invoice->bitpay_id,
$this->bitPayConfiguration->getFacade(),
$this->bitPayConfiguration->isSignRequest()
);

$updateInvoiceData = $this->bitPayUpdateMapper->execute($data)->toArray();
$this->updateInvoiceValidator->execute($data, $bitPayInvoice);
$this->updateInvoice($invoice, $updateInvoiceData);
} catch (\Exception $e) {
} catch (\Exception|\TypeError $e) {
$this->logger->error('INVOICE_UPDATE_FAIL', 'Failed to update invoice', [
'id' => $invoice->id
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ public function execute(?array $data, ?BitPayInvoice $bitPayInvoice): void
throw new ValidationFailed('For IPN request, we need original BitPay model');
}

$uuid = $data['uuid'] ?? null;
if (!$uuid) {
throw new ValidationFailed('Missing uuid');
$bitPayId = $data['id'] ?? null;
if (!$bitPayId || $bitPayId !== $bitPayInvoice->getId()) {
throw new ValidationFailed('Wrong order id');
}

$orderId = $data['orderId'] ?? null;
if (!$orderId || $orderId !== $bitPayInvoice->getOrderId()) {
throw new ValidationFailed('Wrong order id');
}

$this->logger->info('IPN_VALIDATE_SUCCESS', 'Successfully validated IP', ['uuid' => $uuid]);
$this->logger->info('IPN_VALIDATE_SUCCESS', 'Successfully validated IP', ['bitpay_id' => $bitPayId]);
} catch (ValidationFailed $e) {
$this->logger->info('IPN_VALIDATE_FAIL', 'Failed to validate IPN', [
'errorMessage' => $e->getMessage(),
Expand Down
5 changes: 2 additions & 3 deletions app/Http/Controllers/Invoice/GetInvoiceViewController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use App\Repository\InvoiceRepositoryInterface;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class GetInvoiceViewController extends Controller
{
Expand Down Expand Up @@ -45,9 +46,7 @@ public function execute(Request $request, int $id): View
/** @var Invoice $invoice */
$invoice = $this->invoiceRepository->findOne($id);
if (!$invoice) {
return view('pages.invoice.missingInvoice', [
'configuration' => $this->bitPayConfiguration
]);
abort(Response::HTTP_NOT_FOUND);
}

$this->logger->info('INVOICE_GET', 'Loaded invoice', ['id' => $id]);
Expand Down
9 changes: 8 additions & 1 deletion app/Http/Controllers/Invoice/UpdateInvoiceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Http\Controllers\Invoice;

use App\Exceptions\MissingInvoice;
use App\Features\Invoice\UpdateInvoice\UpdateInvoice;
use App\Features\Shared\Logger;
use App\Http\Controllers\Controller;
Expand All @@ -28,7 +29,13 @@ public function execute(Request $request, string $uuid): Response
/** @var array $data */
$data = $request->request->get('data');
$data['uuid'] = $uuid;
$this->updateInvoice->usingBitPayUpdateResponse($uuid, $data);
try {
$this->updateInvoice->usingBitPayUpdateResponse($uuid, $data);
} catch (MissingInvoice $e) {
return response(null, Response::HTTP_NOT_FOUND);
} catch (\Exception $e) {
return response('Unable to process update', Response::HTTP_BAD_REQUEST);
}

return response(null, Response::HTTP_NO_CONTENT);
}
Expand Down
12 changes: 6 additions & 6 deletions database/migrations/2023_03_01_122625_create_bitpay_table.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,17 @@ public function up(): void
$table->bigInteger('invoice_buyer_id')->unsigned();
$table->bigInteger('invoice_refund_id')->unsigned()->nullable(true);
$table->text('pos_data_json')->nullable(true);
$table->float('price')->nullable(true);
$table->string('currency_code')->nullable(true);
$table->string('bitpay_id')->nullable(true);
$table->string('status')->nullable(true);
$table->float('price')->nullable(false);
$table->string('currency_code')->nullable(false);
$table->string('bitpay_id')->nullable(false);
$table->string('status')->nullable(false);
$table->dateTime('created_date')->nullable(true);
$table->dateTime('expiration_time')->nullable(true);
$table->string('bitpay_order_id')->nullable(true);
$table->string('bitpay_order_id')->nullable(false);
$table->string('facade_type')->nullable(true);
$table->string('bitpay_guid')->nullable(true);
$table->string('exception_status')->nullable(true);
$table->string('bitpay_url')->nullable(true);
$table->string('bitpay_url')->nullable(false);
$table->string('redirect_url')->nullable(true);
$table->string('close_url')->nullable(true);
$table->integer('acceptance_window')->nullable(true);
Expand Down
10 changes: 10 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,26 @@
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
cacheResult ="false"
>
<testsuites>
<testsuite name="Integration">
<directory suffix="Test.php">./tests/Integration</directory>
</testsuite>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">./app</directory>
</include>
<exclude>
<directory suffix=".php">./app/Infrastructure</directory>
</exclude>
<report>
<html outputDirectory="./codeCoverage/html" />
</report>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
Expand Down
9 changes: 0 additions & 9 deletions resources/views/pages/invoice/missingInvoice.blade.php

This file was deleted.

9 changes: 9 additions & 0 deletions tests/ExampleInvoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,22 @@ class ExampleInvoice
{
public const UUID = '04373e9d-d265-4a07-aea4-c8a67c253968';
public const TOKEN = 'someToken';
public const BITPAY_ID = 'someBitpayId';
public const BITPAY_ORDER_ID = 'someBitpayOrderId';
public const ITEM_DESCRIPTION = 'someDecription';

public static function create(): Invoice
{
$invoice = new Invoice();
$invoice->uuid = self::UUID;
$invoice->price = 12.35;
$invoice->token = self::TOKEN;
$invoice->bitpay_id = self::BITPAY_ID;
$invoice->bitpay_order_id = self::BITPAY_ORDER_ID;
$invoice->bitpay_url = 'someBitpayUrl';
$invoice->status = 'new';
$invoice->currency_code = 'USD';
$invoice->item_description = self::ITEM_DESCRIPTION;

$invoiceBuyer = new InvoiceBuyer([
'name' => 'SomeName',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@

namespace Tests\Integration\Features\Invoice\UpdateInvoice;

use App\Features\Invoice\UpdateInvoice\BitPayUpdateMapper;
use App\Features\Invoice\UpdateInvoice\SendUpdateInvoiceNotification;
use App\Features\Invoice\UpdateInvoice\UpdateInvoice;
use App\Http\Services\BitPayClientFactory;
use App\Repository\InvoiceRepositoryInterface;
use Illuminate\Foundation\Testing\RefreshDatabase;
use BitPaySDK\Model\Facade;
use BitPaySDK\Model\Invoice\Invoice;
use BitPaySDK\PosClient;
use Mockery\MockInterface;
use PHPUnit\Framework\Assert;
use Tests\ExampleInvoice;
use Tests\TestCase;
use Tests\Integration\IntegrationTest;

class UpdateInvoiceTest extends TestCase
class UpdateInvoiceTest extends IntegrationTest
{
use RefreshDatabase;

/**
* @test
*/
Expand All @@ -27,13 +28,29 @@ public function it_should_update_invoice_and_send_update_notification()

ExampleInvoice::createSaved();

$this->mock(BitPayClientFactory::class, function (MockInterface $mock) {
$mock->shouldReceive('create')->andReturn(new class('', '') extends PosClient {
public function getInvoice(string $invoiceId, string $facade = Facade::Merchant, bool $signRequest = true): Invoice
{
$invoice = new Invoice();
$invoice->setId(ExampleInvoice::BITPAY_ID);
$invoice->setOrderId(ExampleInvoice::BITPAY_ORDER_ID);

return $invoice;
}
});
});
$this->mock(SendUpdateInvoiceNotification::class, function (MockInterface $mock) {
$mock->shouldReceive('execute')->times(1);
});

$testedClass = $this->getTestedClass();
$testedClass->usingBitPayUpdateResponse(ExampleInvoice::UUID, $data);

$invoice = $this->app->make(InvoiceRepositoryInterface::class)->findOne(1);

Assert::assertEquals(ExampleInvoice::TOKEN, $invoice->token);
Assert::assertEquals('MV9fy5iNDkqrg4qrfYpw75', $invoice->bitpay_id);
Assert::assertEquals('someBitpayId', $invoice->bitpay_id);
Assert::assertEquals('https://test.bitpay.com/invoice?id=MV9fy5iNDkqrg4qrfYpw75', $invoice->bitpay_url);
Assert::assertEquals("{\"store\":\"store-1\",\"register\":\"2\",\"reg_transaction_no\":\"87678\",\"price\":\"76.70\"}", $invoice->pos_data_json);
Assert::assertEquals('expired', $invoice->status);
Expand All @@ -48,15 +65,11 @@ public function it_should_update_invoice_and_send_update_notification()
Assert::assertEquals(347100, $btc->total);
Assert::assertEquals(342800, $btc->subtotal);
Assert::assertEquals(0, $invoice->getInvoicePayment()->amount_paid);
Assert::assertEquals('640f27154e58f8.40716035', $invoice->bitpay_order_id);
Assert::assertEquals('someBitpayOrderId', $invoice->bitpay_order_id);
}

private function getTestedClass()
private function getTestedClass(): UpdateInvoice
{
return new UpdateInvoice(
$this->app->make(InvoiceRepositoryInterface::class),
$this->app->make(BitPayUpdateMapper::class),
$this->app->make(SendUpdateInvoiceNotification::class)
);
return $this->app->make(UpdateInvoice::class);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "MV9fy5iNDkqrg4qrfYpw75",
"id": "someBitpayId",
"url": "https://test.bitpay.com/invoice?id=MV9fy5iNDkqrg4qrfYpw75",
"posData": "{\"store\":\"store-1\",\"register\":\"2\",\"reg_transaction_no\":\"87678\",\"price\":\"76.70\"}",
"status": "expired",
Expand Down Expand Up @@ -40,5 +40,5 @@
},
"exchangeRates": {},
"amountPaid": 0,
"orderId": "640f27154e58f8.40716035"
"orderId": "someBitpayOrderId"
}
4 changes: 3 additions & 1 deletion tests/Integration/Features/Shared/InvoiceSaverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class InvoiceSaverTest extends TestCase
public function it_should_save_bitpay_invoice_to_db(): void
{
$bitpayInvoice = (new ExampleSdkInvoice())->get();
$applicationInvoice = $this->getTestedClass()->fromSdkModel($bitpayInvoice);
$uuid = '1234';
$applicationInvoice = $this->getTestedClass()->fromSdkModel($bitpayInvoice, $uuid);

/** @var InvoiceTransaction $transaction */
$transaction = $applicationInvoice->invoiceTransactions()->getResults()[0];
Expand All @@ -33,6 +34,7 @@ public function it_should_save_bitpay_invoice_to_db(): void
$invoiceRefund = $applicationInvoice->getInvoiceRefund();
$refundInfo = $invoiceRefund->getInvoiceRefundInfo();

Assert::assertEquals($uuid, $applicationInvoice->uuid);
Assert::assertEquals($bitpayInvoice->getCurrency(), $applicationInvoice->currency_code);
Assert::assertEquals($bitpayInvoice->getGuid(), $applicationInvoice->bitpay_guid);
Assert::assertEquals($bitpayInvoice->getToken(), $applicationInvoice->token);
Expand Down
38 changes: 38 additions & 0 deletions tests/Integration/Http/CreateInvoiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Tests\Integration\Http;

use App\Repository\InvoiceRepositoryInterface;
use Tests\Integration\IntegrationTest;

class CreateInvoiceTest extends IntegrationTest
{
/**
* @test
*/
public function it_should_fill_form_and_create_bitpay_invoice(): void
{
$this->post('/invoices', [
'_token' => 'FsBmW4CMKpw8zjEBO9F3TQu9tGBbcTJkPQPKcGv7',
'store' => 'store-1',
'register' => '2',
'reg_transaction_no' => 'test123',
'price' => '23.54'
]);

/** @var InvoiceRepositoryInterface $invoiceRepository */
$invoiceRepository = $this->app->make(InvoiceRepositoryInterface::class);
$invoice = $invoiceRepository->findOne(1);

$this->assertNotNull($invoice);
$this->assertNotNull($invoice->bitpay_id);
$this->assertNotNull($invoice->bitpay_order_id);
$this->assertEquals(
'{"store":"store-1","register":"2","reg_transaction_no":"test123","price":"23.54"}',
$invoice->pos_data_json
);
$this->assertEquals(23.54, $invoice->price);
}
}
35 changes: 35 additions & 0 deletions tests/Integration/Http/GetInvoiceViewControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Tests\Integration\Http;

use Symfony\Component\HttpFoundation\Response;
use Tests\ExampleInvoice;
use Tests\Integration\IntegrationTest;

class GetInvoiceViewControllerTest extends IntegrationTest
{
/**
* @test
*/
public function it_should_show_invoice_view(): void
{
$invoice = ExampleInvoice::createSaved();

$result = $this->get('/invoices/' . $invoice->id);
$result->assertSeeText(ExampleInvoice::BITPAY_ID);
$result->assertSeeText($invoice->price);
$result->assertSeeText($invoice->item_description);
$result->assertSeeText($invoice->status);
}

/**
* @test
*/
public function it_should_return_404_for_non_existing_invoice(): void
{
$result = $this->get('/invoices/1');
$this->assertEquals(Response::HTTP_NOT_FOUND, $result->getStatusCode());
}
}
29 changes: 29 additions & 0 deletions tests/Integration/Http/GetInvoicesControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
*
* @copyright Copyright 2022
* @author Marcin Warzybok <[email protected]>
*/
declare(strict_types=1);

namespace Tests\Integration\Http;

use Tests\ExampleInvoice;
use Tests\Integration\IntegrationTest;

class GetInvoicesControllerTest extends IntegrationTest
{
/**
* @test
*/
public function it_should_show_invoices_on_grid(): void
{
$invoice = ExampleInvoice::createSaved();

$result = $this->get('/invoices/');
$result->assertSeeText(ExampleInvoice::BITPAY_ID);
$result->assertSeeText($invoice->price);
$result->assertSeeText($invoice->item_description);
$result->assertSeeText($invoice->status);
}
}
Loading

0 comments on commit 7640459

Please sign in to comment.