File: /home/xedaptot/ai.naniguide.com/tests/Unit/Models/PaymentIntentTest.php
<?php
namespace Tests\Unit\Models;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Model\PaymentIntent;
use App\Cashier\DTO\PaymentIntent as PaymentIntentDto;
use App\Cashier\DTO\SubscriptionSpec;
class PaymentIntentTest extends TestCase
{
use DatabaseTransactions;
public function test_default_status_is_pending()
{
$pi = PaymentIntent::factory()->create();
$this->assertSame(PaymentIntent::STATUS_PENDING, $pi->status);
$this->assertTrue($pi->isPending());
$this->assertFalse($pi->isTerminal());
}
public function test_status_helpers()
{
$succeeded = PaymentIntent::factory()->succeeded()->create();
$this->assertTrue($succeeded->isSucceeded());
$this->assertTrue($succeeded->isTerminal());
$this->assertFalse($succeeded->isPending());
$failed = PaymentIntent::factory()->failed()->create();
$this->assertTrue($failed->isFailed());
$this->assertTrue($failed->isTerminal());
$requiresAction = PaymentIntent::factory()->requiresAction()->create();
$this->assertTrue($requiresAction->isRequiresAction());
$this->assertFalse($requiresAction->isTerminal());
$awaiting = PaymentIntent::factory()->awaitingAdminApproval()->create();
$this->assertTrue($awaiting->isAwaitingAdminApproval());
$this->assertFalse($awaiting->isTerminal());
$this->assertFalse($awaiting->isPending());
}
public function test_scope_active_includes_awaiting_admin_approval()
{
// Scope assertions to rows created in THIS test. DatabaseTransactions
// rolls back per-test commits, but rows seeded outside transactions
// (E2E tests, dev tinker) persist and leak into scope counts.
$ids = [
PaymentIntent::factory()->create()->id, // pending
PaymentIntent::factory()->requiresAction()->create()->id, // requires_action
PaymentIntent::factory()->awaitingAdminApproval()->create()->id, // awaiting_admin_approval
PaymentIntent::factory()->succeeded()->create()->id, // succeeded (excluded)
PaymentIntent::factory()->failed()->create()->id, // failed (excluded)
];
$active = PaymentIntent::active()->whereIn('id', $ids)->get();
$this->assertCount(3, $active);
$this->assertTrue($active->every(fn($i) => in_array($i->status, [
PaymentIntent::STATUS_PENDING,
PaymentIntent::STATUS_REQUIRES_ACTION,
PaymentIntent::STATUS_AWAITING_ADMIN_APPROVAL,
])));
}
public function test_scope_terminal_excludes_awaiting_admin_approval()
{
$ids = [
PaymentIntent::factory()->create()->id, // pending (excluded)
PaymentIntent::factory()->awaitingAdminApproval()->create()->id, // awaiting (excluded)
PaymentIntent::factory()->succeeded()->create()->id, // succeeded
PaymentIntent::factory()->failed()->create()->id, // failed
];
$terminal = PaymentIntent::terminal()->whereIn('id', $ids)->get();
$this->assertCount(2, $terminal);
}
public function test_scope_awaiting_admin_approval_returns_only_that_status()
{
$ids = [
PaymentIntent::factory()->create()->id, // pending (excluded)
PaymentIntent::factory()->awaitingAdminApproval()->create()->id, // ✓
PaymentIntent::factory()->awaitingAdminApproval()->create()->id, // ✓
PaymentIntent::factory()->succeeded()->create()->id, // succeeded (excluded)
];
$awaiting = PaymentIntent::awaitingAdminApproval()->whereIn('id', $ids)->get();
$this->assertCount(2, $awaiting);
$this->assertTrue($awaiting->every(fn($i) => $i->isAwaitingAdminApproval()));
}
public function test_to_dto_produces_cashier_dto_for_one_off()
{
$pi = PaymentIntent::factory()->create([
'amount' => 29.99,
'currency' => 'USD',
]);
$dto = $pi->toDto();
$this->assertInstanceOf(PaymentIntentDto::class, $dto);
$this->assertSame($pi->uid, $dto->uid);
$this->assertSame(29.99, $dto->amount);
$this->assertSame('USD', $dto->currency);
$this->assertSame($pi->paymentGateway->uid, $dto->paymentGatewayId);
$this->assertNull($dto->subscription);
$this->assertFalse($dto->isSubscription());
}
public function test_to_dto_hydrates_subscription_spec_from_metadata()
{
$pi = PaymentIntent::factory()->forSubscription('price_xyz')->create();
$dto = $pi->toDto();
$this->assertInstanceOf(SubscriptionSpec::class, $dto->subscription);
$this->assertSame('price_xyz', $dto->subscription->remotePlanId);
$this->assertTrue($dto->isSubscription());
}
public function test_to_dto_carries_payer_info_from_invoice_and_customer()
{
$pi = PaymentIntent::factory()->create();
$pi->invoice->billing_email = '[email protected]';
$pi->invoice->billing_phone = '+1-555';
$pi->invoice->save();
$dto = $pi->toDto();
$this->assertSame('[email protected]', $dto->payer->email);
$this->assertSame('+1-555', $dto->payer->phone);
$this->assertNotEmpty($dto->payer->uid);
$this->assertNotEmpty($dto->payer->name);
}
}