b2in/tests/Feature/BrandPageTest.php
Kevin Adametz 3958a1fe89 Markenlogos auf ihren Inhalt beschneiden
CABINET und Rotpunkt wirkten neben Februe zu klein. Ursache war nicht die Box,
sondern leerer Rand in den Dateien: CABINET nutzte nur 29 Prozent der Hoehe
seiner Zeichenflaeche, Rotpunkt 70 Prozent. CABINET ist ein 4:1-Schriftzug in
einer fast quadratischen Flaeche – im Seitenkopf blieben davon rund 28 px
sichtbare Hoehe.

Bei beiden SVGs auf die Tuschekante beschnitten (viewBox auf den Inhalt
gesetzt, plus 1 Prozent Luft; die Pfade selbst unveraendert). Beide nutzen ihre
Flaeche jetzt zu 98 Prozent. Im Seitenkopf ist CABINET damit rund zweieinhalb-
mal so gross wie vorher, Rotpunkt gut anderthalbmal und auf derselben Hoehe
wie Februe.

Die Boxgroessen im Frontend bleiben unveraendert – Februe sass bereits richtig,
eine groessere Box haette Februe mitvergroessert.

Ein Test haelt fest, dass unter public/ die beschnittenen Fassungen liegen und
nicht die Zulieferungen.

Tests: 873 gruen (3217 Assertions), Pint sauber.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 11:33:12 +00:00

