Files
L-Ami-Fiduciaire/tests/Feature/Dashboard/WorkerDashboardTest.php
Saad Zoubir 716e9fc4f6 fix: resolve 15 pre-existing test failures flagged across 3 retrospectives
Delete 14 legacy Folder test files (FolderTypeTest, MediaDownloadTest,
FolderMentionTest) that referenced removed routes/tables from the Epic 0
folders-to-declarations rename. Declaration equivalents already exist.
Fix WorkerDashboardTest session edge case where HandleInertiaRequests
middleware auto-assigns workspace, invalidating the no-session assumption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:50:46 +01:00

332 lines
11 KiB
PHP

<?php
use App\Enums\DeclarationStatus;
use App\Models\Client;
use App\Models\Declaration;
use App\Models\User;
use App\Models\Workspace;
use Illuminate\Support\Facades\Cache;
function setupWorkerWorkspace(): array
{
$worker = User::factory()->create();
$workspace = Workspace::factory()->create();
$workspace->users()->attach($worker->id, ['role' => 'worker']);
$client = Client::factory()->create(['workspace_id' => $workspace->id]);
session(['current_workspace_id' => $workspace->id]);
return [$worker, $workspace, $client];
}
test('worker sees only their assigned declarations in kpi counts', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$otherUser = User::factory()->create();
$workspace->users()->attach($otherUser->id, ['role' => 'worker']);
// Assigned to this worker — overdue
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $worker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(3),
]);
// Assigned to this worker — due this week
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $worker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->addDays(2),
]);
// Assigned to this worker — en attente client
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $worker->id,
'status' => DeclarationStatus::EnAttenteClient,
'due_date' => now()->addDays(10),
]);
// Assigned to OTHER worker (should NOT count)
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherUser->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(1),
]);
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('stats.overdue', 1)
->where('stats.dueThisWeek', 1)
->where('stats.enAttenteClient', 1)
->where('stats.enCours', 2)
);
});
test('worker does not see declarations assigned to other team members in kpi counts', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$otherWorker = User::factory()->create();
$workspace->users()->attach($otherWorker->id, ['role' => 'worker']);
// Only assigned to other worker
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherWorker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(5),
]);
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherWorker->id,
'status' => DeclarationStatus::EnAttenteClient,
'due_date' => now()->addDays(2),
]);
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('stats.overdue', 0)
->where('stats.dueThisWeek', 0)
->where('stats.enAttenteClient', 0)
->where('stats.enCours', 0)
);
});
test('worker sees only their assigned declarations in the urgent declarations table', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$otherWorker = User::factory()->create();
$workspace->users()->attach($otherWorker->id, ['role' => 'worker']);
// Assigned to this worker
$myDeclaration = Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $worker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->addDays(2),
]);
// Assigned to other worker
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherWorker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->addDays(1),
]);
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->has('declarations', 1)
->where('declarations.0.id', $myDeclaration->id)
);
});
test('worker sees only their assigned declarations in priority alerts', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$otherWorker = User::factory()->create();
$workspace->users()->attach($otherWorker->id, ['role' => 'worker']);
// Overdue declaration assigned to this worker (generates critical alert)
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $worker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(5),
]);
// Overdue declaration assigned to other worker (should NOT appear)
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherWorker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(3),
]);
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->has('alerts', 1)
->where('alerts.0.severity', 'critical')
);
});
test('worker dashboard returns isWorker true in inertia props', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('isWorker', true)
);
});
test('worker with no assigned declarations gets zero counts and empty arrays', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
// Declarations exist but assigned to someone else
$otherUser = User::factory()->create();
$workspace->users()->attach($otherUser->id, ['role' => 'worker']);
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherUser->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(1),
]);
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('stats.overdue', 0)
->where('stats.dueThisWeek', 0)
->where('stats.enAttenteClient', 0)
->where('stats.enCours', 0)
->where('declarations', [])
->where('alerts', [])
->where('isWorker', true)
);
});
test('worker stat card hrefs include assignee scoping param', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$this->actingAs($worker);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->has('statCards', 4)
->where('statCards.0.href', fn ($href) => str_contains($href, 'assignee='.$worker->id))
->where('statCards.1.href', fn ($href) => str_contains($href, 'assignee='.$worker->id))
->where('statCards.2.href', fn ($href) => str_contains($href, 'assignee='.$worker->id))
->where('statCards.3.href', fn ($href) => str_contains($href, 'assignee='.$worker->id))
);
});
test('owner and manager dashboard returns isWorker false', function () {
$ownerUser = User::factory()->create();
$managerUser = User::factory()->create();
$workspace = Workspace::factory()->create();
$workspace->users()->attach($ownerUser->id, ['role' => 'owner']);
$workspace->users()->attach($managerUser->id, ['role' => 'manager']);
session(['current_workspace_id' => $workspace->id]);
// Owner
$this->actingAs($ownerUser);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('isWorker', false)
);
// Manager
$this->actingAs($managerUser);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('isWorker', false)
);
});
test('user without any workspace gets isWorker false in fallback', function () {
$user = User::factory()->create();
// User has no workspace attachments — middleware cannot auto-assign
$this->actingAs($user);
$response = $this->get(route('dashboard'));
$response->assertOk();
$response->assertInertia(fn ($page) => $page
->component('Dashboard')
->where('isWorker', false)
->where('workspaceName', null)
);
});
test('cached data is scoped per user with worker cache key including user id', function () {
[$worker, $workspace, $client] = setupWorkerWorkspace();
$otherWorker = User::factory()->create();
$workspace->users()->attach($otherWorker->id, ['role' => 'worker']);
// Declaration assigned to first worker
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $worker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(1),
]);
// Declaration assigned to second worker
Declaration::factory()->create([
'workspace_id' => $workspace->id,
'client_id' => $client->id,
'assigned_to' => $otherWorker->id,
'status' => DeclarationStatus::EnCours,
'due_date' => now()->subDays(2),
]);
// First worker request
$this->actingAs($worker);
$this->get(route('dashboard'))->assertOk();
$workerCacheKey = "dashboard:{$workspace->id}:{$worker->id}";
$otherCacheKey = "dashboard:{$workspace->id}:{$otherWorker->id}";
expect(Cache::has($workerCacheKey))->toBeTrue();
expect(Cache::has($otherCacheKey))->toBeFalse();
$workerCached = Cache::get($workerCacheKey);
expect($workerCached['overdue'])->toBe(1)
->and($workerCached['enCours'])->toBe(1);
// Second worker request
$this->actingAs($otherWorker);
$this->get(route('dashboard'))->assertOk();
expect(Cache::has($otherCacheKey))->toBeTrue();
$otherCached = Cache::get($otherCacheKey);
expect($otherCached['overdue'])->toBe(1)
->and($otherCached['enCours'])->toBe(1);
});