import { describe, expect, it } from 'vitest' import { normalizeJobPercent, normalizeJobState, resolveJobCapabilities, } from '../../jobs' import type { JobStateInput, JobStatus } from '../../types/jobs' const legacyCapabilities: Record = { awaiting_input: [false, false], queued: [true, false], running: [true, false], completed: [false, true], failed: [false, true], cancelled: [false, true], } function job(status: JobStatus): JobStateInput { return { id: status, job_id: status, kind: 'analysis', name: status, status, progress: { current_file: 0, total_files: 0, current_filename: null, percent: 0, message: '', stage: status, }, queue_position: 0, warnings: [], error: null, output_path: null, save_path: null, session_id: null, folders: [], folder_path: null, user_id: '1', owner_user_id: '1', experiment_id: null, extraction_result_id: null, metadata: {}, created_at: '2026-07-14T10:00:00+00:00', started_at: null, completed_at: null, } } describe('job capability normalization', () => { it.each(Object.entries(legacyCapabilities))( 'infers legacy capabilities for %s', (status, expected) => { const capabilities = resolveJobCapabilities({ status: status as JobStatus }) expect([capabilities.can_cancel, capabilities.can_delete]).toEqual(expected) }, ) it('keeps explicit capabilities authoritative', () => { const capabilities = resolveJobCapabilities({ status: 'running', can_cancel: false, can_delete: true, }) expect(capabilities).toEqual({ can_cancel: false, can_delete: true }) }) it('fails closed for an unknown legacy status', () => { const capabilities = resolveJobCapabilities({ status: 'custom-status' }) expect(capabilities).toEqual({ can_cancel: false, can_delete: false }) }) it('normalizes without mutating the transport input', () => { const input = job('awaiting_input') normalizeJobState(input) expect('can_cancel' in input).toBe(false) }) it.each([ [Number.NaN, 0], [Number.POSITIVE_INFINITY, 0], [-1, 0], [101, 100], ])('clamps unsafe progress value %s', (value, expected) => { expect(normalizeJobPercent(value)).toBe(expected) }) })