Mails K15/K16 je Funktion (News-Wortlaut eingefroren)
K15 (Bestellung eingegangen) und K16 (Funktion bereit) tragen den Wortlaut der Funktion als Platzhalter (funktion, funktion_gen/akk/nom/pron/dein, preis_hinweis, danach, bereit, knopf, portal_url) statt fest News-Pinnwand. siteFeatures baut die Werte mit bestellMail/bereitMail aus dem Register-Eintrag (mails.*, setupEstimate, returnHash) und dem Katalogpreis je feature.product. K15 geht ohne Anhaenge raus. Die News-Mails bleiben Zeichen fuer Zeichen gleich (Test featureMails friert Betreff und Text ein). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9dd0244537
commit
e200efb7e5
5 files changed
+421
-37
No files matched your search
@@ -6,7 +6,7 @@ import { contractAttachmentFor, termsDocFor } from '../server/services/products.
|
||||
|
||||
const DIR = new URL('../server/mail-templates/', import.meta.url)
|
||||
// G01–G08 Gästemails des Terminplaners (Task 9, neutrales Layout im Auftrag eines Betriebs), K20 und K21 Hinweise an den Betrieb;
|
||||
// K12, K14 und T12 (Wechsel ins Wartungs-Abo) aus Task 9, K13 und T13 (Zusatzspeicher) aus Task 8 (Fix 1); Endfassung der Texte in Task 12; T14 „Löschfristen“ aus Task 21 (F39); T15 Push-Zeitmail; K15, K16, T16 Funktionen (News-Pinnwand); T17 Repo zuordnen; K17 Chat-Hinweis an Kunden; K18, K19 Website-Analyse; T18 Bankzugang erneuern (Finanzen); T20 Terminplaner Betriebsmeldung (Terminplaner TP2, Team-Hinweis; T19 „Erstattung fällig“ folgt in Block B)
|
||||
// K12, K14 und T12 (Wechsel ins Wartungs-Abo) aus Task 9, K13 und T13 (Zusatzspeicher) aus Task 8 (Fix 1); Endfassung der Texte in Task 12; T14 „Löschfristen“ aus Task 21 (F39); T15 Push-Zeitmail; K15, K16, T16 Funktionen (News-Pinnwand, Terminplaner; K15 und K16 gelten je Funktion, Terminplaner TP2 B9a); T17 Repo zuordnen; K17 Chat-Hinweis an Kunden; K18, K19 Website-Analyse; T18 Bankzugang erneuern (Finanzen); T20 Terminplaner Betriebsmeldung (Terminplaner TP2, Team-Hinweis; T19 „Erstattung fällig“ folgt in Block B)
|
||||
const ids = (prefix, count) => Array.from({ length: count }, (_, i) => `${prefix}${String(i + 1).padStart(2, '0')}`)
|
||||
const EXPECTED = [...ids('G', 8), ...ids('K', 21), ...ids('T', 18), 'T20']
|
||||
const GUEST = ids('G', 8)
|
||||
@@ -70,6 +70,33 @@ test('T20: Betreff [Terminplaner], Platzhalter vorfall/details/zeit, keine Blöc
|
||||
for (const line of ['Mailkontingent erreicht', 'Zeile 1\nZeile <2>', '04.10.2026, 10:00']) assert.ok(mail.text.includes(line), `Text enthält: ${line}\n---\n${mail.text}`)
|
||||
})
|
||||
|
||||
// Terminplaner TP2 (B9a): K15 und K16 gelten für jede Funktion des Registers; der Wortlaut je Funktion kommt aus den Platzhaltern
|
||||
test('K15, K16: Platzhalter und Blöcke je Funktion, keine Funktion fest im Text', () => {
|
||||
const k15 = loadTemplate('K15')
|
||||
assert.equal(k15.subject, 'Deine Bestellung: {{funktion}}')
|
||||
assert.deepEqual(k15.placeholders, ['kunde_name', 'projekt', 'funktion', 'funktion_gen', 'funktion_akk', 'funktion_nom', 'funktion_pron', 'preis', 'preis_hinweis', 'zeit', 'danach', 'portal_url', 'rechnung_url'])
|
||||
assert.deepEqual(k15.blocks, ['rechnung'])
|
||||
const k16 = loadTemplate('K16')
|
||||
assert.equal(k16.subject, '{{funktion_dein}} ist bereit')
|
||||
assert.deepEqual(k16.placeholders, ['kunde_name', 'projekt', 'funktion', 'funktion_dein', 'funktion_nom', 'bereit', 'knopf', 'portal_url'])
|
||||
assert.deepEqual(k16.blocks, [])
|
||||
for (const tpl of [k15, k16]) assert.doesNotMatch(tpl.body, /News|Beitr|#news|#termine|Terminplaner/, `${tpl.id}: keine feste Funktion`)
|
||||
|
||||
const mail = renderMail('K15', { ...sampleValues(k15), rechnung_url: 'https://rechnung.example/1', portal_url: 'https://portal.example/#x' }, { rechnung: true })
|
||||
assert.deepEqual(mail.problems, [])
|
||||
assert.equal(mail.subject, 'Deine Bestellung: Wert-funktion')
|
||||
for (const part of ['Wir richten Wert-funktion_akk jetzt für Dein Projekt ein.', 'Sobald Wert-funktion_nom auf Deiner Website eingebaut ist, schalten wir Wert-funktion_pron im Kundenportal frei', 'Wert-danach', 'Wert-preis (Wert-preis_hinweis)', 'Rechnung ansehen: https://rechnung.example/1', 'Zum Kundenportal: https://portal.example/#x']) {
|
||||
assert.ok(mail.text.includes(part), `K15 enthält: ${part}\n---\n${mail.text}`)
|
||||
}
|
||||
assert.doesNotMatch(renderMail('K15', sampleValues(k15), { rechnung: false }).text, /Rechnung ansehen/)
|
||||
const bereit = renderMail('K16', sampleValues(k16), {})
|
||||
assert.deepEqual(bereit.problems, [])
|
||||
assert.equal(bereit.subject, 'Wert-funktion_dein ist bereit')
|
||||
for (const part of ['✓ Wert-funktion', 'Wert-funktion_nom ist auf Deiner Website eingebaut und freigeschaltet. Wert-bereit', 'Wert-knopf: Wert-portal_url']) {
|
||||
assert.ok(bereit.text.includes(part), `K16 enthält: ${part}\n---\n${bereit.text}`)
|
||||
}
|
||||
})
|
||||
|
||||
test('Werte werden HTML-sicher eingesetzt, Zeilenumbrüche werden <br>', () => {
|
||||
const mail = renderMail('T01', { kunde_name: 'Max <b>&"\'', nachricht: 'Zeile 1\nZeile <2>' })
|
||||
assert.match(mail.html, /Max <b>&"' hat im Kundenportal geschrieben/)
|
||||
|
||||
Reference in new issue
Block a user