import React, { act } from 'react'; import { createRoot } from 'react-dom/client'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { GraphProvisioningHud } from '@features/agent-graph/renderer/ui/GraphProvisioningHud'; const hoisted = vi.hoisted(() => ({ stepperProps: [] as { active?: boolean }[], })); const hookState = { presentation: null as { isActive: boolean; isFailed: boolean; hasMembersStillJoining: boolean; failedSpawnCount: number; compactTone: 'default' | 'warning' | 'error' | 'success'; compactTitle: string; compactDetail?: string | null; currentStepIndex: number; progress: { runId: string }; } | null, runInstanceKey: 'team:run-1:2026-04-13T10:00:00.000Z', }; vi.mock('@renderer/components/team/useTeamProvisioningPresentation', () => ({ useTeamProvisioningPresentation: () => hookState, })); vi.mock('@renderer/components/ui/badge', () => ({ Badge: ({ children }: { children: React.ReactNode }) => React.createElement('span', null, children), })); vi.mock('@renderer/components/team/StepProgressBar', () => ({ StepProgressBar: (props: { active?: boolean }) => { hoisted.stepperProps.push(props); return React.createElement( 'div', { 'data-testid': 'stepper', 'data-stepper-active': props.active ? 'true' : 'false', }, 'stepper' ); }, })); vi.mock('@renderer/components/team/TeamProvisioningPanel', () => ({ TeamProvisioningPanel: ({ defaultLogsOpen }: { defaultLogsOpen?: boolean }) => React.createElement( 'div', { 'data-testid': 'panel', 'data-default-logs-open': defaultLogsOpen ? 'true' : 'false' }, 'provisioning-panel' ), })); describe('GraphProvisioningHud', () => { afterEach(() => { document.body.innerHTML = ''; hookState.presentation = null; hookState.runInstanceKey = 'team:run-1:2026-04-13T10:00:00.000Z'; hoisted.stepperProps = []; }); it('hides the graph launch hud once provisioning is ready', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); hookState.presentation = { isActive: false, isFailed: false, hasMembersStillJoining: false, failedSpawnCount: 0, compactTone: 'success', compactTitle: 'Team launched', compactDetail: 'All 3 teammates joined', currentStepIndex: 4, progress: { runId: 'run-1' }, }; const host = document.createElement('div'); document.body.appendChild(host); const root = createRoot(host); await act(async () => { root.render( React.createElement(GraphProvisioningHud, { teamName: 'northstar-core', }) ); await Promise.resolve(); }); expect(host.textContent).toBe(''); expect(host.querySelector('[data-testid="stepper"]')).toBeNull(); expect(document.body.textContent).not.toContain('provisioning-panel'); await act(async () => { root.unmount(); await Promise.resolve(); }); }); it('opens launch details in a separate dialog when the stepper is clicked', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); hookState.presentation = { isActive: true, isFailed: false, hasMembersStillJoining: true, failedSpawnCount: 0, compactTone: 'default', compactTitle: 'Launching team', compactDetail: '1 teammate still joining', currentStepIndex: 2, progress: { runId: 'run-3' }, }; const host = document.createElement('div'); document.body.appendChild(host); const root = createRoot(host); await act(async () => { root.render( React.createElement(GraphProvisioningHud, { teamName: 'northstar-core', }) ); await Promise.resolve(); }); const openButton = host.querySelector('button[aria-label]'); expect(openButton).not.toBeNull(); expect(host.querySelector('[data-testid="stepper"]')?.getAttribute('data-stepper-active')).toBe( 'true' ); await act(async () => { openButton?.dispatchEvent(new MouseEvent('click', { bubbles: true })); await Promise.resolve(); }); expect(document.body.textContent).toContain('provisioning-panel'); expect( document.body.querySelector('[data-testid="panel"]')?.getAttribute('data-default-logs-open') ).toBe('true'); await act(async () => { root.unmount(); await Promise.resolve(); }); }); it('renders the failed graph hud without active stepper animation', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); hookState.presentation = { isActive: false, isFailed: true, hasMembersStillJoining: false, failedSpawnCount: 1, compactTone: 'error', compactTitle: 'Launch failed', compactDetail: 'alice failed to start', currentStepIndex: 2, progress: { runId: 'run-4' }, }; const host = document.createElement('div'); document.body.appendChild(host); const root = createRoot(host); await act(async () => { root.render( React.createElement(GraphProvisioningHud, { teamName: 'northstar-core', }) ); await Promise.resolve(); }); expect(host.querySelector('[data-testid="stepper"]')?.getAttribute('data-stepper-active')).toBe( 'false' ); await act(async () => { root.unmount(); await Promise.resolve(); }); }); it('does not render or animate when disabled for an inactive graph tab', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); hookState.presentation = { isActive: true, isFailed: false, hasMembersStillJoining: false, failedSpawnCount: 0, compactTone: 'default', compactTitle: 'Launching team', compactDetail: 'Waiting for members', currentStepIndex: 1, progress: { runId: 'run-2' }, }; const host = document.createElement('div'); document.body.appendChild(host); const root = createRoot(host); await act(async () => { root.render( React.createElement(GraphProvisioningHud, { teamName: 'northstar-core', enabled: false, }) ); await Promise.resolve(); }); expect(host.textContent).toBe(''); await act(async () => { root.unmount(); await Promise.resolve(); }); }); });