Files
Webklar-Kundenbereich/test/knAnsichtWebsiteDetails.test.js
T

73 lines
6.5 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 {
AUFTRAG_SCHRITTE, statusTon, tagesUeberschrift, baueAuftrag, baueAenderungen, baueArbeiten, baueDateien, baueAktivitaet, ladeProjektDetails, baueProjektDetails,
} from '../public/neu/website-details.js'
import { mit, mitDom } from './support/knDaten.js'
test('Tagesüberschrift im Berliner Tag', () => {
const jetzt = new Date('2026-10-16T09:00:00Z')
assert.deepEqual(['2026-10-15T22:30:00Z', '2026-10-15T20:00:00Z', '2026-10-14T10:00:00Z', '2025-12-24T10:00:00Z'].map((d) => tagesUeberschrift(new Date(d), jetzt)),
['Heute', 'Gestern', 'Mittwoch, 14. Oktober', 'Mittwoch, 24. Dezember 2025'])
})
test('statusTon', () => assert.deepEqual(['new', 'active', 'waiting', 'review', 'done', 'paused', 'stopped', '?'].map(statusTon), ['grau', 'blau', 'orange', 'violett', 'gruen', 'grau', 'rot', 'blau']))
test('Änderungen: nach Tagen, fünf sichtbar, Rest hinter „weitere“, Titel bleibt Text', () => mitDom((fx) => {
const tag = (d, n, p) => Array.from({ length: n }, (_, i) => ({ date: `2026-10-${d}T0${i + 6}:00:00.000Z`, title: `${p} ${i}`, details: [] }))
const el = baueAenderungen([...tag(15, 4, 'Neu'), ...tag(14, 3, 'Alt'), { date: '2026-10-13T06:00:00.000Z', title: '<img src=x onerror=alert(1)>', details: [] }], new Date('2026-10-16T09:00:00Z'))
assert.equal(fx.alle(el, '[data-extra]').length, 3)
assert.equal(fx.finde(el, '[data-mehr]').textContent, '3 weitere Änderungen anzeigen')
assert.equal(fx.finde(el, 'img'), null)
fx.klick(fx.finde(el, '[data-mehr]')); assert.ok(fx.finde(el, '[data-einklappbar]').classList.contains('is-open')); assert.equal(fx.finde(el, '[data-mehr]').textContent, 'Weniger anzeigen')
}))
test('Arbeiten und Dateien: Zähltexte, Leertexte, Ordner mit Schrägstrich', () => mitDom((fx) => {
const e = (i) => ({ date: '2026-10-1' + i, kind: 'work', label: 'Arbeit', minutes: 15, person: 'Kenso' })
assert.equal(fx.finde(baueArbeiten([1, 2, 3, 4, 5].map(e), 'leer'), '[data-mehr]').textContent, '1 weiteren Eintrag anzeigen')
assert.equal(baueArbeiten([], 'Noch keine Arbeiten.').textContent, 'Noch keine Arbeiten.')
const d = baueDateien({ totalFiles: 3, totalSizeBytes: 1536, truncated: true, topLevel: [{ path: 'img', type: 'dir', fileCount: 2, sizeBytes: 1024 }, { path: 'index.html', type: 'file', fileCount: 1, sizeBytes: 512 }] })
assert.match(d.textContent, /3 Dateien · 1,5 KB \(Übersicht unvollständig – sehr großes Projekt\)/); assert.match(d.textContent, /img\//)
assert.equal(baueDateien({ totalFiles: 0 }).textContent, 'Keine Datei-Informationen verfügbar.')
}))
test('Projektdetails: Teilausfall ersetzt nur den betroffenen Abschnitt', () => mitDom(() => {
const el = baueProjektDetails({ git: null, files: { totalFiles: 0 }, work: { order: null, entries: [] } }, new Date())
assert.match(el.textContent, /Die Änderungen können gerade nicht geladen werden\./); assert.match(el.textContent, /Keine Datei-Informationen verfügbar\./)
}))
test('Auftrag: Nummer, Betreff, Status, Fortschritt, Hinweis bei Rückfrage', () => mitDom((fx) => {
assert.deepEqual(AUFTRAG_SCHRITTE, ['Eingegangen', 'In Arbeit', 'Prüfung', 'Erledigt'])
const el = baueAuftrag({ number: '100123', topic: 'Neue Startseite', status: { label: 'Wartet auf dich', tone: 'waiting', step: 2 } }, 150)
assert.match(el.textContent, /Auftrag 100123/); assert.match(el.textContent, /Neue Startseite/); assert.match(el.textContent, /Wartet auf dich/)
assert.match(el.textContent, /Arbeitszeit gesamt: 2 h 30 min/)
const punkte = fx.alle(el, 'li'); assert.equal(punkte.length, 4)
assert.ok(punkte[0].classList.contains('is-done')); assert.ok(punkte[1].classList.contains('is-current')); assert.equal(punkte[1].getAttribute('aria-current'), 'step'); assert.ok(!punkte[2].classList.contains('is-done'))
assert.match(el.textContent, /Wir brauchen noch eine Info von dir\./)
const chat = fx.finde(el, 'a'); assert.deepEqual([chat.getAttribute('href'), chat.getAttribute('data-view')], ['#chat', 'chat'])
const schlicht = baueAuftrag({ number: '', topic: '', status: { label: 'Neu', tone: 'new', step: 0 } })
assert.match(schlicht.textContent, /Dein Auftrag/); assert.equal(fx.alle(schlicht, 'li').length, 0); assert.doesNotMatch(schlicht.textContent, /Wir brauchen/)
}))
test('Aktivität: neueste zuerst, drei sichtbar, „Alle anzeigen (n)“ klappt auf; fremde Inhalte bleiben Text', () => mitDom((fx) => {
const t = (n, createdAt, topic) => ({ number: String(n), topic, createdAt, status: { label: 'Offen', tone: 'active', step: 2 }, entries: [] })
const el = baueAktivitaet([t(1, '2026-10-01T00:00:00Z', 'Eins'), t(4, '2026-10-04T00:00:00Z', '<img src=x onerror=alert(1)>'), t(2, '2026-10-02T00:00:00Z', 'Zwei'), t(3, '2026-10-03T00:00:00Z', 'Drei')], new Date('2026-10-16T09:00:00Z'))
assert.equal(fx.alle(el, 'article').length, 3); assert.match(el.textContent, /Auftrag 4/); assert.doesNotMatch(el.textContent, /Auftrag 1/)
assert.equal(fx.finde(el, 'img'), null)
const alle = fx.finde(el, (e) => e.textContent === 'Alle anzeigen (4)'); assert.ok(alle)
fx.klick(alle); assert.equal(fx.alle(el, 'article').length, 4); assert.ok(fx.finde(el, (e) => e.tagName === 'BUTTON' && e.textContent === 'Weniger anzeigen'))
assert.equal(baueAktivitaet([], new Date()).textContent, 'Es wurden noch keine Arbeiten dokumentiert.')
}))
test('Arbeiten: Unterstützung, Änderungsliste und Text; Zeitangaben', () => mitDom((fx) => {
const el = baueArbeiten([{ date: '2026-09-20', kind: 'update', label: 'Aktualisierung', person: 'Kenso', minutes: 90, changes: ['Menü angepasst'], supports: [{ name: 'Justin', task: 'Bilder', minutes: 15 }] },
{ date: '2026-09-21', kind: 'work', label: 'Arbeit', person: '', minutes: 0, text: 'Kurz geprüft' }], 'leer')
assert.match(el.textContent, /20\.09\.2026 · Kenso/); assert.match(el.textContent, /Menü angepasst/); assert.match(el.textContent, /↳ Unterstützung Justin: Bilder/)
assert.match(el.textContent, /1 h 30 min/); assert.match(el.textContent, /Kurz geprüft/); assert.equal(fx.finde(el, '[data-mehr]'), null)
}))
test('ladeProjektDetails: jede Quelle einzeln, Fehler ergibt null', mit({
'GET /api/projects/p%201/git': { changes: [] },
'GET /api/projects/p%201/files': () => ({ status: 500, body: { error: 'x' } }),
'GET /api/projects/p%201/work': { order: null, entries: [] },
}, async () => {
const d = await ladeProjektDetails('p 1')
assert.deepEqual(d.git, { changes: [] }); assert.equal(d.files, null); assert.deepEqual(d.work, { order: null, entries: [] })
}))