When assertions fails in Unexpected they yield an
UnexpectedError
. This instance has several convenience methods for
retrieving information about the error.
UnexpectedError.getErrorMessage()
Returns the error message as a
magicpen instance. The
method uses the assertion error modes to produce the correct
error message.
This is useful if you want to combine multiple errors in one assertion:
expect.addAssertion("array", "to have item satisfying", function (expect, subject) {
var args = Array.prototype.slice.call(arguments, 2);
var promises = subject.map(function (item) {
return expect.promise(function () {
return expect.apply(expect, [item].concat(args));
});
});
return expect.promise.settle(promises).then(function () {
var failed = promises.every(function (promise) {
return promise.isRejected();
});
if (failed) {
expect.fail({
diff: function (output, diff, inspect, equal) {
var result = {
inline: true,
diff: output
};
promises.forEach(function (promise, index) {
if (index > 0) { result.diff.nl(2); }
var error = promise.reason();
// the error is connected to the current scope
// but we are just interested in the nested error
error.errorMode = 'bubble';
result.diff.append(error.getErrorMessage());
});
return result;
}
});
}
});
});
When the assertion fails we get the following output:
expect(['foo', 'bar'], 'to have item satisfying', 'to equal', 'bar');
expect(['foo', 'bar'], 'to have item satisfying', 'to equal', 'bAr');
expected [ 'foo', 'bar' ] to have item satisfying 'to equal', 'bAr'
expected 'foo' to equal 'bAr'
expected 'bar' to equal 'bAr'
UnexpectedError.parent
When assertions delegate to nested expect
calls the errors that are
thrown on each level are chained together through the parent
property. The error message is serialized lazily, so it is possible to
change the error hierarchy before the error is serialized or extract
information from the hierarchy and use expect.fail to throw
a new error.
We could for example change the error mode for all the errors in the
chain to nested
:
expect.addAssertion('detailed to be', function (expect, subject, value) {
this.errorMode = 'bubble';
expect.withError(function () {
expect(subject, 'to be', value);
}, function (err) {
err.getParents().forEach(function (e){
e.errorMode = 'nested';
});
expect.fail(err);
});
});
expect('f00!', 'detailed to be', 'foo!');
expected 'f00!' to be 'foo!'
expected 'f00!' to equal 'foo!'
UnexpectedError.getParents()
Return an array with all the ancestor errors to this error. See
parent for more information.
UnexpectedError.getAllErrors()
Return an array with this error and all it's ancestors. See
parent for more information.
UnexpectedError.getDiff()
Finds the first error in the hierarchy that contains a diff and
returns it. This method if useful if you want to hoist a diff from an
ancestor error and combine it with a new message.
UnexpectedError.getDiffMethod()
In case you need to wrap diff with additional information you can
retrieve a method that will build a diff for you. It will find the
first ancestor error that contains a diff and return the method to
create the diff. Now you can delegate to that method from
expect.fail
:
expect.addAssertion('to be completely custom', function (expect, subject) {
return expect.withError(function () {
expect(subject, 'to satisfy', { custom: true });
}, function (err) {
var createDiff = err.getDiffMethod();
expect.fail({
diff: function (output, diff, inspect, equal) {
output.text('~~~~~~~~~~~~~~').sp().success('custom').sp().text('~~~~~~~~~~~~~~').nl();
var result = createDiff(output, diff, inspect, equal);
return result;
}
});
});
});
expect({ custom: false }, 'to be completely custom');
expected { custom: false } to be completely custom
~~~~~~~~~~~~~~ custom ~~~~~~~~~~~~~~
{
}
UnexpectedError.getLabel()
Get a shortened representation of the error message that doesn't
repeat the subject, for example should equal 'bar' rather than
expected 'foo' to equal 'bar'. This makes it suitable for display next
to an existing rendering of the subject, such as inside a diff.