ui fixes
This commit is contained in:
@@ -9,6 +9,7 @@ const shellSession = {
|
||||
...policyAuthorSession.scopes,
|
||||
'ui.read',
|
||||
'admin',
|
||||
'ui.admin',
|
||||
'orch:read',
|
||||
'orch:operate',
|
||||
'orch:quota',
|
||||
@@ -23,6 +24,19 @@ const shellSession = {
|
||||
'exceptions:read',
|
||||
'exceptions:approve',
|
||||
'aoc:verify',
|
||||
'policy:read',
|
||||
'policy:author',
|
||||
'policy:review',
|
||||
'policy:approve',
|
||||
'policy:simulate',
|
||||
'policy:audit',
|
||||
'health:read',
|
||||
'notify:viewer',
|
||||
'release:read',
|
||||
'release:write',
|
||||
'release:publish',
|
||||
'sbom:read',
|
||||
'signer:read',
|
||||
]),
|
||||
],
|
||||
};
|
||||
@@ -79,42 +93,35 @@ async function setupShell(page: Page): Promise<void> {
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockConfig),
|
||||
})
|
||||
}),
|
||||
);
|
||||
await page.route('**/config.json', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockConfig),
|
||||
})
|
||||
}),
|
||||
);
|
||||
await page.route('**/authority/.well-known/openid-configuration', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(oidcConfig),
|
||||
})
|
||||
}),
|
||||
);
|
||||
await page.route('**/.well-known/openid-configuration', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(oidcConfig),
|
||||
})
|
||||
}),
|
||||
);
|
||||
await page.route('**/authority/.well-known/jwks.json', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ keys: [] }),
|
||||
})
|
||||
);
|
||||
await page.route('**/authority/connect/**', (route) =>
|
||||
route.fulfill({
|
||||
status: 400,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ error: 'not-used-in-a11y-e2e' }),
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,23 +134,6 @@ async function ensureShell(page: Page): Promise<void> {
|
||||
await expect(page.locator('aside.sidebar')).toHaveCount(1, { timeout: 15000 });
|
||||
}
|
||||
|
||||
async function openSidebarGroupRoute(
|
||||
page: Page,
|
||||
groupLabel: string,
|
||||
targetHref: string
|
||||
): Promise<void> {
|
||||
const sidebar = page.locator('aside.sidebar');
|
||||
const targetLink = sidebar.locator(`a[href="${targetHref}"]`).first();
|
||||
const isVisible = await targetLink.isVisible().catch(() => false);
|
||||
|
||||
if (!isVisible) {
|
||||
await sidebar.getByRole('button', { name: groupLabel, exact: true }).click();
|
||||
}
|
||||
|
||||
await expect(targetLink).toBeVisible();
|
||||
await targetLink.click();
|
||||
}
|
||||
|
||||
test.describe.configure({ mode: 'serial' });
|
||||
|
||||
test.describe('IA v2 accessibility and regression', () => {
|
||||
@@ -152,13 +142,7 @@ test.describe('IA v2 accessibility and regression', () => {
|
||||
});
|
||||
|
||||
test('canonical roots expose landmarks and navigation controls', async ({ page }) => {
|
||||
const roots = [
|
||||
'/dashboard',
|
||||
'/release-control',
|
||||
'/security-risk',
|
||||
'/evidence-audit',
|
||||
'/administration',
|
||||
];
|
||||
const roots = ['/mission-control/board', '/releases', '/security', '/evidence', '/ops', '/setup'];
|
||||
|
||||
for (const path of roots) {
|
||||
await go(page, path);
|
||||
@@ -167,20 +151,10 @@ test.describe('IA v2 accessibility and regression', () => {
|
||||
expect(landmarkCount).toBeGreaterThan(1);
|
||||
await expect(page.locator('aside.sidebar a, aside.sidebar button').first()).toBeVisible();
|
||||
}
|
||||
|
||||
// /platform-ops and /integrations are proxy-captured in dev mode.
|
||||
// Validate both via in-app navigation.
|
||||
await go(page, '/dashboard');
|
||||
await openSidebarGroupRoute(page, 'Platform Ops', '/platform-ops/data-integrity');
|
||||
await expect(page).toHaveURL(/\/platform-ops\/data-integrity$/);
|
||||
|
||||
await go(page, '/dashboard');
|
||||
await openSidebarGroupRoute(page, 'Integrations', '/integrations');
|
||||
await expect(page).toHaveURL(/\/integrations$/);
|
||||
});
|
||||
|
||||
test('keyboard navigation moves focus across shell controls', async ({ page }) => {
|
||||
await go(page, '/dashboard');
|
||||
await go(page, '/mission-control/board');
|
||||
await ensureShell(page);
|
||||
|
||||
const focusedElements: string[] = [];
|
||||
@@ -198,32 +172,29 @@ test.describe('IA v2 accessibility and regression', () => {
|
||||
});
|
||||
|
||||
test('deprecated root labels are absent from primary nav', async ({ page }) => {
|
||||
await go(page, '/dashboard');
|
||||
await go(page, '/mission-control/board');
|
||||
await ensureShell(page);
|
||||
const navText = (await page.locator('aside.sidebar nav').textContent()) ?? '';
|
||||
|
||||
expect(navText).not.toContain('Operations');
|
||||
expect(navText).not.toContain('Security & Risk');
|
||||
expect(navText).not.toContain('Evidence & Audit');
|
||||
expect(navText).not.toContain('Platform Ops');
|
||||
expect(navText).not.toContain('Administration');
|
||||
expect(navText).not.toContain('Policy Studio');
|
||||
expect(navText).not.toContain('\nSecurity\n');
|
||||
expect(navText).not.toContain('\nEvidence\n');
|
||||
});
|
||||
|
||||
test('breadcrumbs render canonical ownership on key shell routes', async ({ page }) => {
|
||||
const checks: Array<{ path: string; expected: string }> = [
|
||||
{ path: '/release-control/setup', expected: 'Setup' },
|
||||
{ path: '/security-risk/advisory-sources', expected: 'Advisory Sources' },
|
||||
{ path: '/evidence-audit/replay', expected: 'Replay / Verify' },
|
||||
{ path: '/platform-ops/data-integrity', expected: 'Data Integrity' },
|
||||
{ path: '/administration/trust-signing', expected: 'Trust & Signing' },
|
||||
{ path: '/mission-control/board', expected: 'Mission Board' },
|
||||
{ path: '/releases/versions', expected: 'Release Versions' },
|
||||
{ path: '/security/advisories-vex', expected: 'Advisories & VEX' },
|
||||
{ path: '/evidence/verify-replay', expected: 'Verify & Replay' },
|
||||
{ path: '/ops/operations/data-integrity', expected: 'Data Integrity' },
|
||||
{ path: '/setup/topology/agents', expected: 'Agent Fleet' },
|
||||
];
|
||||
|
||||
for (const check of checks) {
|
||||
if (check.path === '/platform-ops/data-integrity') {
|
||||
await go(page, '/dashboard');
|
||||
await openSidebarGroupRoute(page, 'Platform Ops', '/platform-ops/data-integrity');
|
||||
} else {
|
||||
await go(page, check.path);
|
||||
}
|
||||
await go(page, check.path);
|
||||
await ensureShell(page);
|
||||
const breadcrumb = page.locator('app-breadcrumb nav.breadcrumb');
|
||||
await expect(breadcrumb).toHaveCount(1);
|
||||
@@ -233,11 +204,11 @@ test.describe('IA v2 accessibility and regression', () => {
|
||||
|
||||
test('mobile viewport keeps shell usable without horizontal overflow', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await go(page, '/dashboard');
|
||||
await go(page, '/mission-control/board');
|
||||
await expect(page.locator('.topbar__menu-toggle')).toBeVisible();
|
||||
|
||||
const hasHorizontalScroll = await page.evaluate(
|
||||
() => document.documentElement.scrollWidth > document.documentElement.clientWidth
|
||||
() => document.documentElement.scrollWidth > document.documentElement.clientWidth,
|
||||
);
|
||||
expect(hasHorizontalScroll).toBe(false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user