import React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import V2AgentControlSection, { AgentControlLoader } from '../components/V2AgentControlSection'; import i18n, { i18nReady } from '../../i18n'; jest.mock('../../utils/axiosConfig', () => ({ __esModule: true, default: { get: jest.fn() }, })); const api = jest.requireMock('../../utils/axiosConfig').default; beforeAll(async () => { await i18nReady; await i18n.changeLanguage('en'); }); const show = (state: 'revoked' | 'stale' | 'never' | 'connected') => render( , ); it('shows a revoked wrapper key and its one reconnect route', () => { show('revoked'); expect(screen.getByTestId('agent-control-section')).toHaveTextContent('Disconnected: key revoked'); expect(screen.getByRole('link', { name: 'Reconnect' })) .toHaveAttribute('href', '/v2/agents/byo?pod=pod-1&name=local&instanceId=default&reconnect=1&mode=machine'); }); it('keeps a never-connected key off the reconnect path', () => { show('never'); expect(screen.getByTestId('agent-control-section')).toHaveTextContent('Not connected yet'); expect(screen.queryByRole('link', { name: 'Reconnect' })).toBeNull(); }); it('offers the connected wrapper one owner-directed key regeneration route', () => { show('connected'); expect(screen.getByRole('link', { name: 'Regenerate key' })) .toHaveAttribute('href', '/v2/agents/byo?pod=pod-1&name=local&instanceId=default&reconnect=1&mode=machine'); expect(screen.queryByRole('link', { name: 'Reconnect' })).toBeNull(); }); it('keeps a nondefault instance on the connected wrapper key route', () => { render( ); expect(screen.getByRole('link', { name: 'Regenerate key' })) .toHaveAttribute('href', '/v2/agents/byo?pod=pod-1&name=local&instanceId=alpha&reconnect=1&mode=machine'); }); it('loads connection state from an installer-owned pod', async () => { const onConnectionState = jest.fn(); api.get.mockImplementation((url: string) => { if (url.endsWith('/manage-settings')) return Promise.resolve({ data: { installations: [{ podId: 'read-only-pod' }], writablePodId: 'owned-pod', } }); if (url === '/api/registry/pods/owned-pod/agents') return Promise.resolve({ data: { agents: [{ name: 'local', instanceId: 'default', runtime: { runtimeType: 'wrapper' }, connection: { state: 'revoked', lastSeenAt: null }, }] } }); return Promise.reject(new Error('Unexpected request')); }); render(); expect(await screen.findByRole('link', { name: 'Reconnect' })) .toHaveAttribute('href', '/v2/agents/byo?pod=owned-pod&name=local&instanceId=default&reconnect=1&mode=machine'); expect(api.get).toHaveBeenCalledWith('/api/registry/agents/local/manage-settings', { params: { instanceId: 'default' } }); expect(onConnectionState).toHaveBeenCalledWith('revoked'); }); it('refreshes the header after a key change and drops the old connected state', async () => { let revoked = false; api.get.mockImplementation((url: string) => { if (url.endsWith('/manage-settings')) return Promise.resolve({ data: { writablePodId: 'owned-pod' } }); if (url === '/api/registry/pods/owned-pod/agents') return Promise.resolve({ data: { agents: [{ name: 'local', instanceId: 'default', runtime: { runtimeType: 'webhook' }, connection: { state: revoked ? 'revoked' : 'connected', lastSeenAt: revoked ? null : new Date().toISOString() }, }] } }); return Promise.reject(new Error('Unexpected request')); }); const renderLoader = (refreshNonce: number) => ; const view = render(renderLoader(0)); expect(await screen.findByText('Connected')).toBeInTheDocument(); revoked = true; view.rerender(renderLoader(1)); expect(await screen.findByText('Disconnected: key revoked')).toBeInTheDocument(); expect(screen.queryByText('Connected')).toBeNull(); }); it('keeps Control steady while a key-change refresh is pending', async () => { let resolveRefresh: ((value: unknown) => void) | undefined; let rosterReads = 0; api.get.mockImplementation((url: string) => { if (url.endsWith('/manage-settings')) return Promise.resolve({ data: { writablePodId: 'owned-pod' } }); if (url === '/api/registry/pods/owned-pod/agents') { rosterReads += 1; if (rosterReads === 2) return new Promise((resolve) => { resolveRefresh = resolve; }); return Promise.resolve({ data: { agents: [{ name: 'local', instanceId: 'default', runtime: { runtimeType: 'wrapper' }, connection: { state: 'connected', lastSeenAt: new Date().toISOString() }, }] } }); } return Promise.reject(new Error('Unexpected request')); }); const renderLoader = (refreshNonce: number) => ; const view = render(renderLoader(0)); expect(await screen.findByRole('link', { name: 'Regenerate key' })).toBeInTheDocument(); view.rerender(renderLoader(1)); await waitFor(() => expect(rosterReads).toBe(2)); expect(screen.getByRole('link', { name: 'Regenerate key' })).toBeInTheDocument(); expect(screen.queryByText('Checking connection…')).toBeNull(); resolveRefresh?.({ data: { agents: [{ name: 'local', instanceId: 'default', runtime: { runtimeType: 'wrapper' }, connection: { state: 'revoked', lastSeenAt: null }, }] } }); expect(await screen.findByRole('link', { name: 'Reconnect' })).toBeInTheDocument(); }); it('uses unavailable only when the roster has no connection signal', async () => { api.get.mockImplementation((url: string) => { if (url.endsWith('/manage-settings')) return Promise.resolve({ data: { writablePodId: 'owned-pod' } }); if (url === '/api/registry/pods/owned-pod/agents') return Promise.resolve({ data: { agents: [{ name: 'local', instanceId: 'default', runtime: { runtimeType: 'native' }, }] } }); return Promise.reject(new Error('Unexpected request')); }); render(); await waitFor(() => expect(screen.getByRole('alert')).toHaveTextContent('Connection status unavailable')); });