Skip to content

Commit 408dbbc

Browse files
committed
feat: switch to generic flags passed to test pages
- flags are set for all test pages - each isolated flag creates its own test page
1 parent 642cb7f commit 408dbbc

File tree

4 files changed

+85
-65
lines changed

4 files changed

+85
-65
lines changed

bin/command.js

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@ import { resolve } from "node:path";
66
import { browsers } from "../flags/browsers.js";
77
import { getPlan, listBrowsers, stopWorkers } from "../browserstack/api.js";
88
import { buildBrowserFromString } from "../browserstack/buildBrowserFromString.js";
9-
import { modules } from "../flags/modules.js";
109
import { run } from "../run.js";
1110
import readYAML from "../lib/readYAML.js";
1211
import { createTestServer } from "../createTestServer.js";
1312

1413
const pkg = JSON.parse( await readFile( new URL( "../package.json", import.meta.url ) ) );
1514

15+
function parseFlags( flags ) {
16+
return Object.keys( flags ?? [] )
17+
.flatMap( ( key ) => flags[ key ]
18+
.map( ( value ) => `${ key }=${ value }` ) );
19+
}
20+
1621
async function parseMiddleware( config, argv ) {
1722
const middleware = await Promise.all( [
1823
...( config.middleware ?? [] ),
@@ -38,14 +43,17 @@ yargs( process.argv.slice( 2 ) )
3843
description: "Path to a YAML configuration file. " +
3944
"Use this to avoid passing options via the command line."
4045
} )
41-
.option( "module", {
42-
alias: "m",
46+
.option( "flag", {
47+
alias: "f",
4348
type: "array",
44-
choices: modules,
45-
description:
46-
"Run tests for a specific module. " +
47-
"Pass multiple modules by repeating the option. " +
48-
"Defaults to all modules."
49+
description: "Add a universal flag to be added as a query parameter " +
50+
"to the test URL for all test pages."
51+
} )
52+
.option( "isolated-flag", {
53+
alias: "i",
54+
type: "array",
55+
description: "Add an isolated flag to be added as a query parameter " +
56+
"to the test URL for each. Each isolated flag creates a new test page."
4957
} )
5058
.option( "browser", {
5159
alias: "b",
@@ -71,12 +79,6 @@ yargs( process.argv.slice( 2 ) )
7179
"Run tests in headless mode. Cannot be used with --debug or --browserstack.",
7280
conflicts: [ "debug", "browserstack" ]
7381
} )
74-
.option( "esm", {
75-
alias: "esmodules",
76-
type: "boolean",
77-
description: "Run tests using jQuery's source, " +
78-
"which is written with ECMAScript Modules."
79-
} )
8082
.option( "concurrency", {
8183
type: "number",
8284
description:
@@ -108,11 +110,6 @@ yargs( process.argv.slice( 2 ) )
108110
type: "boolean",
109111
description: "Log additional information."
110112
} )
111-
.option( "isolate", {
112-
type: "boolean",
113-
description: "Run each module by itself in the test page. " +
114-
"This can extend testing time."
115-
} )
116113
.option( "browserstack", {
117114
type: "array",
118115
description:
@@ -135,8 +132,18 @@ yargs( process.argv.slice( 2 ) )
135132
handler: async( { configFile, ...argv } ) => {
136133
console.log( "Running tests..." );
137134
const config = await readYAML( configFile );
135+
const flag = [
136+
...parseFlags( config.flags ),
137+
...( config.flag ?? [] ),
138+
...( argv.flag ?? [] )
139+
];
140+
const isolatedFlag = [
141+
...parseFlags( config.isolatedFlags ),
142+
...( config.isolatedFlag ?? [] ),
143+
...( argv.isolatedFlag ?? [] )
144+
];
138145
const middleware = await parseMiddleware( config, argv );
139-
return run( { ...config, ...argv, middleware } );
146+
return run( { ...config, ...argv, flag, isolatedFlag, middleware } );
140147
}
141148
} )
142149
.command( {
@@ -170,6 +177,7 @@ yargs( process.argv.slice( 2 ) )
170177
} );
171178
},
172179
handler: async( { configFile, quiet, ...argv } ) => {
180+
console.log( "Starting server..." );
173181
const config = await readYAML( configFile );
174182
const middleware = await parseMiddleware( config, argv );
175183

@@ -215,6 +223,7 @@ yargs( process.argv.slice( 2 ) )
215223
"including any workers running from other projects.\n" +
216224
"This can be used as a failsafe when there are too many stray workers.",
217225
handler: () => {
226+
console.log( "Stopping workers..." );
218227
stopWorkers();
219228
}
220229
} )

lib/buildTestUrl.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
import { generateModuleId } from "./generateHash.js";
22

3-
export function buildTestUrl( modules, { browserstack, esm, jsdom, port, reportId } ) {
3+
export function buildTestUrl( {
4+
browserstack,
5+
flags,
6+
isolatedFlag,
7+
jsdom,
8+
port,
9+
reportId
10+
} ) {
411
if ( !port ) {
512
throw new Error( "No port specified." );
613
}
714

815
const query = new URLSearchParams();
9-
for ( const module of modules ) {
10-
query.append( "moduleId", generateModuleId( module ) );
11-
}
16+
const allFlags = [ ...flags, ...( isolatedFlag ? [ isolatedFlag ] : [] ) ];
17+
for ( const flag of allFlags ) {
18+
const [ key, value ] = flag.split( "=" );
1219

13-
if ( esm ) {
14-
query.append( "esmodules", "true" );
20+
// Special handling for the module flag
21+
if ( key === "module" ) {
22+
query.append( "moduleId", generateModuleId( value ) );
23+
} else {
24+
query.append( key, value ?? "true" );
25+
}
1526
}
1627

1728
if ( jsdom ) {

reporter.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function serializeForDiff( value ) {
1515
return `${ value }`;
1616
}
1717

18-
export function reportTest( test, reportId, { browser, headless } ) {
18+
export function reportTest( test, { browser, headless, id } ) {
1919
if ( test.status === "passed" ) {
2020

2121
// Write to console without newlines
@@ -26,7 +26,7 @@ export function reportTest( test, reportId, { browser, headless } ) {
2626
let message = `${ chalk.bold( `${ test.suiteName }: ${ test.name }` ) }`;
2727
message += `\nTest ${ test.status } on ${ chalk.yellow(
2828
getBrowserString( browser, headless )
29-
) } (${ chalk.bold( reportId ) }).`;
29+
) } (${ chalk.bold( id ) }).`;
3030

3131
// test.assertions only contains passed assertions;
3232
// test.errors contains all failed asssertions
@@ -114,12 +114,14 @@ export function reportTest( test, reportId, { browser, headless } ) {
114114
}
115115
}
116116

117-
export function reportEnd( result, reportId, { browser, headless, modules } ) {
117+
export function reportEnd( result, { browser, flags, headless, id, isolatedFlag } ) {
118118
const fullBrowser = getBrowserString( browser, headless );
119+
const allFlags = [ ...flags, ...( isolatedFlag ? [ isolatedFlag ] : [] ) ];
120+
119121
console.log(
120122
`\n\nTests finished in ${ prettyMs( result.runtime ) } ` +
121-
`for ${ chalk.yellow( modules.join( "," ) ) } ` +
122-
`in ${ chalk.yellow( fullBrowser ) } (${ chalk.bold( reportId ) })...`
123+
`with flags "${ chalk.yellow( allFlags.join( "&" ) ) }" ` +
124+
`in ${ chalk.yellow( fullBrowser ) } (${ chalk.bold( id ) })...`
123125
);
124126
console.log(
125127
( result.status !== "passed" ?

run.js

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import { localTunnel } from "./browserstack/local.js";
66
import { reportEnd, reportTest } from "./reporter.js";
77
import { createTestServer } from "./createTestServer.js";
88
import { buildTestUrl } from "./lib/buildTestUrl.js";
9-
import { generateHash, printModuleHashes } from "./lib/generateHash.js";
9+
import { generateHash } from "./lib/generateHash.js";
1010
import { getBrowserString } from "./lib/getBrowserString.js";
11-
import { modules as allModules } from "./flags/modules.js";
1211
import { cleanupAllBrowsers, touchBrowser } from "./browsers.js";
1312
import {
1413
addRun,
@@ -20,30 +19,24 @@ import {
2019

2120
const EXIT_HOOK_WAIT_TIMEOUT = 60 * 1000;
2221

23-
/**
24-
* Run modules in parallel in different browser instances.
25-
*/
2622
export async function run( {
2723
browser: browserNames = [],
2824
browserstack,
2925
concurrency,
3026
debug,
31-
esm,
27+
flag: flags = [],
3228
hardRetries,
3329
headless,
34-
isolate,
30+
isolatedFlag: isolatedFlags = [],
3531
middleware = [],
36-
module: modules = [],
3732
retries = 0,
3833
runId,
3934
verbose
4035
} ) {
36+
console.log( isolatedFlags );
4137
if ( !browserNames.length ) {
4238
browserNames = [ "chrome" ];
4339
}
44-
if ( !modules.length ) {
45-
modules = allModules;
46-
}
4740
if ( headless && debug ) {
4841
throw new Error(
4942
"Cannot run in headless mode and debug mode at the same time."
@@ -59,11 +52,11 @@ export async function run( {
5952

6053
// Convert browser names to browser objects
6154
let browsers = browserNames.map( ( b ) => ( { browser: b } ) );
62-
const tunnelId = generateHash(
63-
`${ Date.now() }-${ modules.join( ":" ) }-${ ( browserstack || [] )
64-
.concat( browserNames )
65-
.join( ":" ) }`
66-
);
55+
const hashValue = flags
56+
.concat( browserstack || [] )
57+
.concat( browserNames )
58+
.join( ":" );
59+
const tunnelId = generateHash( `${ Date.now() }-${ hashValue }` );
6760

6861
// A unique identifier for this run
6962
if ( !runId ) {
@@ -84,7 +77,7 @@ export async function run( {
8477
const reportId = message.id;
8578
const report = reports[ reportId ];
8679
touchBrowser( report.browser );
87-
const errors = reportTest( message.data, reportId, report );
80+
const errors = reportTest( message.data, report );
8881
pendingErrors[ reportId ] ??= Object.create( null );
8982
if ( errors ) {
9083
pendingErrors[ reportId ][ message.data.name ] = errors;
@@ -111,7 +104,6 @@ export async function run( {
111104
touchBrowser( report.browser );
112105
const { failed, total } = reportEnd(
113106
message.data,
114-
message.id,
115107
reports[ reportId ]
116108
);
117109
report.total = total;
@@ -243,19 +235,18 @@ export async function run( {
243235
tunnel = await localTunnel( tunnelId );
244236
if ( verbose ) {
245237
console.log( "Started BrowserStackLocal." );
246-
247-
printModuleHashes( modules );
248238
}
249239
}
250240

251-
function queueRun( modules, browser ) {
241+
function queueRun( browser, isolatedFlag ) {
252242
const fullBrowser = getBrowserString( browser, headless );
253-
const reportId = generateHash( `${ modules.join( ":" ) } ${ fullBrowser }` );
254-
reports[ reportId ] = { browser, headless, modules };
243+
const reportId = generateHash( `${ hashValue }-${ isolatedFlag }-${ fullBrowser }` );
244+
reports[ reportId ] = { browser, flags, headless, id: reportId, isolatedFlag };
255245

256-
const url = buildTestUrl( modules, {
246+
const url = buildTestUrl( {
257247
browserstack,
258-
esm,
248+
flags,
249+
isolatedFlag,
259250
jsdom: browser.browser === "jsdom",
260251
port,
261252
reportId
@@ -265,8 +256,9 @@ export async function run( {
265256
browserstack,
266257
concurrency,
267258
debug,
259+
flags,
268260
headless,
269-
modules,
261+
isolatedFlag,
270262
reportId,
271263
runId,
272264
tunnelId,
@@ -277,12 +269,12 @@ export async function run( {
277269
}
278270

279271
for ( const browser of browsers ) {
280-
if ( isolate ) {
281-
for ( const module of modules ) {
282-
queueRun( [ module ], browser );
283-
}
272+
if ( isolatedFlags.length > 0 ) {
273+
isolatedFlags.forEach( ( isolatedFlag ) => {
274+
queueRun( browser, isolatedFlag );
275+
} );
284276
} else {
285-
queueRun( modules, browser );
277+
queueRun( browser );
286278
}
287279
}
288280

@@ -301,11 +293,17 @@ export async function run( {
301293
for ( const report of Object.values( reports ) ) {
302294
if ( !report.total ) {
303295
stop = true;
296+
const allFlags = [
297+
...report.flags,
298+
...( report.isolatedFlag ? [ report.isolatedFlag ] : [] )
299+
];
304300
console.error(
305301
chalk.red(
306-
`No tests were run for ${ report.modules.join(
307-
", "
308-
) } in ${ getBrowserString( report.browser ) }`
302+
`No tests were run for page with flags "${
303+
allFlags.join( "&" )
304+
}" in ${
305+
getBrowserString( report.browser )
306+
} (${ report.id })`
309307
)
310308
);
311309
}

0 commit comments

Comments
 (0)