Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<env name="MOYASAR_BASE_URL" value="https://api.moyasar.com/v1" />
<env name="REAL_TESTS" value="false" />
<env name="MOYASAR_SAMPLE_INITIATED_INVOICE_ID" value="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" />
<env name="MOYASAR_SAMPLE_AUTHORIZED_PAYMENT_ID" value="" />
<env name="MOYASAR_SAMPLE_PAID_PAYMENT_ID" value="" />
</php>
<testsuites>
<testsuite name="Test Suite">
Expand Down
2 changes: 1 addition & 1 deletion src/Payment/DTO/PaymentDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Saloon\Http\Response;
use Saloon\Traits\Responses\HasResponse;

final readonly class PaymentDTO
final class PaymentDTO
{
use HasResponse;

Expand Down
29 changes: 28 additions & 1 deletion tests/Config/MockResponses.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,28 @@

use Saloon\Http\Faking\MockResponse;
use Tests\Config\Samples\InvoiceSamples;
use Tests\Config\Samples\PaymentSamples;
use HamodaDev\Moyasar\Invoice\APIs\CancelInvoiceRequest;
use HamodaDev\Moyasar\Invoice\APIs\BulkCreateInvoicesRequest;
use HamodaDev\Moyasar\Invoice\APIs\CreateInvoiceRequest;
use HamodaDev\Moyasar\Invoice\APIs\GetInvoiceRequest;
use HamodaDev\Moyasar\Invoice\APIs\ListInvoicesRequest;
use HamodaDev\Moyasar\Invoice\APIs\UpdateInvoiceRequest;
use HamodaDev\Moyasar\Payment\APIs\CapturePaymentRequest;
use HamodaDev\Moyasar\Payment\APIs\CreatePaymentRequest;
use HamodaDev\Moyasar\Payment\APIs\GetPaymentRequest;
use HamodaDev\Moyasar\Payment\APIs\ListPaymentsRequest;
use HamodaDev\Moyasar\Payment\APIs\RefundPaymentRequest;
use HamodaDev\Moyasar\Payment\APIs\UpdatePaymentRequest;
use HamodaDev\Moyasar\Payment\APIs\VoidPaymentRequest;

class MockResponses
{
public static function getAll(): array
{
return array_merge(
self::invoiceResponses(),
// self::paymentResponses(), // TODO: add when payment mocks are ready
self::paymentResponses(),
);
}

Expand All @@ -43,4 +51,23 @@ private static function invoiceResponses(): array
CancelInvoiceRequest::class => MockResponse::make(body: InvoiceSamples::CANCELED_TEST_INVOICE),
];
}

private static function paymentResponses(): array
{
return [
CreatePaymentRequest::class => MockResponse::make(body: PaymentSamples::TEST_PAYMENT),
GetPaymentRequest::class => MockResponse::make(body: PaymentSamples::TEST_PAYMENT_3),
ListPaymentsRequest::class => MockResponse::make(body: [
'payments' => [
PaymentSamples::TEST_PAYMENT,
PaymentSamples::TEST_PAYMENT_2,
PaymentSamples::TEST_PAYMENT_3,
],
]),
UpdatePaymentRequest::class => MockResponse::make(body: PaymentSamples::TEST_PAYMENT),
RefundPaymentRequest::class => MockResponse::make(body: PaymentSamples::TEST_REFUNDED_PAYMENT),
CapturePaymentRequest::class => MockResponse::make(body: PaymentSamples::TEST_CAPTURED_PAYMENT),
VoidPaymentRequest::class => MockResponse::make(body: PaymentSamples::TEST_VOIDED_PAYMENT),
];
}
}
208 changes: 208 additions & 0 deletions tests/Config/Samples/PaymentSamples.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
<?php

namespace Tests\Config\Samples;

