import { describe, expect, it } from 'vitest'; import { reconcileWorkSession } from '../../src/domain/attendance/work-session.js'; const options = { now: '2026-09-24T20:00:00.000Z', openShiftThresholdMinutes: 14 * 60, }; describe('attendance work-session reconciliation', () => { it('sums several in/out intervals without inventing time between them', () => { const result = reconcileWorkSession( [ { id: '1', type: 'check_in', occurredAt: '2026-09-24T01:00:00.000Z' }, { id: '2', type: 'check_out', occurredAt: '2026-09-24T05:00:00.000Z' }, { id: '3', type: 'check_in', occurredAt: '2026-09-24T06:00:00.000Z' }, { id: '4', type: 'check_out', occurredAt: '2026-09-24T10:30:00.000Z' }, ], options, ); expect(result).toMatchObject({ startedAt: '2026-09-24T01:00:00.000Z', endedAt: '2026-09-24T10:30:00.000Z', workedMinutes: 510, status: 'pending_review', anomalies: [], }); }); it('keeps the first check-in and flags a repeated check-in', () => { const result = reconcileWorkSession( [ { id: '1', type: 'check_in', occurredAt: '2026-09-24T01:00:00.000Z' }, { id: '2', type: 'check_in', occurredAt: '2026-09-24T01:05:00.000Z' }, { id: '3', type: 'check_out', occurredAt: '2026-09-24T09:00:00.000Z' }, ], options, ); expect(result?.workedMinutes).toBe(480); expect(result?.anomalies).toEqual(['repeated_check_in']); }); it('keeps a recent unfinished shift open', () => { const result = reconcileWorkSession( [{ id: '1', type: 'check_in', occurredAt: '2026-09-24T12:00:00.000Z' }], options, ); expect(result).toMatchObject({ status: 'open', endedAt: null, workedMinutes: 0, anomalies: [], }); }); it('flags an old unfinished shift without estimating payable minutes', () => { const result = reconcileWorkSession( [{ id: '1', type: 'check_in', occurredAt: '2026-09-24T01:00:00.000Z' }], options, ); expect(result).toMatchObject({ status: 'pending_review', endedAt: null, workedMinutes: 0, anomalies: ['missing_check_out'], }); }); it('auto-closes only after the scheduler cutoff and leaves an audit-worthy anomaly', () => { const result = reconcileWorkSession( [{ id: '1', type: 'check_in', occurredAt: '2026-09-23T12:00:00.000Z' }], { ...options, automaticCloseAt: '2026-09-23T19:00:00.000Z' }, ); expect(result).toMatchObject({ endedAt: '2026-09-23T19:00:00.000Z', workedMinutes: 420, status: 'pending_review', anomalies: ['auto_closed'], }); }); it('records a check-out without check-in as an anomaly with zero minutes', () => { const result = reconcileWorkSession( [{ id: '1', type: 'check_out', occurredAt: '2026-09-24T09:00:00.000Z' }], options, ); expect(result).toMatchObject({ startedAt: null, endedAt: '2026-09-24T09:00:00.000Z', workedMinutes: 0, status: 'pending_review', anomalies: ['missing_check_in'], }); }); it('rejects invalid timestamps and thresholds', () => { expect(() => reconcileWorkSession([{ id: '1', type: 'check_in', occurredAt: 'not-a-date' }], options), ).toThrow('event 1 must be an ISO date-time'); expect(() => reconcileWorkSession([], { ...options, openShiftThresholdMinutes: 0 })).toThrow( 'openShiftThresholdMinutes must be a positive integer', ); }); });