import { importErrorMessage, summarizeImportResult, } from '../../frontend/src/app/features/admin/challenges/challenges.pure'; describe('Job 903: import error + result helpers', () => { it('summarizeImportResult reports imported/skipped/warning counts', () => { const r = { imported: 2, skipped: [{ name: 'X', reason: 'Unknown category: Y' }], warnings: ['1 skipped.'], }; const out = summarizeImportResult(r as any); expect(out).toContain('Imported 2'); expect(out).toContain('Skipped 1'); expect(out).toContain('1 warning'); }); it('importErrorMessage prefers the nested error.message envelope', () => { expect(importErrorMessage({ error: { message: 'Server said no' } }, 'fallback')).toBe('Server said no'); }); it('importErrorMessage falls back to err.message', () => { expect(importErrorMessage({ message: 'boom' }, 'fallback')).toBe('boom'); }); it('importErrorMessage falls back to the supplied default when no message is available', () => { expect(importErrorMessage({}, 'fallback')).toBe('fallback'); expect(importErrorMessage(null, 'fallback')).toBe('fallback'); }); }); describe('Job 903: confirmed import handler contract', () => { function makeDoc() { return { format: 'hipctf-challenges', version: 1, exportedAt: '', challenges: [] }; } it('a successful confirm yields a closed-modal state and a status banner', async () => { const state = { importOpen: true as boolean, importDoc: makeDoc() as any, importPreview: { total: 2, conflicts: [], unknownCategories: [], warnings: [] } as any, importResult: null as any, importError: null as string | null, importing: false, statusMessage: null as string | null, }; // Simulate onImportConfirm body using pure helpers. try { const result = { imported: 2, skipped: [], warnings: [] }; state.statusMessage = summarizeImportResult(result as any); await Promise.resolve(); // Close-modal branch (the new behavior). state.importOpen = false; state.importDoc = null; state.importPreview = null; state.importResult = null; state.importError = null; } catch (err) { state.importError = importErrorMessage(err, 'Failed to import challenges'); } finally { state.importing = false; } expect(state.importOpen).toBe(false); expect(state.importDoc).toBeNull(); expect(state.importPreview).toBeNull(); expect(state.importResult).toBeNull(); expect(state.importError).toBeNull(); expect(state.statusMessage).toContain('Imported 2'); expect(state.importing).toBe(false); }); it('a rejected confirm keeps the modal open and surfaces the error message', async () => { const state = { importOpen: true as boolean, importDoc: makeDoc() as any, importPreview: { total: 1, conflicts: [], unknownCategories: [], warnings: [] } as any, importResult: null as any, importError: null as string | null, importing: false, statusMessage: null as string | null, }; try { throw { error: { message: 'Server said no' } }; } catch (err) { state.importError = importErrorMessage(err, 'Failed to import challenges'); } finally { state.importing = false; } expect(state.importOpen).toBe(true); expect(state.importError).toBe('Server said no'); expect(state.importing).toBe(false); }); });