81 lines
3.1 KiB
PHP
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([]);
|
|
});
|