// Synthetic browser acceptance. Run with PLAYWRIGHT_MODULE pointing to Playwright's index.mjs.
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import { createServer } from 'node:http';
import { pathToFileURL } from 'node:url';
import { build } from 'esbuild';
const { chromium } = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href);
assert.ok(!(await readFile('src/app/App.tsx', 'utf8')).includes('context-layer-btn'));
const main = await readFile('src/main.tsx', 'utf8');
const styles = [...main.matchAll(/^import '([^']+\.css)';/gm)].map(([, path]) =>
`import ${JSON.stringify(path.startsWith('.') ? './src/' + path.slice(2) : path)};`).join('\n');
const bundle = await build({
stdin: { contents: `${styles}
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { EnginesControl } from './src/components/EnginesControl';
import { FindingContext, FindingContextBadges } from './src/features/finding-reader/FindingContext';
import { DynamicFilterControls } from './src/features/search-filter/DynamicFilterControls';
import { CONTEXT_CLUSTER_FACET_ID } from './src/features/context-layer/context-cluster-facet';
const record = { id:'synthetic', findingOccurrenceId:'synthetic-occurrence', fields:[] };
function Fixture() {
const [filters, setFilters] = useState({});
window.fixtureApp = { setFacetFilter: (id, filter) => setFilters(filter ? {[id]:filter} : {}) };
return <>
{}} onFilter={window.fixtureApp.setFacetFilter}/>
>;
}
createRoot(document.getElementById('root')).render();`, resolveDir: process.cwd(), loader: 'tsx' },
plugins: [{ name: 'synthetic-context', setup(build) {
build.onResolve({ filter: /(?:AppProvider|use-assessment-context)$/ }, args => ({ path: args.path, namespace: 'fixture' }));
build.onLoad({ filter: /.*/, namespace: 'fixture' }, args => ({ contents: args.path.endsWith('AppProvider')
? 'export const useOptionalApp = () => window.fixtureApp;'
: `export const useAssessmentContext = () => ({status:'ready',context:{catalog:{version:'synthetic'},engine:{version:'synthetic'},
settings:[],findings:[{occurrenceId:'synthetic-occurrence',clusterIds:['synthetic-cluster'],conditionIds:[],declaredReferenceIds:[]}],
clusters:[{clusterId:'synthetic-cluster',label:{en:'Synthetic cluster'},description:{en:'Synthetic example context.'},
state:'present',satisfied:0,unknown:0,notSatisfied:0,minimumSatisfied:1,conditions:[],sources:[]}],
coverage:{uncataloguedWithoutRecognition:0,scannerFindings:1},recognitions:[],techniqueAssignments:[],
semantics:[],scannerRules:[],declaredReferences:[],cisControlAreas:[]}});`, loader: 'js' }));
}}], jsx: 'automatic', bundle: true, write: false, outdir: 'synthetic', format: 'iife',
loader: { '.woff2': 'dataurl', '.woff': 'dataurl' }
});
const server = createServer((request, response) => {
const file = bundle.outputFiles.find(file => request.url === '/' + file.path.split(/[\\/]/).at(-1));
response.setHeader('Content-Type', file ? (request.url.endsWith('.css') ? 'text/css' : 'text/javascript') : 'text/html');
response.end(file?.contents ?? '');
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
let browser;
try {
browser = await chromium.launch({ headless: true, channel: 'msedge' });
const page = await browser.newPage({ viewport: { width: 1000, height: 600 } });
page.on('pageerror', error => console.error(error.message));
await page.goto(`http://127.0.0.1:${server.address().port}/`);
const summary = page.locator('details.finding-context > summary');
const content = page.locator('.finding-context__content');
for (const theme of ['dark', 'light']) {
await page.evaluate(theme => { document.documentElement.dataset.theme = theme; }, theme);
await page.getByLabel('Context Cluster', {exact:true}).selectOption('');
assert.equal(await page.getByLabel('Context Cluster', {exact:true}).locator('option:checked').textContent(), 'Context Cluster: All (1)');
await page.screenshot({path:`.context-count-${theme}.png`});
await page.locator('.context-cluster-badge').click();
assert.equal(await page.getByLabel('Context Cluster', {exact:true}).inputValue(), 'synthetic-cluster');
assert.equal(await content.isVisible(), false);
await summary.click();
assert.equal(await content.isVisible(), true);
await summary.click();
assert.equal(await content.isVisible(), false);
await summary.focus();
await page.keyboard.press('Enter');
assert.equal(await content.isVisible(), true);
await page.keyboard.press('Space');
assert.equal(await content.isVisible(), false);
await page.getByLabel('Context Cluster', {exact:true}).selectOption('');
assert.equal(await summary.isVisible(), true);
const engines = page.getByRole('button', { name: 'Engines', exact: true });
const appearance = () => engines.evaluate(el => ({background:getComputedStyle(el).backgroundColor, color:getComputedStyle(el).color}));
await page.mouse.move(900, 550);
const marked = await appearance();
const expected = await engines.evaluate(el => getComputedStyle(el).getPropertyValue('--engines-button-bg').trim());
assert.ok(expected);
assert.notEqual(marked.background, 'rgba(0, 0, 0, 0)');
await engines.hover();
assert.deepEqual(await appearance(), marked);
await engines.click();
const dialog = page.getByRole('dialog', { name:'Engines', exact:true });
const core = dialog.getByRole('checkbox', {name:'Core Engine Always active'});
assert.equal(await core.isChecked(), true);
assert.equal(await core.isDisabled(), true);
const context = dialog.getByRole('checkbox', {name:'Context Engine', exact:true});
const report = dialog.getByRole('checkbox', {name:'Report Engine', exact:true});
assert.equal(await context.isChecked(), true);
assert.equal(await report.isChecked(), true);
if (process.env.ENGINE_SCREENSHOTS === '1') await page.screenshot({path: `.engines-${theme}.png`});
await context.uncheck(); await report.uncheck();
await page.keyboard.press('Escape');
assert.equal(await dialog.count(), 0);
assert.equal(await engines.evaluate(el => el === document.activeElement), true);
assert.deepEqual(await appearance(), marked);
await engines.click();
assert.equal(await context.isChecked(), false);
assert.equal(await report.isChecked(), false);
await context.check(); await report.check();
await dialog.getByRole('button', {name:'Close window'}).click();
console.log(`${theme}: badge filter, disclosure, blue Engines button, locked Core, checkboxes and dismissal passed`);
}
} finally {
await browser?.close();
await new Promise(resolve => server.close(resolve));
}