73 lines
4.0 KiB
JavaScript
73 lines
4.0 KiB
JavaScript
// Synthetic-only browser acceptance; never connects to ASSESSOR or its database.
|
|
// PLAYWRIGHT_MODULE points to an installed Playwright package; SCREENSHOT_DIR is optional.
|
|
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { createServer } from 'node:http';
|
|
import { join } from 'node:path';
|
|
import { pathToFileURL } from 'node:url';
|
|
import { build } from 'esbuild';
|
|
|
|
const { chromium } = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href);
|
|
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 from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { GpoFolderImport } from './src/features/project-import/GpoFolderImport';
|
|
window.showDirectoryPicker = async function() {
|
|
if (this !== window) throw new Error('Incorrect picker receiver');
|
|
return { kind:'directory', name:'Synthetic confidential customer', async *values() {
|
|
throw new DOMException('C:/Customers/Synthetic confidential customer', 'NotFoundError');
|
|
}};
|
|
};
|
|
createRoot(document.getElementById('root')).render(
|
|
<section className="tenant-timeslot-actions" aria-label="Synthetic GPO import">
|
|
<GpoFolderImport projectId="synthetic-project" showStatus={false}/>
|
|
</section>);`, resolveDir: process.cwd(), loader: 'tsx' },
|
|
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 ?? '<!doctype html><html><head><meta charset="utf-8"><link rel="stylesheet" href="/stdin.css"></head><body><div id="root"></div><script src="/stdin.js"></script></body></html>');
|
|
});
|
|
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
|
let browser;
|
|
try {
|
|
browser = await chromium.launch({ headless: true, channel: 'chrome' });
|
|
const page = await browser.newPage({ viewport: { width: 700, height: 450 } });
|
|
const errors = [];
|
|
page.on('pageerror', error => errors.push(error.message));
|
|
await page.goto(`http://127.0.0.1:${server.address().port}/`);
|
|
await page.getByRole('button', { name: 'Import GPO Folder', exact: true }).click();
|
|
const alert = page.getByRole('alert');
|
|
await alert.waitFor();
|
|
const message = await alert.textContent();
|
|
assert.ok(message.includes('Folder enumeration: NotFoundError (1)'));
|
|
assert.ok(!message.includes('Synthetic confidential customer'));
|
|
assert.ok(!message.includes('C:/Customers'));
|
|
for (const theme of ['dark', 'light']) {
|
|
await page.evaluate(theme => { document.documentElement.dataset.theme = theme; }, theme);
|
|
for (const width of [700, 380]) {
|
|
await page.setViewportSize({ width, height: 450 });
|
|
const geometry = await alert.evaluate(element => ({
|
|
width: element.clientWidth, scroll: element.scrollWidth,
|
|
whiteSpace: getComputedStyle(element).whiteSpace,
|
|
right: element.getBoundingClientRect().right
|
|
}));
|
|
assert.equal(geometry.whiteSpace, 'normal');
|
|
assert.ok(geometry.scroll <= geometry.width + 1, JSON.stringify(geometry));
|
|
assert.ok(geometry.right <= width, JSON.stringify(geometry));
|
|
if (process.env.SCREENSHOT_DIR) await page.screenshot({ path: join(process.env.SCREENSHOT_DIR, `gpo-diagnostics-${theme}-${width}.png`) });
|
|
}
|
|
}
|
|
assert.deepEqual(errors, []);
|
|
console.log('Synthetic Chrome GPO diagnostics: private error details hidden; complete wrapped message in both themes at 700px and 380px.');
|
|
} finally {
|
|
await browser?.close();
|
|
await new Promise(resolve => server.close(resolve));
|
|
}
|