Eine cmssy-App testen
Der Editor ist der Pfad, den dein Build nicht prüfen kann. Ein Smoke-Test deckt ihn ab.
Eine Website mit totem Editor kompiliert weiterhin, liefert weiterhin aus und besteht weiterhin deine Unit-Tests. Nichts in einem normalen Build berührt den Edit-Pfad - also sagt dir auch nichts, wenn er kaputtgeht.
checkCmssyEditMode ist die Prüfung, die es tut.
Der Smoke-Test
import { checkCmssyEditMode } from "@cmssy/next/testing";
const result = await checkCmssyEditMode({
baseUrl: "http://localhost:3000",
secret: process.env.CMSSY_DRAFT_SECRET!,
path: "/",
// Nur wenn deine URLs die Sprache tragen. Die Prüfung liest <html lang> -
// einen Vertrag - statt nach einem Wort aus deinen Texten zu suchen, das
// eine Redaktion jederzeit ändern kann.
localizedPath: "/de",
});
expect(result.failures).toEqual([]);Führe ihn gegen einen gestarteten Production-Build aus (next build && next start), nicht gegen den Dev-Server. Genau das statische Rendering hat die Edit-Route überhaupt nötig gemacht - der Dev-Server testet also die falsche App.
Es gibt eine weitere Option für Sites, deren URL-Präfix nicht der Locale-Code ist. localizedLocale benennt die Sprache, die localizedPath rendern muss; standardmäßig ist es das erste Pfadsegment, das auf einer präfixierten Site die Sprache ist. Setze es explizit, wenn Präfix und Locale auseinandergehen - etwa /en-gb für Locale en - sonst vergleicht die Prüfung mit einer Sprache, die es nicht gibt, und schlägt aus dem falschen Grund fehl.
Was er zusichert
- Die öffentliche Seite liefert 200 ohne Editor, mit serverseitig gerendertem Header und Footer.
- Ein bloßes
?cmssyEdit=1ohne Secret geht nicht in den Edit-Modus. Eine unverifizierte Anfrage darf die Tür nie öffnen. - Ein verifiziertes
cmssyEdit=1pluscmssySecretrendert den Editor und verschiebt Header und Footer auf die Edit-Bridge. - Optional: Die lokalisierte Vorschau deklariert die Sprache, die ihre URL verlangt, per
<html lang>.
Warum "kein Header im SSR" Erfolg bedeutet
Diese Zusicherung liest sich verkehrt herum, bis man den Grund sieht.
Im Edit-Modus mounten Header und Footer über die Edit-Bridge, die auf dem Client rendert. Ein Header, der noch im servergerenderten HTML steckt, ist also ein Header, den der Editor auswählen, aber nicht bearbeiten kann - der Unterschied zwischen einem editierbaren Block und bloßem Markup.
Schlägt der Test fehl, benennt die Meldung die Ursache statt des Symptoms:
edit /shop: the header and footer are still server-rendered - they will be
selectable but have no fields (is CMSSY_EDIT_HEADER set on the rewrite?)In CI
- run: pnpm build
- run: |
pnpm start &
npx wait-on http://localhost:3000 --timeout 60000
- run: pnpm smoke:editÜberspringe den Job, wenn die Workspace-Secrets fehlen. Ein grüner Haken, der nichts prüft, ist schlechter als gar keine Prüfung - er macht aus einer Unbekannten eine falsche Sicherheit.
Als Skript verdrahten
Die Referenz-App hält ihn als eigenständiges Skript statt als Test-Runner-Fall, damit er ohne Framework in CI laufen kann:
{
"scripts": {
"smoke:edit": "node smoke-edit.mjs"
}
}// smoke-edit.mjs
import { checkCmssyEditMode } from "@cmssy/next/testing";
const result = await checkCmssyEditMode({
baseUrl: "http://localhost:3000",
secret: process.env.CMSSY_DRAFT_SECRET,
localizedPath: "/de",
});
console.log(result.ok ? "EDITOR OK" : "EDITOR BROKEN");
for (const f of result.failures) console.log(" -", f);
process.exit(result.ok ? 0 : 1);Was sonst noch zu testen ist
Blöcke sind gewöhnliche React-Komponenten, teste sie also gewöhnlich. Zwei cmssy-spezifische Gewohnheiten lohnen sich:
- Rendere jeden Block mit
data: undefined- genau das übergibt der Editor, und ein Block, der ohne Loader-Ergebnis wirft, ist ein Block, der den Editor bricht. - Rendere mit fehlendem Locale - Inhalte sind vielleicht noch nicht übersetzt, und der Fallback-Pfad ist der erste, auf den Besucher in einer neuen Sprache treffen.
Nächste Schritte
- Server-Loader - warum
dataim Editor undefined ist. - Rendering - die Routen, die der Smoke-Test durchspielt.
- Seiten-Editor - was der Editor tut, sobald er offen ist.