Skip to content

Testing

Running the Package Suite

bash
composer test
bash
composer test-coverage

Testing Your Own Code

Freeze the Clock

An amount without an explicit expiry gets tomorrow's date, so any test asserting a payload needs a fixed clock:

php
use Illuminate\Support\Carbon;

beforeEach(fn () => Carbon::setTestNow(Carbon::create(2026, 9, 2, 12, 0, 0)));
afterEach(fn () => Carbon::setTestNow());

Or set an explicit expiry and sidestep the issue:

php
RaastQr::iban($iban)->amount('2500')->expiry('2026-12-31')->toPayload();

Assert the Payload, Not the Pixels

The payload is what banking apps read. The image is just a drawing of it.

php
it('encodes the order total', function () {
    $order = Order::factory()->create(['total' => 2500]);

    expect(RaastQr::iban($this->iban)->amount($order->total)->toPayload())
        ->toContain('05042500');
});

Asserting on PNG bytes tells you almost nothing and breaks whenever the renderer updates.

Skip Rendering Where You Can

Bind a fake renderer so tests don't spend time drawing:

php
use RealRashid\RaastQr\Renderers\Renderer;

beforeEach(function () {
    $this->app->bind(Renderer::class, FakeRenderer::class);
});

See Custom Renderers for a fake you can copy.

Testing Routes

php
it('serves a QR for the order owner', function () {
    $order = Order::factory()->create();

    $this->actingAs($order->user)
        ->get(route('orders.qr', $order))
        ->assertOk()
        ->assertHeader('Content-Type', 'image/svg+xml');
});

it('refuses someone else\'s order', function () {
    $order = Order::factory()->create();

    $this->actingAs(User::factory()->create())
        ->get(route('orders.qr', $order))
        ->assertForbidden();
});

Testing the Blade Component

php
it('renders a payment QR on checkout', function () {
    $order = Order::factory()->create(['total' => 2500]);

    $this->actingAs($order->user)
        ->get(route('checkout.payment', $order))
        ->assertOk()
        ->assertSee('data:image/png;base64,', false);
});

Testing Validation

php
it('rejects a bad IBAN on vendor payout settings', function () {
    $this->actingAs($vendor = User::factory()->create())
        ->post(route('payouts.update'), ['iban' => 'PK00ABCD0000000000000000'])
        ->assertSessionHasErrors('iban');
});

Testing Error Handling

php
use RealRashid\RaastQr\Enums\ErrorCode;
use RealRashid\RaastQr\Exceptions\RaastQrException;

it('reports an unencodable amount', function () {
    expect(fn () => RaastQr::iban($this->iban)->amount('4.222')->toPayload())
        ->toThrow(fn (RaastQrException $e) =>
            expect($e->errorCode)->toBe(ErrorCode::InvalidAmount)
        );
});

A Test IBAN

PK33ABCD0000000000000000 is structurally valid and passes the checksum, which makes it safe to hard-code in tests without pointing at a real account.

php
function testIban(): string
{
    return 'PK33ABCD0000000000000000';
}

Never put a real IBAN in a test fixture

It ends up in your repository, your CI logs and everyone's local checkout. Use the test value above, or generate one in a factory.


Made with ❤️ from Pakistan