get(route('admin.cms.display-modules')); $response->assertRedirect('/login'); }); test('display version list renders for authenticated users', function () { $user = User::factory()->create(); $this->actingAs($user); $response = $this->get(route('admin.cms.display-modules')); $response->assertSuccessful(); $response->assertSeeLivewire(DisplayVersionList::class); }); test('display dashboard documentation describes current workflow', function () { $user = User::factory()->create(); $this->actingAs($user); $this->get(route('admin.cms.display-dashboard')) ->assertSuccessful() ->assertSee('Live und Entwurf') ->assertSee('Meta-Einstellungen pflegen') ->assertSee('SVG-Logos') ->assertSee('/storage/...') ->assertSee('Entwurf in der 9:16-Vorschau'); }); test('can create a display version', function () { $user = User::factory()->create(); Livewire::actingAs($user) ->test(DisplayVersionList::class) ->set('newName', 'Test Version') ->set('newType', 'b2in') ->call('createVersion'); expect(DisplayVersion::where('name', 'Test Version')->exists())->toBeTrue(); $version = DisplayVersion::where('name', 'Test Version')->first(); expect($version->type)->toBe(DisplayVersionType::B2in); expect($version->settings)->toBeArray(); expect($version->settings)->toHaveKey('theme'); expect($version->settings)->toHaveKey('header_logo_url'); expect($version->settings)->toHaveKey('footer_url'); }); test('create version validates required fields', function () { $user = User::factory()->create(); Livewire::actingAs($user) ->test(DisplayVersionList::class) ->set('newName', '') ->set('newType', '') ->call('createVersion') ->assertHasErrors(['newName', 'newType']); }); test('can delete a display version', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(); Livewire::actingAs($user) ->test(DisplayVersionList::class) ->call('deleteVersion', $version->id); expect(DisplayVersion::find($version->id))->toBeNull(); }); test('cannot delete a display version that is used by a playlist', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['name' => 'Genutztes Modul']); $display = Display::factory()->create(); $playlist = DisplayPlaylist::factory()->create([ 'display_id' => $display->id, 'status' => DisplayPlaylist::STATUS_PUBLISHED, 'published_at' => now(), ]); DisplayPlaylistItem::factory()->create([ 'display_playlist_id' => $playlist->id, 'display_version_id' => $version->id, 'sort_order' => 0, ]); Livewire::actingAs($user) ->test(DisplayVersionList::class) ->call('deleteVersion', $version->id) ->assertSee('kann nicht gelöscht werden'); expect(DisplayVersion::find($version->id))->not->toBeNull(); }); test('can toggle display version active status', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['is_active' => true]); Livewire::actingAs($user) ->test(DisplayVersionList::class) ->call('toggleActive', $version->id); expect($version->fresh()->is_active)->toBeFalse(); }); // ======================================== // DisplayVersionEditor // ======================================== test('display version editor renders with correct version data', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['name' => 'My Version']); $this->actingAs($user); $response = $this->get(route('admin.cms.display-module-edit', $version)); $response->assertSuccessful(); $response->assertSeeLivewire(DisplayVersionEditor::class); }); test('display module editor renders module preview', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['name' => 'Preview Modul']); $this->actingAs($user); $response = $this->get(route('admin.cms.display-module-edit', $version)); $response->assertSuccessful(); $response->assertSee('Modul-Vorschau'); $response->assertSee('/preview/module/'.$version->id, false); }); test('item edit modal renders module iframe preview', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'slide', 'content' => [ 'type' => 'product-hero', 'title' => 'Preview Slide', 'image_url' => '../assets/preview.jpg', ], ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', $item->id) ->assertSee('Einzel-Vorschau im Bearbeiten-Dialog') ->assertSee('/preview/module/'.$version->id.'/item/'.$item->id, false) ->assertSee('Schließen'); }); test('item modal url inputs avoid wire:model.blur to prevent the teleported-modal cleanup crash', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'media') ->assertDontSee('wire:model.blur', false) ->assertSee('wire:model.live.debounce.500ms="mediaUrl"', false); }); test('video item modal labels the title field as an internal name not shown on screen', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'video') ->assertSee('Name') ->assertSee('wird nicht im Video eingeblendet') ->assertDontSee('Titel (optional)'); }); test('video playlist renders a media thumbnail for stored videos', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'video', 'content' => ['filename' => '/storage/display-media/clip.mp4', 'title' => 'Clip', 'position' => 25], ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->assertSee('/storage/display-media/clip.mp4#t=1', false); }); test('new item modal shows a placeholder instead of the module preview', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'video') ->assertSee('Die Vorschau erscheint, sobald der Inhalt gespeichert wurde.') ->assertSee('src="about:blank"', false) ->assertDontSee('/preview/module/'.$version->id.'/item/', false); }); test('item modal preview iframe keeps a stable wire:key to avoid morph crashes', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'video') ->assertSee('wire:key="item-modal-preview"', false); }); test('saved item modal shows the single-item preview iframe', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'video', 'content' => ['filename' => 'clip.mp4', 'title' => 'Clip', 'position' => 25], ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', $item->id) ->assertSee('wire:key="item-modal-preview"', false) ->assertSee('/preview/module/'.$version->id.'/item/'.$item->id, false); }); test('can add a video item to video-display version', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'video') ->set('videoFilename', 'test.mp4') ->set('videoTitle', 'Test Video') ->set('videoPosition', 50) ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item)->not->toBeNull(); expect($item->item_type)->toBe('video'); expect($item->content['filename'])->toBe('test.mp4'); expect($item->content['position'])->toBe(50); }); test('can add a media item to b2in version', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'media') ->set('mediaType', 'video') ->set('mediaCategory', 'immobilien') ->set('mediaUrl', '../assets/test.mp4') ->set('mediaHeadline', 'Test Headline') ->set('mediaSubline', 'Test Subline') ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item)->not->toBeNull(); expect($item->item_type)->toBe('media'); expect($item->content['media_type'])->toBe('video'); expect($item->content['headline'])->toBe('Test Headline'); }); test('can edit an existing item', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'video', 'content' => ['filename' => 'old.mp4', 'title' => 'Old', 'position' => 25], ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', $item->id) ->set('videoFilename', 'new.mp4') ->set('videoTitle', 'New Title') ->call('saveItem'); $item->refresh(); expect($item->content['filename'])->toBe('new.mp4'); expect($item->content['title'])->toBe('New Title'); }); test('editing an inactive item keeps it inactive', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'video-display']); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'video', 'content' => ['filename' => 'old.mp4', 'title' => 'Old', 'position' => 25], 'is_active' => false, ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', $item->id) ->assertSet('videoIsActive', false) ->set('videoTitle', 'New Title') ->call('saveItem'); expect($item->fresh()->is_active)->toBeFalse(); }); test('updating an item keeps modal open and refreshes iframe preview', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'slide', 'content' => [ 'type' => 'product-hero', 'title' => 'Old Title', 'image_url' => '../assets/old.jpg', ], ]); $component = Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', $item->id); $initialRefreshCounter = $component->get('previewFrameRefreshCounter'); $component ->set('slideTitle', 'New Title') ->call('saveItem') ->assertSet('showItemModal', true) ->assertSet('itemId', $item->id) ->assertSee('Einzel-Vorschau im Bearbeiten-Dialog'); expect($item->fresh()->content['title'])->toBe('New Title'); expect($component->get('previewFrameRefreshCounter'))->toBeGreaterThan($initialRefreshCounter); }); test('can delete an item', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(); $item = DisplayVersionItem::factory()->create(['display_version_id' => $version->id]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('deleteItem', $item->id); expect(DisplayVersionItem::find($item->id))->toBeNull(); }); test('can toggle item active status', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'is_active' => true, ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('toggleItemStatus', $item->id); expect($item->fresh()->is_active)->toBeFalse(); }); test('can reorder items', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(); $item1 = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'video', 'sort_order' => 0, ]); $item2 = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'video', 'sort_order' => 1, ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('moveItem', $item2->id, 'up'); expect($item1->fresh()->sort_order)->toBe(1); expect($item2->fresh()->sort_order)->toBe(0); }); test('can add a slide item to offers version', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'slide') ->set('slideDuration', 10000) ->set('slideImageUrl', '../assets/goya1.jpg') ->set('slideShowBadge', true) ->set('slideBadge', 'Einzelstück') ->set('slideEyebrow', 'Hersteller: Sudbrock') ->set('slideTitle', 'GOYA Sideboard') ->set('slideShowPrice', true) ->set('slidePrice', '489 €') ->set('slideOriginalPrice', 'statt 4.744 €') ->set('slideQrUrl', 'https://cabinet-bielefeld.de') ->set('slideQrTitle', 'Reservieren') ->set('slideContact', '0521 98620100') ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item)->not->toBeNull(); expect($item->item_type)->toBe('slide'); expect($item->content['type'])->toBe('detail'); expect($item->content['title'])->toBe('GOYA Sideboard'); expect($item->content['price'])->toBe('489 €'); expect($item->content['show_price'])->toBeTrue(); expect($item->content['image_url'])->toBe('../assets/goya1.jpg'); expect($item->content['qr_url'])->toBe('https://cabinet-bielefeld.de'); }); test('can add a slide with bullets to offers version', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'slide') ->set('slideTitle', 'GOYA Sideboard') ->set('slideShowBullets', true) ->set('slideBullets', ['Einzelstück', 'Abholung möglich', 'Lieferung optional']) ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item->content['bullets'])->toHaveCount(3); expect($item->content['bullets'][0])->toBe('Einzelstück'); expect($item->content['show_bullets'])->toBeTrue(); }); test('slide editor persists the strike-through original price option', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'slide') ->set('slideTitle', 'Streich Slide') ->set('slideShowPrice', true) ->set('slidePrice', '199 €') ->set('slideOriginalPrice', 'statt 399 €') ->set('slideStrikeOriginalPrice', true) ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item->content['strike_original_price'])->toBeTrue(); expect($item->content['original_price'])->toBe('statt 399 €'); }); test('slide editor no longer exposes a slide type selector', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'slide') ->assertDontSee('Slide-Typ') ->assertSee('Bild & Badge') ->assertSee('Badge anzeigen') ->assertSee('Aufzählung anzeigen') ->assertSee('QR-Code anzeigen'); }); test('hidden slide blocks are persisted via their show flags', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'slide') ->set('slideTitle', 'Nur Titel') ->set('slideShowBadge', false) ->set('slideShowEyebrow', false) ->set('slideShowBullets', false) ->set('slideShowPrice', false) ->set('slideShowQr', false) ->set('slideShowContact', false) ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item->content['show_badge'])->toBeFalse(); expect($item->content['show_eyebrow'])->toBeFalse(); expect($item->content['show_bullets'])->toBeFalse(); expect($item->content['show_price'])->toBeFalse(); expect($item->content['show_qr'])->toBeFalse(); expect($item->content['show_contact'])->toBeFalse(); }); test('legacy slides without show flags keep rendering their populated blocks', function () { $version = DisplayVersion::factory()->create(['type' => 'offers']); DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'slide', 'content' => [ 'type' => 'product-hero', 'title' => 'Legacy Slide', 'badge_text' => 'Einzelstück', 'price' => '489 €', 'bullets' => ['Punkt A'], ], ]); $config = app(\App\Services\DisplayPlaylistConfigBuilder::class) ->fromModules(DisplayVersion::whereKey($version->id)->with('items')->get()); $slide = $config['playlist'][0]['slides'][0]; expect($slide['show_badge'])->toBeTrue(); expect($slide['show_price'])->toBeTrue(); expect($slide['show_bullets'])->toBeTrue(); expect($slide['show_subline'])->toBeFalse(); expect($slide['show_disclaimer'])->toBeFalse(); }); test('can edit a slide item with new fields', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); $item = DisplayVersionItem::factory()->create([ 'display_version_id' => $version->id, 'item_type' => 'slide', 'content' => [ 'type' => 'product-hero', 'duration' => 10000, 'image_url' => '../assets/old.jpg', 'badge_text' => 'Old Badge', 'eyebrow' => 'Old', 'title' => 'Old Title', 'subline' => '', 'price' => '100 €', 'original_price' => '', 'tag_text' => '', 'bullets' => [], 'disclaimer' => '', 'qr_url' => 'https://example.com', 'qr_title' => 'QR', 'contact' => '', 'show_brand_text' => false, 'brand_tagline' => '', ], ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', $item->id) ->set('slideTitle', 'New Title') ->set('slidePrice', '299 €') ->call('saveItem'); $item->refresh(); expect($item->content['title'])->toBe('New Title'); expect($item->content['price'])->toBe('299 €'); expect($item->content['image_url'])->toBe('../assets/old.jpg'); }); test('can save version settings', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create([ 'type' => 'b2in', 'settings' => ['theme' => 'dark'], ]); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openSettingsModal') ->set('settings.theme', 'light') ->set('settings.header_claim', 'Custom Claim') ->set('settings.footer_prefix', 'powered by') ->call('saveSettings'); expect($version->fresh()->settings['theme'])->toBe('light'); expect($version->fresh()->settings['header_claim'])->toBe('Custom Claim'); expect($version->fresh()->settings['footer_prefix'])->toBe('powered by'); }); test('b2in defaults include brand position and footer toggle', function () { $defaults = \App\Support\DisplayModuleSettings::defaults(DisplayVersionType::B2in); expect($defaults)->toHaveKey('logo_position', 'top-left') ->and($defaults)->toHaveKey('claim_position', 'top-right') ->and($defaults)->toHaveKey('show_footer', true) ->and($defaults)->toHaveKey('show_logo', true) ->and($defaults)->toHaveKey('show_claim', true); }); test('selecting a video medium auto-sets the media type to video', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); $media = DisplayMedia::factory()->video()->create(); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'media') ->set('mediaType', 'image') ->call('onDisplayMediaSelected', 'mediaUrl', $media->id, $media->getUrl()) ->assertSet('mediaType', 'video'); }); test('selecting an image medium auto-sets the media type to image', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); $media = DisplayMedia::factory()->create(['type' => 'image']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'media') ->set('mediaType', 'video') ->call('onDisplayMediaSelected', 'mediaUrl', $media->id, $media->getUrl()) ->assertSet('mediaType', 'image'); }); test('media item modal offers the sonstiges category and an automatic type hint', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'media') ->assertSee('Sonstiges') ->assertSee('wird automatisch aus dem gewählten Medium erkannt'); }); test('b2in settings editor shows the brand section and footer toggle', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->assertSee('Marke') ->assertSee('Logo-Position') ->assertSee('Claim-Position') ->assertSee('Logo anzeigen') ->assertSee('Claim anzeigen') ->assertSee('Footer anzeigen'); }); test('saving b2in settings persists logo and claim visibility', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openSettingsModal') ->set('settings.show_logo', false) ->set('settings.show_claim', false) ->call('saveSettings'); $settings = $version->fresh()->settings; expect($settings['show_logo'])->toBeFalse() ->and($settings['show_claim'])->toBeFalse(); }); test('enabling the footer pulls bottom brand positions back to the top', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->set('settings.show_footer', false) ->set('settings.logo_position', 'bottom-left') ->set('settings.claim_position', 'bottom-right') ->set('settings.show_footer', true) ->assertSet('settings.logo_position', 'top-left') ->assertSet('settings.claim_position', 'top-right'); }); test('bottom brand positions are kept when the footer is hidden', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->set('settings.show_footer', false) ->set('settings.logo_position', 'bottom-left') ->assertSet('settings.logo_position', 'bottom-left'); }); test('claim never shares the same corner as the logo', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->set('settings.show_footer', false) ->set('settings.logo_position', 'bottom-left') ->set('settings.claim_position', 'bottom-left') ->assertSet('settings.claim_position', fn ($value) => $value !== 'bottom-left'); }); test('saving b2in settings persists brand positions and footer toggle', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'b2in']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openSettingsModal') ->set('settings.show_footer', false) ->set('settings.logo_position', 'bottom-right') ->set('settings.claim_position', 'top-left') ->call('saveSettings'); $settings = $version->fresh()->settings; expect($settings['show_footer'])->toBeFalse() ->and($settings['logo_position'])->toBe('bottom-right') ->and($settings['claim_position'])->toBe('top-left'); }); test('offers meta settings only keep loop and transition', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->assertSee('Meta-Einstellungen für dieses Modul') ->call('openSettingsModal') ->assertSee('Endlosschleife') ->assertSee('Transition') ->assertSee('Transition-Dauer (ms)') ->assertDontSee('Branding') ->assertDontSee('Brand-Text') ->assertDontSee('Footer & QR für alle Slides') ->assertDontSee('Footer-Claim'); }); test('offer slide editor manages logo and brand text per slide', function () { $user = User::factory()->create(); $version = DisplayVersion::factory()->create(['type' => 'offers']); Livewire::actingAs($user) ->test(DisplayVersionEditor::class, ['displayVersion' => $version]) ->call('openItemModal', null, 'slide') ->assertSee('Logo & Marke') ->assertSee('Logo & Marken-Text anzeigen') ->set('slideTitle', 'Logo Slide') ->set('slideShowLogo', true) ->set('slideLogoUrl', '/storage/display-media/logo.svg') ->set('slideBrandText', 'Musterstadt') ->set('slideBrandTagline', 'Beratung • Lieferung') ->call('saveItem'); $item = DisplayVersionItem::where('display_version_id', $version->id)->first(); expect($item->content['show_logo'])->toBeTrue(); expect($item->content['logo_url'])->toBe('/storage/display-media/logo.svg'); expect($item->content['brand_text'])->toBe('Musterstadt'); expect($item->content['brand_tagline'])->toBe('Beratung • Lieferung'); });