class PaymentSamples
{
public const array TEST_PAYMENT = [
'id' => 'pay_1',
'status' => 'paid',
'amount' => 10000,
'fee' => 50,
'currency' => 'SAR',
'refunded' => 0,
'refunded_at' => null,
'captured' => 10000,
'captured_at' => '2024-01-15T12:00:00Z',
'voided_at' => null,
'description' => 'Test payment',
'amount_format' => '100.00 SAR',
'fee_format' => '0.50 SAR',
'refunded_format' => '0.00 SAR',
'captured_format' => '100.00 SAR',
'invoice_id' => null,
'ip' => '127.0.0.1',
'callback_url' => 'https://example.com/webhooks/moyasar',
'created_at' => '2024-01-15T10:00:00Z',
'updated_at' => '2024-01-15T12:00:00Z',
'metadata' => [
'order_id' => '1234',
],
'source' => [
'type' => 'creditcard',
'company' => 'visa',
'name' => 'John Doe',
'number' => '**** **** **** 1111',
'message' => null,
],
'given_id' => null,
];

public const array TEST_PAYMENT_2 = [
'id' => 'pay_2',
'status' => 'paid',
'amount' => 2500,
'fee' => 25,
'currency' => 'SAR',
'refunded' => 0,
'refunded_at' => null,
'captured' => 2500,
'captured_at' => '2024-02-01T08:00:00Z',
'voided_at' => null,
'description' => 'Second test payment',
'amount_format' => '25.00 SAR',
'fee_format' => '0.25 SAR',
'refunded_format' => '0.00 SAR',
'captured_format' => '25.00 SAR',
'invoice_id' => null,
'ip' => '192.168.1.1',
'callback_url' => null,
'created_at' => '2024-02-01T07:00:00Z',
'updated_at' => '2024-02-01T08:00:00Z',
'metadata' => [],
'source' => [
'type' => 'creditcard',
'company' => 'mastercard',
'name' => 'Jane Doe',
'number' => '**** **** **** 4242',
'message' => null,
],
'given_id' => 'order_5678',
];

public const array TEST_PAYMENT_3 = [
'id' => 'pay_3',
'status' => 'paid',
'amount' => 6900,
'fee' => 35,
'currency' => 'EGP',
'refunded' => 0,
'refunded_at' => null,
'captured' => 6900,
'captured_at' => '2024-03-01T09:00:00Z',
'voided_at' => null,
'description' => 'Third test payment',
'amount_format' => '69.00 EGP',
'fee_format' => '0.35 EGP',
'refunded_format' => '0.00 EGP',
'captured_format' => '69.00 EGP',
'invoice_id' => null,
'ip' => '10.0.0.1',
'callback_url' => null,
'created_at' => '2024-03-01T08:00:00Z',
'updated_at' => '2024-03-01T09:00:00Z',
'metadata' => [
'order_id' => '333',
],
'source' => [
'type' => 'creditcard',
'company' => 'visa',
'name' => 'Test User',
'number' => '**** **** **** 8888',
'message' => null,
],
'given_id' => null,
];

public const array TEST_REFUNDED_PAYMENT = [
'id' => 'pay_1',
'status' => 'refunded',
'amount' => 10000,
'fee' => 50,
'currency' => 'SAR',
'refunded' => 10000,
'refunded_at' => '2024-01-20T14:00:00Z',
'captured' => 10000,
'captured_at' => '2024-01-15T12:00:00Z',
'voided_at' => null,
'description' => 'Test payment',
'amount_format' => '100.00 SAR',
'fee_format' => '0.50 SAR',
'refunded_format' => '100.00 SAR',
'captured_format' => '100.00 SAR',
'invoice_id' => null,
'ip' => '127.0.0.1',
'callback_url' => 'https://example.com/webhooks/moyasar',
'created_at' => '2024-01-15T10:00:00Z',
'updated_at' => '2024-01-20T14:00:00Z',
'metadata' => [
'order_id' => '1234',
],
'source' => [
'type' => 'creditcard',
'company' => 'visa',
'name' => 'John Doe',
'number' => '**** **** **** 1111',
'message' => null,
],
'given_id' => null,
];

public const array TEST_CAPTURED_PAYMENT = [
'id' => 'pay_1',
'status' => 'captured',
'amount' => 10000,
'fee' => 50,
'currency' => 'SAR',
'refunded' => 0,
'refunded_at' => null,
'captured' => 10000,
'captured_at' => '2024-01-15T12:00:00Z',
'voided_at' => null,
'description' => 'Test payment',
'amount_format' => '100.00 SAR',
'fee_format' => '0.50 SAR',
'refunded_format' => '0.00 SAR',
'captured_format' => '100.00 SAR',
'invoice_id' => null,
'ip' => '127.0.0.1',
'callback_url' => 'https://example.com/webhooks/moyasar',
'created_at' => '2024-01-15T10:00:00Z',
'updated_at' => '2024-01-15T12:00:00Z',
'metadata' => [
'order_id' => '1234',
],
'source' => [
'type' => 'creditcard',
'company' => 'visa',
'name' => 'John Doe',
'number' => '**** **** **** 1111',
'message' => null,
],
'given_id' => null,
];

public const array TEST_VOIDED_PAYMENT = [
'id' => 'pay_1',
'status' => 'voided',
'amount' => 10000,
'fee' => 50,
'currency' => 'SAR',
'refunded' => 0,
'refunded_at' => null,
'captured' => 0,
'captured_at' => null,
'voided_at' => '2024-01-16T10:00:00Z',
'description' => 'Test payment',
'amount_format' => '100.00 SAR',
'fee_format' => '0.50 SAR',
'refunded_format' => '0.00 SAR',
'captured_format' => '0.00 SAR',
'invoice_id' => null,
'ip' => '127.0.0.1',
'callback_url' => 'https://example.com/webhooks/moyasar',
'created_at' => '2024-01-15T10:00:00Z',
'updated_at' => '2024-01-16T10:00:00Z',
'metadata' => [
'order_id' => '1234',
],
'source' => [
'type' => 'creditcard',
'company' => 'visa',
'name' => 'John Doe',
'number' => '**** **** **** 1111',
'message' => null,
],
'given_id' => null,
];
}
29 changes: 29 additions & 0 deletions tests/Feature/Payment/CapturePaymentTest.php

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of

