← Code-Übersicht

ContentConversionTest.php

Pfad: tests/ContentConversionTest.php

Ext: php

Größe: 3190 Bytes

Geändert: 2026-07-16 01:42:10+02

<?php
declare(strict_types=1);

namespace Tests;

use Demo\Infrastructure\Content\HtmlToMarkdown;
use Demo\Infrastructure\Content\MarkdownToHtml;
use PHPUnit\Framework\TestCase;

/**
 * Prueft die Konvertierung der erlaubten Elemente und die XSS-Sicherheit.
 */
final class ContentConversionTest extends TestCase
{
    /**
     * Registriert den Autoloader vor jedem Testfall.
     */
    protected function setUp(): void
    {
        $root = dirname(__DIR__);
        require_once $root . '/src/Autoloader.php';
        (new \Demo\Autoloader($root . '/src'))->register();
    }

    /**
     * Markdown-Grundelemente werden zu den erwarteten HTML-Tags.
     */
    public function testMarkdownRendersAllowedElements(): void
    {
        $html = (new MarkdownToHtml())->render("## Titel\n\nText mit **fett**.\n\n- a\n- b");

        self::assertStringContainsString('<h2>Titel</h2>', $html);
        self::assertStringContainsString('<strong>fett</strong>', $html);
        self::assertStringContainsString('<ul>', $html);
        self::assertStringContainsString('<li>a</li>', $html);
    }

    /**
     * Text mit HTML-Metazeichen wird beim Rendern escaped (kein Stored-XSS).
     */
    public function testMarkdownEscapesHtml(): void
    {
        $html = (new MarkdownToHtml())->render('<script>alert(1)</script>');

        self::assertStringNotContainsString('<script>', $html);
        self::assertStringContainsString('&lt;script&gt;', $html);
    }

    /**
     * Editor-HTML wird korrekt nach Markdown gewandelt.
     */
    public function testHtmlConvertsToMarkdown(): void
    {
        $md = (new HtmlToMarkdown())->convert('<h2>Titel</h2><p>Ein <strong>fett</strong> Wort</p><ul><li>a</li><li>b</li></ul>');

        self::assertStringContainsString('## Titel', $md);
        self::assertStringContainsString('Ein **fett** Wort', $md);
        self::assertStringContainsString('- a', $md);
        self::assertStringContainsString('- b', $md);
    }

    /**
     * Script-Elemente werden bei der Konvertierung verworfen.
     */
    public function testHtmlToMarkdownDropsScript(): void
    {
        $md = (new HtmlToMarkdown())->convert('<p>ok</p><script>boeser_code()</script>');

        self::assertStringNotContainsString('boeser_code', $md);
        self::assertStringContainsString('ok', $md);
    }

    /**
     * Der Roundtrip Markdown -> HTML -> Markdown erhaelt die Inhalte.
     */
    public function testRoundtripPreservesContent(): void
    {
        $quelle = "# Kapitel\n\nAbsatz mit **Betonung**.\n\n1. eins\n2. zwei";
        $html = (new MarkdownToHtml())->render($quelle);
        $zurueck = (new HtmlToMarkdown())->convert($html);

        self::assertStringContainsString('# Kapitel', $zurueck);
        self::assertStringContainsString('**Betonung**', $zurueck);
        self::assertStringContainsString('1. eins', $zurueck);
        self::assertStringContainsString('2. zwei', $zurueck);
    }

    /**
     * HtmlToMarkdown erfuellt den Domaenen-Port HtmlKonverter.
     */
    public function testImplementiertPort(): void
    {
        self::assertInstanceOf(\Demo\Domain\Dokumentation\HtmlKonverter::class, new HtmlToMarkdown());
    }
}