// test/auftraegeTextBausteine.test.js import { test } from 'node:test' import assert from 'node:assert/strict' import * as T from '../server/services/auftraege/texte.js' // Geprüft werden Form und eingesetzte Werte, nie ganze Sätze: die Wortlaute ändert L7. const alleTexte = (wert) => typeof wert === 'string' ? [wert] : Array.isArray(wert) ? wert.flatMap(alleTexte) : wert && typeof wert === 'object' ? Object.values(wert).flatMap(alleTexte) : [] test('Exportnamen und feste Angaben nach Übersicht V7', () => { assert.match(T.TEXTE_FASSUNG, /^\d{4}-\d{2}-\d{2}$/) assert.match(T.FRUEHBEGINN_FASSUNG, /^\d{4}-\d{2}-\d{2}$/) assert.deepEqual(T.ABSENDER, { name: 'WEBklar GbR', strasse: 'Am Schwimmbad 10', plzOrt: '67722 Winnweiler', telefon: '0176 23726355', email: 'support@webklar.com', web: 'webklar.com', vertretenDurch: 'Kenso Grimm und Justin Klein', }) assert.equal(T.AB_TEXTE.titel, 'Auftragsbestätigung') assert.equal(T.AB_TEXTE.kleinunternehmer, 'Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.') assert.equal(T.BESTAETIGUNG_TEXT, 'Ich bestätige den Auftrag zu diesen Bedingungen.') assert.deepEqual(Object.keys(T.AB_TEXTE).sort(), ['agb', 'aufwand', 'einleitung', 'ersetzt', 'gruss', 'kleinunternehmer', 'mitwirkung', 'termine', 'titel', 'zahlungsplan']) assert.deepEqual(Object.keys(T.AB_TEXTE.zahlungsplan).sort(), ['anzahlung', 'frei', 'monatlich', 'nach_abnahme']) for (const name of ['mitwirkung', 'gruss']) assert.ok(typeof T.AB_TEXTE[name] === 'string' && T.AB_TEXTE[name].length > 5, name) assert.ok(typeof T.FRUEHBEGINN_TEXT === 'string' && T.FRUEHBEGINN_TEXT.length > 50 && /Widerruf/.test(T.FRUEHBEGINN_TEXT)) }) test('Einleitung, AGB-Satz, Ersetzt-Hinweis und Termine setzen ihre Werte ein', () => { assert.match(T.AB_TEXTE.einleitung({ datum: '05.10.2026', weg: 'telefonisch' }), /05\.10\.2026.*telefonisch/) assert.doesNotMatch(T.AB_TEXTE.einleitung({ datum: '05.10.2026', weg: '' }), /\(\s*\)/, 'ohne Weg keine leere Klammer') assert.ok(T.AB_TEXTE.agb({ fassung: '30.09.2026' }).includes('30.09.2026')) const ersetzt = T.AB_TEXTE.ersetzt({ nummer: 'AB-2026-0001', datum: '01.10.2026' }) assert.ok(ersetzt.includes('AB-2026-0001') && ersetzt.includes('01.10.2026')) assert.equal(T.AB_TEXTE.termine({ start: null, fertig: null }), null) assert.equal(T.AB_TEXTE.termine({}), null) assert.ok(T.AB_TEXTE.termine({ start: '01.11.2026', fertig: null }).includes('01.11.2026')) const beide = T.AB_TEXTE.termine({ start: '01.11.2026', fertig: '15.12.2026' }) assert.ok(beide.includes('01.11.2026') && beide.includes('15.12.2026')) assert.ok(!T.AB_TEXTE.termine({ start: null, fertig: '15.12.2026' }).includes('null')) }) test('Termine: für Privatpersonen kommt der Satz zum Beginn nach Ablauf der Widerrufsfrist dazu, auch ohne Termine', () => { const ohne = T.AB_TEXTE.termine({ start: '01.11.2026', fertig: '15.12.2026' }) assert.equal(T.AB_TEXTE.termine({ start: '01.11.2026', fertig: '15.12.2026', privat: false }), ohne) assert.doesNotMatch(ohne, /Widerrufsfrist/) const privat = T.AB_TEXTE.termine({ start: '01.11.2026', fertig: '15.12.2026', privat: true }) assert.ok(privat.startsWith(ohne) && privat.length > ohne.length && /Widerrufsfrist/.test(privat), privat) const nurSatz = T.AB_TEXTE.termine({ start: null, fertig: null, privat: true }) assert.ok(typeof nurSatz === 'string' && /Widerrufsfrist/.test(nurSatz) && !nurSatz.includes('null'), String(nurSatz)) assert.equal(T.AB_TEXTE.termine({ privat: true }), nurSatz) }) test('Aufwandsregel und Zahlungsplan: Werte, Schätzung nur wenn gegeben, Ziel 0 heißt sofort', () => { const mit = T.AB_TEXTE.aufwand({ satz: '100,00 €', schaetzung: '10' }) assert.ok(mit.includes('100,00 €') && /\b15\b/.test(mit) && /\b9\b/.test(mit) && /\b10\b/.test(mit), mit) const ohne = T.AB_TEXTE.aufwand({ satz: '100,00 €', schaetzung: null }) assert.ok(!/\b10\b/.test(ohne) && ohne.length < mit.length, ohne) assert.match(T.AB_TEXTE.aufwand({ satz: '100,00 €', schaetzung: '1' }), /\b1 Stunde(?!n)/) const z = T.AB_TEXTE.zahlungsplan const anzahlung = z.anzahlung({ prozent: 50, anzahlung: '400,00 €', rest: '400,00 €', ziel: 14 }) assert.ok(/50\s?%/.test(anzahlung) && anzahlung.split('400,00 €').length === 3 && /\b14\b/.test(anzahlung), anzahlung) for (const art of ['nach_abnahme', 'monatlich']) { assert.ok(/\b14\b/.test(z[art]({ ziel: 14 })), art) assert.ok(!/\b0 Tag/.test(z[art]({ ziel: 0 })), `${art}: Ziel 0`) } const frei = z.frei({ text: 'Zahlung in zwei Raten.', ziel: 14 }) assert.ok(frei.includes('Zahlung in zwei Raten') && !frei.includes('Raten..') && /\b14\b/.test(frei), frei) }) test('Frühbeginn-Erklärung, Widerrufsbelehrung und Formular haben die Form aus V7 und nennen keine Funktionen-Einrichtung mehr', () => { assert.equal(T.WIDERRUFSBELEHRUNG_PROJEKT.titel, 'Widerrufsbelehrung') assert.ok(T.WIDERRUFSBELEHRUNG_PROJEKT.abschnitte.length >= 2) for (const abschnitt of T.WIDERRUFSBELEHRUNG_PROJEKT.abschnitte) { assert.ok(typeof abschnitt.ueberschrift === 'string' && abschnitt.ueberschrift.length > 0) assert.ok(Array.isArray(abschnitt.absaetze) && abschnitt.absaetze.length > 0) for (const absatz of abschnitt.absaetze) assert.ok(typeof absatz === 'string' && absatz.trim() !== '') } assert.equal(T.WIDERRUFSFORMULAR.titel, 'Muster-Widerrufsformular') assert.ok(typeof T.WIDERRUFSFORMULAR.einleitung === 'string' && T.WIDERRUFSFORMULAR.einleitung.length > 0) assert.ok(Array.isArray(T.WIDERRUFSFORMULAR.zeilen) && T.WIDERRUFSFORMULAR.zeilen.length >= 6) const text = alleTexte([T.WIDERRUFSBELEHRUNG_PROJEKT, T.WIDERRUFSFORMULAR, T.FRUEHBEGINN_TEXT]).join('\n') assert.doesNotMatch(text, /Einrichtung|Terminplaner|Wartungs-Abo|Funktionen/) assert.match(text, /vierzehn Tage/) assert.match(text, /Projektauftrag/) assert.match(text, /widerrufen\.html/) assert.match(text, /support@webklar\.com/) })