Fix web route regressions from Playwright QA

This commit is contained in:
master
2026-03-06 19:34:55 +02:00
parent 9b86ad825a
commit 2446e2c61d
6 changed files with 161 additions and 4 deletions

View File

@@ -243,7 +243,7 @@ interface MissionSummary {
<section class="domain-card" aria-label="SBOM snapshot">
<div class="card-header">
<h2 class="card-title">SBOM Findings Snapshot</h2>
<a routerLink="/security/sbom/lake" class="card-link">View SBOM</a>
<a routerLink="/security/sbom-lake" class="card-link">View SBOM</a>
</div>
<div class="card-body">
<div class="snapshot-stat">
@@ -1147,4 +1147,3 @@ export class DashboardV3Component {
}

View File

@@ -17,11 +17,26 @@ export const policyGovernanceRoutes: Routes = [
loadComponent: () =>
import('./risk-budget-dashboard.component').then((m) => m.RiskBudgetDashboardComponent),
},
{
path: 'overview',
loadComponent: () =>
import('./risk-budget-dashboard.component').then((m) => m.RiskBudgetDashboardComponent),
},
{
path: 'risk-budget',
loadComponent: () =>
import('./risk-budget-dashboard.component').then((m) => m.RiskBudgetDashboardComponent),
},
{
path: 'budget',
loadComponent: () =>
import('./risk-budget-dashboard.component').then((m) => m.RiskBudgetDashboardComponent),
},
{
path: 'risk-budget/config',
loadComponent: () =>
import('./risk-budget-config.component').then((m) => m.RiskBudgetConfigComponent),
},
{
path: 'budget/config',
loadComponent: () =>

View File

@@ -18,7 +18,7 @@ import { RouterLink } from '@angular/router';
<h2>Policy Baselines</h2>
<p>Environment-scoped baseline definitions and lock rules.</p>
</a>
<a routerLink="/ops/policy/rules" class="card">
<a routerLink="/ops/policy/gates" class="card">
<h2>Governance Rules</h2>
<p>Rule catalog for release control gate enforcement.</p>
</a>
@@ -26,7 +26,7 @@ import { RouterLink } from '@angular/router';
<h2>Policy Simulation</h2>
<p>Dry-run policy evaluations before production rollout.</p>
</a>
<a routerLink="/ops/policy/exceptions" class="card">
<a routerLink="/ops/policy/waivers" class="card">
<h2>Exception Workflow</h2>
<p>Exception requests, approvals, and expiry management.</p>
</a>

View File

@@ -41,6 +41,15 @@ export const SECURITY_RISK_ROUTES: Routes = [
(m) => m.FindingDetailPageComponent
),
},
{
path: 'advisories-vex',
title: 'Advisories & VEX',
data: { breadcrumb: 'Advisories & VEX' },
loadComponent: () =>
import('../features/security/security-disposition-page.component').then(
(m) => m.SecurityDispositionPageComponent
),
},
{
path: 'supply-chain-data',
title: 'Supply-Chain Data',

View File

@@ -95,6 +95,7 @@ const canonicalRoutes = [
'/security/disposition',
'/security/supply-chain-data',
'/security/supply-chain-data/graph',
'/security/sbom-lake',
'/security/reachability',
'/security/reports',
'/evidence',
@@ -177,6 +178,29 @@ const canonicalRoutes = [
'/setup/topology/gate-profiles',
] as const;
const strictRouteExpectations: Partial<Record<(typeof canonicalRoutes)[number], { title: RegExp; texts: string[] }>> = {
'/security/advisories-vex': {
title: /Advisories/i,
texts: ['Security / Advisories & VEX', 'Providers'],
},
'/security/sbom-lake': {
title: /SBOM Lake/i,
texts: ['SBOM Lake', 'Attestation Coverage Metrics'],
},
'/ops/policy': {
title: /Policy/i,
texts: ['Policy Governance', 'Risk Budget Overview'],
},
'/ops/policy/overview': {
title: /Policy/i,
texts: ['Policy Governance', 'Risk Budget Overview'],
},
'/ops/policy/risk-budget': {
title: /Policy/i,
texts: ['Policy Governance', 'Risk Budget Overview'],
},
};
function collectNgErrors(page: Page): string[] {
const errors: string[] = [];
page.on('console', (msg) => {
@@ -1210,6 +1234,13 @@ test.describe('Pre-alpha canonical full route sweep', () => {
test(`route works: ${path}`, async ({ page }) => {
const errors = collectNgErrors(page);
await assertUsableRoute(page, path);
const expectation = strictRouteExpectations[path];
if (expectation) {
await expect(page).toHaveTitle(expectation.title);
for (const text of expectation.texts) {
await expect(page.locator('#main-content')).toContainText(text);
}
}
expect(errors, `Runtime errors on ${path}: ${errors.join('\n')}`).toEqual([]);
});
}
@@ -1240,6 +1271,16 @@ test.describe('Pre-alpha key end-user interactions', () => {
await expect(page.locator('.topbar__primary-action')).toContainText('Export Report');
});
test('mission board SBOM card opens SBOM Lake', async ({ page }) => {
await page.goto('/mission-control/board', { waitUntil: 'domcontentloaded' });
await page.locator('#main-content a[href="/security/sbom-lake"]').first().click();
await expect(page).toHaveURL(/\/security\/sbom-lake$/);
await expect(page).toHaveTitle(/SBOM Lake/i);
await expect(page.locator('#main-content')).toContainText('SBOM Lake');
await expect(page.locator('#main-content')).toContainText('Attestation Coverage Metrics');
});
test('sidebar root navigation works for all canonical workspaces', async ({ page }) => {
await page.goto('/mission-control/board', { waitUntil: 'domcontentloaded' });
await page.locator('aside.sidebar a[href="/releases/overview"]').first().click();