- Mediathek: Video-Vorschaubilder statt Icons (FFmpeg-Thumbnails + Backfill-Command), Kategorie "Sonstiges" - B2in Media-Picker zeigt alle Medientypen, Typ wird automatisch erkannt; Thumbnail-Preview vor allen Medien-URL-Feldern - B2in Marke/Footer: Footer ein/aus, Logo+Claim frei positionierbar (Ecken) mit Constraints, separate Anzeige-Schalter - Angebote-Modul dynamisch: kein Slide-Typ mehr, einheitliches Detail-Layout mit ein-/ausblendbaren Bloecken, Logo/Brand pro Slide, Streichpreis-Option - Player: leere Module stoppen Endlosschleife, dynamische Layout-Anpassung bei verstecktem Footer/Header - Fix: Script-Ladereihenfolge (Livewire vor Flux), entfernte stale public/flux/flux.js, Modal-Crash beim Aktualisieren behoben Co-authored-by: Cursor <cursoragent@cursor.com>
781 lines
30 KiB
PHP
781 lines
30 KiB
PHP
<?php
|
|
|
|
use App\Enums\DisplayVersionType;
|
|
use App\Livewire\Admin\Cms\DisplayVersionEditor;
|
|
use App\Livewire\Admin\Cms\DisplayVersionList;
|
|
use App\Models\Display;
|
|
use App\Models\DisplayMedia;
|
|
use App\Models\DisplayPlaylist;
|
|
use App\Models\DisplayPlaylistItem;
|
|
use App\Models\DisplayVersion;
|
|
use App\Models\DisplayVersionItem;
|
|
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);
|
|
});
|
|
|
|
// ========================================
|
|
// DisplayVersionList
|
|
// ========================================
|
|
|
|
test('display version list requires authentication', function () {
|
|
$response = $this->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');
|
|
});
|