Files
Webklar-Kundenbereich/test/kundenansichtEntscheidungen.test.js
T
ClaudeandClaude Opus 5.5 b1a582cb20 Datenschutz: neue Fassung vom 29.10.2026 zum Umschalten der Kundenansicht (R14)
Prüfpunkte D1 bis D8 der Rechtsrunde umgesetzt: Kundenart im Kundenkonto
(D3), Nachweis beim Einschalten einer Funktion ohne Zahlung (D1, D4),
Wortlaut und Kundenart im Nachweis bei Abo, Wechsel, Zusatzspeicher (D2)
und Übernahmegutschrift, Website-Analyse im Hosting- und Wartungs-Abo
(D5), Ende und Löschfristen der Funktionen im Abo-Modell (D6), Vorschuss
im Stundenkonto (D7). Neu Abschnitt 6e Öffnungszeiten live, auf den die
Leistungsbeschreibung Fassung 6 verweist. Der Bestand einzeln gekaufter
Funktionen bleibt beschrieben. PDF neu gedruckt, Pins nachgezogen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 13:27:32 +00:00

46 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
// Entscheidungsliste, Kanzlei-Fragen, Ablauf nach der Freigabe und Datenschutz-Prüfpunkte der Rechtsrunde Fassung 6 (Task 11).
const lies = (rel) => readFileSync(new URL(`../${rel}`, import.meta.url), 'utf8')
const ENTWURF = false
const md = lies('docs/rechtliches/kundenansicht-entscheidungen.md'), dsg = lies('docs/rechtliches/datenschutz-kundenansicht-pruefpunkte.md')
test('Entscheidungsliste: R1 bis R18, je Punkt Vorschlag, Alternative und Kanzlei-Frage', () => {
const z = md.split('\n').filter((l) => /^\| R\d+ \|/.test(l)).map((l) => l.split('|').slice(1, -1).map((s) => s.trim()))
assert.deepEqual(z.map((r) => r[0]), Array.from({ length: 18 }, (_, i) => `R${i + 1}`))
for (const r of z) { assert.equal(r.length, 5); assert.ok(r.every(Boolean), r[0]); assert.match(r[4], /^(–|KQ\d+(, KQ\d+)*)$/, r[0]) }
const kq = [...md.matchAll(/^### (KQ\d+): .+$/gm)].map((m) => m[1])
assert.deepEqual(kq, Array.from({ length: 9 }, (_, i) => `KQ${i + 1}`))
for (const r of z) for (const id of r[4].match(/KQ\d+/g) ?? []) assert.ok(kq.includes(id), `${r[0]} nennt ${id}`)
assert.equal(md.includes('Entwurf zur Freigabe, keine Rechtsberatung'), ENTWURF)
})
test('R8 ist mit P4/P6 abgestimmt: Zeiten laufen 30 Tage weiter, die übrigen schalten am Folgetag ab, kein Behalten', () => {
const [, punkt, vorschlag, alternative] = md.split('\n').find((l) => l.startsWith('| R8 |')).split('|').slice(1, -1).map((s) => s.trim())
assert.match(punkt, /mit P4\/P6 abgestimmt/)
for (const s of ['spätestens am Folgetag', 'Öffnungszeiten live läuft nach dem Ende noch 30 Tage unverändert weiter', 'kein Behalten']) assert.ok(vorschlag.includes(s), s)
assert.doesNotMatch(vorschlag, /Karenz|entfällt/)
assert.ok(alternative.includes('Öffnungszeiten live schalten wie die übrigen spätestens am Folgetag ab'))
})
test('Kanzlei-Fragen haben vier Teile', () => {
for (const teil of md.split(/\n(?=### KQ\d+:)/).slice(1)) for (const k of ['**Frage.**', '**Fundstelle im Text.**', '**Unsere Annahme.**', '**Alternative.**']) assert.ok(teil.includes(k), `${teil.slice(0, 8)} ${k}`)
})
test('AVV-Struktur nennt A, B und C; Ablauf nach der Freigabe in fester Reihenfolge mit Schutzbefehlen', () => {
const avv = md.slice(md.indexOf('## AVV-Struktur'), md.indexOf('## Ablauf nach der Freigabe'))
for (const s of ['Option A', 'Option B', 'Option C', 'Anlage 1']) assert.ok(avv.includes(s), s)
const a = md.slice(md.indexOf('## Ablauf nach der Freigabe'))
const reihenfolge = ['Freigabe des Inhabers', 'ENTWURF = false', 'scripts/build-legal-html.mjs funktionen6', 'free -m', 'nice -n 10 scripts/build-legal-pdfs.sh abo6', 'nice -n 10 scripts/build-legal-pdfs.sh funktionen6', 'rechtliches-hochladen.mjs --probe', '--karten-anlegen', 'ein Aufruf je Dokument', '--freigabe=', '--pruefen']
const pos = reihenfolge.map((s) => { const i = a.indexOf(s); assert.ok(i >= 0, s); return i })
assert.deepEqual([...pos].sort((x, y) => x - y), pos, 'Reihenfolge')
assert.ok(a.includes('Datum der Fassungen') && a.includes('Entwurfsmarke'), 'Datum setzen und Marken entfernen')
})
test('Datenschutz-Prüfpunkte D1 bis D8 mit gültiger Fundstelle in public/datenschutz.html', () => {
assert.deepEqual([...dsg.matchAll(/^\*\*(D\d)\*\*/gm)].map((m) => m[1]), ['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8'])
const zeilen = lies('public/datenschutz.html').split('\n')
const refs = [...dsg.matchAll(/public\/datenschutz\.html:(\d+)/g)].map((m) => Number(m[1]))
assert.ok(refs.length >= 8 && refs.every((n) => n >= 1 && n <= zeilen.length))
// Die Zeilen der Prüfpunkte gelten für die Fassung vom 22.10.2026; seit der Fassung vom 29.10.2026 (Umschalten, R14) sind Absätze dazugekommen, darum sucht der Test die Stellen nach Inhalt
const zeile = (text) => zeilen.find((z) => z.includes(text)) ?? ''
assert.ok(zeile('Zahlungspflichtig bestellen').includes('Stripe-Sitzung') && zeile('Leistungsbeginn').includes('Browserkennung') && zeile('Sobald diese Funktion freigeschaltet').includes('Wartungs-Abo'), 'D1, D2, D5 zitieren die richtigen Stellen')
})