286 lines
10 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\CmsBrand;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
beforeEach(function () {
$this->seed(\Database\Seeders\CmsBrandSeeder::class);
});
// ========================================
// Kacheln auf der Startseite
// ========================================
it('shows the maintained brands on the homepage', function () {
$this->get('/')
->assertSuccessful()
->assertSee('CABINET')
->assertSee('Rotpunkt Küchen', false)
->assertSee('Febrü', false);
});
it('links each tile to its detail page', function () {
$this->get('/')
->assertSuccessful()
->assertSee('/marken/cabinet')
->assertSee('/marken/rotpunkt')
->assertSee('/marken/februe');
});
it('hides unpublished brands from the homepage', function () {
CmsBrand::where('slug', 'februe')->update(['is_published' => false]);
$this->get('/')
->assertSuccessful()
->assertSee('CABINET')
->assertDontSee('/marken/februe');
});
// ========================================
// Detailseite
// ========================================
it('serves a detail page for every brand', function () {
foreach (['cabinet', 'rotpunkt', 'februe'] as $slug) {
$this->get('/marken/'.$slug)->assertSuccessful();
}
});
it('renders the template sections from the concept', function () {
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('CABINET') // Header
->assertSee('Einbauschränke nach Maß', false) // Claim
->assertSee('Showroom Bielefeld')
->assertSee('Leistungen und Besonderheiten') // Leistungen
->assertSee('Aufmaß vor Ort', false)
->assertSee('Termin anfragen'); // CTA
});
it('links to the other brands from a detail page', function () {
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('/marken/rotpunkt')
->assertSee('/marken/februe');
});
it('returns 404 for an unknown brand', function () {
$this->get('/marken/gibt-es-nicht')->assertNotFound();
});
it('returns 404 for an unpublished brand', function () {
CmsBrand::where('slug', 'februe')->update(['is_published' => false]);
$this->get('/marken/februe')->assertNotFound();
});
it('carries a brand specific title and description', function () {
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('CABINET – Einbauschränke nach Maß. | B2in Interior', false)
->assertDontSee('Connecting Design and Property');
});
// ========================================
// CMS-Anbindung
// ========================================
it('renders what is maintained in the CMS', function () {
$cabinet = CmsBrand::where('slug', 'cabinet')->firstOrFail();
$cabinet->setTranslation('tagline', 'de', 'Im CMS geänderter Claim');
$cabinet->save();
$this->get('/')->assertSuccessful()->assertSee('Im CMS geänderter Claim');
$this->get('/marken/cabinet')->assertSuccessful()->assertSee('Im CMS geänderter Claim');
});
it('picks up a brand that was added in the CMS, without a code change', function () {
CmsBrand::factory()->create([
'slug' => 'neue-marke',
'name' => ['de' => 'Neue Marke', 'en' => 'New Brand'],
'order' => 9,
]);
$this->get('/')->assertSuccessful()->assertSee('Neue Marke');
$this->get('/marken/neue-marke')->assertSuccessful()->assertSee('Neue Marke');
});
// ========================================
// Galerie: realisierte Projekte vs. Inspirationen
// ========================================
it('shows no gallery section while no images are maintained', function () {
$this->get('/marken/cabinet')
->assertSuccessful()
->assertDontSee('Referenzen und Inspirationen');
});
it('shows both groups with their own labels', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update([
'gallery' => [
['image' => 'projekt.webp', 'category' => 'project', 'caption' => 'Ankleide in Bielefeld'],
['image' => 'entwurf.webp', 'category' => 'inspiration', 'caption' => 'Entwurf Garderobe'],
],
]);
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('Referenzen und Inspirationen')
->assertSee('Realisierte Projekte')
->assertSee('Inspirationen und Entwürfe', false)
->assertSee('Realisiertes Projekt')
->assertSee('Visualisierung')
->assertSee('Ankleide in Bielefeld')
->assertSee('Entwurf Garderobe');
});
it('does not offer a tab switch when only one group is filled', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update([
'gallery' => [
['image' => 'projekt.webp', 'category' => 'project', 'caption' => 'Nur ein Projekt'],
],
]);
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('Realisierte Projekte')
->assertDontSee('Inspirationen und Entwürfe', false);
});
it('marks an image without a category as visualisation, never as a completed project', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update([
'gallery' => [
['image' => 'ohne-kategorie.webp'],
],
]);
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('Visualisierung')
->assertDontSee('Realisiertes Projekt');
});
it('still separates inspirations from completed projects after the rewording', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update([
'gallery' => [
['image' => 'entwurf.webp', 'category' => 'inspiration'],
],
]);
$this->get('/marken/cabinet')
->assertSuccessful()
->assertSee('Entwürfe und Visualisierungen', false)
->assertSee('Visualisierung')
->assertDontSee('Realisiertes Projekt');
});
it('fills the demo galleries with both categories', function () {
$this->seed(\Database\Seeders\DemoBrandGallerySeeder::class);
$grouped = CmsBrand::groupGallery(CmsBrand::where('slug', 'cabinet')->firstOrFail()->gallery);
expect($grouped['projects'])->not->toBeEmpty()
->and($grouped['inspirations'])->not->toBeEmpty();
// Der Vermerk „BEISPIEL“ ist auf Kundenwunsch entfallen. Die Unterscheidung muss deshalb
// an der Kategorie haengen – jedes Demobild braucht eine ausdrueckliche.
foreach (CmsBrand::all() as $brand) {
foreach ($brand->gallery ?? [] as $item) {
expect($item['caption'])->not->toContain('BEISPIEL')
->and($item['category'])->toBeIn(CmsBrand::GALLERY_CATEGORIES);
}
}
});
it('strips the old example prefix without touching image, category or order', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update([
'gallery' => [
['image' => 'a.webp', 'category' => 'project', 'caption' => 'BEISPIEL – Ankleide, Bielefeld'],
['image' => 'b.webp', 'category' => 'inspiration', 'caption' => 'Entwurf Garderobe'],
],
]);
$this->seed(\Database\Seeders\BrandGalleryCaptionNormalizerSeeder::class);
$gallery = CmsBrand::where('slug', 'cabinet')->firstOrFail()->gallery;
expect($gallery)->toHaveCount(2)
->and($gallery[0]['caption'])->toBe('Ankleide, Bielefeld')
->and($gallery[0]['image'])->toBe('a.webp')
->and($gallery[0]['category'])->toBe('project')
->and($gallery[1]['caption'])->toBe('Entwurf Garderobe');
});
// ========================================
// Markenlogos
// ========================================
it('shows the logo instead of the wordmark at the top of a brand page', function () {
$html = $this->get('/marken/rotpunkt')->assertSuccessful()->getContent();
// Das Logo sitzt im <h1>, damit die Ueberschrift erhalten bleibt.
expect($html)->toMatch('/<h1>\s*<img[^>]*marken\/rotpunkt\.svg/')
->and($html)->toContain('alt="Rotpunkt Küchen"');
});
it('falls back to the wordmark for a brand without a logo', function () {
CmsBrand::where('slug', 'rotpunkt')->firstOrFail()->update(['logo' => '']);
$this->get('/marken/rotpunkt')
->assertSuccessful()
->assertSee('<h1 class="text-section-title">Rotpunkt Küchen</h1>', false);
});
it('shows the logo on every tile that leads to a brand page', function (string $path) {
$html = $this->get($path)->assertSuccessful()->getContent();
foreach (['cabinet.svg', 'rotpunkt.svg', 'februe.png'] as $file) {
expect($html)->toContain('marken/'.$file);
}
})->with([
'Startseite' => ['/'],
'Markenuebersicht' => ['/marken'],
]);
it('shows the logo on the other-brands tiles of a detail page', function () {
$html = $this->get('/marken/rotpunkt')->assertSuccessful()->getContent();
// Auf der Rotpunkt-Seite verweisen die Kacheln auf CABINET und Februe.
expect($html)->toContain('marken/cabinet.svg')
->and($html)->toContain('marken/februe.png');
});
it('ships the logo files the seeder points at', function () {
foreach (['cabinet.svg', 'rotpunkt.svg', 'februe.png'] as $file) {
expect(public_path('img/assets/marken/'.$file))->toBeFile();
}
});
it('ships the logos cropped to their content, not as delivered', function (string $file) {
// Die Zulieferungen haben viel leeren Rand in der Datei – CABINET nutzte nur 29 Prozent der
// Hoehe. In einer Logo-Box wirkt so ein Logo winzig, egal wie gross die Box ist. Die
// beschnittenen Fassungen erkennt man am Ursprung: der ist nach dem Beschnitt nicht mehr 0 0.
$viewBox = (string) simplexml_load_file(public_path('img/assets/marken/'.$file))['viewBox'];
expect($viewBox)->not->toStartWith('0 0 ');
})->with(['cabinet.svg', 'rotpunkt.svg']);
it('keeps a logo that was uploaded in the admin', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update(['logo' => 'eigenes-logo.svg']);
$this->seed(\Database\Seeders\BrandLogoSeeder::class);
expect(CmsBrand::where('slug', 'cabinet')->firstOrFail()->logo)->toBe('eigenes-logo.svg');
});
it('adds the logo to a brand that has none yet', function () {
CmsBrand::where('slug', 'cabinet')->firstOrFail()->update(['logo' => '']);
$this->seed(\Database\Seeders\BrandLogoSeeder::class);
expect(CmsBrand::where('slug', 'cabinet')->firstOrFail()->logo)->toBe('marken/cabinet.svg');
});