Files
git.stella-ops.org/src/Web/StellaOps.Web/e2e/interactive-smoke.e2e.spec.ts

569 lines
21 KiB
TypeScript

/**
* Interactive Smoke Tests - Section by Section
* Tests actual UI interactions, clicks, navigation elements on every screen.
* Takes screenshots for visual verification.
*/
import { test, expect } from './fixtures/auth.fixture';
const SCREENSHOT_DIR = 'e2e/screenshots';
async function snap(page: import('@playwright/test').Page, label: string) {
await page.screenshot({ path: `${SCREENSHOT_DIR}/${label}.png`, fullPage: true });
}
function collectErrors(page: import('@playwright/test').Page) {
const errors: string[] = [];
page.on('console', (msg) => {
if (msg.type() === 'error') errors.push(msg.text());
});
page.on('pageerror', (err) => errors.push(err.message));
return errors;
}
async function go(page: import('@playwright/test').Page, path: string) {
await page.goto(path, { waitUntil: 'networkidle', timeout: 30_000 });
await page.waitForLoadState('domcontentloaded');
await page.waitForTimeout(1500);
}
// SECTION 1: Mission Control
test.describe('Section 1: Mission Control', () => {
test('dashboard loads with widgets', async ({ authenticatedPage: page }) => {
const errors = collectErrors(page);
await go(page, '/');
await snap(page, '01-mission-control-dashboard');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(20);
const nav = page.locator('nav, [role="navigation"], .sidebar, .sidenav, mat-sidenav');
const navCount = await nav.count();
expect(navCount, 'Should have navigation element').toBeGreaterThanOrEqual(1);
const criticalErrors = errors.filter(e =>
e.includes('NG0') || e.includes('TypeError') || e.includes('ReferenceError')
);
expect(criticalErrors, 'Critical errors: ' + criticalErrors.join('\n')).toHaveLength(0);
});
test('sidebar navigation has main sections', async ({ authenticatedPage: page }) => {
await go(page, '/');
const links = page.locator('a[href], [routerlink], mat-list-item, .nav-item, .menu-item');
const count = await links.count();
expect(count, 'Should have navigation links').toBeGreaterThan(3);
await snap(page, '01-mission-control-nav');
});
test('mission control alerts page', async ({ authenticatedPage: page }) => {
const errors = collectErrors(page);
await go(page, '/mission-control/alerts');
await snap(page, '01-mission-control-alerts');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
const criticalErrors = errors.filter(e => e.includes('NG0'));
expect(criticalErrors).toHaveLength(0);
});
test('mission control activity page', async ({ authenticatedPage: page }) => {
const errors = collectErrors(page);
await go(page, '/mission-control/activity');
await snap(page, '01-mission-control-activity');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
const criticalErrors = errors.filter(e => e.includes('NG0'));
expect(criticalErrors).toHaveLength(0);
});
});
// SECTION 2: Releases
test.describe('Section 2: Releases', () => {
test('releases overview loads', async ({ authenticatedPage: page }) => {
const errors = collectErrors(page);
await go(page, '/releases/overview');
await snap(page, '02-releases-overview');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
const criticalErrors = errors.filter(e => e.includes('NG0'));
expect(criticalErrors).toHaveLength(0);
});
test('release versions page', async ({ authenticatedPage: page }) => {
await go(page, '/releases/versions');
await snap(page, '02-releases-versions');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('releases runs page', async ({ authenticatedPage: page }) => {
await go(page, '/releases/runs');
await snap(page, '02-releases-runs');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('approvals queue page', async ({ authenticatedPage: page }) => {
await go(page, '/releases/approvals');
await snap(page, '02-releases-approvals');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('promotion queue page', async ({ authenticatedPage: page }) => {
await go(page, '/releases/promotion-queue');
await snap(page, '02-releases-promotion-queue');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('environments page', async ({ authenticatedPage: page }) => {
await go(page, '/releases/environments');
await snap(page, '02-releases-environments');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('deployments page', async ({ authenticatedPage: page }) => {
await go(page, '/releases/deployments');
await snap(page, '02-releases-deployments');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 3: Security
test.describe('Section 3: Security', () => {
test('security posture page', async ({ authenticatedPage: page }) => {
const errors = collectErrors(page);
await go(page, '/security/posture');
await snap(page, '03-security-posture');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
const criticalErrors = errors.filter(e => e.includes('NG0'));
expect(criticalErrors).toHaveLength(0);
});
test('security triage page', async ({ authenticatedPage: page }) => {
await go(page, '/security/triage');
await snap(page, '03-security-triage');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('advisories and VEX page', async ({ authenticatedPage: page }) => {
await go(page, '/security/advisories-vex');
await snap(page, '03-security-advisories-vex');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('disposition center page', async ({ authenticatedPage: page }) => {
await go(page, '/security/disposition');
await snap(page, '03-security-disposition');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('supply chain data page', async ({ authenticatedPage: page }) => {
await go(page, '/security/supply-chain-data');
await snap(page, '03-security-supply-chain');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('reachability center page', async ({ authenticatedPage: page }) => {
await go(page, '/security/reachability');
await snap(page, '03-security-reachability');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('security reports page', async ({ authenticatedPage: page }) => {
await go(page, '/security/reports');
await snap(page, '03-security-reports');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 4: Evidence
test.describe('Section 4: Evidence', () => {
test('evidence overview', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/overview');
await snap(page, '04-evidence-overview');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('decision capsules page', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/capsules');
await snap(page, '04-evidence-capsules');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('verify and replay page', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/verify-replay');
await snap(page, '04-evidence-verify-replay');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('evidence exports page', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/exports');
await snap(page, '04-evidence-exports');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('audit log dashboard', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/audit-log');
await snap(page, '04-evidence-audit-log');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('audit log events', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/audit-log/events');
await snap(page, '04-evidence-audit-events');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('audit timeline search', async ({ authenticatedPage: page }) => {
await go(page, '/evidence/audit-log/timeline');
await snap(page, '04-evidence-audit-timeline');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 5: Ops - Operations
test.describe('Section 5: Ops - Operations', () => {
test('ops overview', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations');
await snap(page, '05-ops-overview');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('jobs and queues', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations/jobs-queues');
await snap(page, '05-ops-jobs-queues');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('system health', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations/system-health');
await snap(page, '05-ops-system-health');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('jobengine dashboard', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations/jobengine');
await snap(page, '05-ops-jobengine');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('doctor diagnostics', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations/doctor');
await snap(page, '05-ops-doctor');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('notifications', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations/notifications');
await snap(page, '05-ops-notifications');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('AI runs list', async ({ authenticatedPage: page }) => {
await go(page, '/ops/operations/ai-runs');
await snap(page, '05-ops-ai-runs');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 6: Ops - Integrations
test.describe('Section 6: Ops - Integrations', () => {
test('integration hub', async ({ authenticatedPage: page }) => {
await go(page, '/ops/integrations');
await snap(page, '06-integrations-hub');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('registries page', async ({ authenticatedPage: page }) => {
await go(page, '/ops/integrations/registries');
await snap(page, '06-integrations-registries');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('source control page', async ({ authenticatedPage: page }) => {
await go(page, '/ops/integrations/scm');
await snap(page, '06-integrations-scm');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('CI/CD page', async ({ authenticatedPage: page }) => {
await go(page, '/ops/integrations/ci');
await snap(page, '06-integrations-ci');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('runtime hosts page', async ({ authenticatedPage: page }) => {
await go(page, '/ops/integrations/runtime-hosts');
await snap(page, '06-integrations-runtime');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 7: Ops - Policy
test.describe('Section 7: Ops - Policy', () => {
test('policy overview', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/overview');
await snap(page, '07-policy-overview');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('policy baselines', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/baselines');
await snap(page, '07-policy-baselines');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('gate catalog', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/gates');
await snap(page, '07-policy-gates');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('shadow mode / simulation', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/simulation');
await snap(page, '07-policy-simulation');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('policy lint', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/simulation/lint');
await snap(page, '07-policy-lint');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('risk budget', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/risk-budget');
await snap(page, '07-policy-risk-budget');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('sealed mode', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/sealed-mode');
await snap(page, '07-policy-sealed-mode');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('policy profiles', async ({ authenticatedPage: page }) => {
await go(page, '/ops/policy/profiles');
await snap(page, '07-policy-profiles');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 8: Setup
test.describe('Section 8: Setup and Configuration', () => {
test('identity and access', async ({ authenticatedPage: page }) => {
await go(page, '/setup/identity-access');
await snap(page, '08-setup-identity');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('tenant and branding', async ({ authenticatedPage: page }) => {
await go(page, '/setup/tenant-branding');
await snap(page, '08-setup-tenant');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('notifications rules', async ({ authenticatedPage: page }) => {
await go(page, '/setup/notifications/rules');
await snap(page, '08-setup-notifications-rules');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('notifications channels', async ({ authenticatedPage: page }) => {
await go(page, '/setup/notifications/channels');
await snap(page, '08-setup-notifications-channels');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('notifications templates', async ({ authenticatedPage: page }) => {
await go(page, '/setup/notifications/templates');
await snap(page, '08-setup-notifications-templates');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('usage and limits', async ({ authenticatedPage: page }) => {
await go(page, '/setup/usage');
await snap(page, '08-setup-usage');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('system settings', async ({ authenticatedPage: page }) => {
await go(page, '/setup/system');
await snap(page, '08-setup-system');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 9: Topology
test.describe('Section 9: Topology', () => {
test('topology overview', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/overview');
await snap(page, '09-topology-overview');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('topology map', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/map');
await snap(page, '09-topology-map');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('regions and environments', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/regions');
await snap(page, '09-topology-regions');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('targets', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/targets');
await snap(page, '09-topology-targets');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('hosts', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/hosts');
await snap(page, '09-topology-hosts');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('agent fleet', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/agents');
await snap(page, '09-topology-agents');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('promotion graph', async ({ authenticatedPage: page }) => {
await go(page, '/setup/topology/promotion-graph');
await snap(page, '09-topology-promotion-graph');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 10: Platform Setup
test.describe('Section 10: Platform Setup', () => {
test('platform setup home', async ({ authenticatedPage: page }) => {
await go(page, '/ops/platform-setup');
await snap(page, '10-platform-setup-home');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('promotion paths', async ({ authenticatedPage: page }) => {
await go(page, '/ops/platform-setup/promotion-paths');
await snap(page, '10-platform-promotion-paths');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('workflows and gates', async ({ authenticatedPage: page }) => {
await go(page, '/ops/platform-setup/workflows-gates');
await snap(page, '10-platform-workflows-gates');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('trust and signing', async ({ authenticatedPage: page }) => {
await go(page, '/ops/platform-setup/trust-signing');
await snap(page, '10-platform-trust-signing');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 11: AI and Analysis
test.describe('Section 11: AI and Analysis', () => {
test('AI chat', async ({ authenticatedPage: page }) => {
await go(page, '/ai/chat');
await snap(page, '11-ai-chat');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('AI autofix', async ({ authenticatedPage: page }) => {
await go(page, '/ai/autofix');
await snap(page, '11-ai-autofix');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('graph explorer', async ({ authenticatedPage: page }) => {
await go(page, '/graph');
await snap(page, '11-graph-explorer');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('timeline', async ({ authenticatedPage: page }) => {
await go(page, '/timeline');
await snap(page, '11-timeline');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
test('change trace', async ({ authenticatedPage: page }) => {
await go(page, '/change-trace');
await snap(page, '11-change-trace');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});
// SECTION 12: Welcome
test.describe('Section 12: Welcome and Setup Wizard', () => {
test('welcome page (no auth)', async ({ page }) => {
await page.goto('/welcome', { waitUntil: 'networkidle', timeout: 30_000 });
await page.waitForTimeout(1500);
await snap(page, '12-welcome');
const body = await page.locator('body').innerText();
expect(body.length).toBeGreaterThan(10);
});
});