Fix web route regressions from Playwright QA
This commit is contained in:
@@ -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 {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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: () =>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user