73 lines
3.9 KiB
TypeScript
73 lines
3.9 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { act } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { afterEach, expect, it, vi } from 'vitest';
|
|
import { AssessorApiClient } from '../../src/api/assessor-api-client';
|
|
import type { RegulatoryCorpusStatus } from '../../src/domain/regulatory-corpus-management';
|
|
import { IsoCorpusLibrary } from '../../src/features/project-import/IsoCorpusLibrary';
|
|
|
|
afterEach(() => { vi.restoreAllMocks(); vi.unstubAllGlobals(); });
|
|
|
|
it('uploads both selected ISO PDFs with the entered operator token and shows embedding progress', async () => {
|
|
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
|
const initial: RegulatoryCorpusStatus = { version: 1, configured: true, active: null, job: null };
|
|
vi.spyOn(AssessorApiClient.prototype, 'getIsoCorpusStatus').mockResolvedValue(initial);
|
|
const submit = vi.spyOn(AssessorApiClient.prototype, 'submitIsoCorpus').mockResolvedValue({
|
|
...initial, job: { id: 'synthetic-job', status: 'running', phase: 'embedding', startedAt: '2026-09-23T00:00:00Z',
|
|
completedChunks: 2, totalChunks: 8 }
|
|
});
|
|
const container = document.createElement('div');
|
|
document.body.append(container);
|
|
const root = createRoot(container);
|
|
|
|
try {
|
|
await act(async () => root.render(<IsoCorpusLibrary/>));
|
|
const fileInputs = container.querySelectorAll<HTMLInputElement>('input[type="file"]');
|
|
const first = new File(['%PDF-synthetic-27001'], '27001.pdf', { type: 'application/pdf' });
|
|
const second = new File(['%PDF-synthetic-27002'], '27002.pdf', { type: 'application/pdf' });
|
|
await act(async () => {
|
|
Object.defineProperty(fileInputs[0], 'files', { configurable: true, value: [first] });
|
|
fileInputs[0].dispatchEvent(new Event('change', { bubbles: true }));
|
|
Object.defineProperty(fileInputs[1], 'files', { configurable: true, value: [second] });
|
|
fileInputs[1].dispatchEvent(new Event('change', { bubbles: true }));
|
|
const token = container.querySelector<HTMLInputElement>('input[type="password"]')!;
|
|
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.set!.call(token, 'synthetic-secret');
|
|
token.dispatchEvent(new Event('input', { bubbles: true }));
|
|
});
|
|
await act(async () => container.querySelector('form')!.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true })));
|
|
expect(submit).toHaveBeenCalledWith(first, second, 'synthetic-secret');
|
|
expect(container.textContent).toContain('Embedding 2 / 8');
|
|
expect(container.querySelector<HTMLInputElement>('input[type="password"]')!.value).toBe('');
|
|
} finally {
|
|
await act(async () => root.unmount());
|
|
container.remove();
|
|
}
|
|
});
|
|
|
|
it('clears a transient status polling error once a later poll succeeds', async () => {
|
|
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
|
vi.useFakeTimers();
|
|
const job = { id: 'synthetic-job', status: 'running' as const, phase: 'embedding' as const, startedAt: '2026-09-23T00:00:00Z' };
|
|
vi.spyOn(AssessorApiClient.prototype, 'getIsoCorpusStatus')
|
|
.mockResolvedValueOnce({ version: 1, configured: true, active: null, job })
|
|
.mockRejectedValueOnce(new Error('Synthetic transient failure.'))
|
|
.mockResolvedValue({ version: 1, configured: true, active: null, job: { ...job, status: 'succeeded', phase: 'complete' } });
|
|
const container = document.createElement('div');
|
|
document.body.append(container);
|
|
const root = createRoot(container);
|
|
|
|
try {
|
|
await act(async () => root.render(<IsoCorpusLibrary/>));
|
|
await act(async () => { await vi.advanceTimersByTimeAsync(2_000); });
|
|
expect(container.textContent).toContain('Synthetic transient failure.');
|
|
await act(async () => { await vi.advanceTimersByTimeAsync(2_000); });
|
|
expect(container.textContent).not.toContain('Synthetic transient failure.');
|
|
expect(container.textContent).toContain('ISO corpus indexed and active.');
|
|
} finally {
|
|
await act(async () => root.unmount());
|
|
container.remove();
|
|
vi.useRealTimers();
|
|
}
|
|
});
|