b2in/tests/Feature/Admin/Cms/CmsReferencesIndexTest.php
Kevin Adametz 90aa079cf7 CMS: Standorte an der Marke, Seitenbaum mit Vorschau, Referenzen-Modul
Nachtrag 11: Herkunfts-Sektion liest Ort, Entfernung und Rolle aus der
Markenverwaltung (drei neue Felder an cms_brands, BrandOriginSeeder),
Kartenpositionen im Code, „Marken“ in der Sidebar.

Nachtrag 12: Inhalte-Editor zeigt die Seiten der Website mit ihren
Sektionen in Reihenfolge (config/cms_pages.php, CmsPageTree), Felder in
Klartext, fehlende Sektionen aus der Sprachdatei anlegbar, Vorschau der
echten Seite im iframe mit Sprung zur Sektion; Anker an allen lebenden
Sektionen nachgezogen.

Nachtrag 13: Referenzen als eigenes Modul (CmsReference, Portal-Seite,
/referenzen mit Fallback auf die Markengalerien); Immobilien-Projekte
aus Sidebar und CMS-Übersicht genommen, Route bleibt.

Dazu .gitignore für _b2in_interior_shop/ und docs/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 14:58:45 +00:00

144 lines
4.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\CmsReference;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Volt\Volt;
uses(RefreshDatabase::class);
/**
* Referenzen verwalten (Nachtrag 13).
*/
beforeEach(function () {
url()->forceRootUrl('https://'.config('domains.domain_portal'));
});
it('requires authentication', function () {
$this->get(route('cms.references.index'))->assertRedirect('/login');
});
it('renders for authenticated users', function () {
$this->actingAs(User::factory()->create())
->get(route('cms.references.index'))
->assertSuccessful()
->assertSee('Referenzen')
->assertSee('Keine Referenzen');
});
it('creates a reference with brands, cover and gallery', function () {
$this->seed(\Database\Seeders\CmsBrandSeeder::class);
$this->actingAs(User::factory()->create());
Volt::test('admin.cms.references-index')
->call('openCreate')
->set('referenceTitle', 'Ankleide unter der Dachschräge')
->set('location', 'Bielefeld')
->set('year', '2025')
->set('description', 'Maßschrank bis unter den First.')
->set('image', 'referenzen/ankleide.webp')
->set('brandSlugs', ['cabinet', 'tischlerei'])
->call('addGalleryImage')
->set('gallery.0.image', 'referenzen/ankleide-2.webp')
->set('gallery.0.caption', 'Innenausbau')
->call('addGalleryImage')
->call('save')
->assertHasNoErrors();
$reference = CmsReference::firstOrFail();
expect($reference->getTranslation('title', 'de'))->toBe('Ankleide unter der Dachschräge')
->and($reference->location)->toBe('Bielefeld')
->and($reference->year)->toBe('2025')
->and($reference->image)->toBe('referenzen/ankleide.webp')
->and($reference->brand_slugs)->toBe(['cabinet', 'tischlerei'])
->and($reference->gallery)->toBe([['image' => 'referenzen/ankleide-2.webp', 'caption' => 'Innenausbau']])
->and($reference->is_published)->toBeTrue();
});
it('requires a title', function () {
$this->actingAs(User::factory()->create());
Volt::test('admin.cms.references-index')
->call('openCreate')
->set('referenceTitle', '')
->call('save')
->assertHasErrors(['referenceTitle']);
expect(CmsReference::count())->toBe(0);
});
it('rejects a brand slug that does not exist', function () {
$this->actingAs(User::factory()->create());
Volt::test('admin.cms.references-index')
->call('openCreate')
->set('referenceTitle', 'Test')
->set('brandSlugs', ['gibt-es-nicht'])
->call('save')
->assertHasErrors(['brandSlugs.0']);
});
it('edits an existing reference and keeps both languages', function () {
$this->actingAs(User::factory()->create());
$reference = CmsReference::factory()->create(['title' => ['de' => 'Küche', 'en' => 'Kitchen']]);
Volt::test('admin.cms.references-index')
->call('openEdit', $reference->id)
->assertSet('referenceTitle', 'Küche')
->set('referenceTitle', 'Küche in Hiddenhausen')
->call('save')
->assertHasNoErrors();
$reference->refresh();
expect($reference->getTranslation('title', 'de'))->toBe('Küche in Hiddenhausen')
->and($reference->getTranslation('title', 'en'))->toBe('Kitchen');
});
it('reorders and removes gallery images', function () {
$this->actingAs(User::factory()->create());
$reference = CmsReference::factory()->withGallery(3)->create();
Volt::test('admin.cms.references-index')
->call('openEdit', $reference->id)
->call('moveGalleryImage', 2, -1)
->call('moveGalleryImage', 0, -1)
->call('removeGalleryImage', 2)
->call('save')
->assertHasNoErrors();
expect(array_column($reference->fresh()->gallery, 'image'))
->toBe(['referenzen/bild-1.webp', 'referenzen/bild-3.webp']);
});
it('toggles the published state and deletes', function () {
$this->actingAs(User::factory()->create());
$reference = CmsReference::factory()->create();
Volt::test('admin.cms.references-index')
->call('togglePublished', $reference->id);
expect($reference->fresh()->is_published)->toBeFalse();
Volt::test('admin.cms.references-index')
->call('deleteReference', $reference->id);
expect(CmsReference::count())->toBe(0);
});
it('is linked from the sidebar while the real estate projects are not', function () {
\Spatie\Permission\Models\Role::firstOrCreate(['name' => 'Admin']);
$user = User::factory()->create();
$user->assignRole('Admin');
$html = $this->actingAs($user)
->get(route('cms.references.index'))
->assertSuccessful()
->getContent();
expect($html)->toMatch('#data-content>\s*Referenzen\s*</div>#')
->not->toContain(route('cms.projects.index'));
});