212 lines
6.8 KiB
PHP
212 lines
6.8 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
use App\Enums\DeclarationStatus;
|
||
|
|
use App\Models\Client;
|
||
|
|
use App\Models\Declaration;
|
||
|
|
use App\Models\User;
|
||
|
|
use App\Models\Workspace;
|
||
|
|
|
||
|
|
function setupActivityWorkspace(string $role = 'owner'): array
|
||
|
|
{
|
||
|
|
$user = User::factory()->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('owner sees workspace-wide activity in activities prop', function () {
|
||
|
|
[$owner, $workspace, $client] = setupActivityWorkspace('owner');
|
||
|
|
|
||
|
|
$otherUser = User::factory()->create();
|
||
|
|
$workspace->users()->attach($otherUser->id, ['role' => 'worker']);
|
||
|
|
|
||
|
|
// Act as owner BEFORE creating declaration so Spatie logs the causer
|
||
|
|
$this->actingAs($owner);
|
||
|
|
|
||
|
|
Declaration::factory()->create([
|
||
|
|
'workspace_id' => $workspace->id,
|
||
|
|
'client_id' => $client->id,
|
||
|
|
'assigned_to' => $otherUser->id,
|
||
|
|
'status' => DeclarationStatus::EnCours,
|
||
|
|
'due_date' => now()->addDays(10),
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$response->assertInertia(fn ($page) => $page
|
||
|
|
->component('Dashboard')
|
||
|
|
->has('activities')
|
||
|
|
->where('activities.0.actorName', $owner->name)
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('worker sees only activity related to their assigned declarations', function () {
|
||
|
|
[$worker, $workspace, $client] = setupActivityWorkspace('worker');
|
||
|
|
|
||
|
|
$otherWorker = User::factory()->create();
|
||
|
|
$workspace->users()->attach($otherWorker->id, ['role' => 'worker']);
|
||
|
|
|
||
|
|
// Declaration assigned to THIS worker — should appear in feed
|
||
|
|
$assignedDeclaration = Declaration::factory()->create([
|
||
|
|
'workspace_id' => $workspace->id,
|
||
|
|
'client_id' => $client->id,
|
||
|
|
'assigned_to' => $worker->id,
|
||
|
|
'status' => DeclarationStatus::EnCours,
|
||
|
|
'due_date' => now()->addDays(10),
|
||
|
|
]);
|
||
|
|
|
||
|
|
// 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()->addDays(5),
|
||
|
|
]);
|
||
|
|
|
||
|
|
$this->actingAs($worker);
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$response->assertInertia(fn ($page) => $page
|
||
|
|
->component('Dashboard')
|
||
|
|
->has('activities')
|
||
|
|
);
|
||
|
|
|
||
|
|
// Verify the worker only sees activities for their own declarations
|
||
|
|
$activitiesData = $response->original->getData()['page']['props']['activities'];
|
||
|
|
expect(count($activitiesData))->toBeGreaterThan(0);
|
||
|
|
|
||
|
|
// All activities should relate to the worker's assigned client
|
||
|
|
collect($activitiesData)->each(function ($a) use ($client) {
|
||
|
|
expect($a['description'])->toContain($client->company_name);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('activity entries contain expected fields', function () {
|
||
|
|
[$owner, $workspace, $client] = setupActivityWorkspace('owner');
|
||
|
|
|
||
|
|
Declaration::factory()->create([
|
||
|
|
'workspace_id' => $workspace->id,
|
||
|
|
'client_id' => $client->id,
|
||
|
|
'assigned_to' => $owner->id,
|
||
|
|
'status' => DeclarationStatus::EnCours,
|
||
|
|
'due_date' => now()->addDays(10),
|
||
|
|
]);
|
||
|
|
|
||
|
|
$this->actingAs($owner);
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$response->assertInertia(fn ($page) => $page
|
||
|
|
->component('Dashboard')
|
||
|
|
->has('activities.0', fn ($activity) => $activity
|
||
|
|
->has('id')
|
||
|
|
->has('actorName')
|
||
|
|
->has('actorInitials')
|
||
|
|
->has('description')
|
||
|
|
->has('targetUrl')
|
||
|
|
->has('targetLabel')
|
||
|
|
->has('timestamp')
|
||
|
|
->has('eventType')
|
||
|
|
)
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('feed is limited to 20 most recent events', function () {
|
||
|
|
[$owner, $workspace, $client] = setupActivityWorkspace('owner');
|
||
|
|
|
||
|
|
// Create 25 declarations to generate 25 activity log entries
|
||
|
|
for ($i = 0; $i < 25; $i++) {
|
||
|
|
Declaration::factory()->create([
|
||
|
|
'workspace_id' => $workspace->id,
|
||
|
|
'client_id' => $client->id,
|
||
|
|
'assigned_to' => $owner->id,
|
||
|
|
'status' => DeclarationStatus::EnCours,
|
||
|
|
'due_date' => now()->addDays($i + 1),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->actingAs($owner);
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$activitiesData = $response->original->getData()['page']['props']['activities'];
|
||
|
|
expect(count($activitiesData))->toBeLessThanOrEqual(20);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('empty activity returns empty array', function () {
|
||
|
|
$user = User::factory()->create();
|
||
|
|
$workspace = Workspace::factory()->create();
|
||
|
|
$workspace->users()->attach($user->id, ['role' => 'owner']);
|
||
|
|
session(['current_workspace_id' => $workspace->id]);
|
||
|
|
|
||
|
|
// No declarations or activity created
|
||
|
|
|
||
|
|
$this->actingAs($user);
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$response->assertInertia(fn ($page) => $page
|
||
|
|
->component('Dashboard')
|
||
|
|
->where('activities', [])
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('activity with deleted subject does not cause errors', function () {
|
||
|
|
[$owner, $workspace, $client] = setupActivityWorkspace('owner');
|
||
|
|
|
||
|
|
// Create a declaration (logs activity), then soft-delete it
|
||
|
|
$declaration = Declaration::factory()->create([
|
||
|
|
'workspace_id' => $workspace->id,
|
||
|
|
'client_id' => $client->id,
|
||
|
|
'assigned_to' => $owner->id,
|
||
|
|
'status' => DeclarationStatus::EnCours,
|
||
|
|
'due_date' => now()->addDays(10),
|
||
|
|
]);
|
||
|
|
|
||
|
|
$declaration->delete();
|
||
|
|
|
||
|
|
$this->actingAs($owner);
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$response->assertInertia(fn ($page) => $page
|
||
|
|
->component('Dashboard')
|
||
|
|
->has('activities')
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('manager sees workspace-wide activity same as owner', function () {
|
||
|
|
[$manager, $workspace, $client] = setupActivityWorkspace('manager');
|
||
|
|
|
||
|
|
$worker = User::factory()->create();
|
||
|
|
$workspace->users()->attach($worker->id, ['role' => 'worker']);
|
||
|
|
|
||
|
|
// Create a declaration by the worker
|
||
|
|
$this->actingAs($worker);
|
||
|
|
Declaration::factory()->create([
|
||
|
|
'workspace_id' => $workspace->id,
|
||
|
|
'client_id' => $client->id,
|
||
|
|
'assigned_to' => $worker->id,
|
||
|
|
'status' => DeclarationStatus::EnCours,
|
||
|
|
'due_date' => now()->addDays(10),
|
||
|
|
]);
|
||
|
|
|
||
|
|
$this->actingAs($manager);
|
||
|
|
$response = $this->get(route('dashboard'));
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$response->assertInertia(fn ($page) => $page
|
||
|
|
->component('Dashboard')
|
||
|
|
->has('activities')
|
||
|
|
);
|
||
|
|
|
||
|
|
$activitiesData = $response->original->getData()['page']['props']['activities'];
|
||
|
|
expect(count($activitiesData))->toBeGreaterThan(0);
|
||
|
|
});
|