Assessor_2.0/tests/compliance/regulatory-mapping-scope-in...

68 lines
2.8 KiB
TypeScript

// @vitest-environment jsdom
import { act, type ReactNode } 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 { RegulatoryMappingResponse } from '../../src/compliance/regulatory-mapping';
import { useRegulatoryMapping } from '../../src/compliance/ui/use-regulatory-mapping';
afterEach(() => {
vi.restoreAllMocks();
vi.unstubAllGlobals();
});
function deferred<T>() {
let resolve!: (value: T) => void;
const promise = new Promise<T>(next => { resolve = next; });
return { promise, resolve };
}
function response(projectId: string, occurrenceId: string): RegulatoryMappingResponse {
return {
version: 1,
projectId,
resultProjectionId: `scanner-finding:${occurrenceId}`,
generationEnabled: true,
state: 'empty',
decisions: []
};
}
function HookProbe({ occurrenceId }: { occurrenceId: string }): ReactNode {
const controller = useRegulatoryMapping('project-1', `scanner-finding:${occurrenceId}`, 'connected');
return <>
<button type="button" onClick={() => controller.setOpen(true)}>Open mapping</button>
<output>{controller.response?.resultProjectionId ?? 'empty'}</output>
</>;
}
it('does not show a previous finding mapping when it resolves after the active finding', async () => {
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
const first = deferred<RegulatoryMappingResponse>();
const second = deferred<RegulatoryMappingResponse>();
const request = vi.spyOn(AssessorApiClient.prototype, 'getRegulatoryMappings').mockImplementation((_projectId, resultProjectionId) =>
resultProjectionId === 'scanner-finding:occurrence-a' ? first.promise : second.promise);
const container = document.createElement('div');
document.body.append(container);
const root = createRoot(container);
try {
await act(async () => root.render(<HookProbe occurrenceId="occurrence-a" />));
await act(async () => container.querySelector<HTMLButtonElement>('button')!.click());
await act(async () => root.render(<HookProbe occurrenceId="occurrence-b" />));
await act(async () => container.querySelector<HTMLButtonElement>('button')!.click());
expect(request).toHaveBeenCalledTimes(2);
await act(async () => { second.resolve(response('project-1', 'occurrence-b')); await Promise.resolve(); });
expect(container.textContent).toContain('scanner-finding:occurrence-b');
await act(async () => { first.resolve(response('project-1', 'occurrence-a')); await Promise.resolve(); });
expect(container.textContent).toContain('scanner-finding:occurrence-b');
expect(container.textContent).not.toContain('scanner-finding:occurrence-a');
} finally {
await act(async () => root.unmount());
container.remove();
}
});