Files
portal/app/tests/Feature/Models/SupplierProjectTest.php
T
Дмитрий 62aa55f033 feat(models): add SupplierProject Eloquent model + factory + tests
- app/Models/SupplierProject.php — fillable + casts (jsonb arrays + datetime)
  + scopes: active() (inactive_since IS NULL), staleSince(N days),
  forSignal(signal_type, unique_key)
- database/factories/SupplierProjectFactory.php — корректно учитывает
  chk_supplier_projects_b1_not_for_sms (B1 не порождает SMS-проекты)
- tests/Feature/Models/SupplierProjectTest.php — 6 тестов: factory,
  array casts (workdays + regions), scopeActive, scopeStaleSince,
  scopeForSignal (3 платформы на один домен — UNIQUE (platform,unique_key))

ide-helper:models -W -M -N перегенерил docblocks для 4 существующих моделей
(SaasAdminAuditLog, SystemSetting, UserRecoveryCode, ImpersonationToken) —
синхронизировал @property после schema v8.16.

Pest: 451 / 449 passed / 2 skipped (было 443+6 новых от Task 6 = 449).
Larastan: 0 errors. Pint: passed.

Spec: §2.2
Plan: Task 6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 13:59:39 +03:00

60 lines
2.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
use App\Models\SupplierProject;
use Illuminate\Foundation\Testing\DatabaseTransactions;
uses(DatabaseTransactions::class);
test('SupplierProject can be created via factory', function () {
$sp = SupplierProject::factory()->create();
expect($sp->id)->toBeInt()->toBeGreaterThan(0);
expect($sp->platform)->toBeIn(['B1', 'B2', 'B3']);
expect($sp->signal_type)->toBeIn(['site', 'call', 'sms']);
});
test('SupplierProject casts current_workdays as array', function () {
$sp = SupplierProject::factory()->create([
'current_workdays' => [1, 2, 3, 4, 5],
]);
expect($sp->fresh()->current_workdays)->toBe([1, 2, 3, 4, 5]);
});
test('SupplierProject casts current_regions as array', function () {
$sp = SupplierProject::factory()->create([
'current_regions' => ['77', '78'],
]);
expect($sp->fresh()->current_regions)->toBe(['77', '78']);
});
test('SupplierProject scopeActive returns only rows with inactive_since IS NULL', function () {
SupplierProject::factory()->create(['inactive_since' => null]);
SupplierProject::factory()->create(['inactive_since' => now()->subDays(10)]);
expect(SupplierProject::active()->count())->toBe(1);
});
test('SupplierProject scopeStaleSince returns rows inactive longer than N days', function () {
SupplierProject::factory()->create(['inactive_since' => now()->subDays(200)]);
SupplierProject::factory()->create(['inactive_since' => now()->subDays(100)]);
SupplierProject::factory()->create(['inactive_since' => null]);
expect(SupplierProject::staleSince(180)->count())->toBe(1);
});
test('SupplierProject scopeForSignal filters by (signal_type, unique_key)', function () {
// Один домен на трёх платформах — UNIQUE (platform, unique_key) допускает.
SupplierProject::factory()->create(['signal_type' => 'site', 'unique_key' => 'a.com', 'platform' => 'B1']);
SupplierProject::factory()->create(['signal_type' => 'site', 'unique_key' => 'a.com', 'platform' => 'B2']);
SupplierProject::factory()->create(['signal_type' => 'site', 'unique_key' => 'a.com', 'platform' => 'B3']);
// Другой источник — не должен попасть в результат.
SupplierProject::factory()->create(['signal_type' => 'site', 'unique_key' => 'b.com', 'platform' => 'B1']);
// Call-сигнал с unique_key=телефон — также не должен попасть.
SupplierProject::factory()->create(['signal_type' => 'call', 'unique_key' => '79991234567', 'platform' => 'B1']);
expect(SupplierProject::forSignal('site', 'a.com')->count())->toBe(3);
});