Files
portal/app/tests/Unit/Billing/PricingTierResolverTest.php
T

70 lines
2.7 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Models\PricingTier;
use App\Services\Billing\PricingTierResolver;
use Illuminate\Database\Eloquent\Collection;
use Tests\TestCase;
uses(TestCase::class);
beforeEach(function () {
$this->resolver = new PricingTierResolver;
// 7-tier сетка in-memory (без БД)
$this->tiers = new Collection([
new PricingTier(['tier_no' => 1, 'leads_in_tier' => 100, 'price_per_lead_kopecks' => 50000]),
new PricingTier(['tier_no' => 2, 'leads_in_tier' => 200, 'price_per_lead_kopecks' => 45000]),
new PricingTier(['tier_no' => 3, 'leads_in_tier' => 400, 'price_per_lead_kopecks' => 40000]),
new PricingTier(['tier_no' => 4, 'leads_in_tier' => 800, 'price_per_lead_kopecks' => 35000]),
new PricingTier(['tier_no' => 5, 'leads_in_tier' => 1500, 'price_per_lead_kopecks' => 30000]),
new PricingTier(['tier_no' => 6, 'leads_in_tier' => 3000, 'price_per_lead_kopecks' => 27000]),
new PricingTier(['tier_no' => 7, 'leads_in_tier' => null, 'price_per_lead_kopecks' => 25000]),
]);
});
it('returns tier 1 for the 1st lead', function () {
$tier = $this->resolver->resolveForCount($this->tiers, 1);
expect($tier->tier_no)->toBe(1);
});
it('returns tier 1 at upper bound (100th lead)', function () {
$tier = $this->resolver->resolveForCount($this->tiers, 100);
expect($tier->tier_no)->toBe(1);
});
it('crosses to tier 2 at 101st lead', function () {
$tier = $this->resolver->resolveForCount($this->tiers, 101);
expect($tier->tier_no)->toBe(2);
});
it('returns tier 6 at cumulative sum of tiers 1-6 (6000th lead)', function () {
// 100 + 200 + 400 + 800 + 1500 + 3000 = 6000; last in tier 6 = 6000th lead
$tier = $this->resolver->resolveForCount($this->tiers, 6000);
expect($tier->tier_no)->toBe(6);
});
it('returns tier 7 (unlimited) for 6001st lead', function () {
$tier = $this->resolver->resolveForCount($this->tiers, 6001);
expect($tier->tier_no)->toBe(7);
});
it('returns tier 7 for 1_000_000th lead (unlimited)', function () {
$tier = $this->resolver->resolveForCount($this->tiers, 1_000_000);
expect($tier->tier_no)->toBe(7);
});
it('throws RuntimeException on empty tiers collection', function () {
expect(fn () => $this->resolver->resolveForCount(new Collection, 1))
->toThrow(RuntimeException::class, 'No active pricing tiers');
});
it('throws InvalidArgumentException on zero or negative ordinal', function () {
expect(fn () => $this->resolver->resolveForCount($this->tiers, 0))
->toThrow(InvalidArgumentException::class, 'leadOrdinal must be >= 1');
expect(fn () => $this->resolver->resolveForCount($this->tiers, -5))
->toThrow(InvalidArgumentException::class, 'leadOrdinal must be >= 1');
});