Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var figures = require('figures');
var globby = require('globby');
var chalk = require('chalk');
var fork = require('./lib/fork');
var formatter = require('./lib/enhance-assert').formatter();

function Api(files, options) {
if (!(this instanceof Api)) {
Expand Down Expand Up @@ -76,6 +77,13 @@ Api.prototype._handleTest = function (test) {
var isError = test.error.message;

if (isError) {
if (test.error.powerAssertContext) {
var message = formatter(test.error.powerAssertContext);
if (test.error.originalMessage) {
message = test.error.originalMessage + ' ' + message;
}
test.error.message = message;
}
this.errors.push(test);
} else {
test.error = null;
Expand Down
2 changes: 0 additions & 2 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,3 @@ x.regexTest = function (regex, contents, msg) {
x.ifError = x.error = function (err, msg) {
test(!err, create(err, 'Error', '!==', msg, x.ifError));
};

require('./enhance-assert')(x);
48 changes: 33 additions & 15 deletions lib/enhance-assert.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = enhanceAssert;
module.exports.formatter = formatter;

module.exports.PATTERNS = [
't.ok(value, [message])',
Expand All @@ -12,23 +13,40 @@ module.exports.PATTERNS = [
't.regexTest(regex, contents, [message])'
];

function enhanceAssert(assert) {
var empower = require('empower');
var powerAssertFormatter = require('power-assert-formatter');
var powerAssertRenderers = require('power-assert-renderers');
module.exports.NON_ENHANCED_PATTERNS = [
't.pass([message])',
't.fail([message])',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-enhanced patterns are a new feature we are adding to power-assert. There will be no source code transform, but we do wrap the function and automatically extract the optional message parameter for you and pass it as event.originalMessage. It will be undefined if the user does not pass it in.

't.throws(fn, [message])',
't.doesNotThrow(fn, [message])',
't.ifError(error, [message])'
];

empower(assert,
powerAssertFormatter({
renderers: [
powerAssertRenderers.AssertionRenderer,
powerAssertRenderers.SuccinctRenderer
]
}),
function enhanceAssert(opts) {
var empower = require('empower-core');
var enhanced = empower(
opts.assert,
{
destructive: true,
modifyMessageOnRethrow: true,
saveContextOnRethrow: false,
patterns: module.exports.PATTERNS
destructive: false,
onError: opts.onError,
onSuccess: opts.onSuccess,
patterns: module.exports.PATTERNS,
wrapOnlyPatterns: module.exports.NON_ENHANCED_PATTERNS
}
);

enhanced.AssertionError = opts.assert.AssertionError;

return enhanced;
}

function formatter() {
var powerAssertFormatter = require('power-assert-formatter');
var powerAssertRenderers = require('power-assert-renderers');

return powerAssertFormatter({
renderers: [
powerAssertRenderers.AssertionRenderer,
powerAssertRenderers.SuccinctRenderer
]
});
}
67 changes: 38 additions & 29 deletions lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var observableToPromise = require('observable-to-promise');
var isPromise = require('is-promise');
var isObservable = require('is-observable');
var assert = require('./assert');
var enhanceAssert = require('./enhance-assert');
var globals = require('./globals');

function Test(title, fn) {
Expand Down Expand Up @@ -61,11 +62,6 @@ Test.prototype._setAssertError = function (err) {
this.assertError = err;
};

// Workaround for power-assert
// `t` must be capturable for decorated assert output
Test.prototype._capt = assert._capt;
Test.prototype._expr = assert._expr;

Test.prototype.plan = function (count) {
if (typeof count !== 'number') {
throw new TypeError('Expected a number');
Expand Down Expand Up @@ -208,9 +204,7 @@ Test.prototype._publicApi = function () {
[
'assertCount',
'title',
'end',
'_capt',
'_expr'
'end'
]
.forEach(function (name) {
Object.defineProperty(api, name, {
Expand Down Expand Up @@ -239,31 +233,46 @@ Test.prototype._publicApi = function () {
self._assert();
}

function onAssertionEvent(event) {
if (event.assertionThrew) {
event.error.powerAssertContext = event.powerAssertContext;
event.error.originalMessage = event.originalMessage;
self._setAssertError(event.error);
self._assert();
return null;
}

var fn = observableToPromise(event.returnValue);

if (isPromise(fn)) {
return Promise.resolve(fn)
.catch(function (err) {
err.originalMessage = event.originalMessage;
self._setAssertError(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will errors here also have powerAssertContext?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given your answer below I understood what is onAssertionEvent for, but I still don't understand what would the answer to my question be.

Here, if assertion returns promise and that promise rejects, we just _setAssertError(), but without powerAssertContext like above (lines 237-242).

Or (correct me if I'm wrong) if "in that promise" there is a failed assertion, onAssertionEvent will be triggered again with event.type === 'error'. In that case, we don't need a .catch() block on that promise, don't we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure - it might. I need to test that. My initial thought is no, sense the only assertions that return promises is throws and doesNotThrow right? Those are non-enhanced.

Definitely worth me double checking though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, only throws and doesNotThrow might return promises.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, then we are good. Those will never have powerAssertContext. Probably would be good to attach originalMessage though right?

})
.finally(function () {
self._assert();
});
}

self._assert();
return null;
}

var enhanced = enhanceAssert({
assert: assert,
onSuccess: onAssertionEvent,
onError: onAssertionEvent
});

// Patched assert methods: increase assert count and store errors.
Object.keys(assert).forEach(function (el) {
api.skip[el] = skipFn;
api[el] = function () {
try {
var fn = assert[el].apply(assert, arguments);

fn = observableToPromise(fn);

if (isPromise(fn)) {
return Promise.resolve(fn)
.catch(function (err) {
self._setAssertError(err);
})
.finally(function () {
self._assert();
});
}
} catch (err) {
self._setAssertError(err);
}

self._assert();
};
api[el] = enhanced[el].bind(enhanced);
});

api._capt = enhanced._capt.bind(enhanced);
api._expr = enhanced._expr.bind(enhanced);

return api;
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"debug": "^2.2.0",
"deeper": "^2.1.0",
"empower": "^1.1.0",
"empower-core": "^0.2.0",
"figures": "^1.4.0",
"fn-name": "^2.0.0",
"globby": "^4.0.0",
Expand Down
21 changes: 21 additions & 0 deletions test/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,24 @@ test('Node.js-style --require CLI argument', function (t) {
t.is(api.passCount, 1);
});
});

test('power-assert support', function (t) {
t.plan(3);

var api = new Api([path.join(__dirname, 'fixture/power-assert.js')]);

api.run()
.then(function () {
t.ok(api.errors[0].error.powerAssertContext);

t.match(
api.errors[0].error.message,
/t\.ok\(a === 'bar'\)\s*\n\s+\|\s*\n\s+"foo"/m
);

t.match(
api.errors[1].error.message,
/with message\s+t\.ok\(a === 'foo', 'with message'\)\s*\n\s+\|\s*\n\s+"bar"/m
);
});
});
8 changes: 7 additions & 1 deletion test/fixture/power-assert.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import test from '../../';

test(t => {
test.serial(t => {
const a = 'foo';

t.ok(a === 'bar');
});

test.serial(t => {
const a = 'bar';

t.ok(a === 'foo', 'with message');
});