Skip to content

Commit

Permalink
Only apply power-assert to new t.assert() assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
eemed authored and novemberborn committed Mar 24, 2019
1 parent c1f6fdf commit 9406470
Show file tree
Hide file tree
Showing 23 changed files with 171 additions and 82 deletions.
42 changes: 35 additions & 7 deletions docs/03-assertions.md
Expand Up @@ -84,7 +84,7 @@ test('skip assertion', t => {

## Enhanced assertion messages

AVA comes with [`power-assert`](https://github.com/power-assert-js/power-assert) built-in, giving you more descriptive assertion messages. It reads your test and tries to infer more information from the code.
AVA comes with [`power-assert`](https://github.com/power-assert-js/power-assert) built-in, giving you more descriptive assertion messages.

Let's take this example, using Node's standard [`assert` library](https://nodejs.org/api/assert.html):

Expand All @@ -101,24 +101,48 @@ If you paste that into a Node REPL it'll return:
AssertionError: false == true
```

In AVA however, this test:
With AVA's `assert` assertion however, this test:

```js
test('enhanced assertions', t => {
const a = /foo/;
const b = 'bar';
const c = 'baz';
t.true(a.test(b) || b === c);
t.assert(a.test(b) || b === c);
});
```

Will output:

```
t.true(a.test(b) || b === c)
| | | |
| "bar" "bar" "baz"
false
6: const c = 'baz';
7: t.assert(a.test(b) || b === c);
8: });
Value is not truthy:
false
a.test(b) || b === c
=> false
b === c
=> false
c
=> 'baz'
b
=> 'bar'
a.test(b)
=> false
b
=> 'bar'
a
=> /foo/
```

## Custom assertions
Expand Down Expand Up @@ -147,6 +171,10 @@ Passing assertion.

Failing assertion.

### `.assert(value, [message])`

Asserts that `value` is truthy. This is [`power-assert`](#enhanced-assertion-messages) enabled.

### `.truthy(value, [message])`

Assert that `value` is truthy.
Expand Down
4 changes: 2 additions & 2 deletions docs/06-configuration.md
Expand Up @@ -57,8 +57,8 @@ 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
- `compileEnhancements`: if `false`, disables [power-assert](https://github.com/power-assert-js/power-assert) — which otherwise helps provide more descriptive error messages — and detection of improper use of the `t.throws()` assertion
- `extensions`: extensions of test files that are not precompiled using AVA's Babel presets. Note that files are still compiled to enable power-assert and other features, so you may also need to set `compileEnhancements` to `false` if your files are not valid JavaScript. Setting this overrides the default `"js"` value, so make sure to include that extension in the list, as long as it's not included in `babel.extensions`
- `compileEnhancements`: if `false`, disables [`power-assert`](./03-assertions.md#enhanced-assertion-messages) — which otherwise helps provide more descriptive error messages — and detection of improper use of the `t.throws()` assertion
- `extensions`: extensions of test files that are not precompiled using AVA's Babel presets. Note that files are still compiled to enable `power-assert` and other features, so you may also need to set `compileEnhancements` to `false` if your files are not valid JavaScript. Setting this overrides the default `"js"` value, so make sure to include that extension in the list, as long as it's not included in `babel.extensions`
- `require`: extra modules to require before tests are run. Modules are required in the [worker processes](./01-writing-tests.md#process-isolation)
- `babel`: test file specific Babel options. See our [Babel recipe](./recipes/babel.md#configuring-babel) for more details
- `babel.extensions`: extensions of test files that will be precompiled using AVA's Babel presets. Setting this overrides the default `"js"` value, so make sure to include that extension in the list
Expand Down
4 changes: 2 additions & 2 deletions docs/08-common-pitfalls.md
Expand Up @@ -75,11 +75,11 @@ AVA [can't trace uncaught exceptions](https://github.com/avajs/ava/issues/214) b

### Why are the enhanced assertion messages not shown?

Ensure that the first parameter passed into your test is named `t`. This is a requirement of [`power-assert`](https://github.com/power-assert-js/power-assert), the library that provides the enhanced messages.
Ensure that the first parameter passed into your test is named `t`. This is a requirement of [`power-assert`](https://github.com/power-assert-js/power-assert), the library that provides the [enhanced messages](./03-assertions.md#enhanced-assertion-messages).

```js
test('one is one', t => {
t.is(1, 1);
t.assert(1 === 1);
});
```

Expand Down
79 changes: 54 additions & 25 deletions lib/assert.js
Expand Up @@ -589,110 +589,139 @@ function wrapAssertions(callbacks) {
message: message || 'No snapshot available, run with --update-snapshots'
}));
}
}
};
},

const enhancedAssertions = enhanceAssert(pass, fail, {
truthy(actual, message) {
if (!actual) {
throw new AssertionError({
if (actual) {
pass(this);
} else {
fail(this, new AssertionError({
assertion: 'truthy',
message,
operator: '!!',
values: [formatWithLabel('Value is not truthy:', actual)]
});
}));
}
},

falsy(actual, message) {
if (actual) {
throw new AssertionError({
fail(this, new AssertionError({
assertion: 'falsy',
message,
operator: '!',
values: [formatWithLabel('Value is not falsy:', actual)]
});
}));
} else {
pass(this);
}
},

true(actual, message) {
if (actual !== true) {
throw new AssertionError({
if (actual === true) {
pass(this);
} else {
fail(this, new AssertionError({
assertion: 'true',
message,
values: [formatWithLabel('Value is not `true`:', actual)]
});
}));
}
},

false(actual, message) {
if (actual !== false) {
throw new AssertionError({
if (actual === false) {
pass(this);
} else {
fail(this, new AssertionError({
assertion: 'false',
message,
values: [formatWithLabel('Value is not `false`:', actual)]
});
}));
}
},

regex(string, regex, message) {
if (typeof string !== 'string') {
throw new AssertionError({
fail(this, 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)) {
throw new AssertionError({
fail(this, 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)) {
throw new AssertionError({
fail(this, new AssertionError({
assertion: 'regex',
message,
values: [
formatWithLabel('Value must match expression:', string),
formatWithLabel('Regular expression:', regex)
]
});
}));
return;
}

pass(this);
},

notRegex(string, regex, message) {
if (typeof string !== 'string') {
throw new AssertionError({
fail(this, 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)) {
throw new AssertionError({
fail(this, 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)) {
throw new AssertionError({
fail(this, new AssertionError({
assertion: 'notRegex',
message,
values: [
formatWithLabel('Value must not match expression:', string),
formatWithLabel('Regular expression:', regex)
]
}));
return;
}

pass(this);
}
};

const enhancedAssertions = enhanceAssert(pass, fail, {
assert(actual, message) {
if (!actual) {
throw new AssertionError({
assertion: 'assert',
message,
operator: '!!',
values: [formatWithLabel('Value is not truthy:', actual)]
});
}
}
Expand Down
7 changes: 1 addition & 6 deletions lib/enhance-assert.js
Expand Up @@ -8,12 +8,7 @@ const concordanceOptions = require('./concordance-options').default;
// https://github.com/avajs/babel-preset-transform-test-files/blob/master/espower-patterns.json
// Then release a new version of that preset and bump the SemVer range here.
const PATTERNS = [
't.truthy(value, [message])',
't.falsy(value, [message])',
't.true(value, [message])',
't.false(value, [message])',
't.regex(contents, regex, [message])',
't.notRegex(contents, regex, [message])'
't.assert(value, [message])'
];

const computeStatement = node => generate(node).code;
Expand Down
Binary file modified media/magic-assert-combined.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed media/magic-assert-nested.png
Binary file not shown.
Binary file added media/power-assert.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 0 additions & 11 deletions media/screenshot-fixtures/magic-assert-nested.js

This file was deleted.

11 changes: 11 additions & 0 deletions media/screenshot-fixtures/package.json
@@ -0,0 +1,11 @@
{
"name": "screenshot-fixtures",
"version": "1.0.0",
"description": "",
"main": "magic-assert-buffers.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": ""
}
8 changes: 8 additions & 0 deletions media/screenshot-fixtures/power-assert.js
@@ -0,0 +1,8 @@
import test from 'ava';

test('power-assert', t => {
const a = /foo/;
const b = 'bar';
const c = 'baz';
t.assert(a.test(b) || b === c);
});
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -61,7 +61,7 @@
],
"dependencies": {
"@ava/babel-preset-stage-4": "^2.0.0",
"@ava/babel-preset-transform-test-files": "^4.0.1",
"@ava/babel-preset-transform-test-files": "^5.0.0",
"@ava/write-file-atomic": "^2.2.0",
"@babel/core": "^7.3.4",
"@babel/generator": "^7.3.4",
Expand Down
3 changes: 2 additions & 1 deletion test/api.js
Expand Up @@ -433,6 +433,7 @@ test('enhanced assertion formatting necessary whitespace and empty strings', t =
/foo/
],
[
/!\(new Object\(foo\) instanceof Object\)/,
/new Object\(foo\) instanceof Object/,
/Object/,
/new Object\(foo\)/,
Expand All @@ -447,7 +448,7 @@ test('enhanced assertion formatting necessary whitespace and empty strings', t =
]
];

t.plan(14);
t.plan(15);
const api = apiCreator();
const errors = [];
api.on('run', plan => {
Expand Down
28 changes: 28 additions & 0 deletions test/assert.js
Expand Up @@ -1513,6 +1513,7 @@ test('.regex() fails if passed a bad value', t => {
assertions.regex(42, /foo/);
}, {
assertion: 'regex',
improperUsage: true,
message: '`t.regex()` must be called with a string',
values: [{label: 'Called with:', formatted: /42/}]
});
Expand Down Expand Up @@ -1577,3 +1578,30 @@ test('.notRegex() fails if passed a bad value', t => {

t.end();
});

test('.assert()', t => {
failsWith(t, () => {
assertions.assert(0);
}, {
assertion: 'assert',
message: '',
operator: '!!',
values: [{label: 'Value is not truthy:', formatted: /0/}]
});

failsWith(t, () => {
assertions.assert(false, 'my message');
}, {
assertion: 'assert',
message: 'my message',
operator: '!!',
values: [{label: 'Value is not truthy:', formatted: /false/}]
});

passes(t, () => {
assertions.assert(1);
assertions.assert(true);
});

t.end();
});

0 comments on commit 9406470

Please sign in to comment.