Skip to content

Commit 49120aa

Browse files
committed
Ensure the assertion message is a string
Fixes #1125.
1 parent 0804107 commit 49120aa

File tree

2 files changed

+307
-9
lines changed

2 files changed

+307
-9
lines changed

lib/assert.js

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -265,18 +265,46 @@ class Assertions {
265265
patterns: [pattern]
266266
});
267267

268+
const checkMessage = (assertion, message, powerAssert = false) => {
269+
if (typeof message === 'undefined' || typeof message === 'string') {
270+
return true;
271+
}
272+
273+
const error = new AssertionError({
274+
assertion,
275+
improperUsage: true,
276+
message: 'The assertion message must be a string',
277+
values: [formatWithLabel('Called with:', message)]
278+
});
279+
280+
if (powerAssert) {
281+
throw error;
282+
}
283+
284+
fail(error);
285+
return false;
286+
};
287+
268288
this.pass = withSkip(() => {
269289
pass();
270290
});
271291

272292
this.fail = withSkip(message => {
293+
if (!checkMessage('fail', message)) {
294+
return;
295+
}
296+
273297
fail(new AssertionError({
274298
assertion: 'fail',
275299
message: message || 'Test failed via `t.fail()`'
276300
}));
277301
});
278302

279303
this.is = withSkip((actual, expected, message) => {
304+
if (!checkMessage('is', message)) {
305+
return;
306+
}
307+
280308
if (Object.is(actual, expected)) {
281309
pass();
282310
} else {
@@ -303,6 +331,10 @@ class Assertions {
303331
});
304332

305333
this.not = withSkip((actual, expected, message) => {
334+
if (!checkMessage('not', message)) {
335+
return;
336+
}
337+
306338
if (Object.is(actual, expected)) {
307339
fail(new AssertionError({
308340
assertion: 'not',
@@ -316,6 +348,10 @@ class Assertions {
316348
});
317349

318350
this.deepEqual = withSkip((actual, expected, message) => {
351+
if (!checkMessage('deepEqual', message)) {
352+
return;
353+
}
354+
319355
const result = concordance.compare(actual, expected, concordanceOptions);
320356
if (result.pass) {
321357
pass();
@@ -332,6 +368,10 @@ class Assertions {
332368
});
333369

334370
this.notDeepEqual = withSkip((actual, expected, message) => {
371+
if (!checkMessage('notDeepEqual', message)) {
372+
return;
373+
}
374+
335375
const result = concordance.compare(actual, expected, concordanceOptions);
336376
if (result.pass) {
337377
const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions);
@@ -351,6 +391,11 @@ class Assertions {
351391
// operator, so we can determine the total number of arguments passed
352392
// to the function.
353393
let [fn, expectations, message] = args;
394+
395+
if (!checkMessage('throws', message)) {
396+
return;
397+
}
398+
354399
if (typeof fn !== 'function') {
355400
fail(new AssertionError({
356401
assertion: 'throws',
@@ -412,6 +457,11 @@ class Assertions {
412457

413458
this.throwsAsync = withSkip((...args) => {
414459
let [thrower, expectations, message] = args;
460+
461+
if (!checkMessage('throwsAsync', message)) {
462+
return Promise.resolve();
463+
}
464+
415465
if (typeof thrower !== 'function' && !isPromise(thrower)) {
416466
fail(new AssertionError({
417467
assertion: 'throwsAsync',
@@ -492,6 +542,10 @@ class Assertions {
492542
});
493543

494544
this.notThrows = withSkip((fn, message) => {
545+
if (!checkMessage('notThrows', message)) {
546+
return;
547+
}
548+
495549
if (typeof fn !== 'function') {
496550
fail(new AssertionError({
497551
assertion: 'notThrows',
@@ -518,6 +572,10 @@ class Assertions {
518572
});
519573

520574
this.notThrowsAsync = withSkip((nonThrower, message) => {
575+
if (!checkMessage('notThrowsAsync', message)) {
576+
return Promise.resolve();
577+
}
578+
521579
if (typeof nonThrower !== 'function' && !isPromise(nonThrower)) {
522580
fail(new AssertionError({
523581
assertion: 'notThrowsAsync',
@@ -574,20 +632,31 @@ class Assertions {
574632
return handlePromise(retval, true);
575633
});
576634

577-
this.snapshot = withSkip((expected, optionsOrMessage, message) => {
578-
const options = {};
579-
if (typeof optionsOrMessage === 'string') {
580-
message = optionsOrMessage;
581-
} else if (optionsOrMessage) {
582-
options.id = optionsOrMessage.id;
635+
this.snapshot = withSkip((expected, ...rest) => {
636+
let message;
637+
let snapshotOptions;
638+
if (rest.length > 1) {
639+
[snapshotOptions, message] = rest;
640+
} else {
641+
const [optionsOrMessage] = rest;
642+
if (typeof optionsOrMessage === 'object') {
643+
snapshotOptions = optionsOrMessage;
644+
} else {
645+
message = optionsOrMessage;
646+
}
583647
}
584648

585-
options.expected = expected;
586-
options.message = message;
649+
if (!checkMessage('snapshot', message)) {
650+
return;
651+
}
587652

588653
let result;
589654
try {
590-
result = compareWithSnapshot(options);
655+
result = compareWithSnapshot({
656+
expected,
657+
id: snapshotOptions ? snapshotOptions.id : undefined,
658+
message
659+
});
591660
} catch (error) {
592661
if (!(error instanceof snapshotManager.SnapshotError)) {
593662
throw error;
@@ -625,6 +694,10 @@ class Assertions {
625694
});
626695

627696
this.truthy = withSkip((actual, message) => {
697+
if (!checkMessage('truthy', message)) {
698+
return;
699+
}
700+
628701
if (actual) {
629702
pass();
630703
} else {
@@ -638,6 +711,10 @@ class Assertions {
638711
});
639712

640713
this.falsy = withSkip((actual, message) => {
714+
if (!checkMessage('falsy', message)) {
715+
return;
716+
}
717+
641718
if (actual) {
642719
fail(new AssertionError({
643720
assertion: 'falsy',
@@ -651,6 +728,10 @@ class Assertions {
651728
});
652729

653730
this.true = withSkip((actual, message) => {
731+
if (!checkMessage('true', message)) {
732+
return;
733+
}
734+
654735
if (actual === true) {
655736
pass();
656737
} else {
@@ -663,6 +744,10 @@ class Assertions {
663744
});
664745

665746
this.false = withSkip((actual, message) => {
747+
if (!checkMessage('false', message)) {
748+
return;
749+
}
750+
666751
if (actual === false) {
667752
pass();
668753
} else {
@@ -675,6 +760,10 @@ class Assertions {
675760
});
676761

677762
this.regex = withSkip((string, regex, message) => {
763+
if (!checkMessage('regex', message)) {
764+
return;
765+
}
766+
678767
if (typeof string !== 'string') {
679768
fail(new AssertionError({
680769
assertion: 'regex',
@@ -711,6 +800,10 @@ class Assertions {
711800
});
712801

713802
this.notRegex = withSkip((string, regex, message) => {
803+
if (!checkMessage('notRegex', message)) {
804+
return;
805+
}
806+
714807
if (typeof string !== 'string') {
715808
fail(new AssertionError({
716809
assertion: 'notRegex',
@@ -749,6 +842,8 @@ class Assertions {
749842
this.assert = withSkip(withPowerAssert(
750843
'assert(value, [message])',
751844
(actual, message) => {
845+
checkMessage('assert', message, true);
846+
752847
if (!actual) {
753848
throw new AssertionError({
754849
assertion: 'assert',

0 commit comments

Comments
 (0)