Because expected true, result false is not enough.
Gives message-less QUnit assertions a message: their own source text.
// you write
assert.ok(user.isActive);
// it compiles to
assert.ok(user.isActive, 'assert.ok(user.isActive)');So a failure reports
assert.ok(user.isActive)
instead of
failed, expected argument to be truthy
Only assertions without a message are touched. Anything you wrote yourself is left alone.
Upgrading from v2? v3 is a Babel plugin rather than an ember-cli addon, and it needs one line of configuration — installing it is no longer enough. See MIGRATION.md.
pnpm add --save-dev ember-qunit-nice-errorsThen add it to your Babel config. This step is required — the plugin does nothing until you do.
// babel.config.mjs
import qunitNiceErrors from 'ember-qunit-nice-errors';
export default {
plugins: [
qunitNiceErrors,
// ...your other plugins
],
};// ember-cli-build.js
const app = new EmberApp(defaults, {
babel: {
plugins: [require.resolve('ember-qunit-nice-errors')],
},
});The same works in an addon's index.js and in an engine's ember-cli-build.js.
@babel/core7 or 8- Node.js 22 or above
There is no longer an Ember version requirement — this is a plain Babel plugin. It works under Vite, Embroider and classic builds alike, and in any QUnit suite that runs through Babel.
| option | type | default | meaning |
|---|---|---|---|
include |
RegExp | string | Array |
[/-test\.(?:[cm]?[jt]sx?|g[jt]s)$/] |
Which filenames to transform. Replaces the default rather than extending it. |
exclude |
RegExp | string | Array |
— | Filenames to skip. Takes precedence over include. |
showFileInfo |
boolean |
false |
Append at <path>:<line>:<column>, relative to Babel's cwd. |
completeExistingMessages |
boolean |
false |
Also overwrite messages you wrote yourself. Off by default, and rarely what you want. |
Strings are compiled with new RegExp(...), so escape accordingly ('\\.spec\\.js$').
[
'ember-qunit-nice-errors',
{
include: [/\.spec\.js$/],
exclude: [/vendor/],
showFileInfo: true,
},
];The default pattern is exported if you would rather extend it than replace it:
const { DEFAULT_INCLUDE } = require('ember-qunit-nice-errors');
['ember-qunit-nice-errors', { include: [...DEFAULT_INCLUDE, /\.spec\.js$/] }];In v2
includeandexcludewere globs read fromconfig/environment.js. They are now regular expressions passed as plugin options — see MIGRATION.md.
ok, notOk, equal, notEqual, strictEqual, notStrictEqual, deepEqual, notDeepEqual, propEqual, notPropEqual.
Assertions whose failure output is already descriptive — throws, step, verifySteps, expect, async, timeout — are deliberately left alone.
It resolves the assert object through Babel's scope rather than matching the identifier by name. A call is transformed only when its object is the first parameter of a function passed to a QUnit test() — including QUnit.test, test.only, test.skip and test.todo.
That means:
- renamed parameters work —
test('x', function (a) { a.ok(v); }) - arrow-function tests work —
test('x', async (assert) => { … }) - an unrelated local called
assertis not transformed - an
assertpassed tohooks.beforeEachis not transformed, because it is not a test callback
The last two were gaps in v2, which tracked the most recently seen test() call textually and only matched FunctionExpression.
It is also idempotent: a call is only matched when its argument count says no message was passed, so re-running the transform cannot append twice.
pnpm install
pnpm test # node --test
pnpm run lint
pnpm run lint:fixMIT