Terminplaner: Portal-Ansicht – Nachbesserungen (1/2: Module getrennt)
public/termine.js in Huelle und Module zerlegt, Verhalten unveraendert (R48): termine-dom.js (Helfer ohne Zustand), termine-tab-termine.js (Liste, Kopf, Zeilen), termine-aktionen.js (Aktionen mit Rueckfrage), termine-formulare.js (Uhrzeiten, Termin eintragen, Zeit sperren). Reiter bekommen Zustand und aktuell() nur ueber ctx; die Huelle haengt sie ueber die Registry REITER ein. Statiktest prueft alle public/termine*.js. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
43e4826ae3
commit
9c07f6a8c5
7 files changed
+697
-645
No files matched your search
+28
-10
@@ -1,6 +1,6 @@
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { readFileSync, readdirSync } from 'node:fs'
|
||||
import {
|
||||
FILTER, ABSAGE_GRUENDE, anfragenText, bereichFuer, datumKurz, datumLang, endeZeit, fensterParsen, fensterText, filterStatus, gruppiereNachTag,
|
||||
fehltText, heuteBerlin, istSperre, monatVon, moeglicheAktionen, ressourcenWort, statusLabel, statusTon, tagPlus, tagUeberschrift, verschiebeTag, wocheVon, zeitNormal, zeitraumTitel,
|
||||
@@ -230,13 +230,31 @@ test('Portal: Ansicht #termine ist verdrahtet, funktionen.js behält seinen eine
|
||||
assert.doesNotMatch(fn, /import\s*\(/, 'auch kein dynamischer Import')
|
||||
})
|
||||
|
||||
test('termine.js: Fremdtext nur als Text, keine Browser-Dialoge, Du-Form', () => {
|
||||
const quelle = lies('public/termine.js').replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|\s)\/\/.*$/gm, '') // ohne Kommentare
|
||||
assert.doesNotMatch(quelle, /innerHTML|insertAdjacentHTML|outerHTML|document\.write/, 'Daten nie als HTML')
|
||||
assert.doesNotMatch(quelle, /\bconfirm\(|\balert\(|\bprompt\(/, 'Rückfragen stehen in der Seite')
|
||||
assert.doesNotMatch(quelle, /\bSie\b|\bIhr(e[nmrs]?)?\b/, 'Portaltexte in der Du-Form')
|
||||
// Links nur auf die eigene Export-Schnittstelle, nie auf Kundentext
|
||||
const hrefs = quelle.match(/href: `[^`]*`/g) || []
|
||||
assert.deepEqual(hrefs, ['href: `/api/termine/export.csv?projectId=${encodeURIComponent(projectId)}`'])
|
||||
assert.doesNotMatch(quelle, /href: [^`]|setAttribute\('href'/, 'sonst kein href')
|
||||
test('Ansicht-Module (public/termine*.js): Fremdtext nur als Text, keine Browser-Dialoge, Du-Form, ein einziger Link', () => {
|
||||
const dateien = readdirSync(new URL('../public/', import.meta.url)).filter((f) => /^termine.*\.js$/.test(f)).sort()
|
||||
assert.deepEqual(dateien, ['termine-aktionen.js', 'termine-dom.js', 'termine-formulare.js', 'termine-tab-termine.js', 'termine-view.js', 'termine.js'])
|
||||
const ohneKommentare = (text) => text.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|\s)\/\/.*$/gm, '')
|
||||
const quellen = dateien.map((f) => [f, ohneKommentare(lies(`public/${f}`))])
|
||||
for (const [datei, quelle] of quellen) {
|
||||
assert.doesNotMatch(quelle, /innerHTML|insertAdjacentHTML|outerHTML|document\.write/, `${datei}: Daten nie als HTML`)
|
||||
assert.doesNotMatch(quelle, /\bconfirm\(|\balert\(|\bprompt\(/, `${datei}: Rückfragen stehen in der Seite`)
|
||||
assert.doesNotMatch(quelle, /\bSie\b|\bIhr(e[nmrs]?)?\b/, `${datei}: Portaltexte in der Du-Form`)
|
||||
assert.doesNotMatch(quelle, /localStorage|sessionStorage|document\.cookie/, `${datei}: kein Browserspeicher`)
|
||||
}
|
||||
// Links nur auf die eigene Export-Schnittstelle (exportUrl), nie auf Kundentext
|
||||
const hrefs = quellen.flatMap(([datei, quelle]) => (quelle.match(/href: [^,}]+|setAttribute\('href'/g) || []).map((m) => `${datei}: ${m}`))
|
||||
assert.deepEqual(hrefs, ['termine.js: href: exportUrl(projectId)'])
|
||||
const dom = quellen.find(([f]) => f === 'termine-dom.js')[1]
|
||||
assert.ok(dom.includes('`/api/termine/export.csv?projectId=${encodeURIComponent(projectId)}`'), 'exportUrl codiert die Projekt-ID')
|
||||
})
|
||||
|
||||
test('Ansicht-Module: Reiter sind Module mit render(panel, ctx), die Huelle kennt sie nur ueber REITER', () => {
|
||||
const huelle = lies('public/termine.js')
|
||||
assert.match(huelle, /import \{ render as renderTermine \} from '\.\/termine-tab-termine\.js'/)
|
||||
assert.match(huelle, /const REITER = \[/)
|
||||
assert.match(lies('public/termine-tab-termine.js'), /export function render\(panel, ctx\)/)
|
||||
// Reiter lesen Zustand nur aus ctx, nicht aus der Huelle
|
||||
for (const datei of ['termine-tab-termine.js', 'termine-aktionen.js', 'termine-formulare.js']) {
|
||||
assert.doesNotMatch(lies(`public/${datei}`), /from '\.\/termine\.js'/, `${datei} importiert die Huelle nicht`)
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user