create(); $workspace = Workspace::factory()->create(); $workspace->users()->attach($user->id, ['role' => $role]); $client = Client::factory()->create(['workspace_id' => $workspace->id]); session(['current_workspace_id' => $workspace->id]); return [$user, $workspace, $client]; } test('overdue declarations appear as critical alerts with correct daysOverdue', function () { [$user, $workspace, $client] = setupAlertWorkspace(); $declaration = Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->subDays(5), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 1) ->where('alerts.0.severity', 'critical') ->where('alerts.0.clientName', $client->company_name) ->where('alerts.0.daysValue', 5) ->where('alerts.0.daysLabel', 'jours en retard') ->has('alerts.0.showUrl') ); }); test('approaching deadline declarations appear as warning alerts', function () { [$user, $workspace, $client] = setupAlertWorkspace(); Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->addDays(2), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 1) ->where('alerts.0.severity', 'warning') ->where('alerts.0.daysLabel', 'jours restants') ); }); test('en_attente_client over 3 days appears as info alert', function () { [$user, $workspace, $client] = setupAlertWorkspace(); Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnAttenteClient, 'due_date' => now()->addDays(10), 'updated_at' => now()->subDays(5), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->where('alerts.0.severity', 'info') ->where('alerts.0.daysLabel', 'jours en attente') ); }); test('en_attente_client 3 days or less does not appear as info alert', function () { [$user, $workspace, $client] = setupAlertWorkspace(); Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnAttenteClient, 'due_date' => now()->addDays(10), 'updated_at' => now()->subDays(2), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 0) ); }); test('alerts are capped at 20 items', function () { [$user, $workspace, $client] = setupAlertWorkspace(); // Create 25 overdue declarations for ($i = 1; $i <= 25; $i++) { Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->subDays($i), ]); } $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 20) ); }); test('alerts are sorted by severity: critical first, then warning, then info', function () { [$user, $workspace, $client] = setupAlertWorkspace(); // Info alert (en_attente_client >3 days) Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnAttenteClient, 'due_date' => now()->addDays(10), 'updated_at' => now()->subDays(5), ]); // Warning alert (due in 2 days) Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->addDays(2), ]); // Critical alert (overdue) Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->subDays(3), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 3) ->where('alerts.0.severity', 'critical') ->where('alerts.1.severity', 'warning') ->where('alerts.2.severity', 'info') ); }); test('worker sees only alerts for assigned declarations', function () { [$user, $workspace, $client] = setupAlertWorkspace('worker'); $otherUser = User::factory()->create(); $workspace->users()->attach($otherUser->id, ['role' => 'worker']); // Overdue assigned to this worker (should appear) Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'assigned_to' => $user->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->subDays(2), ]); // Overdue assigned to other worker (should NOT appear) Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'assigned_to' => $otherUser->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->subDays(3), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 1) ->where('alerts.0.severity', 'critical') ); }); test('empty alerts array when no urgent items exist', function () { [$user, $workspace, $client] = setupAlertWorkspace(); // Declaration far in the future (no alert) Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->addDays(30), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 0) ); }); test('alerts are included in cached dashboard payload', function () { [$user, $workspace, $client] = setupAlertWorkspace(); Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::EnCours, 'due_date' => now()->subDays(2), ]); $this->actingAs($user); $this->get(route('dashboard'))->assertOk(); $cacheKey = "dashboard:{$workspace->id}:{$user->id}"; expect(Cache::has($cacheKey))->toBeTrue(); $cached = Cache::get($cacheKey); expect($cached)->toBeArray() ->and($cached)->toHaveKey('alerts') ->and($cached['alerts'])->toBeArray() ->and($cached['alerts'])->toHaveCount(1) ->and($cached['alerts'][0]['severity'])->toBe('critical'); }); test('excluded statuses do not generate alerts', function () { [$user, $workspace, $client] = setupAlertWorkspace(); // Termine (excluded) - overdue Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::Termine, 'due_date' => now()->subDays(5), ]); // MiseEnDemeure (excluded) - overdue Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::MiseEnDemeure, 'due_date' => now()->subDays(3), ]); // Ferme (excluded) - overdue Declaration::factory()->create([ 'workspace_id' => $workspace->id, 'client_id' => $client->id, 'status' => DeclarationStatus::Ferme, 'due_date' => now()->subDays(1), ]); $this->actingAs($user); $response = $this->get(route('dashboard')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('Dashboard') ->has('alerts', 0) ); });