state(['status' => $status]) ->create([ 'display_id' => $display->id, 'published_at' => $status === DisplayPlaylist::STATUS_PUBLISHED ? now() : null, ]); foreach (array_values($versionIds) as $sortOrder => $versionId) { DisplayPlaylistItem::factory()->create([ 'display_playlist_id' => $playlist->id, 'display_version_id' => $versionId, 'sort_order' => $sortOrder, ]); } return $playlist; } test('display list requires authentication', function () { $response = $this->get(route('admin.cms.displays')); $response->assertRedirect('/login'); }); test('display list renders for authenticated users', function () { $user = User::factory()->create(); $this->actingAs($user); $response = $this->get(route('admin.cms.displays')); $response->assertSuccessful(); $response->assertSeeLivewire(DisplayList::class); }); test('can create a display', function () { $user = User::factory()->create(); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal') ->set('displayName', 'Display 1 - Eingang') ->set('displayLocation', 'Schaufenster links') ->call('save'); expect(Display::where('name', 'Display 1 - Eingang')->exists())->toBeTrue(); }); test('can assign versions to a display', function () { $user = User::factory()->create(); $version1 = DisplayVersion::factory()->create(); $version2 = DisplayVersion::factory()->create(); $display = Display::factory()->create(); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id) ->call('addVersion', $version1->id) ->call('addVersion', $version2->id) ->call('save'); $display->refresh(); expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$version1->id, $version2->id]); }); test('can reorder versions in playlist', function () { $user = User::factory()->create(); $version1 = DisplayVersion::factory()->create(); $version2 = DisplayVersion::factory()->create(); $display = Display::factory()->create(); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id) ->call('addVersion', $version1->id) ->call('addVersion', $version2->id) ->call('moveVersion', 1, 'up') ->call('save'); $display->refresh(); expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$version2->id, $version1->id]); }); test('can remove version from playlist', function () { $user = User::factory()->create(); $version1 = DisplayVersion::factory()->create(); $version2 = DisplayVersion::factory()->create(); $display = Display::factory()->create(); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$version1->id, $version2->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id) ->call('removeVersion', 0) ->call('save'); $display->refresh(); expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$version2->id]); }); test('can delete a display', function () { $user = User::factory()->create(); $display = Display::factory()->create(); Livewire::actingAs($user) ->test(DisplayList::class) ->call('deleteDisplay', $display->id); expect(Display::find($display->id))->toBeNull(); }); test('can toggle display active status', function () { $user = User::factory()->create(); $display = Display::factory()->create(['is_active' => true]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('toggleActive', $display->id); expect($display->fresh()->is_active)->toBeFalse(); }); test('validates required fields when creating display', function () { $user = User::factory()->create(); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal') ->set('displayName', '') ->call('save') ->assertHasErrors(['displayName']); }); test('does not add duplicate version to playlist', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(); $component = Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal') ->call('addVersion', $version->id) ->call('addVersion', $version->id); expect($component->get('selectedVersionIds'))->toHaveCount(1); }); test('plus button adds the first available module when select has no explicit value', function () { $user = User::factory()->create(); $firstVersion = DisplayVersion::factory()->create(['name' => 'Angebote Schauraum']); DisplayVersion::factory()->create(['name' => 'Schaufenster Video']); $component = Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal') ->call('addVersion'); expect($component->get('selectedVersionIds'))->toBe([$firstVersion->id]); }); test('can create a draft playlist from live modules', function () { $user = User::factory()->create(); $version1 = DisplayVersion::factory()->create(); $version2 = DisplayVersion::factory()->create(); $display = Display::factory()->create(['preview_token' => null]); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$version1->id, $version2->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('createDraft', $display->id); $display->refresh(); expect($display->preview_token)->not->toBeNull(); expect($display->draftPlaylist)->not->toBeNull(); expect($display->draftPlaylist->modules->pluck('id')->all())->toBe([$version1->id, $version2->id]); }); test('can discard a draft playlist', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(); $display = Display::factory()->create(); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$version->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('discardDraft', $display->id); expect($display->fresh()->draftPlaylist)->toBeNull(); }); test('can publish a draft playlist over the live playlist', function () { $user = User::factory()->create(); $liveVersion = DisplayVersion::factory()->create(['name' => 'Live Modul']); $draftVersion = DisplayVersion::factory()->create(['name' => 'Draft Modul']); $display = Display::factory()->create(); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$liveVersion->id]); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$draftVersion->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('publishDraft', $display->id); $display->refresh(); expect($display->draftPlaylist)->toBeNull(); expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$draftVersion->id]); }); test('can edit live playlist without changing draft playlist', function () { $user = User::factory()->create(); $liveVersion = DisplayVersion::factory()->create(); $draftVersion = DisplayVersion::factory()->create(); $newLiveVersion = DisplayVersion::factory()->create(); $display = Display::factory()->create(); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$liveVersion->id]); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$draftVersion->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id, DisplayPlaylist::STATUS_PUBLISHED) ->call('addVersion', $newLiveVersion->id) ->call('save'); $display->refresh(); expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$liveVersion->id, $newLiveVersion->id]); expect($display->draftPlaylist->modules->pluck('id')->all())->toBe([$draftVersion->id]); }); test('can edit draft playlist without changing live playlist', function () { $user = User::factory()->create(); $liveVersion = DisplayVersion::factory()->create(); $draftVersion = DisplayVersion::factory()->create(); $newDraftVersion = DisplayVersion::factory()->create(); $display = Display::factory()->create(['preview_token' => null]); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$liveVersion->id]); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$draftVersion->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id, DisplayPlaylist::STATUS_DRAFT) ->call('addVersion', $newDraftVersion->id) ->call('save'); $display->refresh(); expect($display->preview_token)->not->toBeNull(); expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$liveVersion->id]); expect($display->draftPlaylist->modules->pluck('id')->all())->toBe([$draftVersion->id, $newDraftVersion->id]); }); test('draft editor renders iframe preview url', function () { $user = User::factory()->create(); $draftVersion = DisplayVersion::factory()->create(); $display = Display::factory()->create(['preview_token' => null]); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$draftVersion->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id, DisplayPlaylist::STATUS_DRAFT) ->assertSee('Live-Vorschau') ->assertSee('/preview/'.$display->fresh()->preview_token, false) ->assertSeeHtml('create(); $draftVersion = DisplayVersion::factory()->create(); $newDraftVersion = DisplayVersion::factory()->create(); $display = Display::factory()->create(); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$draftVersion->id]); $component = Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id, DisplayPlaylist::STATUS_DRAFT); $initialRefreshCounter = $component->get('previewFrameRefreshCounter'); $component->call('addVersion', $newDraftVersion->id); $display->refresh(); expect($display->draftPlaylist->modules->pluck('id')->all())->toBe([$draftVersion->id, $newDraftVersion->id]); expect($component->get('previewFrameRefreshCounter'))->toBeGreaterThan($initialRefreshCounter); }); test('module select only shows modules that can still be added', function () { $user = User::factory()->create(); $selectedVersion = DisplayVersion::factory()->create(['name' => 'Schon gewählt']); $availableVersion = DisplayVersion::factory()->create(['name' => 'Noch verfügbar']); $display = Display::factory()->create(); createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$selectedVersion->id]); Livewire::actingAs($user) ->test(DisplayList::class) ->call('openModal', $display->id, DisplayPlaylist::STATUS_PUBLISHED) ->assertDontSeeHtml('