import test from 'node:test'; import assert from 'node:assert/strict'; import { filterOvertimeRecordsForExportMonth, filterOvertimeRecordsForViewer, type OvertimeRecord, } from './overtime'; import type { AuthUser } from './auth-user'; import type { Department, Member, RoleItem } from './members'; const departments: Department[] = [ { id: 'dept-tech', name: 'Tech', order: 1, createdAt: '2024-01-01' }, { id: 'dept-front', name: 'Frontend', parentId: 'dept-tech', order: 1, createdAt: '2024-01-01' }, { id: 'dept-back', name: 'Backend', parentId: 'dept-tech', order: 2, createdAt: '2024-01-01' }, { id: 'dept-product', name: 'Product', order: 2, createdAt: '2024-01-01' }, ]; const members: Member[] = [ member('m-lead', 'Lead', 'dept-tech', 'role-lead'), member('m-front', 'Frontend Alice', 'dept-front', 'role-dev'), member('m-back', 'Backend Bob', 'dept-back', 'role-dev'), member('m-pm', 'PM Carol', 'dept-product', 'role-pm'), ]; const records: OvertimeRecord[] = [ record('ot-front', 'Frontend Alice'), record('ot-back', 'Backend Bob'), record('ot-pm', 'PM Carol'), ]; const exportRecords: OvertimeRecord[] = [ { id: 'july-1', projectId: 'project-1', person: 'Alice', startTime: '2026-07-01T19:00:00', endTime: '2026-07-01T21:00:00', duration: 2, reasonId: 'reason-1', createdAt: '2026-07-01', }, { id: 'august-1', projectId: 'project-1', person: 'Bob', startTime: '2026-08-02T19:00:00', endTime: '2026-08-02T21:00:00', duration: 2, reasonId: 'reason-1', createdAt: '2026-08-02', }, ]; test('filterOvertimeRecordsForViewer limits non-admin viewers to their department tree', () => { const visible = filterOvertimeRecordsForViewer(records, { viewer: toAuthUser(members[0]), viewerRole: role('role-lead', ['overtime:view']), members, departments, }); assert.deepEqual(visible.map((item) => item.id), ['ot-front', 'ot-back']); }); test('filterOvertimeRecordsForViewer lets wildcard admin view every department', () => { const visible = filterOvertimeRecordsForViewer(records, { viewer: toAuthUser(members[0]), viewerRole: role('role-admin', ['*']), members, departments, }); assert.deepEqual(visible.map((item) => item.id), ['ot-front', 'ot-back', 'ot-pm']); }); test('filters export records by selected month', () => { const result = filterOvertimeRecordsForExportMonth(exportRecords, '2026-07'); assert.deepEqual(result.map((record) => record.id), ['july-1']); }); test('keeps all export records when all months are selected', () => { const result = filterOvertimeRecordsForExportMonth(exportRecords, ''); assert.deepEqual(result.map((record) => record.id), ['july-1', 'august-1']); }); function member(id: string, name: string, departmentId: string, roleId: string): Member { return { id, name, username: id.toUpperCase(), departmentId, roleId, phone: '', email: '', password: '', createdAt: '2024-01-01', }; } function record(id: string, person: string): OvertimeRecord { return { id, person, projectId: 'project-1', startTime: '2026-06-01T19:00', endTime: '2026-06-01T21:00', duration: 2, reasonId: 'reason-1', createdAt: '2026-06-01', }; } function role(id: string, permissions: string[]): RoleItem { return { id, name: id, createdAt: '2024-01-01', permissions, }; } function toAuthUser(member: Member): AuthUser { return { id: member.id, name: member.name, username: member.username ?? member.id.toUpperCase(), roleId: member.roleId, departmentId: member.departmentId, email: member.email, }; }