From 5c343dbf78098ca8673737eecdcf8b002eb5fbd2 Mon Sep 17 00:00:00 2001 From: tim Date: Sat, 10 Jun 2017 12:13:37 +0200 Subject: [PATCH 1/3] show output for .throws() when promise is resolved --- lib/assert.js | 16 +++++++++++----- test/assert.js | 47 +++++++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 28b8ae09c..f3bde67c7 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -41,7 +41,6 @@ function wrapAssertions(callbacks) { const fail = callbacks.fail; const noop = () => {}; - const makeNoop = () => noop; const makeRethrow = reason => () => { throw reason; }; @@ -119,6 +118,7 @@ function wrapAssertions(callbacks) { }, throws(fn, err, message) { + const assertion = 'throws'; let promise; if (isPromise(fn)) { promise = fn; @@ -126,7 +126,7 @@ function wrapAssertions(callbacks) { promise = observableToPromise(fn); } else if (typeof fn !== 'function') { fail(this, new AssertionError({ - assertion: 'throws', + assertion, improperUsage: true, message: '`t.throws()` must be called with a function, Promise, or Observable', values: [formatAssertError.formatWithLabel('Called with:', fn)] @@ -174,10 +174,16 @@ function wrapAssertions(callbacks) { if (promise) { // Record stack before it gets lost in the promise chain. const stack = getStack(); - const intermediate = promise.then(makeNoop, makeRethrow).then(fn => test(fn, stack)); + const intermediate = promise.then(value => { + throw new AssertionError({ + assertion, + message: 'Expected promise to be rejected, but it was resolved instead', + values: [formatAssertError.formatWithLabel('Resolved with:', value)] + }); + }, reason => test(makeRethrow(reason), stack)); + pending(this, intermediate); - // Don't reject the returned promise, even if the assertion fails. - return intermediate.catch(noop); + return intermediate; } try { diff --git a/test/assert.js b/test/assert.js index 64bb9bee9..99073031d 100644 --- a/test/assert.js +++ b/test/assert.js @@ -27,27 +27,31 @@ function failsWith(t, fn, subset) { return; } - t.is(lastFailure.assertion, subset.assertion); - t.is(lastFailure.message, subset.message); - t.is(lastFailure.name, 'AssertionError'); - t.is(lastFailure.operator, subset.operator); - if (subset.statements) { - t.is(lastFailure.statements.length, subset.statements.length); - lastFailure.statements.forEach((s, i) => { - t.is(s[0], subset.statements[i][0]); - t.match(s[1], subset.statements[i][1]); + testFailResults(t, lastFailure, subset); +} + +function testFailResults(t, actual, expected) { + t.is(actual.assertion, expected.assertion); + t.is(actual.message, expected.message); + t.is(actual.name, 'AssertionError'); + t.is(actual.operator, expected.operator); + if (expected.statements) { + t.is(actual.statements.length, expected.statements.length); + actual.statements.forEach((s, i) => { + t.is(s[0], expected.statements[i][0]); + t.match(s[1], expected.statements[i][1]); }); } else { - t.same(lastFailure.statements, []); + t.same(actual.statements, []); } - if (subset.values) { - t.is(lastFailure.values.length, subset.values.length); - lastFailure.values.forEach((s, i) => { - t.is(s.label, subset.values[i].label); - t.match(s.formatted, subset.values[i].formatted); + if (expected.values) { + t.is(actual.values.length, expected.values.length); + actual.values.forEach((s, i) => { + t.is(s.label, expected.values[i].label); + t.match(s.formatted, expected.values[i].formatted); }); } else { - t.same(lastFailure.values, []); + t.same(actual.values, []); } } @@ -648,6 +652,17 @@ test('.throws() fails if passed a bad value', t => { t.end(); }); +test('promise .throws() fails when promise is resolved', t => { + return assertions.throws(Promise.resolve('foo')) + .catch(err => { + testFailResults(t, err, { + assertion: 'throws', + message: 'Expected promise to be rejected, but it was resolved instead', + values: [{label: 'Resolved with:', formatted: formatValue('foo')}] + }); + }); +}); + test('.notThrows()', t => { passes(t, () => { assertions.notThrows(() => {}); From f164a956a95e7bbf5ce4461cc066e06fa37bb1f3 Mon Sep 17 00:00:00 2001 From: tim Date: Sat, 10 Jun 2017 20:00:19 +0200 Subject: [PATCH 2/3] changes after review (rewrite test) --- lib/assert.js | 8 +++---- test/assert.js | 63 ++++++++++++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index f3bde67c7..b15568109 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -118,7 +118,6 @@ function wrapAssertions(callbacks) { }, throws(fn, err, message) { - const assertion = 'throws'; let promise; if (isPromise(fn)) { promise = fn; @@ -126,7 +125,7 @@ function wrapAssertions(callbacks) { promise = observableToPromise(fn); } else if (typeof fn !== 'function') { fail(this, new AssertionError({ - assertion, + assertion: 'throws', improperUsage: true, message: '`t.throws()` must be called with a function, Promise, or Observable', values: [formatAssertError.formatWithLabel('Called with:', fn)] @@ -176,14 +175,15 @@ function wrapAssertions(callbacks) { const stack = getStack(); const intermediate = promise.then(value => { throw new AssertionError({ - assertion, + assertion: 'throws', message: 'Expected promise to be rejected, but it was resolved instead', values: [formatAssertError.formatWithLabel('Resolved with:', value)] }); }, reason => test(makeRethrow(reason), stack)); pending(this, intermediate); - return intermediate; + // Don't reject the returned promise, even if the assertion fails. + return intermediate.catch(noop); } try { diff --git a/test/assert.js b/test/assert.js index 99073031d..f0c67d0db 100644 --- a/test/assert.js +++ b/test/assert.js @@ -12,49 +12,55 @@ const assertions = assert.wrapAssertions({ lastPassed = true; }, - pending() {}, + pending(_, promise) { + promise.catch(err => { + lastFailure = err; + }); + }, fail(_, error) { lastFailure = error; } }); -function failsWith(t, fn, subset) { - lastFailure = null; +function failsWith(t, fn, subset, failure) { + lastFailure = failure; fn(); if (!lastFailure) { t.fail('Expected assertion to fail'); return; } - testFailResults(t, lastFailure, subset); -} - -function testFailResults(t, actual, expected) { - t.is(actual.assertion, expected.assertion); - t.is(actual.message, expected.message); - t.is(actual.name, 'AssertionError'); - t.is(actual.operator, expected.operator); - if (expected.statements) { - t.is(actual.statements.length, expected.statements.length); - actual.statements.forEach((s, i) => { - t.is(s[0], expected.statements[i][0]); - t.match(s[1], expected.statements[i][1]); + t.is(lastFailure.assertion, subset.assertion); + t.is(lastFailure.message, subset.message); + t.is(lastFailure.name, 'AssertionError'); + t.is(lastFailure.operator, subset.operator); + if (subset.statements) { + t.is(lastFailure.statements.length, subset.statements.length); + lastFailure.statements.forEach((s, i) => { + t.is(s[0], subset.statements[i][0]); + t.match(s[1], subset.statements[i][1]); }); } else { - t.same(actual.statements, []); + t.same(lastFailure.statements, []); } - if (expected.values) { - t.is(actual.values.length, expected.values.length); - actual.values.forEach((s, i) => { - t.is(s.label, expected.values[i].label); - t.match(s.formatted, expected.values[i].formatted); + if (subset.values) { + t.is(lastFailure.values.length, subset.values.length); + lastFailure.values.forEach((s, i) => { + t.is(s.label, subset.values[i].label); + t.match(s.formatted, subset.values[i].formatted); }); } else { - t.same(actual.values, []); + t.same(lastFailure.values, []); } } +function eventuallyFailsWith(t, promise, subset) { + return promise.then(() => { + failsWith(t, () => {}, subset, lastFailure); + }); +} + function fails(t, fn) { lastFailure = null; fn(); @@ -653,13 +659,10 @@ test('.throws() fails if passed a bad value', t => { }); test('promise .throws() fails when promise is resolved', t => { - return assertions.throws(Promise.resolve('foo')) - .catch(err => { - testFailResults(t, err, { - assertion: 'throws', - message: 'Expected promise to be rejected, but it was resolved instead', - values: [{label: 'Resolved with:', formatted: formatValue('foo')}] - }); + return eventuallyFailsWith(t, assertions.throws(Promise.resolve('foo')), { + assertion: 'throws', + message: 'Expected promise to be rejected, but it was resolved instead', + values: [{label: 'Resolved with:', formatted: formatValue('foo')}] }); }); From 06d0da5b91aecc127e7f0ea4fcaa361746a238fb Mon Sep 17 00:00:00 2001 From: tim Date: Sun, 11 Jun 2017 17:37:11 +0200 Subject: [PATCH 3/3] assert changes in test after review --- test/assert.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/assert.js b/test/assert.js index f0c67d0db..67d8bb7bd 100644 --- a/test/assert.js +++ b/test/assert.js @@ -23,9 +23,7 @@ const assertions = assert.wrapAssertions({ } }); -function failsWith(t, fn, subset, failure) { - lastFailure = failure; - fn(); +function assertFailure(t, subset) { if (!lastFailure) { t.fail('Expected assertion to fail'); return; @@ -55,9 +53,16 @@ function failsWith(t, fn, subset, failure) { } } +function failsWith(t, fn, subset) { + lastFailure = null; + fn(); + assertFailure(t, subset); +} + function eventuallyFailsWith(t, promise, subset) { + lastFailure = null; return promise.then(() => { - failsWith(t, () => {}, subset, lastFailure); + assertFailure(t, subset); }); }