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/Plans/QuotasServiceTest.php
<?php

/**
 * QuotasServiceTest — covers Quota gating with counter delegation.
 *
 * See docs/payment-order-plan-subscription-saas/SUBSCRIPTION-COMPREHENSIVE-DESIGN.md §6.2.
 */

use App\Model\Customer;
use App\Model\MailList;
use App\Model\Plan;
use App\Model\PlanQuota;
use App\Model\Subscription;
use App\Services\Plans\Quotas\QuotaKey;
use App\Services\Plans\Quotas\QuotasService;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;

uses(TestCase::class);

beforeEach(function () {
    $this->customer = Customer::forceCreate([
        'uid'      => uniqid('test_c_'),
        'timezone' => 'UTC',
        'status'   => 'active',
    ]);
    $this->plan     = Plan::forceCreate([
        'uid'              => uniqid('test_plan_'),
        'name'             => 'Test Plan',
        'currency_id'      => 1,
        'frequency_amount' => 1,
        'frequency_unit'   => 'month',
        'price'            => 0,
        'status'           => 'active',
    ]);
    $this->sub      = Subscription::create([
        'uid'                    => (string) \Illuminate\Support\Str::uuid(),
        'customer_id'            => $this->customer->id,
        'plan_id'                => $this->plan->id,
        'status'                 => 'active',
        'current_period_ends_at' => now()->addMonth(),
    ]);

    PlanQuota::factory()->for($this->plan, 'plan')
        ->forKey(QuotaKey::MAX_LISTS)
        ->state(['limit_value' => 3])
        ->create();

    $this->svc = app(QuotasService::class);
});

afterEach(function () {
    DB::table('mail_lists')->where('customer_id', $this->customer->id)->delete();
    DB::table('plan_quotas')->where('plan_id', $this->plan->id)->delete();
    $this->sub->delete();
    $this->plan->delete();
    $this->customer->delete();
});

test('canCreate false when no active subscription', function () {
    $this->sub->delete(); // orphan customer

    expect($this->svc->canCreate($this->customer, QuotaKey::MAX_LISTS))->toBeFalse();
});

test('canCreate true when under limit', function () {
    MailList::forceCreate([
        'uid'         => (string) \Illuminate\Support\Str::uuid(),
        'customer_id' => $this->customer->id,
        'name'        => 'Test List ' . uniqid(),
    ]);
    MailList::forceCreate([
        'uid'         => (string) \Illuminate\Support\Str::uuid(),
        'customer_id' => $this->customer->id,
        'name'        => 'Test List ' . uniqid(),
    ]);

    expect($this->svc->used($this->customer, QuotaKey::MAX_LISTS))->toBe(2);
    expect($this->svc->limit($this->customer, QuotaKey::MAX_LISTS))->toBe(3);
    expect($this->svc->canCreate($this->customer, QuotaKey::MAX_LISTS))->toBeTrue();
});

test('canCreate false when at limit', function () {
    foreach (range(1, 3) as $_) {
        MailList::forceCreate([
            'uid'         => (string) \Illuminate\Support\Str::uuid(),
            'customer_id' => $this->customer->id,
            'name'        => 'Test List ' . uniqid(),
        ]);
    }

    expect($this->svc->canCreate($this->customer, QuotaKey::MAX_LISTS))->toBeFalse();
});

test('canCreate false when quota not configured for plan', function () {
    expect($this->svc->canCreate($this->customer, QuotaKey::MAX_CAMPAIGNS))->toBeFalse();
    expect($this->svc->limit($this->customer, QuotaKey::MAX_CAMPAIGNS))->toBeFalse();
});

test('canCreate true when limit is NULL (unlimited)', function () {
    // Overwrite the default limit with NULL
    \App\Model\PlanQuota::where('plan_id', $this->plan->id)
        ->where('quota_key', QuotaKey::MAX_LISTS->value)
        ->update(['limit_value' => null]);

    foreach (range(1, 5) as $_) {
        MailList::forceCreate([
            'uid'         => (string) \Illuminate\Support\Str::uuid(),
            'customer_id' => $this->customer->id,
            'name'        => 'Test List ' . uniqid(),
        ]);
    }

    expect($this->svc->limit($this->customer, QuotaKey::MAX_LISTS))->toBeNull();
    expect($this->svc->canCreate($this->customer, QuotaKey::MAX_LISTS))->toBeTrue();
});

test('per-list and storage quotas throw (no customer-scoped counter)', function () {
    expect(fn () => $this->svc->used($this->customer, QuotaKey::MAX_SEGMENTS_PER_LIST))
        ->toThrow(RuntimeException::class);
    expect(fn () => $this->svc->used($this->customer, QuotaKey::MAX_UPLOAD_SIZE_TOTAL))
        ->toThrow(RuntimeException::class);
});