Terminplaner: Portal-Ansicht – Nachbesserungen (2/2)
- Annehmen mit Rueckfrage in der Seite (schliesst den Vertrag, schickt G02) - Offene Anfragen: alle bis Ende des Buchungszeitraums (Fenster zu je 62 Tagen, hoechstens 6 Aufrufe), passend zur Zahl auf Kachel und Banner - Meldung ins Bild geholt, Fehler mit Fokus; einzige Live-Region - Netzwerkfehler auf Deutsch; Antwort einer frueheren Website erscheint nie unter der neuen (Zaehler je Aufruf); Datumssprung nur mit echtem Tag - Ende um Mitternacht als 24:00, Statusfilter nach Eintragen auf Alle, abgeschaltet ohne Einstellung mit Export-Link, dunkles Datumsfeld - Playwright: Zeitzone New York/Berlin, ferne Anfragen, Projektwechsel, Meldung im Bild, Datumssprung, abgeschaltet ohne Einstellung Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9c07f6a8c5
commit
650919b022
10 files changed
+410
-73
No files matched your search
@@ -3,8 +3,9 @@ import assert from 'node:assert/strict'
|
||||
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,
|
||||
fehltText, fensterAufteilen, heuteBerlin, istSperre, istTag, monatVon, moeglicheAktionen, ressourcenWort, statusLabel, statusTon, tagPlus, tagUeberschrift, verschiebeTag, wocheVon, zeitNormal, zeitraumTitel,
|
||||
} from '../public/termine-view.js'
|
||||
import { exportUrl, request } from '../public/termine-dom.js'
|
||||
|
||||
// Reine Helfer der Portal-Ansicht Terminplaner (public/termine-view.js): Tage sind Berliner Kalendertage 'JJJJ-MM-TT', gerechnet wird
|
||||
// nur mit dem Kalender (kein Browser-Datum), die Uhrzeit des Endes kommt aus endsAt in Berliner Zeit.
|
||||
@@ -80,7 +81,11 @@ test('bereichFuer und verschiebeTag je Ansicht', () => {
|
||||
assert.deepEqual(bereichFuer('tag', '2026-10-07', '2026-10-05'), { von: '2026-10-07', bis: '2026-10-07' })
|
||||
assert.deepEqual(bereichFuer('woche', '2026-10-07', '2026-10-05'), { von: '2026-10-05', bis: '2026-10-11' })
|
||||
assert.deepEqual(bereichFuer('monat', '2026-10-07', '2026-10-05'), { von: '2026-10-01', bis: '2026-10-31' })
|
||||
assert.deepEqual(bereichFuer('anfragen', '2026-10-07', '2026-10-05'), { von: '2026-10-05', bis: '2026-12-06' }, 'ab heute, 62 Tage (Grenze der Schnittstelle)')
|
||||
assert.deepEqual(bereichFuer('anfragen', '2026-10-07', '2026-10-05'), { von: '2026-10-05', bis: '2026-12-04' }, 'ab heute bis zum Ende des Buchungszeitraums (Vorgabe 60 Tage)')
|
||||
assert.deepEqual(bereichFuer('anfragen', '2026-10-07', '2026-10-05', 180), { von: '2026-10-05', bis: '2027-04-03' }, 'Buchungszeitraum der Einstellung')
|
||||
assert.deepEqual(bereichFuer('anfragen', '2026-10-07', '2026-10-05', 365), { von: '2026-10-05', bis: '2027-10-05' })
|
||||
assert.equal(bereichFuer('anfragen', '2026-10-07', '2026-10-05', 9999).bis, '2027-10-05', 'höchstens 365 Tage')
|
||||
for (const kaputt of [0, -5, NaN, 'x', null, undefined]) assert.equal(bereichFuer('anfragen', '2026-10-07', '2026-10-05', kaputt).bis, '2026-12-04', `ungültiger Zeitraum ${String(kaputt)} ⇒ Vorgabe`)
|
||||
assert.equal(verschiebeTag('tag', '2026-10-31', 1), '2026-11-01')
|
||||
assert.equal(verschiebeTag('tag', '2026-10-01', -1), '2026-09-30')
|
||||
assert.equal(verschiebeTag('woche', '2026-10-05', 1), '2026-10-12')
|
||||
@@ -90,6 +95,29 @@ test('bereichFuer und verschiebeTag je Ansicht', () => {
|
||||
assert.equal(verschiebeTag('monat', '2026-12-31', 1), '2027-01-01')
|
||||
})
|
||||
|
||||
test('fensterAufteilen: lückenlose Abfragefenster von höchstens 62 Tagen nach dem Beginn (Grenze der Schnittstelle)', () => {
|
||||
assert.deepEqual(fensterAufteilen('2026-10-05', '2026-10-05'), [{ von: '2026-10-05', bis: '2026-10-05' }])
|
||||
assert.deepEqual(fensterAufteilen('2026-10-05', '2026-12-04'), [{ von: '2026-10-05', bis: '2026-12-04' }], '60 Tage: ein Aufruf')
|
||||
assert.deepEqual(fensterAufteilen('2026-10-05', '2026-12-06'), [{ von: '2026-10-05', bis: '2026-12-06' }], 'genau 62 Tage nach dem Beginn: noch ein Aufruf')
|
||||
assert.deepEqual(fensterAufteilen('2026-10-05', '2026-12-07'), [{ von: '2026-10-05', bis: '2026-12-06' }, { von: '2026-12-07', bis: '2026-12-07' }])
|
||||
const jahr = fensterAufteilen('2026-10-05', '2027-10-05')
|
||||
assert.equal(jahr.length, 6, '365 Tage: höchstens 6 Aufrufe')
|
||||
assert.equal(jahr[0].von, '2026-10-05')
|
||||
assert.equal(jahr.at(-1).bis, '2027-10-05')
|
||||
for (let i = 0; i < jahr.length; i += 1) {
|
||||
assert.ok(jahr[i].bis <= tagPlus(jahr[i].von, 62), `Fenster ${i} nicht länger als 62 Tage`)
|
||||
if (i > 0) assert.equal(jahr[i].von, tagPlus(jahr[i - 1].bis, 1), `Fenster ${i} schließt ohne Lücke und Überlappung an`)
|
||||
}
|
||||
assert.deepEqual(fensterAufteilen('2026-10-05', '2026-10-01'), [], 'Ende vor Beginn')
|
||||
})
|
||||
|
||||
test('istTag: nur echte Kalendertage aus einem vernünftigen Jahr (Datumsfeld mit 5-stelligem Jahr darf nichts auslösen)', () => {
|
||||
for (const gut of ['2026-10-05', '2028-02-29', '2000-01-01', '2100-12-31']) assert.equal(istTag(gut), true, gut)
|
||||
for (const schlecht of ['12345-01-01', '+12345-01-01', '2026-02-30', '2026-13-01', '2026-00-10', '2027-02-29', '0001-01-01', '1999-12-31', '2101-01-01', '2026-1-5', '', 'abc', null, undefined, 20261005]) {
|
||||
assert.equal(istTag(schlecht), false, String(schlecht))
|
||||
}
|
||||
})
|
||||
|
||||
test('Daten: datumLang, datumKurz, tagUeberschrift, zeitraumTitel', () => {
|
||||
assert.equal(datumLang('2026-10-05'), 'Montag, 5. Oktober 2026')
|
||||
assert.equal(datumLang('2026-03-01'), 'Sonntag, 1. März 2026')
|
||||
@@ -117,7 +145,8 @@ test('heuteBerlin: der Berliner Kalendertag, nicht der des Browsers', () => {
|
||||
test('endeZeit: Ende des Termins in Berliner Wanduhr aus endsAt', () => {
|
||||
assert.equal(endeZeit({ endsAt: '2026-10-05T08:45:00.000Z' }), '10:45')
|
||||
assert.equal(endeZeit({ endsAt: '2026-12-01T08:45:00.000Z' }), '09:45', 'Winterzeit')
|
||||
assert.equal(endeZeit({ endsAt: '2026-10-05T22:00:00.000Z' }), '00:00')
|
||||
assert.equal(endeZeit({ endsAt: '2026-10-05T22:00:00.000Z' }), '24:00', 'Ende um Mitternacht ist 24:00, nicht 00:00 (22:00–24:00)')
|
||||
assert.equal(endeZeit({ endsAt: '2026-10-05T22:05:00.000Z' }), '00:05', 'nach Mitternacht bleibt es 00:05')
|
||||
assert.equal(endeZeit({ endsAt: 'kaputt' }), '')
|
||||
assert.equal(endeZeit({}), '')
|
||||
})
|
||||
@@ -258,3 +287,22 @@ test('Ansicht-Module: Reiter sind Module mit render(panel, ctx), die Huelle kenn
|
||||
assert.doesNotMatch(lies(`public/${datei}`), /from '\.\/termine\.js'/, `${datei} importiert die Huelle nicht`)
|
||||
}
|
||||
})
|
||||
|
||||
test('request: Netzwerkfehler auf Deutsch, Fehler der Schnittstelle mit Feldern und Code', async () => {
|
||||
const vorher = globalThis.fetch
|
||||
try {
|
||||
globalThis.fetch = async () => { throw new TypeError('Failed to fetch') }
|
||||
await assert.rejects(request('/api/termine/buchungen'), (err) => err.message === 'Keine Verbindung. Bitte versuch es gleich noch einmal.' && err.status === 0 && !/fetch/i.test(err.message))
|
||||
globalThis.fetch = async () => ({ ok: false, status: 400, json: async () => ({ error: 'Bitte einen Namen angeben.', fehler: { name: 'Bitte einen Namen angeben.' }, code: 'x' }) })
|
||||
await assert.rejects(request('/api/termine/buchungen'), (err) => err.status === 400 && err.fehler.name === 'Bitte einen Namen angeben.' && err.code === 'x')
|
||||
globalThis.fetch = async () => ({ ok: false, status: 502, json: async () => { throw new Error('kein JSON') } })
|
||||
await assert.rejects(request('/x'), /Server nicht erreichbar/)
|
||||
} finally {
|
||||
globalThis.fetch = vorher
|
||||
}
|
||||
})
|
||||
|
||||
test('exportUrl: Projekt-ID wird codiert', () => {
|
||||
assert.equal(exportUrl('p1'), '/api/termine/export.csv?projectId=p1')
|
||||
assert.equal(exportUrl('a&b=c d'), '/api/termine/export.csv?projectId=a%26b%3Dc%20d')
|
||||
})
|
||||
Reference in new issue
Block a user