/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* @todo Bug 2005403
* Move this to main assert module, could look like:
* await Assert.continueOnAssert(async function() {
* Assert.ok();
* await Assert.rejects();
* ...
* });
*/
function SoftAssert() {
this.failures = [];
}
SoftAssert.prototype._recordFailure =
function (err, context) {
this.failures.push({
message: err.message,
name: err.name,
stack: err.stack,
context,
});
};
SoftAssert.prototype.
throws =
function (
block,
expectedError,
message =
"throws failed"
) {
try {
Assert.
throws(block, expectedError, message);
this._recordFailure(
new Error(
"Did not throw"), {
type:
"throws",
expectedError,
message,
});
}
catch {}
};
SoftAssert.prototype.ok =
function (condition, message =
"ok failed") {
try {
Assert.ok(condition, message);
}
catch (err) {
this._recordFailure(err, { type:
"ok", condition, message });
}
};
SoftAssert.prototype.equal =
function (
actual,
expected,
message =
"equal failed"
) {
try {
Assert.equal(actual, expected, message);
}
catch (err) {
this._recordFailure(err, { type:
"equal", actual, expected, message });
}
};
SoftAssert.prototype.notEqual =
function (
actual,
expected,
message =
"notEqual failed"
) {
try {
Assert.notEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, { type:
"notEqual", actual, expected, message });
}
};
SoftAssert.prototype.deepEqual =
function (
actual,
expected,
message =
"deepEqual failed"
) {
try {
Assert.deepEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, { type:
"deepEqual", actual, expected, message });
}
};
SoftAssert.prototype.notDeepEqual =
function (
actual,
expected,
message =
"notDeepEqual failed"
) {
try {
Assert.notDeepEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, {
type:
"notDeepEqual",
actual,
expected,
message,
});
}
};
SoftAssert.prototype.strictEqual =
function (
actual,
expected,
message =
"strictEqual failed"
) {
try {
Assert.strictEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, {
type:
"strictEqual",
actual,
expected,
message,
});
}
};
SoftAssert.prototype.notStrictEqual =
function (
actual,
expected,
message =
"notStrictEqual failed"
) {
try {
Assert.notStrictEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, {
type:
"notStrictEqual",
actual,
expected,
message,
});
}
};
SoftAssert.prototype.rejects = async
function (
actual,
expected,
message =
"rejects failed"
) {
try {
await
Assert.rejects(actual, expected, message);
}
catch (err) {
this._recordFailure(err, { type:
"rejects", actual, expected, message });
}
};
SoftAssert.prototype.greater =
function (
actual,
expected,
message =
"greater failed"
) {
try {
Assert.greater(actual, expected, message);
}
catch (err) {
this._recordFailure(err, { type:
"greater", actual, expected, message });
}
};
SoftAssert.prototype.greaterOrEqual =
function (
actual,
expected,
message =
"greaterOrEqual failed"
) {
try {
Assert.greaterOrEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, {
type:
"greaterOrEqual",
actual,
expected,
message,
});
}
};
SoftAssert.prototype.less =
function (
actual,
expected,
message =
"less failed"
) {
try {
Assert.less(actual, expected, message);
}
catch (err) {
this._recordFailure(err, { type:
"less", actual, expected, message });
}
};
SoftAssert.prototype.lessOrEqual =
function (
actual,
expected,
message =
"lessOrEqual failed"
) {
try {
Assert.lessOrEqual(actual, expected, message);
}
catch (err) {
this._recordFailure(err, {
type:
"lessOrEqual",
actual,
expected,
message,
});
}
};
// Call this at the end to fail the test if any soft asserts failed.
SoftAssert.prototype.assertAll =
function (label =
"Soft assertion failures") {
if (!
this.failures.length) {
return;
}
let details = `${label} (${
this.failures.length}):\n`;
for (let i =
0; i <
this.failures.length; i++) {
const f =
this.failures[i];
details += `\n[${i +
1}] ${f.message}\n`;
if (f.context) {
details += ` Context: ${JSON.stringify(f.context)}\n`;
}
if (f.stack) {
details += ` Stack: ${f.stack}\n`;
}
}
// One combined failure at the end:
throw new Error(details);
};
function softAssertions(
Assert) {
/**
* Provides a way to execute multiple assertions without exiting
* a test after the first assertion failure. All assertions in the
* provided callback will run even if some assertions fail. If an
* assertion fails, the test will fail and provide details on the
* failed assertion(s).
*
* @example
* Assert.withSoftAssertions(function(soft) {
* // Use usual Assert functions via `soft` reference:
* soft.equal(conversation.id.length, 12);
* soft.ok(Array.isArray(conversation.messages));
* soft.ok(!isNaN(conversation.createdDate));
* });
*
* @param {Function} tests - A callback that acceps a `soft` object to run assertions with.
*/
Assert.withSoftAssertions =
function (tests) {
const soft =
new SoftAssert();
tests(soft);
soft.assertAll();
};
}
softAssertions(
Assert);