12-05-2026 admin, Panel Displays

This commit is contained in:
Kevin Adametz 2026-05-12 18:28:38 +02:00
parent 0762e3beac
commit 6a65354f4c
43 changed files with 3273 additions and 410 deletions

View file

@ -2,16 +2,39 @@
use App\Livewire\Admin\Cms\DisplayList;
use App\Models\Display;
use App\Models\DisplayPlaylist;
use App\Models\DisplayPlaylistItem;
use App\Models\DisplayVersion;
use App\Models\User;
use Illuminate\Support\Facades\URL;
use Livewire\Livewire;
beforeEach(function () {
$portalDomain = config('domains.domain_portal');
Livewire::withoutLazyLoading();
url()->forceRootUrl('https://'.$portalDomain);
URL::forceRootUrl('https://'.$portalDomain);
});
function createDisplayListPlaylist(Display $display, string $status, array $versionIds): DisplayPlaylist
{
$playlist = DisplayPlaylist::factory()
->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'));
@ -59,6 +82,7 @@ test('can assign versions to a display', function () {
expect($display->versions)->toHaveCount(2);
expect($display->versions->first()->id)->toBe($version1->id);
expect($display->versions->last()->id)->toBe($version2->id);
expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$version1->id, $version2->id]);
});
test('can reorder versions in playlist', function () {
@ -78,6 +102,7 @@ test('can reorder versions in playlist', function () {
$display->refresh();
expect($display->versions->first()->id)->toBe($version2->id);
expect($display->versions->last()->id)->toBe($version1->id);
expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$version2->id, $version1->id]);
});
test('can remove version from playlist', function () {
@ -99,6 +124,7 @@ test('can remove version from playlist', function () {
$display->refresh();
expect($display->versions)->toHaveCount(1);
expect($display->versions->first()->id)->toBe($version2->id);
expect($display->livePlaylist->modules->pluck('id')->all())->toBe([$version2->id]);
});
test('can delete a display', function () {
@ -146,3 +172,191 @@ test('does not add duplicate version to playlist', function () {
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]);
expect($display->versions->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]);
expect($display->versions->pluck('id')->all())->toBe([]);
});
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('<iframe');
});
test('draft editor persists module changes immediately for preview reloads', function () {
$user = User::factory()->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('<option value="'.$selectedVersion->id.'">Schon gewählt')
->assertSeeHtml('<option value="'.$availableVersion->id.'">Noch verfügbar');
});
test('module select is replaced by a hint when all modules are already selected', function () {
$user = User::factory()->create();
$selectedVersion = DisplayVersion::factory()->create(['name' => 'Einziges Modul']);
$display = Display::factory()->create();
createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$selectedVersion->id]);
Livewire::actingAs($user)
->test(DisplayList::class)
->call('openModal', $display->id, DisplayPlaylist::STATUS_PUBLISHED)
->assertSee('Alle verfügbaren Module sind bereits hinzugefügt.')
->assertDontSeeHtml('<option value="'.$selectedVersion->id.'">Einziges Modul');
});
test('renders live and draft playlist columns', function () {
$user = User::factory()->create();
$liveVersion = DisplayVersion::factory()->create(['name' => 'Live Modul']);
$draftVersion = DisplayVersion::factory()->create(['name' => 'Draft Modul']);
$display = Display::factory()->test()->create(['name' => 'Test-Display']);
createDisplayListPlaylist($display, DisplayPlaylist::STATUS_PUBLISHED, [$liveVersion->id]);
createDisplayListPlaylist($display, DisplayPlaylist::STATUS_DRAFT, [$draftVersion->id]);
Livewire::actingAs($user)
->test(DisplayList::class)
->assertSee('Live Modul')
->assertSee('Draft Modul')
->assertSee('Live bearbeiten')
->assertSee('Live-URL zum Kopieren')
->assertSee(url('/_cabinet/display/index.html').'?id='.$display->id, false)
->assertSee('Entwurf bearbeiten')
->assertSee('Test-Display');
});