OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

PageWritingWiringTest.php

5 KB
<?php

declare(strict_types=1);

use OpenNIT\Content\VersionManager;

/**
 * Deckt ab, dass Seiten schreibende Aufrufer zur Umsetzung passen.
 *
 * Eine falsche Argumentzahl oder eine Spalte, die es nicht gibt, fällt erst zur
 * Laufzeit auf – und in Pfaden mit eigenem catch bleibt davon nur eine
 * allgemeine Meldung übrig. Beides wird deshalb hier festgehalten.
 */
return static function (): void {

    /** @return list<string> Alle PHP-Dateien unterhalb von src/ */
    $quellen = static function (): array {
        $dateien = [];
        $lauf = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator(dirname(__DIR__) . '/src', FilesystemIterator::SKIP_DOTS)
        );
        foreach ($lauf as $datei) {
            if ($datei->isFile() && $datei->getExtension() === 'php') {
                $dateien[] = $datei->getPathname();
            }
        }
        sort($dateien);
        return $dateien;
    };

    // ----------------------------------------------------------------
    // Argumentzahl des VersionManagers
    // ----------------------------------------------------------------

    test('Der VersionManager verlangt Datenbank und Audit-Log', function () {
        $ctor = (new ReflectionClass(VersionManager::class))->getConstructor();

        assertTrue($ctor !== null, 'Kein Konstruktor gefunden');
        assertSame(2, $ctor->getNumberOfRequiredParameters());
    });

    test('Jeder Aufrufer übergibt beide Abhängigkeiten', function () use ($quellen) {
        $ctor     = (new ReflectionClass(VersionManager::class))->getConstructor();
        $noetig   = $ctor->getNumberOfRequiredParameters();
        $gefunden = 0;

        foreach ($quellen() as $datei) {
            $inhalt = (string)file_get_contents($datei);
            if (!preg_match_all('/new VersionManager\(([^)]*)\)/', $inhalt, $treffer)) {
                continue;
            }
            foreach ($treffer[1] as $argumente) {
                $gefunden++;
                $anzahl = trim($argumente) === '' ? 0 : count(explode(',', $argumente));
                assertSame(
                    $noetig,
                    $anzahl,
                    'Zu wenige Argumente in ' . basename($datei) . ': new VersionManager(' . $argumente . ')'
                );
            }
        }

        assertTrue($gefunden > 0, 'Keine Instanziierung gefunden – die Prüfung liefe ins Leere');
    });

    // ----------------------------------------------------------------
    // Geschriebene Spalten der Tabelle pages
    // ----------------------------------------------------------------

    test('Auf pages werden nur vorhandene Spalten geschrieben', function () use ($quellen) {
        // Spaltenbestand aus den Migrationen ableiten: Definition plus spätere
        // ADD COLUMN. Nur so fällt eine erfundene Spalte ohne Datenbank auf.
        $spalten = [];
        foreach (glob(dirname(__DIR__) . '/database/migrations/*.sql') ?: [] as $sql) {
            $inhalt = (string)file_get_contents($sql);

            if (preg_match('/CREATE TABLE IF NOT EXISTS `pages` \((.*?)\n\) ENGINE/s', $inhalt, $m)) {
                preg_match_all('/^\s*`([a-z_]+)`\s+[A-Z]/mi', $m[1], $sm);
                $spalten = array_merge($spalten, $sm[1]);
            }
            if (preg_match_all('/ALTER TABLE `?pages`?\s+(.*?);/s', $inhalt, $am)) {
                foreach ($am[1] as $block) {
                    preg_match_all('/ADD COLUMN `?([a-z_]+)`?/i', $block, $cm);
                    $spalten = array_merge($spalten, $cm[1]);
                }
            }
        }
        $spalten = array_unique($spalten);
        assertTrue(in_array('current_version_id', $spalten, true), 'Spaltenbestand wurde nicht erkannt');

        foreach ($quellen() as $datei) {
            $inhalt = (string)file_get_contents($datei);
            if (!preg_match_all("/update\(\s*'pages'\s*,\s*\[(.*?)\]/s", $inhalt, $treffer)) {
                continue;
            }
            foreach ($treffer[1] as $block) {
                preg_match_all("/'([a-z_]+)'\s*=>/", $block, $km);
                foreach ($km[1] as $spalte) {
                    assertTrue(
                        in_array($spalte, $spalten, true),
                        'Unbekannte Spalte "' . $spalte . '" in ' . basename($datei)
                    );
                }
            }
        }
    });

    // ----------------------------------------------------------------
    // Seite und erste Version entstehen gemeinsam
    // ----------------------------------------------------------------

    test('Die vom KI-Chat angelegte Seite entsteht in einer Transaktion', function () {
        // Bricht die Versionserstellung ab, darf keine Seite ohne Inhalt zurückbleiben.
        $src = (string)file_get_contents(dirname(__DIR__) . '/src/Controllers/AIChatController.php');

        $start = strpos($src, 'private function createPageFromChat');
        assertTrue($start !== false, 'Die Aktion wurde nicht gefunden');
        $block = substr($src, $start, 3000);

        assertTrue(str_contains($block, 'beginTransaction()'), 'Keine Transaktion');
        assertTrue(str_contains($block, 'commit()'), 'Kein Abschluss');
        assertTrue(str_contains($block, 'rollback()'), 'Kein Rückbau bei Abbruch');
        assertTrue(
            strpos($block, 'beginTransaction()') < strpos($block, "insert('pages'"),
            'Der Insert liegt außerhalb der Transaktion'
        );
    });
};