Skip to content

Commit

Permalink
♻️ Attach firstElement and messageArray to assert errors (#32887)
Browse files Browse the repository at this point in the history
* Attach firstElement and messageArray to assert errors

* Add tests

* Use string#replace insteadof iterating over messageArgs
  • Loading branch information
rcebulko committed Feb 25, 2021
1 parent 60ec06c commit ee8ac1e
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
40 changes: 32 additions & 8 deletions src/assert.js
Expand Up @@ -53,6 +53,15 @@ export class UserError extends Error {

/**
* Throws a provided error if the second argument isn't trueish.
*
* Supports argument substitution into the message via %s placeholders.
*
* Throws an error object that has two extra properties:
* - associatedElement: This is the first element provided in the var args.
* It can be used for improved display of error messages.
* - messageArray: The elements of the substituted message as non-stringified
* elements in an array. When e.g. passed to console.error this yields
* native displays of things like HTML elements.
* @param {Object} errorCls
* @param {T} shouldBeTruthy
* @param {string} opt_message
Expand All @@ -65,16 +74,31 @@ function assertion(errorCls, shouldBeTruthy, opt_message, var_args) {
return shouldBeTruthy;
}

// Skip the first 3 arguments to isolate format params
const messageArgs = Array.prototype.slice.call(arguments, 3);
const messageArray = [];
let firstElement;

// Substitute provided values into format string in message
const message = Array.prototype.slice
// Skip the first 3 arguments to isolate format params
.call(arguments, 3)
.reduce(
(msg, subValue) => msg.replace('%s', subValue),
opt_message || 'Assertion failed'
);
const message = (opt_message || 'Assertion failed').replace(/%s/g, () => {
const subValue = messageArgs.shift();

if (subValue != '') {
messageArray.push(subValue);
}

// If an element is provided, add it to the error object
if (!firstElement && subValue?.nodeType == 1) {
firstElement = subValue;
}

return subValue;
});

throw new errorCls(message);
const error = new errorCls(message);
error.messageArray = messageArray;
error.associatedElement = firstElement;
throw error;
}

/**
Expand Down
13 changes: 13 additions & 0 deletions test/unit/test-assert.js
Expand Up @@ -61,4 +61,17 @@ describes.sandboxed('assertions', {}, () => {
`1 a 2 b 3${USER_ERROR_SENTINEL}`
);
});

it('should add element and message info', () => {
const div = document.createElement('div');
let error;
try {
devAssert(false, '%s a %s b %s', div, 2, 3);
} catch (e) {
error = e;
}

expect(error.associatedElement).to.equal(div);
expect(error.messageArray).to.deep.equal([div, 2, 3]);
});
});

0 comments on commit ee8ac1e

Please sign in to comment.