Je Auftrag eine Überschrift (Titel fett, Status-Pille), ein schmaler Balken mit vier Abschnitten (Stufennamen als Text für Screenreader), bei Rückfrage die Zeile "Wir brauchen eine Info von dir · Im Chat antworten" und eine Zeitleiste mit Haarlinie (Datum TT.MM. und Kurztext, drei sichtbar, "mehr anzeigen"). Fünf Aufträge offen, der Rest hinter "Ältere Aufträge anzeigen". Die Auftragsnummer steht nicht mehr im Text (ruhiger), bleibt als data-auftrag. Die alte baueAktivitaet und ihre toten CSS-Regeln entfallen; die Projektdetails (baueAuftrag, baueArbeiten) bleiben unverändert. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
65 lines
5.5 KiB
JavaScript
65 lines
5.5 KiB
JavaScript
import { test } from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import {
|
||
AUFTRAG_SCHRITTE, statusTon, tagesUeberschrift, baueAuftrag, baueAenderungen, baueArbeiten, baueDateien, 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/)
|
||
}))
|
||
|
||
// Die Aktivität der Website-Seite (Zeitleiste) prüfen knAuftragsZeitleiste.test.js und knAuftragsZeitleisteDom.test.js.
|
||
|
||
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: [] })
|
||
}))
|