// Gemeinsame Testdaten und Quelltext-Regeln des Strangs L6 (kein Test, daher nicht *.test.js). // Formen laut Übersicht V3 (AuftragOeffentlich) und V5 (Liste im Portal: plus id und kannBestaetigen). import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' export const TOKEN = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG' // 43 Zeichen wie ein echter Token (base64url) export const BESTAETIGT_AM = '2026-10-07T08:15:00.000Z' // = 07.10.2026, 10:15 Uhr Berliner Zeit (MESZ) export const KLEINUNTERNEHMER = 'Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.' // wie AB_TEXTE.kleinunternehmer; die API liefert ihn als texte.kleinunternehmer /** Festpreis-AB eines Unternehmens, gesendet, noch nicht bestätigt. */ export const ab = (over = {}) => ({ nummer: 'AB-2026-0002', datum: '2026-10-06', titel: 'Website Anelia Wolf', art: 'festpreis', positionen: [ { beschreibung: 'Erstellung der Website anelia-wolf.com', menge: 1, einzelpreisCents: 60000, summeCents: 60000 }, { beschreibung: 'Texte und Bildbearbeitung', menge: 2, einzelpreisCents: 10000, summeCents: 20000 }, ], summeCents: 80000, stundensatzCents: null, schaetzungMinuten: null, aufwandText: null, zahlungsplanText: 'Anzahlung 50 % (400,00 €) nach Auftragsbestätigung, Rest (400,00 €) nach Abnahme; zahlbar jeweils innerhalb von 14 Tagen nach Rechnung.', startAm: '2026-10-12', fertigBis: '2026-11-30', kundenart: 'unternehmen', status: 'versendet', bestaetigtAm: null, fruehbeginn: false, fruehesterBeginn: null, agbUrl: '/rechtliches/agb-2026-09-30.pdf', texte: { bestaetigung: 'Ich bestätige den Auftrag zu diesen Bedingungen.', fruehbeginn: null, kleinunternehmer: KLEINUNTERNEHMER }, ...over, }) /** Dieselbe AB für eine Privatperson (zweites, freiwilliges Häkchen; Texte sind Testtexte, nicht die der Rechtsrunde). */ export const privat = (over = {}) => ab({ kundenart: 'privat', fruehesterBeginn: '2026-10-21', texte: { bestaetigung: 'Ich bestätige den Auftrag zu diesen Bedingungen.', fruehbeginn: 'Ich verlange, dass Sie schon vor Ablauf der Widerrufsfrist mit der Arbeit beginnen.', kleinunternehmer: KLEINUNTERNEHMER, }, ...over, }) /** Die übergebene AB im Zustand „bestätigt“. */ export const bestaetigt = (auftrag) => ({ ...auftrag, status: 'bestaetigt', bestaetigtAm: BESTAETIGT_AM }) /** Eintrag der Portal-Liste (GET /api/auftraege): AB plus id und kannBestaetigen. */ export const eintrag = (over = {}) => ({ id: 'ab1', ...ab(), kannBestaetigen: true, ...over }) const ohneKommentare = (quelle) => quelle.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|\s)\/\/.*$/gm, '$1') const DU = /\b(?:du|dein(?:e[nmrs]?)?|dich|dir)\b/i const SIE = /\b(?:Sie|Ihr(?:e[nmrs]?)?|Ihnen)\b/ /** Steht eine Du- bzw. Sie-Form im Text? (Anrede-Prüfungen der Tests) */ export const hatDuForm = (text) => DU.test(String(text)) export const hatSieForm = (text) => SIE.test(String(text)) /** * Quelltext-Regeln für jedes Modul public/auftrag*.js; gibt den Quelltext ohne Kommentare zurück. * mitTexten: nur auftrag-ansicht.js enthält Kundentexte (ihre Anrede prüft der Test selbst); alle anderen Module enthalten weder Du- noch Sie-Formen. */ export function pruefeQuelltext(datei, { fetchAnzahl = 0, importe = [], mitTexten = false } = {}) { const quelle = ohneKommentare(readFileSync(new URL(`../public/${datei}`, import.meta.url), 'utf8')) assert.doesNotMatch(quelle, /innerHTML|insertAdjacentHTML|outerHTML|document\.write|\beval\(|new Function/, `${datei}: Daten nie als HTML`) assert.doesNotMatch(quelle, /localStorage|sessionStorage|document\.cookie|indexedDB/, `${datei}: kein Browserspeicher`) assert.doesNotMatch(quelle, /\bconsole\./, `${datei}: nichts ins Protokoll (der Token!)`) assert.doesNotMatch(quelle, /\bconfirm\(|\balert\(|\bprompt\(/, `${datei}: keine Browser-Rückfragen`) assert.doesNotMatch(quelle, /import\s*\(/, `${datei}: kein dynamischer Import`) assert.ok(!quelle.includes(String.fromCodePoint(0xa0)), `${datei}: kein verstecktes geschütztes Leerzeichen im Quelltext`) if (!mitTexten) assert.ok(!DU.test(quelle) && !hatSieForm(quelle), `${datei}: keine Kundentexte im Modul (sie stehen in auftrag-ansicht.js; Anrede über ANREDE_SIE/ANREDE_DU)`) assert.equal([...quelle.matchAll(/\bfetch\(/g)].length, fetchAnzahl, `${datei}: Anzahl fetch`) assert.deepEqual([...quelle.matchAll(/\bfrom\s+'([^']+)'/g)].map((m) => m[1]), importe, `${datei}: Importe`) return quelle }