From a2638b671dc251c8e2818df7e5506f918af4ab86 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Sat, 26 Aug 2023 21:06:21 +0000 Subject: [PATCH 1/4] sinon: Add helper function findCall() update readme quite a bit --- README.md | 356 +++++++++++++++++++++++++++++++++++++++++++- lib/sinon.mjs | 7 + test/sinon.test.mjs | 29 ++++ 3 files changed, 390 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 66d2b43..7d80dc1 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,8 @@ Not only does eltro allow you to use any assertion library of your own choosing, * `assert.notMatch(value, [message])`: Check if value does not match RegExp test. * `assert.isFulfilled(promise, [message])`: Assert the promise resolves. * `assert.isRejected(promise, [message])`: Assert the promise gets rejects. - - # Asynchronous Code + +# Asynchronous Code Eltro supports any type of asynchronous code testing. It can either be done by adding a parameter to the function (usually done) that gets called once the tests done but eltro also supports promises. @@ -133,6 +133,30 @@ t.test('async test', async function() { }) ``` +# Spying and stubbing + +Inspired by sinon js, this library comes with pre-built simple sinon-like style spy() and stub() + +```node +import { assert, spy, stub } from 'eltro' + +let myFunc = spy() +let myStub = stub() + +myFunc(1) +myFunc(2) +myFunc(3) +myStub.returns('world') +let out = myStub('hello') + +assert.strictEqual(out, 'world') +assert.strictEqual(myFunc.getCall(0), 1) +assert.strictEqual(myFunc.getCall(1), 2) +assert.strictEqual(myFunc.getCall(2), 3) +assert.strictEqual(myFunc.callCount, 3) +assert.strictEqual(myStub.callCount, 1) +``` + # Api ### t.test(message, func) @@ -227,6 +251,70 @@ t.describe('#anotherTest()', function() { }) ``` +### t.beforeEach(func) + +Queue up the `func` to run before each test or groups within current active group. + +```node +import { Eltro as t, assert} from 'eltro' + +t.beforeEach(function() { + // Prepare something before each of the following tests +}) + +t.describe('#myTest()', function() { + t.beforeEach(function() { + // Runs before every test in this group + }) + + t.test('true should always be true', function() { + assert.strictEqual(true, true) + }) +}) + +t.describe('#anotherTest()', function() { + t.beforeEach(function() { + // Runs before every test in this group + }) + + t.test('false should always be false', function() { + assert.strictEqual(false, false) + }) +}) +``` + +### t.afterEach(func) + +Queue up the `func` to run after every test or groups within current active group. + +```node +import { Eltro as t, assert} from 'eltro' + +t.afterEach(function() { + // After we finish each individual test below, this gets run +}) + +t.describe('#myTest()', function() { + t.afterEach(function() { + // Runs after each text in this group + }) + + t.test('true should always be true', function() { + assert.strictEqual(true, true) + }) +}) + +t.describe('#anotherTest()', function() { + t.afterEach(function() { + // Runs after each text in this group + }) + + t.test('false should always be false', function() { + assert.strictEqual(false, false) + }) +}) +``` + ### t.only() Eltro supports exclusivity when running tests. When specified, only tests marked with only will be run. @@ -305,3 +393,267 @@ or like so: ```node t.timeout(5000).test('A long test', async function() { ... }) ``` + +# Assert + +Eltro comes with an extended version of node's built-in assertion library. +You can start using them by simply importing it with eltro test runner: + +```node +import { assert } from 'eltro' +``` + + +### assert.notOk(value[, message]) + +Tests if value is a falsy value using `Boolean(value) == false` + +```node +assert.notOk(false) // ok +assert.notOk(null) // ok +assert.notOk(undefined) // ok +assert.notOk([]) // throws +``` + +### assert.match(value, test[, message]) + +Test if the string value has a regex match of test + +```node +assert.match('asdf', /a/) // ok +assert.match('hello world', /hello/) // ok +assert.match('something', /else/) // throws +``` + +### assert.notMatch(value, test[, message]) + +Test if the string value does not regex match the test + +```node +assert.notMatch('asdf', /b/) // ok +assert.notMatch('something', /else/) // ok +assert.notMatch('hello world', /hello/) // throws +``` + +### assert.isFulfilled(promise[, message]) + +Tests to make sure the promise gets fulfilled successfully and +returns the final result. + +```node +await assert.isFulfilled(Promise.resolve(null)) // ok +await assert.isFulfilled(() => { throw new Error() }) // throws +``` + +### assert.isRejected(promise[, message]) + +Tests to make sure the promise gets rejected and returns the error +or value that was rejected + +```node +let val = await assert.isRejected(Promise.reject('asdf')) // ok +assert.strictEqual(val, 'asdf') + +let err = await assert.isRejected(() => { throw new Error('hello') }) // ok +assert.strictEqual(err.message, 'hello') +``` + +# Sinon-like spy()/stub() + +Using sinon-inspired mechanics for spying on calls as well as being able +to stub existing functionality, eltro comes with a handy little copy-cat. + +Functionality-wise, the difference between spy() and stub() are none. +Both will do the exact same thing, the naming differention is simply to allow +the resulting code to speak about its purpose. + +To create a stub or a spy, simply import it and call it like so: + +```node +import { spy, stub } from 'eltro' + +let spying = spy() +let fn = stub() +``` + +Each call to stub or spy is an array list of the passed-on arguments: + +```node +let spying = spy() +spying('hello', 'world') + +assert.strictEqual(spying.lastCall[0], 'hello') +assert.strictEqual(spying.lastCall[1], 'world') +``` + +### lastCall + +Returns the last call that was made to sinon and stub: + +```node +let spying = spy() +spying('a') +spying('b') +spying('c') + +assert.strictEqual(spying.lastCall[0], 'c') +``` + +### called + +Boolean variable that gets flipped once it's called at least once + +```node +let spying = spy() +assert.strictEqual(spying.called, false) +spying('a') +assert.strictEqual(spying.called, true) +spying('b') +spying('c') +assert.strictEqual(spying.called, true) +``` + +### callCount + +The number of times it's been called + +```node +let spying = spy() +assert.strictEqual(spying.callCount, 0) +spying('a') +assert.strictEqual(spying.callCount, 1) +spying('b') +spying('c') +assert.strictEqual(spying.callCount, 3) +``` + +### returns(data) + +Specifies what value the stub or spy should return when it gets called. + +```node +let fn = stub() +fn.returns('a') + +assert.strictEqual(fn(), 'a') +assert.strictEqual(fn(), 'a') +``` + +### throws(data) + +Specifies what value the stub or spy should throw when it gets called. + +```node +let fn = stub() +fn.throws(new Error('b')) + +try { + fn() +} catch (err) { + assert.strictEqual(fn(), 'b') +} +``` + +### resolves(data) + +Specifies what value the stub or spy should return wrapped in a promise. + +```node +let fn = stub() +fn.resolves('a') + +fn().then(function(data) { + assert.strictEqual(data, 'a') +}) +``` + +### rejects(data) + +Specifies what value the stub or spy should reject, wrapped in a promise. + +```node +let fn = stub() +fn.rejects('nope') + +fn().catch(function(data) { + assert.strictEqual(data, 'nope') +}) +``` + +### returnWith(fn) + +Specify custom function to be called whenever the stub or spy gets called. + +```node +let fn = stub() +fn.returnWith(function(a) { + if (a === 'a') return true + return false +}) + +assert.strictEqual(fn(), false) +assert.strictEqual(fn('b'), false) +assert.strictEqual(fn('a'), true) +assert.strictEqual(fn.callCount, 3) +``` + +### getCall(index) +### getCallN(num) + +Get a specific call. The `getCall` gets a zero-based index call while the `getCallN(num)` gets the more natural number call + +```node +let spying = spy() +spying('a') +spying('b') +spying('c') +assert.strictEqual(spying.getCall(0), 'a') +assert.strictEqual(spying.getCall(1), 'b') +assert.strictEqual(spying.getCallN(1), 'a') +assert.strictEqual(spying.getCallN(2), 'b') +``` + +### onCall(index) +### onCallN(num) + +Overwrite behavior for a specific numbered call. Just like with getCall/getCallN, the onCall is zero-indexed number of the call you want to specify custom behavior while onCallN is the more natural number of the call you want to specify custom behavior. + +Note, when called with null, it specifies the default behavior. + +```node +let fnOne = stub() +let fnTwo = stub() + +fnOne.onCall(1).returns('b') + .onCall().returns('a') + +fnTwo.onCallN(2).returns('two') + .onCallN().returns('one') + +assert.strictEqual(fnOne(), 'a') +assert.strictEqual(fnOne(), 'b') +assert.strictEqual(fnOne(), 'a') + +assert.strictEqual(fnTwo(), 'one') +assert.strictEqual(fnTwo(), 'two') +assert.strictEqual(fnTwo(), 'one') +``` + +### findCall(fn) + +Search for the first call when `fn(call)` returns `true`. Essentially a filter to search for a specific call that matches whatever call you're searching for. + + +```node +let evnt = stub() + +evnt('onclick', 'one') +evnt('onerror', 'two') +evnt('something', 'three') +evnt('onpress', 'four') +evnt('else', 'five') + +let foundPressCall = evnt.findCall(function(call) { return call[0] === 'onpress' }) +assert.strictEqual(foundPressCall[0], 'onpress') +assert.strictEqual(foundPressCall[1], 'four') +``` diff --git a/lib/sinon.mjs b/lib/sinon.mjs index 616fac8..0623163 100644 --- a/lib/sinon.mjs +++ b/lib/sinon.mjs @@ -35,6 +35,13 @@ export function stub(returnFunc = null) { func.called = false func.callCount = 0 + func.findCall = function(fn) { + for (let call of calls) { + if (fn(call)) return call + } + return null + } + func.getCall = function(i) { return calls[i] } diff --git a/test/sinon.test.mjs b/test/sinon.test.mjs index ead55e2..bfa6951 100644 --- a/test/sinon.test.mjs +++ b/test/sinon.test.mjs @@ -96,6 +96,35 @@ import { spy, stub } from '../index.mjs' assert.strictEqual(spyer.thirdCall[0], assertThirdArgs[0]) assert.strictEqual(spyer.thirdCall[1], assertThirdArgs[1]) }) + + + t.test('should support searching for a call', function() { + const assertFirstArgs = 'asdf' + const assertSecondArgs = { a: 1 } + const assertThirdArgs = [{ b: 1 }, { c: 2 }] + let spyer = tester() + assert.notOk(spyer.called) + + spyer(assertFirstArgs) + spyer(assertSecondArgs) + spyer(assertThirdArgs[0], assertThirdArgs[1]) + + let call = spyer.findCall((args) => args[0] === assertSecondArgs) + assert.strictEqual(spyer.secondCall, call) + assert.strictEqual(call[0], assertSecondArgs) + + call = spyer.findCall((args) => args[0].b === assertThirdArgs[0].b) + assert.strictEqual(spyer.thirdCall, call) + assert.strictEqual(call[0], assertThirdArgs[0]) + assert.strictEqual(call[1], assertThirdArgs[1]) + + call = spyer.findCall((args) => typeof args[0] === 'string') + assert.strictEqual(spyer.firstCall, call) + assert.strictEqual(call[0], assertFirstArgs) + + call = spyer.findCall(() => false) + assert.strictEqual(call, null) + }) }) }) From c2b95f62a85f7fa8b4b4a1f29b0688f32b9037d2 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Sat, 26 Aug 2023 21:10:56 +0000 Subject: [PATCH 2/4] Update readme --- README.md | 100 ++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 7d80dc1..173571f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ $ mkdir test Next in your favourite editor, create `test/test.mjs`: -```node +```javascript import { Eltro as t, assert} from 'eltro' t.describe('Array', function() { @@ -81,7 +81,7 @@ Eltro supports any type of asynchronous code testing. It can either be done by a Example of testing using done: -```node +```javascript import { Eltro as t, assert} from 'eltro' t.describe('User', function() { @@ -99,7 +99,7 @@ t.describe('User', function() { Alternatively, just use the done() callback directly (which will handle an error argument, if it exists): -```node +```javascript import { Eltro as t, assert} from 'eltro' t.describe('User', function() { @@ -114,7 +114,7 @@ t.describe('User', function() { Or another alternative is to use promises and return a promise directly: -```node +```javascript import { Eltro as t, assert} from 'eltro' t.test('should complete this test', function(done) { @@ -126,7 +126,7 @@ t.test('should complete this test', function(done) { Which works well with `async/await` like so: -```node +```javascript t.test('async test', async function() { let user = await User.find({ username: 'test' }) assert.ok(user) @@ -137,7 +137,7 @@ t.test('async test', async function() { Inspired by sinon js, this library comes with pre-built simple sinon-like style spy() and stub() -```node +```javascript import { assert, spy, stub } from 'eltro' let myFunc = spy() @@ -167,7 +167,7 @@ Queue up the `func` as a test with the specified messagt. In case you wanna describe a bunch of tests, you can add them inside `func` and it will have the specified `message` prepended before every test: -```node +```javascript import { Eltro as t, assert} from 'eltro' function someFunction() { return true } @@ -191,7 +191,7 @@ will output: Queue up the `func` to run before any test or groups within current active group. -```node +```javascript import { Eltro as t, assert} from 'eltro' t.before(function() { @@ -223,7 +223,7 @@ t.describe('#anotherTest()', function() { Queue up the `func` to run after any test or groups within current active group. -```node +```javascript import { Eltro as t, assert} from 'eltro' t.after(function() { @@ -255,7 +255,7 @@ t.describe('#anotherTest()', function() { Queue up the `func` to run before each test or groups within current active group. -```node +```javascript import { Eltro as t, assert} from 'eltro' t.beforeEach(function() { @@ -287,7 +287,7 @@ t.describe('#anotherTest()', function() { Queue up the `func` to run after every test or groups within current active group. -```node +```javascript import { Eltro as t, assert} from 'eltro' t.afterEach(function() { @@ -321,7 +321,7 @@ Eltro supports exclusivity when running tests. When specified, only tests marked You can do exclusivity on tests by adding `.only()` in front of describe, after or before the test like so: -```node +```javascript t.only().describe('Only these will run', function() { t.test('this one', function() { assert.strictEqual(true, true) }) t.test('and this one', function() { assert.strictEqual(true, true) }) @@ -330,7 +330,7 @@ t.only().describe('Only these will run', function() { You can also put it on individual test like so -```node +```javascript t.test('Only run this test', function() { assert.strictEqual(true, true) }).only() @@ -338,7 +338,7 @@ t.test('Only run this test', function() { or like so: -```node +```javascript t.only().test('Only run this test', function() { assert.strictEqual(true, true) }) @@ -348,7 +348,7 @@ t.only().test('Only run this test', function() { You can skip tests easily by adding `.skip()` before describe, before or after the test like so: -```node +```javascript t.skip().describe('None of these will run', function() { t.test('not this', function() { assert.strictEqual(true, true) }) t.test('or this one', function() { assert.strictEqual(true, true) }) @@ -357,7 +357,7 @@ t.skip().describe('None of these will run', function() { You can also do it on individual tests like so: -```node +```javascript t.test('Skip due to something being broken', function() { BrokenFunction() }).skip() @@ -365,7 +365,7 @@ t.test('Skip due to something being broken', function() { or like so: -```node +```javascript t.skip().test('Skip this', function() { ... }) ``` @@ -373,7 +373,7 @@ t.skip().test('Skip this', function() { ... }) Tests can take a long time. By default, eltro will cancel a test if it takes longer than 2 seconds. You can however override this by calling the timeout function after or before the test or before the describe with the specified duration in milliseconds like so: -```node +```javascript t.timeout(5000).describe('These will all have same timeout', function() { t.test('One slow function', async function() { ... }) t.test('Another slow function', async function() { ... }) @@ -382,7 +382,7 @@ t.timeout(5000).describe('These will all have same timeout', function() { Or apply to individual test like so: -```node +```javascript t.test('This is a really long test', async function() { await DoSomethingForReallyLongTime() }).timeout(5000) // 5 seconds @@ -390,7 +390,7 @@ t.test('This is a really long test', async function() { or like so: -```node +```javascript t.timeout(5000).test('A long test', async function() { ... }) ``` @@ -399,7 +399,7 @@ t.timeout(5000).test('A long test', async function() { ... }) Eltro comes with an extended version of node's built-in assertion library. You can start using them by simply importing it with eltro test runner: -```node +```javascript import { assert } from 'eltro' ``` @@ -408,7 +408,7 @@ import { assert } from 'eltro' Tests if value is a falsy value using `Boolean(value) == false` -```node +```javascript assert.notOk(false) // ok assert.notOk(null) // ok assert.notOk(undefined) // ok @@ -419,7 +419,7 @@ assert.notOk([]) // throws Test if the string value has a regex match of test -```node +```javascript assert.match('asdf', /a/) // ok assert.match('hello world', /hello/) // ok assert.match('something', /else/) // throws @@ -429,7 +429,7 @@ assert.match('something', /else/) // throws Test if the string value does not regex match the test -```node +```javascript assert.notMatch('asdf', /b/) // ok assert.notMatch('something', /else/) // ok assert.notMatch('hello world', /hello/) // throws @@ -440,7 +440,7 @@ assert.notMatch('hello world', /hello/) // throws Tests to make sure the promise gets fulfilled successfully and returns the final result. -```node +```javascript await assert.isFulfilled(Promise.resolve(null)) // ok await assert.isFulfilled(() => { throw new Error() }) // throws ``` @@ -450,7 +450,7 @@ await assert.isFulfilled(() => { throw new Error() }) // throws Tests to make sure the promise gets rejected and returns the error or value that was rejected -```node +```javascript let val = await assert.isRejected(Promise.reject('asdf')) // ok assert.strictEqual(val, 'asdf') @@ -458,7 +458,7 @@ let err = await assert.isRejected(() => { throw new Error('hello') }) // ok assert.strictEqual(err.message, 'hello') ``` -# Sinon-like spy()/stub() +# Sinon-like spy() stub() Using sinon-inspired mechanics for spying on calls as well as being able to stub existing functionality, eltro comes with a handy little copy-cat. @@ -469,7 +469,7 @@ the resulting code to speak about its purpose. To create a stub or a spy, simply import it and call it like so: -```node +```javascript import { spy, stub } from 'eltro' let spying = spy() @@ -478,7 +478,7 @@ let fn = stub() Each call to stub or spy is an array list of the passed-on arguments: -```node +```javascript let spying = spy() spying('hello', 'world') @@ -488,9 +488,9 @@ assert.strictEqual(spying.lastCall[1], 'world') ### lastCall -Returns the last call that was made to sinon and stub: +Returns the last call that was made to the spy or stub: -```node +```javascript let spying = spy() spying('a') spying('b') @@ -501,9 +501,9 @@ assert.strictEqual(spying.lastCall[0], 'c') ### called -Boolean variable that gets flipped once it's called at least once +Boolean variable that gets flipped once it gets called at least once -```node +```javascript let spying = spy() assert.strictEqual(spying.called, false) spying('a') @@ -517,7 +517,7 @@ assert.strictEqual(spying.called, true) The number of times it's been called -```node +```javascript let spying = spy() assert.strictEqual(spying.callCount, 0) spying('a') @@ -531,7 +531,7 @@ assert.strictEqual(spying.callCount, 3) Specifies what value the stub or spy should return when it gets called. -```node +```javascript let fn = stub() fn.returns('a') @@ -543,14 +543,14 @@ assert.strictEqual(fn(), 'a') Specifies what value the stub or spy should throw when it gets called. -```node +```javascript let fn = stub() fn.throws(new Error('b')) try { fn() } catch (err) { - assert.strictEqual(fn(), 'b') + assert.strictEqual(err.message, 'b') } ``` @@ -558,7 +558,7 @@ try { Specifies what value the stub or spy should return wrapped in a promise. -```node +```javascript let fn = stub() fn.resolves('a') @@ -571,7 +571,7 @@ fn().then(function(data) { Specifies what value the stub or spy should reject, wrapped in a promise. -```node +```javascript let fn = stub() fn.rejects('nope') @@ -584,7 +584,7 @@ fn().catch(function(data) { Specify custom function to be called whenever the stub or spy gets called. -```node +```javascript let fn = stub() fn.returnWith(function(a) { if (a === 'a') return true @@ -597,12 +597,11 @@ assert.strictEqual(fn('a'), true) assert.strictEqual(fn.callCount, 3) ``` -### getCall(index) -### getCallN(num) +### getCall(index) getCallN(num) Get a specific call. The `getCall` gets a zero-based index call while the `getCallN(num)` gets the more natural number call -```node +```javascript let spying = spy() spying('a') spying('b') @@ -613,14 +612,13 @@ assert.strictEqual(spying.getCallN(1), 'a') assert.strictEqual(spying.getCallN(2), 'b') ``` -### onCall(index) -### onCallN(num) +### onCall(index) onCallN(num) Overwrite behavior for a specific numbered call. Just like with getCall/getCallN, the onCall is zero-indexed number of the call you want to specify custom behavior while onCallN is the more natural number of the call you want to specify custom behavior. Note, when called with null, it specifies the default behavior. -```node +```javascript let fnOne = stub() let fnTwo = stub() @@ -644,14 +642,14 @@ assert.strictEqual(fnTwo(), 'one') Search for the first call when `fn(call)` returns `true`. Essentially a filter to search for a specific call that matches whatever call you're searching for. -```node +```javascript let evnt = stub() -evnt('onclick', 'one') -evnt('onerror', 'two') +evnt('onclick', 'one') +evnt('onerror', 'two') evnt('something', 'three') -evnt('onpress', 'four') -evnt('else', 'five') +evnt('onpress', 'four') +evnt('else', 'five') let foundPressCall = evnt.findCall(function(call) { return call[0] === 'onpress' }) assert.strictEqual(foundPressCall[0], 'onpress') From 1b697090aa001ec4a515363b121dfe1321291f09 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Sat, 26 Aug 2023 21:20:56 +0000 Subject: [PATCH 3/4] Trigger a new release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6dae7f..2b0ef0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eltro", - "version": "1.3.2", + "version": "1.3.3", "description": "Eltro is a tiny no-dependancy test framework for node", "main": "index.mjs", "scripts": { From bd478e77532c217ffa8673ca201e815946c5f022 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Mon, 28 Aug 2023 06:25:22 +0000 Subject: [PATCH 4/4] assert: Add new feature throwsAndCatch, returns the original thrown error --- README.md | 9 +++++++++ lib/assert.mjs | 9 +++++++++ package.json | 2 +- test/assert.test.mjs | 22 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 173571f..93b55d1 100644 --- a/README.md +++ b/README.md @@ -458,6 +458,15 @@ let err = await assert.isRejected(() => { throw new Error('hello') }) // ok assert.strictEqual(err.message, 'hello') ``` +### assert.throwsAndCatch(fn[, message]) + +Tests to make sure the function throws an exception. The important feature is this returns the original error that was thrown. + +```javascript +let err = assert.throwsAndCatch(() => { throw new Error('hello world') }) // ok +assert.strictEqual(err.message, 'hello world') +``` + # Sinon-like spy() stub() Using sinon-inspired mechanics for spying on calls as well as being able diff --git a/lib/assert.mjs b/lib/assert.mjs index 0d7cc06..e4fa038 100644 --- a/lib/assert.mjs +++ b/lib/assert.mjs @@ -48,6 +48,15 @@ assert.notMatch = (value, test, message) => { fail(m); } +assert.throwsAndCatch = (fn, message) => { + let err = null + assert.throws(fn, function(error) { + err = error + return true + }, message) + return err +} + assert.isFulfilled = (promise, message) => { return Promise.resolve(true) .then(() => promise) diff --git a/package.json b/package.json index 2b0ef0a..d729388 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eltro", - "version": "1.3.3", + "version": "1.3.4", "description": "Eltro is a tiny no-dependancy test framework for node", "main": "index.mjs", "scripts": { diff --git a/test/assert.test.mjs b/test/assert.test.mjs index 6331300..69d16f2 100644 --- a/test/assert.test.mjs +++ b/test/assert.test.mjs @@ -29,6 +29,28 @@ t.describe('#notOk()', function() { }) }) +t.describe('#throwAndCatch()', function() { + t.test('should work and return the original error', function() { + const assertError = new Error('Speed') + + let err = assert.throwsAndCatch(() => { throw assertError }) + assert.strictEqual(err, assertError) + }) + + t.test('should otherwise throw if no error', function() { + const assertMessage = 'Hello world' + let error = null + + try { + assert.throwsAndCatch(() => { }, assertMessage) + } catch (err) { + error = err + } + assert.ok(error) + assert.match(error.message, new RegExp(assertMessage)) + }) +}) + t.describe('#isFulfilled()', function() { t.test('should exist', function() { assertExtended.ok(assertExtended.isFulfilled)