Files
ladill-mini/tests/Feature/MiniPaymentCheckoutTest.php
T
isaacclad 86d2dcbf0b
Deploy Ladill Mini / deploy (push) Successful in 1m4s
Restore Paystack Inline in-page sheet/modal; stop separate-browser checkout.
Pass access_code through pay responses and launch PaystackPop from the shared sheet instead of window.open.
2026-07-21 19:12:24 +00:00

194 lines
6.6 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\QrCode;
use App\Models\User;
use App\Services\Pay\PayClient;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Mockery;
use Tests\TestCase;
class MiniPaymentCheckoutTest extends TestCase
{
use RefreshDatabase;
public function test_payment_landing_shows_secure_checkout_not_momo(): void
{
$user = User::create([
'public_id' => (string) Str::uuid(),
'name' => 'Vendor',
'email' => 'vendor@example.com',
]);
$qr = QrCode::query()->create([
'user_id' => $user->id,
'short_code' => 'payland01',
'type' => QrCode::TYPE_PAYMENT,
'label' => 'Till',
'payload' => [
'content' => [
'business_name' => 'Accra Kiosk',
'currency' => 'GHS',
],
'style' => [],
],
'is_active' => true,
]);
$this->withHeader(\App\Support\LadillLink::INTERNAL_HEADER, '1')
->get('/q/'.$qr->short_code)
->assertOk()
->assertSee('Your payment is processed securely', false)
->assertSee('md:items-center', false)
->assertSee('Complete your payment', false)
->assertSee('data-ladill-pay-sheet', false)
->assertSee('resumeTransaction', false)
->assertSee('/q/'.$qr->short_code.'/pay', false)
->assertDontSee('https://ladl.link/'.$qr->short_code.'/pay', false)
->assertDontSee('MTN MoMo number', false)
->assertDontSee('Pay with MTN MoMo', false)
->assertDontSee('Continue to Paystack', false)
->assertDontSee('Paystack checkout', false);
}
public function test_json_pay_post_is_not_redirected_to_ladill_link(): void
{
$user = User::create([
'public_id' => (string) Str::uuid(),
'name' => 'Vendor',
'email' => 'vendor-ajax@example.com',
]);
$qr = QrCode::query()->create([
'user_id' => $user->id,
'short_code' => 'payajax01',
'type' => QrCode::TYPE_PAYMENT,
'label' => 'Till',
'payload' => [
'content' => [
'business_name' => 'Accra Kiosk',
'currency' => 'GHS',
],
'style' => [],
],
'is_active' => true,
]);
$pay = Mockery::mock(PayClient::class);
$pay->shouldReceive('createCheckout')
->once()
->andReturn([
'id' => 100,
'reference' => 'LP-TESTMINIAjax01',
'checkout_url' => 'https://checkout.paystack.com/mini-ajax',
'access_code' => 'mini-ajax',
'public_key' => 'pk_test_x',
'provider' => 'paystack',
'platform_fee_minor' => 15,
'merchant_amount_minor' => 985,
]);
$this->app->instance(PayClient::class, $pay);
// No INTERNAL header — XHR/JSON must still hit Mini, not 307 to ladl.link.
$this->postJson('/q/'.$qr->short_code.'/pay', [
'amount' => 10,
])
->assertOk()
->assertJsonPath('checkout_url', 'https://checkout.paystack.com/mini-ajax')
->assertJsonPath('access_code', 'mini-ajax')
->assertJsonPath('provider', 'paystack');
}
public function test_pay_initiation_does_not_require_phone_and_returns_paystack_checkout(): void
{
$user = User::create([
'public_id' => (string) Str::uuid(),
'name' => 'Vendor',
'email' => 'vendor@example.com',
]);
$qr = QrCode::query()->create([
'user_id' => $user->id,
'short_code' => 'payinit01',
'type' => QrCode::TYPE_PAYMENT,
'label' => 'Till',
'payload' => [
'content' => [
'business_name' => 'Accra Kiosk',
'currency' => 'GHS',
],
'style' => [],
],
'is_active' => true,
]);
$pay = Mockery::mock(PayClient::class);
$pay->shouldReceive('createCheckout')
->once()
->with(Mockery::on(function (array $payload): bool {
return ($payload['source_service'] ?? '') === 'mini'
&& ! array_key_exists('customer_phone', $payload)
&& ($payload['line_items'][0]['unit_price_minor'] ?? 0) === 2500;
}))
->andReturn([
'id' => 99,
'reference' => 'LP-TESTMINIPAY001',
'checkout_url' => 'https://checkout.paystack.com/mini-test',
'access_code' => 'mini-test',
'public_key' => 'pk_test_x',
'provider' => 'paystack',
'platform_fee_minor' => 38,
'merchant_amount_minor' => 2462,
]);
$this->app->instance(PayClient::class, $pay);
$this->withHeader(\App\Support\LadillLink::INTERNAL_HEADER, '1')
->postJson('/q/'.$qr->short_code.'/pay', [
'amount' => 25,
])
->assertOk()
->assertJsonPath('checkout_url', 'https://checkout.paystack.com/mini-test')
->assertJsonPath('access_code', 'mini-test')
->assertJsonPath('provider', 'paystack');
$this->assertDatabaseHas('mini_payments', [
'qr_code_id' => $qr->id,
'amount_minor' => 2500,
'payment_reference' => 'LP-TESTMINIPAY001',
'payer_phone' => null,
]);
}
public function test_payment_callback_returns_top_frame_escape(): void
{
$user = User::create([
'public_id' => (string) Str::uuid(),
'name' => 'Vendor',
'email' => 'vendor3@example.com',
]);
$qr = QrCode::query()->create([
'user_id' => $user->id,
'short_code' => 'paycb001',
'type' => QrCode::TYPE_PAYMENT,
'label' => 'Till',
'payload' => [
'content' => [
'business_name' => 'Accra Kiosk',
'currency' => 'GHS',
],
'style' => [],
],
'is_active' => true,
]);
$this->withHeader(\App\Support\LadillLink::INTERNAL_HEADER, '1')
->get('/q/'.$qr->short_code.'/pay/callback')
->assertOk()
->assertSee('Confirming your payment', false)
->assertSee('window.top.location.replace', false);
}
}