Close frontend canonical verification gaps

This commit is contained in:
rcourtman
2026-08-24 22:41:14 +01:00
parent 0a58e77bc6
commit 2f882a569a
9 changed files with 76 additions and 40 deletions
@@ -17,11 +17,8 @@ the duplicated seams made future density, header, phone-disclosure, and form
changes likely to drift. This slice removes those seams and turns the visual
agreement into shared structure plus static enforcement.
Rendered evidence is stored under:
`/Users/rcourtman/.codex/visualizations/2026/08/24/01a03497-2e33-7a81-95ce-f33967bb968d/platform-audit`
The directory contains a desktop and phone capture for every route in the
Rendered evidence is stored in the task's `platform-audit` visual-artifact
directory. It contains a desktop and phone capture for every route in the
coverage matrix, representative open drawers and History tabs, post-change
captures prefixed with `post-`, and independent Computer Use evidence.
@@ -205,6 +202,25 @@ well.
- Availability check drawers intentionally omitting History when no useful
historical series exists.
## Verification closure
- The eight focused stale-contract files passed **38 tests** after their
assertions were migrated to the canonical drawer, disclosure, sorting, and
operator-information contracts.
- The four files that timed out only under the initial unbounded worker load
passed **115 tests** in isolated reruns, confirming contention rather than a
product or contract failure.
- The bounded complete frontend suite passed **1,149 test files** with
**20,676 passing tests** and **3 intentionally skipped Windows-specific
tests**. One test file is intentionally skipped; there were no failed files,
unhandled worker errors, or RPC timeouts.
- `npm run lint` passed, including the theme, copy, and canonical-platform
ownership audits. `npm run type-check` and the production `npm run build`
also passed.
- The production build retained only the existing Vite advisory for modules
that are both statically and dynamically imported; it did not affect build
correctness or the canonical frontend contract.
## Remaining exceptions
There are no known static-audit or platform-page exceptions to the canonical
@@ -7,8 +7,8 @@ const sectionSource = readFileSync(
'utf-8',
);
const overviewTabSource = readFileSync(
resolve(__dirname, '..', 'ResourceDetailDrawerOverviewTab.tsx'),
const drawerSource = readFileSync(
resolve(__dirname, '..', 'ResourceDetailDrawer.tsx'),
'utf-8',
);
@@ -79,14 +79,14 @@ describe('maintenanceVerification API client', () => {
});
});
describe('ResourceDetailDrawerOverviewTab integration', () => {
describe('ResourceDetailDrawer manage-tab integration', () => {
it('renders MaintenanceVerificationSection directly under the operator-state section', () => {
expect(overviewTabSource).toContain("from './MaintenanceVerificationSection'");
expect(overviewTabSource).toContain(
'<MaintenanceVerificationSection resourceId={resource.id} />',
expect(drawerSource).toContain("from './MaintenanceVerificationSection'");
expect(drawerSource).toContain(
'<MaintenanceVerificationSection resourceId={props.resource.id} />',
);
const operatorIndex = overviewTabSource.indexOf('<ResourceOperatorStateSection');
const verificationIndex = overviewTabSource.indexOf('<MaintenanceVerificationSection');
const operatorIndex = drawerSource.indexOf('<ResourceOperatorStateSection');
const verificationIndex = drawerSource.indexOf('<MaintenanceVerificationSection');
expect(operatorIndex).toBeGreaterThan(0);
expect(verificationIndex).toBeGreaterThan(operatorIndex);
});
@@ -85,18 +85,19 @@ const buildKubernetesResource = (): Resource => ({
});
describe('ResourceDetailDrawer kubernetes capabilities', () => {
it('renders Kubernetes capability badges when metric capabilities are present', () => {
const { getByText } = render(() => (
it('keeps raw Kubernetes collection capabilities out of the operator overview', async () => {
const { queryByText } = render(() => (
<ResourceDetailDrawer resource={buildKubernetesResource()} />
));
expect(getByText('Platform signals')).toBeInTheDocument();
expect(getByText('K8s Node CPU/Memory')).toBeInTheDocument();
expect(getByText('Node Telemetry (Agent)')).toBeInTheDocument();
expect(getByText('Pod CPU/Memory')).toBeInTheDocument();
expect(getByText('Pod Network')).toBeInTheDocument();
expect(getByText('Pod Ephemeral Disk')).toBeInTheDocument();
expect(getByText('Pod Disk I/O Unsupported')).toBeInTheDocument();
const details = (await screen.findByTestId('resource-platform-details')) as HTMLDetailsElement;
details.open = true;
fireEvent(details, new Event('toggle'));
expect(queryByText('Platform signals')).toBeNull();
expect(queryByText('K8s Node CPU/Memory')).toBeNull();
expect(queryByText('Node Telemetry (Agent)')).toBeNull();
expect(screen.getByRole('tab', { name: 'Namespaces' })).toBeInTheDocument();
expect(screen.getByRole('tab', { name: 'Deployments' })).toBeInTheDocument();
});
it('uses the canonical Kubernetes cluster name for drawer fetch keys', async () => {
@@ -4,6 +4,12 @@ import type { Resource } from '@/types/resource';
import { ResourceDetailDrawer } from '../ResourceDetailDrawer';
import { resetAIRuntimeState, syncAIRuntimeSettings } from '@/stores/aiRuntimeState';
const expandPlatformDetails = (): void => {
const details = screen.getByTestId('resource-platform-details') as HTMLDetailsElement;
details.open = true;
fireEvent(details, new Event('toggle'));
};
vi.mock('@/components/Workloads/GuestDrawerHistory', () => ({
GuestDrawerHistory: (props: {
target: { resourceType: string; resourceId: string } | null;
@@ -149,7 +155,7 @@ describe('ResourceDetailDrawer machine metrics history', () => {
expect(discovery).toHaveAttribute('data-manual-run', 'true');
});
it('opens agent machine facts by default in table-row presentation', () => {
it('keeps agent machine facts behind the shared nested detail disclosures', () => {
render(() => (
<ResourceDetailDrawer
presentation="table-row"
@@ -191,12 +197,15 @@ describe('ResourceDetailDrawer machine metrics history', () => {
/>
));
expect(screen.queryByTestId('resource-host-details-section')).toBeNull();
expandPlatformDetails();
const machineSection = screen.getByTestId('resource-host-details-section');
expect(within(machineSection).getByText('Machine')).toBeInTheDocument();
expect(
within(machineSection).getByRole('button', { name: 'Hide details' }),
within(machineSection).getByRole('button', { name: 'Show details' }),
).toBeInTheDocument();
expect(within(machineSection).queryByRole('button', { name: 'Show details' })).toBeNull();
expect(within(machineSection).queryByRole('button', { name: 'Hide details' })).toBeNull();
fireEvent.click(within(machineSection).getByRole('button', { name: 'Show details' }));
expect(within(machineSection).getByText('richard-mac-mini.local')).toBeInTheDocument();
expect(within(machineSection).getByText('Network')).toBeInTheDocument();
expect(within(machineSection).getByText('192.168.0.42')).toBeInTheDocument();
@@ -228,6 +237,8 @@ describe('ResourceDetailDrawer machine metrics history', () => {
/>
));
expect(screen.queryByTestId('resource-host-details-section')).toBeNull();
expandPlatformDetails();
const hostSection = screen.getByTestId('resource-host-details-section');
expect(within(hostSection).getByText('Host')).toBeInTheDocument();
expect(within(hostSection).getByRole('button', { name: 'Show host' })).toBeInTheDocument();
@@ -4,6 +4,12 @@ import { fireEvent, render, within } from '@solidjs/testing-library';
import type { Resource } from '@/types/resource';
import { ResourceDetailDrawer } from '@/components/Infrastructure/ResourceDetailDrawer';
const expandPlatformDetails = (getByTestId: (id: string) => HTMLElement): void => {
const details = getByTestId('resource-platform-details') as HTMLDetailsElement;
details.open = true;
fireEvent(details, new Event('toggle'));
};
const wsState = vi.hoisted(() => ({ pmg: [] as any[] }));
const reconnectSpy = vi.hoisted(() => vi.fn());
@@ -90,6 +96,7 @@ describe('ResourceDetailDrawer service cards', () => {
<ResourceDetailDrawer resource={resource} />
));
expandPlatformDetails(getByTestId);
expect(getByText('Service')).toBeInTheDocument();
expect(getByText('2 datastores · 3 jobs')).toBeInTheDocument();
expect(getByText('Platform ID')).toBeInTheDocument();
@@ -105,7 +112,6 @@ describe('ResourceDetailDrawer service cards', () => {
expect(queryByText('Job breakdown')).toBeNull();
expect(queryByText('Types')).toBeNull();
expect(queryByText('Show job detail')).toBeNull();
fireEvent.click(getByRole('button', { name: 'Show access' }));
fireEvent.click(getByRole('button', { name: 'Show jobs' }));
expect(getByText('Datastores')).toBeInTheDocument();
expect(getByText('Jobs')).toBeInTheDocument();
@@ -183,6 +189,7 @@ describe('ResourceDetailDrawer service cards', () => {
<ResourceDetailDrawer resource={resource} />
));
expandPlatformDetails(getByTestId);
expect(getByText('2 datastores · 2 active tasks')).toBeInTheDocument();
fireEvent.click(getByRole('button', { name: 'Show service' }));
const serviceDetails = within(getByTestId('resource-service-details-section'));
@@ -224,10 +231,11 @@ describe('ResourceDetailDrawer service cards', () => {
},
});
const { getByText, getByRole, getByTestId, queryByText } = render(() => (
const { getByText, getByRole, getByTestId, queryByRole, queryByText } = render(() => (
<ResourceDetailDrawer resource={resource} />
));
expandPlatformDetails(getByTestId);
expect(getByText('Service')).toBeInTheDocument();
expect(getByText('519 queued messages · 16 delayed messages')).toBeInTheDocument();
expect(getByText('Platform ID')).toBeInTheDocument();
@@ -253,11 +261,7 @@ describe('ResourceDetailDrawer service cards', () => {
expect(pmgSupportContext.getByText('Updated')).toBeInTheDocument();
expect(getByText('Queue detail').closest('summary')?.textContent).toBe('Queue detail');
expect(getByText('Mail detail').closest('summary')?.textContent).toBe('Mail detail');
fireEvent.click(getByRole('button', { name: 'Show access' }));
expect(getByRole('link', { name: /open pmg thresholds/i })).toHaveAttribute(
'href',
'/alerts/thresholds/mail-gateway',
);
expect(queryByRole('link', { name: /open pmg thresholds/i })).toBeNull();
});
it('keeps PMG freshness in support context even without a node count', () => {
@@ -282,6 +286,7 @@ describe('ResourceDetailDrawer service cards', () => {
const { getByRole, getByTestId } = render(() => <ResourceDetailDrawer resource={resource} />);
expandPlatformDetails(getByTestId);
fireEvent.click(getByRole('button', { name: 'Show service' }));
fireEvent.click(getByRole('button', { name: 'Show mail flow' }));
const pmgSupportContext = within(getByTestId('pmg-support-context'));
@@ -310,10 +315,11 @@ describe('ResourceDetailDrawer service cards', () => {
},
});
const { getByText, getByRole, queryByText } = render(() => (
const { getByText, getByRole, getByTestId, queryByText } = render(() => (
<ResourceDetailDrawer resource={resource} />
));
expandPlatformDetails(getByTestId);
expect(getByText('Service')).toBeInTheDocument();
expect(getByText('18 containers · 4 updates')).toBeInTheDocument();
fireEvent.click(getByRole('button', { name: 'Show service' }));
@@ -153,7 +153,7 @@ describe('platform resource table drawers', () => {
await expectRowOpensResourceDrawer(row!, system.id);
});
it('opens native TrueNAS detail by default from TrueNAS storage topology rows', async () => {
it('keeps native TrueNAS provider detail collapsed from storage topology rows', async () => {
const pool = makeResource({
id: 'storage:tank',
type: 'storage',
@@ -190,7 +190,7 @@ describe('platform resource table drawers', () => {
);
expect(screen.getByTestId('resource-detail-drawer')).toHaveAttribute(
'data-initial-show-truenas-details',
'true',
'false',
);
});
@@ -79,7 +79,7 @@ describe('ProxmoxCoverageTable column visibility', () => {
expect(headers).toContain('Type');
expect(headers).toContain('Target ID');
expect(headers).toContain('Node');
expect(headers).toContain('Posture');
expect(headers).toContain('Posture');
expect(headers).toContain('Restore');
expect(headers).toContain('PBS snapshot');
expect(headers).toContain('Guest snapshot');
@@ -114,7 +114,7 @@ describe('ProxmoxCoverageTable column visibility', () => {
/>
));
expect(headerTexts()).toEqual(['Workload', 'Posture', 'Age', 'PBS', 'Job']);
expect(headerTexts()).toEqual(['Workload', 'Posture', 'Age', 'PBS', 'Job']);
expect(document.body.textContent).toContain('Prot.');
expect(document.body.textContent).not.toContain('VM 100 · pve1');
});
@@ -56,7 +56,7 @@ describe('ProxmoxRecoverableTable responsive columns', () => {
'Workload',
'Via',
'Loc',
'Age',
'Age',
'State',
]);
expect(document.body.textContent).toContain('VM 100');
@@ -73,7 +73,7 @@ describe('ProxmoxRecoverableTable responsive columns', () => {
'Target ID',
'Source',
'Location',
'Created',
'Created',
'Size',
'State',
'Details',
@@ -58,7 +58,9 @@ describe('TrueNASServicesTable', () => {
expect(detail.getByText('2418, 2420')).toBeInTheDocument();
expect(detail.getByText('TrueNAS-SCALE-24.10.2')).toBeInTheDocument();
await fireEvent.click(detail.getByRole('button', { name: 'Close' }));
await fireEvent.click(
detail.getByRole('button', { name: `Collapse ${rows[0].id} details` }),
);
expect(screen.queryByTestId('truenas-service-detail')).not.toBeInTheDocument();
expect(row).toHaveAttribute('aria-expanded', 'false');