85 lines
3.1 KiB
PHP
85 lines
3.1 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Settings\Index as SettingsIndex;
|
|
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' => 'Settings Nav Tester', 'email' => 'sn@test.example',
|
|
'tenant_id' => $tenant->id, 'password' => bcrypt('password'),
|
|
]);
|
|
|
|
$role = Role::where('name', 'school-admin')->first();
|
|
DB::table('role_user')->insert([
|
|
'user_id' => $this->user->id, 'role_id' => $role->id,
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
]);
|
|
|
|
$this->actingAs($this->user);
|
|
});
|
|
|
|
it('default section is profile, server-rendered (no Alpine flicker)', function () {
|
|
Livewire::test(SettingsIndex::class)
|
|
->assertSet('section', 'profile')
|
|
->assertSee('Profil')
|
|
->assertSeeHtml('data-section="profile"')
|
|
->assertDontSeeHtml('data-section="language"');
|
|
});
|
|
|
|
it('?section=security URL param hydrates initial state', function () {
|
|
Livewire::withQueryParams(['section' => 'security'])
|
|
->test(SettingsIndex::class)
|
|
->assertSet('section', 'security')
|
|
->assertSeeHtml('data-section="security"');
|
|
});
|
|
|
|
it('invalid section param falls back to profile', function () {
|
|
Livewire::withQueryParams(['section' => 'evil'])
|
|
->test(SettingsIndex::class)
|
|
->assertSet('section', 'profile');
|
|
});
|
|
|
|
it('setSection only accepts allowed values', function () {
|
|
Livewire::test(SettingsIndex::class)
|
|
->call('setSection', 'security')
|
|
->assertSet('section', 'security')
|
|
->call('setSection', 'malicious')
|
|
->assertSet('section', 'security');
|
|
});
|
|
|
|
it('only one section card renders at a time (no flicker)', function () {
|
|
$html = Livewire::test(SettingsIndex::class)->html();
|
|
|
|
// Profile renders, others do NOT (server-side conditional)
|
|
expect($html)->toContain('data-section="profile"');
|
|
expect($html)->not->toContain('data-section="language"');
|
|
expect($html)->not->toContain('data-section="security"');
|
|
expect($html)->not->toContain('data-section="notifications"');
|
|
expect($html)->not->toContain('data-section="danger"');
|
|
});
|
|
|
|
it('sub-nav uses server-rendered active state (aria-current)', function () {
|
|
$html = Livewire::test(SettingsIndex::class)->html();
|
|
expect($html)->toMatch('/data-testid="settings-nav-profile"[^>]*aria-current="page"|aria-current="page"[^>]*data-testid="settings-nav-profile"/');
|
|
});
|
|
|
|
it('sub-nav buttons NOT using :class Alpine bindings (no client-side flicker)', function () {
|
|
$tpl = file_get_contents(base_path('resources/views/livewire/settings/index.blade.php'));
|
|
// Sub-nav must use plain class string (server-side), not :class= for active state
|
|
expect($tpl)->not->toContain(':class="activeSection ===');
|
|
});
|