Hustler-Pixelwelt T10: Keller (Szene mit Arne nach Status, Register-Buch, Akte, Gründe)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-22 08:53:56 +00:00
1 parent ec63e5a43d
commit 1b3fdf5d97
14 files changed
+2247 -312

No files matched your search

+39 -17
View File
@@ -79,26 +79,48 @@ test('pageInfo: Seiten, Blättern und Beschriftung', () => {
assert.deepEqual(pageInfo({}), { pages: 1, hasPrev: false, hasNext: false, label: 'Keine Einträge' })
})
test('BotLeadList.jsx: Links nur aus der Zeilen-Ableitung, extern mit rel noopener, kein HTML-Einschub, Knöpfe mit type="button"', () => {
const src = read('src/components/workers/BotLeadList.jsx')
assert.match(src, /botleadRow\(/)
assert.match(src, /rel="noopener noreferrer"/); assert.match(src, /target="_blank"/)
// jeder href kommt aus row.sourceHref (botleadRow → safeHref), nie aus dem Eintrag selbst
assert.match(src, /href=\{row\.sourceHref\}/)
assert.doesNotMatch(src, /\bhref=\{(?!row\.sourceHref\})/)
assert.doesNotMatch(src, /\bhref="/)
assert.doesNotMatch(src, /dangerouslySetInnerHTML|innerHTML/)
// Quelltext des Kellers (BotLeadList.jsx und keller/*, Hustler-Pixelwelt T10): die Zeilen-Ableitung steckt in src/lib/hustlerKeller.js (eintragModell → botleadRow),
// Links gibt es nur in der Akte. UMGESTELLT gegenüber der alten Tabelle: die Prüfungen laufen über alle Dateien des Kellers statt über BotLeadList.jsx allein.
const KELLER_DATEIEN = [
'src/components/workers/BotLeadList.jsx',
'src/components/workers/keller/KellerSzene.jsx',
'src/components/workers/keller/RegisterBuch.jsx',
'src/components/workers/keller/Akte.jsx',
]
// Quelltext ohne Kommentare (die Kommentare nennen auch, was es nicht gibt, etwa „kein innerHTML“)
const ohneKommentare = (src) => src.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|\s)\/\/.*$/gm, '$1')
test('Keller: Links nur aus der Zeilen-Ableitung, extern mit rel noopener, kein HTML-Einschub, Knöpfe mit type="button"', () => {
const quellen = KELLER_DATEIEN.map((p) => ({ p, src: ohneKommentare(read(p)) }))
const alle = quellen.map((q) => q.src).join('\n')
// die Ableitung läuft über botleadRow (safeHref für die Quelle, Telefonregel, Datum)
assert.match(ohneKommentare(read('src/components/workers/BotLeadList.jsx')), /eintragModell\(/)
assert.match(read('src/lib/hustlerKeller.js'), /botleadRow\(/)
// genau ein Link im ganzen Keller: die Quelle in der Akte, extern in neuem Tab ohne Rückbezug
const akte = ohneKommentare(read('src/components/workers/keller/Akte.jsx'))
assert.match(akte, /rel="noopener noreferrer"/); assert.match(akte, /target="_blank"/)
// jeder href kommt aus e.sourceHref (eintragModell → botleadRow → safeHref), nie aus dem Eintrag selbst
assert.match(akte, /href=\{e\.sourceHref\}/)
assert.equal((alle.match(/\bhref=/g) || []).length, 1)
assert.doesNotMatch(alle, /\bhref=\{(?!e\.sourceHref\})/)
assert.doesNotMatch(alle, /\bhref="/)
assert.equal((alle.match(/<a\b/g) || []).length, 1)
assert.doesNotMatch(alle, /dangerouslySetInnerHTML|innerHTML/)
// kein Anruf-Link, kein Mailversand
assert.doesNotMatch(src, /tel:|mailto:/)
assert.doesNotMatch(alle, /tel:|mailto:/)
// WOMS-Button hat keinen Standard-type: jeder Knopf nennt ihn
assert.equal((src.match(/<(?:button|Button)\b/g) || []).length > 0, true)
assert.equal((src.match(/<(?:button|Button)\b/g) || []).length, (src.match(/<(?:button|Button)\b[^>]*type="button"/g) || []).length)
for (const { p, src } of quellen) {
assert.equal((src.match(/<(?:button|Button)\b/g) || []).length, (src.match(/<(?:button|Button)\b[^>]*type="button"/g) || []).length, p)
}
assert.ok((alle.match(/<button\b/g) || []).length > 0)
// kein Polling
assert.doesNotMatch(src, /setInterval/)
assert.doesNotMatch(alle, /setInterval/)
})
test('BotLeadList.jsx: Zeilen ohne Kennung teilen sich keinen key (Ausweichwert aus der Position), aria-current nur in der Einzelansicht', () => {
const src = read('src/components/workers/BotLeadList.jsx')
assert.match(src, /key=\{row\.id \|\| /)
assert.match(src, /aria-current=\{single && row\.id === botId \?/)
test('Keller: Zeilen ohne Kennung teilen sich keinen key (Ausweichwert aus der Position), aria-current nur in der Einzelansicht', () => {
const src = ohneKommentare(read('src/components/workers/keller/RegisterBuch.jsx'))
assert.match(src, /key=\{z\.id \|\| /)
assert.match(src, /aktuell=\{einzeln && z\.id === botId\}/)
assert.match(src, /aria-current=\{aktuell \? 'true' : undefined\}/)
})