Testing
Running the Package Suite
composer testcomposer test-coverageTesting 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:
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:
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.
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:
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
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
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
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
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.
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