b2in/tests/Feature/MagazinPageTest.php
Kevin Adametz 6d53243ea6 B2in Interior: Relaunch der Website, Kernmarken-CMS und Terminanfrage
Umsetzung von AP0-AP6 aus dev/2026-08-28/entwicklungsplan.md sowie der
vorab gefundenen Befunde T1 und B1-B13.

Befunde
- CmsContentSeeder überschrieb bei jedem Lauf alle redaktionellen Inhalte;
  jetzt Redaktionsschutz plus gezielter Relaunch-Seeder (B1)
- Magazin-CMS war nicht ans Frontend angebunden, Artikel jetzt über Slugs
  mit 301 von den alten numerischen URLs (B2)
- Vier veröffentlichte Display-Playlists zeigten auf b2in.test und wären
  live nicht ladbar gewesen (B13)
- Info-Tablet speicherte geleerte Öffnungszeiten nicht (T1)
- /service und /portfolio lieferten seit Februar 500 (B12)

Website
- Startseite neu strukturiert und umgetextet, eigene Seite /marken mit
  Detailseite je Kernmarke, /netzwerk und Altrouten leiten dorthin
- Galerie je Marke, getrennt nach realisierten Projekten und
  Visualisierungen; ohne gesetzte Kategorie gilt ein Bild als Entwurf
- Seite /referenzen, gespeist aus den Markengalerien
- Showroom-Display im 9:16-Rahmen über eine schreibgeschützte Embed-Route
  ohne Preview-Token
- Terminanfrage-Widget auf allen Seiten, Markenauswahl aus dem CMS,
  WhatsApp per Klick-zum-Chat-Link mit vorbereitetem Text
- FAQ, Über-uns, Kontakt und Magazin inhaltlich auf Interior umgestellt

Sonstiges
- Vorschau-Instanzen liefern noindex und verlinken sich bei unbekanntem
  Host auf sich selbst statt auf eine fremde Domain
- Seeder-Zugangsdaten aus dem Code in die Konfiguration (B8)
- Ablauf für die Vorschau: dev/2026-08-28/preview-deployment.md

833 Tests grün (3084 Assertions), Pint sauber.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 15:31:19 +00:00

171 lines
5.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
use App\Models\CmsArticle;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('magazin list page loads successfully', function () {
$this->get('/magazin')
->assertSuccessful()
->assertSee('Magazin');
});
it('magazin list shows all five articles', function () {
$this->get('/magazin')
->assertSuccessful()
->assertSee('Escrow-System')
->assertSee('Al Jaddaf')
->assertSee('Turnkey-Investments')
->assertSee('Supply-Chain-Management')
->assertSee('Local for Local');
});
it('magazin detail page loads for the first article', function () {
$this->get('/magazin/escrow-system-dubai-investoren')
->assertSuccessful()
->assertSee('Escrow-System')
->assertSee('Dubai Land Department');
});
it('magazin detail page loads for the last article', function () {
$this->get('/magazin/local-for-local-regionaler-moebelhandel')
->assertSuccessful()
->assertSee('Local for Local')
->assertSee('Support your Locals');
});
it('serves every article by its slug', function () {
foreach (CmsArticle::LEGACY_ID_TO_SLUG as $slug) {
$this->get('/magazin/'.$slug)->assertSuccessful();
}
});
it('returns 404 for an unknown slug instead of silently showing the first article', function () {
$this->get('/magazin/gibt-es-nicht')->assertNotFound();
});
it('links to the articles by slug, not by id', function () {
$this->get('/magazin')
->assertSuccessful()
->assertSee('/magazin/escrow-system-dubai-investoren');
});
// ========================================
// Alte numerische URLs
// ========================================
it('redirects the old numeric URLs permanently to the slug', function () {
foreach (CmsArticle::LEGACY_ID_TO_SLUG as $id => $slug) {
$this->get('/magazin/'.$id)
->assertStatus(301)
->assertRedirect('/magazin/'.$slug);
}
});
it('returns 404 for a numeric URL that never existed', function () {
$this->get('/magazin/999')->assertNotFound();
});
// ========================================
// CMS-Anbindung
// ========================================
it('renders what is maintained in the CMS, not the lang file', function () {
CmsArticle::factory()->create([
'slug' => 'escrow-system-dubai-investoren',
'title' => 'Im CMS geänderter Titel',
'is_published' => true,
'order' => 1,
'content' => ['de' => ['intro' => 'Im CMS geänderter Einstieg.', 'sections' => []]],
]);
$this->get('/magazin')
->assertSuccessful()
->assertSee('Im CMS geänderter Titel');
$this->get('/magazin/escrow-system-dubai-investoren')
->assertSuccessful()
->assertSee('Im CMS geänderter Titel');
});
it('hides unpublished articles from the list and returns 404 on their detail page', function () {
CmsArticle::factory()->create([
'slug' => 'noch-nicht-fertig',
'title' => 'Entwurf, noch nicht öffentlich',
'is_published' => false,
'order' => 1,
]);
// Ein veroeffentlichter Artikel muss existieren, sonst greift der Lang-Fallback.
CmsArticle::factory()->create([
'slug' => 'escrow-system-dubai-investoren',
'title' => 'Veröffentlicht',
'is_published' => true,
'order' => 2,
]);
$this->get('/magazin')
->assertSuccessful()
->assertDontSee('Entwurf, noch nicht öffentlich');
$this->get('/magazin/noch-nicht-fertig')->assertNotFound();
});
it('falls back to the lang file while no articles are maintained', function () {
expect(CmsArticle::count())->toBe(0);
$this->get('/magazin')
->assertSuccessful()
->assertSee('Escrow-System');
});
it('prefers the CMS over the lang file once articles exist', function () {
CmsArticle::factory()->create([
'slug' => 'nur-dieser-eine',
'title' => 'Einziger gepflegter Artikel',
'is_published' => true,
'order' => 1,
]);
$this->get('/magazin')
->assertSuccessful()
->assertSee('Einziger gepflegter Artikel')
->assertDontSee('Al Jaddaf');
});
// ========================================
// Neue Interior-Beiträge
// ========================================
it('leads the list with the interior articles, not with the dubai ones', function () {
$slugs = array_keys(CmsArticle::forFrontend());
expect($slugs[0])->toBe('massanfertigung-warum-der-millimeter-zaehlt')
->and($slugs[1])->toBe('kueche-planen-vom-wunsch-zum-grundriss');
});
it('serves the two new articles by their own slug', function () {
$this->get('/magazin/massanfertigung-warum-der-millimeter-zaehlt')
->assertSuccessful()
->assertSee('Nach Maß statt von der Stange', false);
$this->get('/magazin/kueche-planen-vom-wunsch-zum-grundriss')
->assertSuccessful()
->assertSee('Küche planen', false);
});
it('does not invent legacy numeric urls for the new articles', function () {
// Die Slugs kommen aus der Lang-Datei, nicht aus LEGACY_ID_TO_SLUG – /magazin/6 gab es nie.
expect(CmsArticle::slugForLegacyId(6))->toBeNull();
$this->get('/magazin/6')->assertNotFound();
});
it('takes the slug from the lang entry when one is given', function () {
expect(CmsArticle::slugForLangArticle(6, ['slug' => 'eigener-slug']))->toBe('eigener-slug')
->and(CmsArticle::slugForLangArticle(1, []))->toBe('escrow-system-dubai-investoren')
->and(CmsArticle::slugForLangArticle(99, []))->toBeNull();
});