Migration 20260912000500 legt eine Tabelle menu an: ein Menü je Platz (header, footer) und Sprache, Elementbaum als JSON, Version für dieselbe Konflikterkennung wie bei Seiten. Ein Eintrag verweist auf eine Seite, auf ein Sprungziel innerhalb einer Seite oder auf eine Adresse (HTTPS, lokaler Pfad, mailto:, tel:). Seitenverweise speichern die Seiten-ID, nie den Pfad - ein Eintrag folgt damit einer umbenannten Seite. Beim Rendern fallen Einträge zu gelöschten oder unveröffentlichten Seiten heraus, ohne den gespeicherten Baum zu ändern und ohne die übrigen Einträge zu verlieren. Die Verwaltung nutzt eine nummerierte Zeilenliste statt Drag-and-drop und funktioniert damit vollständig ohne JavaScript; Untermenüs in der Ausgabe über details/summary. tests/bootstrap.php verwirft var/cache/test je Lauf. Ohne Debug prüft Symfony weder den kompilierten Container noch die Vorlagen auf Aktualität, was zweimal ein falsches Testergebnis erzeugt hat. Geprüft: 79 PHP-Tests / 285 Assertions unter PHP 8.2.12 und 8.4.22, 11 JavaScript-Modelltests, Lint/Format/Container, Migration zuerst gegen eine Datenbankkopie, wiederholtes Seeding. Keine Browser- oder Lighthouse-Läufe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
61 lines
2.9 KiB
PHP
61 lines
2.9 KiB
PHP
<?php
|
|
|
|
// Isolated test data only. Never touches the configured application database.
|
|
require dirname(__DIR__).'/vendor/autoload.php';
|
|
|
|
use App\Content\DemoContent;
|
|
use App\Content\DocumentValidator;
|
|
use App\Content\PageRepository;
|
|
use App\Infrastructure\ConnectionFactory;
|
|
use Doctrine\DBAL\Schema\Schema;
|
|
use DoctrineMigrations\Version20260912000100;
|
|
use DoctrineMigrations\Version20260912000200;
|
|
use DoctrineMigrations\Version20260912000300;
|
|
use DoctrineMigrations\Version20260912000400;
|
|
use DoctrineMigrations\Version20260912000500;
|
|
use Psr\Log\NullLogger;
|
|
|
|
$directory = dirname(__DIR__).'/var/browser-tests';
|
|
if (!is_dir($directory)) {
|
|
mkdir($directory, 0775, true);
|
|
}
|
|
$path = $directory.'/'.bin2hex(random_bytes(12)).'.db';
|
|
$url = 'sqlite:///'.str_replace('\\', '/', $path);
|
|
$db = ConnectionFactory::create($url);
|
|
$schema = new Schema();
|
|
(new Version20260912000100($db, new NullLogger()))->up($schema);
|
|
(new Version20260912000200($db, new NullLogger()))->up($schema);
|
|
(new Version20260912000300($db, new NullLogger()))->up($schema);
|
|
(new Version20260912000400($db, new NullLogger()))->up($schema);
|
|
(new Version20260912000500($db, new NullLogger()))->up($schema);
|
|
foreach ($schema->toSql($db->getDatabasePlatform()) as $sql) {
|
|
$db->executeStatement($sql);
|
|
}
|
|
Version20260912000400::applyIndexes($db);
|
|
$db->insert('website', ['id' => 'default', 'name' => 'Browser test', 'default_locale' => 'de', 'theme' => '{}']);
|
|
$pages = new PageRepository($db, new DocumentValidator());
|
|
foreach (DemoContent::pages() as $slug => $document) {
|
|
$id = 'test-'.$slug;
|
|
$db->insert('page', ['id' => $id, 'slug' => $slug, 'path' => $slug, 'type' => 'page', 'locale' => 'de', 'website_id' => 'default', 'version' => 0, 'created_at' => gmdate('Y-m-d H:i:s')]);
|
|
$revision = $pages->saveDraft($id, $document, 0);
|
|
$pages->publish($id, $revision, 1);
|
|
}
|
|
$password = bin2hex(random_bytes(20));
|
|
$username = 'browser-'.bin2hex(random_bytes(6));
|
|
$db->insert('cms_user', ['id' => $username, 'username' => $username, 'password_hash' => password_hash($password, PASSWORD_BCRYPT, ['cost' => 4]), 'roles' => '["ROLE_ADMIN"]']);
|
|
$images = [];
|
|
foreach (['Berge', 'Küste'] as $index => $title) {
|
|
$image = imagecreatetruecolor(1800, 1200);
|
|
for ($y = 0; $y < 1200; ++$y) {
|
|
$color = imagecolorallocate($image, 110 + (int) ($y / 18), 150 + (int) ($y / 30), 155 + (int) ($y / 28));
|
|
imageline($image, 0, $y, 1799, $y, $color);
|
|
}
|
|
imagefilledellipse($image, 1300, 270, 210, 210, imagecolorallocate($image, 245, 223, 169));
|
|
imagefilledpolygon($image, [0, 1000, 420, 350 + $index * 150, 950, 980, 1400, 550, 1800, 1100, 1800, 1200, 0, 1200], imagecolorallocate($image, 42, 83 + $index * 20, 75));
|
|
$imagePath = $path.'-'.$title.'.png';
|
|
imagepng($image, $imagePath);
|
|
imagedestroy($image);
|
|
$images[] = $imagePath;
|
|
}
|
|
echo json_encode(['databaseUrl' => $url, 'mediaDirectory' => $path.'-media', 'images' => $images, 'username' => $username, 'password' => $password]);
|