From ca9022bd535bc2c4b73ecfb4e14daf3df7075fe3 Mon Sep 17 00:00:00 2001 From: John Markham Date: Thu, 20 Aug 2020 23:09:39 -0700 Subject: [PATCH 01/10] feat: have assertions return booleans --- lib/assert.js | 207 +++++++++++++++++++++++---------------------- test-tap/assert.js | 72 ++++++++-------- 2 files changed, 140 insertions(+), 139 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 8201ea9fb..b28343f30 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -307,6 +307,7 @@ class Assertions { this.pass = withSkip(() => { pass(); + return true; }); this.fail = withSkip(message => { @@ -318,6 +319,7 @@ class Assertions { assertion: 'fail', message: message || 'Test failed via `t.fail()`' })); + return false; }); this.is = withSkip((actual, expected, message) => { @@ -326,28 +328,28 @@ class Assertions { } if (Object.is(actual, expected)) { - pass(); - } else { - const result = concordance.compare(actual, expected, concordanceOptions); - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); + return pass(); + } - if (result.pass) { - fail(new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] - })); - } else { - fail(new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); - } + const result = concordance.compare(actual, expected, concordanceOptions); + const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); + const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); + + if (result.pass) { + return fail(new AssertionError({ + assertion: 'is', + message, + raw: {actual, expected}, + values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] + })); } + + return fail(new AssertionError({ + assertion: 'is', + message, + raw: {actual, expected}, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); }); this.not = withSkip((actual, expected, message) => { @@ -356,15 +358,15 @@ class Assertions { } if (Object.is(actual, expected)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'not', message, raw: {actual, expected}, values: [formatWithLabel('Value is the same as:', actual)] })); - } else { - pass(); } + + return pass(); }); this.deepEqual = withSkip((actual, expected, message) => { @@ -374,17 +376,18 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { - pass(); - } else { - const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); - fail(new AssertionError({ - assertion: 'deepEqual', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); + return pass(); } + + const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); + const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); + + return fail(new AssertionError({ + assertion: 'deepEqual', + message, + raw: {actual, expected}, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); }); this.notDeepEqual = withSkip((actual, expected, message) => { @@ -395,30 +398,37 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notDeepEqual', message, raw: {actual, expected}, values: [formatDescriptorWithLabel('Value is deeply equal:', actualDescriptor)] })); - } else { - pass(); } + + return pass(); }); this.like = withSkip((actual, selector, message) => { + if (!experiments.likeAssertion) { + return fail(new AssertionError({ + assertion: 'like', + improperUsage: true, + message: 'You must enable the `likeAssertion` experiment in order to use `t.like()`' + })); + } + if (!checkMessage('like', message)) { return; } if (!isLikeSelector(selector)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must be a non-empty object', values: [formatWithLabel('Called with:', selector)] })); - return; } let comparable; @@ -426,13 +436,12 @@ class Assertions { comparable = selectComparable(actual, selector); } catch (error) { if (error === CIRCULAR_SELECTOR) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must not contain circular references', values: [formatWithLabel('Called with:', selector)] })); - return; } throw error; @@ -440,16 +449,16 @@ class Assertions { const result = concordance.compare(comparable, selector, concordanceOptions); if (result.pass) { - pass(); - } else { - const actualDescriptor = result.actual || concordance.describe(comparable, concordanceOptions); - const expectedDescriptor = result.expected || concordance.describe(selector, concordanceOptions); - fail(new AssertionError({ - assertion: 'like', - message, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); + return pass(); } + + const actualDescriptor = result.actual || concordance.describe(comparable, concordanceOptions); + const expectedDescriptor = result.expected || concordance.describe(selector, concordanceOptions); + return fail(new AssertionError({ + assertion: 'like', + message, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); }); this.throws = withSkip((...args) => { @@ -743,29 +752,30 @@ class Assertions { improperUsage.expectedVersion = error.expectedVersion; } - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'snapshot', message: message || 'Could not compare snapshot', improperUsage })); - return; } if (result.pass) { - pass(); - } else if (result.actual) { - fail(new AssertionError({ + return pass(); + } + + if (result.actual) { + return fail(new AssertionError({ assertion: 'snapshot', message: message || 'Did not match snapshot', values: [formatDescriptorDiff(result.actual, result.expected, {invert: true})] })); - } else { - // This can only occur in CI environments. - fail(new AssertionError({ - assertion: 'snapshot', - message: message || 'No snapshot available — new snapshots are not created in CI environments' - })); } + + // This can only occur in CI environments. + return fail(new AssertionError({ + assertion: 'snapshot', + message: message || 'No snapshot available — new snapshots are not created in CI environments' + })); }); this.truthy = withSkip((actual, message) => { @@ -774,15 +784,15 @@ class Assertions { } if (actual) { - pass(); - } else { - fail(new AssertionError({ - assertion: 'truthy', - message, - operator: '!!', - values: [formatWithLabel('Value is not truthy:', actual)] - })); + return pass(); } + + return fail(new AssertionError({ + assertion: 'truthy', + message, + operator: '!!', + values: [formatWithLabel('Value is not truthy:', actual)] + })); }); this.falsy = withSkip((actual, message) => { @@ -791,15 +801,15 @@ class Assertions { } if (actual) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'falsy', message, operator: '!', values: [formatWithLabel('Value is not falsy:', actual)] })); - } else { - pass(); } + + return pass(); }); this.true = withSkip((actual, message) => { @@ -808,14 +818,14 @@ class Assertions { } if (actual === true) { - pass(); - } else { - fail(new AssertionError({ - assertion: 'true', - message, - values: [formatWithLabel('Value is not `true`:', actual)] - })); + return pass(); } + + return fail(new AssertionError({ + assertion: 'true', + message, + values: [formatWithLabel('Value is not `true`:', actual)] + })); }); this.false = withSkip((actual, message) => { @@ -824,14 +834,14 @@ class Assertions { } if (actual === false) { - pass(); - } else { - fail(new AssertionError({ - assertion: 'false', - message, - values: [formatWithLabel('Value is not `false`:', actual)] - })); + return pass(); } + + return fail(new AssertionError({ + assertion: 'false', + message, + values: [formatWithLabel('Value is not `false`:', actual)] + })); }); this.regex = withSkip((string, regex, message) => { @@ -840,27 +850,25 @@ class Assertions { } if (typeof string !== 'string') { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); - return; } if (!(regex instanceof RegExp)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); - return; } if (!regex.test(string)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'regex', message, values: [ @@ -868,10 +876,9 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); - return; } - pass(); + return pass(); }); this.notRegex = withSkip((string, regex, message) => { @@ -880,27 +887,25 @@ class Assertions { } if (typeof string !== 'string') { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); - return; } if (!(regex instanceof RegExp)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); - return; } if (regex.test(string)) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'notRegex', message, values: [ @@ -908,10 +913,9 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); - return; } - pass(); + return pass(); }); if (powerAssert === undefined) { @@ -921,16 +925,15 @@ class Assertions { } if (!actual) { - fail(new AssertionError({ + return fail(new AssertionError({ assertion: 'assert', message, operator: '!!', values: [formatWithLabel('Value is not truthy:', actual)] })); - return; } - pass(); + return pass(); }); } else { this.assert = withSkip(withPowerAssert( diff --git a/test-tap/assert.js b/test-tap/assert.js index be0f29eb5..b055cd6e0 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -12,26 +12,26 @@ const snapshotManager = require('../lib/snapshot-manager'); const HelloMessage = require('./fixture/hello-message'); let lastFailure = null; -let lastPassed = false; const AssertionsBase = class extends assert.Assertions { constructor(overwrites = {}) { super({ - pass: () => { - lastPassed = true; - }, + pass: () => true, pending: promise => { - promise.then(() => { - lastPassed = true; - }, error => { + return promise.then(() => + true + , error => { lastFailure = error; }); }, fail: error => { lastFailure = error; + return false; }, skip: () => {}, - experiments: {}, + experiments: { + likeAssertion: true + }, ...overwrites }); } @@ -144,10 +144,8 @@ function eventuallyFails(t, fn) { */ function passes(t, fn) { - lastPassed = false; lastFailure = null; - fn(); - if (lastPassed) { + if (fn()) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -156,10 +154,9 @@ function passes(t, fn) { function eventuallyPasses(t, fn) { return add(() => { - lastPassed = false; lastFailure = null; - return fn().then(() => { - if (lastPassed) { + return fn().then(passed => { + if (passed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -170,12 +167,12 @@ function eventuallyPasses(t, fn) { test('.pass()', t => { passes(t, () => { - assertions.pass(); + return assertions.pass(); }); passes(t, () => { const {pass} = assertions; - pass(); + return pass(); }); t.end(); @@ -183,14 +180,14 @@ test('.pass()', t => { test('.fail()', t => { failsWith(t, () => { - assertions.fail(); + return assertions.fail(); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - assertions.fail('my message'); + return assertions.fail('my message'); }, { assertion: 'fail', message: 'my message' @@ -198,14 +195,14 @@ test('.fail()', t => { failsWith(t, () => { const {fail} = assertions; - fail(); + return fail(); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - assertions.fail(null); + return assertions.fail(null); }, { assertion: 'fail', improperUsage: true, @@ -221,73 +218,73 @@ test('.fail()', t => { test('.is()', t => { passes(t, () => { - assertions.is('foo', 'foo'); + return assertions.is('foo', 'foo'); }); passes(t, () => { const {is} = assertions; - is('foo', 'foo'); + return is('foo', 'foo'); }); passes(t, () => { - assertions.is('', ''); + return assertions.is('', ''); }); passes(t, () => { - assertions.is(true, true); + return assertions.is(true, true); }); passes(t, () => { - assertions.is(false, false); + return assertions.is(false, false); }); passes(t, () => { - assertions.is(null, null); + return assertions.is(null, null); }); passes(t, () => { - assertions.is(undefined, undefined); + return assertions.is(undefined, undefined); }); passes(t, () => { - assertions.is(1, 1); + return assertions.is(1, 1); }); passes(t, () => { - assertions.is(0, 0); + return assertions.is(0, 0); }); passes(t, () => { - assertions.is(-0, -0); + return assertions.is(-0, -0); }); passes(t, () => { - assertions.is(Number.NaN, Number.NaN); + return assertions.is(Number.NaN, Number.NaN); }); passes(t, () => { - assertions.is(0 / 0, Number.NaN); + return assertions.is(0 / 0, Number.NaN); }); passes(t, () => { const someRef = {foo: 'bar'}; - assertions.is(someRef, someRef); + return assertions.is(someRef, someRef); }); fails(t, () => { - assertions.is(0, -0); + return assertions.is(0, -0); }); fails(t, () => { - assertions.is(0, false); + return assertions.is(0, false); }); fails(t, () => { - assertions.is('', false); + return assertions.is('', false); }); fails(t, () => { - assertions.is('0', 0); + return assertions.is('0', 0); }); fails(t, () => { @@ -2186,3 +2183,4 @@ test('.assert()', t => { t.end(); }); + From fe3725022a6e3d050809a6c9d1850e77ffd74ea6 Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Sat, 19 Sep 2020 23:03:25 +0530 Subject: [PATCH 02/10] Assertions return boolean --- lib/assert.js | 160 +++++++++++++++++++++++++++---------------- test-tap/assert.js | 164 +++++++++++++++++++++++++++++---------------- 2 files changed, 206 insertions(+), 118 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index b28343f30..8f2145f70 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -286,6 +286,7 @@ class Assertions { }, onSuccess: () => { pass(); + return true; }, bindReceiver: false, patterns: [pattern] @@ -328,7 +329,8 @@ class Assertions { } if (Object.is(actual, expected)) { - return pass(); + pass(); + return true; } const result = concordance.compare(actual, expected, concordanceOptions); @@ -336,20 +338,22 @@ class Assertions { const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); if (result.pass) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'is', message, raw: {actual, expected}, values: [formatDescriptorWithLabel('Values are deeply equal to each other, but they are not the same:', actualDescriptor)] })); + } else { + fail(new AssertionError({ + assertion: 'is', + message, + raw: {actual, expected}, + values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] + })); } - return fail(new AssertionError({ - assertion: 'is', - message, - raw: {actual, expected}, - values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] - })); + return false; }); this.not = withSkip((actual, expected, message) => { @@ -358,15 +362,17 @@ class Assertions { } if (Object.is(actual, expected)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'not', message, raw: {actual, expected}, values: [formatWithLabel('Value is the same as:', actual)] })); + return false; } - return pass(); + pass(); + return true; }); this.deepEqual = withSkip((actual, expected, message) => { @@ -376,18 +382,20 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { - return pass(); + pass(); + return true; } const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); const expectedDescriptor = result.expected || concordance.describe(expected, concordanceOptions); - - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'deepEqual', message, raw: {actual, expected}, values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] })); + + return false; }); this.notDeepEqual = withSkip((actual, expected, message) => { @@ -398,37 +406,32 @@ class Assertions { const result = concordance.compare(actual, expected, concordanceOptions); if (result.pass) { const actualDescriptor = result.actual || concordance.describe(actual, concordanceOptions); - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notDeepEqual', message, raw: {actual, expected}, values: [formatDescriptorWithLabel('Value is deeply equal:', actualDescriptor)] })); + return false; } - return pass(); + pass(); + return true; }); this.like = withSkip((actual, selector, message) => { - if (!experiments.likeAssertion) { - return fail(new AssertionError({ - assertion: 'like', - improperUsage: true, - message: 'You must enable the `likeAssertion` experiment in order to use `t.like()`' - })); - } - if (!checkMessage('like', message)) { return; } if (!isLikeSelector(selector)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must be a non-empty object', values: [formatWithLabel('Called with:', selector)] })); + return false; } let comparable; @@ -436,12 +439,13 @@ class Assertions { comparable = selectComparable(actual, selector); } catch (error) { if (error === CIRCULAR_SELECTOR) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'like', improperUsage: true, message: '`t.like()` selector must not contain circular references', values: [formatWithLabel('Called with:', selector)] })); + return false; } throw error; @@ -449,16 +453,19 @@ class Assertions { const result = concordance.compare(comparable, selector, concordanceOptions); if (result.pass) { - return pass(); + pass(); + return true; } const actualDescriptor = result.actual || concordance.describe(comparable, concordanceOptions); const expectedDescriptor = result.expected || concordance.describe(selector, concordanceOptions); - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'like', message, values: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)] })); + + return false; }); this.throws = withSkip((...args) => { @@ -628,7 +635,7 @@ class Assertions { message: '`t.notThrows()` must be called with a function', values: [formatWithLabel('Called with:', fn)] })); - return; + return false; } try { @@ -640,10 +647,11 @@ class Assertions { actualStack: error.stack, values: [formatWithLabel('Function threw:', error)] })); - return; + return false; } pass(); + return true; }); this.notThrowsAsync = withSkip((nonThrower, message) => { @@ -714,7 +722,7 @@ class Assertions { message: '`t.snapshot()` can only be used in tests', improperUsage: true })); - return; + return false; } let message; @@ -752,30 +760,43 @@ class Assertions { improperUsage.expectedVersion = error.expectedVersion; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'snapshot', message: message || 'Could not compare snapshot', improperUsage })); + return false; } if (result.pass) { - return pass(); + pass(); + return true; } if (result.actual) { - return fail(new AssertionError({ - assertion: 'snapshot', - message: message || 'Did not match snapshot', - values: [formatDescriptorDiff(result.actual, result.expected, {invert: true})] - })); + fail( + new AssertionError({ + assertion: 'snapshot', + message: message || 'Did not match snapshot', + values: [ + formatDescriptorDiff(result.actual, result.expected, { + invert: true + }) + ] + }) + ); + return false; } // This can only occur in CI environments. - return fail(new AssertionError({ - assertion: 'snapshot', - message: message || 'No snapshot available — new snapshots are not created in CI environments' - })); + fail( + new AssertionError({ + assertion: 'snapshot', + message: message || 'No snapshot available — new snapshots are not created in CI environments' + }) + ); + + return false; }); this.truthy = withSkip((actual, message) => { @@ -784,15 +805,18 @@ class Assertions { } if (actual) { - return pass(); + pass(); + return true; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'truthy', message, operator: '!!', values: [formatWithLabel('Value is not truthy:', actual)] })); + + return false; }); this.falsy = withSkip((actual, message) => { @@ -801,15 +825,17 @@ class Assertions { } if (actual) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'falsy', message, operator: '!', values: [formatWithLabel('Value is not falsy:', actual)] })); + return false; } - return pass(); + pass(); + return true; }); this.true = withSkip((actual, message) => { @@ -818,14 +844,17 @@ class Assertions { } if (actual === true) { - return pass(); + pass(); + return true; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'true', message, values: [formatWithLabel('Value is not `true`:', actual)] })); + + return false; }); this.false = withSkip((actual, message) => { @@ -834,14 +863,17 @@ class Assertions { } if (actual === false) { - return pass(); + pass(); + return true; } - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'false', message, values: [formatWithLabel('Value is not `false`:', actual)] })); + + return false; }); this.regex = withSkip((string, regex, message) => { @@ -850,25 +882,27 @@ class Assertions { } if (typeof string !== 'string') { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); + return false; } if (!(regex instanceof RegExp)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'regex', improperUsage: true, message: '`t.regex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); + return false; } if (!regex.test(string)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'regex', message, values: [ @@ -876,9 +910,11 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); + return false; } - return pass(); + pass(); + return true; }); this.notRegex = withSkip((string, regex, message) => { @@ -887,25 +923,27 @@ class Assertions { } if (typeof string !== 'string') { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a string', values: [formatWithLabel('Called with:', string)] })); + return false; } if (!(regex instanceof RegExp)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notRegex', improperUsage: true, message: '`t.notRegex()` must be called with a regular expression', values: [formatWithLabel('Called with:', regex)] })); + return false; } if (regex.test(string)) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'notRegex', message, values: [ @@ -913,9 +951,11 @@ class Assertions { formatWithLabel('Regular expression:', regex) ] })); + return false; } - return pass(); + pass(); + return true; }); if (powerAssert === undefined) { @@ -925,15 +965,17 @@ class Assertions { } if (!actual) { - return fail(new AssertionError({ + fail(new AssertionError({ assertion: 'assert', message, operator: '!!', values: [formatWithLabel('Value is not truthy:', actual)] })); + return false; } - return pass(); + pass(); + return true; }); } else { this.assert = withSkip(withPowerAssert( diff --git a/test-tap/assert.js b/test-tap/assert.js index b055cd6e0..13232e5d9 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -12,26 +12,26 @@ const snapshotManager = require('../lib/snapshot-manager'); const HelloMessage = require('./fixture/hello-message'); let lastFailure = null; +let lastPassed = false; const AssertionsBase = class extends assert.Assertions { constructor(overwrites = {}) { super({ - pass: () => true, + pass: () => { + lastPassed = true; + }, pending: promise => { - return promise.then(() => - true - , error => { + promise.then(() => { + lastPassed = true; + }, error => { lastFailure = error; }); }, fail: error => { lastFailure = error; - return false; - }, - skip: () => {}, - experiments: { - likeAssertion: true }, + skip: () => { }, + experiments: {}, ...overwrites }); } @@ -144,8 +144,10 @@ function eventuallyFails(t, fn) { */ function passes(t, fn) { + lastPassed = false; lastFailure = null; - if (fn()) { + fn(); + if (lastPassed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -154,9 +156,10 @@ function passes(t, fn) { function eventuallyPasses(t, fn) { return add(() => { + lastPassed = false; lastFailure = null; - return fn().then(passed => { - if (passed) { + return fn().then(() => { + if (lastPassed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -167,27 +170,30 @@ function eventuallyPasses(t, fn) { test('.pass()', t => { passes(t, () => { - return assertions.pass(); + const result = assertions.pass(); + assertions.true(result); }); passes(t, () => { const {pass} = assertions; - return pass(); + const result = pass(); + assertions.true(result); }); t.end(); }); test('.fail()', t => { + const results = []; failsWith(t, () => { - return assertions.fail(); + results.push(assertions.fail()); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - return assertions.fail('my message'); + results.push(assertions.fail('my message')); }, { assertion: 'fail', message: 'my message' @@ -195,14 +201,14 @@ test('.fail()', t => { failsWith(t, () => { const {fail} = assertions; - return fail(); + results.push(fail()); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - return assertions.fail(null); + assertions.fail(null); }, { assertion: 'fail', improperUsage: true, @@ -212,125 +218,156 @@ test('.fail()', t => { formatted: /null/ }] }); + for (const result of results) { + t.is(result, false); + } t.end(); }); test('.is()', t => { passes(t, () => { - return assertions.is('foo', 'foo'); + const result = assertions.is('foo', 'foo'); + assertions.true(result); }); passes(t, () => { const {is} = assertions; - return is('foo', 'foo'); + const result = is('foo', 'foo'); + assertions.true(result); }); passes(t, () => { - return assertions.is('', ''); + const result = assertions.is('', ''); + assertions.true(result); }); passes(t, () => { - return assertions.is(true, true); + const result = assertions.is(true, true); + assertions.true(result); }); passes(t, () => { - return assertions.is(false, false); + const result = assertions.is(false, false); + assertions.true(result); }); passes(t, () => { - return assertions.is(null, null); + const result = assertions.is(null, null); + assertions.true(result); }); passes(t, () => { - return assertions.is(undefined, undefined); + const result = assertions.is(undefined, undefined); + assertions.true(result); }); passes(t, () => { - return assertions.is(1, 1); + const result = assertions.is(1, 1); + assertions.true(result); }); passes(t, () => { - return assertions.is(0, 0); + const result = assertions.is(0, 0); + assertions.true(result); }); passes(t, () => { - return assertions.is(-0, -0); + const result = assertions.is(-0, -0); + assertions.true(result); }); passes(t, () => { - return assertions.is(Number.NaN, Number.NaN); + const result = assertions.is(Number.NaN, Number.NaN); + assertions.true(result); }); passes(t, () => { - return assertions.is(0 / 0, Number.NaN); + const result = assertions.is(0 / 0, Number.NaN); + assertions.true(result); }); passes(t, () => { const someRef = {foo: 'bar'}; - return assertions.is(someRef, someRef); + const result = assertions.is(someRef, someRef); + assertions.true(result); }); fails(t, () => { - return assertions.is(0, -0); + const result = assertions.is(0, -0); + assertions.false(result); }); fails(t, () => { - return assertions.is(0, false); + const result = assertions.is(0, false); + assertions.false(result); }); fails(t, () => { - return assertions.is('', false); + const result = assertions.is('', false); + assertions.false(result); }); fails(t, () => { - return assertions.is('0', 0); + const result = assertions.is('0', 0); + assertions.false(result); }); fails(t, () => { - assertions.is('17', 17); + const result = assertions.is('17', 17); + assertions.false(result); }); fails(t, () => { - assertions.is([1, 2], '1,2'); + const result = assertions.is([1, 2], '1,2'); + assertions.false(result); }); fails(t, () => { // eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins - assertions.is(new String('foo'), 'foo'); + const result = assertions.is(new String('foo'), 'foo'); + assertions.false(result); }); fails(t, () => { - assertions.is(null, undefined); + const result = assertions.is(null, undefined); + assertions.false(result); }); fails(t, () => { - assertions.is(null, false); + const result = assertions.is(null, false); + assertions.false(result); }); fails(t, () => { - assertions.is(undefined, false); + const result = assertions.is(undefined, false); + assertions.false(result); }); fails(t, () => { // eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins - assertions.is(new String('foo'), new String('foo')); + const result = assertions.is(new String('foo'), new String('foo')); + assertions.false(result); }); fails(t, () => { - assertions.is(0, null); + const result = assertions.is(0, null); + assertions.false(result); }); fails(t, () => { - assertions.is(0, Number.NaN); + const result = assertions.is(0, Number.NaN); + assertions.false(result); }); fails(t, () => { - assertions.is('foo', Number.NaN); + const result = assertions.is('foo', Number.NaN); + assertions.false(result); }); + const failureResults = []; failsWith(t, () => { - assertions.is({foo: 'bar'}, {foo: 'bar'}); + failureResults.push(assertions.is({foo: 'bar'}, {foo: 'bar'})); }, { assertion: 'is', message: '', @@ -343,7 +380,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is('foo', 'bar'); + failureResults.push(assertions.is('foo', 'bar')); }, { assertion: 'is', message: '', @@ -354,7 +391,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is('foo', 42); + failureResults.push(assertions.is('foo', 42)); }, { actual: 'foo', assertion: 'is', @@ -366,7 +403,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is('foo', 42, 'my message'); + failureResults.push(assertions.is('foo', 42, 'my message')); }, { assertion: 'is', message: 'my message', @@ -376,7 +413,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is(0, -0, 'my message'); + failureResults.push(assertions.is(0, -0, 'my message')); }, { assertion: 'is', message: 'my message', @@ -386,7 +423,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is(-0, 0, 'my message'); + failureResults.push(assertions.is(-0, 0, 'my message')); }, { assertion: 'is', message: 'my message', @@ -396,7 +433,7 @@ test('.is()', t => { }); failsWith(t, () => { - assertions.is(0, 0, null); + failureResults.push(assertions.is(0, 0, null)); }, { assertion: 'is', improperUsage: true, @@ -406,30 +443,36 @@ test('.is()', t => { formatted: /null/ }] }); + for (const result of failureResults) { + t.false(result); + } t.end(); }); test('.not()', t => { passes(t, () => { - assertions.not('foo', 'bar'); + const result = assertions.not('foo', 'bar'); + assertions.true(result); }); passes(t, () => { const {not} = assertions; - not('foo', 'bar'); + const result = not('foo', 'bar'); + assertions.true(result); }); + const failureResults = []; fails(t, () => { - assertions.not(Number.NaN, Number.NaN); + failureResults.push(assertions.not(Number.NaN, Number.NaN)); }); fails(t, () => { - assertions.not(0 / 0, Number.NaN); + failureResults.push(assertions.not(0 / 0, Number.NaN)); }); failsWith(t, () => { - assertions.not('foo', 'foo'); + failureResults.push(assertions.not('foo', 'foo')); }, { assertion: 'not', message: '', @@ -438,7 +481,7 @@ test('.not()', t => { }); failsWith(t, () => { - assertions.not('foo', 'foo', 'my message'); + failureResults.push(assertions.not('foo', 'foo', 'my message')); }, { assertion: 'not', message: 'my message', @@ -446,7 +489,7 @@ test('.not()', t => { }); failsWith(t, () => { - assertions.not(0, 1, null); + failureResults.push(assertions.not(0, 1, null)); }, { assertion: 'not', improperUsage: true, @@ -456,6 +499,9 @@ test('.not()', t => { formatted: /null/ }] }); + for (const result of failureResults) { + t.false(result); + } t.end(); }); From bd54aa458fb10457b854a34f4c7f100459d66039 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Sun, 20 Sep 2020 10:32:29 +0200 Subject: [PATCH 03/10] Fix return value of checkMessage() --- lib/assert.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/assert.js b/lib/assert.js index 8f2145f70..07321f438 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -295,7 +295,7 @@ class Assertions { const checkMessage = (assertion, message, powerAssert = false) => { const result = checkAssertionMessage(assertion, message); if (result === true) { - return this.true; + return true; } if (powerAssert) { From 66d2409561c7007f50b09f80e872870522571f99 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Sun, 20 Sep 2020 10:36:54 +0200 Subject: [PATCH 04/10] Return false when an illegal message is passed --- lib/assert.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 07321f438..a481c3cdc 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -313,7 +313,7 @@ class Assertions { this.fail = withSkip(message => { if (!checkMessage('fail', message)) { - return; + return false; } fail(new AssertionError({ @@ -325,7 +325,7 @@ class Assertions { this.is = withSkip((actual, expected, message) => { if (!checkMessage('is', message)) { - return; + return false; } if (Object.is(actual, expected)) { @@ -358,7 +358,7 @@ class Assertions { this.not = withSkip((actual, expected, message) => { if (!checkMessage('not', message)) { - return; + return false; } if (Object.is(actual, expected)) { @@ -377,7 +377,7 @@ class Assertions { this.deepEqual = withSkip((actual, expected, message) => { if (!checkMessage('deepEqual', message)) { - return; + return false; } const result = concordance.compare(actual, expected, concordanceOptions); @@ -400,7 +400,7 @@ class Assertions { this.notDeepEqual = withSkip((actual, expected, message) => { if (!checkMessage('notDeepEqual', message)) { - return; + return false; } const result = concordance.compare(actual, expected, concordanceOptions); @@ -421,7 +421,7 @@ class Assertions { this.like = withSkip((actual, selector, message) => { if (!checkMessage('like', message)) { - return; + return false; } if (!isLikeSelector(selector)) { @@ -625,7 +625,7 @@ class Assertions { this.notThrows = withSkip((fn, message) => { if (!checkMessage('notThrows', message)) { - return; + return false; } if (typeof fn !== 'function') { @@ -656,7 +656,7 @@ class Assertions { this.notThrowsAsync = withSkip((nonThrower, message) => { if (!checkMessage('notThrowsAsync', message)) { - return Promise.resolve(); + return Promise.resolve(false); } if (typeof nonThrower !== 'function' && !isPromise(nonThrower)) { @@ -739,7 +739,7 @@ class Assertions { } if (!checkMessage('snapshot', message)) { - return; + return false; } let result; @@ -801,7 +801,7 @@ class Assertions { this.truthy = withSkip((actual, message) => { if (!checkMessage('truthy', message)) { - return; + return false; } if (actual) { @@ -821,7 +821,7 @@ class Assertions { this.falsy = withSkip((actual, message) => { if (!checkMessage('falsy', message)) { - return; + return false; } if (actual) { @@ -840,7 +840,7 @@ class Assertions { this.true = withSkip((actual, message) => { if (!checkMessage('true', message)) { - return; + return false; } if (actual === true) { @@ -859,7 +859,7 @@ class Assertions { this.false = withSkip((actual, message) => { if (!checkMessage('false', message)) { - return; + return false; } if (actual === false) { @@ -878,7 +878,7 @@ class Assertions { this.regex = withSkip((string, regex, message) => { if (!checkMessage('regex', message)) { - return; + return false; } if (typeof string !== 'string') { @@ -919,7 +919,7 @@ class Assertions { this.notRegex = withSkip((string, regex, message) => { if (!checkMessage('notRegex', message)) { - return; + return false; } if (typeof string !== 'string') { @@ -961,7 +961,7 @@ class Assertions { if (powerAssert === undefined) { this.assert = withSkip((actual, message) => { if (!checkMessage('assert', message)) { - return; + return false; } if (!actual) { From 372b001138e970dde1f03fdd8feb2731cf82fa7f Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Sat, 17 Oct 2020 23:00:01 +0530 Subject: [PATCH 05/10] Returning boolean for notThrowsAsync() --- lib/assert.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index a481c3cdc..83dcc38ab 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -283,6 +283,7 @@ class Assertions { } fail(event.error); + return false; }, onSuccess: () => { pass(); @@ -666,14 +667,14 @@ class Assertions { message: '`t.notThrowsAsync()` must be called with a function or promise', values: [formatWithLabel('Called with:', nonThrower)] })); - return Promise.resolve(); + return Promise.resolve(false); } const handlePromise = (promise, wasReturned) => { // Create an error object to record the stack before it gets lost in the promise chain. const savedError = getErrorWithLongStackTrace(); // Handle "promise like" objects by casting to a real Promise. - const intermediate = Promise.resolve(promise).then(noop, error => { // eslint-disable-line promise/prefer-await-to-then + const intermediate = Promise.resolve(promise).then(() => true, error => { // eslint-disable-line promise/prefer-await-to-then throw new AssertionError({ assertion: 'notThrowsAsync', message, @@ -700,7 +701,7 @@ class Assertions { actualStack: error.stack, values: [formatWithLabel('Function threw:', error)] })); - return Promise.resolve(); + return Promise.resolve(false); } if (!isPromise(retval)) { @@ -709,7 +710,7 @@ class Assertions { message, values: [formatWithLabel('Function did not return a promise. Use `t.notThrows()` instead:', retval)] })); - return Promise.resolve(); + return Promise.resolve(false); } return handlePromise(retval, true); From 3d3a40e2b05cc03bc882904c3a3aa7d4f0a0cc17 Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Sat, 17 Oct 2020 23:00:30 +0530 Subject: [PATCH 06/10] Refactor assertion return testcases --- test-tap/assert.js | 163 ++++++++++++++++++--------------------------- 1 file changed, 63 insertions(+), 100 deletions(-) diff --git a/test-tap/assert.js b/test-tap/assert.js index 13232e5d9..7e0b4bf70 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -30,7 +30,7 @@ const AssertionsBase = class extends assert.Assertions { fail: error => { lastFailure = error; }, - skip: () => { }, + skip: () => {}, experiments: {}, ...overwrites }); @@ -73,6 +73,10 @@ function assertFailure(t, subset) { } else { t.same(lastFailure.values, []); } + + if ('returnValue' in subset) { + t.false(subset.returnValue); + } } let gathering = false; @@ -105,7 +109,11 @@ function add(fn) { function failsWith(t, fn, subset) { lastFailure = null; - fn(); + const returnValue = fn(); + if (returnValue !== undefined) { + subset.returnValue = returnValue; + } + assertFailure(t, subset); } @@ -120,8 +128,7 @@ function eventuallyFailsWith(t, fn, subset) { function fails(t, fn) { lastFailure = null; - fn(); - if (lastFailure) { + if (!fn() && lastFailure) { t.pass(); } else { t.fail('Expected assertion to fail'); @@ -146,8 +153,7 @@ function eventuallyFails(t, fn) { function passes(t, fn) { lastPassed = false; lastFailure = null; - fn(); - if (lastPassed) { + if (fn() && lastPassed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -170,30 +176,27 @@ function eventuallyPasses(t, fn) { test('.pass()', t => { passes(t, () => { - const result = assertions.pass(); - assertions.true(result); + return assertions.pass(); }); passes(t, () => { const {pass} = assertions; - const result = pass(); - assertions.true(result); + return pass(); }); t.end(); }); test('.fail()', t => { - const results = []; failsWith(t, () => { - results.push(assertions.fail()); + return assertions.fail(); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - results.push(assertions.fail('my message')); + return assertions.fail('my message'); }, { assertion: 'fail', message: 'my message' @@ -201,14 +204,14 @@ test('.fail()', t => { failsWith(t, () => { const {fail} = assertions; - results.push(fail()); + return fail(); }, { assertion: 'fail', message: 'Test failed via `t.fail()`' }); failsWith(t, () => { - assertions.fail(null); + return assertions.fail(null); }, { assertion: 'fail', improperUsage: true, @@ -218,156 +221,125 @@ test('.fail()', t => { formatted: /null/ }] }); - for (const result of results) { - t.is(result, false); - } t.end(); }); test('.is()', t => { passes(t, () => { - const result = assertions.is('foo', 'foo'); - assertions.true(result); + return assertions.is('foo', 'foo'); }); passes(t, () => { const {is} = assertions; - const result = is('foo', 'foo'); - assertions.true(result); + return is('foo', 'foo'); }); passes(t, () => { - const result = assertions.is('', ''); - assertions.true(result); + return assertions.is('', ''); }); passes(t, () => { - const result = assertions.is(true, true); - assertions.true(result); + return assertions.is(true, true); }); passes(t, () => { - const result = assertions.is(false, false); - assertions.true(result); + return assertions.is(false, false); }); passes(t, () => { - const result = assertions.is(null, null); - assertions.true(result); + return assertions.is(null, null); }); passes(t, () => { - const result = assertions.is(undefined, undefined); - assertions.true(result); + return assertions.is(undefined, undefined); }); passes(t, () => { - const result = assertions.is(1, 1); - assertions.true(result); + return assertions.is(1, 1); }); passes(t, () => { - const result = assertions.is(0, 0); - assertions.true(result); + return assertions.is(0, 0); }); passes(t, () => { - const result = assertions.is(-0, -0); - assertions.true(result); + return assertions.is(-0, -0); }); passes(t, () => { - const result = assertions.is(Number.NaN, Number.NaN); - assertions.true(result); + return assertions.is(Number.NaN, Number.NaN); }); passes(t, () => { - const result = assertions.is(0 / 0, Number.NaN); - assertions.true(result); + return assertions.is(0 / 0, Number.NaN); }); passes(t, () => { const someRef = {foo: 'bar'}; - const result = assertions.is(someRef, someRef); - assertions.true(result); + return assertions.is(someRef, someRef); }); fails(t, () => { - const result = assertions.is(0, -0); - assertions.false(result); + return assertions.is(0, -0); }); fails(t, () => { - const result = assertions.is(0, false); - assertions.false(result); + return assertions.is(0, false); }); fails(t, () => { - const result = assertions.is('', false); - assertions.false(result); + return assertions.is('', false); }); fails(t, () => { - const result = assertions.is('0', 0); - assertions.false(result); + return assertions.is('0', 0); }); fails(t, () => { - const result = assertions.is('17', 17); - assertions.false(result); + return assertions.is('17', 17); }); fails(t, () => { - const result = assertions.is([1, 2], '1,2'); - assertions.false(result); + return assertions.is([1, 2], '1,2'); }); fails(t, () => { // eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins - const result = assertions.is(new String('foo'), 'foo'); - assertions.false(result); + return assertions.is(new String('foo'), 'foo'); }); fails(t, () => { - const result = assertions.is(null, undefined); - assertions.false(result); + return assertions.is(null, undefined); }); fails(t, () => { - const result = assertions.is(null, false); - assertions.false(result); + return assertions.is(null, false); }); fails(t, () => { - const result = assertions.is(undefined, false); - assertions.false(result); + return assertions.is(undefined, false); }); fails(t, () => { // eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins - const result = assertions.is(new String('foo'), new String('foo')); - assertions.false(result); + return assertions.is(new String('foo'), new String('foo')); }); fails(t, () => { - const result = assertions.is(0, null); - assertions.false(result); + return assertions.is(0, null); }); fails(t, () => { - const result = assertions.is(0, Number.NaN); - assertions.false(result); + return assertions.is(0, Number.NaN); }); fails(t, () => { - const result = assertions.is('foo', Number.NaN); - assertions.false(result); + return assertions.is('foo', Number.NaN); }); - const failureResults = []; failsWith(t, () => { - failureResults.push(assertions.is({foo: 'bar'}, {foo: 'bar'})); + return assertions.is({foo: 'bar'}, {foo: 'bar'}); }, { assertion: 'is', message: '', @@ -380,7 +352,7 @@ test('.is()', t => { }); failsWith(t, () => { - failureResults.push(assertions.is('foo', 'bar')); + return assertions.is('foo', 'bar'); }, { assertion: 'is', message: '', @@ -391,7 +363,7 @@ test('.is()', t => { }); failsWith(t, () => { - failureResults.push(assertions.is('foo', 42)); + return assertions.is('foo', 42); }, { actual: 'foo', assertion: 'is', @@ -403,7 +375,7 @@ test('.is()', t => { }); failsWith(t, () => { - failureResults.push(assertions.is('foo', 42, 'my message')); + return assertions.is('foo', 42, 'my message'); }, { assertion: 'is', message: 'my message', @@ -413,7 +385,7 @@ test('.is()', t => { }); failsWith(t, () => { - failureResults.push(assertions.is(0, -0, 'my message')); + return assertions.is(0, -0, 'my message'); }, { assertion: 'is', message: 'my message', @@ -423,7 +395,7 @@ test('.is()', t => { }); failsWith(t, () => { - failureResults.push(assertions.is(-0, 0, 'my message')); + return assertions.is(-0, 0, 'my message'); }, { assertion: 'is', message: 'my message', @@ -433,7 +405,7 @@ test('.is()', t => { }); failsWith(t, () => { - failureResults.push(assertions.is(0, 0, null)); + return assertions.is(0, 0, null); }, { assertion: 'is', improperUsage: true, @@ -443,36 +415,30 @@ test('.is()', t => { formatted: /null/ }] }); - for (const result of failureResults) { - t.false(result); - } t.end(); }); test('.not()', t => { passes(t, () => { - const result = assertions.not('foo', 'bar'); - assertions.true(result); + return assertions.not('foo', 'bar'); }); passes(t, () => { const {not} = assertions; - const result = not('foo', 'bar'); - assertions.true(result); + return not('foo', 'bar'); }); - const failureResults = []; fails(t, () => { - failureResults.push(assertions.not(Number.NaN, Number.NaN)); + return assertions.not(Number.NaN, Number.NaN); }); fails(t, () => { - failureResults.push(assertions.not(0 / 0, Number.NaN)); + return assertions.not(0 / 0, Number.NaN); }); failsWith(t, () => { - failureResults.push(assertions.not('foo', 'foo')); + return assertions.not('foo', 'foo'); }, { assertion: 'not', message: '', @@ -481,7 +447,7 @@ test('.not()', t => { }); failsWith(t, () => { - failureResults.push(assertions.not('foo', 'foo', 'my message')); + return assertions.not('foo', 'foo', 'my message'); }, { assertion: 'not', message: 'my message', @@ -489,7 +455,7 @@ test('.not()', t => { }); failsWith(t, () => { - failureResults.push(assertions.not(0, 1, null)); + return assertions.not(0, 1, null); }, { assertion: 'not', improperUsage: true, @@ -499,9 +465,6 @@ test('.not()', t => { formatted: /null/ }] }); - for (const result of failureResults) { - t.false(result); - } t.end(); }); @@ -1651,17 +1614,17 @@ test('.notThrowsAsync()', gather(t => { }); })); -test('.notThrowsAsync() returns undefined for a fulfilled promise', t => { +test('.notThrowsAsync() returns true for a fulfilled promise', t => { return assertions.notThrowsAsync(Promise.resolve(Symbol(''))).then(actual => { - t.is(actual, undefined); + t.is(actual, true); }); }); -test('.notThrowsAsync() returns undefined for a fulfilled promise returned by the function', t => { +test('.notThrowsAsync() returns true for a fulfilled promise returned by the function', t => { return assertions.notThrowsAsync(() => { return Promise.resolve(Symbol('')); }).then(actual => { - t.is(actual, undefined); + t.is(actual, true); }); }); From 65b1852673fede9590b9c3007f9aac7930bdb2bd Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Mon, 19 Oct 2020 13:40:39 +0530 Subject: [PATCH 07/10] Update test-tap/assert.js Co-authored-by: Mark Wubben --- test-tap/assert.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test-tap/assert.js b/test-tap/assert.js index 7e0b4bf70..713a25f5d 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -153,7 +153,7 @@ function eventuallyFails(t, fn) { function passes(t, fn) { lastPassed = false; lastFailure = null; - if (fn() && lastPassed) { + if (fn() === true && lastPassed) { t.pass(); } else { t.ifError(lastFailure, 'Expected assertion to pass'); @@ -2192,4 +2192,3 @@ test('.assert()', t => { t.end(); }); - From bb6efc43e6d6342740548b19d3d429385c0a98a8 Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Mon, 19 Oct 2020 13:41:00 +0530 Subject: [PATCH 08/10] Update test-tap/assert.js Co-authored-by: Mark Wubben --- test-tap/assert.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-tap/assert.js b/test-tap/assert.js index 713a25f5d..dd4ff8d4c 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -128,7 +128,7 @@ function eventuallyFailsWith(t, fn, subset) { function fails(t, fn) { lastFailure = null; - if (!fn() && lastFailure) { + if (fn() === false && lastFailure) { t.pass(); } else { t.fail('Expected assertion to fail'); From 163a5c816812d6423c6470dcc8d2cd44aca50351 Mon Sep 17 00:00:00 2001 From: Aditya Subramanian Date: Mon, 19 Oct 2020 16:37:11 +0530 Subject: [PATCH 09/10] Test case fixes --- test-tap/assert.js | 245 ++++++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 112 deletions(-) diff --git a/test-tap/assert.js b/test-tap/assert.js index dd4ff8d4c..0063c044c 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -156,6 +156,7 @@ function passes(t, fn) { if (fn() === true && lastPassed) { t.pass(); } else { + lastFailure = new Error('Assertion failed'); t.ifError(lastFailure, 'Expected assertion to pass'); } } @@ -474,11 +475,11 @@ test('.deepEqual()', t => { // used to test deep object equality fails(t, () => { - assertions.deepEqual({a: false}, {a: 0}); + return assertions.deepEqual({a: false}, {a: 0}); }); passes(t, () => { - assertions.deepEqual({ + return assertions.deepEqual({ a: 'a', b: 'b' }, { @@ -489,11 +490,11 @@ test('.deepEqual()', t => { passes(t, () => { const {deepEqual} = assertions; - deepEqual({a: 'a', b: 'b'}, {b: 'b', a: 'a'}); + return deepEqual({a: 'a', b: 'b'}, {b: 'b', a: 'a'}); }); passes(t, () => { - assertions.deepEqual({ + return assertions.deepEqual({ a: 'a', b: 'b', c: { @@ -509,17 +510,17 @@ test('.deepEqual()', t => { }); fails(t, () => { - assertions.deepEqual([1, 2, 3], [1, 2, 3, 4]); + return assertions.deepEqual([1, 2, 3], [1, 2, 3, 4]); }); passes(t, () => { - assertions.deepEqual([1, 2, 3], [1, 2, 3]); + return assertions.deepEqual([1, 2, 3], [1, 2, 3]); }); fails(t, () => { const fnA = a => a; const fnB = a => a; - assertions.deepEqual(fnA, fnB); + return assertions.deepEqual(fnA, fnB); }); passes(t, () => { @@ -531,7 +532,7 @@ test('.deepEqual()', t => { const y2 = {x: x2}; x2.y = y2; - assertions.deepEqual(x1, x2); + return assertions.deepEqual(x1, x2); }); passes(t, () => { @@ -542,7 +543,7 @@ test('.deepEqual()', t => { const x = new Foo(1); const y = new Foo(1); - assertions.deepEqual(x, y); + return assertions.deepEqual(x, y); }); fails(t, () => { @@ -557,11 +558,11 @@ test('.deepEqual()', t => { const x = new Foo(1); const y = new Bar(1); - assertions.deepEqual(x, y); + return assertions.deepEqual(x, y); }); fails(t, () => { - assertions.deepEqual({ + return assertions.deepEqual({ a: 'a', b: 'b', c: { @@ -577,73 +578,76 @@ test('.deepEqual()', t => { }); fails(t, () => { - assertions.deepEqual({}, []); + return assertions.deepEqual({}, []); }); fails(t, () => { - assertions.deepEqual({0: 'a', 1: 'b'}, ['a', 'b']); + return assertions.deepEqual({0: 'a', 1: 'b'}, ['a', 'b']); }); fails(t, () => { - assertions.deepEqual({a: 1}, {a: 1, b: undefined}); + return assertions.deepEqual({a: 1}, {a: 1, b: undefined}); }); fails(t, () => { - assertions.deepEqual(new Date('1972-08-01'), null); + return assertions.deepEqual(new Date('1972-08-01'), null); }); fails(t, () => { - assertions.deepEqual(new Date('1972-08-01'), undefined); + return assertions.deepEqual(new Date('1972-08-01'), undefined); }); passes(t, () => { - assertions.deepEqual(new Date('1972-08-01'), new Date('1972-08-01')); + return assertions.deepEqual(new Date('1972-08-01'), new Date('1972-08-01')); }); passes(t, () => { - assertions.deepEqual({x: new Date('1972-08-01')}, {x: new Date('1972-08-01')}); + return assertions.deepEqual({x: new Date('1972-08-01')}, {x: new Date('1972-08-01')}); }); fails(t, () => { - assertions.deepEqual(() => {}, () => {}); + return assertions.deepEqual(() => {}, () => {}); }); passes(t, () => { - assertions.deepEqual(undefined, undefined); - assertions.deepEqual({x: undefined}, {x: undefined}); - assertions.deepEqual({x: [undefined]}, {x: [undefined]}); + const result1 = assertions.deepEqual(undefined, undefined); + const result2 = assertions.deepEqual({x: undefined}, {x: undefined}); + const result3 = assertions.deepEqual({x: [undefined]}, {x: [undefined]}); + return result1 && result2 && result3; }); passes(t, () => { - assertions.deepEqual(null, null); - assertions.deepEqual({x: null}, {x: null}); - assertions.deepEqual({x: [null]}, {x: [null]}); + const result1 = assertions.deepEqual(null, null); + const result2 = assertions.deepEqual({x: null}, {x: null}); + const result3 = assertions.deepEqual({x: [null]}, {x: [null]}); + return result1 && result2 && result3; }); passes(t, () => { - assertions.deepEqual(0, 0); - assertions.deepEqual(1, 1); - assertions.deepEqual(3.14, 3.14); + const result1 = assertions.deepEqual(0, 0); + const result2 = assertions.deepEqual(1, 1); + const result3 = assertions.deepEqual(3.14, 3.14); + return result1 && result2 && result3; }); fails(t, () => { - assertions.deepEqual(0, 1); + return assertions.deepEqual(0, 1); }); fails(t, () => { - assertions.deepEqual(1, -1); + return assertions.deepEqual(1, -1); }); fails(t, () => { - assertions.deepEqual(3.14, 2.72); + return assertions.deepEqual(3.14, 2.72); }); fails(t, () => { - assertions.deepEqual({0: 'a', 1: 'b'}, ['a', 'b']); + return assertions.deepEqual({0: 'a', 1: 'b'}, ['a', 'b']); }); passes(t, () => { - assertions.deepEqual( + return assertions.deepEqual( [ {foo: {z: 100, y: 200, x: 300}}, 'bar', @@ -660,14 +664,14 @@ test('.deepEqual()', t => { }); passes(t, () => { - assertions.deepEqual( + return assertions.deepEqual( {x: {a: 1, b: 2}, y: {c: 3, d: 4}}, {y: {d: 4, c: 3}, x: {b: 2, a: 1}} ); }); passes(t, () => { - assertions.deepEqual( + return assertions.deepEqual( renderer.create(React.createElement(HelloMessage, {name: 'Sindre'})).toJSON(), React.createElement('div', null, 'Hello ', React.createElement('mark', null, 'Sindre')) ); @@ -676,33 +680,33 @@ test('.deepEqual()', t => { // Regression test end here passes(t, () => { - assertions.deepEqual({a: 'a'}, {a: 'a'}); + return assertions.deepEqual({a: 'a'}, {a: 'a'}); }); passes(t, () => { - assertions.deepEqual(['a', 'b'], ['a', 'b']); + return assertions.deepEqual(['a', 'b'], ['a', 'b']); }); fails(t, () => { - assertions.deepEqual({a: 'a'}, {a: 'b'}); + return assertions.deepEqual({a: 'a'}, {a: 'b'}); }); fails(t, () => { - assertions.deepEqual(['a', 'b'], ['a', 'a']); + return assertions.deepEqual(['a', 'b'], ['a', 'a']); }); fails(t, () => { - assertions.deepEqual([['a', 'b'], 'c'], [['a', 'b'], 'd']); + return assertions.deepEqual([['a', 'b'], 'c'], [['a', 'b'], 'd']); }); fails(t, () => { const circular = ['a', 'b']; circular.push(circular); - assertions.deepEqual([circular, 'c'], [circular, 'd']); + return assertions.deepEqual([circular, 'c'], [circular, 'd']); }); failsWith(t, () => { - assertions.deepEqual('foo', 'bar'); + return assertions.deepEqual('foo', 'bar'); }, { assertion: 'deepEqual', message: '', @@ -711,7 +715,7 @@ test('.deepEqual()', t => { }); failsWith(t, () => { - assertions.deepEqual('foo', 42); + return assertions.deepEqual('foo', 42); }, { assertion: 'deepEqual', message: '', @@ -720,7 +724,7 @@ test('.deepEqual()', t => { }); failsWith(t, () => { - assertions.deepEqual('foo', 42, 'my message'); + return assertions.deepEqual('foo', 42, 'my message'); }, { assertion: 'deepEqual', message: 'my message', @@ -728,7 +732,7 @@ test('.deepEqual()', t => { }); failsWith(t, () => { - assertions.deepEqual({}, {}, null); + return assertions.deepEqual({}, {}, null); }, { assertion: 'deepEqual', improperUsage: true, @@ -744,22 +748,22 @@ test('.deepEqual()', t => { test('.notDeepEqual()', t => { passes(t, () => { - assertions.notDeepEqual({a: 'a'}, {a: 'b'}); + return assertions.notDeepEqual({a: 'a'}, {a: 'b'}); }); passes(t, () => { const {notDeepEqual} = assertions; - notDeepEqual({a: 'a'}, {a: 'b'}); + return notDeepEqual({a: 'a'}, {a: 'b'}); }); passes(t, () => { - assertions.notDeepEqual(['a', 'b'], ['c', 'd']); + return assertions.notDeepEqual(['a', 'b'], ['c', 'd']); }); const actual = {a: 'a'}; const expected = {a: 'a'}; failsWith(t, () => { - assertions.notDeepEqual(actual, expected); + return assertions.notDeepEqual(actual, expected); }, { actual, assertion: 'notDeepEqual', @@ -770,7 +774,7 @@ test('.notDeepEqual()', t => { }); failsWith(t, () => { - assertions.notDeepEqual(['a', 'b'], ['a', 'b'], 'my message'); + return assertions.notDeepEqual(['a', 'b'], ['a', 'b'], 'my message'); }, { assertion: 'notDeepEqual', message: 'my message', @@ -778,7 +782,7 @@ test('.notDeepEqual()', t => { }); failsWith(t, () => { - assertions.notDeepEqual({}, [], null); + return assertions.notDeepEqual({}, [], null); }, { assertion: 'notDeepEqual', improperUsage: true, @@ -794,11 +798,11 @@ test('.notDeepEqual()', t => { test('.like()', t => { fails(t, () => { - assertions.like({a: false}, {a: 0}); + return assertions.like({a: false}, {a: 0}); }); passes(t, () => { - assertions.like({ + return assertions.like({ a: 'a', b: 'b' }, { @@ -809,11 +813,11 @@ test('.like()', t => { passes(t, () => { const {like} = assertions; - like({a: 'a', b: 'b'}, {b: 'b', a: 'a'}); + return like({a: 'a', b: 'b'}, {b: 'b', a: 'a'}); }); passes(t, () => { - assertions.like({ + return assertions.like({ a: 'a', b: 'b', c: { @@ -831,11 +835,11 @@ test('.like()', t => { }); fails(t, () => { - assertions.like([1, 2, 3], [1, 2, 3, 4]); + return assertions.like([1, 2, 3], [1, 2, 3, 4]); }); fails(t, () => { - assertions.like({ + return assertions.like({ a: [1, 2, 3] }, { a: [1, 2, 3, 4] @@ -843,7 +847,7 @@ test('.like()', t => { }); passes(t, () => { - assertions.like({ + return assertions.like({ a: [1, 2, 3], x: 'x' }, { @@ -862,19 +866,19 @@ test('.like()', t => { a: 'a' }; - assertions.like(actual, likePattern); + return assertions.like(actual, likePattern); }); fails(t, () => { const fnA = a => a; const fnB = a => a; - assertions.like(fnA, fnB); + return assertions.like(fnA, fnB); }); fails(t, () => { const fnA = a => a; const fnB = a => a; - assertions.like({ + return assertions.like({ fn: fnA }, { fn: fnB @@ -893,59 +897,59 @@ test('.like()', t => { const x = new Foo(1); const y = new Bar(1); - assertions.like(x, y); + return assertions.like(x, y); }); passes(t, () => { - assertions.like({a: 'a'}, {a: 'a'}); + return assertions.like({a: 'a'}, {a: 'a'}); }); passes(t, () => { - assertions.like({a: 'a', b: 'b'}, {a: 'a'}); + return assertions.like({a: 'a', b: 'b'}, {a: 'a'}); }); passes(t, () => { - assertions.like({ab: ['a', 'b']}, {ab: ['a', 'b']}); + return assertions.like({ab: ['a', 'b']}, {ab: ['a', 'b']}); }); passes(t, () => { - assertions.like({ab: ['a', 'b'], c: 'c'}, {ab: ['a', 'b']}); + return assertions.like({ab: ['a', 'b'], c: 'c'}, {ab: ['a', 'b']}); }); fails(t, () => { - assertions.like({a: 'a'}, {a: 'b'}); + return assertions.like({a: 'a'}, {a: 'b'}); }); fails(t, () => { - assertions.like({a: 'a', b: 'b'}, {a: 'b'}); + return assertions.like({a: 'a', b: 'b'}, {a: 'b'}); }); fails(t, () => { - assertions.like({ab: ['a', 'b']}, {ab: ['a', 'a']}); + return assertions.like({ab: ['a', 'b']}, {ab: ['a', 'a']}); }); fails(t, () => { - assertions.like({ab: ['a', 'b'], c: 'c'}, {ab: ['a', 'a']}); + return assertions.like({ab: ['a', 'b'], c: 'c'}, {ab: ['a', 'a']}); }); fails(t, () => { - assertions.like([['a', 'b'], 'c'], [['a', 'b'], 'd']); + return assertions.like([['a', 'b'], 'c'], [['a', 'b'], 'd']); }); fails(t, () => { const circular = ['a', 'b']; circular.push(circular); - assertions.like([circular, 'c'], [circular, 'd']); + return assertions.like([circular, 'c'], [circular, 'd']); }); fails(t, () => { const circular = ['a', 'b']; circular.push(circular); - assertions.like({xc: [circular, 'c']}, {xc: [circular, 'd']}); + return assertions.like({xc: [circular, 'c']}, {xc: [circular, 'd']}); }); failsWith(t, () => { - assertions.like({a: 'a'}, {}); + return assertions.like({a: 'a'}, {}); }, { assertion: 'like', message: '`t.like()` selector must be a non-empty object', @@ -953,7 +957,7 @@ test('.like()', t => { }); failsWith(t, () => { - assertions.like('foo', 'bar'); + return assertions.like('foo', 'bar'); }, { assertion: 'like', message: '`t.like()` selector must be a non-empty object', @@ -966,7 +970,7 @@ test('.like()', t => { }; likePattern.circular = likePattern; - assertions.like({}, likePattern); + return assertions.like({}, likePattern); }, { assertion: 'like', message: '`t.like()` selector must not contain circular references', @@ -974,7 +978,7 @@ test('.like()', t => { }); failsWith(t, () => { - assertions.like({}, {}, null); + return assertions.like({}, {}, null); }, { assertion: 'like', improperUsage: true, @@ -986,7 +990,7 @@ test('.like()', t => { }); failsWith(t, () => { - assertions.like({a: 'foo', b: 'irrelevant'}, {a: 'bar'}); + return assertions.like({a: 'foo', b: 'irrelevant'}, {a: 'bar'}); }, { assertion: 'like', message: '', @@ -1053,6 +1057,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw new Error('foo'); }); + return true; }); // Passes because the correct error is thrown. @@ -1061,6 +1066,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw err; }, {is: err}); + return true; }); // Fails because the thrown value is not an error @@ -1069,6 +1075,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw object; }, {is: object}); + return false; }); // Fails because the thrown value is not the right one @@ -1077,6 +1084,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw err; }, {is: {}}); + return false; }); // Passes because the correct error is thrown. @@ -1084,6 +1092,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw new TypeError(); // eslint-disable-line unicorn/error-message }, {name: 'TypeError'}); + return true; }); // Fails because the thrown value is not an error @@ -1092,6 +1101,7 @@ test('.throws()', gather(t => { const err = {name: 'Bob'}; throw err; }, {name: 'Bob'}); + return false; }); // Fails because the thrown value is not the right one @@ -1099,6 +1109,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw new Error('foo'); }, {name: 'TypeError'}); + return false; }); // Passes because the correct error is thrown. @@ -1108,6 +1119,7 @@ test('.throws()', gather(t => { err.code = 'ERR_TEST'; throw err; }, {code: 'ERR_TEST'}); + return true; }); // Passes because the correct error is thrown. @@ -1117,6 +1129,7 @@ test('.throws()', gather(t => { err.code = 42; throw err; }, {code: 42}); + return true; }); // Fails because the thrown value is not the right one @@ -1126,6 +1139,7 @@ test('.throws()', gather(t => { err.code = 'ERR_NOPE'; throw err; }, {code: 'ERR_TEST'}); + return false; }); fails(t, () => { @@ -1134,6 +1148,7 @@ test('.throws()', gather(t => { err.code = 1; throw err; }, {code: 42}); + return false; }); // Regression test for https://github.com/avajs/ava/issues/1676 @@ -1141,6 +1156,7 @@ test('.throws()', gather(t => { assertions.throws(() => { throw new Error('foo'); }, false); + return false; }); // Regression test for https://github.com/avajs/ava/issues/1676 @@ -1148,22 +1164,19 @@ test('.throws()', gather(t => { assertions.throws(() => { throw new Error('foo'); }, null); + return true; }); passes(t, () => { assertions.throws(() => { throw new Error('foo'); }, undefined); - }); - - passes(t, async () => { - await assertions.throwsAsync(() => { - return Promise.reject(new Error('foo')); - }, undefined); + return true; }); failsWith(t, () => { assertions.throws(() => {}, null, null); + return false; }, { assertion: 'throws', improperUsage: true, @@ -1252,6 +1265,8 @@ test('.throwsAsync()', gather(t => { formatted: /null/ }] }); + + eventuallyPasses(t, () => assertions.throwsAsync(() => Promise.reject(new Error('foo')))); })); test('.throwsAsync() returns the rejection reason of promise', t => { @@ -1513,12 +1528,12 @@ test('.throwsAsync() fails if passed null expectation with disableNullExpectatio test('.notThrows()', gather(t => { // Passes because the function doesn't throw passes(t, () => { - assertions.notThrows(() => {}); + return assertions.notThrows(() => {}); }); passes(t, () => { const {notThrows} = assertions; - notThrows(() => {}); + return notThrows(() => {}); }); // Fails because the function throws. @@ -1689,24 +1704,24 @@ test('.snapshot()', t => { const assertions = setup('passes'); passes(t, () => { - assertions.snapshot({foo: 'bar'}); + return assertions.snapshot({foo: 'bar'}); }); passes(t, () => { const {snapshot} = assertions; - snapshot({foo: 'bar'}); + return snapshot({foo: 'bar'}); }); passes(t, () => { - assertions.snapshot({foo: 'bar'}, {id: 'fixed id'}, 'message not included in snapshot report'); + return assertions.snapshot({foo: 'bar'}, {id: 'fixed id'}, 'message not included in snapshot report'); }); passes(t, () => { - assertions.snapshot(React.createElement(HelloMessage, {name: 'Sindre'})); + return assertions.snapshot(React.createElement(HelloMessage, {name: 'Sindre'})); }); passes(t, () => { - assertions.snapshot(renderer.create(React.createElement(HelloMessage, {name: 'Sindre'})).toJSON()); + return assertions.snapshot(renderer.create(React.createElement(HelloMessage, {name: 'Sindre'})).toJSON()); }); } @@ -1755,7 +1770,7 @@ test('.snapshot()', t => { assertions.snapshot(renderer.create(React.createElement(HelloMessage, {name: 'Sindre'})).toJSON()); } else { passes(t, () => { - assertions.snapshot(React.createElement('div', null, 'Hello ', React.createElement('mark', null, 'Sindre'))); + return assertions.snapshot(React.createElement('div', null, 'Hello ', React.createElement('mark', null, 'Sindre'))); }); } } @@ -1829,14 +1844,16 @@ test('.truthy()', t => { }); passes(t, () => { - assertions.truthy(1); - assertions.truthy(true); + const result1 = assertions.truthy(1); + const result2 = assertions.truthy(true); + return result1 && result2; }); passes(t, () => { const {truthy} = assertions; - truthy(1); - truthy(true); + const result1 = truthy(1); + const result2 = truthy(true); + return result1 && result2; }); failsWith(t, () => { @@ -1874,14 +1891,16 @@ test('.falsy()', t => { }); passes(t, () => { - assertions.falsy(0); - assertions.falsy(false); + const result1 = assertions.falsy(0); + const result2 = assertions.falsy(false); + return result1 && result2; }); passes(t, () => { const {falsy} = assertions; - falsy(0); - falsy(false); + const result1 = falsy(0); + const result2 = falsy(false); + return result1 && result2; }); failsWith(t, () => { @@ -1933,12 +1952,12 @@ test('.true()', t => { }); passes(t, () => { - assertions.true(true); + return assertions.true(true); }); passes(t, () => { const {true: trueFn} = assertions; - trueFn(true); + return trueFn(true); }); failsWith(t, () => { @@ -1990,12 +2009,12 @@ test('.false()', t => { }); passes(t, () => { - assertions.false(false); + return assertions.false(false); }); passes(t, () => { const {false: falseFn} = assertions; - falseFn(false); + return falseFn(false); }); failsWith(t, () => { @@ -2015,12 +2034,12 @@ test('.false()', t => { test('.regex()', t => { passes(t, () => { - assertions.regex('abc', /^abc$/); + return assertions.regex('abc', /^abc$/); }); passes(t, () => { const {regex} = assertions; - regex('abc', /^abc$/); + return regex('abc', /^abc$/); }); failsWith(t, () => { @@ -2083,12 +2102,12 @@ test('.regex() fails if passed a bad value', t => { test('.notRegex()', t => { passes(t, () => { - assertions.notRegex('abc', /def/); + return assertions.notRegex('abc', /def/); }); passes(t, () => { const {notRegex} = assertions; - notRegex('abc', /def/); + return notRegex('abc', /def/); }); failsWith(t, () => { @@ -2168,14 +2187,16 @@ test('.assert()', t => { }); passes(t, () => { - assertions.assert(1); - assertions.assert(true); + const result1 = assertions.assert(1); + const result2 = assertions.assert(true); + return result1 && result2; }); passes(t, () => { const {assert} = assertions; - assert(1); - assert(true); + const result1 = assert(1); + const result2 = assert(true); + return result1 && result2; }); failsWith(t, () => { From e3dd4eeec1c778559614485edb75064322a22acf Mon Sep 17 00:00:00 2001 From: "Jason T. Bradshaw" Date: Tue, 13 Oct 2020 18:20:36 -0500 Subject: [PATCH 10/10] cherry-picking relavent changes from jasontbradshaw:assertions-return-booleans(ca0c975d808efac7b88cdafc12c6794b258aba24) --- index.d.ts | 162 +++++++++++++++++++++++++++++++++------------ test-tap/assert.js | 58 ++++++++-------- 2 files changed, 148 insertions(+), 72 deletions(-) diff --git a/index.d.ts b/index.d.ts index a1a8fa595..899b23070 100644 --- a/index.d.ts +++ b/index.d.ts @@ -39,40 +39,68 @@ export type SnapshotOptions = { }; export interface Assertions { - /** Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy). Comes with power-assert. */ + /** + * Assert that `actual` is + * [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), + * returning Boolean indicating whether the assertion passes. Comes with + * power-assert. + */ assert: AssertAssertion; - /** Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to `expected`. */ + /** + * Assert that `actual` is [deeply + * equal](https://github.com/concordancejs/concordance#comparison-details) to + * `expected`, returning Boolean indicating whether the assertion passes. + */ deepEqual: DeepEqualAssertion; - /** Assert that `actual` is like `expected`. */ + /** + * Assert that `value` is like `selector`, returning Boolean indicating + * whether the assertion passes. + */ like: LikeAssertion; - /** Fail the test. */ + /** Fail the test, always returning `false`. */ fail: FailAssertion; - /** Assert that `actual` is strictly false. */ + /** + * Assert that `actual` is strictly false, returning Boolean indicating + * whether the assertion passes. + */ false: FalseAssertion; - /** Assert that `actual` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy). */ + /** + * Assert that `actual` is + * [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), returning + * Boolean whether the assertion passes. + */ falsy: FalsyAssertion; /** * Assert that `actual` is [the same - * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`. + * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) + * as `expected`, returning Boolean indicating whether the assertion passes. */ is: IsAssertion; /** * Assert that `actual` is not [the same - * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`. + * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) + * as `expected`, returning Boolean indicating whether the assertion passes. */ not: NotAssertion; - /** Assert that `actual` is not [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to `expected`. */ + /** + * Assert that `actual` is not [deeply + * equal](https://github.com/concordancejs/concordance#comparison-details) to + * `expected`, returning Boolean indicating whether the assertion passes. + */ notDeepEqual: NotDeepEqualAssertion; - /** Assert that `string` does not match the regular expression. */ + /** + * Assert that `string` does not match the regular expression, returning + * Boolean indicating whether the assertion passes. + */ notRegex: NotRegexAssertion; /** Assert that the function does not throw. */ @@ -81,10 +109,13 @@ export interface Assertions { /** Assert that the async function does not throw, or that the promise does not reject. Must be awaited. */ notThrowsAsync: NotThrowsAsyncAssertion; - /** Count a passing assertion. */ + /** Count a passing assertion, always returning `true`. */ pass: PassAssertion; - /** Assert that `string` matches the regular expression. */ + /** + * Assert that `string` matches the regular expression, returning Boolean + * indicating whether the assertion passes. + */ regex: RegexAssertion; /** @@ -105,56 +136,82 @@ export interface Assertions { */ throwsAsync: ThrowsAsyncAssertion; - /** Assert that `actual` is strictly true. */ + /** + * Assert that `actual` is strictly true, returning Boolean indicating + * whether the assertion passes. + */ true: TrueAssertion; - /** Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy). */ + /** + * Assert that `actual` is + * [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), + * returning Boolean indicating whether the assertion passes. + */ truthy: TruthyAssertion; } export interface AssertAssertion { - /** Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy). Comes with power-assert. */ - (actual: any, message?: string): void; + /** + * Assert that `actual` is + * [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), + * returning Boolean indicating whether the assertion passes. Comes with + * power-assert. + */ + (actual: any, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, message?: string): void; } export interface DeepEqualAssertion { - /** Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to `expected`. */ - (actual: ValueType, expected: ValueType, message?: string): void; + /** + * Assert that `actual` is [deeply + * equal](https://github.com/concordancejs/concordance#comparison-details) to + * `expected`, returning Boolean indicating whether the assertion passes. + */ + (actual: ValueType, expected: ValueType, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, expected: any, message?: string): void; } export interface LikeAssertion { - /** Assert that `value` is like `selector`. */ - (value: any, selector: Record, message?: string): void; + /** + * Assert that `value` is like `selector`, returning Boolean indicating + * whether the assertion passes. + */ + (value: any, selector: Record, message?: string): boolean; /** Skip this assertion. */ skip(value: any, selector: any, message?: string): void; } export interface FailAssertion { - /** Fail the test. */ - (message?: string): void; + /** Fail the test, always returning `false`. */ + (message?: string): false; /** Skip this assertion. */ skip(message?: string): void; } export interface FalseAssertion { - /** Assert that `actual` is strictly false. */ - (actual: any, message?: string): void; + /** + * Assert that `actual` is strictly false, returning Boolean indicating + * whether the assertion passes. + */ + (actual: any, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, message?: string): void; } export interface FalsyAssertion { - /** Assert that `actual` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy). */ - (actual: any, message?: string): void; + /** + * Assert that `actual` is + * [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), returning + * Boolean whether the assertion passes. + */ + (actual: any, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, message?: string): void; @@ -163,9 +220,10 @@ export interface FalsyAssertion { export interface IsAssertion { /** * Assert that `actual` is [the same - * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`. + * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) + * as `expected`, returning Boolean indicating whether the assertion passes. */ - (actual: ValueType, expected: ValueType, message?: string): void; + (actual: ValueType, expected: ValueType, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, expected: any, message?: string): void; @@ -174,25 +232,33 @@ export interface IsAssertion { export interface NotAssertion { /** * Assert that `actual` is not [the same - * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`. + * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) + * as `expected`, returning Boolean indicating whether the assertion passes. */ - (actual: ValueType, expected: ValueType, message?: string): void; + (actual: ValueType, expected: ValueType, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, expected: any, message?: string): void; } export interface NotDeepEqualAssertion { - /** Assert that `actual` is not [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to `expected`. */ - (actual: ValueType, expected: ValueType, message?: string): void; + /** + * Assert that `actual` is not [deeply + * equal](https://github.com/concordancejs/concordance#comparison-details) to + * `expected`, returning Boolean indicating whether the assertion passes. + */ + (actual: ValueType, expected: ValueType, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, expected: any, message?: string): void; } export interface NotRegexAssertion { - /** Assert that `string` does not match the regular expression. */ - (string: string, regex: RegExp, message?: string): void; + /** + * Assert that `string` does not match the regular expression, returning + * Boolean indicating whether the assertion passes. + */ + (string: string, regex: RegExp, message?: string): boolean; /** Skip this assertion. */ skip(string: string, regex: RegExp, message?: string): void; @@ -218,16 +284,19 @@ export interface NotThrowsAsyncAssertion { } export interface PassAssertion { - /** Count a passing assertion. */ - (message?: string): void; + /** Count a passing assertion, always returning `true`. */ + (message?: string): true; /** Skip this assertion. */ skip(message?: string): void; } export interface RegexAssertion { - /** Assert that `string` matches the regular expression. */ - (string: string, regex: RegExp, message?: string): void; + /** + * Assert that `string` matches the regular expression, returning Boolean + * indicating whether the assertion passes. + */ + (string: string, regex: RegExp, message?: string): boolean; /** Skip this assertion. */ skip(string: string, regex: RegExp, message?: string): void; @@ -296,16 +365,23 @@ export interface ThrowsAsyncAssertion { } export interface TrueAssertion { - /** Assert that `actual` is strictly true. */ - (actual: any, message?: string): void; + /** + * Assert that `actual` is strictly true, returning Boolean indicating + * whether the assertion passes. + */ + (actual: any, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, message?: string): void; } export interface TruthyAssertion { - /** Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy). */ - (actual: any, message?: string): void; + /** + * Assert that `actual` is + * [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), + * returning Boolean indicating whether the assertion passes. + */ + (actual: any, message?: string): boolean; /** Skip this assertion. */ skip(actual: any, message?: string): void; @@ -433,7 +509,7 @@ export interface CbExecutionContext extends ExecutionContext< end(error?: any): void; } -export type ImplementationResult = PromiseLike | Subscribable | void; +export type ImplementationResult = PromiseLike | Subscribable | boolean | void; export type Implementation = (t: ExecutionContext) => ImplementationResult; export type CbImplementation = (t: CbExecutionContext) => ImplementationResult; diff --git a/test-tap/assert.js b/test-tap/assert.js index 0063c044c..eda890a2e 100644 --- a/test-tap/assert.js +++ b/test-tap/assert.js @@ -1826,7 +1826,7 @@ test('.snapshot()', t => { test('.truthy()', t => { failsWith(t, () => { - assertions.truthy(0); + return assertions.truthy(0); }, { assertion: 'truthy', message: '', @@ -1835,7 +1835,7 @@ test('.truthy()', t => { }); failsWith(t, () => { - assertions.truthy(false, 'my message'); + return assertions.truthy(false, 'my message'); }, { assertion: 'truthy', message: 'my message', @@ -1857,7 +1857,7 @@ test('.truthy()', t => { }); failsWith(t, () => { - assertions.truthy(true, null); + return assertions.truthy(true, null); }, { assertion: 'truthy', improperUsage: true, @@ -1873,7 +1873,7 @@ test('.truthy()', t => { test('.falsy()', t => { failsWith(t, () => { - assertions.falsy(1); + return assertions.falsy(1); }, { assertion: 'falsy', message: '', @@ -1882,7 +1882,7 @@ test('.falsy()', t => { }); failsWith(t, () => { - assertions.falsy(true, 'my message'); + return assertions.falsy(true, 'my message'); }, { assertion: 'falsy', message: 'my message', @@ -1904,7 +1904,7 @@ test('.falsy()', t => { }); failsWith(t, () => { - assertions.falsy(false, null); + return assertions.falsy(false, null); }, { assertion: 'falsy', improperUsage: true, @@ -1920,7 +1920,7 @@ test('.falsy()', t => { test('.true()', t => { failsWith(t, () => { - assertions.true(1); + return assertions.true(1); }, { assertion: 'true', message: '', @@ -1928,7 +1928,7 @@ test('.true()', t => { }); failsWith(t, () => { - assertions.true(0); + return assertions.true(0); }, { assertion: 'true', message: '', @@ -1936,7 +1936,7 @@ test('.true()', t => { }); failsWith(t, () => { - assertions.true(false); + return assertions.true(false); }, { assertion: 'true', message: '', @@ -1944,7 +1944,7 @@ test('.true()', t => { }); failsWith(t, () => { - assertions.true('foo', 'my message'); + return assertions.true('foo', 'my message'); }, { assertion: 'true', message: 'my message', @@ -1961,7 +1961,7 @@ test('.true()', t => { }); failsWith(t, () => { - assertions.true(true, null); + return assertions.true(true, null); }, { assertion: 'true', improperUsage: true, @@ -1977,7 +1977,7 @@ test('.true()', t => { test('.false()', t => { failsWith(t, () => { - assertions.false(0); + return assertions.false(0); }, { assertion: 'false', message: '', @@ -1985,7 +1985,7 @@ test('.false()', t => { }); failsWith(t, () => { - assertions.false(1); + return assertions.false(1); }, { assertion: 'false', message: '', @@ -1993,7 +1993,7 @@ test('.false()', t => { }); failsWith(t, () => { - assertions.false(true); + return assertions.false(true); }, { assertion: 'false', message: '', @@ -2001,7 +2001,7 @@ test('.false()', t => { }); failsWith(t, () => { - assertions.false('foo', 'my message'); + return assertions.false('foo', 'my message'); }, { assertion: 'false', message: 'my message', @@ -2018,7 +2018,7 @@ test('.false()', t => { }); failsWith(t, () => { - assertions.false(false, null); + return assertions.false(false, null); }, { assertion: 'false', improperUsage: true, @@ -2043,7 +2043,7 @@ test('.regex()', t => { }); failsWith(t, () => { - assertions.regex('foo', /^abc$/); + return assertions.regex('foo', /^abc$/); }, { assertion: 'regex', message: '', @@ -2054,7 +2054,7 @@ test('.regex()', t => { }); failsWith(t, () => { - assertions.regex('foo', /^abc$/, 'my message'); + return assertions.regex('foo', /^abc$/, 'my message'); }, { assertion: 'regex', message: 'my message', @@ -2065,7 +2065,7 @@ test('.regex()', t => { }); failsWith(t, () => { - assertions.regex('foo', /^abc$/, null); + return assertions.regex('foo', /^abc$/, null); }, { assertion: 'regex', improperUsage: true, @@ -2081,7 +2081,7 @@ test('.regex()', t => { test('.regex() fails if passed a bad value', t => { failsWith(t, () => { - assertions.regex(42, /foo/); + return assertions.regex(42, /foo/); }, { assertion: 'regex', improperUsage: true, @@ -2090,7 +2090,7 @@ test('.regex() fails if passed a bad value', t => { }); failsWith(t, () => { - assertions.regex('42', {}); + return assertions.regex('42', {}); }, { assertion: 'regex', message: '`t.regex()` must be called with a regular expression', @@ -2111,7 +2111,7 @@ test('.notRegex()', t => { }); failsWith(t, () => { - assertions.notRegex('abc', /abc/); + return assertions.notRegex('abc', /abc/); }, { assertion: 'notRegex', message: '', @@ -2122,7 +2122,7 @@ test('.notRegex()', t => { }); failsWith(t, () => { - assertions.notRegex('abc', /abc/, 'my message'); + return assertions.notRegex('abc', /abc/, 'my message'); }, { assertion: 'notRegex', message: 'my message', @@ -2133,7 +2133,7 @@ test('.notRegex()', t => { }); failsWith(t, () => { - assertions.notRegex('abc', /abc/, null); + return assertions.notRegex('abc', /abc/, null); }, { assertion: 'notRegex', improperUsage: true, @@ -2149,7 +2149,7 @@ test('.notRegex()', t => { test('.notRegex() fails if passed a bad value', t => { failsWith(t, () => { - assertions.notRegex(42, /foo/); + return assertions.notRegex(42, /foo/); }, { assertion: 'notRegex', message: '`t.notRegex()` must be called with a string', @@ -2157,7 +2157,7 @@ test('.notRegex() fails if passed a bad value', t => { }); failsWith(t, () => { - assertions.notRegex('42', {}); + return assertions.notRegex('42', {}); }, { assertion: 'notRegex', message: '`t.notRegex()` must be called with a regular expression', @@ -2169,7 +2169,7 @@ test('.notRegex() fails if passed a bad value', t => { test('.assert()', t => { failsWith(t, () => { - assertions.assert(0); + return assertions.assert(0); }, { assertion: 'assert', message: '', @@ -2178,7 +2178,7 @@ test('.assert()', t => { }); failsWith(t, () => { - assertions.assert(false, 'my message'); + return assertions.assert(false, 'my message'); }, { assertion: 'assert', message: 'my message', @@ -2200,7 +2200,7 @@ test('.assert()', t => { }); failsWith(t, () => { - assertions.assert(null, null); + return assertions.assert(null, null); }, { assertion: 'assert', improperUsage: true,