b2in/tests/Feature/BrandTranslationsTest.php
Kevin Adametz 8ddc85422e Englische Fassung der Markenseiten: Merkmale, Leistungen, Abschnitte, Showroom, Bildunterschriften
Diese Markenfelder waren nur einsprachig gespeichert und erschienen auf der englischen Seite
deutsch. Neue Spalte cms_brands.field_translations (additiv) trägt die Übersetzungen je Sprache,
die bisherigen Spalten bleiben die deutsche Fassung; ohne Übersetzung gilt weiter Deutsch.
Marken-Editor bearbeitet die Felder über den DE/EN-Umschalter (Bilder und Rubriken bleiben
sprachübergreifend). BrandTranslationsSeeder spielt die englischen Texte der vier Kernmarken
ein, ohne gepflegte Übersetzungen zu überschreiben. php artisan cms:untranslated listet
Inhalte, die in einer Sprache noch fehlen oder deutsch sind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:08:03 +00:00

116 lines
5 KiB
PHP

<?php
use App\Models\CmsBrand;
use App\Models\User;
use Database\Seeders\BrandImageSeeder;
use Database\Seeders\BrandPageTextSeeder;
use Database\Seeders\BrandTranslationsSeeder;
use Database\Seeders\CmsBrandSeeder;
use Database\Seeders\ContentCorrections20261008Seeder;
use Database\Seeders\DemoBrandGalleryCleanupSeeder;
use Database\Seeders\OtterpohlBrandSeeder;
use Livewire\Volt\Volt;
/**
* Englische Fassung der bisher einsprachigen Markenfelder (09.10.2026).
*/
function brandWithGallery(): CmsBrand
{
return CmsBrand::factory()->create([
'slug' => 'muster',
'highlights' => ['Millimetergenaue Planung'],
'services' => [['title' => 'Aufmaß vor Ort', 'description' => 'Bei Ihnen zu Hause.']],
'showroom' => 'Showroom Bielefeld',
'gallery' => [
['image' => 'a.webp', 'category' => 'inspiration', 'caption' => 'Schrank in Eiche'],
['image' => 'b.webp', 'category' => 'project', 'caption' => 'Küche mit Insel'],
],
]);
}
it('falls back to german and uses the english version where one exists', function () {
$brand = brandWithGallery();
$brand->setLocalized('highlights', 'en', ['Planned to the millimetre']);
$brand->setLocalized('gallery_captions', 'en', ['a.webp' => 'Wardrobe in oak']);
$brand->save();
expect($brand->localized('highlights', 'en'))->toBe(['Planned to the millimetre'])
->and($brand->localized('highlights', 'de'))->toBe(['Millimetergenaue Planung'])
->and($brand->localized('services', 'en'))->toBe($brand->services)
->and(array_column($brand->localizedGallery('en'), 'caption'))->toBe(['Wardrobe in oak', 'Küche mit Insel']);
});
it('does not store a translation that is just the german text', function () {
$brand = brandWithGallery();
$brand->setLocalized('showroom', 'en', 'Showroom Bielefeld');
$brand->setLocalized('highlights', 'en', ['Millimetergenaue Planung']);
$brand->save();
expect($brand->fresh()->field_translations)->toBeNull();
});
it('edits the english fields in the brand editor without touching the german ones', function () {
$this->actingAs(User::factory()->create());
$brand = brandWithGallery();
Volt::test('admin.cms.brands-index')
->call('openEdit', $brand->id)
->call('switchLocale', 'en')
->assertSet('highlights', ['Millimetergenaue Planung'])
->set('highlights', ['Planned to the millimetre'])
->set('services', [['title' => 'Measuring on site', 'description' => 'At your home.']])
->set('gallery.1.caption', 'Kitchen with island')
->set('brandName', 'Muster')
->call('save');
$brand->refresh();
expect($brand->highlights)->toBe(['Millimetergenaue Planung'])
->and($brand->gallery[1]['caption'])->toBe('Küche mit Insel')
->and($brand->localized('highlights', 'en'))->toBe(['Planned to the millimetre'])
->and($brand->localized('services', 'en')[0]['title'])->toBe('Measuring on site')
->and(array_column($brand->localizedGallery('en'), 'caption'))->toBe(['Schrank in Eiche', 'Kitchen with island']);
});
it('translates every german brand text of the four core brands and keeps maintained translations', function () {
foreach ([CmsBrandSeeder::class, BrandPageTextSeeder::class, OtterpohlBrandSeeder::class, BrandImageSeeder::class, DemoBrandGalleryCleanupSeeder::class, ContentCorrections20261008Seeder::class] as $seeder) {
$this->seed($seeder);
}
$cabinet = CmsBrand::query()->where('slug', 'cabinet')->first();
$cabinet->setLocalized('showroom', 'en', 'Our own showroom');
$cabinet->save();
$this->seed(BrandTranslationsSeeder::class);
$this->seed(BrandTranslationsSeeder::class);
foreach (CmsBrand::query()->get() as $brand) {
foreach (['highlights', 'services', 'sections'] as $field) {
$german = $brand->localized($field, 'de');
$english = $brand->localized($field, 'en');
expect($english)->not->toBe($german, "{$brand->slug}.{$field}")
->and(count($english ?? []))->toBe(count($german ?? []), "{$brand->slug}.{$field}");
}
}
expect($cabinet->fresh()->localized('showroom', 'en'))->toBe('Our own showroom');
$this->artisan('cms:untranslated')->expectsOutputToContain('Keine deutschen')->assertSuccessful();
});
it('shows the english brand texts on the english website and the german ones on the german', function () {
foreach ([CmsBrandSeeder::class, BrandPageTextSeeder::class, BrandTranslationsSeeder::class] as $seeder) {
$this->seed($seeder);
}
$this->withSession(['locale' => 'en'])->get('/marken/cabinet')->assertSuccessful()
->assertSee('Millimetres, not standard sizes')
->assertDontSee('Millimeter statt Standardmaß');
$this->withSession(['locale' => 'en'])->get('/marken')->assertSuccessful()
->assertSee('Planned to the millimetre');
$this->withSession(['locale' => 'de'])->get('/marken/cabinet')->assertSuccessful()
->assertSee('Millimeter statt Standardmaß');
});