Files
portal/app/tests/Feature/Admin/AdminSupplierIntegrationTest.php
T

81 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Jobs\Supplier\CsvReconcileJob;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
it('GET /api/admin/supplier-integration returns channel health + history', function (): void {
DB::connection('pgsql_supplier')->table('supplier_csv_reconcile_log')->insert([
'started_at' => now()->subMinutes(10),
'finished_at' => now()->subMinutes(9),
'window_start' => now()->subDay(),
'window_end' => now(),
'total_csv_rows' => 100,
'matched_count' => 98,
'recovered_count' => 2,
'drift_ratio' => 0.02,
'status' => 'ok',
'created_at' => now()->subMinutes(10),
]);
$response = $this->getJson('/api/admin/supplier-integration');
$response->assertOk();
$response->assertJsonStructure([
'health' => ['last_run_at', 'last_status', 'drift_ratio', 'webhook_state'],
'history' => [['started_at', 'status', 'total_csv_rows', 'matched_count', 'recovered_count', 'drift_ratio']],
]);
expect($response->json('health.last_status'))->toBe('ok');
expect($response->json('health.webhook_state'))->toBe('live');
});
it('webhook_state is "down" when last run had drift_alert', function (): void {
DB::connection('pgsql_supplier')->table('supplier_csv_reconcile_log')->insert([
'started_at' => now()->subMinutes(5),
'finished_at' => now()->subMinutes(4),
'window_start' => now()->subDay(),
'window_end' => now(),
'total_csv_rows' => 100,
'matched_count' => 80,
'recovered_count' => 20,
'drift_ratio' => 0.20,
'status' => 'drift_alert',
'created_at' => now()->subMinutes(5),
]);
$response = $this->getJson('/api/admin/supplier-integration');
expect($response->json('health.webhook_state'))->toBe('down');
});
it('POST /api/admin/supplier-integration/reconcile dispatches CsvReconcileJob', function (): void {
Bus::fake([CsvReconcileJob::class]);
$response = $this->postJson('/api/admin/supplier-integration/reconcile');
$response->assertOk();
$response->assertJson(['dispatched' => true]);
Bus::assertDispatched(CsvReconcileJob::class, 1);
});
it('returns nulls in health when reconcile log is empty (no run yet)', function (): void {
// Пустой supplier_csv_reconcile_log — до первой сверки. Контроллер не должен
// падать на $last === null (property access на null).
DB::connection('pgsql_supplier')->table('supplier_csv_reconcile_log')->truncate();
$response = $this->getJson('/api/admin/supplier-integration');
$response->assertOk();
expect($response->json('health.last_run_at'))->toBeNull();
expect($response->json('health.last_status'))->toBeNull();
expect($response->json('health.drift_ratio'))->toBeNull();
expect($response->json('health.webhook_state'))->toBe('live');
expect($response->json('history'))->toBe([]);
});