Gästetexte des Terminplaners: Fassung 2026-10-05, Erinnerungs- und Abo-Ende-Satz, Archiv je Fassung
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1a91a331b4
commit
c1266fcce7
11 files changed
+313
-33
No files matched your search
@@ -22,7 +22,7 @@ const aw = await startAppwriteMock({
|
||||
useTestEnv({ appwriteUrl: aw.url, stripeUrl: 'http://127.0.0.1:1' })
|
||||
|
||||
const { config } = await import('../server/config.js')
|
||||
const { deleteDocument } = await import('../server/services/appwriteAdmin.js')
|
||||
const { deleteDocument, updateDocument } = await import('../server/services/appwriteAdmin.js')
|
||||
const { setMailTransportForTests } = await import('../server/services/mailer.js')
|
||||
const { startTestApp, send } = await import('./support/testApp.js')
|
||||
const { kundenansichtCookie } = await import('./support/fixtures.js')
|
||||
@@ -32,7 +32,7 @@ const { resetOutboxForTests, warteAufVersand } = await import('../server/service
|
||||
const { buchungsNummer, formToken, pruefeFormToken, verwaltungsToken } = await import('../server/services/termine/token.js')
|
||||
const { speichereEinstellung, resetKontextForTests } = await import('../server/services/termine/kontext.js')
|
||||
const { resetTermineLimitsForTests, darfHaltung } = await import('../server/services/termine/limits.js')
|
||||
const { ZUSTIMMUNG_STORNO, ZUSTIMMUNG_ERINNERUNG, ZUSTIMMUNG_VORZEITIG, GESUNDHEIT_HINWEIS, formularHinweis, widerrufsbelehrung } = await import(
|
||||
const { RECHTSTEXTE_VERSION, ZUSTIMMUNG_STORNO, ZUSTIMMUNG_ERINNERUNG, ZUSTIMMUNG_VORZEITIG, GESUNDHEIT_HINWEIS, formularHinweis, widerrufsbelehrung } = await import(
|
||||
'../server/services/termine/rechtstexte.js'
|
||||
)
|
||||
const { halte } = await import('../server/services/termine/ablauf.js')
|
||||
@@ -274,6 +274,8 @@ test('config: Betriebsdaten, Leistungen, Regeln, Texte und Formular-Token; keine
|
||||
gesundheit: GESUNDHEIT_HINWEIS,
|
||||
widerrufsbelehrung: widerrufsbelehrung(ctx.einstellung.betrieb),
|
||||
})
|
||||
// Haken Erinnerung: Wortlaut der Fassung mit dem Widerrufssatz (Art. 7 Abs. 3 DSGVO), wörtlich in der öffentlichen Konfiguration
|
||||
assert.equal(c.texte.erinnerung, 'Ich möchte 24 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.')
|
||||
assert.equal(pruefeFormToken(SITE_KEY, c.formToken, plus(JETZT, 10000)), 'ok')
|
||||
assert.equal(pruefeFormToken('bcdefghijklmnopq', c.formToken, plus(JETZT, 10000)), 'ungueltig', 'das Token gilt nur fuer diesen siteKey')
|
||||
|
||||
@@ -564,6 +566,36 @@ test('Buchung: 201 mit maskierter Adresse und Haltezeit; Buchung gehalten, Mail
|
||||
assert.ok(!JSON.stringify(res.body).includes(b.$id))
|
||||
})
|
||||
|
||||
test('nachweis_fassung: eine neue Buchung trägt die aktuelle Fassung der Gästetexte, eine Altbuchung behält 2026-10-02 (der Nachweis wird nie umgeschrieben)', async () => {
|
||||
await speichere()
|
||||
const { id: neu, verwaltung } = await gebucht({ erinnerung: true, zustimmungen: { storno: true, vorzeitig: false } })
|
||||
const nachweisNeu = JSON.parse(aw.docs('termineBookings').get(neu).nachweis)
|
||||
assert.equal(nachweisNeu.fassung, RECHTSTEXTE_VERSION)
|
||||
assert.notEqual(nachweisNeu.fassung, '2026-10-02')
|
||||
assert.equal(nachweisNeu.erinnerung.hash.length, 64)
|
||||
|
||||
// Altbuchung: Nachweis der Fassung 2026-10-02; Bestätigen, Verschieben und Absagen schreiben den Nachweis nicht um
|
||||
const alt = await buchen({ email: 'alt@example.com', zeit: '11:00', ressource: R1 })
|
||||
assert.equal(alt.status, 201)
|
||||
await warteAufVersand()
|
||||
const buchungAlt = buchungen().find((b) => b.gastEmail === 'alt@example.com')
|
||||
const nachweisAlt = JSON.stringify({ ...JSON.parse(buchungAlt.nachweis), fassung: '2026-10-02' })
|
||||
await updateDocument('termineBookings', buchungAlt.$id, { nachweis: nachweisAlt })
|
||||
const vToken = tokenAusMail(mailsAn('alt@example.com')[0], 'v')
|
||||
assert.equal((await tokenAnruf('bestaetigen', { token: vToken })).status, 200)
|
||||
await warteAufVersand()
|
||||
const mToken = tokenAusMail(mailsAn('alt@example.com').find((m) => /#m=/.test(m.text)), 'm')
|
||||
assert.equal((await tokenAnruf('verschieben', { token: mToken, tag: TAG_FERN, zeit: '11:30' })).status, 200)
|
||||
assert.equal((await tokenAnruf('absagen', { token: mToken })).status, 200)
|
||||
const danach = aw.docs('termineBookings').get(buchungAlt.$id)
|
||||
assert.equal(danach.status, 'abgesagt')
|
||||
assert.equal(danach.nachweis, nachweisAlt, 'der Nachweis der Altbuchung bleibt byte-gleich')
|
||||
assert.equal(JSON.parse(danach.nachweis).fassung, '2026-10-02')
|
||||
// die neue Buchung ist davon unberührt
|
||||
assert.equal(JSON.parse(aw.docs('termineBookings').get(neu).nachweis).fassung, RECHTSTEXTE_VERSION)
|
||||
assert.ok(verwaltung)
|
||||
})
|
||||
|
||||
test('zu viele offene Termine: dieselbe 201-Antwort, keine neue Buchung, statt der Bestaetigung geht G01 "zu viele"', async () => {
|
||||
await speichere()
|
||||
// drei bestaetigte Termine belegen die drei offenen Plaetze; die Kappe der Adresse (3 Mails je Stunde) ist damit ausgeschoepft,
|
||||
|
||||
@@ -55,8 +55,11 @@ function fristBaustein() {
|
||||
|
||||
const belehrung = (betrieb = BETRIEB) => widerrufsbelehrung(betrieb)
|
||||
|
||||
test('Fassung der Rechtstexte', () => {
|
||||
assert.equal(RECHTSTEXTE_VERSION, '2026-10-02')
|
||||
test('version_gleich_register: RECHTSTEXTE_VERSION ist das Fassungsdatum des Registers und nicht mehr die Altfassung 2026-10-02', () => {
|
||||
assert.equal(RECHTSTEXTE_VERSION, config.termine.avvVersion)
|
||||
assert.notEqual(RECHTSTEXTE_VERSION, '2026-10-02')
|
||||
assert.match(RECHTSTEXTE_VERSION, /^\d{4}-\d{2}-\d{2}$/)
|
||||
assert.ok(RECHTSTEXTE_VERSION > '2026-10-02', 'die Fassung liegt nach der eingefrorenen Altfassung')
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------- Widerrufsbelehrung
|
||||
@@ -177,8 +180,8 @@ test('Zustimmungstexte wortgleich zu den Vorgaben (Sie-Form)', () => {
|
||||
+ 'Widerrufe ich vor der vollständigen Erbringung, schulde ich einen angemessenen Betrag für die bis dahin erbrachte Leistung (§ 357a Abs. 2 BGB).',
|
||||
)
|
||||
assert.equal(ZUSTIMMUNG_STORNO, 'Ich habe die Stornobedingungen gelesen.')
|
||||
assert.equal(ZUSTIMMUNG_ERINNERUNG(24), 'Ich möchte 24 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten.')
|
||||
assert.equal(ZUSTIMMUNG_ERINNERUNG(2), 'Ich möchte 2 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten.')
|
||||
assert.equal(ZUSTIMMUNG_ERINNERUNG(24), 'Ich möchte 24 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.')
|
||||
assert.equal(ZUSTIMMUNG_ERINNERUNG(2), 'Ich möchte 2 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.')
|
||||
assert.equal(GESUNDHEIT_HINWEIS, 'Bitte keine Gesundheitsangaben.')
|
||||
})
|
||||
|
||||
@@ -187,6 +190,23 @@ test('Zustimmung zum vorzeitigen Beginn setzt den Betriebsnamen unverändert ein
|
||||
assert.ok(text.startsWith("Ich verlange ausdrücklich, dass Frisör $& $1 'Anna' mit der Leistung vor Ablauf"))
|
||||
})
|
||||
|
||||
test('erinnerung_widerrufssatz: Haken-Text, Hinweise-Dokument wörtlich gleich; der Haken trägt den Widerrufssatz (Art. 7 Abs. 3 DSGVO)', () => {
|
||||
const satz = (n) => `Ich möchte ${n} Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.`
|
||||
for (const n of [2, 12, 24, 48]) assert.equal(ZUSTIMMUNG_ERINNERUNG(n), satz(n))
|
||||
const md = lies('docs/rechtliches/termine-hinweise.md').replace(/\r/g, '')
|
||||
assert.ok(md.includes(satz('{{n}}')), 'Hinweise-Dokument: Haken Erinnerung weicht ab')
|
||||
assert.ok(md.includes(ZUSTIMMUNG_ERINNERUNG('{{n}}')))
|
||||
assert.ok(!md.includes('Erinnerung per E-Mail erhalten. |'), 'der alte Haken ohne Widerrufssatz steht nicht mehr im Dokument')
|
||||
assert.equal(ZUSTIMMUNG_ERINNERUNG(24).split('\n').length, 1, 'ein Satz im Haken, keine Umbrüche')
|
||||
})
|
||||
|
||||
test('dokumente_nennen_fassung: die drei Gäste-Dokumente tragen die Fassung der Gästetexte', () => {
|
||||
for (const rel of ['docs/rechtliches/termine-hinweise.md', 'docs/rechtliches/termine-datenschutz-absatz.md', 'docs/rechtliches/termine-widerrufsbelehrung-muster.md']) {
|
||||
assert.ok(lies(rel).includes(`Fassung ${RECHTSTEXTE_VERSION}.`), `${rel} nennt nicht „Fassung ${RECHTSTEXTE_VERSION}.“`)
|
||||
assert.ok(!lies(rel).includes('Fassung 2026-10-02.'), `${rel} trägt noch die Altfassung`)
|
||||
}
|
||||
})
|
||||
|
||||
const EINSTELLUNG = { anrede: 'sie', aufbewahrungTage: 90, betrieb: BETRIEB }
|
||||
|
||||
test('Formular-Hinweis (Sie): Zweck, Auftragsverarbeiter, Löschfristen, keine Cookies, Gesundheit, Verantwortlicher', () => {
|
||||
@@ -271,8 +291,8 @@ const normalisiere = (text) => text.split(/\n[ \t]*\n/).map((a) => a.replace(/\s
|
||||
/**
|
||||
* Datenschutz-Absatz aus der Markdown-Quelle: Blockquote der Fassung („Sie“ | „Du“), `> `, `**` und `###` entfernt,
|
||||
* [[wenn …: X]] durch X (Schalter an) oder nichts (Schalter aus) ersetzt, Platzhalter mit den Testwerten gefüllt.
|
||||
* Ein Satzteil, der mit einem Wort beginnt („und die Angaben …“), steht in der Quelle ohne Leerzeichen am Vordertext
|
||||
* („Platz[[…: und die Angaben …]]“); er wird hier mit Leerzeichen angefügt (Satzteile mit Komma bleiben unmittelbar dran).
|
||||
* Ein Satzteil, der mit einem Wort beginnt („und die Angaben …“), trägt sein Leerzeichen selbst in der Klammer (zwei Leerzeichen
|
||||
* nach dem Doppelpunkt); die Ersetzung fügt nichts hinzu.
|
||||
*/
|
||||
function datenschutzQuelle(fassung, zustand, { tage = 90 } = {}) {
|
||||
const md = lies('docs/rechtliches/termine-datenschutz-absatz.md').replace(/\r/g, '')
|
||||
@@ -281,11 +301,10 @@ function datenschutzQuelle(fassung, zustand, { tage = 90 } = {}) {
|
||||
const zitat = teil.split('\n').filter((z) => z.startsWith('>')).map((z) => z.replace(/^>\s?/, '').replace(/^### /, ''))
|
||||
assert.ok(zitat.length > 10, 'Blockquote der Quelle nicht gefunden')
|
||||
const roh = zitat.join('\n').replace(/\*\*/g, '')
|
||||
const bedingt = roh.replace(/\[\[wenn ([^:]+): ([\s\S]*?)\]\]/g, (_, bedingung, satz, offset, ganz) => {
|
||||
const bedingt = roh.replace(/\[\[wenn ([^:]+): ([\s\S]*?)\]\]/g, (_, bedingung, satz) => {
|
||||
const eintrag = DS_BEDINGUNGEN.find(([muster]) => muster.test(bedingung))
|
||||
assert.ok(eintrag, `unbekannte Bedingung in der Quelle: ${bedingung}`)
|
||||
if (!zustand[eintrag[1]]) return ''
|
||||
return /^[A-Za-zÄÖÜäöüß]/.test(satz) && offset > 0 && !/\s/.test(ganz[offset - 1]) ? ` ${satz}` : satz
|
||||
return zustand[eintrag[1]] ? satz : ''
|
||||
})
|
||||
const werte = { Firma: BETRIEB.name, Anschrift: BETRIEB.adresse, 'E-Mail': BETRIEB.email, Telefon: BETRIEB.telefon, Tage: String(tage) }
|
||||
const gefuellt = bedingt.replace(/\{\{([^}]+)\}\}/g, (_, name) => {
|
||||
@@ -364,6 +383,63 @@ test('Datenschutz-Absatz: die Bedingungen lesen die Einstellung wie das Widget',
|
||||
assert.ok(text({ ...alleAn, betrieb: { ...BETRIEB, telefon: ' 06301\n1234 ' } }).includes('telefonisch erreichen: 06301 1234.'))
|
||||
})
|
||||
|
||||
const ABO_ENDE_SATZ = 'Wird die Online-Terminbuchung abgeschaltet, zum Beispiel weil unser Vertrag mit WEBklar endet, werden alle Termindaten 30 Tage nach dem Abschalten gelöscht.'
|
||||
|
||||
test('absatz_abo_ende: Funktion und Markdown (Sie und Du) nennen den Abo-Ende-Satz mit „30 Tage nach dem Abschalten“; der alte Satz ist weg', () => {
|
||||
const md = lies('docs/rechtliches/termine-datenschutz-absatz.md').replace(/\r/g, '')
|
||||
const fassungen = md.split(/^## Fassung /m).slice(1)
|
||||
assert.equal(fassungen.length, 2)
|
||||
for (const f of fassungen) {
|
||||
assert.ok(normalisiere(f.replace(/^> ?/gm, '')).includes(ABO_ENDE_SATZ), 'Markdown: Abo-Ende-Satz fehlt')
|
||||
assert.ok(f.includes('30 Tage nach dem Abschalten'))
|
||||
assert.ok(!f.includes('löschen wir alle Termindaten 30 Tage'), 'Markdown: alter Satz steht noch')
|
||||
}
|
||||
for (const anrede of ['sie', 'du']) {
|
||||
for (const zustand of [DS_ALLE_AN, DS_ALLE_AUS]) {
|
||||
const text = datenschutzAbsatz(dsEinstellung(zustand), anrede)
|
||||
assert.equal(text.split(ABO_ENDE_SATZ).length, 2, `${anrede}: Satz genau einmal`)
|
||||
assert.ok(text.includes('30 Tage nach dem Abschalten'))
|
||||
assert.ok(!text.includes('löschen wir alle Termindaten'), `${anrede}: alter Satz steht noch`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('haltezeit_aus_config: „der Bestätigungslink gilt N Minuten“ folgt config.termine.holdMinutes; die Markdown-Quelle nennt denselben Wert', () => {
|
||||
const md = lies('docs/rechtliches/termine-datenschutz-absatz.md')
|
||||
for (const anrede of ['sie', 'du']) {
|
||||
assert.ok(datenschutzAbsatz(dsEinstellung(DS_ALLE_AN), anrede).includes(`(der Bestätigungslink gilt ${config.termine.holdMinutes} Minuten)`))
|
||||
}
|
||||
assert.equal((md.match(new RegExp(`Bestätigungslink gilt ${config.termine.holdMinutes} Minuten`, 'g')) || []).length, 2, 'die Quelle nennt beide Fassungen mit dem Wert aus config')
|
||||
const vorher = config.termine.holdMinutes
|
||||
try {
|
||||
config.termine.holdMinutes = 45
|
||||
for (const anrede of ['sie', 'du']) {
|
||||
const text = datenschutzAbsatz(dsEinstellung(DS_ALLE_AN), anrede)
|
||||
assert.ok(text.includes('(der Bestätigungslink gilt 45 Minuten)'), anrede)
|
||||
assert.ok(!text.includes('30 Minuten'), `${anrede}: kein fester Wert mehr im Text`)
|
||||
}
|
||||
} finally {
|
||||
config.termine.holdMinutes = vorher
|
||||
}
|
||||
})
|
||||
|
||||
test('quelle_satzteile_mit_leerzeichen: ein Satzteil der Quelle, der mit einem Wort beginnt, trägt sein Leerzeichen in der Klammer', () => {
|
||||
const md = lies('docs/rechtliches/termine-datenschutz-absatz.md').replace(/\r/g, '')
|
||||
let mitLeerzeichen = 0
|
||||
for (const m of md.matchAll(/\[\[wenn ([^:]+): ([\s\S]*?)\]\]/g)) {
|
||||
if (m[1] === '…') continue // die Erklärung der Schreibweise im Kopf der Quelle
|
||||
const davor = md[m.index - 1]
|
||||
if (/^[A-Za-zÄÖÜäöüß]/.test(m[2])) {
|
||||
// Satzteil beginnt mit einem Wort: nur nach Leerzeichen erlaubt (Satzanfang), sonst klebte er am Vordertext („Platzund“)
|
||||
assert.ok(/\s/.test(davor), `Satzteil „${m[2].slice(0, 30)}…“ hängt ohne Leerzeichen am Vordertext`)
|
||||
} else if (m[2].startsWith(' ')) {
|
||||
mitLeerzeichen += 1
|
||||
assert.ok(/^ [A-Za-zÄÖÜäöüß]/.test(m[2]) && !/\s/.test(davor), `Leerzeichen in der Klammer nur am Anschluss an ein Wort: „${m[2].slice(0, 30)}…“`)
|
||||
}
|
||||
}
|
||||
assert.equal(mitLeerzeichen, 4, 'vier Satzteile mit „und“ tragen ihr Leerzeichen selbst (Sie und Du, je zwei)')
|
||||
})
|
||||
|
||||
test('Datenschutz-Absatz: Aufbewahrung nach dem Termin, ungültiger Wert wird zu 90 Tagen (wie der Formular-Hinweis)', () => {
|
||||
for (const anrede of ['sie', 'du']) {
|
||||
const mit = (aufbewahrungTage) => datenschutzAbsatz(dsEinstellung(DS_ALLE_AN, { aufbewahrungTage }), anrede)
|
||||
|
||||
@@ -88,6 +88,10 @@ test('archiv_inhalt: alle Gästetexte stehen wörtlich im Archiv, die Betriebsan
|
||||
assert.ok(text.includes('Auf unserer Website kannst du Termine online buchen.'))
|
||||
assert.ok(text.includes('Vertrag widerrufen'))
|
||||
assert.ok(text.includes('Wenn Sie eine Erinnerung vor dem Termin wünschen'))
|
||||
// Fassung 2026-10-05: Widerrufssatz am Erinnerungshaken und Abo-Ende-Satz im Datenschutz-Absatz (Sie und Du)
|
||||
assert.ok(text.includes('> Ich möchte {{Stunden}} Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.\n'))
|
||||
assert.equal(text.split('zum Beispiel weil unser Vertrag mit WEBklar endet, werden alle Termindaten 30 Tage nach dem Abschalten gelöscht.').length, 3, 'Abo-Ende-Satz in Sie- und Du-Fassung')
|
||||
assert.ok(!text.includes('löschen wir alle Termindaten 30 Tage'))
|
||||
// Nachweis-Hinweis (⚖ Q26)
|
||||
assert.ok(text.includes('Der Nachweis speichert Hashes der Texte mit den Betriebsangaben zum Buchungszeitpunkt (⚖ Q26).'))
|
||||
// kein Rest, keine echten Betriebsdaten
|
||||
@@ -96,9 +100,22 @@ test('archiv_inhalt: alle Gästetexte stehen wörtlich im Archiv, die Betriebsan
|
||||
assert.ok(text.endsWith('\n') && !text.endsWith('\n\n'))
|
||||
})
|
||||
|
||||
|
||||
// SHA-256 der eingefrorenen Datei der Fassung 2026-10-02 (aus den unveränderten Texten erzeugt, vor jeder Textänderung eingecheckt)
|
||||
const HASH_2026_10_02 = '920633e2e23c9c98aded0c1509db5cac1465058a025aeddc76a9a1282041a6a9'
|
||||
|
||||
// SHA-256 der Archivdatei der aktuellen Fassung: ändert sich ein Gästetext, ohne dass die Fassung (RECHTSTEXTE_VERSION) ein neues Datum
|
||||
// und diese Datei eine neue Archivdatei bekommt, schlägt der Test an. Bei einer neuen Fassung: neue Datei, neues Datum, neuer Pin.
|
||||
const HASH_AKTUELL = { '2026-10-05': '6bcad4c4a02ea5e39b3ec690d40617fdfb3cb1290aadd3304f0ecabab14c4a59' }
|
||||
|
||||
test('textstand_pin: Hash der aktuellen Archivdatei ist festgenagelt (Textänderung ohne neues Datum fällt auf)', () => {
|
||||
assert.ok(Object.hasOwn(HASH_AKTUELL, RECHTSTEXTE_VERSION), `kein Hash-Pin für die Fassung ${RECHTSTEXTE_VERSION}`)
|
||||
const datei = lies(archivPfad())
|
||||
assert.equal(sha256(datei), HASH_AKTUELL[RECHTSTEXTE_VERSION], 'Gästetext geändert, aber die Fassung ist dieselbe: neues Datum, neue Archivdatei und neuer Pin nötig')
|
||||
assert.equal(sha256(baueArchiv()), HASH_AKTUELL[RECHTSTEXTE_VERSION])
|
||||
assert.notEqual(HASH_AKTUELL[RECHTSTEXTE_VERSION], HASH_2026_10_02, 'die neue Fassung unterscheidet sich von der eingefrorenen')
|
||||
})
|
||||
|
||||
test('archiv_altfassung_eingefroren: Datei 2026-10-02 hat den alten Erinnerungstext ohne den Widerrufssatz; ihr Hash ist festgenagelt', () => {
|
||||
const alt = lies(`${ARCHIV_DIR}/termine-gaestetexte-2026-10-02.md`)
|
||||
assert.ok(alt.startsWith('# Gästetexte des Terminplaners, Fassung 2026-10-02\n'))
|
||||
|
||||
@@ -447,7 +447,7 @@ test('avv_gleich_datenschutz_absatz: Fristen und Orte stimmen mit dem Datenschut
|
||||
assert.ok(absatz.includes('löschen wir 48 Stunden nach Ablauf dieser Frist'))
|
||||
assert.ok(absatz.includes(`Bestätigte Termine löschen wir ${einstellung.aufbewahrungTage} Tage nach dem Termin`))
|
||||
assert.ok(absatz.includes('abgesagte oder abgelehnte Termine 30 Tage nach der Absage oder Ablehnung'))
|
||||
assert.ok(absatz.includes(`löschen wir alle Termindaten ${LOESCHFRIST_TAGE} Tage nach dem Abschalten`))
|
||||
assert.ok(absatz.includes(`zum Beispiel weil unser Vertrag mit WEBklar endet, werden alle Termindaten ${LOESCHFRIST_TAGE} Tage nach dem Abschalten gelöscht`))
|
||||
assert.ok(absatz.includes('nicht zustellbare E-Mails nach 48 Stunden'))
|
||||
assert.ok(absatz.includes('Rechenzentren Falkenstein und Nürnberg') && absatz.includes('Eine Übermittlung in Drittländer findet nicht statt.'))
|
||||
assert.ok(absatz.includes('Der Server speichert sie kurzzeitig in Protokollen und löscht sie nach 14 Tagen'))
|
||||
|
||||
@@ -182,7 +182,7 @@ async function pruefungen() {
|
||||
// Haken: Storno und vorzeitiger Beginn Pflicht (12.10. liegt in der Widerrufsfrist), Erinnerung freiwillig und nicht vorangekreuzt
|
||||
eq(await wd.locator('label[for$="h-storno"]').innerText(), 'Ich habe die Stornobedingungen gelesen.', 'Haken Storno')
|
||||
assert((await wd.locator('label[for$="h-vorzeitig"]').innerText()).startsWith('Ich verlange ausdrücklich, dass Salon Müller mit der Leistung vor Ablauf der Widerrufsfrist beginnt.'), 'Haken vorzeitig')
|
||||
eq(await wd.locator('label[for$="h-erinnerung"]').innerText(), 'Ich möchte 24 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten.', 'Haken Erinnerung')
|
||||
eq(await wd.locator('label[for$="h-erinnerung"]').innerText(), 'Ich möchte 24 Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.', 'Haken Erinnerung')
|
||||
assert(!(await wd.locator('input[name=erinnerung]').isChecked()), 'Erinnerung darf nicht vorangekreuzt sein')
|
||||
assert(await wd.locator('input[name=storno]').getAttribute('required') !== null && await wd.locator('input[name=vorzeitig]').getAttribute('required') !== null, 'Pflicht-Haken')
|
||||
assert(await wd.locator('input[name=erinnerung]').getAttribute('required') === null, 'Erinnerung ist freiwillig')
|
||||
|
||||
Reference in new issue
Block a user