// @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 { AiOverviewResponse } from '../../src/domain/ai-overview'; import { useAiOverview } from '../../src/features/dashboard/AiOverviewPanel'; afterEach(() => { vi.restoreAllMocks(); vi.unstubAllGlobals(); }); function deferred() { let resolve!: (value: T) => void; const promise = new Promise(next => { resolve = next; }); return { promise, resolve }; } function response(projectId: string): AiOverviewResponse { return { version: 1, projectId, scope: { assessmentIds: [`assessment-${projectId}`], scanRunIds: [] }, generationEnabled: true, state: 'empty', stale: false }; } function HookProbe({ projectId }: { projectId: string }): ReactNode { const controller = useAiOverview(projectId, [`assessment-${projectId}`]); return {controller.response?.projectId ?? 'empty'}; } it('does not show a previous project response when it resolves after the active project', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); const first = deferred(); const second = deferred(); const request = vi.spyOn(AssessorApiClient.prototype, 'getAiOverview').mockImplementation(projectId => projectId === 'project-a' ? first.promise : second.promise); const container = document.createElement('div'); document.body.append(container); const root = createRoot(container); try { await act(async () => root.render()); await act(async () => root.render()); expect(request).toHaveBeenCalledTimes(2); await act(async () => { second.resolve(response('project-b')); await Promise.resolve(); }); expect(container.textContent).toBe('project-b'); await act(async () => { first.resolve(response('project-a')); await Promise.resolve(); }); expect(container.textContent).toBe('project-b'); } finally { await act(async () => root.unmount()); container.remove(); } });