feat(vorlagen): Editor, Liste und Versionsgeschichte (#24)
This commit was merged in pull request #24.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { Markdown } from "@/components/markdown";
|
||||
|
||||
/**
|
||||
* Hilfetexte als Markdown – und nichts darueber hinaus (#010).
|
||||
*
|
||||
* Ein Hilfetext wird von einem Redakteur geschrieben und von jedem Techniker
|
||||
* geoeffnet. Rohes HTML darin waere fremder Code in fremden Browsern; ueber den
|
||||
* JSON-Import kaeme er sogar von ausserhalb des Hauses. `react-markdown` laesst
|
||||
* HTML von sich aus fallen — dieser Test haelt fest, dass niemand spaeter
|
||||
* `rehype-raw` dazustellt, weil „der Kunde Tabellen in HTML schreibt".
|
||||
*
|
||||
* Gerendert wird mit `react-dom/server`, damit der Test ohne DOM-Umgebung laeuft.
|
||||
*/
|
||||
|
||||
function alsHtml(text: string): string {
|
||||
return renderToStaticMarkup(<Markdown text={text} />);
|
||||
}
|
||||
|
||||
describe("Markdown im Hilfetext", () => {
|
||||
it("rendert Fettschrift, Listen und Code", () => {
|
||||
const html = alsHtml("**wichtig**\n\n- eins\n- zwei\n\n`Get-Help`");
|
||||
expect(html).toContain("<strong>wichtig</strong>");
|
||||
expect(html).toContain("<li>eins</li>");
|
||||
expect(html).toContain("Get-Help");
|
||||
});
|
||||
|
||||
it("rendert Tabellen aus GitHub-Markdown", () => {
|
||||
const html = alsHtml("| Gerät | Port |\n|---|---|\n| Switch | 24 |");
|
||||
expect(html).toContain("<table>");
|
||||
expect(html).toContain("Switch");
|
||||
});
|
||||
|
||||
it("laesst ein script-Element nicht durch", () => {
|
||||
const html = alsHtml('Hinweis <script>alert("1")</script> Ende');
|
||||
expect(html).not.toContain("<script>");
|
||||
// Der Text bleibt sichtbar – maskiert, nicht heimlich verschluckt.
|
||||
expect(html).toContain("<script>");
|
||||
});
|
||||
|
||||
it("laesst weder Bilder mit Ereignisattribut noch eingebettete Rahmen durch", () => {
|
||||
// Geprueft wird die *Auszeichnung*, nicht das Wort: „onerror" steht danach
|
||||
// noch im Text, aber maskiert – es wird angezeigt und nicht ausgefuehrt.
|
||||
const html = alsHtml('<img src=x onerror="alert(1)"> <iframe src="https://fremd.example"></iframe>');
|
||||
expect(html).not.toContain("<img");
|
||||
expect(html).not.toContain("<iframe");
|
||||
expect(html).toContain("<img");
|
||||
});
|
||||
|
||||
it("oeffnet Links in einem neuen Tab ohne Herkunft", () => {
|
||||
// Ein Klick mitten im Lauf darf den Lauf nicht verlassen, und die Zielseite
|
||||
// muss nicht erfahren, aus welcher Installation der Klick kam.
|
||||
const html = alsHtml("[Doku](https://intern.example/doku)");
|
||||
expect(html).toContain('target="_blank"');
|
||||
expect(html).toContain('rel="noreferrer"');
|
||||
});
|
||||
|
||||
it("macht aus einem javascript-Link keinen klickbaren Verweis", () => {
|
||||
// Markdown erlaubt `[Text](javascript:…)`. react-markdown filtert das
|
||||
// Protokoll; faellt dieser Schutz weg, faellt es hier auf.
|
||||
const html = alsHtml("[klick mich](javascript:alert(1))");
|
||||
expect(html).not.toContain("javascript:alert");
|
||||
});
|
||||
|
||||
it("gibt bei leerem Text nichts aus, ohne zu scheitern", () => {
|
||||
expect(() => alsHtml("")).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Verweise und Bilder", () => {
|
||||
it("macht aus einem Verweis ohne erlaubtes Protokoll keinen Verweis", () => {
|
||||
// react-markdown leert den href. Ein <a href=""> laedt beim Klick die
|
||||
// aktuelle Seite in einem neuen Tab – verwirrender als gar kein Verweis.
|
||||
const html = renderToStaticMarkup(<Markdown text="[klick mich](javascript:alert(1))" />);
|
||||
expect(html).not.toContain("<a");
|
||||
expect(html).toContain("klick mich");
|
||||
});
|
||||
|
||||
it("zeigt ein Bild als Alternativtext, statt es einzubinden", () => {
|
||||
// Ein Bild laege auf einem fremden Host, und img-src erlaubt nur self.
|
||||
const html = renderToStaticMarkup(<Markdown text="" />);
|
||||
expect(html).not.toContain("<img");
|
||||
expect(html).toContain("[Bild: Schrankplan]");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user