import assert from 'node:assert/strict'; import { addHistoryEntries, removeHistoryEntry, loadFromJSON, saveToJSON, normalizeEmployees, removeEmployee } from '../js/data.js'; function makeState(history = []) { return { employees: [], calendar: { holidays: [], companyClosures: [] }, history: [...history] }; } // addHistoryEntries: two entries with same date but different employees both kept { const state = makeState(); addHistoryEntries(state, [ { date: '2026-04-01', employeeId: 'alice', manual: false }, { date: '2026-04-01', employeeId: 'bob', manual: false } ]); assert.equal(state.history.length, 2, 'two distinct entries kept on same date'); const ids = state.history.map(h => h.employeeId).sort(); assert.deepEqual(ids, ['alice', 'bob'], 'both employees present'); } // addHistoryEntries: same (date, employeeId) replaced, others on same date untouched { const state = makeState([ { date: '2026-04-01', employeeId: 'alice', manual: false }, { date: '2026-04-01', employeeId: 'bob', manual: false } ]); addHistoryEntries(state, [ { date: '2026-04-01', employeeId: 'alice', manual: true } ]); assert.equal(state.history.length, 2, 'still two entries'); const alice = state.history.find(h => h.employeeId === 'alice'); assert.equal(alice.manual, true, 'alice replaced with manual=true'); const bob = state.history.find(h => h.employeeId === 'bob'); assert.equal(bob.manual, false, 'bob untouched'); } // addHistoryEntries: empty input → no change { const state = makeState([{ date: '2026-04-01', employeeId: 'alice', manual: false }]); addHistoryEntries(state, []); assert.equal(state.history.length, 1, 'empty entries → no change'); } // removeHistoryEntry without employeeId: removes all entries on that date { const state = makeState([ { date: '2026-04-01', employeeId: 'alice', manual: false }, { date: '2026-04-01', employeeId: 'bob', manual: false }, { date: '2026-04-02', employeeId: 'alice', manual: false } ]); removeHistoryEntry(state, '2026-04-01'); assert.equal(state.history.length, 1, 'only 2026-04-02 alice remains'); assert.equal(state.history[0].date, '2026-04-02', 'remaining entry is 2026-04-02'); } // removeHistoryEntry with employeeId: removes only that one entry { const state = makeState([ { date: '2026-04-01', employeeId: 'alice', manual: false }, { date: '2026-04-01', employeeId: 'bob', manual: false } ]); removeHistoryEntry(state, '2026-04-01', 'alice'); assert.equal(state.history.length, 1, 'one entry remains'); assert.equal(state.history[0].employeeId, 'bob', 'bob still there'); } // removeHistoryEntry with employeeId that does not exist: no-op { const state = makeState([ { date: '2026-04-01', employeeId: 'alice', manual: false } ]); removeHistoryEntry(state, '2026-04-01', 'nonexistent'); assert.equal(state.history.length, 1, 'no change when employeeId not found'); } // loadFromJSON: missing settings → default {moderatorsPerDay: 1} { const json = JSON.stringify({ employees: [], calendar: { holidays: [], companyClosures: [] }, history: [] }); const loaded = loadFromJSON(json); assert.deepEqual(loaded.settings, { moderatorsPerDay: 1 }, 'default settings when missing'); } // loadFromJSON: present settings preserved, moderatorsPerDay clamped to [1,5] { const json = JSON.stringify({ employees: [], calendar: { holidays: [], companyClosures: [] }, history: [], settings: { moderatorsPerDay: 3 } }); const loaded = loadFromJSON(json); assert.equal(loaded.settings.moderatorsPerDay, 3, 'preserved value'); } // loadFromJSON: invalid moderatorsPerDay (string, out of range) → fallback to 1 { const tooHigh = loadFromJSON(JSON.stringify({ employees: [], calendar: { holidays: [], companyClosures: [] }, history: [], settings: { moderatorsPerDay: 99 } })); assert.equal(tooHigh.settings.moderatorsPerDay, 1, 'out of range falls back to 1'); const wrongType = loadFromJSON(JSON.stringify({ employees: [], calendar: { holidays: [], companyClosures: [] }, history: [], settings: { moderatorsPerDay: 'two' } })); assert.equal(wrongType.settings.moderatorsPerDay, 1, 'wrong type falls back to 1'); } // saveToJSON: settings are serialized { const state = { employees: [], calendar: { holidays: [], companyClosures: [] }, history: [], settings: { moderatorsPerDay: 2 } }; const json = saveToJSON(state); const parsed = JSON.parse(json); assert.deepEqual(parsed.settings, { moderatorsPerDay: 2 }, 'settings round-trip'); } // normalizeEmployees: missing constraints are filled with defaults { const out = normalizeEmployees([{ id: 'a', name: 'Alice' }]); assert.equal(out.length, 1, 'employee kept'); assert.deepEqual(out[0].constraints.neverDays, [], 'neverDays defaulted'); assert.equal(out[0].constraints.minGapDays, 14, 'minGapDays defaulted to 14'); assert.equal(out[0].constraints.maxPerMonth, null, 'maxPerMonth defaulted to null'); } // normalizeEmployees: rows without a usable name are dropped { const out = normalizeEmployees([{ id: 'a', name: ' ' }, { id: 'b' }, null, 42]); assert.equal(out.length, 0, 'nameless/invalid rows dropped'); } // normalizeEmployees: duplicate ids are de-duplicated to distinct ids { const out = normalizeEmployees([{ id: 'dup', name: 'A' }, { id: 'dup', name: 'B' }]); assert.equal(out.length, 2, 'both kept'); assert.notEqual(out[0].id, out[1].id, 'duplicate id resolved'); } // normalizeEmployees: invalid vacation ranges dropped, valid kept { const out = normalizeEmployees([{ id: 'a', name: 'A', constraints: { vacations: [ { from: '2026-05-10', to: '2026-05-05' }, // reversed → dropped { from: '2026-06-01', to: '2026-06-07' } // valid → kept ] } }]); assert.equal(out[0].constraints.vacations.length, 1, 'only valid vacation kept'); assert.equal(out[0].constraints.vacations[0].from, '2026-06-01', 'valid vacation preserved'); } // loadFromJSON: employees without constraints are normalized (no later crash) { const loaded = loadFromJSON(JSON.stringify({ employees: [{ id: 'x', name: 'NoConstraints' }], calendar: { holidays: [], companyClosures: [] }, history: [] })); assert.ok(Array.isArray(loaded.employees[0].constraints.neverDays), 'constraints present after load'); } // removeEmployee: also removes the employee's history entries (no orphans) { const state = { employees: [{ id: 'a', name: 'Alice' }, { id: 'b', name: 'Bob' }], calendar: { holidays: [], companyClosures: [] }, history: [ { date: '2026-04-01', employeeId: 'a', manual: false }, { date: '2026-04-02', employeeId: 'b', manual: false } ] }; removeEmployee(state, 'a'); assert.equal(state.employees.length, 1, 'alice removed from employees'); assert.ok(!state.history.some(h => h.employeeId === 'a'), 'alice history removed'); assert.equal(state.history.length, 1, 'bob history untouched'); } console.log('All data tests passed.');