694 lines
22 KiB
PHP
694 lines
22 KiB
PHP
<?php
|
|
|
|
use App\Models\AdminLog;
|
|
use App\Models\Timeline;
|
|
use App\Models\TimelineUpdate;
|
|
use App\Models\User;
|
|
use App\Notifications\TimelineUpdateNotification;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Livewire\Volt\Volt;
|
|
|
|
beforeEach(function () {
|
|
$this->admin = User::factory()->admin()->create();
|
|
$this->client = User::factory()->individual()->create();
|
|
$this->timeline = Timeline::factory()->create(['user_id' => $this->client->id]);
|
|
});
|
|
|
|
// ===========================================
|
|
// View & Access Tests
|
|
// ===========================================
|
|
|
|
test('admin can view timeline show page', function () {
|
|
$this->actingAs($this->admin)
|
|
->get(route('admin.timelines.show', $this->timeline))
|
|
->assertOk();
|
|
});
|
|
|
|
test('admin can view timeline with updates', function () {
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'First update text here',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->assertSee('First update text here')
|
|
->assertSee($this->admin->full_name);
|
|
});
|
|
|
|
test('non-admin cannot access timeline show page', function () {
|
|
$this->actingAs($this->client)
|
|
->get(route('admin.timelines.show', $this->timeline))
|
|
->assertForbidden();
|
|
});
|
|
|
|
test('guest cannot access timeline show page', function () {
|
|
$this->get(route('admin.timelines.show', $this->timeline))
|
|
->assertRedirect(route('login'));
|
|
});
|
|
|
|
// ===========================================
|
|
// Add Update Tests
|
|
// ===========================================
|
|
|
|
test('admin can add update with valid text', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is a valid update text with enough characters.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
expect(TimelineUpdate::where('timeline_id', $this->timeline->id)->count())->toBe(1);
|
|
|
|
$update = TimelineUpdate::where('timeline_id', $this->timeline->id)->first();
|
|
expect($update->update_text)->toContain('This is a valid update text with enough characters.');
|
|
expect($update->admin_id)->toBe($this->admin->id);
|
|
});
|
|
|
|
test('admin can add update with minimum 10 characters', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', '1234567890')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
expect(TimelineUpdate::where('timeline_id', $this->timeline->id)->exists())->toBeTrue();
|
|
});
|
|
|
|
test('cannot add update with empty text', function () {
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', '')
|
|
->call('addUpdate')
|
|
->assertHasErrors(['updateText' => 'required']);
|
|
});
|
|
|
|
test('cannot add update with less than 10 characters', function () {
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'short')
|
|
->call('addUpdate')
|
|
->assertHasErrors(['updateText' => 'min']);
|
|
});
|
|
|
|
test('admin name is automatically recorded when adding update', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
$update = TimelineUpdate::where('timeline_id', $this->timeline->id)->first();
|
|
expect($update->admin_id)->toBe($this->admin->id);
|
|
expect($update->admin->id)->toBe($this->admin->id);
|
|
});
|
|
|
|
test('timestamp is automatically recorded when adding update', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$beforeTime = now()->subSecond();
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
$update = TimelineUpdate::where('timeline_id', $this->timeline->id)->first();
|
|
expect($update->created_at)->not->toBeNull();
|
|
expect($update->created_at->isAfter($beforeTime))->toBeTrue();
|
|
});
|
|
|
|
test('update text is cleared after adding update', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$component = Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
expect($component->get('updateText'))->toBe('');
|
|
});
|
|
|
|
// ===========================================
|
|
// Edit Update Tests
|
|
// ===========================================
|
|
|
|
test('admin can edit existing update', function () {
|
|
Notification::fake();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', 'Updated text with new content.')
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
$update->refresh();
|
|
expect($update->update_text)->toContain('Updated text with new content.');
|
|
});
|
|
|
|
test('edit preserves original created_at timestamp', function () {
|
|
Notification::fake();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$originalCreatedAt = $update->created_at->toDateTimeString();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
// Wait a moment to ensure time difference
|
|
sleep(1);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', 'Updated text with new content.')
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
$update->refresh();
|
|
expect($update->created_at->toDateTimeString())->toBe($originalCreatedAt);
|
|
});
|
|
|
|
test('edit updates the updated_at timestamp', function () {
|
|
Notification::fake();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$originalUpdatedAt = $update->updated_at;
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
// Wait a moment to ensure time difference
|
|
sleep(1);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', 'Updated text with new content.')
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
$update->refresh();
|
|
expect($update->updated_at->gt($originalUpdatedAt))->toBeTrue();
|
|
});
|
|
|
|
test('cannot change admin on edit', function () {
|
|
Notification::fake();
|
|
|
|
$otherAdmin = User::factory()->admin()->create();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $otherAdmin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', 'Updated text with new content.')
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
$update->refresh();
|
|
expect($update->admin_id)->toBe($otherAdmin->id);
|
|
});
|
|
|
|
test('cancel edit clears form', function () {
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$component = Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->call('cancelEdit');
|
|
|
|
expect($component->get('editingUpdateId'))->toBeNull();
|
|
expect($component->get('updateText'))->toBe('');
|
|
});
|
|
|
|
test('edit update loads text into form', function () {
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$component = Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id);
|
|
|
|
expect($component->get('editingUpdateId'))->toBe($update->id);
|
|
expect($component->get('updateText'))->toBe('Original text here.');
|
|
});
|
|
|
|
// ===========================================
|
|
// HTML Sanitization Tests
|
|
// ===========================================
|
|
|
|
test('html is sanitized when adding update', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$maliciousText = '<script>alert("xss")</script>Valid update text here.';
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', $maliciousText)
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
$update = TimelineUpdate::where('timeline_id', $this->timeline->id)->first();
|
|
expect($update->update_text)->not->toContain('<script>');
|
|
expect($update->update_text)->toContain('Valid update text here.');
|
|
});
|
|
|
|
test('html is sanitized when editing update', function () {
|
|
Notification::fake();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$maliciousText = '<script>alert("xss")</script>Updated safe text.';
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', $maliciousText)
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
$update->refresh();
|
|
expect($update->update_text)->not->toContain('<script>');
|
|
expect($update->update_text)->toContain('Updated safe text.');
|
|
});
|
|
|
|
test('allowed html tags are preserved', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$validHtml = '<strong>Bold text</strong> and <em>italic text</em> and <a href="https://example.com">a link</a>';
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', $validHtml)
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
$update = TimelineUpdate::where('timeline_id', $this->timeline->id)->first();
|
|
expect($update->update_text)->toContain('<strong>');
|
|
expect($update->update_text)->toContain('<em>');
|
|
expect($update->update_text)->toContain('<a href=');
|
|
});
|
|
|
|
// ===========================================
|
|
// Notification Tests
|
|
// ===========================================
|
|
|
|
test('client receives notification when update is added', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$this->client,
|
|
TimelineUpdateNotification::class
|
|
);
|
|
});
|
|
|
|
test('notification contains correct update data', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is the notification test update.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$this->client,
|
|
TimelineUpdateNotification::class,
|
|
function ($notification) {
|
|
return str_contains($notification->update->update_text, 'This is the notification test update.');
|
|
}
|
|
);
|
|
});
|
|
|
|
test('deactivated user does not receive notification when update is added', function () {
|
|
Notification::fake();
|
|
|
|
$deactivatedClient = User::factory()->individual()->deactivated()->create();
|
|
$timeline = Timeline::factory()->create(['user_id' => $deactivatedClient->id]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertNotSentTo($deactivatedClient, TimelineUpdateNotification::class);
|
|
});
|
|
|
|
test('notification uses arabic subject for arabic-preferred user', function () {
|
|
Notification::fake();
|
|
|
|
$arabicClient = User::factory()->individual()->create(['preferred_language' => 'ar']);
|
|
$timeline = Timeline::factory()->create([
|
|
'user_id' => $arabicClient->id,
|
|
'case_name' => 'Test Case Name',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$arabicClient,
|
|
TimelineUpdateNotification::class,
|
|
function ($notification, $channels, $notifiable) {
|
|
$mail = $notification->toMail($notifiable);
|
|
|
|
return str_contains($mail->subject, 'تحديث جديد على قضيتك')
|
|
&& str_contains($mail->subject, 'Test Case Name');
|
|
}
|
|
);
|
|
});
|
|
|
|
test('notification uses english subject for english-preferred user', function () {
|
|
Notification::fake();
|
|
|
|
$englishClient = User::factory()->individual()->create(['preferred_language' => 'en']);
|
|
$timeline = Timeline::factory()->create([
|
|
'user_id' => $englishClient->id,
|
|
'case_name' => 'Test Case Name',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$englishClient,
|
|
TimelineUpdateNotification::class,
|
|
function ($notification, $channels, $notifiable) {
|
|
$mail = $notification->toMail($notifiable);
|
|
|
|
return str_contains($mail->subject, 'New update on your case')
|
|
&& str_contains($mail->subject, 'Test Case Name');
|
|
}
|
|
);
|
|
});
|
|
|
|
test('notification defaults to arabic when preferred language is ar', function () {
|
|
Notification::fake();
|
|
|
|
$arabicClient = User::factory()->individual()->create(['preferred_language' => 'ar']);
|
|
$timeline = Timeline::factory()->create([
|
|
'user_id' => $arabicClient->id,
|
|
'case_name' => 'Default Arabic Case',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$arabicClient,
|
|
TimelineUpdateNotification::class,
|
|
function ($notification, $channels, $notifiable) {
|
|
$mail = $notification->toMail($notifiable);
|
|
|
|
return str_contains($mail->subject, 'تحديث جديد على قضيتك');
|
|
}
|
|
);
|
|
});
|
|
|
|
test('notification is queued for performance', function () {
|
|
expect(TimelineUpdateNotification::class)
|
|
->toImplement(\Illuminate\Contracts\Queue\ShouldQueue::class);
|
|
});
|
|
|
|
test('notification uses correct markdown template for arabic user', function () {
|
|
Notification::fake();
|
|
|
|
$arabicClient = User::factory()->individual()->create(['preferred_language' => 'ar']);
|
|
$timeline = Timeline::factory()->create(['user_id' => $arabicClient->id]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$arabicClient,
|
|
TimelineUpdateNotification::class,
|
|
function ($notification, $channels, $notifiable) {
|
|
$mail = $notification->toMail($notifiable);
|
|
|
|
return $mail->markdown === 'emails.timeline.update.ar';
|
|
}
|
|
);
|
|
});
|
|
|
|
test('notification uses correct markdown template for english user', function () {
|
|
Notification::fake();
|
|
|
|
$englishClient = User::factory()->individual()->create(['preferred_language' => 'en']);
|
|
$timeline = Timeline::factory()->create(['user_id' => $englishClient->id]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
Notification::assertSentTo(
|
|
$englishClient,
|
|
TimelineUpdateNotification::class,
|
|
function ($notification, $channels, $notifiable) {
|
|
$mail = $notification->toMail($notifiable);
|
|
|
|
return $mail->markdown === 'emails.timeline.update.en';
|
|
}
|
|
);
|
|
});
|
|
|
|
// ===========================================
|
|
// Audit Log Tests
|
|
// ===========================================
|
|
|
|
test('audit log created when update is added', function () {
|
|
Notification::fake();
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->set('updateText', 'This is a valid update text.')
|
|
->call('addUpdate')
|
|
->assertHasNoErrors();
|
|
|
|
expect(AdminLog::where('action', 'create')
|
|
->where('target_type', 'timeline_update')
|
|
->where('admin_id', $this->admin->id)
|
|
->exists())->toBeTrue();
|
|
});
|
|
|
|
test('audit log created when update is edited', function () {
|
|
Notification::fake();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', 'Updated text content here.')
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
expect(AdminLog::where('action', 'update')
|
|
->where('target_type', 'timeline_update')
|
|
->where('target_id', $update->id)
|
|
->where('admin_id', $this->admin->id)
|
|
->exists())->toBeTrue();
|
|
});
|
|
|
|
test('audit log contains old and new values when editing', function () {
|
|
Notification::fake();
|
|
|
|
$update = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Original text here.',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->call('editUpdate', $update->id)
|
|
->set('updateText', 'Updated text content here.')
|
|
->call('saveEdit')
|
|
->assertHasNoErrors();
|
|
|
|
$log = AdminLog::where('action', 'update')
|
|
->where('target_type', 'timeline_update')
|
|
->where('target_id', $update->id)
|
|
->first();
|
|
|
|
expect($log->old_values)->toHaveKey('update_text');
|
|
expect($log->old_values['update_text'])->toBe('Original text here.');
|
|
expect($log->new_values)->toHaveKey('update_text');
|
|
});
|
|
|
|
// ===========================================
|
|
// Display Order Tests
|
|
// ===========================================
|
|
|
|
test('updates display in chronological order oldest first', function () {
|
|
$oldUpdate = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'First update - oldest.',
|
|
'created_at' => now()->subDays(3),
|
|
]);
|
|
|
|
$newUpdate = TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Second update - newest.',
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
$this->timeline->refresh();
|
|
$updates = $this->timeline->updates;
|
|
|
|
expect($updates->first()->id)->toBe($oldUpdate->id);
|
|
expect($updates->last()->id)->toBe($newUpdate->id);
|
|
});
|
|
|
|
test('timeline model orders updates chronologically', function () {
|
|
TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Middle update.',
|
|
'created_at' => now()->subDay(),
|
|
]);
|
|
|
|
TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Oldest update.',
|
|
'created_at' => now()->subDays(5),
|
|
]);
|
|
|
|
TimelineUpdate::factory()->create([
|
|
'timeline_id' => $this->timeline->id,
|
|
'admin_id' => $this->admin->id,
|
|
'update_text' => 'Newest update.',
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
$updates = $this->timeline->updates;
|
|
|
|
expect($updates[0]->update_text)->toBe('Oldest update.');
|
|
expect($updates[1]->update_text)->toBe('Middle update.');
|
|
expect($updates[2]->update_text)->toBe('Newest update.');
|
|
});
|
|
|
|
// ===========================================
|
|
// Timeline Header Display Tests
|
|
// ===========================================
|
|
|
|
test('timeline show page displays case name', function () {
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->assertSee($this->timeline->case_name);
|
|
});
|
|
|
|
test('timeline show page displays case reference if present', function () {
|
|
$timeline = Timeline::factory()->create([
|
|
'user_id' => $this->client->id,
|
|
'case_reference' => 'REF-12345',
|
|
]);
|
|
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $timeline])
|
|
->assertSee('REF-12345');
|
|
});
|
|
|
|
test('timeline show page displays client info', function () {
|
|
$this->actingAs($this->admin);
|
|
|
|
Volt::test('admin.timelines.show', ['timeline' => $this->timeline])
|
|
->assertSee($this->client->full_name)
|
|
->assertSee($this->client->email);
|
|
});
|