Files
git.stella-ops.org/src/Web/StellaOps.Web/tests/e2e/doctor-registry.spec.ts
2026-02-21 19:10:28 +02:00

212 lines
6.4 KiB
TypeScript

import { expect, test, type Page } from '@playwright/test';
import { policyAuthorSession } from '../../src/app/testing';
const mockConfig = {
authority: {
issuer: 'https://authority.local',
clientId: 'stella-ops-ui',
authorizeEndpoint: 'https://authority.local/connect/authorize',
tokenEndpoint: 'https://authority.local/connect/token',
logoutEndpoint: 'https://authority.local/connect/logout',
redirectUri: 'http://127.0.0.1:4400/auth/callback',
postLogoutRedirectUri: 'http://127.0.0.1:4400/',
scope: 'openid profile email ui.read doctor:read',
audience: 'https://doctor.local',
},
apiBaseUrls: {
authority: 'https://authority.local',
doctor: 'https://doctor.local',
gateway: 'https://gateway.local',
},
quickstartMode: true,
setup: 'complete',
};
const oidcConfig = {
issuer: mockConfig.authority.issuer,
authorization_endpoint: mockConfig.authority.authorizeEndpoint,
token_endpoint: mockConfig.authority.tokenEndpoint,
jwks_uri: 'https://authority.local/.well-known/jwks.json',
response_types_supported: ['code'],
subject_types_supported: ['public'],
id_token_signing_alg_values_supported: ['RS256'],
};
const doctorSession = {
...policyAuthorSession,
scopes: [
...new Set([
...policyAuthorSession.scopes,
'ui.read',
'admin',
'ui.admin',
'orch:read',
'orch:operate',
'health:read',
'doctor:read',
]),
],
};
const mockPlugins = {
plugins: [
{
pluginId: 'integration.registry',
displayName: 'Registry Integration',
category: 'integration',
version: '1.0.0',
checkCount: 3,
},
],
total: 1,
};
const mockChecks = {
checks: [
{
checkId: 'integration.registry.v2-endpoint',
name: 'V2 Endpoint Check',
description: 'Verify OCI registry V2 API endpoint accessibility',
pluginId: 'integration.registry',
category: 'integration',
defaultSeverity: 'fail',
tags: ['registry', 'oci', 'connectivity'],
estimatedDurationMs: 5000,
},
{
checkId: 'integration.registry.auth-config',
name: 'Authentication Config',
description: 'Validate registry authentication configuration',
pluginId: 'integration.registry',
category: 'integration',
defaultSeverity: 'fail',
tags: ['registry', 'oci', 'auth'],
estimatedDurationMs: 3000,
},
{
checkId: 'integration.registry.referrers-api',
name: 'Referrers API Support',
description: 'Detect OCI 1.1 Referrers API support',
pluginId: 'integration.registry',
category: 'integration',
defaultSeverity: 'warn',
tags: ['registry', 'oci', 'referrers'],
estimatedDurationMs: 4000,
},
],
total: 3,
};
async function setupDoctorPage(page: Page): Promise<void> {
await page.addInitScript((stubSession) => {
(window as any).__stellaopsTestSession = stubSession;
}, doctorSession);
await page.route('**/config.json', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(mockConfig),
}),
);
await page.route('**/platform/envsettings.json', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(mockConfig),
}),
);
await page.route('https://authority.local/**', (route) => {
const url = route.request().url();
if (url.includes('/.well-known/openid-configuration')) {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(oidcConfig),
});
}
if (url.includes('/.well-known/jwks.json')) {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ keys: [] }),
});
}
return route.abort();
});
await page.route('**/doctor/api/v1/doctor/plugins**', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(mockPlugins),
}),
);
await page.route('**/doctor/api/v1/doctor/checks**', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(mockChecks),
}),
);
await page.route('**/doctor/api/v1/doctor/run', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ runId: 'dr-mock-001' }),
}),
);
await page.route('**/doctor/api/v1/doctor/run/**', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
runId: 'dr-mock-001',
status: 'completed',
startedAt: '2026-02-21T10:00:00Z',
completedAt: '2026-02-21T10:00:10Z',
durationMs: 10000,
summary: { passed: 2, info: 0, warnings: 1, failed: 0, skipped: 0, total: 3 },
overallSeverity: 'warn',
results: [],
}),
}),
);
}
async function openDoctor(page: Page): Promise<void> {
await page.goto('/ops/operations/doctor', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => null);
}
test.describe('Doctor dashboard registry surface', () => {
test.beforeEach(async ({ page }) => {
await setupDoctorPage(page);
});
test('loads Doctor diagnostics page with run controls', async ({ page }) => {
await openDoctor(page);
await expect(page.getByRole('heading', { name: 'Doctor Diagnostics' })).toBeVisible({
timeout: 15000,
});
await expect(page.getByRole('button', { name: /Quick Check/i })).toBeVisible();
await expect(page.getByRole('button', { name: /Normal Check/i })).toBeVisible();
await expect(page.getByRole('button', { name: /Full Check/i })).toBeVisible();
});
test('renders registry plugin and checks in doctor packs', async ({ page }) => {
await openDoctor(page);
await expect(page.getByRole('heading', { name: /Doctor Packs/i })).toBeVisible({ timeout: 15000 });
await expect(page.getByText(/Registry Integration/i)).toBeVisible();
await expect(page.getByText(/integration\.registry\.v2-endpoint/i)).toBeVisible();
});
test('filter controls and initial empty-state are visible', async ({ page }) => {
await openDoctor(page);
await expect(page.locator('#category-filter')).toBeVisible();
await expect(page.locator('#search-filter')).toBeVisible();
await expect(page.getByText(/No Diagnostics Run Yet/i)).toBeVisible();
});
});