Die Bereiche der FAQ-Seite lagen als verschachtelte Listen in sections, der Editor zeigte davon nur JSON-Text. Jetzt stehen alle Fragen in questions mit dem Feld category, Überschrift und Symbol der Bereiche in categories. FAQ::groups baut daraus die Seite (allgemeine Fragen zuerst), alte Einträge werden weiter dargestellt. FaqCategoriesSeeder stellt gespeicherte Einträge um (FAQ und Immobilien-FAQ), Texte bleiben. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
103 lines
4.8 KiB
PHP
103 lines
4.8 KiB
PHP
<?php
|
||
|
||
use App\Livewire\Web\Components\Sections\FAQ;
|
||
use Database\Seeders\FaqCategoriesSeeder;
|
||
use FluxCms\Core\Models\CmsContent;
|
||
|
||
/**
|
||
* FAQ mit Bereich je Frage statt verschachtelter `sections` (09.10.2026) – so kann der
|
||
* Inhalte-Editor alle Fragen als Liste zeigen.
|
||
*/
|
||
function legacyFaq(): array
|
||
{
|
||
return [
|
||
'title' => 'FAQ',
|
||
'questions' => [['question' => 'Allgemein?', 'answer' => 'A']],
|
||
'sections' => [
|
||
['title' => 'Für Ihr Zuhause', 'icon' => 'home-modern', 'questions' => [['question' => 'Zuhause?', 'answer' => 'B']]],
|
||
['title' => 'Für Projekte', 'icon' => 'briefcase', 'questions' => [['question' => 'Projekt?', 'answer' => 'C']]],
|
||
],
|
||
];
|
||
}
|
||
|
||
it('flattens the nested sections into one list with a category per question', function () {
|
||
expect(FAQ::flatten(legacyFaq()))->toBe([
|
||
'title' => 'FAQ',
|
||
'questions' => [
|
||
['question' => 'Allgemein?', 'answer' => 'A', 'category' => ''],
|
||
['question' => 'Zuhause?', 'answer' => 'B', 'category' => 'Für Ihr Zuhause'],
|
||
['question' => 'Projekt?', 'answer' => 'C', 'category' => 'Für Projekte'],
|
||
],
|
||
'categories' => [
|
||
['title' => 'Für Ihr Zuhause', 'icon' => 'home-modern'],
|
||
['title' => 'Für Projekte', 'icon' => 'briefcase'],
|
||
],
|
||
]);
|
||
});
|
||
|
||
it('groups the questions: general first, then the categories in their order, unknown ones last', function () {
|
||
$groups = FAQ::groups([
|
||
'questions' => [
|
||
['question' => 'Neu?', 'answer' => 'x', 'category' => 'Sonstiges'],
|
||
['question' => 'Projekt?', 'answer' => 'x', 'category' => 'Für Projekte'],
|
||
['question' => 'Allgemein?', 'answer' => 'x', 'category' => ''],
|
||
['question' => '', 'answer' => 'leer'],
|
||
],
|
||
'categories' => [
|
||
['title' => 'Für Ihr Zuhause', 'icon' => 'home-modern'],
|
||
['title' => 'Für Projekte', 'icon' => 'briefcase'],
|
||
],
|
||
]);
|
||
|
||
expect(array_column($groups, 'title'))->toBe([null, 'Für Projekte', 'Sonstiges'])
|
||
->and(array_column($groups, 'icon'))->toBe([null, 'briefcase', 'question-mark-circle']);
|
||
});
|
||
|
||
it('shows all thirteen questions with both headings on the faq page', function () {
|
||
$page = $this->get('/faq')->assertSuccessful()->getContent();
|
||
$html = substr($page, strpos($page, 'id="faq"'));
|
||
|
||
expect(substr_count($html, 'card-elevated rounded-xl overflow-hidden'))->toBe(13)
|
||
->and(strpos($html, 'Was ist B2in und welche Services'))->toBeLessThan(strpos($html, 'Für Ihr Zuhause'))
|
||
->and(strpos($html, 'Für Ihr Zuhause'))->toBeLessThan(strpos($html, 'Muss ich gleich die ganze Wohnung'))
|
||
->and(strpos($html, 'Muss ich gleich die ganze Wohnung'))->toBeLessThan(strpos($html, 'Für Projekte und Objekte'))
|
||
->and(strpos($html, 'Für Projekte und Objekte'))->toBeLessThan(strpos($html, 'Ab welcher Größe'));
|
||
});
|
||
|
||
it('converts stored faq entries once and keeps maintained texts', function () {
|
||
$legacy = legacyFaq();
|
||
$legacy['sections'][0]['questions'][0]['answer'] = 'Im CMS gepflegt';
|
||
$row = CmsContent::create(['group' => 'faq', 'key' => 'faq', 'type' => 'json', 'order' => 0, 'value' => ['de' => $legacy, 'en' => legacyFaq()]]);
|
||
|
||
$this->seed(FaqCategoriesSeeder::class);
|
||
$first = $row->refresh()->getTranslations('value');
|
||
$this->seed(FaqCategoriesSeeder::class);
|
||
|
||
expect($row->refresh()->getTranslations('value'))->toBe($first)
|
||
->and($first['de'])->not->toHaveKey('sections')
|
||
->and($first['de']['questions'][1])->toBe(['question' => 'Zuhause?', 'answer' => 'Im CMS gepflegt', 'category' => 'Für Ihr Zuhause']);
|
||
|
||
$this->get('/faq')->assertSuccessful()->assertSee('Im CMS gepflegt')->assertSee('Für Projekte');
|
||
});
|
||
|
||
it('still renders entries in the old form until the seeder ran', function () {
|
||
CmsContent::create(['group' => 'faq', 'key' => 'faq', 'type' => 'json', 'order' => 0, 'value' => ['de' => legacyFaq()]]);
|
||
|
||
$this->get('/faq')->assertSuccessful()->assertSee('Zuhause?')->assertSee('Für Ihr Zuhause');
|
||
});
|
||
|
||
it('opens every faq question as plain fields in the content editor', function () {
|
||
$this->actingAs(App\Models\User::factory()->create());
|
||
$this->seed(Database\Seeders\CmsContentSeeder::class);
|
||
$row = CmsContent::query()->where('group', 'faq')->where('key', 'faq')->first();
|
||
|
||
$component = Livewire\Volt\Volt::test('admin.cms.content-index')
|
||
->call('startFieldEdit', $row->id, 'questions');
|
||
|
||
$items = $component->get('jsonItems');
|
||
|
||
expect($items)->toHaveCount(13)
|
||
->and(array_keys($items[5]))->toBe(['question', 'answer', 'category'])
|
||
->and($items[5]['category'])->toBe('Für Ihr Zuhause')
|
||
->and(collect($items)->flatten()->filter(fn ($value) => str_starts_with((string) $value, '[{')))->toBeEmpty();
|
||
});
|