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 |