$paymentId = (getenv('REAL_TESTS') === 'true')
        ? getenv('MOYASAR_SAMPLE_AUTHORIZED_PAYMENT_ID') ?: $payment->id
        : $payment->id;

Do 2 things:

  1. Include all new environment variables in phpunit.xml.dist as well as '.env.example' and '.env' with their default values, so you don't have to worry about their nullity
  2. Since you have a default value, and in case of Mock tests you are [intuitively] mocking the response, it's safe to change the above snippet into
$invoice = getenv('MOYASAR_SAMPLE_AUTHORIZED_PAYMENT_ID') ?: $payment->id;

Also, I observe in my machine that sometimes the getenv() function cast the values, that's why I wrote in tests/Config/MoyasarInitializer.php the condition like this

$isMock = empty(getenv('REAL_TESTS')) || getenv('REAL_TESTS') === 'false';

It casted the value false to an empty string (false). Kindly keep that in mind for next tests

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

use HamodaDev\Moyasar\Payment\DTO\CreatePaymentDTO;
use HamodaDev\Moyasar\Payment\DTO\PaymentDTO;
use Tests\Config\MoyasarInitializer;

beforeAll(fn() => validateEnvIsSet());

it('captures an authorized payment', function () {
// arrange
$moyasar = MoyasarInitializer::getInstance()->getMoyasar();

$payment = $moyasar->payment()->create(CreatePaymentDTO::fromArray(mockCreatePaymentDTO()));

$paymentId = getenv('MOYASAR_SAMPLE_AUTHORIZED_PAYMENT_ID') ?: $payment->id;

// act
$captured = $moyasar->payment()->capture($paymentId);

// assert
expect($captured)->toBeInstanceOf(PaymentDTO::class)
->and($captured->id)->toBe($paymentId)
->and($captured->status)->toBe('captured')
->and($captured->captured)->toBeGreaterThan(0)
->and($captured->capturedAt)->not->toBeNull();
})->skip(
fn () => getenv('REAL_TESTS') === 'true' && empty(getenv('MOYASAR_SAMPLE_AUTHORIZED_PAYMENT_ID')),
'MOYASAR_SAMPLE_AUTHORIZED_PAYMENT_ID is required for real capture tests'
);
54 changes: 54 additions & 0 deletions tests/Feature/Payment/CreatePaymentTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

use HamodaDev\Moyasar\Payment\DTO\CreatePaymentDTO;
use HamodaDev\Moyasar\Payment\DTO\PaymentDTO;
use HamodaDev\Moyasar\Payment\DTO\Source\CreditCardSourceDTO;
use Tests\Config\MoyasarInitializer;

beforeAll(fn() => validateEnvIsSet());

it('creates a payment with credit card source', function () {
// arrange
$moyasar = MoyasarInitializer::getInstance()->getMoyasar();

// act
$payment = $moyasar->payment()->create(new CreatePaymentDTO(
amount: 10000,
currency: 'SAR',
description: 'Test payment',
callbackUrl: 'https://example.com/webhook',
source: new CreditCardSourceDTO(
name: 'John Doe',
number: '4111111111111111',
month: 12,
year: 2030,
cvc: 123,
),
));

// assert
expect($payment)->toBeInstanceOf(PaymentDTO::class)
->and($payment->id)->not->toBeEmpty()
->and($payment->status)->toBeIn(['initiated', 'paid'])
->and($payment->amount)->toBe(10000)
->and($payment->currency)->toBe('SAR')
->and($payment->source)->toBeArray()
->and($payment->source['type'])->toBe('creditcard');
});

it('creates a payment using fromArray with array source', function () {
// arrange
$moyasar = MoyasarInitializer::getInstance()->getMoyasar();

// act
$payment = $moyasar->payment()->create(CreatePaymentDTO::fromArray(mockCreatePaymentDTO([
'amount' => 6900,
'currency' => 'EGP',
])));

// assert
expect($payment)->toBeInstanceOf(PaymentDTO::class)
->and($payment->id)->not->toBeEmpty()
->and($payment->amount)->toBeIn([10000, 6900])
->and($payment->source)->toBeArray();
});
Loading
Loading