import assert from 'node:assert/strict' import test from 'node:test' import { run } from './fleet-driver-qualification.mjs' const copy = value => structuredClone(value) const PNG = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aH1kAAAAASUVORK5CYII=', 'base64') function fixture(fault) { const rows = new Map(), history = new Map(), calls = [], files = new Map() const response = (data, code='200', http=200) => ({ http, body: { code, data: copy(data) }, requestId: 'test-request', traceId: 'test-trace' }) function qualification(row, expectedEnd) { const now = Date.now(), expiry = Date.parse(row.details.licenseExpiresOn + 'T00:00:00Z') const expiringSoon = expiry >= now - 86400000 && expiry - now <= 30 * 86400000 let reason = !row.active ? 'INACTIVE' : !row.licenseFileId ? 'MISSING_LICENSE' : row.reviewStatus === 'REJECTED' ? 'REJECTED' : row.reviewStatus !== 'APPROVED' ? 'PENDING_REVIEW' : !expectedEnd ? 'MISSING_TRIP_END' : Date.parse(expectedEnd) <= now ? 'INVALID_TRIP_END' : Date.parse(expectedEnd) >= expiry + 86400000 ? 'EXPIRES_DURING_TRIP' : 'ELIGIBLE' if (fault === 'allows expiry boundary' && reason === 'EXPIRES_DURING_TRIP') reason = 'ELIGIBLE' return { canDispatch: reason === 'ELIGIBLE', reason, expiringSoon: fault === 'missing warning' ? false : expiringSoon } } function present(row) { return { ...copy(row), qualification: qualification(row), licenseState: row.details.licenseExpiresOn < new Date().toISOString().slice(0,10) ? 'EXPIRED' : 'EXPIRING' } } function record(row, action) { history.get(row.id).unshift({ action, recordVersion: row.recordVersion, snapshot: present(row) }) } const context = { marker: 'CONTROLLED-DRIVER-TEST', createdResources: {}, assert(_module, label, _response, condition) { assert.ok(condition, label) }, apiSuccess(_module, label, value) { assert.equal(value.http, 200, label); assert.equal(value.body?.code, '200', label); return value.body.data }, async request(method, raw, body) { calls.push({ method, raw, body: copy(body) }); const url = new URL(raw, 'https://fixture.invalid'), parts = url.pathname.split('/drivers'), suffix = parts[1] if (method === 'POST' && suffix === '') { const id = String(rows.size+1); const row = { id, driverNo: 'DR-'+id, details: copy(body), active: true, reviewStatus: 'PENDING', licenseFileId: null, recordVersion: 0 }; rows.set(id,row); history.set(id,[]); record(row,'CREATE'); return response(present(row)) } const [, id, action, fileId] = suffix.split('/'), row = rows.get(id); assert.ok(row) if (action === 'license') return fault === 'file outage' ? response(null, 'S0503', 503) : response(null, fault === 'cross-driver leak' ? '200' : 'A0404') if (method === 'GET' && !action) return response(present(row)) if (action === 'qualification') return response(qualification(row, url.searchParams.get('expectedEnd'))) if (action === 'history') return response({ records: history.get(id) }) if (Number(body.recordVersion) !== row.recordVersion) return response(null, 'A0409') if (action === 'review') { if (body.decision === 'APPROVED' && (!row.licenseFileId || row.details.licenseExpiresOn < new Date().toISOString().slice(0,10))) return response(null, 'A0400') if (body.decision === 'REJECTED' && !body.reason) return response(null, 'A0400') row.reviewStatus = body.decision } else if (action === 'submit') row.reviewStatus = 'PENDING' else if (action === 'status') row.active = body.active else if (method === 'PUT') { if (body.details.licenseExpiresOn !== row.details.licenseExpiresOn && fault !== 'renewal skips review') row.reviewStatus='PENDING'; row.details=copy(body.details) } else throw new Error(`Unexpected request ${method} ${raw}`) row.recordVersion++; record(row, action === 'review' ? body.decision : action === 'submit' ? 'RESUBMIT' : action === 'status' ? 'DEACTIVATE' : 'UPDATE'); return response(present(row)) }, async requestMultipart(method, raw) { calls.push({ method, raw }); const id = raw.split('/drivers/')[1].split('/')[0], row = rows.get(id); row.licenseFileId=String(files.size+1);files.set(row.licenseFileId,id);row.reviewStatus='PENDING';row.recordVersion++;record(row,'UPLOAD_LICENSE');return response(present(row)) }, async requestBinary(method, raw) { calls.push({ method, raw });return { http: 200, contentType: 'image/png', bytes: fault === 'corrupt image' ? Buffer.from('wrong') : PNG } }, } return { context, rows, calls } } test('full driver fixture checks lifecycle and deactivates both owned drivers', async () => { const { context, rows } = fixture(); await run(context) assert.equal(context.createdResources.fleetDriverQualification.status, 'VERIFIED') assert.equal(rows.size, 2); assert.ok([...rows.values()].every(row=>!row.active)) }) for (const fault of ['allows expiry boundary', 'missing warning', 'cross-driver leak', 'file outage', 'renewal skips review', 'corrupt image']) { test(`driver verifier rejects ${fault} and still deactivates created drivers`, async () => { const { context, rows } = fixture(fault); await assert.rejects(run(context)) assert.equal(context.createdResources.fleetDriverQualification.status, 'FAILED') assert.ok(rows.size>0); assert.ok([...rows.values()].every(row=>!row.active)) }) }