import assert from 'node:assert/strict'; import test from 'node:test'; import { bookingConfirmationMessage, canSubmitBookingForm, formatDateKey, formatEventDuration, getSlotsForDate, requiresIntroductionDetails, validateBookingForm } from '../public/booking/booking.js'; const events = [ { id: 'one', project: 'perspektivwerk', startsAt: '2026-09-14 08:00:00', endsAt: '2026-09-18 16:00:00', status: 'available' }, { id: 'two', project: 'perspektivwerk', startsAt: '2026-09-15 09:00:00', endsAt: '2026-09-15 13:00:00', status: 'full' }, ]; test('liefert auch mehrtägige Termine für jeden betroffenen Kalendertag', () => { const slots = getSlotsForDate('perspektivwerk', '2026-09-15', events); assert.equal(slots.length, 2); assert.equal(slots.filter((slot) => slot.status === 'available').length, 1); }); test('liefert für einen Tag ohne Termin keine Slots', () => { assert.deepEqual(getSlotsForDate('produktionsschule', '2026-09-15', events), []); }); test('verschiebt Kalendertage in der Sommerzeit nicht auf den Vortag', () => { process.env.TZ = 'Europe/Berlin'; assert.equal(formatDateKey(new Date(2026, 7, 24)), '2026-08-24'); }); test('validiert die Pflichtangaben der Buchungsmaske', () => { assert.deepEqual(validateBookingForm({ name: '', email: 'ungültig', privacyAccepted: false }), { name: 'Bitte geben Sie Ihren Namen ein.', email: 'Bitte geben Sie eine gültige E-Mail-Adresse ein.', phone: 'Bitte geben Sie eine gültige Telefonnummer ein.', privacy: 'Bitte bestätigen Sie die Datenschutzhinweise.' }); }); test('verlangt im SOLL-Stand eine Telefonnummer', () => { assert.equal(validateBookingForm({ name: 'Max Mustermann', email: 'max@example.org', privacyAccepted: true }).phone, 'Bitte geben Sie eine gültige Telefonnummer ein.'); }); test('akzeptiert die vollständigen Pflichtangaben der Buchungsmaske', () => { assert.deepEqual(validateBookingForm({ name: 'Max Mustermann', email: 'max@example.org', phone: '+49 351 123456', privacyAccepted: true }), {}); }); test('setzt die Zusatzangaben für Probearbeiten durch', () => { assert.equal(requiresIntroductionDetails({ project: 'produktionsschule', introductionRequired: true }), true); assert.equal(requiresIntroductionDetails({ project: 'perspektivwerk', introductionRequired: true }), false); assert.deepEqual(validateBookingForm({ name: 'Max Mustermann', email: 'max@example.org', phone: '+49 351 123456', privacyAccepted: true, event: { project: 'produktionsschule', introductionRequired: true } }), { introductionAttended: 'Bitte bestätigen Sie die Teilnahme an einer Einführungsveranstaltung.', introductionDate: 'Bitte geben Sie das Datum der Einführungsveranstaltung ein.' }); }); test('formatiert kurze und mehrtägige Termindauern', () => { assert.equal(formatEventDuration({ startsAt: '2026-09-15 09:00:00', endsAt: '2026-09-15 13:00:00' }), '4 Stunden'); assert.equal(formatEventDuration({ startsAt: '2026-09-21 08:00:00', endsAt: '2026-09-25 16:00:00' }), '5 Tage'); }); test('gibt den Absenden-Button erst nach DSGVO-Einwilligung frei', () => { assert.equal(canSubmitBookingForm(false), false); assert.equal(canSubmitBookingForm(true), true); }); test('zeigt nach dem Absenden eine verbindliche Bestätigung ohne Mockup-Hinweis', () => { const message = bookingConfirmationMessage('Erstgespräch'); assert.match(message, /verbindlich gespeichert/); assert.doesNotMatch(message, /Vorschau|Mockup/i); });