// @vitest-environment jsdom import { cleanup, render, screen, waitFor } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import type { InstanceContext, InstanceModule } from '../app-shell.js'; import { InstanceDetail, type CapabilityDataSource, type InstanceCapabilityMap, } from './instance-detail.js'; afterEach(cleanup); const owner: InstanceContext = { id: 'owner', name: 'Owner modem', origin: 'https://owner.example/path', status: 'online', authentication: 'authenticated', freshness: 'fresh', }; const capabilities: InstanceCapabilityMap = { overview: { state: 'supported' }, messages: { state: 'degraded', explanation: 'Message history is read-only.' }, calls: { state: 'unsupported', explanation: 'This modem has no voice support.' }, esim: { state: 'unknown', explanation: 'Capability discovery did not report eSIM.' }, }; describe('InstanceDetail', () => { it('makes only supported modules actionable and explains every other capability state', () => { render( , ); expect(screen.getByRole('link', { name: 'Overview' }).getAttribute('href')).toBe( '/instances/owner/overview', ); expect(screen.queryByRole('link', { name: 'Messages' })).toBeNull(); expect(screen.getByText('Message history is read-only.')).toBeTruthy(); expect(screen.getByText('This modem has no voice support.')).toBeTruthy(); expect(screen.getByText('Capability discovery did not report eSIM.')).toBeTruthy(); expect(screen.getAllByText('Capability state is unknown.').length).toBeGreaterThan(0); }); it('never renders or loads context when the direct-route owner does not match', () => { const load = vi.fn(); render( , ); expect(screen.queryByText('Owner modem')).toBeNull(); expect(screen.queryByRole('navigation', { name: 'Instance modules' })).toBeNull(); expect(screen.getByText(/Instance context is unavailable/i)).toBeTruthy(); expect(load).not.toHaveBeenCalled(); }); it('aborts the prior owner load and fences stale results to the latest owner', async () => { const pending = new Map< string, { resolve: (value: InstanceCapabilityMap) => void; signal: AbortSignal } >(); const dataSource: CapabilityDataSource = { load(instanceId, signal) { return new Promise((resolve) => pending.set(instanceId, { resolve, signal })); }, }; const second: InstanceContext = { ...owner, id: 'second', name: 'Second modem' }; const { rerender } = render( , ); await waitFor(() => expect(pending.has('owner')).toBe(true)); rerender( , ); await waitFor(() => expect(pending.has('second')).toBe(true)); expect(pending.get('owner')?.signal.aborted).toBe(true); pending.get('second')?.resolve({ overview: { state: 'supported' } }); expect(await screen.findByRole('link', { name: 'Overview' })).toBeTruthy(); pending .get('owner') ?.resolve({ overview: { state: 'unsupported', explanation: 'Stale owner result' } }); await waitFor(() => expect(screen.queryByText('Stale owner result')).toBeNull()); expect(screen.getByText('Second modem')).toBeTruthy(); }); it.each<[InstanceModule, string]>([ ['cellular', 'Cellular'], ['device-network', 'Device Network'], ['automation', 'Automation'], ['ota', 'OTA'], ])('uses the existing module contract for %s', (module, label) => { render( , ); expect(screen.getByRole('heading', { name: label })).toBeTruthy(); }); });