b2in/tests/Feature/LiveSiteReviewTest.php
Kevin Adametz 7953a8c9a1 Interior-Farbwelt, Welten-Trennung, Tischlerei und Herkunfts-Sektion
Arbeitsplan 14.09.2026, Punkte 1.1 bis 1.4 (Nachträge 6 bis 10 im Entwicklungsplan):

- Farbwelt Interior (Tanne, Creme, Sand, Ocker, Clay) als Standard, Immobilien-Welt
  behält das bisherige Blau über body.world-immobilien; Logo je Welt, Favicons neu,
  Welten-Wechsler in Kopf- und Fußzeile.
- Saubere Trennung der Welten: eigene Navigation, Ankündigungsleiste, Magazinliste,
  Über-uns-Seite, FAQ, Kontaktseite und Abschluss-CTA für Immobilien; Beiträge tragen
  eine Welt (Migration + Admin-Feld). Abschluss-CTA Ton in Ton statt Grün-zu-Ocker.
- Kontakt: Betreffe in Gruppen Interior / Immobilien / B2in, Marken darin.
  Terminanfrage-Buttons öffnen das Widget mit vorgewähltem Anliegen; Select-Felder
  einheitlich gestaltet.
- Tischlerei als vierte Kernmarke (Platzhalter), Kachelraster 2×2.
- Herkunfts-Sektion „Aus der Region gefertigt“ mit schematischer Standortkarte und
  Ablauf CABINET (Beratung Bielefeld, Fertigung Köln, Aufbau mit Tischlerei).

Deployment: migrate, WorldSplitCmsSeeder, CmsBrandSeeder, OriginSectionCmsSeeder
(Abschnitt 8 im Entwicklungsplan).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 12:46:41 +00:00

148 lines
6.1 KiB
PHP
Raw Permalink 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);
// ========================================
// Live-Seiten: HTTP Status
// ========================================
it('homepage loads', fn () => $this->get('/')->assertSuccessful());
it('immobilien page loads', fn () => $this->get('/immobilien')->assertSuccessful());
it('immobilien expose loads', fn () => $this->get('/immobilien/azizi-creek-views-4')->assertSuccessful());
it('marken page loads', fn () => $this->get('/marken')->assertSuccessful());
it('magazin list loads', fn () => $this->get('/magazin')->assertSuccessful());
it('every magazin article loads under its slug', function (string $slug) {
$this->get('/magazin/'.$slug)->assertSuccessful();
})->with(array_values(App\Models\CmsArticle::LEGACY_ID_TO_SLUG));
// Die alten numerischen URLs bleiben erreichbar – jetzt ueber eine 301 auf den Slug.
it('every old numeric magazin URL still reaches its article', function (int $id) {
$slug = App\Models\CmsArticle::slugForLegacyId($id);
$this->get('/magazin/'.$id)->assertRedirect('/magazin/'.$slug);
$this->get('/magazin/'.$slug)->assertSuccessful();
})->with(array_keys(App\Models\CmsArticle::LEGACY_ID_TO_SLUG));
it('about page loads', fn () => $this->get('/about')->assertSuccessful());
it('contact page loads', fn () => $this->get('/contact')->assertSuccessful());
it('faq page loads', fn () => $this->get('/faq')->assertSuccessful());
// ========================================
// Redirects
// ========================================
it('interior redirects to marken', fn () => $this->get('/interior')->assertRedirect('/marken'));
it('partner redirects to marken', fn () => $this->get('/partner')->assertRedirect('/marken'));
it('netzwerk redirects to marken', fn () => $this->get('/netzwerk')->assertRedirect('/marken'));
it('ecosystem redirects to partner', fn () => $this->get('/ecosystem')->assertRedirect('/partner'));
// ========================================
// Dev/Archiv-Seiten
// ========================================
it('dev sitemap loads', fn () => $this->get('/dev/sitemap')->assertSuccessful());
it('dev immobilien v1 loads', fn () => $this->get('/dev/immobilien-v1')->assertSuccessful());
it('dev interior v1 loads', fn () => $this->get('/dev/interior-v1')->assertSuccessful());
it('dev partner v1 loads', fn () => $this->get('/dev/partner-v1')->assertSuccessful());
// ========================================
// 404 für ungültige Routen
// ========================================
it('invalid immobilien slug returns 404', fn () => $this->get('/immobilien/nonexistent')->assertNotFound());
// ========================================
// Announcement Bar auf allen Seiten
// ========================================
it('announcement bar visible on homepage', fn () => $this->get('/')->assertSee('B2in Interior'));
it('announcement bar visible on about', fn () => $this->get('/about')->assertSee('B2in Interior'));
// ========================================
// Kritische Inhalte vorhanden
// ========================================
it('homepage has navigation', fn () => $this->get('/')->assertSee('Immobilien')->assertSee('Netzwerk')->assertSee('Magazin'));
it('immobilien has all five sections', function () {
$this->get('/immobilien')
->assertSee('Warum Dubai für Investoren relevant bleibt')
->assertSee('Der Kaufprozess mit B2in')
->assertSee('Passt Dubai zu Ihrer Investmentstrategie?')
->assertSee('Einrichtung mitdenken')
->assertSee('Investoren');
});
it('marken page lists the core brands', fn () => $this->get('/marken')->assertSee('CABINET')->assertSee('Febrü', false));
it('magazin has all articles across both worlds', function () {
$this->get('/magazin')
->assertSee('Supply-Chain')
->assertSee('Local for Local');
$this->get('/immobilien/magazin')
->assertSee('Escrow-System')
->assertSee('Al Jaddaf')
->assertSee('Turnkey');
});
// ========================================
// Verwaiste Seiten
// ========================================
//
// /service und /portfolio lieferten Status 500, weil ihre Content-Sektionen nicht mehr
// existieren. Sie sind oeffentlich erreichbar und damit auch fuer Crawler sichtbar.
it('service page no longer errors', fn () => $this->get('/service')->assertRedirect('/marken'));
it('portfolio page no longer errors', fn () => $this->get('/portfolio')->assertRedirect('/immobilien'));
// ========================================
// Inhalte auf den Interior-Auftritt umgestellt
// ========================================
it('no longer sells dubai investments in the faq', function () {
$response = $this->get('/faq')->assertSuccessful();
$response->assertDontSee('Dubai')
->assertSee('Für Ihr Zuhause', false)
->assertSee('Für Projekte und Objekte');
});
it('tells the interior story on the about page', function () {
$this->get('/about')
->assertSuccessful()
->assertDontSee('Dubai')
->assertDontSee('digitale Werkzeuge')
->assertSee('Beratung statt Verkauf')
->assertSee('Regional verwurzelt');
});
it('offers interior subjects in the contact form', function () {
$this->get('/contact')
->assertSuccessful()
->assertSee('Beratungstermin')
->assertSee('Maßanfertigung für mein Zuhause', false)
->assertSee('Küchenplanung', false);
});
// ========================================
// Vorschau-Instanzen dürfen nicht indexiert werden
// ========================================
it('allows indexing in production', function () {
config()->set('app.indexable', true);
$this->get('/')
->assertSuccessful()
->assertDontSee('noindex', false);
});
it('blocks indexing on a preview instance', function () {
config()->set('app.indexable', false);
$this->get('/')
->assertSuccessful()
->assertSee('<meta name="robots" content="noindex, nofollow">', false);
});
it('defaults to noindex outside production', function () {
// Gegenprobe zur Konfiguration selbst: ohne expliziten Schalter entscheidet APP_ENV.
expect((bool) (env('SITE_INDEXABLE', env('APP_ENV', 'production') === 'production')))->toBeFalse();
});