From de1625816b740093558bb8514826eda56ab810ef Mon Sep 17 00:00:00 2001 From: John Markham Date: Thu, 20 Aug 2020 23:09:39 -0700 Subject: [PATCH 01/14] feat: have assertions return booleans --- lib/assert.js | 207 +++++++++++++++++++++++---------------------- test-tap/assert.js | 72 ++++++++-------- 2 files changed, 140 insertions(+), 139 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index fe8f1bfa3..2cb2ac340 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -299,6 +299,7 @@ class Assertions { this.pass = withSkip(() => { pass(); + return true; }); this.fail = withSkip(message => { @@ -310,6 +311,7 @@ class Assertions { assertion: 'fail', message: message || 'Test failed via `t.fail()`' })); + return false; }); this.is = withSkip((actual, expected, message) => { @@ -318,28 +320,28 @@ class Assertions { } if (Object.is(actual, expected)) { - pass(); - } else { - const result = concordance.compare(actual, expected, concordanceOptions); - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); + return pass(); + } - if (result.pass) { - fail(new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] - })); - } else { - fail(new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); - } + const result = concordance.compare(actual, expected, concordanceOptions); + const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); + const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); + + if (result.pass) { + return fail(new AssertionError({ + assertion: 'is', + message, + raw: {actual, expected}, + values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] + })); } + + return fail(new AssertionError({ + assertion: 'is', + message, + raw: {actual, expected}, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); }); this.not = withSkip((actual, expected, message) => { @@ -348,15 +350,15 @@ class Assertions { } if (Object.is(actual, expected)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'not', message, raw: {actual, expected}, values: [formatWithLabel('Value is the same as:', actual)] })); - } else { - pass(); } + + return pass(); }); this.deepEqual = withSkip((actual, expected, message) => { @@ -366,17 +368,18 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { - pass(); - } else { - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); - fail(new AssertionError({ - assertion: 'deepEqual', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); + return pass(); } + + const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); + const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); + + return fail(new AssertionError({ + assertion: 'deepEqual', + message, + raw: {actual, expected}, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); }); this.notDeepEqual = withSkip((actual, expected, message) => { @@ -387,30 +390,37 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notDeepEqual', message, raw: {actual, expected}, values: [formatDescriptorWithLabel('Value is deeply equal:', actualDescriptor)] })); - } else { - pass(); } + + return pass(); }); this.like = withSkip((actual, selector, message) => { + if (!experiments.likeAssertion) { + return fail(new AssertionError({ + assertion: 'like', + improperUsage: true, + message: 'You must enable the `likeAssertion` experiment in order to use `t.like()`' + })); + } + if (!checkMessage('like', message)) { return; } if (!isLikeSelector(selector)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must be a non-empty object', values: [formatWithLabel('Called with:', selector)] })); - return; } let comparable; @@ -418,13 +428,12 @@ class Assertions { comparable = selectComparable(actual, selector); } catch (error) { if (error === CIRCULAR_SELECTOR) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must not contain circular references', values: [formatWithLabel('Called with:', selector)] })); - return; } throw error; @@ -432,16 +441,16 @@ class Assertions { const result = concordance.compare(comparable, selector, concordanceOptions); if (result.pass) { - pass(); - } else { - const actualDescriptor = result.actual || concordance.describe(comparable, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(selector, concordanceOptions); - fail(new AssertionError({ - assertion: 'like', - message, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); + return pass(); } + + const actualDescriptor = result.actual || concordance.describe(comparable, concordanceOptions); + const expectedDescriptor = result.expected || concordance.describe(selector, concordanceOptions); + return fail(new AssertionError({ + assertion: 'like', + message, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); }); this.throws = withSkip((...args) => { @@ -735,29 +744,30 @@ class Assertions { improperUsage.expectedVersion = error.expectedVersion; } - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'snapshot', message: message || 'Could not compare snapshot', improperUsage })); - return; } if (result.pass) { - pass(); - } else if (result.actual) { - fail(new AssertionError({ + return pass(); + } + + if (result.actual) { + return fail(new AssertionError({ assertion: 'snapshot', message: message || 'Did not match snapshot', values: [formatDescriptorDiff(result.actual, result.expected, {invert: true})] })); - } else { - // This can only occur in CI environments. - fail(new AssertionError({ - assertion: 'snapshot', - message: message || 'No snapshot available — new snapshots are not created in CI environments' - })); } + + // This can only occur in CI environments. + return fail(new AssertionError({ + assertion: 'snapshot', + message: message || 'No snapshot available — new snapshots are not created in CI environments' + })); }); this.truthy = withSkip((actual, message) => { @@ -766,15 +776,15 @@ class Assertions { } if (actual) { - pass(); - } else { - fail(new AssertionError({ - assertion: 'truthy', - message, - operator: '!!', - values: [formatWithLabel('Value is not truthy:', actual)] - })); + return pass(); } + + return fail(new AssertionError({ + assertion: 'truthy', + message, + operator: '!!', + values: [formatWithLabel('Value is not truthy:', actual)] + })); }); this.falsy = withSkip((actual, message) => { @@ -783,15 +793,15 @@ class Assertions { } if (actual) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'falsy', message, operator: '!', values: [formatWithLabel('Value is not falsy:', actual)] })); - } else { - pass(); } + + return pass(); }); this.true = withSkip((actual, message) => { @@ -800,14 +810,14 @@ class Assertions { } if (actual === true) { - pass(); - } else { - fail(new AssertionError({ - assertion: 'true', - message, - values: [formatWithLabel('Value is not `true`:', actual)] - })); + return pass(); } + + return fail(new AssertionError({ + assertion: 'true', + message, + values: [formatWithLabel('Value is not `true`:', actual)] + })); }); this.false = withSkip((actual, message) => { @@ -816,14 +826,14 @@ class Assertions { } if (actual === false) { - pass(); - } else { - fail(new AssertionError({ - assertion: 'false', - message, - values: [formatWithLabel('Value is not `false`:', actual)] - })); + return pass(); } + + return fail(new AssertionError({ + assertion: 'false', + message, + values: [formatWithLabel('Value is not `false`:', actual)] + })); }); this.regex = withSkip((string, regex, message) => { @@ -832,27 +842,25 @@ class Assertions { } if (typeof string !== 'string') { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); - return; } if (!(regex instanceof RegExp)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); - return; } if (!regex.test(string)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'regex', message, values: [ @@ -860,10 +868,9 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); - return; } - pass(); + return pass(); }); this.notRegex = withSkip((string, regex, message) => { @@ -872,27 +879,25 @@ class Assertions { } if (typeof string !== 'string') { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); - return; } if (!(regex instanceof RegExp)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); - return; } if (regex.test(string)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notRegex', message, values: [ @@ -900,10 +905,9 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); - return; } - pass(); + return pass(); }); if (powerAssert === undefined) { @@ -913,16 +917,15 @@ class Assertions { } if (!actual) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'assert', message, operator: '!!', values: [formatWithLabel('Value is not truthy:', actual)] })); - return; } - pass(); + return pass(); }); } else { this.assert = withSkip(withPowerAssert( diff --git a/test-tap/assert.js b/test-tap/assert.js index f5b38cbdf..3d8fbc9f4 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -12,26 +12,26 @@ const snapshotManager = require('../lib/snapshot-manager'); const HelloMessage = require('./fixture/hello-message'); let lastFailure = null; -let lastPassed = false; const assertions = new class extends assert.Assertions { constructor(overwrites = {}) { super({ - pass: () => { - lastPassed = true; - }, + pass: () => true, pending: promise => { - promise.then(() => { - lastPassed = true; - }, error => { + return promise.then(() => + true + , error => { lastFailure = error; }); }, fail: error => { lastFailure = error; + return false; }, skip: () => {}, - experiments: {}, + experiments: { + likeAssertion: true + }, ...overwrites }); } @@ -142,10 +142,8 @@ function eventuallyFails(t, fn) { */ function passes(t, fn) { - lastPassed = false; lastFailure = null; - fn(); - if (lastPassed) { + if (fn()) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -154,10 +152,9 @@ function passes(t, fn) { function eventuallyPasses(t, fn) { return add(() => { - lastPassed = false; lastFailure = null; - return fn().then(() => { - if (lastPassed) { + return fn().then(passed => { + if (passed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -168,12 +165,12 @@ function eventuallyPasses(t, fn) { test('.pass()', t => { passes(t, () => { - assertions.pass(); + return assertions.pass(); }); passes(t, () => { const {pass} = assertions; - pass(); + return pass(); }); t.end(); @@ -181,14 +178,14 @@ test('.pass()', t => { test('.fail()', t => { failsWith(t, () => { - assertions.fail(); + return assertions.fail(); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - assertions.fail('my message'); + return assertions.fail('my message'); }, { assertion: 'fail', message: 'my message' @@ -196,14 +193,14 @@ test('.fail()', t => { failsWith(t, () => { const {fail} = assertions; - fail(); + return fail(); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - assertions.fail(null); + return assertions.fail(null); }, { assertion: 'fail', improperUsage: true, @@ -219,73 +216,73 @@ test('.fail()', t => { test('.is()', t => { passes(t, () => { - assertions.is('foo', 'foo'); + return assertions.is('foo', 'foo'); }); passes(t, () => { const {is} = assertions; - is('foo', 'foo'); + return is('foo', 'foo'); }); passes(t, () => { - assertions.is('', ''); + return assertions.is('', ''); }); passes(t, () => { - assertions.is(true, true); + return assertions.is(true, true); }); passes(t, () => { - assertions.is(false, false); + return assertions.is(false, false); }); passes(t, () => { - assertions.is(null, null); + return assertions.is(null, null); }); passes(t, () => { - assertions.is(undefined, undefined); + return assertions.is(undefined, undefined); }); passes(t, () => { - assertions.is(1, 1); + return assertions.is(1, 1); }); passes(t, () => { - assertions.is(0, 0); + return assertions.is(0, 0); }); passes(t, () => { - assertions.is(-0, -0); + return assertions.is(-0, -0); }); passes(t, () => { - assertions.is(Number.NaN, Number.NaN); + return assertions.is(Number.NaN, Number.NaN); }); passes(t, () => { - assertions.is(0 / 0, Number.NaN); + return assertions.is(0 / 0, Number.NaN); }); passes(t, () => { const someRef = {foo: 'bar'}; - assertions.is(someRef, someRef); + return assertions.is(someRef, someRef); }); fails(t, () => { - assertions.is(0, -0); + return assertions.is(0, -0); }); fails(t, () => { - assertions.is(0, false); + return assertions.is(0, false); }); fails(t, () => { - assertions.is('', false); + return assertions.is('', false); }); fails(t, () => { - assertions.is('0', 0); + return assertions.is('0', 0); }); fails(t, () => { @@ -2156,3 +2153,4 @@ test('.assert()', t => { t.end(); }); + From 9ceb562e6d9a995b0ec76558b3193785b0f5e56d Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Sat, 22 Aug 2020 14:16:57 +0200 Subject: [PATCH 02/14] Test compatibility with TypeScript 4.0 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32bf84867..164c01b05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ts-version: [~3.7.5, ~3.8, ~3.9] + ts-version: [~3.7.5, ~3.8, ~3.9, ~4.0] steps: - uses: actions/checkout@v1 with: From 43587147f1f5cd31e2f88d4d2faf34c19d05751a Mon Sep 17 00:00:00 2001 From: Raul Date: Sun, 23 Aug 2020 11:44:41 +0200 Subject: [PATCH 03/14] Experimentally configure module formats for test files Fixes #2345. Co-authored-by: Mark Wubben --- ava.config.js | 7 +- docs/06-configuration.md | 23 +++++- lib/cli.js | 14 ++-- lib/extensions.js | 5 +- lib/load-config.js | 2 +- lib/module-types.js | 75 ++++++++++++++++++ test/configurable-module-format/commonjs.js | 26 ++++++ test/configurable-module-format/custom.js | 16 ++++ .../experimental.js | 10 +++ .../fixtures/array-custom.config.js | 3 + .../fixtures/array-extensions.config.js | 3 + .../fixtures/bad-custom-type.config.js | 9 +++ .../fixtures/change-cjs-loading.config.js | 8 ++ .../fixtures/change-js-loading.config.js | 8 ++ .../fixtures/change-mjs-loading.config.js | 8 ++ .../fixtures/not-enabled.config.js | 7 ++ .../fixtures/object-custom.config.js | 9 +++ .../fixtures/object-extensions.config.js | 10 +++ .../fixtures/package.json | 1 + .../fixtures/test.cjs | 5 ++ .../fixtures/test.js | 5 ++ .../fixtures/test.mjs | 5 ++ .../fixtures/test.ts | 8 ++ .../invalid-configurations.js | 24 ++++++ test/configurable-module-format/module.js | 23 ++++++ .../snapshots/experimental.js.md | 11 +++ .../snapshots/experimental.js.snap | Bin 0 -> 177 bytes .../snapshots/invalid-configurations.js.md | 29 +++++++ .../snapshots/invalid-configurations.js.snap | Bin 0 -> 270 bytes xo.config.js | 2 +- 30 files changed, 345 insertions(+), 11 deletions(-) create mode 100644 lib/module-types.js create mode 100644 test/configurable-module-format/commonjs.js create mode 100644 test/configurable-module-format/custom.js create mode 100644 test/configurable-module-format/experimental.js create mode 100644 test/configurable-module-format/fixtures/array-custom.config.js create mode 100644 test/configurable-module-format/fixtures/array-extensions.config.js create mode 100644 test/configurable-module-format/fixtures/bad-custom-type.config.js create mode 100644 test/configurable-module-format/fixtures/change-cjs-loading.config.js create mode 100644 test/configurable-module-format/fixtures/change-js-loading.config.js create mode 100644 test/configurable-module-format/fixtures/change-mjs-loading.config.js create mode 100644 test/configurable-module-format/fixtures/not-enabled.config.js create mode 100644 test/configurable-module-format/fixtures/object-custom.config.js create mode 100644 test/configurable-module-format/fixtures/object-extensions.config.js create mode 100644 test/configurable-module-format/fixtures/package.json create mode 100644 test/configurable-module-format/fixtures/test.cjs create mode 100644 test/configurable-module-format/fixtures/test.js create mode 100644 test/configurable-module-format/fixtures/test.mjs create mode 100644 test/configurable-module-format/fixtures/test.ts create mode 100644 test/configurable-module-format/invalid-configurations.js create mode 100644 test/configurable-module-format/module.js create mode 100644 test/configurable-module-format/snapshots/experimental.js.md create mode 100644 test/configurable-module-format/snapshots/experimental.js.snap create mode 100644 test/configurable-module-format/snapshots/invalid-configurations.js.md create mode 100644 test/configurable-module-format/snapshots/invalid-configurations.js.snap diff --git a/ava.config.js b/ava.config.js index 363e4279f..b667ffd2b 100644 --- a/ava.config.js +++ b/ava.config.js @@ -1,4 +1,9 @@ +const skipTests = []; +if (process.versions.node < '12.14.0') { + skipTests.push('!test/configurable-module-format/module.js'); +} + export default { - files: ['test/**', '!test/**/{fixtures,helpers}/**'], + files: ['test/**', '!test/**/{fixtures,helpers}/**', ...skipTests], ignoredByWatcher: ['{coverage,docs,media,test-d,test-tap}/**'] }; diff --git a/docs/06-configuration.md b/docs/06-configuration.md index eb2c48ace..75d9f1c08 100644 --- a/docs/06-configuration.md +++ b/docs/06-configuration.md @@ -52,7 +52,7 @@ Arguments passed to the CLI will always take precedence over the CLI options con - `tap`: if `true`, enables the [TAP reporter](./05-command-line.md#tap-reporter) - `verbose`: if `true`, enables verbose output - `snapshotDir`: specifies a fixed location for storing snapshot files. Use this if your snapshots are ending up in the wrong location -- `extensions`: extensions of test files. Setting this overrides the default `["cjs", "mjs", "js"]` value, so make sure to include those extensions in the list +- `extensions`: extensions of test files. Setting this overrides the default `["cjs", "mjs", "js"]` value, so make sure to include those extensions in the list. [Experimentally you can configure how files are loaded](#configuring-module-formats) - `require`: extra modules to require before tests are run. Modules are required in the [worker processes](./01-writing-tests.md#process-isolation) - `timeout`: Timeouts in AVA behave differently than in other test frameworks. AVA resets a timer after each test, forcing tests to quit if no new test results were received within the specified timeout. This can be used to handle stalled tests. See our [timeout documentation](./07-test-timeouts.md) for more options. - `nodeArguments`: Configure Node.js arguments used to launch worker processes. @@ -213,6 +213,27 @@ export default { }; ``` +### Configuring module formats + +Node.js can only load non-standard extension as ES Modules when using [experimental loaders](https://nodejs.org/docs/latest/api/esm.html#esm_experimental_loaders). To use this you'll also have to configure AVA to `import()` your test file. + +This is still an experimental feature. You can opt in to it by enabling the `configurableModuleFormat` experiment. Afterwards, you'll be able to specify per-extension module formats using an object form. + +As with the array form, you need to explicitly list `js`, `cjs`, and `mjs` extensions. These **must** be set using the `true` value; other extensions are configurable using either `'commonjs'` or `'module'`: + +`ava.config.js`: +```js +export default { + nonSemVerExperiments: { + configurableModuleFormat: true + }, + extensions: { + js: true, + ts: 'module' + } +}; +``` + ## Node arguments The `nodeArguments` configuration may be used to specify additional arguments for launching worker processes. These are combined with `--node-arguments` passed on the CLI and any arguments passed to the `node` binary when starting AVA. diff --git a/lib/cli.js b/lib/cli.js index fc80e1ee9..7e83bb1bd 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -284,6 +284,7 @@ exports.run = async () => { // eslint-disable-line complexity const TapReporter = require('./reporters/tap'); const Watcher = require('./watcher'); const normalizeExtensions = require('./extensions'); + const normalizeModuleTypes = require('./module-types'); const {normalizeGlobs, normalizePattern} = require('./globs'); const normalizeNodeArguments = require('./node-arguments'); const validateEnvironmentVariables = require('./environment-variables'); @@ -301,12 +302,6 @@ exports.run = async () => { // eslint-disable-line complexity const {type: defaultModuleType = 'commonjs'} = pkg || {}; - const moduleTypes = { - cjs: 'commonjs', - mjs: 'module', - js: defaultModuleType - }; - const providers = []; if (Reflect.has(conf, 'babel')) { try { @@ -348,6 +343,13 @@ exports.run = async () => { // eslint-disable-line complexity exit(error.message); } + let moduleTypes; + try { + moduleTypes = normalizeModuleTypes(conf.extensions, defaultModuleType, experiments); + } catch (error) { + exit(error.message); + } + let globs; try { globs = normalizeGlobs({files: conf.files, ignoredByWatcher: conf.ignoredByWatcher, extensions, providers}); diff --git a/lib/extensions.js b/lib/extensions.js index b6b3077b2..8ee05c3f7 100644 --- a/lib/extensions.js +++ b/lib/extensions.js @@ -2,8 +2,11 @@ module.exports = (configuredExtensions, providers = []) => { // Combine all extensions possible for testing. Remove duplicate extensions. const duplicates = new Set(); const seen = new Set(); + + const normalize = extensions => Array.isArray(extensions) ? extensions : Object.keys(extensions); + const combine = extensions => { - for (const ext of extensions) { + for (const ext of normalize(extensions)) { if (seen.has(ext)) { duplicates.add(ext); } else { diff --git a/lib/load-config.js b/lib/load-config.js index 77fd7e92f..7d349344a 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -7,7 +7,7 @@ const pkgConf = require('pkg-conf'); const NO_SUCH_FILE = Symbol('no ava.config.js file'); const MISSING_DEFAULT_EXPORT = Symbol('missing default export'); -const EXPERIMENTS = new Set(['disableSnapshotsInHooks', 'reverseTeardowns']); +const EXPERIMENTS = new Set(['configurableModuleFormat', 'disableSnapshotsInHooks', 'reverseTeardowns']); // *Very* rudimentary support for loading ava.config.js files containing an `export default` statement. const evaluateJsConfig = configFile => { diff --git a/lib/module-types.js b/lib/module-types.js new file mode 100644 index 000000000..087d5d1e2 --- /dev/null +++ b/lib/module-types.js @@ -0,0 +1,75 @@ +const requireTrueValue = value => { + if (value !== true) { + throw new TypeError('When specifying module types, use `true` for ’cjs’, ’mjs’ and ’js’ extensions'); + } +}; + +const normalize = (extension, type, defaultModuleType) => { + switch (extension) { + case 'cjs': + requireTrueValue(type); + return 'commonjs'; + case 'mjs': + requireTrueValue(type); + return 'module'; + case 'js': + requireTrueValue(type); + return defaultModuleType; + default: + if (type !== 'commonjs' && type !== 'module') { + throw new TypeError(`Module type for ’${extension}’ must be ’commonjs’ or ’module’`); + } + + return type; + } +}; + +const deriveFromObject = (extensionsObject, defaultModuleType) => { + const moduleTypes = {}; + for (const [extension, type] of Object.entries(extensionsObject)) { + moduleTypes[extension] = normalize(extension, type, defaultModuleType); + } + + return moduleTypes; +}; + +const deriveFromArray = (extensions, defaultModuleType) => { + const moduleTypes = {}; + for (const extension of extensions) { + switch (extension) { + case 'cjs': + moduleTypes.cjs = 'commonjs'; + break; + case 'mjs': + moduleTypes.mjs = 'module'; + break; + case 'js': + moduleTypes.js = defaultModuleType; + break; + default: + moduleTypes[extension] = 'commonjs'; + } + } + + return moduleTypes; +}; + +module.exports = (configuredExtensions, defaultModuleType, experiments) => { + if (configuredExtensions === undefined) { + return { + cjs: 'commonjs', + mjs: 'module', + js: defaultModuleType + }; + } + + if (Array.isArray(configuredExtensions)) { + return deriveFromArray(configuredExtensions, defaultModuleType); + } + + if (!experiments.configurableModuleFormat) { + throw new Error('You must enable the `configurableModuleFormat` experiment in order to specify module types'); + } + + return deriveFromObject(configuredExtensions, defaultModuleType); +}; diff --git a/test/configurable-module-format/commonjs.js b/test/configurable-module-format/commonjs.js new file mode 100644 index 000000000..41c312466 --- /dev/null +++ b/test/configurable-module-format/commonjs.js @@ -0,0 +1,26 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('load js and cjs as commonjs (default configuration)', async t => { + const result = await exec.fixture(['*.js', '*.cjs']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 2); + t.true(files.has('test.cjs')); + t.true(files.has('test.js')); +}); + +test('load js and cjs as commonjs (using an extensions array)', async t => { + const result = await exec.fixture(['*.js', '*.cjs', '--config', 'array-extensions.config.js']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 2); + t.true(files.has('test.cjs')); + t.true(files.has('test.js')); +}); + +test('load js and cjs as commonjs (using an extensions object)', async t => { + const result = await exec.fixture(['*.js', '*.cjs', '--config', 'object-extensions.config.js']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 2); + t.true(files.has('test.cjs')); + t.true(files.has('test.js')); +}); diff --git a/test/configurable-module-format/custom.js b/test/configurable-module-format/custom.js new file mode 100644 index 000000000..3f5d6c3e4 --- /dev/null +++ b/test/configurable-module-format/custom.js @@ -0,0 +1,16 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('load ts as commonjs (using an extensions array)', async t => { + const result = await exec.fixture(['*.ts', '--config', 'array-custom.config.js']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 1); + t.true(files.has('test.ts')); +}); + +test('load ts as commonjs (using an extensions object)', async t => { + const result = await exec.fixture(['*.ts', '--config', 'object-custom.config.js']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 1); + t.true(files.has('test.ts')); +}); diff --git a/test/configurable-module-format/experimental.js b/test/configurable-module-format/experimental.js new file mode 100644 index 000000000..37d297028 --- /dev/null +++ b/test/configurable-module-format/experimental.js @@ -0,0 +1,10 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +const stripLeadingFigures = string => string.replace(/^\W+/, ''); + +test('opt-in is required', async t => { + const result = await t.throwsAsync(exec.fixture(['--config', 'not-enabled.config.js'])); + t.is(result.exitCode, 1); + t.snapshot(stripLeadingFigures(result.stderr.trim())); +}); diff --git a/test/configurable-module-format/fixtures/array-custom.config.js b/test/configurable-module-format/fixtures/array-custom.config.js new file mode 100644 index 000000000..8452365f9 --- /dev/null +++ b/test/configurable-module-format/fixtures/array-custom.config.js @@ -0,0 +1,3 @@ +export default { + extensions: ['js', 'ts'] +}; diff --git a/test/configurable-module-format/fixtures/array-extensions.config.js b/test/configurable-module-format/fixtures/array-extensions.config.js new file mode 100644 index 000000000..ca91b839a --- /dev/null +++ b/test/configurable-module-format/fixtures/array-extensions.config.js @@ -0,0 +1,3 @@ +export default { + extensions: ['js', 'cjs', 'mjs'] +}; diff --git a/test/configurable-module-format/fixtures/bad-custom-type.config.js b/test/configurable-module-format/fixtures/bad-custom-type.config.js new file mode 100644 index 000000000..ad3db25c0 --- /dev/null +++ b/test/configurable-module-format/fixtures/bad-custom-type.config.js @@ -0,0 +1,9 @@ +export default { + extensions: { + js: true, + ts: 'cjs' + }, + nonSemVerExperiments: { + configurableModuleFormat: true + } +}; diff --git a/test/configurable-module-format/fixtures/change-cjs-loading.config.js b/test/configurable-module-format/fixtures/change-cjs-loading.config.js new file mode 100644 index 000000000..c21d1fdb1 --- /dev/null +++ b/test/configurable-module-format/fixtures/change-cjs-loading.config.js @@ -0,0 +1,8 @@ +export default { + extensions: { + cjs: 'module' + }, + nonSemVerExperiments: { + configurableModuleFormat: true + } +}; diff --git a/test/configurable-module-format/fixtures/change-js-loading.config.js b/test/configurable-module-format/fixtures/change-js-loading.config.js new file mode 100644 index 000000000..4200e3f9c --- /dev/null +++ b/test/configurable-module-format/fixtures/change-js-loading.config.js @@ -0,0 +1,8 @@ +export default { + extensions: { + js: 'module' + }, + nonSemVerExperiments: { + configurableModuleFormat: true + } +}; diff --git a/test/configurable-module-format/fixtures/change-mjs-loading.config.js b/test/configurable-module-format/fixtures/change-mjs-loading.config.js new file mode 100644 index 000000000..2437790ff --- /dev/null +++ b/test/configurable-module-format/fixtures/change-mjs-loading.config.js @@ -0,0 +1,8 @@ +export default { + extensions: { + mjs: 'commonjs' + }, + nonSemVerExperiments: { + configurableModuleFormat: true + } +}; diff --git a/test/configurable-module-format/fixtures/not-enabled.config.js b/test/configurable-module-format/fixtures/not-enabled.config.js new file mode 100644 index 000000000..5088cbaac --- /dev/null +++ b/test/configurable-module-format/fixtures/not-enabled.config.js @@ -0,0 +1,7 @@ +export default { + extensions: { + js: true, + cjs: true, + mjs: true + } +}; diff --git a/test/configurable-module-format/fixtures/object-custom.config.js b/test/configurable-module-format/fixtures/object-custom.config.js new file mode 100644 index 000000000..094ca3877 --- /dev/null +++ b/test/configurable-module-format/fixtures/object-custom.config.js @@ -0,0 +1,9 @@ +export default { + extensions: { + js: true, + ts: 'commonjs' + }, + nonSemVerExperiments: { + configurableModuleFormat: true + } +}; diff --git a/test/configurable-module-format/fixtures/object-extensions.config.js b/test/configurable-module-format/fixtures/object-extensions.config.js new file mode 100644 index 000000000..dd7d62356 --- /dev/null +++ b/test/configurable-module-format/fixtures/object-extensions.config.js @@ -0,0 +1,10 @@ +export default { + extensions: { + js: true, + cjs: true, + mjs: true + }, + nonSemVerExperiments: { + configurableModuleFormat: true + } +}; diff --git a/test/configurable-module-format/fixtures/package.json b/test/configurable-module-format/fixtures/package.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/configurable-module-format/fixtures/package.json @@ -0,0 +1 @@ +{} diff --git a/test/configurable-module-format/fixtures/test.cjs b/test/configurable-module-format/fixtures/test.cjs new file mode 100644 index 000000000..d7dd4fe69 --- /dev/null +++ b/test/configurable-module-format/fixtures/test.cjs @@ -0,0 +1,5 @@ +const test = require('ava'); + +test('always passing test', t => { + t.pass(); +}); diff --git a/test/configurable-module-format/fixtures/test.js b/test/configurable-module-format/fixtures/test.js new file mode 100644 index 000000000..d7dd4fe69 --- /dev/null +++ b/test/configurable-module-format/fixtures/test.js @@ -0,0 +1,5 @@ +const test = require('ava'); + +test('always passing test', t => { + t.pass(); +}); diff --git a/test/configurable-module-format/fixtures/test.mjs b/test/configurable-module-format/fixtures/test.mjs new file mode 100644 index 000000000..b9c488ebb --- /dev/null +++ b/test/configurable-module-format/fixtures/test.mjs @@ -0,0 +1,5 @@ +import test from 'ava'; + +test('always passing test', t => { + t.pass(); +}); diff --git a/test/configurable-module-format/fixtures/test.ts b/test/configurable-module-format/fixtures/test.ts new file mode 100644 index 000000000..93d621261 --- /dev/null +++ b/test/configurable-module-format/fixtures/test.ts @@ -0,0 +1,8 @@ +// eslint-disable-next-line ava/no-ignored-test-files +const test = require('ava'); + +test('always passing test', t => { + const numberWithTypes = 0; + + t.is(numberWithTypes, 0); +}); diff --git a/test/configurable-module-format/invalid-configurations.js b/test/configurable-module-format/invalid-configurations.js new file mode 100644 index 000000000..a780e13db --- /dev/null +++ b/test/configurable-module-format/invalid-configurations.js @@ -0,0 +1,24 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +const stripLeadingFigures = string => string.replace(/^\W+/, ''); + +test('cannot configure how js extensions should be loaded', async t => { + const result = await t.throwsAsync(exec.fixture(['--config', 'change-js-loading.config.js'])); + t.snapshot(stripLeadingFigures(result.stderr.trim())); +}); + +test('cannot configure how cjs extensions should be loaded', async t => { + const result = await t.throwsAsync(exec.fixture(['--config', 'change-cjs-loading.config.js'])); + t.snapshot(stripLeadingFigures(result.stderr.trim())); +}); + +test('cannot configure how mjs extensions should be loaded', async t => { + const result = await t.throwsAsync(exec.fixture(['--config', 'change-mjs-loading.config.js'])); + t.snapshot(stripLeadingFigures(result.stderr.trim())); +}); + +test('custom extensions must be either commonjs or module', async t => { + const result = await t.throwsAsync(exec.fixture(['--config', 'bad-custom-type.config.js'])); + t.snapshot(stripLeadingFigures(result.stderr.trim())); +}); diff --git a/test/configurable-module-format/module.js b/test/configurable-module-format/module.js new file mode 100644 index 000000000..9b07beb08 --- /dev/null +++ b/test/configurable-module-format/module.js @@ -0,0 +1,23 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('load mjs as module (default configuration)', async t => { + const result = await exec.fixture(['*.mjs']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 1); + t.true(files.has('test.mjs')); +}); + +test('load mjs as module (using an extensions array)', async t => { + const result = await exec.fixture(['*.mjs', '--config', 'array-extensions.config.js']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 1); + t.true(files.has('test.mjs')); +}); + +test('load mjs as module (using an extensions object)', async t => { + const result = await exec.fixture(['*.mjs', '--config', 'object-extensions.config.js']); + const files = new Set(result.stats.passed.map(({file}) => file)); + t.is(files.size, 1); + t.true(files.has('test.mjs')); +}); diff --git a/test/configurable-module-format/snapshots/experimental.js.md b/test/configurable-module-format/snapshots/experimental.js.md new file mode 100644 index 000000000..fdd39f4bb --- /dev/null +++ b/test/configurable-module-format/snapshots/experimental.js.md @@ -0,0 +1,11 @@ +# Snapshot report for `test/configurable-module-format/experimental.js` + +The actual snapshot is saved in `experimental.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## opt-in is required + +> Snapshot 1 + + 'You must enable the `configurableModuleFormat` experiment in order to specify module types' diff --git a/test/configurable-module-format/snapshots/experimental.js.snap b/test/configurable-module-format/snapshots/experimental.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..4b56cc63f54b51cbe9b2b261544a71608f6b3d62 GIT binary patch literal 177 zcmV;i08alwRzVw|>;24IYfE&umtETOW%E00000000A1 zU|?Wi1mZmxTOyXKJW`#0e#KdB8;}SCLk18tGq8i%jI0cTj8T#Kr3$&F#U%=7_*=5#Rij(wtPc{G!~%k_3g+ih|Ul%-qzx5{1k>h5VwF)FOqF fe1+nI)a1;xN`+joVug~*g4ALFP!bR%hyVZpssl^z literal 0 HcmV?d00001 diff --git a/test/configurable-module-format/snapshots/invalid-configurations.js.md b/test/configurable-module-format/snapshots/invalid-configurations.js.md new file mode 100644 index 000000000..61c38084e --- /dev/null +++ b/test/configurable-module-format/snapshots/invalid-configurations.js.md @@ -0,0 +1,29 @@ +# Snapshot report for `test/configurable-module-format/invalid-configurations.js` + +The actual snapshot is saved in `invalid-configurations.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## cannot configure how cjs extensions should be loaded + +> Snapshot 1 + + 'When specifying module types, use `true` for ’cjs’, ’mjs’ and ’js’ extensions' + +## cannot configure how js extensions should be loaded + +> Snapshot 1 + + 'When specifying module types, use `true` for ’cjs’, ’mjs’ and ’js’ extensions' + +## cannot configure how mjs extensions should be loaded + +> Snapshot 1 + + 'When specifying module types, use `true` for ’cjs’, ’mjs’ and ’js’ extensions' + +## custom extensions must be either commonjs or module + +> Snapshot 1 + + 'Module type for ’ts’ must be ’commonjs’ or ’module’' diff --git a/test/configurable-module-format/snapshots/invalid-configurations.js.snap b/test/configurable-module-format/snapshots/invalid-configurations.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..100a0f7b99b72642dcc572f0d41bdb3fd21465c8 GIT binary patch literal 270 zcmV+p0rCDpRzVexTY5#hb!>Ri_C7`i5J(4NvvRfQvU&Pzwzq8DV;yr_h!HG$4v52e z*(Nkgoa0jPT_Luj#_KO5Skx4#wKJkRT&m)(NXj9u$*bpFPhbR#HUTj+13TDcMpgzv z#>nuD)I5dag4E>9w93r9bcNjfl+v73g_6pG)M6cl(&AKwgp#7t)C7gJ{33-%4KtIo zih-mKh?xs!DkSEmfOrs2YDGzEUU6oAUhy!t#@-iUEX<@5u!h{y;u3|VRIt(cxw-jy U5OW|(AdUet0P?bwbMOHG0RE+W{{R30 literal 0 HcmV?d00001 diff --git a/xo.config.js b/xo.config.js index 75eb391c7..bb009d6c6 100644 --- a/xo.config.js +++ b/xo.config.js @@ -44,7 +44,7 @@ module.exports = { } }, { - files: ['test-tap/fixture/**/*.js', 'test/**/fixtures/**/*.js'], + files: ['test-tap/fixture/**', 'test/**/fixtures/**'], rules: { 'import/no-extraneous-dependencies': 'off' } From 65de5fe8ce2ac3e3e1535719c37eedf236697072 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Sun, 23 Aug 2020 21:37:45 +0200 Subject: [PATCH 04/14] Update dependencies * Update dev dependencies * Update XO * Update dependencies * Rebuild lockfile --- index.d.ts | 2 +- lib/provider-manager.js | 2 +- package-lock.json | 715 +++++++++++++++++++++------------------- package.json | 22 +- test-tap/runner.js | 24 +- 5 files changed, 398 insertions(+), 367 deletions(-) diff --git a/index.d.ts b/index.d.ts index 8bd9a58e2..a1a8fa595 100644 --- a/index.d.ts +++ b/index.d.ts @@ -433,7 +433,7 @@ export interface CbExecutionContext extends ExecutionContext< end(error?: any): void; } -export type ImplementationResult = PromiseLike | Subscribable | void; // eslint-disable-line @typescript-eslint/no-invalid-void-type +export type ImplementationResult = PromiseLike | Subscribable | void; export type Implementation = (t: ExecutionContext) => ImplementationResult; export type CbImplementation = (t: CbExecutionContext) => ImplementationResult; diff --git a/lib/provider-manager.js b/lib/provider-manager.js index 48d6aabd5..5c95c07ff 100644 --- a/lib/provider-manager.js +++ b/lib/provider-manager.js @@ -21,7 +21,7 @@ function load(providerModule, projectDir) { let level; const provider = makeProvider({ negotiateProtocol(identifiers, {version}) { - const [identifier] = identifiers.filter(identifier => Reflect.has(levelsByProtocol, identifier)); + const identifier = identifiers.find(identifier => Reflect.has(levelsByProtocol, identifier)); if (identifier === undefined) { fatal = new Error(`This version of AVA (${ava.version}) is not compatible with ${providerModule}@${version}`); diff --git a/package-lock.json b/package-lock.json index 9ae84a8d3..81e040dd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -107,9 +107,9 @@ } }, "@ava/v3": { - "version": "npm:ava@3.10.1", - "resolved": "https://registry.npmjs.org/ava/-/ava-3.10.1.tgz", - "integrity": "sha512-+w86ZHyFHIGCABi7NUrn/WJMyC+fDj0BSIlFNVS45WDKAD5vxbIiDWeclctxOOc2KDPfQD7tFOURSBz0FBLD0A==", + "version": "npm:ava@3.11.1", + "resolved": "https://registry.npmjs.org/ava/-/ava-3.11.1.tgz", + "integrity": "sha512-yGPD0msa5Qronw7GHDNlLaB7oU5zryYtXeuvny40YV6TMskSghqK7Ky3NisM/sr+aqI3DY7sfmORx8dIWQgMoQ==", "dev": true, "requires": { "@concordance/react": "^2.0.0", @@ -120,7 +120,7 @@ "arrify": "^2.0.1", "callsites": "^3.1.0", "chalk": "^4.1.0", - "chokidar": "^3.4.0", + "chokidar": "^3.4.1", "chunkd": "^2.0.1", "ci-info": "^2.0.0", "ci-parallel-vars": "^1.0.1", @@ -134,7 +134,7 @@ "currently-unhandled": "^0.4.1", "debug": "^4.1.1", "del": "^5.1.0", - "emittery": "^0.7.0", + "emittery": "^0.7.1", "equal-length": "^1.0.0", "figures": "^3.2.0", "globby": "^11.0.1", @@ -142,14 +142,14 @@ "import-local": "^3.0.2", "indent-string": "^4.0.0", "is-error": "^2.2.2", - "is-plain-object": "^3.0.1", + "is-plain-object": "^4.1.1", "is-promise": "^4.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "matcher": "^3.0.0", "md5-hex": "^3.0.1", "mem": "^6.1.0", "ms": "^2.1.2", - "ora": "^4.0.4", + "ora": "^4.0.5", "p-map": "^4.0.0", "picomatch": "^2.2.2", "pkg-conf": "^3.1.0", @@ -166,14 +166,109 @@ "trim-off-newlines": "^1.0.1", "update-notifier": "^4.1.0", "write-file-atomic": "^3.0.3", - "yargs": "^15.4.0" + "yargs": "^15.4.1" }, "dependencies": { - "is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "ora": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", + "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.2.0", + "is-interactive": "^1.0.0", + "log-symbols": "^3.0.0", + "mute-stream": "0.0.8", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } } } }, @@ -186,19 +281,19 @@ } }, "@babel/core": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz", - "integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", + "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.5", - "@babel/helper-module-transforms": "^7.10.5", + "@babel/generator": "^7.11.4", + "@babel/helper-module-transforms": "^7.11.0", "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.10.5", + "@babel/parser": "^7.11.4", "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.5", - "@babel/types": "^7.10.5", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", @@ -224,12 +319,12 @@ } }, "@babel/generator": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz", - "integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", + "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", "dev": true, "requires": { - "@babel/types": "^7.10.5", + "@babel/types": "^7.11.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -263,12 +358,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz", - "integrity": "sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "dev": true, "requires": { - "@babel/types": "^7.10.5" + "@babel/types": "^7.11.0" } }, "@babel/helper-module-imports": { @@ -281,17 +376,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz", - "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.10.4", "@babel/helper-replace-supers": "^7.10.4", "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", "@babel/template": "^7.10.4", - "@babel/types": "^7.10.5", + "@babel/types": "^7.11.0", "lodash": "^4.17.19" } }, @@ -332,13 +427,22 @@ "@babel/types": "^7.10.4" } }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, "@babel/helper-split-export-declaration": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz", - "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.11.0" } }, "@babel/helper-validator-identifier": { @@ -414,9 +518,9 @@ } }, "@babel/parser": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz", - "integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", + "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", "dev": true }, "@babel/plugin-proposal-do-expressions": { @@ -450,12 +554,13 @@ } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz", - "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, @@ -519,26 +624,26 @@ } }, "@babel/traverse": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz", - "integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.5", + "@babel/generator": "^7.11.0", "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "@babel/parser": "^7.10.5", - "@babel/types": "^7.10.5", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" } }, "@babel/types": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz", - "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -640,9 +745,9 @@ } }, "@sinonjs/samsam": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", - "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.1.0.tgz", + "integrity": "sha512-42nyaQOVunX5Pm6GRJobmzbS7iLI+fhERITnETXzzwDZh+TtDr/Au3yAvXVjFmZ4wEUaE4Y3NFZfKv0bV0cbtg==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", @@ -720,9 +825,9 @@ "dev": true }, "@types/node": { - "version": "14.0.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz", - "integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==" + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz", + "integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -736,12 +841,12 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.7.0.tgz", - "integrity": "sha512-4OEcPON3QIx0ntsuiuFP/TkldmBGXf0uKxPQlGtS/W2F3ndYm8Vgdpj/woPJkzUc65gd3iR+qi3K8SDQP/obFg==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.9.1.tgz", + "integrity": "sha512-XIr+Mfv7i4paEdBf0JFdIl9/tVxyj+rlilWIfZ97Be0lZ7hPvUbS5iHt9Glc8kRI53dsr0PcAEudbf8rO2wGgg==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "3.7.0", + "@typescript-eslint/experimental-utils": "3.9.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", @@ -750,45 +855,45 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.7.0.tgz", - "integrity": "sha512-xpfXXAfZqhhqs5RPQBfAFrWDHoNxD5+sVB5A46TF58Bq1hRfVROrWHcQHHUM9aCBdy9+cwATcvCbRg8aIRbaHQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz", + "integrity": "sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.7.0", - "@typescript-eslint/typescript-estree": "3.7.0", + "@typescript-eslint/types": "3.9.1", + "@typescript-eslint/typescript-estree": "3.9.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.7.0.tgz", - "integrity": "sha512-2LZauVUt7jAWkcIW7djUc3kyW+fSarNEuM3RF2JdLHR9BfX/nDEnyA4/uWz0wseoWVZbDXDF7iF9Jc342flNqQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.1.tgz", + "integrity": "sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.7.0", - "@typescript-eslint/types": "3.7.0", - "@typescript-eslint/typescript-estree": "3.7.0", + "@typescript-eslint/experimental-utils": "3.9.1", + "@typescript-eslint/types": "3.9.1", + "@typescript-eslint/typescript-estree": "3.9.1", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/types": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.7.0.tgz", - "integrity": "sha512-reCaK+hyKkKF+itoylAnLzFeNYAEktB0XVfSQvf0gcVgpz1l49Lt6Vo9x4MVCCxiDydA0iLAjTF/ODH0pbfnpg==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.1.tgz", + "integrity": "sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.0.tgz", - "integrity": "sha512-xr5oobkYRebejlACGr1TJ0Z/r0a2/HUf0SXqPvlgUMwiMqOCu/J+/Dr9U3T0IxpE5oLFSkqMx1FE/dKaZ8KsOQ==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz", + "integrity": "sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA==", "dev": true, "requires": { - "@typescript-eslint/types": "3.7.0", - "@typescript-eslint/visitor-keys": "3.7.0", + "@typescript-eslint/types": "3.9.1", + "@typescript-eslint/visitor-keys": "3.9.1", "debug": "^4.1.1", "glob": "^7.1.6", "is-glob": "^4.0.1", @@ -798,9 +903,9 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.7.0.tgz", - "integrity": "sha512-k5PiZdB4vklUpUX4NBncn5RBKty8G3ihTY+hqJsCdMuD0v4jofI5xuqwnVcWxfv6iTm2P/dfEa2wMUnsUY8ODw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz", + "integrity": "sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" @@ -813,9 +918,9 @@ "dev": true }, "acorn": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", - "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.1.tgz", + "integrity": "sha512-dmKn4pqZ29iQl2Pvze1zTrps2luvls2PBY//neO2WJ0s10B3AxJXshN+Ph7B4GrhfGhHXrl4dnUwyNNXQcnWGQ==" }, "acorn-jsx": { "version": "5.2.0", @@ -824,23 +929,23 @@ "dev": true }, "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.0.0.tgz", + "integrity": "sha512-oZRad/3SMOI/pxbbmqyurIx7jHw1wZDcR9G44L8pUVFEomX/0dH89SrM1KaDXuv1NpzAXz6Op/Xu/Qd5XXzdEA==" }, "aggregate-error": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", - "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1054,14 +1159,15 @@ } }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" }, "dependencies": { "bn.js": { @@ -1150,9 +1256,9 @@ "dev": true }, "aws4": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", - "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, "babel-eslint": { @@ -1285,9 +1391,9 @@ "integrity": "sha512-x5PKJHY5rHQYaADj6NwPUR2QRCUVSggPzrUKkeENpj871o9l9IefJbO2jkT5UvYykeOK9dx0VmkIo6dZ+vThYw==" }, "bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", "dev": true }, "boxen": { @@ -1406,16 +1512,16 @@ } }, "browserify-sign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz", - "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", "dev": true, "requires": { "bn.js": "^5.1.1", "browserify-rsa": "^4.0.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.2", + "elliptic": "^6.5.3", "inherits": "^2.0.4", "parse-asn1": "^5.1.5", "readable-stream": "^3.6.0", @@ -1493,9 +1599,9 @@ "dev": true }, "c8": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.2.1.tgz", - "integrity": "sha512-HwMat7Hsz6u+Muuj9wZlz9lPxQA7BvBa2Xx+xMa52U7o6dDO1oG0QU4Q0pKQbRuR39PhIcs7eb6x4xSIAew3dw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.3.0.tgz", + "integrity": "sha512-DEWiHtepo/KB50K+gw2z5MWnQbgzACy8xqTREBmAAg4j5UOlkmDeJfl8jWjk2iDTDaJfXR0sbnqx7iNCwgsblQ==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", @@ -1508,7 +1614,7 @@ "istanbul-reports": "^3.0.2", "rimraf": "^3.0.0", "test-exclude": "^6.0.0", - "v8-to-istanbul": "^4.1.2", + "v8-to-istanbul": "^5.0.0", "yargs": "^15.0.0", "yargs-parser": "^18.0.0" } @@ -1544,6 +1650,14 @@ "responselike": "^1.0.2" }, "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -1680,9 +1794,9 @@ } }, "chokidar": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", - "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -1886,9 +2000,9 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concordance": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.0.tgz", - "integrity": "sha512-stOCz9ffg0+rytwTaL2njUOIyMfANwfwmqc9Dr4vTUS/x/KkVFlWx9Zlzu6tHYtjKxxaCF/cEAZgPDac+n35sg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.1.tgz", + "integrity": "sha512-TbNtInKVElgEBnJ1v2Xg+MFX2lvFLbmlv3EuSC5wTfCwpB8kC3w3mffF6cKuUhkn475Ym1f1I4qmuXzx2+uXpw==", "requires": { "date-time": "^3.1.0", "esutils": "^2.0.3", @@ -1979,27 +2093,27 @@ "dev": true }, "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", + "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", - "yaml": "^1.7.2" + "yaml": "^1.10.0" }, "dependencies": { "parse-json": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.1.tgz", - "integrity": "sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } } @@ -2050,13 +2164,13 @@ } }, "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", "dev": true, "requires": { "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "elliptic": "^6.5.3" }, "dependencies": { "bn.js": { @@ -2590,9 +2704,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz", - "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz", + "integrity": "sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -2690,18 +2804,18 @@ } }, "eslint-config-xo": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.30.0.tgz", - "integrity": "sha512-0C+Hl1Mfrbh+LMc2A2v2BabI+n0MoVHYyGJOJoWped/Tfh/OoyZ7gLyed5vLqVR4czjR8Zi7DGW2S1nTGKUY4w==", + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.32.1.tgz", + "integrity": "sha512-achnYLilUTtljR1CGRikVj9HRAf5GplJeGgeyQMvph7mKo+AqTkNuig4EO/IrNOChcjoazgw9YT4cW/3+69i3Q==", "dev": true, "requires": { "confusing-browser-globals": "1.0.9" } }, "eslint-config-xo-typescript": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/eslint-config-xo-typescript/-/eslint-config-xo-typescript-0.31.0.tgz", - "integrity": "sha512-zxfUdKscsdrZTI5Uz9ZqAAR+W6fuH+DiQnTRRJAwLZaKJemT3hzH0DtIxNhB9t5fxKMwZYNYw2lvW4aWrSMbag==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/eslint-config-xo-typescript/-/eslint-config-xo-typescript-0.32.0.tgz", + "integrity": "sha512-GCYR9wXNATh6/yB9s9PvKia7tlv86ZsrN3CYk/qfcTJhFSO41fagBgA8G8H1j0CACC4AHaRpgbTEu4+W0p9hkw==", "dev": true }, "eslint-formatter-pretty": { @@ -2717,17 +2831,6 @@ "plur": "^4.0.0", "string-width": "^4.2.0", "supports-hyperlinks": "^2.0.0" - }, - "dependencies": { - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "requires": { - "chalk": "^4.0.0" - } - } } }, "eslint-import-resolver-node": { @@ -3137,16 +3240,16 @@ "dev": true }, "eslint-plugin-unicorn": { - "version": "20.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-20.1.0.tgz", - "integrity": "sha512-XQxLBJT/gnwyRR6cfYsIK1AdekQchAt5tmcsnldevGjgR2xoZsRUa5/i6e0seNHy2RoT57CkTnbVHwHF8No8LA==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-21.0.0.tgz", + "integrity": "sha512-S8v7+v4gZTQPj4pKKvexhgSUaLQSyItvxW2SVZDaX9Iu5IjlAmF2eni+L6w8a2aqshxgU8Lle4FIAVDtuejSKQ==", "dev": true, "requires": { "ci-info": "^2.0.0", "clean-regexp": "^1.0.0", "eslint-ast-utils": "^1.1.0", "eslint-template-visitor": "^2.0.0", - "eslint-utils": "^2.0.0", + "eslint-utils": "^2.1.0", "import-modules": "^2.0.0", "lodash": "^4.17.15", "pluralize": "^8.0.0", @@ -3177,9 +3280,9 @@ } }, "eslint-rule-docs": { - "version": "1.1.201", - "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.201.tgz", - "integrity": "sha512-HS327MkM3ebCcjAQMkhNYZbN/4Eu/NO5ipDK8uNVPqUrAPRUsXkuuEfE+DEx4YItkszKp4ND1F3hN8BwfXdx0w==", + "version": "1.1.205", + "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.205.tgz", + "integrity": "sha512-yguHHAkBG9L09YoaOpXXi3MsvEwPlqhas8yDnnaykbA6I8BAxUpa3FkCspxyzdnDPuLWEy+vVmrZHXL2M4zFTQ==", "dev": true }, "eslint-scope": { @@ -3246,14 +3349,22 @@ } }, "espree": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", - "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", "dev": true, "requires": { - "acorn": "^7.3.1", + "acorn": "^7.4.0", "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + } } }, "esprima": { @@ -3280,9 +3391,9 @@ }, "dependencies": { "estraverse": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", - "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true } } @@ -3344,6 +3455,17 @@ "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } } }, "expand-brackets": { @@ -3704,18 +3826,18 @@ "dev": true }, "flow-parser": { - "version": "0.130.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.130.0.tgz", - "integrity": "sha512-h9NATB7QsKhj2ucgEH2XzB7p+5ubk8IZX5u/qHkN+oyQoECi1diq6mYfIuYBOyL35f3AhJf/YDkBYQBTqqYK+w==", + "version": "0.132.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.132.0.tgz", + "integrity": "sha512-y1P37zDCPSdphlk+w+roCqcOar6iQdNaAJldJ6xx5/2r4ZRv4KHO+qL+AXwPWp+34eN+oPxPjWnU7GybJnyISQ==", "dev": true }, "flow-remove-types": { - "version": "2.130.0", - "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.130.0.tgz", - "integrity": "sha512-x48wARPzBge8aRd0ZI3lQi59afHwVk7DymUIFf423bUfa3u1GJWOfpdHggPkN1f4R16oUH+YO4KldBz8Ce2ldg==", + "version": "2.132.0", + "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.132.0.tgz", + "integrity": "sha512-J1EfutfdC68xEZ8i44Hdlaa3MnONuQQB4/+wtnw/ontdcwuz/yGAVQ/O35dFIqNaQoCUWNDN1mHHagbRYLfihQ==", "dev": true, "requires": { - "flow-parser": "^0.130.0", + "flow-parser": "^0.132.0", "pirates": "^3.0.2", "vlq": "^0.2.1" } @@ -3843,12 +3965,10 @@ "dev": true }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "requires": { - "pump": "^3.0.0" - } + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true }, "get-value": { "version": "2.0.6", @@ -3959,12 +4079,12 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -4503,9 +4623,9 @@ } }, "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { "has-symbols": "^1.0.1" @@ -4945,6 +5065,11 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "json-parse-even-better-errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz", + "integrity": "sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==" + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -5087,9 +5212,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "lodash.clonedeep": { "version": "4.5.0", @@ -5134,57 +5259,11 @@ "dev": true }, "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "chalk": "^4.0.0" } }, "loose-envify": { @@ -5324,18 +5403,16 @@ "dev": true }, "meow": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz", - "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.0.tgz", + "integrity": "sha512-kq5F0KVteskZ3JdfyQFivJEj2RaA8NFsS4+r9DaMKLcUHpk5OcHS3Q0XkCXONB1mZRPsu/Y/qImKri0nwSEZog==", "dev": true, "requires": { "@types/minimist": "^1.2.0", - "arrify": "^2.0.1", - "camelcase": "^6.0.0", "camelcase-keys": "^6.2.2", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", - "minimist-options": "^4.0.2", + "minimist-options": "4.1.0", "normalize-package-data": "^2.5.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", @@ -5344,12 +5421,6 @@ "yargs-parser": "^18.1.3" }, "dependencies": { - "camelcase": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", - "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==", - "dev": true - }, "read-pkg-up": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", @@ -6152,9 +6223,9 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "requires": { "mimic-fn": "^2.1.0" } @@ -6200,29 +6271,18 @@ } }, "ora": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.5.tgz", - "integrity": "sha512-jCDgm9DqvRcNIAEv2wZPrh7E5PcQiDUnbnWbAfu4NGAE2ZNqPFbDixmWldy1YG2QfLeQhuiu6/h5VRrk6cG50w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.0.0.tgz", + "integrity": "sha512-s26qdWqke2kjN/wC4dy+IQPBIMWBJlSU/0JZhk30ZDBLelW25rv66yutUWARMigpGPzcXHb+Nac5pNhN/WsARw==", "requires": { - "chalk": "^3.0.0", + "chalk": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-spinners": "^2.2.0", + "cli-spinners": "^2.4.0", "is-interactive": "^1.0.0", - "log-symbols": "^3.0.0", + "log-symbols": "^4.0.0", "mute-stream": "0.0.8", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } } }, "os-browserify": { @@ -6367,14 +6427,13 @@ } }, "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "dev": true, "requires": { - "asn1.js": "^4.0.0", + "asn1.js": "^5.2.0", "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" @@ -6786,13 +6845,13 @@ }, "dependencies": { "parse-json": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.1.tgz", - "integrity": "sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, @@ -7274,17 +7333,17 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "sinon": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", - "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.3.tgz", + "integrity": "sha512-IKo9MIM111+smz9JGwLmw5U1075n1YXeAq8YeSFlndCLhAL5KGn6bLgu7b/4AYHTV/LcEMcRm2wU2YiL55/6Pg==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.2", "@sinonjs/fake-timers": "^6.0.1", "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.0.3", + "@sinonjs/samsam": "^5.1.0", "diff": "^4.0.2", - "nise": "^4.0.1", + "nise": "^4.0.4", "supports-color": "^7.1.0" } }, @@ -9580,9 +9639,9 @@ } }, "update-notifier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", - "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.1.tgz", + "integrity": "sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg==", "requires": { "boxen": "^4.2.0", "chalk": "^3.0.0", @@ -9693,9 +9752,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz", - "integrity": "sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-5.0.1.tgz", + "integrity": "sha512-mbDNjuDajqYe3TXFk5qxcQy8L1msXNE37WTlLoqqpBfRsimbNcrlhQlDPntmECEcUvdC+AQ8CyMMf6EUx1r74Q==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -9825,30 +9884,30 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" }, "xo": { - "version": "0.32.1", - "resolved": "https://registry.npmjs.org/xo/-/xo-0.32.1.tgz", - "integrity": "sha512-L43ROY2opNW7yp7byEAibBSk0jYvMuC4yUUrphkqegqU76Bxp5Rc+Gcl62lK1f5zuRrlY0IwMypIfY4EPSzMfQ==", + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/xo/-/xo-0.33.0.tgz", + "integrity": "sha512-9fUpHn9w2trvZSatInPfscwQVO3f60nXcTelg4GV6u0/+aqx3DPEdEliWFN7cmtUUf8sofZH3Itjg8Txnvzv3A==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "^3.1.0", - "@typescript-eslint/parser": "^3.1.0", + "@typescript-eslint/eslint-plugin": "^3.9.0", + "@typescript-eslint/parser": "^3.9.0", "arrify": "^2.0.1", - "cosmiconfig": "^6.0.0", + "cosmiconfig": "^7.0.0", "debug": "^4.1.1", - "eslint": "^7.1.0", + "eslint": "^7.6.0", "eslint-config-prettier": "^6.11.0", - "eslint-config-xo": "^0.30.0", - "eslint-config-xo-typescript": "^0.31.0", - "eslint-formatter-pretty": "^3.0.1", + "eslint-config-xo": "^0.32.1", + "eslint-config-xo-typescript": "^0.32.0", + "eslint-formatter-pretty": "^4.0.0", "eslint-import-resolver-webpack": "^0.12.1", - "eslint-plugin-ava": "^10.3.0", + "eslint-plugin-ava": "^10.5.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.20.2", "eslint-plugin-no-use-extend-native": "^0.5.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.3", "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-unicorn": "^20.1.0", + "eslint-plugin-unicorn": "^21.0.0", "find-cache-dir": "^3.3.1", "find-up": "^4.1.0", "fs-extra": "^9.0.0", @@ -9859,7 +9918,7 @@ "is-path-inside": "^3.0.2", "json-stable-stringify-without-jsonify": "^1.0.1", "json5": "^2.1.3", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "meow": "^7.0.1", "micromatch": "^4.0.2", "open-editor": "^2.0.1", @@ -9871,7 +9930,7 @@ "semver": "^7.3.2", "slash": "^3.0.0", "to-absolute-glob": "^2.0.2", - "typescript": "^3.3.1", + "typescript": "^3.9.7", "update-notifier": "^4.1.0" }, "dependencies": { @@ -9919,16 +9978,6 @@ } } }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "dir-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", @@ -9938,21 +9987,6 @@ "path-type": "^3.0.0" } }, - "eslint-formatter-pretty": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-formatter-pretty/-/eslint-formatter-pretty-3.0.1.tgz", - "integrity": "sha512-hhQ/ASD4i6BAEalcEfUxesFtJFftT8xFsimCzUpPbTzygJ4J17yCGcJ3XKCB2g7XTJTv0pi7rVTadfHVmtfSRA==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "eslint-rule-docs": "^1.1.5", - "log-symbols": "^3.0.0", - "plur": "^3.0.1", - "string-width": "^4.2.0", - "supports-hyperlinks": "^2.0.0" - } - }, "fast-glob": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", @@ -10075,12 +10109,6 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "irregular-plurals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", - "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", - "dev": true - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -10118,15 +10146,6 @@ } } }, - "plur": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", - "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", - "dev": true, - "requires": { - "irregular-plurals": "^2.0.0" - } - }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", diff --git a/package.json b/package.json index 3d17e8526..bb655a060 100644 --- a/package.json +++ b/package.json @@ -56,14 +56,14 @@ ], "dependencies": { "@concordance/react": "^2.0.0", - "acorn": "^7.3.1", - "acorn-walk": "^7.2.0", + "acorn": "^8.0.1", + "acorn-walk": "^8.0.0", "ansi-styles": "^4.2.1", "arrgv": "^1.0.2", "arrify": "^2.0.1", "callsites": "^3.1.0", "chalk": "^4.1.0", - "chokidar": "^3.4.1", + "chokidar": "^3.4.2", "chunkd": "^2.0.1", "ci-info": "^2.0.0", "ci-parallel-vars": "^1.0.1", @@ -72,7 +72,7 @@ "cli-truncate": "^2.1.0", "code-excerpt": "^3.0.0", "common-path-prefix": "^3.0.0", - "concordance": "^5.0.0", + "concordance": "^5.0.1", "convert-source-map": "^1.7.0", "currently-unhandled": "^0.4.1", "debug": "^4.1.1", @@ -87,12 +87,12 @@ "is-error": "^2.2.2", "is-plain-object": "^4.1.1", "is-promise": "^4.0.0", - "lodash": "^4.17.19", + "lodash": "^4.17.20", "matcher": "^3.0.0", "md5-hex": "^3.0.1", "mem": "^6.1.0", "ms": "^2.1.2", - "ora": "^4.0.5", + "ora": "^5.0.0", "p-map": "^4.0.0", "picomatch": "^2.2.2", "pkg-conf": "^3.1.0", @@ -107,7 +107,7 @@ "supertap": "^1.0.0", "temp-dir": "^2.0.0", "trim-off-newlines": "^1.0.1", - "update-notifier": "^4.1.0", + "update-notifier": "^4.1.1", "write-file-atomic": "^3.0.3", "yargs": "^15.4.1" }, @@ -117,17 +117,17 @@ "@babel/plugin-proposal-do-expressions": "^7.10.4", "@sinonjs/fake-timers": "^6.0.1", "ansi-escapes": "^4.3.1", - "c8": "^7.2.1", + "c8": "^7.3.0", "delay": "^4.4.0", "esm": "^3.2.25", "execa": "^4.0.3", - "get-stream": "^5.1.0", + "get-stream": "^6.0.0", "p-event": "^4.2.0", "proxyquire": "^2.1.3", "react": "^16.13.1", "react-test-renderer": "^16.13.1", "replace-string": "^3.1.0", - "sinon": "^9.0.2", + "sinon": "^9.0.3", "source-map-fixtures": "^2.1.0", "tap": "^14.10.8", "temp-write": "^4.0.0", @@ -135,7 +135,7 @@ "touch": "^3.1.0", "tsd": "^0.13.1", "typescript": "^3.9.7", - "xo": "^0.32.1", + "xo": "^0.33.0", "zen-observable": "^0.8.15" } } diff --git a/test-tap/runner.js b/test-tap/runner.js index 446122b9a..5954c87cf 100644 --- a/test-tap/runner.js +++ b/test-tap/runner.js @@ -796,7 +796,9 @@ test('hooks run concurrently, but can be serialized', t => { runner.chain.before(() => { t.is(activeCount, 0); activeCount++; - return new Promise(resolve => setTimeout(resolve, 20)).then(() => { + return new Promise(resolve => { + setTimeout(resolve, 20); + }).then(() => { activeCount--; }); }); @@ -804,7 +806,9 @@ test('hooks run concurrently, but can be serialized', t => { runner.chain.before(() => { t.is(activeCount, 1); activeCount++; - return new Promise(resolve => setTimeout(resolve, 10)).then(() => { + return new Promise(resolve => { + setTimeout(resolve, 10); + }).then(() => { activeCount--; }); }); @@ -812,7 +816,9 @@ test('hooks run concurrently, but can be serialized', t => { runner.chain.serial.before(() => { t.is(activeCount, 0); activeCount++; - return new Promise(resolve => setTimeout(resolve, 10)).then(() => { + return new Promise(resolve => { + setTimeout(resolve, 10); + }).then(() => { activeCount--; }); }); @@ -820,7 +826,9 @@ test('hooks run concurrently, but can be serialized', t => { runner.chain.before(() => { t.is(activeCount, 0); activeCount++; - return new Promise(resolve => setTimeout(resolve, 20)).then(() => { + return new Promise(resolve => { + setTimeout(resolve, 20); + }).then(() => { activeCount--; }); }); @@ -828,7 +836,9 @@ test('hooks run concurrently, but can be serialized', t => { runner.chain.before(() => { t.is(activeCount, 1); activeCount++; - return new Promise(resolve => setTimeout(resolve, 10)).then(() => { + return new Promise(resolve => { + setTimeout(resolve, 10); + }).then(() => { activeCount--; }); }); @@ -836,7 +846,9 @@ test('hooks run concurrently, but can be serialized', t => { runner.chain.serial.before(() => { t.is(activeCount, 0); activeCount++; - return new Promise(resolve => setTimeout(resolve, 10)).then(() => { + return new Promise(resolve => { + setTimeout(resolve, 10); + }).then(() => { activeCount--; }); }); From 1e064b0e610fe35508bf6e4f9b9ba43cb1e01009 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Sun, 23 Aug 2020 21:39:09 +0200 Subject: [PATCH 05/14] 3.12.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 81e040dd8..752623a30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ava", - "version": "3.11.1", + "version": "3.12.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index bb655a060..4ed7ce6d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ava", - "version": "3.11.1", + "version": "3.12.0", "description": "Node.js test runner that lets you develop with confidence.", "license": "MIT", "repository": "avajs/ava", From e0aa9c6d2dce5bc885a5816cecc194cb71b0dd95 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Mon, 24 Aug 2020 11:04:42 +0200 Subject: [PATCH 06/14] Revert advanced IPC * Revert "Don't use global setImmediate" This reverts commit ea66e6455cdadedc74f6cefc42cc1ccf07e1fc18. * Revert "Use advanced serialization (when available) for worker communication" This reverts commit 0f879f46811369aaf3102d9038bf73e3a494d6b5. --- lib/cli.js | 2 +- lib/fork.js | 20 +++------ lib/ipc-flow-control.js | 42 ------------------- lib/worker/ipc.js | 6 +-- .../report/regular/uncaught-exception.js | 2 +- test-tap/reporters/mini.regular.v10.log | 4 +- test-tap/reporters/mini.regular.v12.log | 7 ++-- test-tap/reporters/mini.regular.v14.log | 7 ++-- test-tap/reporters/tap.regular.v10.log | 4 +- test-tap/reporters/tap.regular.v12.log | 9 ++-- test-tap/reporters/tap.regular.v14.log | 9 ++-- test-tap/reporters/verbose.regular.v10.log | 4 +- test-tap/reporters/verbose.regular.v12.log | 7 ++-- test-tap/reporters/verbose.regular.v14.log | 7 ++-- test/helpers/exec.js | 2 +- 15 files changed, 41 insertions(+), 91 deletions(-) delete mode 100644 lib/ipc-flow-control.js diff --git a/lib/cli.js b/lib/cli.js index 7e83bb1bd..ef93cf5a7 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -430,7 +430,7 @@ exports.run = async () => { // eslint-disable-line complexity reporter.startRun(plan); if (process.env.AVA_EMIT_RUN_STATUS_OVER_IPC === 'I\'ll find a payphone baby / Take some time to talk to you') { - if (process.versions.node >= '12.17.0') { + if (process.versions.node >= '12.16.0') { plan.status.on('stateChange', evt => { process.send(evt); }); diff --git a/lib/fork.js b/lib/fork.js index cf0717d9c..f393011e5 100644 --- a/lib/fork.js +++ b/lib/fork.js @@ -3,7 +3,6 @@ const childProcess = require('child_process'); const path = require('path'); const fs = require('fs'); const Emittery = require('emittery'); -const {controlFlow} = require('./ipc-flow-control'); if (fs.realpathSync(__filename) !== __filename) { console.warn('WARNING: `npm link ava` and the `--preserve-symlink` flag are incompatible. We have detected that AVA is linked via `npm link`, and that you are using either an early version of Node 6, or the `--preserve-symlink` flag. This breaks AVA. You should upgrade to Node 6.2.0+, avoid the `--preserve-symlink` flag, or avoid using `npm link ava`.'); @@ -15,12 +14,6 @@ const AVA_PATH = path.resolve(__dirname, '..'); const workerPath = require.resolve('./worker/subprocess'); -const useAdvanced = process.versions.node >= '12.17.0'; -// FIXME: Fix this in api.js or cli.js. -const serializeOptions = useAdvanced ? - options => JSON.parse(JSON.stringify(options)) : // Use JSON serialization to remove non-clonable values. - options => options; - module.exports = (file, options, execArgv = process.execArgv) => { let finished = false; @@ -41,8 +34,7 @@ module.exports = (file, options, execArgv = process.execArgv) => { cwd: options.projectDir, silent: true, env: {NODE_ENV: 'test', ...process.env, ...options.environmentVariables, AVA_PATH}, - execArgv, - serialization: useAdvanced ? 'advanced' : 'json' + execArgv }); subprocess.stdout.on('data', chunk => { @@ -53,12 +45,12 @@ module.exports = (file, options, execArgv = process.execArgv) => { emitStateChange({type: 'worker-stderr', chunk}); }); - const bufferedSend = controlFlow(subprocess); - let forcedExit = false; const send = evt => { - if (!finished && !forcedExit) { - bufferedSend({ava: evt}); + if (subprocess.connected && !finished && !forcedExit) { + subprocess.send({ava: evt}, () => { + // Disregard errors. + }); } }; @@ -74,7 +66,7 @@ module.exports = (file, options, execArgv = process.execArgv) => { } if (message.ava.type === 'ready-for-options') { - send({type: 'options', options: serializeOptions(options)}); + send({type: 'options', options}); return; } diff --git a/lib/ipc-flow-control.js b/lib/ipc-flow-control.js deleted file mode 100644 index 89a355372..000000000 --- a/lib/ipc-flow-control.js +++ /dev/null @@ -1,42 +0,0 @@ -// Manage how quickly messages are delivered to the channel. In theory, we -// should be able to call `send()` until it returns `false` but this leads to -// crashes with advanced serialization, see -// . -// -// Even if that's fixed (and the Node.js versions with the fixes are the -// minimally supported versions) we need flow control based on `send()`'s return -// value. - -const nowAndTimers = require('./now-and-timers'); - -function controlFlow(channel) { - let sending = false; - - const buffer = []; - const deliverNext = () => { - if (!channel.connected) { - buffer.length = 0; - } - - if (buffer.length === 0) { - sending = false; - return; - } - - channel.send(buffer.shift(), deliverNext); - }; - - return message => { - if (!channel.connected) { - return; - } - - buffer.push(message); - if (!sending) { - sending = true; - nowAndTimers.setImmediate(deliverNext); - } - }; -} - -exports.controlFlow = controlFlow; diff --git a/lib/worker/ipc.js b/lib/worker/ipc.js index 0f172c6c9..2eb5bda86 100644 --- a/lib/worker/ipc.js +++ b/lib/worker/ipc.js @@ -1,6 +1,5 @@ 'use strict'; const Emittery = require('emittery'); -const {controlFlow} = require('../ipc-flow-control'); const emitter = new Emittery(); process.on('message', message => { @@ -26,9 +25,10 @@ process.on('message', message => { exports.options = emitter.once('options'); exports.peerFailed = emitter.once('peerFailed'); -const bufferedSend = controlFlow(process); function send(evt) { - bufferedSend({ava: evt}); + if (process.connected) { + process.send({ava: evt}); + } } exports.send = send; diff --git a/test-tap/fixture/report/regular/uncaught-exception.js b/test-tap/fixture/report/regular/uncaught-exception.js index e23a53f5c..020ebb012 100644 --- a/test-tap/fixture/report/regular/uncaught-exception.js +++ b/test-tap/fixture/report/regular/uncaught-exception.js @@ -1,7 +1,7 @@ const test = require('../../../..'); test('passes', t => { - setImmediate(() => { + setTimeout(() => { throw new Error('Can’t catch me'); }); t.pass(); diff --git a/test-tap/reporters/mini.regular.v10.log b/test-tap/reporters/mini.regular.v10.log index a05131d46..9a5cea281 100644 --- a/test-tap/reporters/mini.regular.v10.log +++ b/test-tap/reporters/mini.regular.v10.log @@ -515,13 +515,13 @@ uncaught-exception.js:5 - 4: setImmediate(() => { + 4: setTimeout(() => {  5: throw new Error('Can’t catch me'); 6: }); Error: Can’t catch me - › Immediate.setImmediate (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + › Timeout.setTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) diff --git a/test-tap/reporters/mini.regular.v12.log b/test-tap/reporters/mini.regular.v12.log index 5f7ea89a6..af1efa390 100644 --- a/test-tap/reporters/mini.regular.v12.log +++ b/test-tap/reporters/mini.regular.v12.log @@ -497,14 +497,15 @@ uncaught-exception.js:5 - 4: setImmediate(() => { + 4: setTimeout(() => {  5: throw new Error('Can’t catch me'); 6: }); Error: Can’t catch me - › Immediate. (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › processImmediate (internal/timers.js:456:21) + › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + › listOnTimeout (internal/timers.js:549:17) + › processTimers (internal/timers.js:492:7) diff --git a/test-tap/reporters/mini.regular.v14.log b/test-tap/reporters/mini.regular.v14.log index 1bd6425c4..cb509dedb 100644 --- a/test-tap/reporters/mini.regular.v14.log +++ b/test-tap/reporters/mini.regular.v14.log @@ -497,14 +497,15 @@ uncaught-exception.js:5 - 4: setImmediate(() => { + 4: setTimeout(() => {  5: throw new Error('Can’t catch me'); 6: }); Error: Can’t catch me - › Immediate. (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › processImmediate (internal/timers.js:458:21) + › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + › listOnTimeout (internal/timers.js:551:17) + › processTimers (internal/timers.js:494:7) diff --git a/test-tap/reporters/tap.regular.v10.log b/test-tap/reporters/tap.regular.v10.log index e0d6eddb1..09ad84f4c 100644 --- a/test-tap/reporters/tap.regular.v10.log +++ b/test-tap/reporters/tap.regular.v10.log @@ -323,9 +323,7 @@ not ok 25 - Error: Can’t catch me --- name: Error message: Can’t catch me - at: >- - Immediate.setImmediate - (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + at: 'Timeout.setTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9)' ... ---tty-stream-chunk-separator # uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/tap.regular.v12.log b/test-tap/reporters/tap.regular.v12.log index 86828fc8c..92dabd285 100644 --- a/test-tap/reporters/tap.regular.v12.log +++ b/test-tap/reporters/tap.regular.v12.log @@ -296,11 +296,10 @@ not ok 25 - Error: Can’t catch me --- name: Error message: Can’t catch me - at: >- - Immediate. - (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - - processImmediate (internal/timers.js:456:21) + at: |- + Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + listOnTimeout (internal/timers.js:549:17) + processTimers (internal/timers.js:492:7) ... ---tty-stream-chunk-separator # uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/tap.regular.v14.log b/test-tap/reporters/tap.regular.v14.log index f878d9f91..7aafb489b 100644 --- a/test-tap/reporters/tap.regular.v14.log +++ b/test-tap/reporters/tap.regular.v14.log @@ -296,11 +296,10 @@ not ok 25 - Error: Can’t catch me --- name: Error message: Can’t catch me - at: >- - Immediate. - (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - - processImmediate (internal/timers.js:458:21) + at: |- + Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + listOnTimeout (internal/timers.js:551:17) + processTimers (internal/timers.js:494:7) ... ---tty-stream-chunk-separator # uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/verbose.regular.v10.log b/test-tap/reporters/verbose.regular.v10.log index f7d3ea109..8c0b7b721 100644 --- a/test-tap/reporters/verbose.regular.v10.log +++ b/test-tap/reporters/verbose.regular.v10.log @@ -87,13 +87,13 @@ uncaught-exception.js:5 - 4: setImmediate(() => { + 4: setTimeout(() => {  5: throw new Error('Can’t catch me'); 6: }); Error: Can’t catch me - › Immediate.setImmediate (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + › Timeout.setTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) ---tty-stream-chunk-separator ✖ uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/verbose.regular.v12.log b/test-tap/reporters/verbose.regular.v12.log index 62e9e5862..dcc88f811 100644 --- a/test-tap/reporters/verbose.regular.v12.log +++ b/test-tap/reporters/verbose.regular.v12.log @@ -87,14 +87,15 @@ uncaught-exception.js:5 - 4: setImmediate(() => { + 4: setTimeout(() => {  5: throw new Error('Can’t catch me'); 6: }); Error: Can’t catch me - › Immediate. (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › processImmediate (internal/timers.js:456:21) + › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + › listOnTimeout (internal/timers.js:549:17) + › processTimers (internal/timers.js:492:7) ---tty-stream-chunk-separator ✖ uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/verbose.regular.v14.log b/test-tap/reporters/verbose.regular.v14.log index 438e94b62..0514a3f43 100644 --- a/test-tap/reporters/verbose.regular.v14.log +++ b/test-tap/reporters/verbose.regular.v14.log @@ -87,14 +87,15 @@ uncaught-exception.js:5 - 4: setImmediate(() => { + 4: setTimeout(() => {  5: throw new Error('Can’t catch me'); 6: }); Error: Can’t catch me - › Immediate. (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › processImmediate (internal/timers.js:458:21) + › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) + › listOnTimeout (internal/timers.js:551:17) + › processTimers (internal/timers.js:494:7) ---tty-stream-chunk-separator ✖ uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test/helpers/exec.js b/test/helpers/exec.js index 8c9dec619..cc85c1761 100644 --- a/test/helpers/exec.js +++ b/test/helpers/exec.js @@ -8,7 +8,7 @@ const defaultsDeep = require('lodash/defaultsDeep'); const cliPath = path.resolve(__dirname, '../../cli.js'); const ttySimulator = path.join(__dirname, './simulate-tty.js'); -const serialization = process.versions.node >= '12.17.0' ? 'advanced' : 'json'; +const serialization = process.versions.node >= '12.16.0' ? 'advanced' : 'json'; const normalizePath = (root, file) => path.posix.normalize(path.relative(root, file)); From ce3797b240e471a7ff68fcc50ce42c2a7181c87a Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Mon, 24 Aug 2020 12:01:38 +0200 Subject: [PATCH 07/14] 3.12.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 752623a30..8b62d4a26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ava", - "version": "3.12.0", + "version": "3.12.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4ed7ce6d5..dc76447ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ava", - "version": "3.12.0", + "version": "3.12.1", "description": "Node.js test runner that lets you develop with confidence.", "license": "MIT", "repository": "avajs/ava", From 1ab3cfbd6dd2495323d54e32895ff44e119fc6db Mon Sep 17 00:00:00 2001 From: "Mark S. Miller" Date: Tue, 25 Aug 2020 01:06:51 -0700 Subject: [PATCH 08/14] Fix typo in VSCode recipe --- docs/recipes/debugging-with-vscode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/recipes/debugging-with-vscode.md b/docs/recipes/debugging-with-vscode.md index f3602df29..f3cb3797c 100644 --- a/docs/recipes/debugging-with-vscode.md +++ b/docs/recipes/debugging-with-vscode.md @@ -13,7 +13,7 @@ You can use VS Code's “JavaScript Debug Terminal” to automatically debug AVA ## Creating a launch configuration -Alternatively you can create a lanch configuration, which makes it easier to debug individual test files. +Alternatively you can create a launch configuration, which makes it easier to debug individual test files. 1. Open a workspace for your project. 1. In the sidebar click the *Debug* handle. From 3b4e3dec6b6af6f6a36c24d279aabd0616e73df6 Mon Sep 17 00:00:00 2001 From: Jonathan Samines Date: Sat, 5 Sep 2020 08:44:32 -0600 Subject: [PATCH 09/14] Update enzyme recipe to work with latest enzyme --- docs/recipes/react.md | 49 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/docs/recipes/react.md b/docs/recipes/react.md index 4037a5514..bfc5a8743 100644 --- a/docs/recipes/react.md +++ b/docs/recipes/react.md @@ -26,21 +26,59 @@ You can find more information in [`@ava/babel`](https://github.com/avajs/babel). ## Using [Enzyme](https://github.com/airbnb/enzyme) -Let's first see how to use AVA with one of the most popular React testing libraries: [Enzyme](https://github.com/airbnb/enzyme). +Let's first see how to use AVA with one of the most popular React testing libraries: [Enzyme](https://github.com/enzymejs/enzyme). If you intend to only use [shallow component rendering](https://facebook.github.io/react/docs/test-utils.html#shallow-rendering), you don't need any extra setup. -First install [Enzyme required packages](https://github.com/airbnb/enzyme/#installation): +### Install Enzyme + +First install [Enzyme and its required adapter](https://github.com/enzymejs/enzyme#installation): ```console -$ npm install --save-dev enzyme react-addons-test-utils react-dom +$ npm install --save-dev enzyme enzyme-adapter-react-16 +``` + +### Set up Enzyme + +Create a helper file, prefixed with an underscore. This ensures AVA does not treat it as a test. + +`test/_setup-enzyme-adapter.js`: + +```js +const Enzyme = require('enzyme'); +const Adapter = require('enzyme-adapter-react-16'); + +Enzyme.configure({ + adapter: new Adapter() +}); +``` + +### Configure tests to use Enzyme + +Configure AVA to `require` the helper before every test file. + +**`package.json`:** + +```json +{ + "ava": { + "require": [ + "./test/_setup-enzyme-adapter.js" + ] + } +} ``` +### Enjoy + Then you can use Enzyme straight away: +`test.js`: + ```js const test = require('ava'); const React = require('react'); +const PropTypes = require('prop-types'); const {shallow} = require('enzyme'); const Foo = ({children}) => @@ -51,7 +89,7 @@ const Foo = ({children}) => ; Foo.propTypes = { - children: React.PropTypes.any + children: PropTypes.any }; test('has a .Foo class name', t => { @@ -93,6 +131,7 @@ Usage example: ```js const test = require('ava'); const React = require('react'); +const PropTypes = require('prop-types'); const {renderJSX, JSX} = require('jsx-test-helpers'); const Foo = ({children}) => @@ -103,7 +142,7 @@ const Foo = ({children}) => ; Foo.propTypes = { - children: React.PropTypes.any + children: PropTypes.any }; test('renders correct markup', t => { From 13ac99c0f2f840cb80da8f137f7e32a740e5aeac Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Tue, 8 Sep 2020 10:39:57 +0200 Subject: [PATCH 10/14] Sanitize timers.js positions in reporter logs --- test-tap/helper/report.js | 1 + test-tap/reporters/mini.js | 2 +- test-tap/reporters/mini.regular.v12.log | 4 ++-- test-tap/reporters/mini.regular.v14.log | 4 ++-- test-tap/reporters/tap.js | 2 +- test-tap/reporters/tap.regular.v12.log | 4 ++-- test-tap/reporters/tap.regular.v14.log | 4 ++-- test-tap/reporters/verbose.js | 2 +- test-tap/reporters/verbose.regular.v12.log | 4 ++-- test-tap/reporters/verbose.regular.v14.log | 4 ++-- 10 files changed, 16 insertions(+), 15 deletions(-) diff --git a/test-tap/helper/report.js b/test-tap/helper/report.js index b374dd6fa..1656cccaf 100644 --- a/test-tap/helper/report.js +++ b/test-tap/helper/report.js @@ -61,6 +61,7 @@ exports.sanitizers = { experimentalWarning: string => string.replace(/^\(node:\d+\) ExperimentalWarning.+\n/g, ''), lineEndings: string => replaceString(string, '\r\n', '\n'), posix: string => replaceString(string, '\\', '/'), + timers: string => string.replace(/timers\.js:\d+:\d+/g, 'timers.js'), version: string => replaceString(string, `v${pkg.version}`, 'v1.0.0-beta.5.1') }; diff --git a/test-tap/reporters/mini.js b/test-tap/reporters/mini.js index d06424b56..0c541157b 100644 --- a/test-tap/reporters/mini.js +++ b/test-tap/reporters/mini.js @@ -19,7 +19,7 @@ const run = (type, sanitizers = []) => t => { const tty = new TTYStream({ columns: 200, - sanitizers: [...sanitizers, report.sanitizers.cwd, report.sanitizers.experimentalWarning, report.sanitizers.posix, report.sanitizers.version] + sanitizers: [...sanitizers, report.sanitizers.cwd, report.sanitizers.experimentalWarning, report.sanitizers.posix, report.sanitizers.timers, report.sanitizers.version] }); const reporter = new Reporter({ projectDir: report.projectDir(type), diff --git a/test-tap/reporters/mini.regular.v12.log b/test-tap/reporters/mini.regular.v12.log index af1efa390..e4dfaac1a 100644 --- a/test-tap/reporters/mini.regular.v12.log +++ b/test-tap/reporters/mini.regular.v12.log @@ -504,8 +504,8 @@ Error: Can’t catch me › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › listOnTimeout (internal/timers.js:549:17) - › processTimers (internal/timers.js:492:7) + › listOnTimeout (internal/timers.js) + › processTimers (internal/timers.js) diff --git a/test-tap/reporters/mini.regular.v14.log b/test-tap/reporters/mini.regular.v14.log index cb509dedb..e4dfaac1a 100644 --- a/test-tap/reporters/mini.regular.v14.log +++ b/test-tap/reporters/mini.regular.v14.log @@ -504,8 +504,8 @@ Error: Can’t catch me › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › listOnTimeout (internal/timers.js:551:17) - › processTimers (internal/timers.js:494:7) + › listOnTimeout (internal/timers.js) + › processTimers (internal/timers.js) diff --git a/test-tap/reporters/tap.js b/test-tap/reporters/tap.js index 4290bc361..846f7f378 100644 --- a/test-tap/reporters/tap.js +++ b/test-tap/reporters/tap.js @@ -14,7 +14,7 @@ const run = (type, sanitizers = []) => t => { const tty = new TTYStream({ columns: 200, - sanitizers: [...sanitizers, report.sanitizers.cwd, report.sanitizers.experimentalWarning, report.sanitizers.posix] + sanitizers: [...sanitizers, report.sanitizers.cwd, report.sanitizers.experimentalWarning, report.sanitizers.posix, report.sanitizers.timers] }); const reporter = new TapReporter({ projectDir: report.projectDir(type), diff --git a/test-tap/reporters/tap.regular.v12.log b/test-tap/reporters/tap.regular.v12.log index 92dabd285..1c549e76e 100644 --- a/test-tap/reporters/tap.regular.v12.log +++ b/test-tap/reporters/tap.regular.v12.log @@ -298,8 +298,8 @@ not ok 25 - Error: Can’t catch me message: Can’t catch me at: |- Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - listOnTimeout (internal/timers.js:549:17) - processTimers (internal/timers.js:492:7) + listOnTimeout (internal/timers.js) + processTimers (internal/timers.js) ... ---tty-stream-chunk-separator # uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/tap.regular.v14.log b/test-tap/reporters/tap.regular.v14.log index 7aafb489b..1c549e76e 100644 --- a/test-tap/reporters/tap.regular.v14.log +++ b/test-tap/reporters/tap.regular.v14.log @@ -298,8 +298,8 @@ not ok 25 - Error: Can’t catch me message: Can’t catch me at: |- Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - listOnTimeout (internal/timers.js:551:17) - processTimers (internal/timers.js:494:7) + listOnTimeout (internal/timers.js) + processTimers (internal/timers.js) ... ---tty-stream-chunk-separator # uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/verbose.js b/test-tap/reporters/verbose.js index 303bdcb54..3cf6f800b 100644 --- a/test-tap/reporters/verbose.js +++ b/test-tap/reporters/verbose.js @@ -13,7 +13,7 @@ const run = (type, sanitizers = []) => t => { const tty = new TTYStream({ columns: 200, - sanitizers: [...sanitizers, report.sanitizers.cwd, report.sanitizers.experimentalWarning, report.sanitizers.posix, report.sanitizers.version] + sanitizers: [...sanitizers, report.sanitizers.cwd, report.sanitizers.experimentalWarning, report.sanitizers.posix, report.sanitizers.timers, report.sanitizers.version] }); const reporter = new Reporter({ projectDir: report.projectDir(type), diff --git a/test-tap/reporters/verbose.regular.v12.log b/test-tap/reporters/verbose.regular.v12.log index dcc88f811..38a5fa0b2 100644 --- a/test-tap/reporters/verbose.regular.v12.log +++ b/test-tap/reporters/verbose.regular.v12.log @@ -94,8 +94,8 @@ Error: Can’t catch me › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › listOnTimeout (internal/timers.js:549:17) - › processTimers (internal/timers.js:492:7) + › listOnTimeout (internal/timers.js) + › processTimers (internal/timers.js) ---tty-stream-chunk-separator ✖ uncaught-exception.js exited with a non-zero exit code: 1 diff --git a/test-tap/reporters/verbose.regular.v14.log b/test-tap/reporters/verbose.regular.v14.log index 0514a3f43..38a5fa0b2 100644 --- a/test-tap/reporters/verbose.regular.v14.log +++ b/test-tap/reporters/verbose.regular.v14.log @@ -94,8 +94,8 @@ Error: Can’t catch me › Timeout._onTimeout (test-tap/fixture/report/regular/uncaught-exception.js:5:9) - › listOnTimeout (internal/timers.js:551:17) - › processTimers (internal/timers.js:494:7) + › listOnTimeout (internal/timers.js) + › processTimers (internal/timers.js) ---tty-stream-chunk-separator ✖ uncaught-exception.js exited with a non-zero exit code: 1 From 67acbea91107ad8599357fc39e37a5478985fbe2 Mon Sep 17 00:00:00 2001 From: tymfear Date: Wed, 9 Sep 2020 10:22:23 +0300 Subject: [PATCH 11/14] Make `t.passed` usable in tests and teardown functions --- docs/02-execution-context.md | 4 ++-- lib/test.js | 3 ++- test-tap/test.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/02-execution-context.md b/docs/02-execution-context.md index 3d08cbb84..778b826a3 100644 --- a/docs/02-execution-context.md +++ b/docs/02-execution-context.md @@ -24,7 +24,7 @@ Contains shared state from hooks. ## `t.passed` -Whether a test has passed. This value is only accurate in the `test.afterEach()` and `test.afterEach.always()` hooks. +When used in `test.afterEach()` or `test.afterEach.always()` hooks this tells you whether the test has passed. When used in a test itself (including teardown functions) this remains `true` until an assertion fails, the test has ended with an error, or a teardown function caused an error. This value has no meaning in other hooks. ## `t.end()` @@ -36,7 +36,7 @@ Log values contextually alongside the test result instead of immediately printin ## `t.plan(count)` -Plan how many assertion there are in the test. The test will fail if the actual assertion count doesn't match the number of planned assertions. See [assertion planning](./03-assertions.md#assertion-planning). +Plan how many assertions there are in the test. The test will fail if the actual assertion count doesn't match the number of planned assertions. See [assertion planning](./03-assertions.md#assertion-planning). ## `t.teardown(fn)` diff --git a/lib/test.js b/lib/test.js index 1b2af9ff4..e18b78ce2 100644 --- a/lib/test.js +++ b/lib/test.js @@ -187,7 +187,8 @@ class ExecutionContext extends assert.Assertions { } get passed() { - return testMap.get(this).testPassed; + const test = testMap.get(this); + return test.isHook ? test.testPassed : !test.assertError; } _throwsArgStart(assertion, file, line) { diff --git a/test-tap/test.js b/test-tap/test.js index c534f9a84..4b648d990 100644 --- a/test-tap/test.js +++ b/test-tap/test.js @@ -956,3 +956,33 @@ test('.teardown() is bound', t => { t.ok(teardownCallback.calledOnce); }); }); + +test('t.passed value is true when teardown callback is executed for passing test', t => { + new Test({ + fn(a) { + a.teardown(() => { + t.is(a.passed, true); + t.end(); + }); + a.pass(); + }, + metadata: {type: 'test'}, + onResult() {}, + title: 'foo' + }).run(); +}); + +test('t.passed value is false when teardown callback is executed for failing test', t => { + new Test({ + fn(a) { + a.teardown(() => { + t.is(a.passed, false); + t.end(); + }); + a.fail(); + }, + metadata: {type: 'test'}, + onResult() {}, + title: 'foo' + }).run(); +}); From aa06d33f18bd22d408cbb2de6f11cc5612265e37 Mon Sep 17 00:00:00 2001 From: Jonathan Samines Date: Wed, 9 Sep 2020 01:27:25 -0600 Subject: [PATCH 12/14] Convert integration tests to be self-hosted * Reconfigure xo and eslint to purposely ignore bad configurations * Rewrite expectations to use snapshots * Fix trailing symbols strip functionality for output cleanup * Use posix path relative resolution on tests filename snapshots * Normalize posix paths on test snapshots --- .../environment-variables/ava.config.js | 3 - .../dir-a-wrapper/dir-a/dir-a-wrapper-3.js | 5 - .../dir-a-wrapper/dir-a/dir-a-wrapper-4.js | 5 - .../resolve-dir/dir-a/dir-a-base-1.js | 5 - .../resolve-dir/dir-a/dir-a-base-2.js | 5 - .../fixture/pkg-conf/resolve-dir/package.json | 7 - test-tap/integration/concurrency.js | 42 ------ test-tap/integration/config.js | 54 -------- test-tap/integration/environment-variables.js | 35 ----- test-tap/integration/extensions.js | 22 --- test-tap/integration/globs.js | 30 ----- test-tap/integration/line-numbers.js | 108 --------------- test-tap/integration/node-arguments.js | 24 ---- .../concurrency/fixtures/concurrency.js | 2 +- test/concurrency/fixtures/package.json | 7 + test/concurrency/snapshots/test.js.md | 29 ++++ test/concurrency/snapshots/test.js.snap | Bin 0 -> 238 bytes test/concurrency/test.js | 30 +++++ .../fixtures/config-errors/ava.config.js | 1 + .../fixtures/config-errors}/package.json | 0 test/config/fixtures/config-errors/test.js | 5 + .../dir-a-wrapper/dir-a/dir-a-wrapper-3.js | 6 + .../dir-a-wrapper/dir-a/dir-a-wrapper-4.js | 6 + .../resolve-pkg-dir/dir-a/dir-a-base-1.js | 5 + .../resolve-pkg-dir/dir-a/dir-a-base-2.js | 5 + .../fixtures/resolve-pkg-dir/package.json | 7 + test/config/snapshots/test.js.md | 46 +++++++ test/config/snapshots/test.js.snap | Bin 0 -> 351 bytes test/config/test.js | 57 ++++++++ .../experimental.js | 4 +- .../invalid-configurations.js | 10 +- .../snapshots/invalid-configurations.js.snap | Bin 270 -> 275 bytes .../environment-variables/ava.config.js | 4 + .../environment-variables.js | 2 +- .../environment-variables/package.json | 1 + .../package.json | 0 .../snapshots/test.js.md | 33 +++++ .../snapshots/test.js.snap | Bin 0 -> 334 bytes test/environment-variables/test.js | 35 +++++ .../fixtures}/shared-duplicates/package.json | 0 .../top-level-duplicates/package.json | 0 .../fixtures}/top-level/package.json | 0 test/extensions/snapshots/test.js.md | 17 +++ test/extensions/snapshots/test.js.snap | Bin 0 -> 178 bytes test/extensions/test.js | 17 +++ .../globs/fixtures}/files/package.json | 0 .../fixtures}/ignored-by-watcher/package.json | 0 test/globs/snapshots/test.js.md | 17 +++ test/globs/snapshots/test.js.snap | Bin 0 -> 208 bytes test/globs/test.js | 22 +++ test/helpers/exec.js | 16 ++- .../line-numbers/fixtures}/line-numbers.js | 6 +- test/line-numbers/fixtures/package.json | 7 + test/line-numbers/snapshots/test.js.md | 126 ++++++++++++++++++ test/line-numbers/snapshots/test.js.snap | Bin 0 -> 582 bytes test/line-numbers/test.js | 62 +++++++++ .../node-arguments-from-config.js | 2 +- .../node-arguments-from-config}/package.json | 3 + .../node-arguments-from-config}/setup.js | 0 .../node-arguments}/node-arguments.js | 2 +- .../fixtures/node-arguments/package.json | 7 + test/node-arguments/snapshots/test.js.md | 33 +++++ test/node-arguments/snapshots/test.js.snap | Bin 0 -> 418 bytes test/node-arguments/test.js | 32 +++++ test/snapshot-updates/snapshots/test.js.snap | Bin 454 -> 453 bytes test/snapshot-updates/test.js | 6 +- xo.config.js | 1 + 67 files changed, 649 insertions(+), 367 deletions(-) delete mode 100644 test-tap/fixture/environment-variables/ava.config.js delete mode 100644 test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js delete mode 100644 test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js delete mode 100644 test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js delete mode 100644 test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js delete mode 100644 test-tap/fixture/pkg-conf/resolve-dir/package.json delete mode 100644 test-tap/integration/concurrency.js delete mode 100644 test-tap/integration/config.js delete mode 100644 test-tap/integration/environment-variables.js delete mode 100644 test-tap/integration/extensions.js delete mode 100644 test-tap/integration/globs.js delete mode 100644 test-tap/integration/line-numbers.js delete mode 100644 test-tap/integration/node-arguments.js rename test-tap/fixture/concurrency/test.js => test/concurrency/fixtures/concurrency.js (52%) create mode 100644 test/concurrency/fixtures/package.json create mode 100644 test/concurrency/snapshots/test.js.md create mode 100644 test/concurrency/snapshots/test.js.snap create mode 100644 test/concurrency/test.js create mode 100644 test/config/fixtures/config-errors/ava.config.js rename {test-tap/fixture/environment-variables => test/config/fixtures/config-errors}/package.json (100%) create mode 100644 test/config/fixtures/config-errors/test.js create mode 100644 test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js create mode 100644 test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js create mode 100644 test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-1.js create mode 100644 test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-2.js create mode 100644 test/config/fixtures/resolve-pkg-dir/package.json create mode 100644 test/config/snapshots/test.js.md create mode 100644 test/config/snapshots/test.js.snap create mode 100644 test/config/test.js create mode 100644 test/environment-variables/fixtures/environment-variables/ava.config.js rename test-tap/fixture/environment-variables/test.js => test/environment-variables/fixtures/environment-variables/environment-variables.js (71%) create mode 100644 test/environment-variables/fixtures/environment-variables/package.json rename {test-tap/fixture => test/environment-variables/fixtures}/invalid-environment-variables/package.json (100%) create mode 100644 test/environment-variables/snapshots/test.js.md create mode 100644 test/environment-variables/snapshots/test.js.snap create mode 100644 test/environment-variables/test.js rename {test-tap/fixture/invalid-extensions => test/extensions/fixtures}/shared-duplicates/package.json (100%) rename {test-tap/fixture/invalid-extensions => test/extensions/fixtures}/top-level-duplicates/package.json (100%) rename {test-tap/fixture/invalid-extensions => test/extensions/fixtures}/top-level/package.json (100%) create mode 100644 test/extensions/snapshots/test.js.md create mode 100644 test/extensions/snapshots/test.js.snap create mode 100644 test/extensions/test.js rename {test-tap/fixture/invalid-globs => test/globs/fixtures}/files/package.json (100%) rename {test-tap/fixture/invalid-globs => test/globs/fixtures}/ignored-by-watcher/package.json (100%) create mode 100644 test/globs/snapshots/test.js.md create mode 100644 test/globs/snapshots/test.js.snap create mode 100644 test/globs/test.js rename {test-tap/fixture => test/line-numbers/fixtures}/line-numbers.js (60%) create mode 100644 test/line-numbers/fixtures/package.json create mode 100644 test/line-numbers/snapshots/test.js.md create mode 100644 test/line-numbers/snapshots/test.js.snap create mode 100644 test/line-numbers/test.js rename test-tap/fixture/node-arguments/test.js => test/node-arguments/fixtures/node-arguments-from-config/node-arguments-from-config.js (84%) rename {test-tap/fixture/node-arguments => test/node-arguments/fixtures/node-arguments-from-config}/package.json (72%) rename {test-tap/fixture/node-arguments => test/node-arguments/fixtures/node-arguments-from-config}/setup.js (100%) rename {test-tap/fixture => test/node-arguments/fixtures/node-arguments}/node-arguments.js (87%) create mode 100644 test/node-arguments/fixtures/node-arguments/package.json create mode 100644 test/node-arguments/snapshots/test.js.md create mode 100644 test/node-arguments/snapshots/test.js.snap create mode 100644 test/node-arguments/test.js diff --git a/test-tap/fixture/environment-variables/ava.config.js b/test-tap/fixture/environment-variables/ava.config.js deleted file mode 100644 index e64b98605..000000000 --- a/test-tap/fixture/environment-variables/ava.config.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - environmentVariables: {MY_ENVIRONMENT_VARIABLE: 'some value'} -}; diff --git a/test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js b/test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js deleted file mode 100644 index 91dbe5b2c..000000000 --- a/test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('../../../../../..'); - -test('test', t => { - t.pass(); -}); diff --git a/test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js b/test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js deleted file mode 100644 index 91dbe5b2c..000000000 --- a/test-tap/fixture/pkg-conf/resolve-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('../../../../../..'); - -test('test', t => { - t.pass(); -}); diff --git a/test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js b/test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js deleted file mode 100644 index ce4a7c0bd..000000000 --- a/test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-1.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('../../../../..'); - -test('test', t => { - t.pass(); -}); diff --git a/test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js b/test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js deleted file mode 100644 index ce4a7c0bd..000000000 --- a/test-tap/fixture/pkg-conf/resolve-dir/dir-a/dir-a-base-2.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('../../../../..'); - -test('test', t => { - t.pass(); -}); diff --git a/test-tap/fixture/pkg-conf/resolve-dir/package.json b/test-tap/fixture/pkg-conf/resolve-dir/package.json deleted file mode 100644 index 2e6f0c272..000000000 --- a/test-tap/fixture/pkg-conf/resolve-dir/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "application-name", - "version": "0.0.1", - "ava": { - "files": ["dir-a/*.js"] - } -} diff --git a/test-tap/integration/concurrency.js b/test-tap/integration/concurrency.js deleted file mode 100644 index e4c1177ad..000000000 --- a/test-tap/integration/concurrency.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; -const {test} = require('tap'); -const {execCli} = require('../helper/cli'); - -test('bails when --concurrency is provided without value', t => { - execCli(['--concurrency', 'test.js'], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { - t.is(err.code, 1); - t.match(stderr, 'The --concurrency or -c flag must be provided with a nonnegative integer.'); - t.end(); - }); -}); - -test('bails when --concurrency is provided with an input that is a string', t => { - execCli(['--concurrency=foo', 'test.js'], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { - t.is(err.code, 1); - t.match(stderr, 'The --concurrency or -c flag must be provided with a nonnegative integer.'); - t.end(); - }); -}); - -test('bails when --concurrency is provided with an input that is a float', t => { - execCli(['--concurrency=4.7', 'test.js'], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { - t.is(err.code, 1); - t.match(stderr, 'The --concurrency or -c flag must be provided with a nonnegative integer.'); - t.end(); - }); -}); - -test('bails when --concurrency is provided with an input that is negative', t => { - execCli(['--concurrency=-1', 'test.js'], {dirname: 'fixture/concurrency'}, (err, stdout, stderr) => { - t.is(err.code, 1); - t.match(stderr, 'The --concurrency or -c flag must be provided with a nonnegative integer.'); - t.end(); - }); -}); - -test('works when --concurrency is provided with a value', t => { - execCli(['--concurrency=1', 'test.js'], {dirname: 'fixture/concurrency'}, err => { - t.ifError(err); - t.end(); - }); -}); diff --git a/test-tap/integration/config.js b/test-tap/integration/config.js deleted file mode 100644 index 25df91996..000000000 --- a/test-tap/integration/config.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -const fs = require('fs'); -const path = require('path'); -const {test} = require('tap'); -const execa = require('execa'); -const tempy = require('tempy'); -const {execCli} = require('../helper/cli'); - -test('formats errors from ava.config.js', t => { - execCli(['es2015.js'], {dirname: 'fixture/load-config/throws'}, (err, stdout, stderr) => { - t.ok(err); - - const lines = stderr.split('\n'); - t.is(lines[0], ''); - t.match(lines[1], /Error loading ava\.config\.js:/); - t.is(lines[2], ''); - t.match(lines[3], /ava\.config\.js/); - t.match(lines[4], /foo/); - t.end(); - }); -}); - -test('pkg-conf(resolve-dir): works as expected when run from the package.json directory', t => { - execCli(['--verbose'], {dirname: 'fixture/pkg-conf/resolve-dir'}, (err, stdout) => { - t.ifError(err); - t.match(stdout, /dir-a-base-1/); - t.match(stdout, /dir-a-base-2/); - t.notMatch(stdout, /dir-a-wrapper/); - t.notMatch(stdout, /dir-a-wrapper/); - t.end(); - }); -}); - -test('pkg-conf(resolve-dir): resolves tests from the package.json dir if none are specified on cli', t => { - execCli(['--verbose'], {dirname: 'fixture/pkg-conf/resolve-dir/dir-a-wrapper'}, (err, stdout) => { - t.ifError(err); - t.match(stdout, /dir-a-base-1/); - t.match(stdout, /dir-a-base-2/); - t.notMatch(stdout, /dir-a-wrapper/); - t.notMatch(stdout, /dir-a-wrapper/); - t.end(); - }); -}); - -test('use current working directory if `package.json` is not found', () => { - const cwd = tempy.directory(); - const testFilePath = path.join(cwd, 'test.js'); - const cliPath = require.resolve('../../cli.js'); - const avaPath = require.resolve('../../'); - - fs.writeFileSync(testFilePath, `const test = require(${JSON.stringify(avaPath)});\ntest('test', t => { t.pass(); });`); - - return execa(process.execPath, [cliPath], {cwd, env: {AVA_FORCE_CI: 'ci'}}); -}); diff --git a/test-tap/integration/environment-variables.js b/test-tap/integration/environment-variables.js deleted file mode 100644 index fc06a97a3..000000000 --- a/test-tap/integration/environment-variables.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -const {test} = require('tap'); -const figures = require('figures'); -const {execCli} = require('../helper/cli'); - -test('sets default environment variables from the config', t => { - execCli(['test.js'], {dirname: 'fixture/environment-variables'}, (err, stdout) => { - t.ifError(err); - t.match(stdout, /1 test passed/); - t.end(); - }); -}); - -test('overrides environment variables provided through the CLI', t => { - const env = {MY_ENVIRONMENT_VARIABLE: 'some value (updated)'}; - - execCli(['test.js'], {dirname: 'fixture/environment-variables', env}, (err, stdout) => { - t.ifError(err); - t.match(stdout, /1 test passed/); - t.end(); - }); -}); - -test('errors if environment variables are not string values', t => { - execCli(['es2015.js'], {dirname: 'fixture/invalid-environment-variables'}, (err, stdout, stderr) => { - t.ok(err); - - let expectedOutput = '\n '; - expectedOutput += figures.cross + ' The ’environmentVariables’ configuration must be an object containing string values.'; - expectedOutput += '\n'; - - t.is(stderr, expectedOutput); - t.end(); - }); -}); diff --git a/test-tap/integration/extensions.js b/test-tap/integration/extensions.js deleted file mode 100644 index d670c47cc..000000000 --- a/test-tap/integration/extensions.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -const {test} = require('tap'); -const figures = require('figures'); -const {execCli} = require('../helper/cli'); - -for (const [where, which, message = '’js’, ’jsx’'] of [ - ['top-level', 'top-level-duplicates'], - ['top-level and babel', 'shared-duplicates', '’jsx’'] -]) { - test(`errors if ${where} extensions include duplicates`, t => { - execCli(['es2015.js'], {dirname: `fixture/invalid-extensions/${which}`}, (err, stdout, stderr) => { - t.ok(err); - - let expectedOutput = '\n '; - expectedOutput += figures.cross + ` Unexpected duplicate extensions in options: ${message}.`; - expectedOutput += '\n'; - - t.is(stderr, expectedOutput); - t.end(); - }); - }); -} diff --git a/test-tap/integration/globs.js b/test-tap/integration/globs.js deleted file mode 100644 index 64c3b6ad4..000000000 --- a/test-tap/integration/globs.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -const {test} = require('tap'); -const figures = require('figures'); -const {execCli} = require('../helper/cli'); - -test('errors if top-level files is an empty array', t => { - execCli(['es2015.js'], {dirname: 'fixture/invalid-globs/files'}, (err, stdout, stderr) => { - t.ok(err); - - let expectedOutput = '\n '; - expectedOutput += figures.cross + ' The ’files’ configuration must be an array containing glob patterns.'; - expectedOutput += '\n'; - - t.is(stderr, expectedOutput); - t.end(); - }); -}); - -test('errors if top-level ignoredByWatcher is an empty array', t => { - execCli(['es2015.js'], {dirname: 'fixture/invalid-globs/ignored-by-watcher'}, (err, stdout, stderr) => { - t.ok(err); - - let expectedOutput = '\n '; - expectedOutput += figures.cross + ' The ’ignoredByWatcher’ configuration must be an array containing glob patterns.'; - expectedOutput += '\n'; - - t.is(stderr, expectedOutput); - t.end(); - }); -}); diff --git a/test-tap/integration/line-numbers.js b/test-tap/integration/line-numbers.js deleted file mode 100644 index 899dbbf2a..000000000 --- a/test-tap/integration/line-numbers.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; -const {test} = require('tap'); -const {execCli} = require('../helper/cli'); - -test('select test by line number', t => { - execCli([ - 'line-numbers.js', - 'line-numbers.js:3' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /unicorn/); - t.match(stdout, /1 test passed/); - t.notMatch(stdout, /todo/); - t.end(); - }); -}); - -test('select serial test by line number', t => { - execCli([ - 'line-numbers.js:11' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /cat/); - t.match(stdout, /1 test passed/); - t.notMatch(stdout, /todo/); - t.end(); - }); -}); - -test('select todo test by line number', t => { - execCli([ - 'line-numbers.js:15' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /dog/); - t.match(stdout, /1 test todo/); - t.end(); - }); -}); - -test('select tests by line number range', t => { - execCli([ - 'line-numbers.js:5-7' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /unicorn/); - t.match(stdout, /rainbow/); - t.match(stdout, /2 tests passed/); - t.notMatch(stdout, /todo/); - t.end(); - }); -}); - -test('select two tests declared on same line', t => { - execCli([ - 'line-numbers.js:18' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /sun/); - t.match(stdout, /moon/); - t.match(stdout, /2 tests passed/); - t.notMatch(stdout, /todo/); - t.end(); - }); -}); - -test('select only one of two tests declared on same line', t => { - execCli([ - 'line-numbers.js:19' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /moon/); - t.match(stdout, /1 test passed/); - t.notMatch(stdout, /todo/); - t.end(); - }); -}); - -test('no test selected by line number', t => { - execCli([ - 'line-numbers.js:6' - ], (error, stdout) => { - t.ok(error); - t.match(stdout, /Line numbers for line-numbers\.js did not match any tests/); - t.end(); - }); -}); - -test('parent call is not selected', t => { - execCli([ - 'line-numbers.js:23' - ], (error, stdout) => { - t.ok(error); - t.match(stdout, /Line numbers for line-numbers\.js did not match any tests/); - t.end(); - }); -}); - -test('nested call is selected', t => { - execCli([ - 'line-numbers.js:24' - ], (error, stdout) => { - t.ifError(error); - t.match(stdout, /nested/); - t.match(stdout, /1 test passed/); - t.end(); - }); -}); diff --git a/test-tap/integration/node-arguments.js b/test-tap/integration/node-arguments.js deleted file mode 100644 index b807808e8..000000000 --- a/test-tap/integration/node-arguments.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -const {test} = require('tap'); -const {execCli} = require('../helper/cli'); - -test('passes node arguments to workers', t => { - t.plan(1); - execCli(['--node-arguments="--throw-deprecation --zero-fill-buffers"', 'node-arguments.js'], - (err, stdout, stderr) => t.ifError(err, null, {stdout, stderr})); -}); - -test('reads node arguments from config', t => { - t.plan(1); - execCli(['test.js'], { - dirname: 'fixture/node-arguments' - }, (err, stdout, stderr) => t.ifError(err, null, {stdout, stderr})); -}); - -test('detects incomplete --node-arguments', t => { - t.plan(2); - execCli(['--node-arguments="--foo=\'bar"', 'node-arguments.js'], (err, stdout, stderr) => { - t.ok(err); - t.match(stderr, /Could not parse `--node-arguments` value. Make sure all strings are closed and backslashes are used correctly./); - }); -}); diff --git a/test-tap/fixture/concurrency/test.js b/test/concurrency/fixtures/concurrency.js similarity index 52% rename from test-tap/fixture/concurrency/test.js rename to test/concurrency/fixtures/concurrency.js index 5743bf4e2..d4747061d 100644 --- a/test-tap/fixture/concurrency/test.js +++ b/test/concurrency/fixtures/concurrency.js @@ -1,4 +1,4 @@ -const test = require('../../..'); +const test = require('ava'); test('works', t => { t.pass(); diff --git a/test/concurrency/fixtures/package.json b/test/concurrency/fixtures/package.json new file mode 100644 index 000000000..a0befd106 --- /dev/null +++ b/test/concurrency/fixtures/package.json @@ -0,0 +1,7 @@ +{ + "ava": { + "files": [ + "*.js" + ] + } +} diff --git a/test/concurrency/snapshots/test.js.md b/test/concurrency/snapshots/test.js.md new file mode 100644 index 000000000..16c01cfbe --- /dev/null +++ b/test/concurrency/snapshots/test.js.md @@ -0,0 +1,29 @@ +# Snapshot report for `test/concurrency/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## bails when --concurrency is provided with an input that is a float + +> fails with message + + 'The --concurrency or -c flag must be provided with a nonnegative integer.' + +## bails when --concurrency is provided with an input that is a string + +> fails with message + + 'The --concurrency or -c flag must be provided with a nonnegative integer.' + +## bails when --concurrency is provided with an input that is negative + +> fails with message + + 'The --concurrency or -c flag must be provided with a nonnegative integer.' + +## bails when --concurrency is provided without value + +> fails with message + + 'The --concurrency or -c flag must be provided with a nonnegative integer.' diff --git a/test/concurrency/snapshots/test.js.snap b/test/concurrency/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..816ed91000a2c81c6bdb9517cdb731b1ddbe0310 GIT binary patch literal 238 zcmV-gMr0iW*>_P00000000Ba zV_;xlVYqoT!{+F1xk)U2tS3!n3b}+^2N}Vl>wx&k zf@xWapE4f)R$dbC$yYFk5iH6I)EfTq&F39CaiP{C&exn6|A;e!MPq=NnSmW_G9xR4 zAfsnUMyi6YZgPHJa%oXfYF=`sLVl5gZn8pJPGY)3ZfS9eLQ<+iK~a8LW=d*`LV0FM ohC-r3UVdI)YI { + const result = await t.throwsAsync(exec.fixture(['--concurrency', 'concurrency.js'])); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); + +test('bails when --concurrency is provided with an input that is a string', async t => { + const result = await t.throwsAsync(exec.fixture(['--concurrency=foo', 'concurrency.js'])); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); + +test('bails when --concurrency is provided with an input that is a float', async t => { + const result = await t.throwsAsync(exec.fixture(['--concurrency=4.7', 'concurrency.js'])); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); + +test('bails when --concurrency is provided with an input that is negative', async t => { + const result = await t.throwsAsync(exec.fixture(['--concurrency=-1', 'concurrency.js'])); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); + +test('works when --concurrency is provided with a value', async t => { + await t.notThrowsAsync(exec.fixture(['--concurrency=1', 'concurrency.js'])); +}); diff --git a/test/config/fixtures/config-errors/ava.config.js b/test/config/fixtures/config-errors/ava.config.js new file mode 100644 index 000000000..cd8e188c7 --- /dev/null +++ b/test/config/fixtures/config-errors/ava.config.js @@ -0,0 +1 @@ +throw new Error('foo'); diff --git a/test-tap/fixture/environment-variables/package.json b/test/config/fixtures/config-errors/package.json similarity index 100% rename from test-tap/fixture/environment-variables/package.json rename to test/config/fixtures/config-errors/package.json diff --git a/test/config/fixtures/config-errors/test.js b/test/config/fixtures/config-errors/test.js new file mode 100644 index 000000000..5ca41efa1 --- /dev/null +++ b/test/config/fixtures/config-errors/test.js @@ -0,0 +1,5 @@ +const test = require('ava'); + +test('test', t => { + t.pass(); +}); diff --git a/test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js b/test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js new file mode 100644 index 000000000..159662d3d --- /dev/null +++ b/test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-3.js @@ -0,0 +1,6 @@ +// eslint-disable-next-line ava/no-ignored-test-files +const test = require('ava'); + +test('test', t => { + t.pass(); +}); diff --git a/test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js b/test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js new file mode 100644 index 000000000..159662d3d --- /dev/null +++ b/test/config/fixtures/resolve-pkg-dir/dir-a-wrapper/dir-a/dir-a-wrapper-4.js @@ -0,0 +1,6 @@ +// eslint-disable-next-line ava/no-ignored-test-files +const test = require('ava'); + +test('test', t => { + t.pass(); +}); diff --git a/test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-1.js b/test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-1.js new file mode 100644 index 000000000..5ca41efa1 --- /dev/null +++ b/test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-1.js @@ -0,0 +1,5 @@ +const test = require('ava'); + +test('test', t => { + t.pass(); +}); diff --git a/test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-2.js b/test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-2.js new file mode 100644 index 000000000..5ca41efa1 --- /dev/null +++ b/test/config/fixtures/resolve-pkg-dir/dir-a/dir-a-base-2.js @@ -0,0 +1,5 @@ +const test = require('ava'); + +test('test', t => { + t.pass(); +}); diff --git a/test/config/fixtures/resolve-pkg-dir/package.json b/test/config/fixtures/resolve-pkg-dir/package.json new file mode 100644 index 000000000..4cc2f3b9c --- /dev/null +++ b/test/config/fixtures/resolve-pkg-dir/package.json @@ -0,0 +1,7 @@ +{ + "name": "application-name", + "version": "0.0.1", + "ava": { + "files": ["dir-a/*.js"] + } + } diff --git a/test/config/snapshots/test.js.md b/test/config/snapshots/test.js.md new file mode 100644 index 000000000..4115fcb77 --- /dev/null +++ b/test/config/snapshots/test.js.md @@ -0,0 +1,46 @@ +# Snapshot report for `test/config/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## pkg-conf(resolve-dir): resolves tests from the package.json dir if none are specified on cli + +> resolves test files from configuration + + [ + { + file: '../dir-a/dir-a-base-1.js', + title: 'test', + }, + { + file: '../dir-a/dir-a-base-2.js', + title: 'test', + }, + ] + +## pkg-conf(resolve-dir): works as expected when run from the package.json directory + +> resolves test files from configuration + + [ + { + file: 'dir-a/dir-a-base-1.js', + title: 'test', + }, + { + file: 'dir-a/dir-a-base-2.js', + title: 'test', + }, + ] + +## use current working directory if `package.json` is not found + +> resolves test files without configuration + + [ + { + file: 'test.js', + title: 'test name', + }, + ] diff --git a/test/config/snapshots/test.js.snap b/test/config/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..4c31532feab9da2d1363b3aef742ace3f204bb09 GIT binary patch literal 351 zcmV-l0igatRzV2P3lqkTwHi2Ot(^WD{g$bu21MtYl<_ zvH1D<85p@37?~ItxfvO~AsT_KG7!xOHe(@>xg3aZ!pvavPs&P7E@5PXGX(?$z)F8Z zbTJq+qA6uYRmuytkRPaqNraJ^fss{^ktHoNCl$sKP01|MP1FaIx=D$}sk(-GS;c5N zSW7ZX5L#GDQj1H-G1-VHlaT_INe4(95eiU7a4_1yV { + const options = { + cwd: exec.cwd('config-errors') + }; + + const result = await t.throwsAsync(exec.fixture(['test.js'], options)); + + const lines = result.stderr.split('\n'); + + t.is(lines[0], ''); + t.regex(lines[1], /Error loading ava\.config\.js:/); + t.is(lines[2], ''); + t.regex(lines[3], /ava\.config\.js/); + t.regex(lines[4], /foo/); +}); + +test('pkg-conf(resolve-dir): works as expected when run from the package.json directory', async t => { + const options = { + cwd: exec.cwd('resolve-pkg-dir') + }; + + const result = await exec.fixture([], options); + + t.snapshot(result.stats.passed, 'resolves test files from configuration'); +}); + +test('pkg-conf(resolve-dir): resolves tests from the package.json dir if none are specified on cli', async t => { + const options = { + cwd: exec.cwd('resolve-pkg-dir/dir-a-wrapper') + }; + + const result = await exec.fixture(['--verbose'], options); + + t.snapshot(result.stats.passed, 'resolves test files from configuration'); +}); + +test('use current working directory if `package.json` is not found', async t => { + const cwd = tempy.directory(); + const testFilePath = path.join(cwd, 'test.js'); + const avaPath = require.resolve('../../'); + + fs.writeFileSync(testFilePath, `const test = require(${JSON.stringify(avaPath)});\ntest('test name', t => { t.pass(); });`); + + const options = { + cwd + }; + + const result = await exec.fixture([], options); + + t.snapshot(result.stats.passed, 'resolves test files without configuration'); +}); diff --git a/test/configurable-module-format/experimental.js b/test/configurable-module-format/experimental.js index 37d297028..d12c2ae52 100644 --- a/test/configurable-module-format/experimental.js +++ b/test/configurable-module-format/experimental.js @@ -1,10 +1,8 @@ const test = require('@ava/test'); const exec = require('../helpers/exec'); -const stripLeadingFigures = string => string.replace(/^\W+/, ''); - test('opt-in is required', async t => { const result = await t.throwsAsync(exec.fixture(['--config', 'not-enabled.config.js'])); t.is(result.exitCode, 1); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); diff --git a/test/configurable-module-format/invalid-configurations.js b/test/configurable-module-format/invalid-configurations.js index a780e13db..1df36e353 100644 --- a/test/configurable-module-format/invalid-configurations.js +++ b/test/configurable-module-format/invalid-configurations.js @@ -1,24 +1,22 @@ const test = require('@ava/test'); const exec = require('../helpers/exec'); -const stripLeadingFigures = string => string.replace(/^\W+/, ''); - test('cannot configure how js extensions should be loaded', async t => { const result = await t.throwsAsync(exec.fixture(['--config', 'change-js-loading.config.js'])); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); test('cannot configure how cjs extensions should be loaded', async t => { const result = await t.throwsAsync(exec.fixture(['--config', 'change-cjs-loading.config.js'])); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); test('cannot configure how mjs extensions should be loaded', async t => { const result = await t.throwsAsync(exec.fixture(['--config', 'change-mjs-loading.config.js'])); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); test('custom extensions must be either commonjs or module', async t => { const result = await t.throwsAsync(exec.fixture(['--config', 'bad-custom-type.config.js'])); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); diff --git a/test/configurable-module-format/snapshots/invalid-configurations.js.snap b/test/configurable-module-format/snapshots/invalid-configurations.js.snap index 100a0f7b99b72642dcc572f0d41bdb3fd21465c8..a26ad210bc11bc14d7b918ed0bcbe47f3c1c0619 100644 GIT binary patch delta 194 zcmV;z06qVX0+RxNK~_N^Q*L2!b7*gLAa*he0sxtM{YQlFx4sD^Ah&Ow;}IW=2mk;8 z00003%VS_*U||U3Wt-3}agIyDcZJxB8n3^M3?PsW#GMh<;ZhZMMN$rNOzLa@j9^h|pw{40KDBKJw53-Fq+7>^7j5rjk%wC`F^VhlBUscFsI@bqI$Wyau1LxVA+E`*=Uh)@i4Z= r-WOpk%%l>qhTPKP5{0Bxu+jOsx%qhzb0A6}jsY?N^0Jh3@Bsh-G}2N_ diff --git a/test/environment-variables/fixtures/environment-variables/ava.config.js b/test/environment-variables/fixtures/environment-variables/ava.config.js new file mode 100644 index 000000000..ebbfe1444 --- /dev/null +++ b/test/environment-variables/fixtures/environment-variables/ava.config.js @@ -0,0 +1,4 @@ +export default { + environmentVariables: {MY_ENVIRONMENT_VARIABLE: 'some value'}, + files: ['*.js'] +}; diff --git a/test-tap/fixture/environment-variables/test.js b/test/environment-variables/fixtures/environment-variables/environment-variables.js similarity index 71% rename from test-tap/fixture/environment-variables/test.js rename to test/environment-variables/fixtures/environment-variables/environment-variables.js index 9ff79c537..096d09ac7 100644 --- a/test-tap/fixture/environment-variables/test.js +++ b/test/environment-variables/fixtures/environment-variables/environment-variables.js @@ -1,4 +1,4 @@ -const test = require('../../..'); +const test = require('ava'); test('works', t => { t.is(process.env.MY_ENVIRONMENT_VARIABLE, 'some value'); diff --git a/test/environment-variables/fixtures/environment-variables/package.json b/test/environment-variables/fixtures/environment-variables/package.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/environment-variables/fixtures/environment-variables/package.json @@ -0,0 +1 @@ +{} diff --git a/test-tap/fixture/invalid-environment-variables/package.json b/test/environment-variables/fixtures/invalid-environment-variables/package.json similarity index 100% rename from test-tap/fixture/invalid-environment-variables/package.json rename to test/environment-variables/fixtures/invalid-environment-variables/package.json diff --git a/test/environment-variables/snapshots/test.js.md b/test/environment-variables/snapshots/test.js.md new file mode 100644 index 000000000..138d60426 --- /dev/null +++ b/test/environment-variables/snapshots/test.js.md @@ -0,0 +1,33 @@ +# Snapshot report for `test/environment-variables/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## errors if environment variables are not string values + +> fails with message + + 'The ’environmentVariables’ configuration must be an object containing string values.' + +## overrides environment variables provided through the CLI + +> tests pass + + [ + { + file: 'environment-variables.js', + title: 'works', + }, + ] + +## sets default environment variables from the config + +> tests pass + + [ + { + file: 'environment-variables.js', + title: 'works', + }, + ] diff --git a/test/environment-variables/snapshots/test.js.snap b/test/environment-variables/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..43f12dabab1f70b6e8a86a7a1942f4205949874b GIT binary patch literal 334 zcmV-U0kQr;RzVp>&WggBfOM!0j~|N&000000009E zVPIfjX2^4xm&Kt`ILjl8Yw`ra1%8YSAaE3jBOALTc+5|pG4B_bII-kPG9y^D3#i~? zSns_hX61L<1HS&-#lQ3oBUtnUBgi~Q zKLaBd10y2?BR35AR|j!W=<-MBaxa{mRXdamz$bbqFa_&l$n^6lUl5oRg9*IwIs6yp^LRVzbLzS zczJ@AL69*bBqLSfQNv6m^TJ@p0fiNk^YhX&(@TpIOEUBG6mm<8OB9k)6%z9l^1+S; g$(JN%=4IxkD-@R$fvB>?oKm1u0KgUsl0*Uk07>VD_5c6? literal 0 HcmV?d00001 diff --git a/test/environment-variables/test.js b/test/environment-variables/test.js new file mode 100644 index 000000000..0cb91f851 --- /dev/null +++ b/test/environment-variables/test.js @@ -0,0 +1,35 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('sets default environment variables from the config', async t => { + const options = { + cwd: exec.cwd('environment-variables') + }; + + const results = await exec.fixture(['environment-variables.js'], options); + + t.snapshot(results.stats.passed, 'tests pass'); +}); + +test('overrides environment variables provided through the CLI', async t => { + const options = { + cwd: exec.cwd('environment-variables'), + env: { + MY_ENVIRONMENT_VARIABLE: 'some value (updated)' + } + }; + + const results = await exec.fixture(['environment-variables.js'], options); + + t.snapshot(results.stats.passed, 'tests pass'); +}); + +test('errors if environment variables are not string values', async t => { + const options = { + cwd: exec.cwd('invalid-environment-variables') + }; + + const result = await t.throwsAsync(exec.fixture(['environment-variables.js'], options)); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); diff --git a/test-tap/fixture/invalid-extensions/shared-duplicates/package.json b/test/extensions/fixtures/shared-duplicates/package.json similarity index 100% rename from test-tap/fixture/invalid-extensions/shared-duplicates/package.json rename to test/extensions/fixtures/shared-duplicates/package.json diff --git a/test-tap/fixture/invalid-extensions/top-level-duplicates/package.json b/test/extensions/fixtures/top-level-duplicates/package.json similarity index 100% rename from test-tap/fixture/invalid-extensions/top-level-duplicates/package.json rename to test/extensions/fixtures/top-level-duplicates/package.json diff --git a/test-tap/fixture/invalid-extensions/top-level/package.json b/test/extensions/fixtures/top-level/package.json similarity index 100% rename from test-tap/fixture/invalid-extensions/top-level/package.json rename to test/extensions/fixtures/top-level/package.json diff --git a/test/extensions/snapshots/test.js.md b/test/extensions/snapshots/test.js.md new file mode 100644 index 000000000..693d6a568 --- /dev/null +++ b/test/extensions/snapshots/test.js.md @@ -0,0 +1,17 @@ +# Snapshot report for `test/extensions/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## errors if top-level and babel extensions include duplicates + +> fails with message + + 'Unexpected duplicate extensions in options: ’jsx’.' + +## errors if top-level extensions include duplicates + +> fails with message + + 'Unexpected duplicate extensions in options: ’js’, ’jsx’.' diff --git a/test/extensions/snapshots/test.js.snap b/test/extensions/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..58e5b89be2c662344d22c7b5303c308b5c118ce2 GIT binary patch literal 178 zcmV;j08RfvRzVcNRGxPI`6*BV_@(W5pOe=*) g4KuTffrJi(RRJXRP)su;*)*^j0N1;n4$J@m057LTi~s-t literal 0 HcmV?d00001 diff --git a/test/extensions/test.js b/test/extensions/test.js new file mode 100644 index 000000000..1a908d98e --- /dev/null +++ b/test/extensions/test.js @@ -0,0 +1,17 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +for (const [where, which] of [ + ['top-level', 'top-level-duplicates'], + ['top-level and babel', 'shared-duplicates'] +]) { + test(`errors if ${where} extensions include duplicates`, async t => { + const options = { + cwd: exec.cwd(which) + }; + + const result = await t.throwsAsync(exec.fixture([], options)); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); + }); +} diff --git a/test-tap/fixture/invalid-globs/files/package.json b/test/globs/fixtures/files/package.json similarity index 100% rename from test-tap/fixture/invalid-globs/files/package.json rename to test/globs/fixtures/files/package.json diff --git a/test-tap/fixture/invalid-globs/ignored-by-watcher/package.json b/test/globs/fixtures/ignored-by-watcher/package.json similarity index 100% rename from test-tap/fixture/invalid-globs/ignored-by-watcher/package.json rename to test/globs/fixtures/ignored-by-watcher/package.json diff --git a/test/globs/snapshots/test.js.md b/test/globs/snapshots/test.js.md new file mode 100644 index 000000000..33110a7fa --- /dev/null +++ b/test/globs/snapshots/test.js.md @@ -0,0 +1,17 @@ +# Snapshot report for `test/globs/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## errors if top-level files is an empty array + +> fails with message + + 'The ’files’ configuration must be an array containing glob patterns.' + +## errors if top-level ignoredByWatcher is an empty array + +> fails with message + + 'The ’ignoredByWatcher’ configuration must be an array containing glob patterns.' diff --git a/test/globs/snapshots/test.js.snap b/test/globs/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..9b11766cc2e4fd343011f0ced7dd11e1676690fb GIT binary patch literal 208 zcmV;>05AVRRzVYpRiuF)T4ThSUnVy$ll$zpH8J<{@oRL~Yi3I@c KWB&p10001Qqf%o4 literal 0 HcmV?d00001 diff --git a/test/globs/test.js b/test/globs/test.js new file mode 100644 index 000000000..229f97e5b --- /dev/null +++ b/test/globs/test.js @@ -0,0 +1,22 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('errors if top-level files is an empty array', async t => { + const options = { + cwd: exec.cwd('files') + }; + + const result = await t.throwsAsync(exec.fixture([], options)); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); + +test('errors if top-level ignoredByWatcher is an empty array', async t => { + const options = { + cwd: exec.cwd('ignored-by-watcher') + }; + + const result = await t.throwsAsync(exec.fixture([], options)); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); diff --git a/test/helpers/exec.js b/test/helpers/exec.js index cc85c1761..4834a0fb5 100644 --- a/test/helpers/exec.js +++ b/test/helpers/exec.js @@ -4,13 +4,15 @@ const v8 = require('v8'); const test = require('@ava/test'); const execa = require('execa'); const defaultsDeep = require('lodash/defaultsDeep'); +const replaceString = require('replace-string'); const cliPath = path.resolve(__dirname, '../../cli.js'); const ttySimulator = path.join(__dirname, './simulate-tty.js'); const serialization = process.versions.node >= '12.16.0' ? 'advanced' : 'json'; -const normalizePath = (root, file) => path.posix.normalize(path.relative(root, file)); +const normalizePosixPath = string => replaceString(string, '\\', '/'); +const normalizePath = (root, file) => normalizePosixPath(path.posix.normalize(path.relative(root, file))); const compareStatObjects = (a, b) => { if (a.file < b.file) { @@ -28,8 +30,11 @@ const compareStatObjects = (a, b) => { return 1; }; +exports.cwd = (...paths) => path.join(path.dirname(test.meta.file), 'fixtures', ...paths); +exports.cleanOutput = string => string.replace(/^\W+/, '').replace(/\W+\n+$/g, '').trim(); + exports.fixture = async (args, options = {}) => { - const cwd = path.join(path.dirname(test.meta.file), 'fixtures'); + const cwd = options.cwd || exports.cwd(); const running = execa.node(cliPath, args, defaultsDeep({ env: { AVA_EMIT_RUN_STATUS_OVER_IPC: 'I\'ll find a payphone baby / Take some time to talk to you' @@ -51,6 +56,7 @@ exports.fixture = async (args, options = {}) => { failedHooks: [], passed: [], skipped: [], + todo: [], uncaughtExceptions: [], unsavedSnapshots: [], getError(statObject) { @@ -78,6 +84,11 @@ exports.fixture = async (args, options = {}) => { stats.skipped.push({title, file: normalizePath(cwd, testFile)}); } + if (statusEvent.todo) { + const {title, testFile} = statusEvent; + stats.todo.push({title, file: normalizePath(cwd, testFile)}); + } + break; } @@ -124,6 +135,7 @@ exports.fixture = async (args, options = {}) => { stats.failedHooks.sort(compareStatObjects); stats.passed.sort(compareStatObjects); stats.skipped.sort(compareStatObjects); + stats.todo.sort(compareStatObjects); stats.unsavedSnapshots.sort(compareStatObjects); } }; diff --git a/test-tap/fixture/line-numbers.js b/test/line-numbers/fixtures/line-numbers.js similarity index 60% rename from test-tap/fixture/line-numbers.js rename to test/line-numbers/fixtures/line-numbers.js index a1a2a58d1..cc165dec7 100644 --- a/test-tap/fixture/line-numbers.js +++ b/test/line-numbers/fixtures/line-numbers.js @@ -1,4 +1,4 @@ -const test = require('../..'); +const test = require('ava'); test('unicorn', t => { t.pass(); @@ -14,11 +14,11 @@ test.serial('cat', t => { test.todo('dog'); -/* eslint-disable max-statements-per-line */ +/* eslint-disable max-statements-per-line, ava/no-inline-assertions */ test('sun', t => t.pass()); test('moon', t => { t.pass(); }); -/* eslint-enable max-statements-per-line */ +/* eslint-enable max-statements-per-line, ava/no-inline-assertions */ (() => { test('nested call', t => { diff --git a/test/line-numbers/fixtures/package.json b/test/line-numbers/fixtures/package.json new file mode 100644 index 000000000..a0befd106 --- /dev/null +++ b/test/line-numbers/fixtures/package.json @@ -0,0 +1,7 @@ +{ + "ava": { + "files": [ + "*.js" + ] + } +} diff --git a/test/line-numbers/snapshots/test.js.md b/test/line-numbers/snapshots/test.js.md new file mode 100644 index 000000000..eff67de3a --- /dev/null +++ b/test/line-numbers/snapshots/test.js.md @@ -0,0 +1,126 @@ +# Snapshot report for `test/line-numbers/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## nested call is selected + +> no todo tests are selected + + [] + +> selected tests pass + + [ + { + file: 'line-numbers.js', + title: 'nested call', + }, + ] + +## no test selected by line number + +> fails with message + + 'Line numbers for line-numbers.js did not match any tests' + +## parent call is not selected + +> fails with message + + 'Line numbers for line-numbers.js did not match any tests' + +## select only one of two tests declared on same line + +> no todo tests are selected + + [] + +> selected tests pass + + [ + { + file: 'line-numbers.js', + title: 'moon', + }, + ] + +## select serial test by line number + +> no todo tests are selected + + [] + +> selected tests pass + + [ + { + file: 'line-numbers.js', + title: 'cat', + }, + ] + +## select test by line number + +> no todo tests are selected + + [] + +> selected tests pass + + [ + { + file: 'line-numbers.js', + title: 'unicorn', + }, + ] + +## select tests by line number range + +> no todo tests are selected + + [] + +> selected tests pass + + [ + { + file: 'line-numbers.js', + title: 'rainbow', + }, + { + file: 'line-numbers.js', + title: 'unicorn', + }, + ] + +## select todo test by line number + +> selected todo test passes + + [ + { + file: 'line-numbers.js', + title: 'dog', + }, + ] + +## select two tests declared on same line + +> no todo tests are selected + + [] + +> selected tests pass + + [ + { + file: 'line-numbers.js', + title: 'moon', + }, + { + file: 'line-numbers.js', + title: 'sun', + }, + ] diff --git a/test/line-numbers/snapshots/test.js.snap b/test/line-numbers/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..4ed4624c95adaec351c6db3ef4fee90c59ec6eb6 GIT binary patch literal 582 zcmV-M0=fM`RzVqf00000000A1 zU}Rw6WT=pMq!rLn8-C*Kq1~|+*+NVVAfODzML;ztOiom|yeT+;Y4L^C^2>`ZFo8v< zLa{$k! zF)-Ybl#;&S<@VHE=<4*|2&O%ZV9{D2_FF!E*RrsEp=|fB-dSw;SDz6qdKieiF3#-f z*>|k&jF@Vgl7Gz%Ca~x;C|<(Oz`)GF4h{=O4hCUHHbF*K$D*RdN=8N)i=Uq#p@fmy z07#nwu>%m}QqRE1#lXnKz{t(W=nc^bWR-zvMz9$Rfz0JVd>Lj2n}1SPYH|r96Pzg^ zAOKeS1E}O55Nk1_DP=}g$_uuTAE<^&gprwnkyVh9B`q^26~^Ju$;?aD%`44KN-ZkZ z%PK}w%UY6If>6v}l$e>9lwVG5V@vZglkDVQd4BrgR{k3&b-C z1Tj@T$ef&5GHgA^otIi%lA5BBoS2g{Y(2@6o1dRIG@Z_zlAk`f%d)RPCBK1Kot|YG zI7X=*)WxNUM8e7-$Y|jM)U5#3t&o;qq=06eLP} { + const result = await exec.fixture(['line-numbers.js', 'line-numbers.js:3']); + + t.snapshot(result.stats.todo, 'no todo tests are selected'); + t.snapshot(result.stats.passed, 'selected tests pass'); +}); + +test('select serial test by line number', async t => { + const result = await exec.fixture(['line-numbers.js:11']); + + t.snapshot(result.stats.todo, 'no todo tests are selected'); + t.snapshot(result.stats.passed, 'selected tests pass'); +}); + +test('select todo test by line number', async t => { + const result = await exec.fixture(['line-numbers.js:15']); + + t.snapshot(result.stats.todo, 'selected todo test passes'); +}); + +test('select tests by line number range', async t => { + const result = await exec.fixture(['line-numbers.js:5-7']); + + t.snapshot(result.stats.todo, 'no todo tests are selected'); + t.snapshot(result.stats.passed, 'selected tests pass'); +}); + +test('select two tests declared on same line', async t => { + const result = await exec.fixture(['line-numbers.js:18']); + + t.snapshot(result.stats.todo, 'no todo tests are selected'); + t.snapshot(result.stats.passed, 'selected tests pass'); +}); + +test('select only one of two tests declared on same line', async t => { + const result = await exec.fixture(['line-numbers.js:19']); + + t.snapshot(result.stats.todo, 'no todo tests are selected'); + t.snapshot(result.stats.passed, 'selected tests pass'); +}); + +test('no test selected by line number', async t => { + const result = await t.throwsAsync(exec.fixture(['line-numbers.js:6'])); + + t.snapshot(exec.cleanOutput(result.stdout), 'fails with message'); +}); + +test('parent call is not selected', async t => { + const result = await t.throwsAsync(exec.fixture(['line-numbers.js:23'])); + + t.snapshot(exec.cleanOutput(result.stdout), 'fails with message'); +}); + +test('nested call is selected', async t => { + const result = await exec.fixture(['line-numbers.js:24']); + + t.snapshot(result.stats.todo, 'no todo tests are selected'); + t.snapshot(result.stats.passed, 'selected tests pass'); +}); diff --git a/test-tap/fixture/node-arguments/test.js b/test/node-arguments/fixtures/node-arguments-from-config/node-arguments-from-config.js similarity index 84% rename from test-tap/fixture/node-arguments/test.js rename to test/node-arguments/fixtures/node-arguments-from-config/node-arguments-from-config.js index 3ec80ebb8..61a4c5feb 100644 --- a/test-tap/fixture/node-arguments/test.js +++ b/test/node-arguments/fixtures/node-arguments-from-config/node-arguments-from-config.js @@ -1,4 +1,4 @@ -const test = require('../../..'); +const test = require('ava'); test('works', t => { t.plan(2); diff --git a/test-tap/fixture/node-arguments/package.json b/test/node-arguments/fixtures/node-arguments-from-config/package.json similarity index 72% rename from test-tap/fixture/node-arguments/package.json rename to test/node-arguments/fixtures/node-arguments-from-config/package.json index eef55b831..83d37be0f 100644 --- a/test-tap/fixture/node-arguments/package.json +++ b/test/node-arguments/fixtures/node-arguments-from-config/package.json @@ -1,5 +1,8 @@ { "ava": { + "files": [ + "*.js" + ], "nodeArguments": [ "--require", "./setup.js" diff --git a/test-tap/fixture/node-arguments/setup.js b/test/node-arguments/fixtures/node-arguments-from-config/setup.js similarity index 100% rename from test-tap/fixture/node-arguments/setup.js rename to test/node-arguments/fixtures/node-arguments-from-config/setup.js diff --git a/test-tap/fixture/node-arguments.js b/test/node-arguments/fixtures/node-arguments/node-arguments.js similarity index 87% rename from test-tap/fixture/node-arguments.js rename to test/node-arguments/fixtures/node-arguments/node-arguments.js index 781743abf..765f9531c 100644 --- a/test-tap/fixture/node-arguments.js +++ b/test/node-arguments/fixtures/node-arguments/node-arguments.js @@ -1,4 +1,4 @@ -const test = require('../..'); +const test = require('ava'); test('exec arguments includes --throw-deprecation and --zero-fill-buffers', t => { t.plan(2); diff --git a/test/node-arguments/fixtures/node-arguments/package.json b/test/node-arguments/fixtures/node-arguments/package.json new file mode 100644 index 000000000..a0befd106 --- /dev/null +++ b/test/node-arguments/fixtures/node-arguments/package.json @@ -0,0 +1,7 @@ +{ + "ava": { + "files": [ + "*.js" + ] + } +} diff --git a/test/node-arguments/snapshots/test.js.md b/test/node-arguments/snapshots/test.js.md new file mode 100644 index 000000000..b44239fd0 --- /dev/null +++ b/test/node-arguments/snapshots/test.js.md @@ -0,0 +1,33 @@ +# Snapshot report for `test/node-arguments/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## detects incomplete --node-arguments + +> fails with message + + 'Could not parse `--node-arguments` value. Make sure all strings are closed and backslashes are used correctly.' + +## passed node arguments to workers + +> tests pass + + [ + { + file: 'node-arguments.js', + title: 'exec arguments includes --throw-deprecation and --zero-fill-buffers', + }, + ] + +## reads node arguments from config + +> tests pass + + [ + { + file: 'node-arguments-from-config.js', + title: 'works', + }, + ] diff --git a/test/node-arguments/snapshots/test.js.snap b/test/node-arguments/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..1e47c193a702c24bb4054d2b35ee4e10c1e867ef GIT binary patch literal 418 zcmV;T0bTw~7R8O)wtxnyLLlWKv>%HI00000000B6 zQ9VloK@i=!crhq)ISgW>Y_FTbRt3F)o!Dq$m(AT?a>-^l?A{p@()bgsgPkBY_VEM3 z!q)#Ff~{C8h?__vv9ZvFVZPp**~jc6gi>g+!*7kPY*S8aSy2fI(_rz-foZT zm(A9-Z+qSOrQTyN1B0q(_2*3v_+TR!L_sDzz(U5jL6v5> zNQjUDBUF`>Iuo%j;seSPmdD$)#;{Hl!<2KZV-<*48VaSyJ M1SK}&&XxiI0Pi)$v;Y7A literal 0 HcmV?d00001 diff --git a/test/node-arguments/test.js b/test/node-arguments/test.js new file mode 100644 index 000000000..bbf928366 --- /dev/null +++ b/test/node-arguments/test.js @@ -0,0 +1,32 @@ +const test = require('@ava/test'); +const exec = require('../helpers/exec'); + +test('passed node arguments to workers', async t => { + const options = { + cwd: exec.cwd('node-arguments') + }; + + const result = await exec.fixture(['--node-arguments="--throw-deprecation --zero-fill-buffers"', 'node-arguments.js'], options); + + t.snapshot(result.stats.passed, 'tests pass'); +}); + +test('detects incomplete --node-arguments', async t => { + const options = { + cwd: exec.cwd('node-arguments') + }; + + const result = await t.throwsAsync(exec.fixture(['--node-arguments="--foo=\'bar"', 'node-arguments.js'], options)); + + t.snapshot(exec.cleanOutput(result.stderr), 'fails with message'); +}); + +test('reads node arguments from config', async t => { + const options = { + cwd: exec.cwd('node-arguments-from-config') + }; + + const result = await exec.fixture(['node-arguments-from-config.js'], options); + + t.snapshot(result.stats.passed, 'tests pass'); +}); diff --git a/test/snapshot-updates/snapshots/test.js.snap b/test/snapshot-updates/snapshots/test.js.snap index 1891e9e1f527fc6fa10adb5dab9ae40a1e60811d..fd04d3f956cd3d8b10f2bd5f51ba46fb61780c7a 100644 GIT binary patch delta 268 zcmV+n0rURG1H}VcK~_N^Q*L2!b7*gLAa*he0syvncWu&U54a?NdgkdOO4}cc2mk;8 z00003>tkSGU}0Flto3@=;wu(i?;2Ojhn1)?GJrrV5JwAe2HVFysgT?-3VEfuNvTD8 zD27`SG(0!4Bsl}qY=kkB1OYZ0{$ON+GX(?$7#MjO7?~It`GIPfL>QTY&K8qY0WL&+ z1@-?B^$rh6Q2{WnK#@YJADEJXbS7ctkSGU}1;y1L;h{?q?*){Rmg#bj% { t.snapshot(result.stats.unsavedSnapshots, 'files where snapshots could not be updated'); }); -const stripLeadingFigures = string => string.replace(/^\W+/, ''); - test('cannot update snapshots when matching test titles', async t => { const result = await t.throwsAsync(exec.fixture(['contains-skip.js', '-u', '-m=snapshot'])); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); test('cannot update snapshots when selecting tests by line number', async t => { const result = await t.throwsAsync(exec.fixture(['contains-skip.js:4', '-u'])); - t.snapshot(stripLeadingFigures(result.stderr.trim())); + t.snapshot(exec.cleanOutput(result.stderr)); }); diff --git a/xo.config.js b/xo.config.js index bb009d6c6..44f42e795 100644 --- a/xo.config.js +++ b/xo.config.js @@ -1,6 +1,7 @@ module.exports = { ignores: [ 'media/**', + 'test/config/fixtures/config-errors/test.js', 'test-tap/fixture/ava-paths/target/test.js', 'test-tap/fixture/{source-map-initial,syntax-error}.js', 'test-tap/fixture/snapshots/test-sourcemaps/build/**', From 13469c8db97a30da1afa00f353af0415bc4cd215 Mon Sep 17 00:00:00 2001 From: John Simoni Date: Wed, 9 Sep 2020 00:29:06 -0700 Subject: [PATCH 13/14] Experimentally disable null expectations for throws assertions --- docs/03-assertions.md | 4 ++-- lib/assert.js | 14 +++++++++++--- lib/load-config.js | 2 +- test-tap/assert.js | 34 ++++++++++++++++++++++++++++++++-- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/docs/03-assertions.md b/docs/03-assertions.md index 40e1777c8..4ed650dc1 100644 --- a/docs/03-assertions.md +++ b/docs/03-assertions.md @@ -244,7 +244,7 @@ Assert that an error is thrown. `fn` must be a function which should throw. The * `name`: the expected `.name` value of the thrown error * `code`: the expected `.code` value of the thrown error -`expectation` does not need to be specified. If you don't need it but do want to set an assertion message you have to specify `null`. +`expectation` does not need to be specified. If you don't need it but do want to set an assertion message you have to specify `undefined`. (AVA 3 also allows you to specify `null`. This will be removed in AVA 4. You can opt into this change early by enabling the `disableNullExpectations` experiment.) Example: @@ -276,7 +276,7 @@ The thrown value *must* be an error. It is returned so you can run more assertio * `name`: the expected `.name` value of the thrown error * `code`: the expected `.code` value of the thrown error -`expectation` does not need to be specified. If you don't need it but do want to set an assertion message you have to specify `null`. +`expectation` does not need to be specified. If you don't need it but do want to set an assertion message you have to specify `undefined`. (AVA 3 also allows you to specify `null`. This will be removed in AVA 4. You can opt into this change early by enabling the `disableNullExpectations` experiment.) Example: diff --git a/lib/assert.js b/lib/assert.js index 2cb2ac340..b28343f30 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -87,8 +87,16 @@ function getErrorWithLongStackTrace() { return err; } -function validateExpectations(assertion, expectations, numberArgs) { // eslint-disable-line complexity +function validateExpectations(assertion, expectations, numberArgs, experiments) { // eslint-disable-line complexity if (numberArgs === 1 || expectations === null || expectations === undefined) { + if (experiments.disableNullExpectations && expectations === null) { + throw new AssertionError({ + assertion, + message: `The second argument to \`t.${assertion}()\` must be an expectation object or \`undefined\``, + values: [formatWithLabel('Called with:', expectations)] + }); + } + expectations = {}; } else if ( typeof expectations === 'function' || @@ -474,7 +482,7 @@ class Assertions { } try { - expectations = validateExpectations('throws', expectations, args.length); + expectations = validateExpectations('throws', expectations, args.length, experiments); } catch (error) { fail(error); return; @@ -540,7 +548,7 @@ class Assertions { } try { - expectations = validateExpectations('throwsAsync', expectations, args.length); + expectations = validateExpectations('throwsAsync', expectations, args.length, experiments); } catch (error) { fail(error); return Promise.resolve(); diff --git a/lib/load-config.js b/lib/load-config.js index 7d349344a..ff6029737 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -7,7 +7,7 @@ const pkgConf = require('pkg-conf'); const NO_SUCH_FILE = Symbol('no ava.config.js file'); const MISSING_DEFAULT_EXPORT = Symbol('missing default export'); -const EXPERIMENTS = new Set(['configurableModuleFormat', 'disableSnapshotsInHooks', 'reverseTeardowns']); +const EXPERIMENTS = new Set(['configurableModuleFormat', 'disableNullExpectations', 'disableSnapshotsInHooks', 'reverseTeardowns']); // *Very* rudimentary support for loading ava.config.js files containing an `export default` statement. const evaluateJsConfig = configFile => { diff --git a/test-tap/assert.js b/test-tap/assert.js index 3d8fbc9f4..b055cd6e0 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -13,7 +13,7 @@ const HelloMessage = require('./fixture/hello-message'); let lastFailure = null; -const assertions = new class extends assert.Assertions { +const AssertionsBase = class extends assert.Assertions { constructor(overwrites = {}) { super({ pass: () => true, @@ -35,7 +35,9 @@ const assertions = new class extends assert.Assertions { ...overwrites }); } -}(); +}; + +const assertions = new AssertionsBase(); function assertFailure(t, subset) { if (!lastFailure) { @@ -1471,6 +1473,34 @@ test('.throwsAsync() fails if passed a bad expectation', t => { t.end(); }); +test('.throws() fails if passed null expectation with disableNullExpectations', t => { + const asserter = new AssertionsBase({experiments: {disableNullExpectations: true}}); + + failsWith(t, () => { + asserter.throws(() => {}, null); + }, { + assertion: 'throws', + message: 'The second argument to `t.throws()` must be an expectation object or `undefined`', + values: [{label: 'Called with:', formatted: /null/}] + }); + + t.end(); +}); + +test('.throwsAsync() fails if passed null expectation with disableNullExpectations', t => { + const asserter = new AssertionsBase({experiments: {disableNullExpectations: true}}); + + failsWith(t, () => { + asserter.throwsAsync(() => {}, null); + }, { + assertion: 'throwsAsync', + message: 'The second argument to `t.throwsAsync()` must be an expectation object or `undefined`', + values: [{label: 'Called with:', formatted: /null/}] + }); + + t.end(); +}); + test('.notThrows()', gather(t => { // Passes because the function doesn't throw passes(t, () => { From 7acbfce7afb1b012641a208c56b2c73e54cc2700 Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Sat, 19 Sep 2020 23:03:25 +0530 Subject: [PATCH 14/14] Assertions return boolean --- lib/assert.js | 160 +++++++++++++++++++++++++++---------------- test-tap/assert.js | 164 +++++++++++++++++++++++++++++---------------- 2 files changed, 206 insertions(+), 118 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index b28343f30..8f2145f70 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -286,6 +286,7 @@ class Assertions { }, onSuccess: () => { pass(); + return true; }, bindReceiver: false, patterns: [pattern] @@ -328,7 +329,8 @@ class Assertions { } if (Object.is(actual, expected)) { - return pass(); + pass(); + return true; } const result = concordance.compare(actual, expected, concordanceOptions); @@ -336,20 +338,22 @@ class Assertions { const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); if (result.pass) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'is', message, raw: {actual, expected}, values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] })); + } else { + fail(new AssertionError({ + assertion: 'is', + message, + raw: {actual, expected}, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); } - return fail(new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); + return false; }); this.not = withSkip((actual, expected, message) => { @@ -358,15 +362,17 @@ class Assertions { } if (Object.is(actual, expected)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'not', message, raw: {actual, expected}, values: [formatWithLabel('Value is the same as:', actual)] })); + return false; } - return pass(); + pass(); + return true; }); this.deepEqual = withSkip((actual, expected, message) => { @@ -376,18 +382,20 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { - return pass(); + pass(); + return true; } const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); - - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'deepEqual', message, raw: {actual, expected}, values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] })); + + return false; }); this.notDeepEqual = withSkip((actual, expected, message) => { @@ -398,37 +406,32 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notDeepEqual', message, raw: {actual, expected}, values: [formatDescriptorWithLabel('Value is deeply equal:', actualDescriptor)] })); + return false; } - return pass(); + pass(); + return true; }); this.like = withSkip((actual, selector, message) => { - if (!experiments.likeAssertion) { - return fail(new AssertionError({ - assertion: 'like', - improperUsage: true, - message: 'You must enable the `likeAssertion` experiment in order to use `t.like()`' - })); - } - if (!checkMessage('like', message)) { return; } if (!isLikeSelector(selector)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must be a non-empty object', values: [formatWithLabel('Called with:', selector)] })); + return false; } let comparable; @@ -436,12 +439,13 @@ class Assertions { comparable = selectComparable(actual, selector); } catch (error) { if (error === CIRCULAR_SELECTOR) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must not contain circular references', values: [formatWithLabel('Called with:', selector)] })); + return false; } throw error; @@ -449,16 +453,19 @@ class Assertions { const result = concordance.compare(comparable, selector, concordanceOptions); if (result.pass) { - return pass(); + pass(); + return true; } const actualDescriptor = result.actual || concordance.describe(comparable, concordanceOptions); const expectedDescriptor = result.expected || concordance.describe(selector, concordanceOptions); - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'like', message, values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] })); + + return false; }); this.throws = withSkip((...args) => { @@ -628,7 +635,7 @@ class Assertions { message: '`t.notThrows()` must be called with a function', values: [formatWithLabel('Called with:', fn)] })); - return; + return false; } try { @@ -640,10 +647,11 @@ class Assertions { actualStack: error.stack, values: [formatWithLabel('Function threw:', error)] })); - return; + return false; } pass(); + return true; }); this.notThrowsAsync = withSkip((nonThrower, message) => { @@ -714,7 +722,7 @@ class Assertions { message: '`t.snapshot()` can only be used in tests', improperUsage: true })); - return; + return false; } let message; @@ -752,30 +760,43 @@ class Assertions { improperUsage.expectedVersion = error.expectedVersion; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'snapshot', message: message || 'Could not compare snapshot', improperUsage })); + return false; } if (result.pass) { - return pass(); + pass(); + return true; } if (result.actual) { - return fail(new AssertionError({ - assertion: 'snapshot', - message: message || 'Did not match snapshot', - values: [formatDescriptorDiff(result.actual, result.expected, {invert: true})] - })); + fail( + new AssertionError({ + assertion: 'snapshot', + message: message || 'Did not match snapshot', + values: [ + formatDescriptorDiff(result.actual, result.expected, { + invert: true + }) + ] + }) + ); + return false; } // This can only occur in CI environments. - return fail(new AssertionError({ - assertion: 'snapshot', - message: message || 'No snapshot available — new snapshots are not created in CI environments' - })); + fail( + new AssertionError({ + assertion: 'snapshot', + message: message || 'No snapshot available — new snapshots are not created in CI environments' + }) + ); + + return false; }); this.truthy = withSkip((actual, message) => { @@ -784,15 +805,18 @@ class Assertions { } if (actual) { - return pass(); + pass(); + return true; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'truthy', message, operator: '!!', values: [formatWithLabel('Value is not truthy:', actual)] })); + + return false; }); this.falsy = withSkip((actual, message) => { @@ -801,15 +825,17 @@ class Assertions { } if (actual) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'falsy', message, operator: '!', values: [formatWithLabel('Value is not falsy:', actual)] })); + return false; } - return pass(); + pass(); + return true; }); this.true = withSkip((actual, message) => { @@ -818,14 +844,17 @@ class Assertions { } if (actual === true) { - return pass(); + pass(); + return true; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'true', message, values: [formatWithLabel('Value is not `true`:', actual)] })); + + return false; }); this.false = withSkip((actual, message) => { @@ -834,14 +863,17 @@ class Assertions { } if (actual === false) { - return pass(); + pass(); + return true; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'false', message, values: [formatWithLabel('Value is not `false`:', actual)] })); + + return false; }); this.regex = withSkip((string, regex, message) => { @@ -850,25 +882,27 @@ class Assertions { } if (typeof string !== 'string') { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); + return false; } if (!(regex instanceof RegExp)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); + return false; } if (!regex.test(string)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'regex', message, values: [ @@ -876,9 +910,11 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); + return false; } - return pass(); + pass(); + return true; }); this.notRegex = withSkip((string, regex, message) => { @@ -887,25 +923,27 @@ class Assertions { } if (typeof string !== 'string') { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); + return false; } if (!(regex instanceof RegExp)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); + return false; } if (regex.test(string)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notRegex', message, values: [ @@ -913,9 +951,11 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); + return false; } - return pass(); + pass(); + return true; }); if (powerAssert === undefined) { @@ -925,15 +965,17 @@ class Assertions { } if (!actual) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'assert', message, operator: '!!', values: [formatWithLabel('Value is not truthy:', actual)] })); + return false; } - return pass(); + pass(); + return true; }); } else { this.assert = withSkip(withPowerAssert( diff --git a/test-tap/assert.js b/test-tap/assert.js index b055cd6e0..13232e5d9 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -12,26 +12,26 @@ const snapshotManager = require('../lib/snapshot-manager'); const HelloMessage = require('./fixture/hello-message'); let lastFailure = null; +let lastPassed = false; const AssertionsBase = class extends assert.Assertions { constructor(overwrites = {}) { super({ - pass: () => true, + pass: () => { + lastPassed = true; + }, pending: promise => { - return promise.then(() => - true - , error => { + promise.then(() => { + lastPassed = true; + }, error => { lastFailure = error; }); }, fail: error => { lastFailure = error; - return false; - }, - skip: () => {}, - experiments: { - likeAssertion: true }, + skip: () => { }, + experiments: {}, ...overwrites }); } @@ -144,8 +144,10 @@ function eventuallyFails(t, fn) { */ function passes(t, fn) { + lastPassed = false; lastFailure = null; - if (fn()) { + fn(); + if (lastPassed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -154,9 +156,10 @@ function passes(t, fn) { function eventuallyPasses(t, fn) { return add(() => { + lastPassed = false; lastFailure = null; - return fn().then(passed => { - if (passed) { + return fn().then(() => { + if (lastPassed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -167,27 +170,30 @@ function eventuallyPasses(t, fn) { test('.pass()', t => { passes(t, () => { - return assertions.pass(); + const result = assertions.pass(); + assertions.true(result); }); passes(t, () => { const {pass} = assertions; - return pass(); + const result = pass(); + assertions.true(result); }); t.end(); }); test('.fail()', t => { + const results = []; failsWith(t, () => { - return assertions.fail(); + results.push(assertions.fail()); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - return assertions.fail('my message'); + results.push(assertions.fail('my message')); }, { assertion: 'fail', message: 'my message' @@ -195,14 +201,14 @@ test('.fail()', t => { failsWith(t, () => { const {fail} = assertions; - return fail(); + results.push(fail()); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - return assertions.fail(null); + assertions.fail(null); }, { assertion: 'fail', improperUsage: true, @@ -212,125 +218,156 @@ test('.fail()', t => { formatted: /null/ }] }); + for (const result of results) { + t.is(result, false); + } t.end(); }); test('.is()', t => { passes(t, () => { - return assertions.is('foo', 'foo'); + const result = assertions.is('foo', 'foo'); + assertions.true(result); }); passes(t, () => { const {is} = assertions; - return is('foo', 'foo'); + const result = is('foo', 'foo'); + assertions.true(result); }); passes(t, () => { - return assertions.is('', ''); + const result = assertions.is('', ''); + assertions.true(result); }); passes(t, () => { - return assertions.is(true, true); + const result = assertions.is(true, true); + assertions.true(result); }); passes(t, () => { - return assertions.is(false, false); + const result = assertions.is(false, false); + assertions.true(result); }); passes(t, () => { - return assertions.is(null, null); + const result = assertions.is(null, null); + assertions.true(result); }); passes(t, () => { - return assertions.is(undefined, undefined); + const result = assertions.is(undefined, undefined); + assertions.true(result); }); passes(t, () => { - return assertions.is(1, 1); + const result = assertions.is(1, 1); + assertions.true(result); }); passes(t, () => { - return assertions.is(0, 0); + const result = assertions.is(0, 0); + assertions.true(result); }); passes(t, () => { - return assertions.is(-0, -0); + const result = assertions.is(-0, -0); + assertions.true(result); }); passes(t, () => { - return assertions.is(Number.NaN, Number.NaN); + const result = assertions.is(Number.NaN, Number.NaN); + assertions.true(result); }); passes(t, () => { - return assertions.is(0 / 0, Number.NaN); + const result = assertions.is(0 / 0, Number.NaN); + assertions.true(result); }); passes(t, () => { const someRef = {foo: 'bar'}; - return assertions.is(someRef, someRef); + const result = assertions.is(someRef, someRef); + assertions.true(result); }); fails(t, () => { - return assertions.is(0, -0); + const result = assertions.is(0, -0); + assertions.false(result); }); fails(t, () => { - return assertions.is(0, false); + const result = assertions.is(0, false); + assertions.false(result); }); fails(t, () => { - return assertions.is('', false); + const result = assertions.is('', false); + assertions.false(result); }); fails(t, () => { - return assertions.is('0', 0); + const result = assertions.is('0', 0); + assertions.false(result); }); fails(t, () => { - assertions.is('17', 17); + const result = assertions.is('17', 17); + assertions.false(result); }); fails(t, () => { - assertions.is([1, 2], '1,2'); + const result = assertions.is([1, 2], '1,2'); + assertions.false(result); }); fails(t, () => { // eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins - assertions.is(new String('foo'), 'foo'); + const result = assertions.is(new String('foo'), 'foo'); + assertions.false(result); }); fails(t, () => { - assertions.is(null, undefined); + const result = assertions.is(null, undefined); + assertions.false(result); }); fails(t, () => { - assertions.is(null, false); + const result = assertions.is(null, false); + assertions.false(result); }); fails(t, () => { - assertions.is(undefined, false); + const result = assertions.is(undefined, false); + assertions.false(result); }); fails(t, () => { // eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins - assertions.is(new String('foo'), new String('foo')); + const result = assertions.is(new String('foo'), new String('foo')); + assertions.false(result); }); fails(t, () => { - assertions.is(0, null); + const result = assertions.is(0, null); + assertions.false(result); }); fails(t, () => { - assertions.is(0, Number.NaN); + const result = assertions.is(0, Number.NaN); + assertions.false(result); }); fails(t, () => { - assertions.is('foo', Number.NaN); + const result = assertions.is('foo', Number.NaN); + assertions.false(result); }); + const failureResults = []; failsWith(t, () => { - assertions.is({foo: 'bar'}, {foo: 'bar'}); + failureResults.push(assertions.is({foo: 'bar'}, {foo: 'bar'})); }, { assertion: 'is', message: '', @@ -343,7 +380,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is('foo', 'bar'); + failureResults.push(assertions.is('foo', 'bar')); }, { assertion: 'is', message: '', @@ -354,7 +391,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is('foo', 42); + failureResults.push(assertions.is('foo', 42)); }, { actual: 'foo', assertion: 'is', @@ -366,7 +403,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is('foo', 42, 'my message'); + failureResults.push(assertions.is('foo', 42, 'my message')); }, { assertion: 'is', message: 'my message', @@ -376,7 +413,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is(0, -0, 'my message'); + failureResults.push(assertions.is(0, -0, 'my message')); }, { assertion: 'is', message: 'my message', @@ -386,7 +423,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is(-0, 0, 'my message'); + failureResults.push(assertions.is(-0, 0, 'my message')); }, { assertion: 'is', message: 'my message', @@ -396,7 +433,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is(0, 0, null); + failureResults.push(assertions.is(0, 0, null)); }, { assertion: 'is', improperUsage: true, @@ -406,30 +443,36 @@ test('.is()', t => { formatted: /null/ }] }); + for (const result of failureResults) { + t.false(result); + } t.end(); }); test('.not()', t => { passes(t, () => { - assertions.not('foo', 'bar'); + const result = assertions.not('foo', 'bar'); + assertions.true(result); }); passes(t, () => { const {not} = assertions; - not('foo', 'bar'); + const result = not('foo', 'bar'); + assertions.true(result); }); + const failureResults = []; fails(t, () => { - assertions.not(Number.NaN, Number.NaN); + failureResults.push(assertions.not(Number.NaN, Number.NaN)); }); fails(t, () => { - assertions.not(0 / 0, Number.NaN); + failureResults.push(assertions.not(0 / 0, Number.NaN)); }); failsWith(t, () => { - assertions.not('foo', 'foo'); + failureResults.push(assertions.not('foo', 'foo')); }, { assertion: 'not', message: '', @@ -438,7 +481,7 @@ test('.not()', t => { }); failsWith(t, () => { - assertions.not('foo', 'foo', 'my message'); + failureResults.push(assertions.not('foo', 'foo', 'my message')); }, { assertion: 'not', message: 'my message', @@ -446,7 +489,7 @@ test('.not()', t => { }); failsWith(t, () => { - assertions.not(0, 1, null); + failureResults.push(assertions.not(0, 1, null)); }, { assertion: 'not', improperUsage: true, @@ -456,6 +499,9 @@ test('.not()', t => { formatted: /null/ }] }); + for (const result of failureResults) { + t.false(result); + } t.end(); });