Files
KantSites/tests/browser-fixture.php
T
kantarciandClaude Opus 5 a6ffb9bdfd Seiten im Browser anlegen und löschen, Adresshierarchie und Beitragstyp
Migration 20260912000400 ergänzt page.path, parent_id, type und
created_at. Die websiteweite Eindeutigkeit wandert vom Slug auf den
vollständigen Pfad, damit gleiche Segmente unter verschiedenen Eltern
möglich sind. Nur ADD COLUMN: Index- oder Fremdschlüsseländerungen
würden SQLite die Tabelle neu aufbauen lassen, was am Fremdschlüssel
revision.page_id scheitert; die Indizes werden in postUp() gesetzt.

POST /admin/pages legt Seiten und Beiträge als privaten Entwurf an
(ROLE_EDITOR), POST /admin/pages/{id}/delete entfernt eine Seite mit
allen Revisionen (ROLE_ADMIN). Beides mit CSRF, ohne JavaScript
bedienbar, mit Schutz für Elternseiten und veraltete Versionen.
Die öffentliche Route bedient verschachtelte Pfade und lässt die
CMS-Routen unberührt.

Testumgebung: Login-Throttling zählt jetzt in einem Array-Cache,
weil die persistierten Zähler die Anmeldung über Testläufe hinweg
aussperrten.

Geprüft: 56 PHP-Tests / 212 Assertions unter PHP 8.2.12 und 8.4.22,
10 JavaScript-Modelltests, Lint/Format/Container, Migration zuerst
gegen eine Datenbankkopie. Keine Browser- oder Lighthouse-Läufe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 10:31:46 +02:00

59 lines
2.8 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 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);
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]);