130 lines
4.7 KiB
PHP
130 lines
4.7 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Notifications\Index as NotificationsIndex;
|
|
use App\Livewire\Tasks\Index as TasksIndex;
|
|
use App\Models\License;
|
|
use App\Models\Role;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Livewire\Livewire;
|
|
|
|
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->seed(\Database\Seeders\RolesSeeder::class);
|
|
|
|
$tenant = Tenant::firstOrCreate(
|
|
['name' => 'Test Schule'],
|
|
['type' => 'school', 'active' => true]
|
|
);
|
|
|
|
$this->user = User::withoutGlobalScopes()->create([
|
|
'name' => 'URL Tester', 'email' => 'url@test.example',
|
|
'tenant_id' => $tenant->id, 'password' => bcrypt('password'),
|
|
]);
|
|
|
|
$role = Role::where('name', 'child')->first();
|
|
DB::table('role_user')->insert([
|
|
'user_id' => $this->user->id, 'role_id' => $role->id,
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
]);
|
|
|
|
$license = License::withoutGlobalScopes()->create([
|
|
'tenant_id' => $tenant->id, 'type' => 'school_flat',
|
|
'expires_at' => now()->addYear(), 'active' => true,
|
|
]);
|
|
DB::table('license_assignments')->insert([
|
|
'license_id' => $license->id, 'user_id' => $this->user->id,
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
]);
|
|
|
|
$this->actingAs($this->user);
|
|
});
|
|
|
|
it('Tasks: default filter is open, server-renders correct from first paint', function () {
|
|
Livewire::test(TasksIndex::class)
|
|
->assertSet('filter', 'open')
|
|
->assertSee('Multiplikation bis 100')
|
|
->assertDontSee('Gedicht lernen');
|
|
});
|
|
|
|
it('Tasks: filter param from URL hydrates initial state', function () {
|
|
Livewire::withQueryParams(['filter' => 'done'])
|
|
->test(TasksIndex::class)
|
|
->assertSet('filter', 'done')
|
|
->assertSee('Gedicht lernen')
|
|
->assertDontSee('Multiplikation bis 100');
|
|
});
|
|
|
|
it('Tasks: invalid filter param falls back to open', function () {
|
|
Livewire::withQueryParams(['filter' => 'evil-injection'])
|
|
->test(TasksIndex::class)
|
|
->assertSet('filter', 'open');
|
|
});
|
|
|
|
it('Tasks: setFilter only accepts allowed values', function () {
|
|
Livewire::test(TasksIndex::class)
|
|
->call('setFilter', 'done')
|
|
->assertSet('filter', 'done')
|
|
->call('setFilter', 'all')
|
|
->assertSet('filter', 'all')
|
|
->call('setFilter', 'malicious')
|
|
->assertSet('filter', 'all');
|
|
});
|
|
|
|
it('Tasks: filter pill has aria-current=page when active', function () {
|
|
Livewire::test(TasksIndex::class)
|
|
->call('setFilter', 'done')
|
|
->assertSeeHtml('data-testid="filter-done"')
|
|
->assertSeeHtml('aria-current="page"');
|
|
});
|
|
|
|
it('Tasks: skeleton uses bg-bg-soft (same as table card), with bg-line bars', function () {
|
|
$html = Livewire::test(TasksIndex::class)->html();
|
|
expect($html)->toContain('wire:loading.flex');
|
|
expect($html)->toContain('animate-pulse');
|
|
expect($html)->toContain('bg-line');
|
|
expect($html)->toContain('data-testid="tasks-skeleton"');
|
|
// Skeleton container must use same surface as table card (bg-bg-soft within same tag)
|
|
expect(preg_match('/<div[^>]+class="[^"]*\bbg-bg-soft\b[^"]*"[^>]+data-testid="tasks-skeleton"/', $html))->toBe(1);
|
|
});
|
|
|
|
it('Tasks: task row is NOT clickable; modal trigger is button only', function () {
|
|
$html = Livewire::test(TasksIndex::class)->html();
|
|
// Detail-button is the wire:click trigger
|
|
expect($html)->toContain('data-testid="task-detail-btn"');
|
|
expect($html)->toContain("openModal");
|
|
// Row container does NOT have wire:click on itself
|
|
expect(preg_match('/data-testid="task-row"[^>]*wire:click=/', $html))->toBe(0);
|
|
});
|
|
|
|
it('Notifications: default filter is all', function () {
|
|
Livewire::test(NotificationsIndex::class)->assertSet('filter', 'all');
|
|
});
|
|
|
|
it('Notifications: filter param "unread" hydrates from URL', function () {
|
|
Livewire::withQueryParams(['filter' => 'unread'])
|
|
->test(NotificationsIndex::class)
|
|
->assertSet('filter', 'unread');
|
|
});
|
|
|
|
it('Notifications: invalid filter falls back to all', function () {
|
|
Livewire::withQueryParams(['filter' => 'bogus'])
|
|
->test(NotificationsIndex::class)
|
|
->assertSet('filter', 'all');
|
|
});
|
|
|
|
it('Notifications: markRead adds key', function () {
|
|
Livewire::test(NotificationsIndex::class)
|
|
->call('markRead', 'n1')
|
|
->assertSet('readKeys', ['n1']);
|
|
});
|
|
|
|
it('Notifications: skeleton uses bg-bg-soft + bg-line bars', function () {
|
|
$html = Livewire::test(NotificationsIndex::class)->html();
|
|
expect($html)->toContain('data-testid="notif-skeleton"');
|
|
expect($html)->toContain('bg-line');
|
|
expect(preg_match('/<div[^>]+class="[^"]*\bbg-bg-soft\b[^"]*"[^>]+data-testid="notif-skeleton"/', $html))->toBe(1);
|
|
});
|