63 lines
3.5 KiB
JavaScript
63 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
|||
|
|
/**
|
||
|
|
* Real-browser regression test: a `background` shorthand followed by an
|
||
|
|
* undefined/'' background longhand wipes the gradient in Chromium (React
|
||
|
|
* assigns '' for undefined style values). jsdom cannot reproduce this, so
|
||
|
|
* mount the real components via react-dom in headless Chromium and assert the
|
||
|
|
* COMPUTED style. Run: npm run test:browser:bg (needs a Playwright chromium)
|
||
|
|
*/
|
||
|
|
import { build } from 'esbuild';
|
||
|
|
import { chromium, firefox } from '@playwright/test';
|
||
|
|
import { fileURLToPath } from 'node:url';
|
||
|
|
import path from 'node:path';
|
||
|
|
|
||
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||
|
|
const out = await build({
|
||
|
|
entryPoints: [path.join(root, 'scripts/e2e-background-entry.tsx')],
|
||
|
|
bundle: true, write: false, format: 'iife', platform: 'browser',
|
||
|
|
define: { 'process.env.NODE_ENV': '"production"' }, jsx: 'automatic', logLevel: 'error',
|
||
|
|
});
|
||
|
|
const js = out.outputFiles[0].text;
|
||
|
|
|
||
|
|
const cases = [
|
||
|
|
['hero gradient', 'HeroSimple', { bgType: 'gradient', bgGradientFrom: '#0f172a', bgGradientTo: '#334155' }, 'backgroundImage', /linear-gradient/],
|
||
|
|
['hero color', 'HeroSimple', { bgType: 'color', bgColor: '#123456' }, 'backgroundColor', /rgb\(18, 52, 86\)/],
|
||
|
|
['hero image', 'HeroSimple', { bgType: 'image', bgImage: 'https://example.invalid/a.jpg' }, 'backgroundImage', /url\(.*a\.jpg/],
|
||
|
|
['hero video (fallback color)', 'HeroSimple', { bgType: 'video', bgVideo: 'v.mp4', bgColor: '#123456' }, 'backgroundColor', /rgb\(18, 52, 86\)/],
|
||
|
|
['BackgroundSection image', 'BackgroundSection', { bgImage: 'https://example.invalid/b.jpg', bgColor: '#123456' }, 'backgroundImage', /url\(.*b\.jpg/],
|
||
|
|
['BackgroundSection color', 'BackgroundSection', { bgColor: '#123456' }, 'backgroundColor', /rgb\(18, 52, 86\)/],
|
||
|
|
['CTASection gradient', 'CTASection', { gradient: 'linear-gradient(135deg, #111111, #222222)' }, 'backgroundImage', /linear-gradient/],
|
||
|
|
['CallToAction gradient', 'CallToAction', { bgType: 'gradient', bgValue: 'linear-gradient(135deg, #111111, #222222)' }, 'backgroundImage', /linear-gradient/],
|
||
|
|
];
|
||
|
|
|
||
|
|
// Override binaries with CHROMIUM_PATH / FIREFOX_PATH when the Playwright-pinned builds are not installed.
|
||
|
|
async function run(name, launcher, exe) {
|
||
|
|
const browser = await launcher.launch({ executablePath: exe || undefined, ...(name === 'chromium' ? { args: ['--no-sandbox'] } : {}) });
|
||
|
|
const page = await browser.newPage();
|
||
|
|
const errors = [];
|
||
|
|
page.on('pageerror', (e) => errors.push(String(e)));
|
||
|
|
await page.setContent('<!doctype html><html><body></body></html>');
|
||
|
|
await page.addScriptTag({ content: js });
|
||
|
|
|
||
|
|
let failed = 0;
|
||
|
|
for (const [i, [label, type, props, prop, re]] of cases.entries()) {
|
||
|
|
const id = `c${i}`;
|
||
|
|
await page.evaluate(([id, type, props]) => window.mountNode(id, type, props), [id, type, props]);
|
||
|
|
await page.waitForSelector(`#${id} section`, { timeout: 5000 }).catch(() => {});
|
||
|
|
const value = await page.evaluate(([id, prop]) => {
|
||
|
|
const s = document.querySelector(`#${id} section`);
|
||
|
|
return s ? getComputedStyle(s)[prop] : '<<no section>>';
|
||
|
|
}, [id, prop]);
|
||
|
|
const ok = re.test(value);
|
||
|
|
if (!ok) failed++;
|
||
|
|
console.log(`[${name}] ${ok ? 'PASS' : 'FAIL'} ${label}: computed ${prop} = ${value}`);
|
||
|
|
}
|
||
|
|
if (errors.length) console.log('page errors:', errors.join('\n'));
|
||
|
|
await browser.close();
|
||
|
|
return failed;
|
||
|
|
|
||
|
|
}
|
||
|
|
let total = 0;
|
||
|
|
total += await run('chromium', chromium, process.env.CHROMIUM_PATH);
|
||
|
|
total += await run('firefox', firefox, process.env.FIREFOX_PATH);
|
||
|
|
process.exit(total ? 1 : 0);
|