Add device visibility and responsive navigation for 1.10.0
This commit is contained in:
1 parent
eea6747d9e
commit
37c2942d1d
18 files changed
+493
-26
No files matched your search
+7
-4
@@ -574,7 +574,8 @@ final class CmsTest extends TestCase
|
||||
self::assertStringContainsString('href="https://hausklar.app"', $html);
|
||||
self::assertStringContainsString('href="tel:+4972219957150"', $html);
|
||||
// The home link is the current page; an anchor inside it is not.
|
||||
self::assertSame(1, substr_count($html, 'aria-current="page"'));
|
||||
// Desktop and collapsed menu carry the same marker; CSS exposes one variant at a time.
|
||||
self::assertSame(2, substr_count($html, 'aria-current="page"'));
|
||||
self::assertMatchesRegularExpression('~<a href="/" aria-current="page">\s*<span class="nav-label"><span>Start</span></span>\s*</a>~', $html);
|
||||
|
||||
// On another page the marker moves and nothing else changes.
|
||||
@@ -2569,7 +2570,7 @@ final class CmsTest extends TestCase
|
||||
self::assertStringContainsString('<header class="site-header">', $html);
|
||||
self::assertStringContainsString('<p id="area-header-name" class="block-text">kantsites</p>', $html);
|
||||
self::assertStringContainsString('aria-label="Hauptnavigation"', $html);
|
||||
self::assertStringContainsString('>Start</a>', $html);
|
||||
self::assertStringContainsString('<span class="nav-label"><span>Start</span></span>', $html);
|
||||
|
||||
// Changing the header reaches every page at once, because it is one shared document.
|
||||
$header = $this->partials->findByKind('header');
|
||||
@@ -2699,7 +2700,8 @@ final class CmsTest extends TestCase
|
||||
self::assertSame('_blank', $crawler->filter($selector)->attr('target'));
|
||||
self::assertSame('noopener', $crawler->filter($selector)->attr('rel'));
|
||||
}
|
||||
self::assertCount(2, $crawler->filter('.site-header .menu-list a[target="_blank"][rel="noopener"]'));
|
||||
self::assertCount(2, $crawler->filter('.site-header .block-menu > .menu-list a[target="_blank"][rel="noopener"]'));
|
||||
self::assertCount(2, $crawler->filter('.site-header .menu-burger a[target="_blank"][rel="noopener"]'));
|
||||
$document['blocks'][array_key_last($document['blocks'])]['props']['newTab'] = 'yes';
|
||||
$this->expectException(InvalidDocument::class);
|
||||
(new DocumentValidator())->validate($document);
|
||||
@@ -3295,7 +3297,8 @@ final class CmsTest extends TestCase
|
||||
$html = $this->request('/')->getContent();
|
||||
self::assertStringContainsString('class="block-menu menu-'.$layout, $html);
|
||||
// The burger opens with a details element, so it works on a page that runs no script.
|
||||
self::assertSame('burger' === $layout, str_contains($html, 'menu-burger'));
|
||||
$crawler = new \Symfony\Component\DomCrawler\Crawler($html);
|
||||
self::assertCount('vertical' === $layout ? 0 : 1, $crawler->filter('#nav > details.menu-burger'));
|
||||
self::assertStringContainsString("script-src 'none'", (string) $this->request('/')->headers->get('Content-Security-Policy'));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests;
|
||||
|
||||
use App\Content\DocumentValidator;
|
||||
use App\Domain\InvalidDocument;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ResponsiveVisibilityTest extends TestCase
|
||||
{
|
||||
private function document(int $version = 22): array
|
||||
{
|
||||
return ['schemaVersion' => $version, 'title' => 'Geräte', 'description' => 'Geräteprüfung', 'blocks' => [
|
||||
['id' => 'heading', 'type' => 'heading', 'props' => ['text' => 'Geräte', 'level' => 1]],
|
||||
['id' => 'menu', 'type' => 'menu', 'props' => ['slot' => 'header', 'layout' => 'horizontal']],
|
||||
]];
|
||||
}
|
||||
|
||||
public function testOldDocumentsAndEveryVisibilityAndMenuOptionRemainValid(): void
|
||||
{
|
||||
$validator = new DocumentValidator();
|
||||
$validator->validate($this->document(21));
|
||||
foreach (['all', 'desktop', 'tablet', 'mobile', 'hide-desktop', 'hide-tablet', 'hide-mobile', 'hidden'] as $visibility) {
|
||||
foreach (['tablet', 'mobile', 'never'] as $collapse) {
|
||||
$document = $this->document();
|
||||
$document['blocks'][1]['layout'] = ['visibility' => $visibility];
|
||||
$document['blocks'][1]['props']['collapse'] = $collapse;
|
||||
$validator->validate($document);
|
||||
self::assertSame($document, json_decode(json_encode($document, JSON_THROW_ON_ERROR), true, 512, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testInvalidValuesAndOlderSchemasRejectNewOptions(): void
|
||||
{
|
||||
foreach ([['visibility', 'desktop', 21], ['collapse', 'tablet', 21], ['visibility', 'injected class', 22], ['collapse', 'sometimes', 22], ['visibility', [], 22], ['collapse', null, 22]] as [$key, $value, $version]) {
|
||||
$document = $this->document($version);
|
||||
$document['blocks'][1]['visibility' === $key ? 'layout' : 'props'][$key] = $value;
|
||||
try {
|
||||
(new DocumentValidator())->validate($document);
|
||||
self::fail('Ungültige Geräteoption wurde akzeptiert.');
|
||||
} catch (InvalidDocument $error) {
|
||||
self::assertNotEmpty($error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { EditorHistory, setVisibility, locate, duplicateBlock } from '../public/assets/editor-model.js';
|
||||
|
||||
test('visibility preserves responsive layout and migrates, undoes, redoes and resets atomically', () => {
|
||||
const original = { schemaVersion: 21, title: 'Geräte', description: '', blocks: [{ id: 'section', type: 'section', layout: { width: 'full' }, style: { desktop: { display: 'flex' }, mobile: { display: 'grid' } }, children: [] }] };
|
||||
const history = new EditorHistory(original);
|
||||
history.change(doc => setVisibility(doc, 'section', 'mobile'));
|
||||
assert.equal(history.document.schemaVersion, 22);
|
||||
assert.equal(locate(history.document.blocks, 'section').block.layout.visibility, 'mobile');
|
||||
history.undo(); assert.deepEqual(history.document, original);
|
||||
history.redo(); assert.equal(history.document.blocks[0].layout.visibility, 'mobile');
|
||||
const duplicate = history.change(doc => duplicateBlock(doc, 'section'));
|
||||
assert.equal(locate(history.document.blocks, duplicate).block.layout.visibility, 'mobile');
|
||||
history.change(doc => setVisibility(doc, 'section', 'all'));
|
||||
assert.deepEqual(history.document.blocks[0], original.blocks[0]);
|
||||
assert.throws(() => setVisibility(history.document, 'section', 'invalid'));
|
||||
});
|
||||
Reference in new issue
Block a user