mirror of
https://github.com/jquery/jquery.git
synced 2024-12-25 13:14:21 +00:00
103 lines
2.8 KiB
JavaScript
103 lines
2.8 KiB
JavaScript
|
// Build a queue that runs both browsers and modules
|
||
|
// in parallel when the length reaches the concurrency limit
|
||
|
// and refills the queue when one promise resolves.
|
||
|
|
||
|
import chalk from "chalk";
|
||
|
import { getAvailableSessions } from "./browserstack/api.js";
|
||
|
import { runWorker } from "./browserstack/workers.js";
|
||
|
import { getBrowserString } from "./lib/getBrowserString.js";
|
||
|
import { runSelenium } from "./selenium/runSelenium.js";
|
||
|
import { runJSDOM } from "./jsdom.js";
|
||
|
|
||
|
const queue = [];
|
||
|
const promises = [];
|
||
|
|
||
|
const SELENIUM_WAIT_TIME = 100;
|
||
|
const BROWSERSTACK_WAIT_TIME = 5000;
|
||
|
const WORKER_WAIT_TIME = 30000;
|
||
|
|
||
|
// Limit concurrency to 8 by default in selenium
|
||
|
// BrowserStack defaults to the max allowed by the plan
|
||
|
// More than this will log MaxListenersExceededWarning
|
||
|
const MAX_CONCURRENCY = 8;
|
||
|
|
||
|
export function addRun( url, browser, options ) {
|
||
|
queue.push( { url, browser, options } );
|
||
|
}
|
||
|
|
||
|
export async function runFullQueue( {
|
||
|
browserstack,
|
||
|
concurrency: defaultConcurrency,
|
||
|
verbose
|
||
|
} ) {
|
||
|
while ( queue.length ) {
|
||
|
const next = queue.shift();
|
||
|
const { url, browser, options } = next;
|
||
|
|
||
|
const fullBrowser = getBrowserString( browser, options.headless );
|
||
|
console.log(
|
||
|
`\nRunning ${ chalk.yellow( options.modules.join( ", " ) ) } tests ` +
|
||
|
`in ${ chalk.yellow( fullBrowser ) } (${ chalk.bold( options.reportId ) })...`
|
||
|
);
|
||
|
|
||
|
// Wait enough time between requests
|
||
|
// to give concurrency a chance to update.
|
||
|
// In selenium, this helps avoid undici connect timeout errors.
|
||
|
await new Promise( ( resolve ) =>
|
||
|
setTimeout(
|
||
|
resolve,
|
||
|
browserstack ? BROWSERSTACK_WAIT_TIME : SELENIUM_WAIT_TIME
|
||
|
)
|
||
|
);
|
||
|
|
||
|
const concurrency =
|
||
|
browserstack && !defaultConcurrency ?
|
||
|
await getAvailableSessions() :
|
||
|
defaultConcurrency || MAX_CONCURRENCY;
|
||
|
|
||
|
if ( verbose ) {
|
||
|
console.log(
|
||
|
`\nConcurrency: ${ concurrency }. Tests remaining: ${ queue.length + 1 }.`
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// If concurrency is 0, wait a bit and try again
|
||
|
if ( concurrency <= 0 ) {
|
||
|
if ( verbose ) {
|
||
|
console.log( "\nWaiting for available sessions..." );
|
||
|
}
|
||
|
queue.unshift( next );
|
||
|
await new Promise( ( resolve ) => setTimeout( resolve, WORKER_WAIT_TIME ) );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
let promise;
|
||
|
if ( browser.browser === "jsdom" ) {
|
||
|
promise = runJSDOM( url, options );
|
||
|
} else if ( browserstack ) {
|
||
|
promise = runWorker( url, browser, options );
|
||
|
} else {
|
||
|
promise = runSelenium( url, browser, options );
|
||
|
}
|
||
|
|
||
|
// Remove the promise from the list when it resolves
|
||
|
promise.then( () => {
|
||
|
const index = promises.indexOf( promise );
|
||
|
if ( index !== -1 ) {
|
||
|
promises.splice( index, 1 );
|
||
|
}
|
||
|
} );
|
||
|
|
||
|
// Add the promise to the list
|
||
|
promises.push( promise );
|
||
|
|
||
|
// Wait until at least one promise resolves
|
||
|
// if we've reached the concurrency limit
|
||
|
if ( promises.length >= concurrency ) {
|
||
|
await Promise.any( promises );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
await Promise.all( promises );
|
||
|
}
|