Backend-WIP: Kontakt-Queue, Page-Cache, Validierungs-Feedback, i18n

Gebuendelt, da ueber gemeinsame lang-/Service-Dateien verschraenkt:
- Kontakt-Nachrichten: contact_messages-Tabelle + Model/Enums/Factory,
  Admin-Queue (livewire/admin/contact-messages), ContactController
  persistiert das Anliegen zusaetzlich zur Brand-Mail
- Page-Data-Cache (Services/Web/*PageData) + web-archive-Indizes auf
  press_releases
- Validierungs-Feedback + Company-Portal-Restriction (Feature-Tests)
- i18n-Auslagerung lang/de|en (auth, passwords, validation, static)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-09 15:38:11 +00:00
parent c6b5ec8479
commit fd8e050cb7
60 changed files with 3963 additions and 327 deletions

View file

@ -1,6 +1,7 @@
<?php
use App\Enums\Portal;
use App\Enums\PressReleasePlaceholder;
use App\Enums\PressReleaseStatus;
use App\Models\Category;
use App\Models\Company;
@ -80,15 +81,20 @@ test('the ad-hoc ticker also renders on subpages', function () {
'published_at' => now()->subHour(),
]);
// Ticker-Meldungen sind anklickbar und führen zur Detailseite. Der Host der
// generierten URL stammt in Tests aus APP_URL (ThemeServiceProvider bootet
// vor dem Test-Request), daher wird nur der Pfad geprüft.
$this->get('https://businessportal24.test/de/newsrooms')
->assertSuccessful()
->assertSeeText('AD-HOC')
->assertSeeText('Ticker-Meldung auf Unterseite');
->assertSeeText('Ticker-Meldung auf Unterseite')
->assertSee('/de/press-release/ticker-meldung-auf-unterseite', false);
$this->get('https://businessportal24.test/de/preise')
->assertSuccessful()
->assertSeeText('AD-HOC')
->assertSeeText('Ticker-Meldung auf Unterseite');
->assertSeeText('Ticker-Meldung auf Unterseite')
->assertSee('/de/press-release/ticker-meldung-auf-unterseite', false);
});
test('businessportal24 homepage hides data sections and shows the empty feed state without content', function () {
@ -170,6 +176,38 @@ test('businessportal24 homepage feed only shows published businessportal content
->assertDontSeeText('Entwurf nicht sichtbar');
});
test('businessportal24 homepage renders the chosen placeholder for image-less releases', function () {
/** @var TestCase $this */
$category = Category::factory()->create([
'portal' => Portal::Businessportal24,
]);
$category->translations()->create([
'locale' => 'de',
'name' => 'Energie & Klima',
'slug' => 'energie-klima',
]);
$company = Company::factory()->businessportal24()->create([
'name' => 'Muster Energie GmbH',
]);
PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for($company)
->create([
'title' => 'Meldung mit gewähltem Platzhalter',
'slug' => 'meldung-mit-gewaehltem-platzhalter',
'placeholder_variant' => PressReleasePlaceholder::DotsAmber,
'published_at' => now()->subHour(),
]);
$this->get('https://businessportal24.test/de')
->assertSuccessful()
->assertSee('images/press-release-placeholders/09-dots-amber.svg', false);
});
test('businessportal24 homepage shows most read releases in the sidebar', function () {
/** @var TestCase $this */
$category = Category::factory()->create([

View file

@ -1,13 +1,15 @@
<?php
use App\Enums\ContactMessageTopic;
use App\Mail\ContactRequestSubmitted;
use App\Models\ContactMessage;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
test('the hub landing renders the contact modal form', function () {
/** @var TestCase $this */
// Die frühere Kontakt-Seite wurde zurückgebaut; das Formular lebt im
// Kontakt-Modal des Hubs und postet weiter auf kontakt.store.
// schwebenden Kontakt-Widget und postet weiter auf kontakt.store.
$this->get('https://pressekonto.test/')
->assertSuccessful()
->assertSee('name="name"', false)
@ -16,6 +18,45 @@ test('the hub landing renders the contact modal form', function () {
->assertSee('Nachricht senden');
});
test('the spoke pages render the floating contact launcher', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/faq')
->assertSuccessful()
->assertSee('open-contact-modal', false)
->assertSee(route('kontakt.store', ['edition' => 'de']), false)
->assertSee('Fehler melden')
->assertSee('Pressemitteilung melden');
});
test('the english edition renders the launcher with english strings', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/en/suche')
->assertSuccessful()
->assertSee('Report a bug')
->assertSee('Report a press release')
->assertSee('Send message')
->assertDontSee('Fehler melden');
});
test('a submission on the english edition flashes an english confirmation', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://businessportal24.test/en/kontakt', [
'name' => 'Paula Press',
'email' => 'paula@example.test',
'message' => 'I have a question about your platform, please get back to me.',
])->assertSessionHas('contact-status', __('web.launcher.success', [], 'en'));
});
test('the login page renders the floating contact launcher', function () {
/** @var TestCase $this */
$this->get('https://pressekonto.test/login')
->assertSuccessful()
->assertSee('open-contact-modal', false)
->assertSee(route('kontakt.store', ['edition' => 'de']), false);
});
test('a valid contact request sends a mail to the configured recipient', function () {
/** @var TestCase $this */
Mail::fake();
@ -66,6 +107,64 @@ test('a contact request from the hub domain goes to the pressekonto brand addres
Mail::assertSent(ContactRequestSubmitted::class, fn (ContactRequestSubmitted $mail) => $mail->hasTo('kontakt@pressekonto.de'));
});
test('a contact request is stored in the contact queue', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://businessportal24.test/de/kontakt', [
'name' => 'Paula Presse',
'email' => 'paula@example.test',
'message' => 'Ich habe eine Frage zu Ihrer Plattform und bitte um Rückruf.',
])->assertSessionHas('contact-status');
$message = ContactMessage::query()->sole();
expect($message->topic)->toBe(ContactMessageTopic::Contact)
->and($message->portal)->toBe('businessportal24')
->and($message->name)->toBe('Paula Presse')
->and($message->email)->toBe('paula@example.test')
->and($message->status->isOpen())->toBeTrue();
});
test('a widget submission stores topic and page url', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://presseecho.test/de/kontakt', [
'name' => 'Bernd Bug',
'email' => 'bernd@example.test',
'message' => 'Die Suche liefert auf der Startseite einen Fehler 500.',
'topic' => 'bug_report',
'page_url' => 'https://presseecho.test/de/suche',
])->assertSessionHas('contact-status');
$message = ContactMessage::query()->sole();
expect($message->topic)->toBe(ContactMessageTopic::BugReport)
->and($message->portal)->toBe('presseecho')
->and($message->page_url)->toBe('https://presseecho.test/de/suche');
Mail::assertSent(ContactRequestSubmitted::class, function (ContactRequestSubmitted $mail) {
return $mail->topicLabel === 'Fehlermeldung'
&& $mail->pageUrl === 'https://presseecho.test/de/suche';
});
});
test('an unknown topic is rejected', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://businessportal24.test/de/kontakt', [
'name' => 'Paula Presse',
'email' => 'paula@example.test',
'message' => 'Ich habe eine Frage zu Ihrer Plattform und bitte um Rückruf.',
'topic' => 'not-a-topic',
])->assertSessionHasErrors(['topic']);
expect(ContactMessage::query()->count())->toBe(0);
Mail::assertNothingSent();
});
test('honeypot submissions are silently accepted without sending mail', function () {
/** @var TestCase $this */
Mail::fake();
@ -78,6 +177,7 @@ test('honeypot submissions are silently accepted without sending mail', function
])->assertSessionHas('contact-status');
Mail::assertNothingSent();
expect(ContactMessage::query()->count())->toBe(0);
});
test('the contact form validates its inputs', function () {

View file

@ -1,5 +1,7 @@
<?php
use App\Enums\Portal;
use App\Models\Category;
use Tests\TestCase;
test('header and footer link to faq, hilfe and legal pages and drop dead links', function () {
@ -15,8 +17,10 @@ test('header and footer link to faq, hilfe and legal pages and drop dead links',
->assertSee('/de/richtlinien', false)
->assertSee('/de/melden', false)
->assertDontSee('/de/cookies', false)
// „Anmelden" führt jetzt in den Hub statt auf einen toten Anker.
// „Anmelden" öffnet ein Modal, das Pressekonto erklärt und in den Hub verlinkt.
->assertSee('/login', false)
->assertSeeText(__('web.header.login_modal_title'))
->assertSeeText(__('web.header.login_modal_hub'))
->assertDontSee('href="#newsletter"', false)
->assertDontSee('href="#rss"', false)
->assertDontSee('href="#anmelden"', false)
@ -24,3 +28,26 @@ test('header and footer link to faq, hilfe and legal pages and drop dead links',
->assertDontSee('Mediendaten')
->assertDontSee('Verifizierter Newsroom');
});
test('categories beyond the top nine appear in the header more dropdown', function () {
/** @var TestCase $this */
// 12 Top-Level-Rubriken: die Top 9 erscheinen als Tabs, der Rest im
// „Mehr“-Dropdown (Desktop) bzw. in der Mobile-Liste — keine Rubrik
// fällt mehr komplett aus der Navigation.
$categories = Category::factory()
->count(12)
->state(['portal' => Portal::Both->value])
->withTranslations()
->create();
$response = $this->get('https://businessportal24.test/de');
$response->assertSuccessful()
->assertSeeText(__('web.nav.more'));
foreach ($categories as $category) {
$translation = $category->translations()->where('locale', 'de')->first();
$response->assertSeeText($translation->name);
}
});

View file

@ -0,0 +1,160 @@
<?php
use App\Enums\Portal;
use App\Models\Category;
use App\Models\Company;
use App\Models\PressRelease;
use Illuminate\Support\Facades\Cache;
use Livewire\Volt\Volt as LivewireVolt;
use Tests\TestCase;
function makeCategoryWithSlug(Portal $portal, string $name, string $slug, ?int $parentId = null): Category
{
$category = Category::factory()->create(['portal' => $portal, 'parent_id' => $parentId]);
$category->translations()->create([
'locale' => 'de',
'name' => $name,
'slug' => $slug,
]);
return $category;
}
test('homepage data is cached per portal and language', function () {
/** @var TestCase $this */
$category = makeCategoryWithSlug(Portal::Presseecho, 'Energie & Klima', 'energie-klima');
$company = Company::factory()->presseecho()->create();
PressRelease::factory()
->published()
->forPortal(Portal::Presseecho)
->for($category)
->for($company)
->create([
'title' => 'Erste Meldung im Cache',
'slug' => 'erste-meldung-im-cache',
'published_at' => now()->subHour(),
]);
$this->get('https://presseecho.test/de')
->assertSuccessful()
->assertSeeText('Erste Meldung im Cache');
expect(Cache::has('web.home.presseecho.de'))->toBeTrue();
PressRelease::factory()
->published()
->forPortal(Portal::Presseecho)
->for($category)
->for($company)
->create([
'title' => 'Neue Meldung nach Cache-Aufbau',
'slug' => 'neue-meldung-nach-cache-aufbau',
'published_at' => now()->subMinutes(5),
]);
// Innerhalb der TTL liefert HomePageData den gecachten Stand: Lead bleibt
// die alte Meldung. (Der Livewire-Feed ist bewusst ungecacht und zeigt
// neue Meldungen sofort.)
$cachedLead = $this->get('https://presseecho.test/de')
->assertSuccessful()
->viewData('leadRelease');
expect($cachedLead->title)->toBe('Erste Meldung im Cache');
Cache::flush();
$freshLead = $this->get('https://presseecho.test/de')
->assertSuccessful()
->viewData('leadRelease');
expect($freshLead->title)->toBe('Neue Meldung nach Cache-Aufbau');
});
test('category page data is cached per portal, language and slug but 404s are not cached', function () {
/** @var TestCase $this */
$category = makeCategoryWithSlug(Portal::Businessportal24, 'Mobilität', 'mobilitaet');
PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for(Company::factory()->businessportal24())
->create([
'slug' => 'mobilitaets-meldung',
'published_at' => now()->subDay(),
]);
$this->get('https://businessportal24.test/de/category/mobilitaet')->assertSuccessful();
expect(Cache::has('web.category.businessportal24.de.mobilitaet'))->toBeTrue();
$this->get('https://businessportal24.test/de/category/gibt-es-nicht')->assertNotFound();
expect(Cache::has('web.category.businessportal24.de.gibt-es-nicht'))->toBeFalse();
});
test('subcategory counts are aggregated correctly in a single grouped query', function () {
/** @var TestCase $this */
$parent = makeCategoryWithSlug(Portal::Both, 'Wirtschaft', 'wirtschaft');
$child = makeCategoryWithSlug(Portal::Both, 'Handel', 'handel', $parent->id);
$company = Company::factory()->businessportal24()->create();
// Stichtag (referenceNow) = jüngste Meldung: 2 im 7-Tage-Fenster, 1 älter (>14 Tage).
foreach ([1, 2, 20] as $daysAgo) {
PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($child)
->for($company)
->create([
'slug' => "handel-meldung-{$daysAgo}",
'published_at' => now()->subDays($daysAgo),
]);
}
$response = $this->get('https://businessportal24.test/de/category/wirtschaft')->assertSuccessful();
$subCategories = $response->viewData('subCategories');
expect($subCategories)->toHaveCount(1)
->and($subCategories[0]['name'])->toBe('Handel')
->and($subCategories[0]['total'])->toBe(3)
->and($subCategories[0]['recent'])->toBe(2)
->and($subCategories[0]['delta'])->toBe(2);
});
test('the press release feed today filter matches the reference day via range comparison', function () {
/** @var TestCase $this */
$category = makeCategoryWithSlug(Portal::Presseecho, 'Technologie', 'technologie');
$company = Company::factory()->presseecho()->create();
// Historisches Archiv: Stichtag = jüngste Meldung (vor 10 Tagen).
PressRelease::factory()
->published()
->forPortal(Portal::Presseecho)
->for($category)
->for($company)
->create([
'title' => 'Meldung am Stichtag',
'slug' => 'meldung-am-stichtag',
'published_at' => now()->subDays(10)->setTime(9, 0),
]);
PressRelease::factory()
->published()
->forPortal(Portal::Presseecho)
->for($category)
->for($company)
->create([
'title' => 'Meldung vom Vortag',
'slug' => 'meldung-vom-vortag',
'published_at' => now()->subDays(11)->setTime(9, 0),
]);
LivewireVolt::test('web.press-release-feed', ['portal' => Portal::Presseecho->value, 'language' => 'de'])
->call('setTimeframe', 'today')
->assertSee('Meldung am Stichtag')
->assertDontSee('Meldung vom Vortag');
});

View file

@ -101,6 +101,25 @@ test('the hub page speaks of Pruefung without the redaktionell qualifier', funct
->assertSeeText('Prüfung inklusive');
});
test('the hub links faq and help center in header and footer', function () {
/** @var TestCase $this */
$this->seed(PlanSeeder::class);
$response = $this->get('https://pressekonto.test/')->assertSuccessful();
$content = $response->getContent();
// FAQ + Hilfe sind in der Top-Utility-Bar (neben Kontakt) und im
// Footer unter „Plattform" verlinkt.
expect($content)
->toContain('/de/faq')
->toContain('/de/hilfe')
->toContain('Hilfe-Center');
// Beide Ziele sind auf der Hub-Domain erreichbar.
$this->get('https://pressekonto.test/de/faq')->assertSuccessful();
$this->get('https://pressekonto.test/de/hilfe')->assertSuccessful();
});
test('legal pages are reachable on the hub domain', function () {
/** @var TestCase $this */
$this->get('https://pressekonto.test/de/impressum')->assertSuccessful();

View file

@ -2,6 +2,7 @@
use App\Enums\CompanyType;
use App\Enums\Portal;
use App\Enums\PressReleasePlaceholder;
use App\Enums\PressReleaseStatus;
use App\Models\Category;
use App\Models\Company;
@ -71,7 +72,58 @@ test('businessportal24 release detail renders the editorial shell with real data
->assertSeeText('Annika Werthmann')
->assertSeeText('Dekarbonisierung der Schwerindustrie')
->assertSeeText('Über das Unternehmen')
->assertSeeText('Wasserstoff');
->assertSeeText('Wasserstoff')
// Magic-Link-Hinweis: hinterlegte Kontakte verwalten die PM im pressekonto.
->assertSeeText('Sie sind als Firma oder Pressekontakt dieser Mitteilung hinterlegt?')
->assertSee(rtrim(config('domains.domain_portal_url'), '/').'/anmeldelink', false);
});
test('release detail without image embeds the headline in the generated hero', function () {
/** @var TestCase $this */
[$category, $company] = detailCategoryAndCompany(Portal::Businessportal24);
$release = PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for($company)
->create([
'title' => 'Meldung ohne Pressefoto',
'slug' => 'meldung-ohne-pressefoto',
'placeholder_variant' => PressReleasePlaceholder::LinesGreen,
]);
$this->get('https://businessportal24.test/de/press-release/'.$release->slug)
->assertSuccessful()
->assertSeeText('Meldung ohne Pressefoto')
->assertSee('bg-hero-grad', false)
// Es muss dieselbe Platzhalter-Variante wie im User-Panel erscheinen.
->assertSee('images/press-release-placeholders/05-lines-green.svg', false)
->assertDontSee('Bild · Pressefoto');
});
test('release detail without chosen placeholder falls back to the generic hero', function () {
/** @var TestCase $this */
// Altbestand: PMs ohne gesetzte `placeholder_variant` rendern weiterhin
// die generische Hero-Fallback-Grafik statt einer Platzhalter-SVG.
[$category, $company] = detailCategoryAndCompany(Portal::Businessportal24);
$release = PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for($company)
->create([
'title' => 'Altbestand ohne Platzhalter-Variante',
'slug' => 'altbestand-ohne-variante',
]);
PressRelease::withoutGlobalScopes()->whereKey($release->id)->update(['placeholder_variant' => null]);
$this->get('https://businessportal24.test/de/press-release/'.$release->slug)
->assertSuccessful()
->assertSeeText('Altbestand ohne Platzhalter-Variante')
->assertDontSee('images/press-release-placeholders/', false);
});
test('release detail shows prominent report links below the article', function () {
@ -257,5 +309,39 @@ test('release detail shows more from newsroom and related releases', function ()
->assertSeeText('Mehr von Muster Energie GmbH')
->assertSeeText('Weitere Meldung desselben Newsrooms')
->assertSeeText('Verwandte Meldungen')
->assertSeeText('Verwandte Branchenmeldung');
->assertSeeText('Verwandte Branchenmeldung')
->assertSee('grid grid-cols-1 gap-10 md:grid-cols-2', false);
});
test('a single recommendation list spans the full layout width', function () {
/** @var TestCase $this */
[$category, $company] = detailCategoryAndCompany(Portal::Businessportal24);
$main = PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for($company)
->create(['slug' => 'einzelliste-hauptmeldung', 'published_at' => now()->subDay()]);
$otherCompany = Company::factory()->create([
'portal' => Portal::Businessportal24,
'name' => 'Andere Industrie AG',
'is_active' => true,
]);
// Nur verwandte Meldungen (andere Firma, gleiche Rubrik) — kein
// "Mehr von …": die einzelne Liste darf nicht auf halber Breite stehen.
PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for($otherCompany)
->create(['slug' => 'einzelliste-verwandt', 'published_at' => now()->subDays(2)]);
$this->get('https://businessportal24.test/de/press-release/'.$main->slug)
->assertSuccessful()
->assertSeeText('Verwandte Meldungen')
->assertSee('grid grid-cols-1 gap-10"', false)
->assertDontSee('grid grid-cols-1 gap-10 md:grid-cols-2', false);
});

View file

@ -75,6 +75,18 @@ test('the terms render the b2b version with cancellation and archive rules', fun
->assertDontSeeText('Business Portal GmbH');
});
test('the terms state that subscriptions renew for the chosen term instead of switching to monthly billing', function () {
/** @var TestCase $this */
// Jahresabos verlängern sich um jeweils zwölf Monate und sind zum
// Laufzeitende kündbar — kein Wechsel auf monatliche Abrechnung mehr.
$this->get('https://pressekonto.test/de/agb')
->assertSuccessful()
->assertSeeText('verlängert sich jeweils automatisch um die')
->assertSeeText('zum Ende des jeweiligen Zwölfmonats-Zeitraums')
->assertDontSeeText('auf unbestimmte Zeit')
->assertDontSeeText('erfolgt die Abrechnung nach Ablauf der Erstlaufzeit monatlich');
});
test('the guidelines list the rejection categories with anchors', function () {
/** @var TestCase $this */
// Kategorien kommen live aus rejection_categories (E3) — neue Zeilen
@ -108,7 +120,11 @@ test('the reporting page separates free legal paths from the paid takedown servi
->assertSeeText('Ausübung gesetzlicher Rechte')
// Depublikations-Preis (O6, 06.07.: 35 € netto) im Doppelausweis.
->assertSeeText('35,00 € zzgl. USt.')
->assertSeeText('41,65 € inkl. 19');
->assertSeeText('41,65 € inkl. 19')
// Keine Melde-E-Mail-Adresse mehr auf der Seite: alle Wege verweisen
// auf das Kontakt-Widget (Badge unten rechts, wie im Footer).
->assertDontSee('mailto:', false)
->assertSeeText('Kontaktformular');
});
test('the reporting page falls back to the neutral price wording when depublication is disabled', function () {
@ -152,3 +168,76 @@ test('the help center shows quick links and topics', function () {
->assertSee(route('faq'), false)
->assertSee(route('veroeffentlichen'), false);
});
dataset('static pages in english', [
'faq' => ['en/faq', 'Frequently asked questions'],
'hilfe' => ['en/hilfe', 'Help center'],
'api' => ['en/api', 'API documentation'],
'impressum' => ['en/impressum', 'Imprint'],
'melden' => ['en/melden', 'Report content or request changes'],
'kuendigung' => ['en/kuendigung', 'Cancel contracts here'],
]);
test('the translated static pages render in english on the en edition', function (string $path, string $heading) {
/** @var TestCase $this */
$this->get("https://businessportal24.test/{$path}")
->assertSuccessful()
->assertSeeText($heading)
// Kein deutsches Seiten-Gerüst mehr auf der EN-Ausgabe.
->assertDontSeeText('Häufig gestellte Fragen')
->assertDontSeeText('Hilfe-Center');
})->with('static pages in english');
test('the publish page renders in english with an en hreflang alternate', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/en/veroeffentlichen')
->assertSuccessful()
->assertSeeText('Publish a press release.')
->assertSeeText('Four principles that carry this platform')
->assertSee('hreflang="en"', false)
->assertDontSeeText('Pressemitteilung veröffentlichen.');
});
test('the report forms render in english on the en edition', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/en/melden/rechtswidrig')
->assertSuccessful()
->assertSeeText('Report illegal content')
->assertSeeText('Submit report');
$this->get('https://businessportal24.test/en/melden/kontaktdaten')
->assertSuccessful()
->assertSeeText('Have your own contact details removed')
->assertSeeText('Submit request');
});
test('the binding legal texts stay german but show an english language notice on the en edition', function () {
/** @var TestCase $this */
// AGB/Datenschutz/Richtlinien bleiben deutsch (O-C: EN-Fassungen erst
// nach fachanwaltlicher Prüfung) — die EN-Ausgabe erklärt das sichtbar.
$this->get('https://businessportal24.test/en/agb')
->assertSuccessful()
->assertSeeText('The German version is authoritative and legally binding.')
->assertSeeText('Allgemeine Geschäftsbedingungen');
$this->get('https://businessportal24.test/en/datenschutz')
->assertSuccessful()
->assertSeeText('The German version is authoritative and legally binding.');
// Auf der deutschen Ausgabe erscheint kein Hinweis.
$this->get('https://businessportal24.test/de/agb')
->assertSuccessful()
->assertDontSeeText('The German version is authoritative and legally binding.');
});
test('german validation messages are used on the de edition forms', function () {
/** @var TestCase $this */
$response = $this->from('https://businessportal24.test/de/melden/rechtswidrig')
->post('https://businessportal24.test/de/melden/rechtswidrig', []);
$response->assertSessionHasErrors(['reported_url', 'requester_name', 'requester_email', 'message']);
$messages = collect(session('errors')->all())->implode(' ');
expect($messages)->toContain('muss ausgefüllt werden')
->not->toContain('field is required');
});