libra/tests/Feature/Client/TimelineViewTest.php

229 lines
7.1 KiB
PHP

<?php
use App\Models\Timeline;
use App\Models\TimelineUpdate;
use App\Models\User;
use Livewire\Volt\Volt;
// Authorization Tests
test('client can view own timelines list', function () {
$client = User::factory()->individual()->create();
Timeline::factory()->count(3)->create(['user_id' => $client->id]);
$this->actingAs($client)
->get(route('client.timelines.index'))
->assertOk();
});
test('client cannot view other clients timelines in list', function () {
$client = User::factory()->individual()->create();
$otherClient = User::factory()->individual()->create();
Timeline::factory()->create([
'user_id' => $otherClient->id,
'case_name' => 'Other Client Case',
]);
$this->actingAs($client);
Volt::test('client.timelines.index')
->assertDontSee('Other Client Case');
});
test('client can view own timeline detail', function () {
$client = User::factory()->individual()->create();
$timeline = Timeline::factory()->create([
'user_id' => $client->id,
'case_name' => 'My Contract Case',
]);
$this->actingAs($client)
->get(route('client.timelines.show', $timeline))
->assertOk()
->assertSee('My Contract Case');
});
test('client cannot view other clients timeline detail', function () {
$client = User::factory()->individual()->create();
$otherClient = User::factory()->individual()->create();
$otherTimeline = Timeline::factory()->create(['user_id' => $otherClient->id]);
$this->actingAs($client)
->get(route('client.timelines.show', $otherTimeline))
->assertForbidden();
});
test('guest cannot access timelines', function () {
$this->get(route('client.timelines.index'))
->assertRedirect(route('login'));
});
test('admin cannot access client timeline routes', function () {
$admin = User::factory()->admin()->create();
$this->actingAs($admin)
->get(route('client.timelines.index'))
->assertForbidden();
});
// List View Tests
test('active timelines displayed separately from archived', function () {
$client = User::factory()->individual()->create();
Timeline::factory()->create([
'user_id' => $client->id,
'case_name' => 'Active Case',
'status' => 'active',
]);
Timeline::factory()->create([
'user_id' => $client->id,
'case_name' => 'Archived Case',
'status' => 'archived',
]);
$this->actingAs($client);
Volt::test('client.timelines.index')
->assertSee('Active Case')
->assertSee('Archived Case')
->assertSeeInOrder([__('client.active_cases'), 'Active Case', __('client.archived_cases'), 'Archived Case']);
});
test('timeline list shows update count', function () {
$client = User::factory()->individual()->create();
$timeline = Timeline::factory()->create(['user_id' => $client->id]);
TimelineUpdate::factory()->count(5)->create(['timeline_id' => $timeline->id]);
$this->actingAs($client);
Volt::test('client.timelines.index')
->assertSee('5');
});
test('empty state shown when no timelines', function () {
$client = User::factory()->individual()->create();
$this->actingAs($client);
Volt::test('client.timelines.index')
->assertSee(__('client.no_cases_yet'));
});
// Detail View Tests
test('timeline detail shows all updates chronologically', function () {
$client = User::factory()->individual()->create();
$timeline = Timeline::factory()->create(['user_id' => $client->id]);
TimelineUpdate::factory()->create([
'timeline_id' => $timeline->id,
'update_text' => 'First Update',
'created_at' => now()->subDays(2),
]);
TimelineUpdate::factory()->create([
'timeline_id' => $timeline->id,
'update_text' => 'Second Update',
'created_at' => now()->subDay(),
]);
$this->actingAs($client);
Volt::test('client.timelines.show', ['timeline' => $timeline])
->assertSeeInOrder(['First Update', 'Second Update']);
});
test('timeline detail shows case name and reference', function () {
$client = User::factory()->individual()->create();
$timeline = Timeline::factory()->create([
'user_id' => $client->id,
'case_name' => 'Property Dispute',
'case_reference' => 'REF-2024-001',
]);
$this->actingAs($client);
Volt::test('client.timelines.show', ['timeline' => $timeline])
->assertSee('Property Dispute')
->assertSee('REF-2024-001');
});
test('timeline detail shows status badge', function () {
$client = User::factory()->individual()->create();
$activeTimeline = Timeline::factory()->create([
'user_id' => $client->id,
'status' => 'active',
]);
$this->actingAs($client);
Volt::test('client.timelines.show', ['timeline' => $activeTimeline])
->assertSee(__('client.active'));
});
test('empty updates shows no updates message', function () {
$client = User::factory()->individual()->create();
$timeline = Timeline::factory()->create(['user_id' => $client->id]);
$this->actingAs($client);
Volt::test('client.timelines.show', ['timeline' => $timeline])
->assertSee(__('client.no_updates_yet'));
});
// Read-Only Enforcement Tests
test('client timeline view is read-only with no edit actions', function () {
$client = User::factory()->individual()->create();
$timeline = Timeline::factory()->create(['user_id' => $client->id]);
$this->actingAs($client);
// Verify no edit/delete/archive buttons or forms exist in the view
Volt::test('client.timelines.show', ['timeline' => $timeline])
->assertDontSee('wire:click="edit"')
->assertDontSee('wire:click="delete"')
->assertDontSee('wire:click="archive"')
->assertDontSee('wire:submit');
});
// Company client access test
test('company client can view own timelines', function () {
$company = User::factory()->company()->create();
Timeline::factory()->count(2)->create(['user_id' => $company->id]);
$this->actingAs($company)
->get(route('client.timelines.index'))
->assertOk();
});
// Pagination Tests
test('timeline list paginates active timelines', function () {
$client = User::factory()->individual()->create();
// Create 15 active timelines (more than page size of 10)
Timeline::factory()->count(15)->create([
'user_id' => $client->id,
'status' => 'active',
]);
$this->actingAs($client);
// First page should show 10 timelines
$response = $this->get(route('client.timelines.index'));
$response->assertOk();
// Navigate to second page
$response = $this->get(route('client.timelines.index', ['active' => 2]));
$response->assertOk();
});
test('timeline list paginates archived timelines separately', function () {
$client = User::factory()->individual()->create();
// Create 15 archived timelines
Timeline::factory()->count(15)->create([
'user_id' => $client->id,
'status' => 'archived',
]);
$this->actingAs($client);
// Navigate to second page of archived
$response = $this->get(route('client.timelines.index', ['archived' => 2]));
$response->assertOk();
});