| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Run unit tests in headless or headful browser environment using Puppeteer.
- // This allows us to run tests in an environment that closely resembles how users would experience them,
- // including asset loading and browser-specific APIs,
- // while still being able to automate and capture results in a CI/CD pipeline.
- // It also enables us to capture console output from the browser and display it in the terminal.
- // Unit testing loaders in particular benefit from running in this setup,
- // as they require a server to facilitate assets loading,
- // and some of them require a browser environment to run in (e.g. ImageLoader => createElementNS('img')).
- import puppeteer from 'puppeteer';
- const networkTimeout = 5; // 5 minutes, set to 0 to disable
- const port = 1234;
- let browser;
- import { createServer } from '../../utils/server.js';
- const server = createServer();
- server.listen( port, main );
- const color = code => msg => console.log( `\x1b[${code}m${msg}\x1b[39m` );
- const white = color( 37 );
- const red = color( 31 );
- const green = color( 32 );
- const yellow = color( 33 );
- const blue = color( 34 );
- const cyan = color( 36 );
- const captureConsole = ( page ) => {
- const colors = {
- LOG: white,
- ERROR: red,
- WARN: yellow,
- INFO: green,
- };
- page.on( 'console', async ( message ) => {
- const type = message.type().toUpperCase();
- const color = colors[ type ] || blue;
- color( `${type}: ${message.text()} ` );
- } );
- };
- function main() {
- ( async () => {
- const flags = [
- '--hide-scrollbars',
- '--enable-unsafe-webgpu',
- '--enable-features=Vulkan',
- '--disable-vulkan-surface',
- '--ignore-gpu-blocklist',
- '--disable-gpu-driver-bug-workarounds',
- '--no-sandbox'
- ];
- let testPage = '';
- let testMode = '';
- let argvIndex = 2;
- if ( process.argv[ argvIndex ].startsWith( '--testPage' ) ) {
- testPage = process.argv[ argvIndex ].split( '=' )[ 1 ];
- argvIndex ++;
- }
- if ( process.argv[ argvIndex ].startsWith( '--mode' ) ) {
- testMode = process.argv[ argvIndex ].split( '=' )[ 1 ];
- argvIndex ++;
- }
- browser = await puppeteer.launch( {
- headless: testMode === 'headless',
- args: flags,
- env: { ...process.env, VK_DRIVER_FILES: '/usr/share/vulkan/icd.d/lvp_icd.x86_64.json' },
- defaultViewport: null,
- handleSIGINT: false,
- protocolTimeout: 0,
- userDataDir: './.puppeteer_profile'
- } );
- if ( testMode === 'headful' ) {
- browser.on( 'targetdestroyed', target => {
- // close the process when testing page is closed
- if ( target.type() === 'page' ) close( 0 );
- } );
- }
- const page = await browser.newPage();
- captureConsole( page );
- const testUrl = `http://localhost:${port}/test/unit/${testPage}`;
- // Load the test page
- await page.goto( testUrl, {
- waitUntil: 'networkidle0',
- timeout: networkTimeout * 60000
- } );
- // Wait for the QUnit test results
- await page.waitForFunction( () => {
- return window.QUnit && window.QUnit.done;
- } );
- // Get the test results
- const stats = await page.evaluate( () => {
- // these are set on window in the HTML test page
- return window._QUnitStats;
- } );
- white( `1..${stats.total}` );
- green( `# pass ${stats.passed}` );
- yellow( `# skip ${stats.skipped}` );
- cyan( `# todo ${stats.todo}` );
- red( `# fail ${stats.failed}` );
- // Keep the process running if testing in headful mode, otherwise close it.
- testMode === 'headless' && close( stats.failed > 0 ? 1 : 0 );
- } )();
- }
- process.on( 'SIGINT', () => close() );
- function close( exitCode = 1 ) {
- browser.close();
- server.close();
- process.exit( exitCode );
- }
|