171 lines
6.0 KiB
PHP
171 lines
6.0 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Notifications\Modals\Detail as NotificationDetail;
|
|
use App\Livewire\PhotoHelp\Modals\Result as PhotoResult;
|
|
use App\Livewire\Rewards\Modals\Purchase as RewardsPurchase;
|
|
use App\Livewire\Settings\Modals\Delete as SettingsDelete;
|
|
use App\Livewire\Settings\Modals\LogoutAll as SettingsLogoutAll;
|
|
use App\Livewire\Subjects\Modals\Detail as SubjectDetail;
|
|
use App\Livewire\Tasks\Modals\Detail as TaskDetail;
|
|
use App\Models\License;
|
|
use App\Models\Role;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Livewire\Livewire;
|
|
use LivewireUI\Modal\ModalComponent;
|
|
|
|
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' => 'Modal Tester',
|
|
'email' => 'modal@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('Subjects\\Modals\\Detail extends ModalComponent and renders', function () {
|
|
expect(is_subclass_of(SubjectDetail::class, ModalComponent::class))->toBeTrue();
|
|
|
|
Livewire::test(SubjectDetail::class, [
|
|
'subject' => ['name' => 'Mathematik', 'icon' => '∑', 'color' => 'primary', 'progress' => 75, 'lessons' => '18 / 24', 'next' => 'Multiplizieren', 'level' => 'K4'],
|
|
])
|
|
->assertSee('Mathematik')
|
|
->assertSee('75 %')
|
|
->assertSee('Multiplizieren');
|
|
});
|
|
|
|
it('Tasks\\Modals\\Detail renders with task data', function () {
|
|
Livewire::test(TaskDetail::class, [
|
|
'task' => ['title' => 'Multiplikation', 'meta' => 'Mathe · 12 Aufgaben', 'points' => 120, 'due' => 'Heute', 'status' => 'open'],
|
|
])
|
|
->assertSee('Multiplikation')
|
|
->assertSee('+120')
|
|
->assertSee('Heute')
|
|
->assertSee('Offen');
|
|
});
|
|
|
|
it('PhotoHelp\\Modals\\Result renders step-by-step solution', function () {
|
|
Livewire::test(PhotoResult::class)
|
|
->assertSee('Erkennung')
|
|
->assertSee('Methode')
|
|
->assertSee('Schritte');
|
|
});
|
|
|
|
it('Rewards\\Modals\\Purchase: confirm + purchase flow', function () {
|
|
$item = ['title' => 'Avatar', 'emoji' => '🎨', 'category' => 'Avatar', 'desc' => 'Cool item', 'price' => 800];
|
|
|
|
Livewire::test(RewardsPurchase::class, ['item' => $item, 'balance' => 2480])
|
|
->assertSee('Avatar')
|
|
->assertSee('800')
|
|
->call('confirm')
|
|
->assertSet('confirming', true)
|
|
->call('purchase')
|
|
->assertSet('purchased', true)
|
|
->assertSet('balance', 1680);
|
|
});
|
|
|
|
it('Rewards\\Modals\\Purchase: cannot purchase if insufficient balance', function () {
|
|
$item = ['title' => 'Drache', 'emoji' => '🐉', 'category' => 'Tier', 'desc' => 'Big', 'price' => 5000];
|
|
|
|
Livewire::test(RewardsPurchase::class, ['item' => $item, 'balance' => 100])
|
|
->call('purchase')
|
|
->assertSet('purchased', false)
|
|
->assertSet('balance', 100);
|
|
});
|
|
|
|
it('Notifications\\Modals\\Detail renders notification body', function () {
|
|
Livewire::test(NotificationDetail::class, [
|
|
'notification' => ['title' => 'Neue Aufgabe', 'body' => 'Heute warten 4 Aufgaben.', 'time' => 'vor 10 Min.'],
|
|
])
|
|
->assertSee('Neue Aufgabe')
|
|
->assertSee('Heute warten 4 Aufgaben.');
|
|
});
|
|
|
|
it('Settings\\Modals\\LogoutAll renders confirm prompt', function () {
|
|
Livewire::test(SettingsLogoutAll::class)
|
|
->assertSee('Auf allen Geräten abmelden');
|
|
});
|
|
|
|
it('Settings\\Modals\\Delete: only deletes when confirmText is LÖSCHEN', function () {
|
|
Livewire::test(SettingsDelete::class)
|
|
->set('confirmText', 'falsch')
|
|
->call('delete')
|
|
->assertSet('confirmText', 'falsch')
|
|
->set('confirmText', 'LÖSCHEN')
|
|
->call('delete');
|
|
});
|
|
|
|
it('all modal classes extend wire-elements ModalComponent', function () {
|
|
$modals = [
|
|
SubjectDetail::class,
|
|
TaskDetail::class,
|
|
PhotoResult::class,
|
|
RewardsPurchase::class,
|
|
NotificationDetail::class,
|
|
SettingsLogoutAll::class,
|
|
SettingsDelete::class,
|
|
];
|
|
|
|
foreach ($modals as $modal) {
|
|
expect(is_subclass_of($modal, ModalComponent::class))
|
|
->toBeTrue("{$modal} must extend LivewireUI\\Modal\\ModalComponent");
|
|
}
|
|
});
|
|
|
|
it('dashboard layout includes livewire-ui-modal container', function () {
|
|
$response = $this->get(route('dashboard'));
|
|
$response->assertOk();
|
|
$response->assertSee('livewire-ui-modal', false);
|
|
});
|
|
|
|
it('Livewire ComponentRegistry resolves feature modal aliases', function () {
|
|
$registry = app('livewire');
|
|
|
|
// Each modal alias must be resolvable by Livewire to its class
|
|
$cases = [
|
|
'subjects.modals.detail' => SubjectDetail::class,
|
|
'tasks.modals.detail' => TaskDetail::class,
|
|
'photo-help.modals.result' => PhotoResult::class,
|
|
'rewards.modals.purchase' => RewardsPurchase::class,
|
|
'notifications.modals.detail' => NotificationDetail::class,
|
|
'settings.modals.logout-all' => SettingsLogoutAll::class,
|
|
'settings.modals.delete' => SettingsDelete::class,
|
|
];
|
|
|
|
foreach ($cases as $alias => $class) {
|
|
$resolved = app('livewire.finder')->resolveClassComponentClassName($alias);
|
|
expect($resolved)->toBe($class, "Alias [{$alias}] must resolve to {$class}, got {$resolved}");
|
|
}
|
|
});
|