Skip to content

Commit f328a69

Browse files
authored
Experimentally disable null expectations for throws assertions
1 parent 33172dc commit f328a69

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

docs/03-assertions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ Assert that an error is thrown. `fn` must be a function which should throw. The
244244
* `name`: the expected `.name` value of the thrown error
245245
* `code`: the expected `.code` value of the thrown error
246246

247-
`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`.
247+
`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.)
248248

249249
Example:
250250

@@ -276,7 +276,7 @@ The thrown value *must* be an error. It is returned so you can run more assertio
276276
* `name`: the expected `.name` value of the thrown error
277277
* `code`: the expected `.code` value of the thrown error
278278

279-
`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`.
279+
`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.)
280280

281281
Example:
282282

lib/assert.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,16 @@ function getErrorWithLongStackTrace() {
8787
return err;
8888
}
8989

90-
function validateExpectations(assertion, expectations, numberArgs) { // eslint-disable-line complexity
90+
function validateExpectations(assertion, expectations, numberArgs, experiments) { // eslint-disable-line complexity
9191
if (numberArgs === 1 || expectations === null || expectations === undefined) {
92+
if (experiments.disableNullExpectations && expectations === null) {
93+
throw new AssertionError({
94+
assertion,
95+
message: `The second argument to \`t.${assertion}()\` must be an expectation object or \`undefined\``,
96+
values: [formatWithLabel('Called with:', expectations)]
97+
});
98+
}
99+
92100
expectations = {};
93101
} else if (
94102
typeof expectations === 'function' ||
@@ -465,7 +473,7 @@ class Assertions {
465473
}
466474

467475
try {
468-
expectations = validateExpectations('throws', expectations, args.length);
476+
expectations = validateExpectations('throws', expectations, args.length, experiments);
469477
} catch (error) {
470478
fail(error);
471479
return;
@@ -531,7 +539,7 @@ class Assertions {
531539
}
532540

533541
try {
534-
expectations = validateExpectations('throwsAsync', expectations, args.length);
542+
expectations = validateExpectations('throwsAsync', expectations, args.length, experiments);
535543
} catch (error) {
536544
fail(error);
537545
return Promise.resolve();

lib/load-config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const pkgConf = require('pkg-conf');
77

88
const NO_SUCH_FILE = Symbol('no ava.config.js file');
99
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
10-
const EXPERIMENTS = new Set(['configurableModuleFormat', 'disableSnapshotsInHooks', 'reverseTeardowns']);
10+
const EXPERIMENTS = new Set(['configurableModuleFormat', 'disableNullExpectations', 'disableSnapshotsInHooks', 'reverseTeardowns']);
1111

1212
// *Very* rudimentary support for loading ava.config.js files containing an `export default` statement.
1313
const evaluateJsConfig = configFile => {

test-tap/assert.js

+32-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const HelloMessage = require('./fixture/hello-message');
1414
let lastFailure = null;
1515
let lastPassed = false;
1616

17-
const assertions = new class extends assert.Assertions {
17+
const AssertionsBase = class extends assert.Assertions {
1818
constructor(overwrites = {}) {
1919
super({
2020
pass: () => {
@@ -35,7 +35,9 @@ const assertions = new class extends assert.Assertions {
3535
...overwrites
3636
});
3737
}
38-
}();
38+
};
39+
40+
const assertions = new AssertionsBase();
3941

4042
function assertFailure(t, subset) {
4143
if (!lastFailure) {
@@ -1474,6 +1476,34 @@ test('.throwsAsync() fails if passed a bad expectation', t => {
14741476
t.end();
14751477
});
14761478

1479+
test('.throws() fails if passed null expectation with disableNullExpectations', t => {
1480+
const asserter = new AssertionsBase({experiments: {disableNullExpectations: true}});
1481+
1482+
failsWith(t, () => {
1483+
asserter.throws(() => {}, null);
1484+
}, {
1485+
assertion: 'throws',
1486+
message: 'The second argument to `t.throws()` must be an expectation object or `undefined`',
1487+
values: [{label: 'Called with:', formatted: /null/}]
1488+
});
1489+
1490+
t.end();
1491+
});
1492+
1493+
test('.throwsAsync() fails if passed null expectation with disableNullExpectations', t => {
1494+
const asserter = new AssertionsBase({experiments: {disableNullExpectations: true}});
1495+
1496+
failsWith(t, () => {
1497+
asserter.throwsAsync(() => {}, null);
1498+
}, {
1499+
assertion: 'throwsAsync',
1500+
message: 'The second argument to `t.throwsAsync()` must be an expectation object or `undefined`',
1501+
values: [{label: 'Called with:', formatted: /null/}]
1502+
});
1503+
1504+
t.end();
1505+
});
1506+
14771507
test('.notThrows()', gather(t => {
14781508
// Passes because the function doesn't throw
14791509
passes(t, () => {

0 commit comments

Comments
 (0)