- render.test.mjs drives the real UI under jsdom: employees tab renders and
add works, planning tab renders the calendar grid (makeDayCell), generate
fills slots, a manual slot change updates history, and a beforeunload flush
persists state to localStorage; data tab renders the history view.
- persistence.test.mjs seeds malformed persisted state (employee without
constraints, out-of-range moderatorsPerDay) and asserts the startup load
normalizes it without crashing.
- jsdom added as the single devDependency; node_modules gitignored; both
suites wired into npm test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New js/utils.js exports toISO, monthPrefix, getWeekday, formatDateDE and
buildNameMap. algorithm.js, calendar.js, excel.js and history.js now import
these instead of re-implementing ISO construction, weekday math, DD.MM.YYYY
formatting and the id→name map inline. Adds tests/utils.test.mjs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds sanitizeCell(): cell values starting with = + - @ or a control char are
prefixed with an apostrophe so spreadsheets render them as literal text
instead of executing them as formulas. Applied to the names column.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
removeEmployee now also filters the deleted employee's history entries, so
no orphaned "(unbekannt)" rows remain. Adds a test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- loadFromJSON and the localStorage startup load now run employees through
normalizeEmployees(): fills missing constraints, drops unusable rows,
de-duplicates ids, and discards invalid vacation ranges — preventing
later crashes (e.g. c.neverDays on undefined) and same-day double-books.
- Excel import is wrapped in try/catch with a typeof XLSX guard and user
feedback; the Excel export button gets the same guard.
- createEmployee reuses the shared defaultConstraints() factory.
Adds normalizeEmployees tests (defaults, dropping, dedup, vacations) and a
loadFromJSON normalization test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
generatePlan gains a preAssigned parameter: manual entries occupy slots,
count toward eligibility (maxPerMonth/minGap) and are never double-booked;
only the remaining slots per day are auto-filled. The generate handler now
keeps manual:true entries for the month instead of wiping them.
Adds tests for slot occupation, fully-manual days, and maxPerMonth counting.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>