// 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)); }