- Hinweisleiste per B2IN_ANNOUNCEMENT_BAR ausgeblendet (Standard aus) - Hero: „Räume aus einer Hand.“ als neue Überschrift, zweiter Button entfernt - Projekttext mit zentralem deutschen Vertragspartner (Punkt statt Gedankenstrich) - Otterpohl als vierte Kernmarke: Text v2, Abschnitt „Montage“, Titelbild getauscht - Markenabschnitte: Absätze mit „- “ als Liste mit fetter Einleitung - Titelbilder und Galerien für CABINET, Rotpunkt, Febrü und Otterpohl (WebP) - Feedback 17.09. in den Markentexten, Demobilder entfernt, WhatsApp-Nummer - Palette „Modern“ fest ohne Schalter, Entwurf /entwurf mit Hero-Slideshow - Seeder-Liste fürs Deployment im Entwicklungsplan Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
87 lines
3.5 KiB
PHP
87 lines
3.5 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
use Illuminate\Support\Facades\Blade;
|
||
|
||
uses(RefreshDatabase::class);
|
||
|
||
// ========================================
|
||
// <x-appointment-link>: Kontakt-Links oeffnen das Widget
|
||
// ========================================
|
||
|
||
it('marks links to the contact pages as widget triggers', function (string $href) {
|
||
$html = Blade::render('<x-appointment-link :href="$href" class="btn">Termin</x-appointment-link>', ['href' => $href]);
|
||
|
||
expect($html)->toContain('data-open-appointment')
|
||
->toContain('href="'.$href.'"')
|
||
->toContain('class="btn"');
|
||
})->with([
|
||
'interior' => '/contact',
|
||
'immobilien' => '/immobilien/kontakt',
|
||
'absolute' => 'https://b2in.test/contact',
|
||
]);
|
||
|
||
it('leaves links to other pages as plain links', function () {
|
||
$html = Blade::render('<x-appointment-link href="/marken" class="btn">Marken</x-appointment-link>');
|
||
|
||
expect($html)->not->toContain('data-open-appointment')
|
||
->toContain('href="/marken"');
|
||
});
|
||
|
||
it('hands over the topic that should be preselected', function () {
|
||
$html = Blade::render('<x-appointment-link href="/contact" topic="cabinet">Termin</x-appointment-link>');
|
||
|
||
expect($html)->toContain('data-appointment-topic="cabinet"');
|
||
});
|
||
|
||
// ========================================
|
||
// Sektionen auf der Seite
|
||
// ========================================
|
||
|
||
it('opens the widget from the appointment buttons of the homepage', function () {
|
||
$html = $this->get('/')->assertSuccessful()->getContent();
|
||
|
||
// Weiche (beide Karten) und Abschluss-CTA – der zweite Hero-Button entfällt seit 01.10.2026.
|
||
expect(substr_count($html, 'data-open-appointment'))->toBeGreaterThanOrEqual(3);
|
||
});
|
||
|
||
it('preselects the brand when the widget is opened from a brand page', function () {
|
||
$html = $this->get('/marken/cabinet')->assertSuccessful()->getContent();
|
||
|
||
expect($html)->toContain('data-appointment-topic="cabinet"');
|
||
});
|
||
|
||
it('opens the widget from the real estate calls to action too', function () {
|
||
$html = $this->get('/immobilien')->assertSuccessful()->getContent();
|
||
|
||
expect($html)->toContain('data-open-appointment');
|
||
});
|
||
|
||
it('keeps the contact button in the header as a link to the contact page', function () {
|
||
$html = $this->get('/')->assertSuccessful()->getContent();
|
||
$header = substr($html, (int) strpos($html, '<header'), (int) strpos($html, '</header>') - (int) strpos($html, '<header'));
|
||
|
||
expect($header)->toContain('href="'.route('contact').'"')
|
||
->not->toContain('data-open-appointment');
|
||
});
|
||
|
||
it('listens for the open event in the widget and intercepts the links in the frontend script', function () {
|
||
expect($this->get('/')->assertSuccessful()->getContent())->toContain('open-appointment.window');
|
||
expect(file_get_contents(resource_path('js/app.js')))->toContain('a[data-open-appointment]')
|
||
->toContain("new CustomEvent('open-appointment'");
|
||
});
|
||
|
||
// ========================================
|
||
// Formularfelder
|
||
// ========================================
|
||
|
||
it('styles the selects of the widget and the contact page with the shared field classes', function () {
|
||
expect($this->get('/')->assertSuccessful()->getContent())->toMatch('/<select[^>]*id="appointment-topic"[^>]*class="form-field form-select"/');
|
||
expect($this->get('/contact')->assertSuccessful()->getContent())->toMatch('/<select[^>]*id="subject"[^>]*class="form-field form-select"/');
|
||
|
||
$css = file_get_contents(resource_path('css/web/shared-styles.css'));
|
||
|
||
expect($css)->toContain('.form-field')->toContain('.form-select');
|
||
});
|