HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.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);
    }
}