Skip to content

Commit

Permalink
CLI: Fix --seed <file> arg confusion, Backport --seed=true support
Browse files Browse the repository at this point in the history
* Fix `--seed <file>` arg confusion. This is now correctly interpreted
  as a file.

* Fix presence of "Running tests with seed:" message on CLI when preconfig
  qunit_config_seed is set via environment variable. Previously the
  seed was applied, but not printed because the printing logic only
  checked the CLI options, not QUnit.config.

* Add `--seed=true` to generate a new seed.
  This is backported from QUnit 3.0.0-alpha, and aligns the CLI with
  what was already supported via Preconfig, QUnit.config, and URL
  params.

Cherry-picked from 390a5b7 (3.0.0-dev).
> Ref #1691.
  • Loading branch information
Krinkle committed Dec 6, 2024
1 parent da0c59e commit eea01ba
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 10 deletions.
4 changes: 2 additions & 2 deletions bin/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ program
'reporters will be displayed')
.option('--require <module>', 'specify a module or script to include before running ' +
'any tests.', collect, [])
.option('--seed [value]', 'specify a seed to re-order your tests; ' +
'if specified without a value, a seed will be generated')
.option('--seed <value>', 'specify a seed to re-order your tests; ' +
'set to "true" to generate a new seed')
.option('-w, --watch', 'watch files for changes and re-run the test suite')
.parse(process.argv);

Expand Down
9 changes: 6 additions & 3 deletions src/cli/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ async function run (args, options) {

const seed = options.seed;
if (seed) {
if (seed === true) {
QUnit.config.seed = Math.random().toString(36).slice(2);
if (seed === 'true' || seed === true) {
// NOTE: QUnit 3 will set preconfig qunit_config_seed from here.
// NOTE: This duplicates logic from /src/core/config.js. Consolidated in QUnit 3.
QUnit.config.seed = (Math.random().toString(36) + '0000000000').slice(2, 12);
} else {
QUnit.config.seed = seed;
}

}
if (QUnit.config.seed) {
console.log(`Running tests with seed: ${QUnit.config.seed}`);
}

Expand Down
14 changes: 13 additions & 1 deletion src/core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ function readFlatPreconfigString (val, dest) {
}
}

function readFlatPreconfigStringOrBoolean (val, dest) {
if (typeof val === 'boolean' || (typeof val === 'string' && val !== '')) {
config[dest] = val;
}
}

function readFlatPreconfigStringArray (val, dest) {
if (typeof val === 'string' && val !== '') {
config[dest] = [val];
Expand All @@ -178,7 +184,7 @@ function readFlatPreconfig (obj) {
readFlatPreconfigBoolean(obj.qunit_config_reorder, 'reorder');
readFlatPreconfigBoolean(obj.qunit_config_requireexpects, 'requireExpects');
readFlatPreconfigBoolean(obj.qunit_config_scrolltop, 'scrolltop');
readFlatPreconfigString(obj.qunit_config_seed, 'seed');
readFlatPreconfigStringOrBoolean(obj.qunit_config_seed, 'seed');
readFlatPreconfigStringArray(obj.qunit_config_testid, 'testId');
readFlatPreconfigNumber(obj.qunit_config_testtimeout, 'testTimeout');
}
Expand All @@ -200,4 +206,10 @@ if (preConfig) {
// Push a loose unnamed module to the modules collection
config.modules.push(config.currentModule);

if (config.seed === 'true' || config.seed === true) {
// Generate a random seed
// Length of `Math.random()` fraction, in base 36, may vary from 6-14.
// Pad and take slice to a consistent 10-digit value.
config.seed = (Math.random().toString(36) + '0000000000').slice(2, 12);
}
export default config;
8 changes: 5 additions & 3 deletions src/html-runner/urlparams.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ import { window } from '../globals';
QUnit.config.testId = [].concat(urlParams.testId || []);

// Test order randomization
if (urlParams.seed === true) {
// Generate a random seed if the option is specified without a value
QUnit.config.seed = Math.random().toString(36).slice(2);
// Generate a random seed if `?seed` is specified without a value (boolean true),
// or when set to the string "true".
if (urlParams.seed === 'true' || urlParams.seed === true) {
// NOTE: This duplicates logic from /src/core/config.js. Consolidated in QUnit 3.
QUnit.config.seed = (Math.random().toString(36) + '0000000000').slice(2, 12);
} else if (urlParams.seed) {
QUnit.config.seed = urlParams.seed;
}
Expand Down
35 changes: 34 additions & 1 deletion test/cli/cli-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ QUnit.module('CLI Main', () => {
qunit_config_testtimeout: '7'
}
});
assert.equal(execution.snapshot, `TAP version 13
assert.equal(execution.snapshot, `Running tests with seed: dummyfirstyes
TAP version 13
ok 1 dummy
not ok 2 slow
---
Expand Down Expand Up @@ -367,6 +368,38 @@ not ok 1 global failure
# exit code: 1`);
});

QUnit.test('--seed=true generates new random seed', async assert => {
const command = ['qunit', '--seed', 'true', 'basic-one.js', 'test/'];
const execution = await execute(command);

const actualHarness = execution.snapshot
.replace(/^(Running tests with seed: )([a-z0-9]{10,20})/g, (_m, m1) => {
return m1 + '0000000000';
})
.split('\n')
.filter(line => !line.startsWith('ok '))
.join('\n');

const actualResults = execution.snapshot
.replace(/^ok \d/gm, 'ok 0')
.split('\n')
.filter(line => line.startsWith('ok '))
.sort()
.join('\n');

assert.equal(actualHarness, `Running tests with seed: 0000000000
TAP version 13
1..3
# pass 3
# skip 0
# todo 0
# fail 0`);

assert.equal(actualResults, `ok 0 First > 1
ok 0 Second > 1
ok 0 Single > has a test`);
});

QUnit.test('--require loads unknown module', async assert => {
const command = ['qunit', 'basic-one.js', '--require', 'does-not-exist-at-all'];
const execution = await execute(command);
Expand Down

0 comments on commit eea01ba

Please sign in to comment.