import test from 'node:test'; import assert from 'node:assert/strict'; import { calcActualElapsedHours, calcWorkHours, formatActualDuration } from './work-hours'; import { calcDuration } from './overtime'; test('calcWorkHours skips official holidays and counts makeup workdays', () => { assert.equal(calcWorkHours('2026-10-01T09:00:00', '2026-10-01T18:00:00'), 0); assert.equal(calcWorkHours('2026-10-10T09:00:00', '2026-10-10T18:00:00'), 8); }); test('calcActualElapsedHours uses work calendar time with a half-hour minimum', () => { assert.equal(calcActualElapsedHours('2026-06-22T09:00:00', '2026-06-22T09:10:00'), 0.5); assert.equal(calcActualElapsedHours('2026-06-22T09:00:00', '2026-06-22T10:15:00'), 1.5); assert.equal(calcActualElapsedHours('2026-10-01T09:00:00', '2026-10-01T18:00:00'), 0); assert.equal(calcActualElapsedHours('2026-10-10T09:00:00', '2026-10-10T10:00:00'), 1); assert.equal(calcActualElapsedHours('2026-06-22T10:00:00', '2026-06-22T09:00:00'), 0); }); test('overtime duration uses project day rhythm instead of continuous clock time', () => { assert.equal(calcDuration('2026-07-01T09:00:00', '2026-07-02T18:00:00'), 16); assert.equal(calcDuration('2026-07-01T09:00:00', '2026-07-02T20:00:00'), 18); }); test('overtime duration counts holidays as selectable work days without skipping them', () => { assert.equal(calcDuration('2026-10-01T09:00:00', '2026-10-01T18:00:00'), 8); }); test('formatActualDuration converts hours to natural days', () => { assert.equal(formatActualDuration(60.5), '60.5h(2.5天)'); assert.equal(formatActualDuration(0.5), '0.5h(0.02天)'); assert.equal(formatActualDuration(0), '0h(0天)'); });