Sprint SPRINT_20260415_002_FE_integration_audit_links_and_dashboard_tips. - integration-hub: integration-detail component + spec with audit links. - dashboard-v3: component + specs (core/testing + tests/dashboard) with getting-started tips. - audit-log: audit-log-table component + spec. - policy-governance: client + scope helper. - deploy-diff: panel + page + service. - graph: graph-filters component. - jobengine: scheduler-workers-panel component. - reachability: reachability-center + witness page components. - release-investigation: release-investigation-context. - E2E: audit-consolidation, integrations, policy-orchestrator specs + live-auth fixture; live-frontdoor-auth script + playwright outputs. - Utility scripts: debug-auth, probe-services, scan-pages. - package.json tweaks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75 lines
2.7 KiB
JavaScript
75 lines
2.7 KiB
JavaScript
import { chromium } from 'playwright';
|
|
|
|
const BASE = 'http://127.1.0.5';
|
|
const USERNAME = process.env.STELLAOPS_FRONTDOOR_USERNAME?.trim()
|
|
|| process.env.STELLAOPS_ADMIN_USER?.trim()
|
|
|| 'admin';
|
|
const PASSWORD = process.env.STELLAOPS_FRONTDOOR_PASSWORD?.trim()
|
|
|| process.env.STELLAOPS_ADMIN_PASS?.trim();
|
|
|
|
(async () => {
|
|
if (!PASSWORD) {
|
|
throw new Error('Set STELLAOPS_FRONTDOOR_PASSWORD or STELLAOPS_ADMIN_PASS before running this script.');
|
|
}
|
|
|
|
const browser = await chromium.launch({ headless: true });
|
|
const context = await browser.newContext({ ignoreHTTPSErrors: true });
|
|
const page = await context.newPage();
|
|
|
|
// Sign in
|
|
console.log('=== SIGNING IN ===');
|
|
await page.goto(BASE + '/', { waitUntil: 'networkidle', timeout: 15000 });
|
|
const signInBtn = page.locator('button:has-text("Sign In"), a:has-text("Sign In")').first();
|
|
try { await signInBtn.click({ timeout: 5000 }); } catch {}
|
|
await page.waitForTimeout(2000);
|
|
try {
|
|
await page.locator('input[name="Username"], input[type="text"]').first().fill(USERNAME, { timeout: 5000 });
|
|
await page.locator('input[type="password"]').first().fill(PASSWORD);
|
|
await page.locator('button[type="submit"]').first().click();
|
|
await page.waitForTimeout(4000);
|
|
} catch (e) { console.log('Login error: ' + e.message); }
|
|
console.log('Signed in: ' + page.url());
|
|
|
|
// Probe specific failing pages
|
|
const failPages = [
|
|
'/operations/scheduler',
|
|
'/operations/notifications',
|
|
'/evidence/bundles',
|
|
'/policy',
|
|
];
|
|
|
|
for (const route of failPages) {
|
|
const apiCalls = [];
|
|
|
|
page.on('response', async (response) => {
|
|
const url = response.url();
|
|
if (url.startsWith(BASE) && !url.includes('.js') && !url.includes('.css') && !url.includes('.html') && !url.includes('/config.json') && !url.includes('.ico')) {
|
|
const path = new URL(url).pathname;
|
|
if (path.startsWith('/api/') || path.startsWith('/v1/') || path.startsWith('/scheduler/') ||
|
|
path.startsWith('/doctor/') || path.startsWith('/console/') || path.startsWith('/health')) {
|
|
let body = '';
|
|
try { body = await response.text(); } catch {}
|
|
apiCalls.push({ path, status: response.status(), body: body.substring(0, 200) });
|
|
}
|
|
}
|
|
});
|
|
|
|
await page.evaluate((r) => {
|
|
window.history.pushState({}, '', r);
|
|
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
}, route);
|
|
|
|
await page.waitForTimeout(4000);
|
|
page.removeAllListeners('response');
|
|
|
|
console.log('\n--- ' + route + ' ---');
|
|
for (const c of apiCalls) {
|
|
console.log(' ' + c.status + ' ' + c.path);
|
|
if (c.status >= 400) console.log(' Body: ' + c.body);
|
|
}
|
|
if (apiCalls.length === 0) console.log(' NO API CALLS');
|
|
}
|
|
|
|
await browser.close();
|
|
})();
|