Skip to content

Commit

Permalink
Experimentally disable null expectations for throws assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
JSimoni42 committed Sep 9, 2020
1 parent 33172dc commit f328a69
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
4 changes: 2 additions & 2 deletions docs/03-assertions.md
Expand Up @@ -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:

Expand Down Expand Up @@ -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:

Expand Down
14 changes: 11 additions & 3 deletions lib/assert.js
Expand Up @@ -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' ||
Expand Down Expand Up @@ -465,7 +473,7 @@ class Assertions {
}

try {
expectations = validateExpectations('throws', expectations, args.length);
expectations = validateExpectations('throws', expectations, args.length, experiments);
} catch (error) {
fail(error);
return;
Expand Down Expand Up @@ -531,7 +539,7 @@ class Assertions {
}

try {
expectations = validateExpectations('throwsAsync', expectations, args.length);
expectations = validateExpectations('throwsAsync', expectations, args.length, experiments);
} catch (error) {
fail(error);
return Promise.resolve();
Expand Down
2 changes: 1 addition & 1 deletion lib/load-config.js
Expand Up @@ -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 => {
Expand Down
34 changes: 32 additions & 2 deletions test-tap/assert.js
Expand Up @@ -14,7 +14,7 @@ const HelloMessage = require('./fixture/hello-message');
let lastFailure = null;
let lastPassed = false;

const assertions = new class extends assert.Assertions {
const AssertionsBase = class extends assert.Assertions {
constructor(overwrites = {}) {
super({
pass: () => {
Expand All @@ -35,7 +35,9 @@ const assertions = new class extends assert.Assertions {
...overwrites
});
}
}();
};

const assertions = new AssertionsBase();

function assertFailure(t, subset) {
if (!lastFailure) {
Expand Down Expand Up @@ -1474,6 +1476,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, () => {
Expand Down

0 comments on commit f328a69

Please sign in to comment.