prune temp files
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 844 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 233 KiB |
|
Before Width: | Height: | Size: 843 KiB |
|
Before Width: | Height: | Size: 306 KiB |
@@ -1,196 +0,0 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { chromium, devices } from 'playwright';
|
||||
|
||||
const baseUrl = 'https://127.0.0.1:4400';
|
||||
const outputDir = path.resolve(process.cwd(), '..', '..', '..', 'output', 'playwright', 'qa-visual-review');
|
||||
|
||||
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: 'https://127.0.0.1:4400/auth/callback',
|
||||
postLogoutRedirectUri: 'https://127.0.0.1:4400/',
|
||||
scope: 'openid profile email ui.read',
|
||||
audience: 'https://scanner.local',
|
||||
dpopAlgorithms: ['ES256'],
|
||||
refreshLeewaySeconds: 60,
|
||||
},
|
||||
apiBaseUrls: {
|
||||
authority: 'https://authority.local',
|
||||
scanner: 'https://scanner.local',
|
||||
policy: 'https://policy.local',
|
||||
concelier: 'https://concelier.local',
|
||||
attestor: 'https://attestor.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 shellSession = {
|
||||
subjectId: 'qa-visual-user',
|
||||
tenant: 'tenant-default',
|
||||
scopes: [
|
||||
'ui.read',
|
||||
'admin',
|
||||
'ui.admin',
|
||||
'orch:read',
|
||||
'orch:operate',
|
||||
'orch:quota',
|
||||
'findings:read',
|
||||
'vuln:view',
|
||||
'vuln:investigate',
|
||||
'vuln:operate',
|
||||
'vuln:audit',
|
||||
'authority:tenants.read',
|
||||
'advisory:read',
|
||||
'vex:read',
|
||||
'exceptions:read',
|
||||
'exceptions:approve',
|
||||
'aoc:verify',
|
||||
'policy:read',
|
||||
'policy:author',
|
||||
'policy:review',
|
||||
'policy:approve',
|
||||
'policy:simulate',
|
||||
'policy:audit',
|
||||
'health:read',
|
||||
'notify:viewer',
|
||||
'release:read',
|
||||
'release:write',
|
||||
'release:publish',
|
||||
'sbom:read',
|
||||
'signer:read',
|
||||
'analytics.read',
|
||||
'scheduler:read',
|
||||
'scheduler:operate',
|
||||
],
|
||||
};
|
||||
|
||||
const routesToCapture = [
|
||||
'/setup',
|
||||
'/setup/wizard',
|
||||
'/mission-control/board',
|
||||
'/security',
|
||||
'/security/findings',
|
||||
'/releases',
|
||||
'/ops',
|
||||
];
|
||||
|
||||
function sanitizeRoute(route) {
|
||||
return route.replace(/^\//, '').replace(/[/?#=&]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') || 'home';
|
||||
}
|
||||
|
||||
async function applyMocks(page) {
|
||||
await page.route('**/*', (route) => {
|
||||
const url = route.request().url();
|
||||
|
||||
if (url.includes('/config.json')) {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockConfig),
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/platform/envsettings.json')) {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockConfig),
|
||||
});
|
||||
}
|
||||
|
||||
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: [] }),
|
||||
});
|
||||
}
|
||||
|
||||
const apiLike =
|
||||
url.includes('authority.local') ||
|
||||
url.includes('scanner.local') ||
|
||||
url.includes('policy.local') ||
|
||||
url.includes('concelier.local') ||
|
||||
url.includes('attestor.local') ||
|
||||
url.includes('gateway.local') ||
|
||||
url.includes('/platform/') ||
|
||||
url.includes('/authority/') ||
|
||||
url.includes('/scanner/') ||
|
||||
url.includes('/policy/') ||
|
||||
url.includes('/concelier/') ||
|
||||
url.includes('/attestor/') ||
|
||||
url.includes('/api/');
|
||||
|
||||
if (apiLike) {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ items: [], data: [], total: 0 }),
|
||||
});
|
||||
}
|
||||
|
||||
return route.continue();
|
||||
});
|
||||
|
||||
await page.addInitScript((session) => {
|
||||
window.__stellaopsTestSession = session;
|
||||
}, shellSession);
|
||||
}
|
||||
|
||||
async function captureContext(browser, name, contextOptions) {
|
||||
const context = await browser.newContext({ ignoreHTTPSErrors: true, ...contextOptions });
|
||||
const page = await context.newPage();
|
||||
|
||||
await applyMocks(page);
|
||||
|
||||
for (const route of routesToCapture) {
|
||||
const fullUrl = `${baseUrl}${route}`;
|
||||
await page.goto(fullUrl, { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(2500);
|
||||
|
||||
const file = path.join(outputDir, `${name}-${sanitizeRoute(route)}.png`);
|
||||
await page.screenshot({ path: file, fullPage: true });
|
||||
console.log(`[${name}] captured ${route} -> ${file}`);
|
||||
}
|
||||
|
||||
await context.close();
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await fs.mkdir(outputDir, { recursive: true });
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
|
||||
try {
|
||||
await captureContext(browser, 'desktop', { viewport: { width: 1440, height: 1024 } });
|
||||
await captureContext(browser, 'mobile', devices['iPhone 13']);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
console.log(`Screenshots saved in ${outputDir}`);
|
||||
})();
|
||||
|
Before Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 122 KiB |