diff --git a/README.md b/README.md index a3f740a9..65396bb7 100644 --- a/README.md +++ b/README.md @@ -55,11 +55,11 @@ Enjoying **Poku**? Consider giving him a star ⭐️ check Less verbose
check High **isolation** level per file
     check No eval needed πŸ”
+     check No global state
check **Parallel** and **Sequential** runs πŸƒπŸ½πŸƒπŸ»
check **Poku** is [**100%** documented](https://poku.io/docs)
check Designed to be human-friendly
-check **Poku** doesn't use a global state
check Compatible with **Coverage** tools
check [**Node.js**][node-version-url], [**Bun**][bun-version-url] and [**Deno**][deno-version-url] compatibility 🩡
@@ -190,11 +190,10 @@ deno run npm:poku ### Helpers -- `beforeEach` and `afterEach` -- `test` -- `describe` and `log` -- `listFiles` -- `exit` +- [**beforeEach**](https://poku.io/docs/category/beforeeach-and-aftereach) and [**afterEach**](https://poku.io/docs/category/beforeeach-and-aftereach) +- [**test**](https://poku.io/docs/documentation/helpers/test) +- [**describe**](https://poku.io/docs/documentation/helpers/describe) +- _and much more_ ✨ [**See the complete documentation**](https://poku.io/docs). diff --git a/src/modules/assert-promise.ts b/src/modules/assert-promise.ts index 2eb1b10a..36db0f1e 100644 --- a/src/modules/assert-promise.ts +++ b/src/modules/assert-promise.ts @@ -100,12 +100,16 @@ const notDeepStrictEqual = async ( }); }; -const ifError = async (value: unknown): Promise => { +const ifError = async ( + value: unknown, + message?: ParseAssertionOptions['message'] +): Promise => { await parseAssertion( () => { nodeAssert.ifError(value); }, { + message, defaultMessage: 'Expected no error, but received an error', hideDiff: true, throw: true, diff --git a/src/modules/assert.ts b/src/modules/assert.ts index cf87a424..cac39a5f 100644 --- a/src/modules/assert.ts +++ b/src/modules/assert.ts @@ -94,13 +94,17 @@ const notDeepStrictEqual = ( }); }; -const ifError = (value: unknown, message?: string): void => { +const ifError = ( + value: unknown, + message?: ParseAssertionOptions['message'] +): void => { parseAssertion( () => { nodeAssert.ifError(value); }, { - defaultMessage: message || 'Expected no error, but received an error', + message, + defaultMessage: 'Expected no error, but received an error', hideDiff: true, throw: true, } diff --git a/test/unit/asser-promise-no-message.test.ts b/test/unit/asser-promise-no-message.test.ts new file mode 100644 index 00000000..b008f0ee --- /dev/null +++ b/test/unit/asser-promise-no-message.test.ts @@ -0,0 +1,191 @@ +import { nodeVersion } from '../../src/helpers/get-runtime.js'; +import { assertPromise as assert, describe, test } from '../../src/index.js'; + +describe('Assert Promise Suite (No Message)', { + background: false, + icon: 'πŸ”¬', +}); + +test(() => { + assert(true); + assert(1); + assert('string'); + assert([]); + assert({}); + assert(() => {}); + assert(3 > 2); +}); + +test(() => { + assert.ok(true); + assert.ok(1); + assert.ok('string'); + assert.ok([]); + assert.ok({}); + assert.ok(() => {}); + assert.ok(3 > 2); +}); + +test(() => { + assert.equal(1, 1); + assert.equal('text', 'text'); + assert.equal(2 + 2, 4); + assert.equal('Hello'.toUpperCase(), 'HELLO'); +}); + +test(() => { + assert.deepEqual({ a: 1 }, { a: 1 }); + assert.deepEqual([1, 2], [1, 2]); + assert.deepEqual([2, 3, 4], [2, 3, 4]); + assert.deepEqual([1, 2, 3].reverse(), [3, 2, 1]); +}); + +test(() => { + assert.strictEqual(1, 1); + assert.strictEqual('text', 'text'); + assert.strictEqual(2 * 2, 4); +}); + +test(() => { + assert.deepStrictEqual({ a: 1 }, { a: 1 }); + assert.deepStrictEqual([1, 2], [1, 2]); + assert.deepStrictEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); +}); + +test(() => { + assert.doesNotThrow(() => 1 + 1); +}); + +test(() => { + assert.notEqual(1, 2); + assert.notEqual(2 + 2, 5); + assert.notEqual('Hello'.toLowerCase(), 'HELLO'); +}); + +test(() => { + assert.notStrictEqual(1, true); + assert.notStrictEqual(1, '1'); + assert.notStrictEqual(2 * 2, '4'); + assert.notStrictEqual(2, '2'); +}); + +test(() => { + assert.notDeepEqual({ a: 1 }, { a: 2 }); + assert.notDeepEqual([2, 3, 4], [4, 5, 6]); +}); + +test(() => { + assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); + assert.notDeepStrictEqual([1, 2, 3], [1, 2, '3']); + assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); +}); + +const callbackFunction = (cb: (err: Error | null, result?: string) => void) => { + cb(null, 'no error'); +}; + +test(() => { + assert.ifError(null); + assert.ifError(undefined); +}); + +test(() => { + if (!nodeVersion || nodeVersion > 8) { + const obj = { a: 1 }; + + const functionThatThrows = () => { + throw new Error('Specific error'); + }; + + test(() => { + assert.throws(() => { + throw new Error('error'); + }); + assert.throws(() => { + throw new Error('Test error'); + }); + assert.throws(() => { + throw new Error('Test error'); + }); + assert.throws(functionThatThrows, new Error('Specific error')); + assert.throws(functionThatThrows, /Specific error/); + assert.throws( + functionThatThrows, + (err) => err instanceof Error && err.message === 'Specific error' + ); + }); + + test(() => { + assert.doesNotThrow(() => { + obj.a = 2; + }); + assert.strictEqual(obj.a, 2); + assert.doesNotThrow(() => { + return 42; + }); + assert.doesNotThrow(() => + callbackFunction((err) => { + assert.ifError(err); + }) + ); + assert.doesNotThrow(() => 42); + assert.doesNotThrow(() => 'no error'); + }); + } +}); + +test(() => { + if (!nodeVersion || nodeVersion > 12) { + const text = 'sample text'; + + test(() => { + assert.match(text, /sample/); + }); + + test(() => { + assert.doesNotMatch(text, /notpresent/); + assert.doesNotMatch('abc', /123/); + assert.doesNotMatch('', /\d/); + assert.doesNotMatch('abc', /\d+/); + }); + } +}); + +test(() => { + if (!nodeVersion || nodeVersion > 10) { + const asyncFunctionThatRejects = async () => + await Promise.reject(new Error('Async error')); + + const asyncFunctionThatResolves = () => + Promise.resolve('Resolved successfully'); + + const asyncFunctionThatFails = () => + new Promise((_, reject) => reject(new Error('Failed'))); + + const asyncFunctionThatCouldReject = () => + new Promise((resolve) => resolve(undefined)); + + test(() => { + assert.rejects( + async () => await asyncFunctionThatFails(), + new Error('Failed') + ); + assert.rejects(asyncFunctionThatRejects, new Error('Async error')); + assert.rejects( + () => Promise.reject('Simple rejection'), + (err) => err === 'Simple rejection' + ); + assert.rejects(asyncFunctionThatRejects, new Error('Async error')); + }); + + test(() => { + assert.doesNotReject(asyncFunctionThatResolves); + assert.doesNotReject(Promise.resolve('Immediate resolve')); + assert.doesNotReject(asyncFunctionThatCouldReject); + assert.doesNotReject(() => + Promise.resolve('Async function with no rejection') + ); + assert.doesNotReject(asyncFunctionThatResolves); + }); + } +}); diff --git a/test/unit/assert-no-message.test.ts b/test/unit/assert-no-message.test.ts new file mode 100644 index 00000000..93c3fd6e --- /dev/null +++ b/test/unit/assert-no-message.test.ts @@ -0,0 +1,188 @@ +import { nodeVersion } from '../../src/helpers/get-runtime.js'; +import { assert, describe, test } from '../../src/index.js'; + +describe('Assert Suite (No Message)', { background: false, icon: 'πŸ”¬' }); + +test(() => { + assert(true); + assert(1); + assert('string'); + assert([]); + assert({}); + assert(() => {}); + assert(3 > 2); +}); + +test(() => { + assert.ok(true); + assert.ok(1); + assert.ok('string'); + assert.ok([]); + assert.ok({}); + assert.ok(() => {}); + assert.ok(3 > 2); +}); + +test(() => { + assert.equal(1, 1); + assert.equal('text', 'text'); + assert.equal(2 + 2, 4); + assert.equal('Hello'.toUpperCase(), 'HELLO'); +}); + +test(() => { + assert.deepEqual({ a: 1 }, { a: 1 }); + assert.deepEqual([1, 2], [1, 2]); + assert.deepEqual([2, 3, 4], [2, 3, 4]); + assert.deepEqual([1, 2, 3].reverse(), [3, 2, 1]); +}); + +test(() => { + assert.strictEqual(1, 1); + assert.strictEqual('text', 'text'); + assert.strictEqual(2 * 2, 4); +}); + +test(() => { + assert.deepStrictEqual({ a: 1 }, { a: 1 }); + assert.deepStrictEqual([1, 2], [1, 2]); + assert.deepStrictEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); +}); + +test(() => { + assert.doesNotThrow(() => 1 + 1); +}); + +test(() => { + assert.notEqual(1, 2); + assert.notEqual(2 + 2, 5); + assert.notEqual('Hello'.toLowerCase(), 'HELLO'); +}); + +test(() => { + assert.notStrictEqual(1, true); + assert.notStrictEqual(1, '1'); + assert.notStrictEqual(2 * 2, '4'); + assert.notStrictEqual(2, '2'); +}); + +test(() => { + assert.notDeepEqual({ a: 1 }, { a: 2 }); + assert.notDeepEqual([2, 3, 4], [4, 5, 6]); +}); + +test(() => { + assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); + assert.notDeepStrictEqual([1, 2, 3], [1, 2, '3']); + assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); +}); + +const callbackFunction = (cb: (err: Error | null, result?: string) => void) => { + cb(null, 'no error'); +}; + +test(() => { + assert.ifError(null); + assert.ifError(undefined); +}); + +test(() => { + if (!nodeVersion || nodeVersion > 8) { + const obj = { a: 1 }; + + const functionThatThrows = () => { + throw new Error('Specific error'); + }; + + test(() => { + assert.throws(() => { + throw new Error('error'); + }); + assert.throws(() => { + throw new Error('Test error'); + }); + assert.throws(() => { + throw new Error('Test error'); + }); + assert.throws(functionThatThrows, new Error('Specific error')); + assert.throws(functionThatThrows, /Specific error/); + assert.throws( + functionThatThrows, + (err) => err instanceof Error && err.message === 'Specific error' + ); + }); + + test(() => { + assert.doesNotThrow(() => { + obj.a = 2; + }); + assert.strictEqual(obj.a, 2); + assert.doesNotThrow(() => { + return 42; + }); + assert.doesNotThrow(() => + callbackFunction((err) => { + assert.ifError(err); + }) + ); + assert.doesNotThrow(() => 42); + assert.doesNotThrow(() => 'no error'); + }); + } +}); + +test(() => { + if (!nodeVersion || nodeVersion > 12) { + const text = 'sample text'; + + test(() => { + assert.match(text, /sample/); + }); + + test(() => { + assert.doesNotMatch(text, /notpresent/); + assert.doesNotMatch('abc', /123/); + assert.doesNotMatch('', /\d/); + assert.doesNotMatch('abc', /\d+/); + }); + } +}); + +test(() => { + if (!nodeVersion || nodeVersion > 10) { + const asyncFunctionThatRejects = async () => + await Promise.reject(new Error('Async error')); + + const asyncFunctionThatResolves = () => + Promise.resolve('Resolved successfully'); + + const asyncFunctionThatFails = () => + new Promise((_, reject) => reject(new Error('Failed'))); + + const asyncFunctionThatCouldReject = () => + new Promise((resolve) => resolve(undefined)); + + test(() => { + assert.rejects( + async () => await asyncFunctionThatFails(), + new Error('Failed') + ); + assert.rejects(asyncFunctionThatRejects, new Error('Async error')); + assert.rejects( + () => Promise.reject('Simple rejection'), + (err) => err === 'Simple rejection' + ); + assert.rejects(asyncFunctionThatRejects, new Error('Async error')); + }); + + test(() => { + assert.doesNotReject(asyncFunctionThatResolves); + assert.doesNotReject(Promise.resolve('Immediate resolve')); + assert.doesNotReject(asyncFunctionThatCouldReject); + assert.doesNotReject(() => + Promise.resolve('Async function with no rejection') + ); + assert.doesNotReject(asyncFunctionThatResolves); + }); + } +}); diff --git a/test/unit/assert-promise.test.ts b/test/unit/assert-promise.test.ts index 75a7415d..91efaa21 100644 --- a/test/unit/assert-promise.test.ts +++ b/test/unit/assert-promise.test.ts @@ -1,139 +1,308 @@ import { nodeVersion } from '../../src/helpers/get-runtime.js'; -import { assertPromise as assert, describe } from '../../src/index.js'; +import { assertPromise as assert, describe, test } from '../../src/index.js'; describe('Assert (Promise) Suite', { background: false, icon: 'πŸ”¬' }); -assert.ok(true, 'ok with true'); -assert.ok(1, 'ok with 1'); +test(() => { + assert(true, 'ok (default) with true'); + assert(1, 'ok (default) with 1'); + assert('string', 'ok (default) with string'); + assert([], 'ok (default) with empty array'); + assert({}, 'ok (default) with empty object'); + assert(() => {}, 'ok (default) with empty function'); + assert(3 > 2, 'ok (default) 3 should be greater than 2'); +}); -assert.equal(1, 1, 'equal with same numbers'); -assert.equal('text', 'text', 'equal with same strings'); +test(() => { + assert.ok(true, 'ok with true'); + assert.ok(1, 'ok with 1'); + assert.ok('string', 'ok with string'); + assert.ok([], 'ok with empty array'); + assert.ok({}, 'ok with empty object'); + assert.ok(() => {}, 'ok with empty function'); + assert.ok(3 > 2, '3 should be greater than 2'); +}); -assert.deepEqual({ a: 1 }, { a: 1 }, 'deepEqual with same objects'); -assert.deepEqual([1, 2], [1, 2], 'deepEqual with same arrays'); - -assert.strictEqual(1, 1, 'strictEqual with same numbers'); -assert.strictEqual('text', 'text', 'strictEqual with same strings'); - -assert.deepStrictEqual({ a: 1 }, { a: 1 }, 'deepStrictEqual with same objects'); -assert.deepStrictEqual([1, 2], [1, 2], 'deepStrictEqual with same arrays'); - -assert.notEqual(1, 2, 'notEqual with different numbers'); - -assert.notDeepEqual({ a: 1 }, { a: 2 }, 'notDeepEqual with different objects'); - -assert.notStrictEqual( - 1, - '1', - 'notStrictEqual with loosely equal but not strictly equal values' -); - -assert.notDeepStrictEqual( - { a: 1 }, - { a: '1' }, - 'notDeepStrictEqual with loosely equal but not strictly deep equal objects' -); - -(async () => { - const trueValue = true; - await assert.ok(trueValue, 'Should resolve to true'); - - const oneValue = 1; - await assert.ok(oneValue, 'Should resolve to 1'); +test(() => { + assert.equal(1, 1, 'equal with same numbers'); + assert.equal('text', 'text', 'equal with same strings'); + assert.equal(2 + 2, 4, '2 + 2 should equal 4'); + assert.equal( + 'Hello'.toUpperCase(), + 'HELLO', + 'toUpperCase should convert to all upper case' + ); +}); - const numberOne = 1; - await assert.equal(numberOne, 1, 'Should resolve to equal 1'); +test(() => { + assert.deepEqual({ a: 1 }, { a: 1 }, 'deepEqual with same objects'); + assert.deepEqual([1, 2], [1, 2], 'deepEqual with same arrays'); + assert.deepEqual( + [2, 3, 4], + [2, 3, 4], + 'Arrays [2, 3, 4] should be deeply equal' + ); + assert.deepEqual( + [1, 2, 3].reverse(), + [3, 2, 1], + 'Reversing [1, 2, 3] should give [3, 2, 1]' + ); +}); - const textValue = 'text'; - await assert.equal(textValue, 'text', 'Should resolve to equal "text"'); +test(() => { + assert.strictEqual(1, 1, 'strictEqual with same numbers'); + assert.strictEqual('text', 'text', 'strictEqual with same strings'); + assert.strictEqual(2 * 2, 4, '2 * 2 should be strictly equal to 4'); +}); - const objectValue = { a: 1 }; - await assert.deepEqual( - objectValue, +test(() => { + assert.deepStrictEqual( { a: 1 }, - 'Should resolve to deep equal the object' + { a: 1 }, + 'deepStrictEqual with same objects' + ); + assert.deepStrictEqual([1, 2], [1, 2], 'deepStrictEqual with same arrays'); + assert.deepStrictEqual( + { a: 1, b: 2 }, + { a: 1, b: 2 }, + 'Objects { a: 1, b: 2 } should be deeply and strictly equal' ); +}); + +test(() => { + assert.doesNotThrow(() => 1 + 1, 'doesNotThrow with non-throwing function'); +}); - const arrayValue = [1, 2]; - await assert.deepEqual( - arrayValue, - [1, 2], - 'Should resolve to deep equal the array' +test(() => { + assert.notEqual(1, 2, 'notEqual with different numbers'); + assert.notEqual(2 + 2, 5, '2 + 2 should not equal 5'); + assert.notEqual( + 'Hello'.toLowerCase(), + 'HELLO', + 'toLowerCase should not match the upper case version' ); +}); - const strictNumber = 1; - await assert.strictEqual( - strictNumber, +test(() => { + assert.notStrictEqual(1, true, 'notStrictEqual with different types'); + assert.notStrictEqual( 1, - 'Should resolve to strictly equal 1' + '1', + 'notStrictEqual with loosely equal but not strictly equal values' ); - - const strictText = 'text'; - await assert.strictEqual( - strictText, - 'text', - 'Should resolve to strictly equal "text"' + assert.notStrictEqual( + 2 * 2, + '4', + '2 * 2 should not be strictly equal to "4"' ); + assert.notStrictEqual(2, '2', '2 should not be strictly equal to "2"'); +}); - const deepStrictObject = { a: 1 }; - await assert.deepStrictEqual( - deepStrictObject, +test(() => { + assert.notDeepEqual( { a: 1 }, - 'Should resolve to deep strictly equal the object' + { a: 2 }, + 'notDeepEqual with different objects' + ); + assert.notDeepEqual( + [2, 3, 4], + [4, 5, 6], + 'Arrays [2, 3, 4] and [4, 5, 6] should not be deeply equal' ); +}); - const deepStrictArray = [1, 2]; - await assert.deepStrictEqual( - deepStrictArray, - [1, 2], - 'Should resolve to deep strictly equal the array' +test(() => { + assert.notDeepStrictEqual( + { a: 1 }, + { a: '1' }, + 'notDeepStrictEqual with loosely equal but not strictly deep equal objects' + ); + assert.notDeepStrictEqual( + [1, 2, 3], + [1, 2, '3'], + '[1, 2, 3] should not be deeply strictly equal to [1, 2, "3"]' ); + assert.notDeepStrictEqual( + { a: 1 }, + { a: '1' }, + 'Objects { a: 1 } and { a: "1" } should not be deeply and strictly equal' + ); +}); + +const callbackFunction = (cb: (err: Error | null, result?: string) => void) => { + cb(null, 'no error'); +}; +test(() => { + assert.ifError(null, 'ifError did not throw an error for null'); + assert.ifError(undefined, 'ifError did not throw an error for undefined'); +}); + +test(() => { if (!nodeVersion || nodeVersion > 8) { - await assert.doesNotThrow( - () => Promise.resolve('no error'), - 'Should not throw an error' - ); - - await assert.doesNotThrow( - () => 1 + 1, - 'doesNotThrow with non-throwing function' - ); - - await assert.throws(() => { - throw new Error('error'); - }, 'throws with throwing function'); + const obj = { a: 1 }; + + const functionThatThrows = () => { + throw new Error('Specific error'); + }; + + test(() => { + assert.throws(() => { + throw new Error('error'); + }, 'throws with throwing function'); + assert.throws(() => { + throw new Error('Test error'); + }, 'Should throw an exception for a function that generates an error'); + assert.throws(() => { + throw new Error('Test error'); + }, 'Should throw an error for a function that actually throws'); + assert.throws( + functionThatThrows, + new Error('Specific error'), + 'Should throw the specific error' + ); + + assert.throws( + functionThatThrows, + /Specific error/, + 'Should throw an error matching the regex' + ); + + assert.throws( + functionThatThrows, + (err) => err instanceof Error && err.message === 'Specific error', + 'Should throw an error where the message equals the specific string' + ); + }); + + test(() => { + assert.doesNotThrow(() => { + obj.a = 2; + }, 'Changing property should not throw'); + assert.strictEqual(obj.a, 2, 'Property a should be 2 after mutation'); + + // Test to check functions that do or do not throw errors + assert.doesNotThrow(() => { + return 42; + }, 'Should not throw an exception for a function returning 42'); + + assert.doesNotThrow( + () => + callbackFunction((err) => { + assert.ifError(err); + }), + 'Should not throw an error for a callback function that does not error' + ); + + assert.doesNotThrow( + () => 42, + 'Should not throw an error for a function returning a number' + ); + + assert.doesNotThrow( + () => 'no error', + 'Should not throw an error for a function returning a string' + ); + + assert.doesNotThrow( + () => 'no error', + 'Should not throw an error for an async function that resolves' + ); + }); } +}); - if (!nodeVersion || nodeVersion > 10) { - await assert.rejects( - async () => await Promise.reject(new Error('error')), - Error('error'), - 'Should throw an error' - ); +test(() => { + if (!nodeVersion || nodeVersion > 12) { + const text = 'sample text'; + + test(() => { + assert.match(text, /sample/, 'Text should match the regex'); + }); + + test(() => { + assert.doesNotMatch( + text, + /notpresent/, + 'Text should not match the regex' + ); + assert.doesNotMatch( + 'abc', + /123/, + 'String "abc" should not match the pattern /123/' + ); + assert.doesNotMatch( + '', + /\d/, + 'Empty string should not match the pattern /d/' + ); + assert.doesNotMatch( + 'abc', + /\d+/, + 'String "abc" should not match the pattern /d+/' + ); + }); } +}); - const notEqualNumber = 1; - await assert.notEqual(notEqualNumber, 2, 'Should resolve to not equal 2'); +test(() => { + if (!nodeVersion || nodeVersion > 10) { + const asyncFunctionThatRejects = async () => + await Promise.reject(new Error('Async error')); - const notDeepEqualObject = { a: 1 }; - await assert.notDeepEqual( - notDeepEqualObject, - { a: 2 }, - 'Should resolve to not deep equal the object' - ); + const asyncFunctionThatResolves = () => + Promise.resolve('Resolved successfully'); - const notStrictEqualNumber = 1; - await assert.notStrictEqual( - notStrictEqualNumber, - '2', - 'Should resolve to not strictly equal "2"' - ); + const asyncFunctionThatFails = () => + new Promise((_, reject) => reject(new Error('Failed'))); - const notDeepStrictEqualObject = { a: 1 }; - await assert.notDeepStrictEqual( - notDeepStrictEqualObject, - { a: '2' }, - 'Should resolve to not deep strictly equal the object' - ); -})(); + const asyncFunctionThatCouldReject = () => + new Promise((resolve) => resolve(undefined)); + + test(() => { + assert.rejects( + async () => await asyncFunctionThatFails(), + new Error('Failed'), + 'Async function should reject with an error' + ); + assert.rejects( + asyncFunctionThatRejects, + new Error('Async error'), + 'Should reject with an Error object with "Async error" message' + ); + assert.rejects( + () => Promise.reject('Simple rejection'), + (err) => err === 'Simple rejection', + 'Should handle rejection with a simple string message' + ); + assert.rejects( + asyncFunctionThatRejects, + new Error('Async error'), + 'Should reject with the specified error message' + ); + }); + + test(() => { + assert.doesNotReject( + asyncFunctionThatResolves, + 'Should not reject for a function that resolves' + ); + assert.doesNotReject( + Promise.resolve('Immediate resolve'), + 'Should not reject for an immediately resolving promise' + ); + assert.doesNotReject( + asyncFunctionThatCouldReject, + 'Should not reject for a function that could reject but resolves instead' + ); + assert.doesNotReject( + () => Promise.resolve('Async function with no rejection'), + 'Should handle async functions that do not reject' + ); + assert.doesNotReject( + asyncFunctionThatResolves, + 'Should handle cases with no specific error argument in doesNotReject' + ); + }); + } +}); diff --git a/test/unit/assert.test.ts b/test/unit/assert.test.ts index 1f9c96ad..2f030f25 100644 --- a/test/unit/assert.test.ts +++ b/test/unit/assert.test.ts @@ -1,306 +1,308 @@ import { nodeVersion } from '../../src/helpers/get-runtime.js'; -import { assert, describe } from '../../src/index.js'; +import { assert, describe, test } from '../../src/index.js'; describe('Assert Suite', { background: false, icon: 'πŸ”¬' }); -assert(true, 'ok (default) with true'); -assert(1, 'ok (default) with 1'); -assert('string', 'ok (default) with string'); -assert([], 'ok (default) with empty array'); -assert({}, 'ok (default) with empty object'); -assert(() => {}, 'ok (default) with empty function'); - -assert.ok(true, 'ok with true'); -assert.ok(1, 'ok with 1'); -assert.ok('string', 'ok with string'); -assert.ok([], 'ok with empty array'); -assert.ok({}, 'ok with empty object'); -assert.ok(() => {}, 'ok with empty function'); - -assert.equal(1, 1, 'equal with same numbers'); -assert.equal('text', 'text', 'equal with same strings'); - -assert.deepEqual({ a: 1 }, { a: 1 }, 'deepEqual with same objects'); -assert.deepEqual([1, 2], [1, 2], 'deepEqual with same arrays'); - -assert.strictEqual(1, 1, 'strictEqual with same numbers'); -assert.strictEqual('text', 'text', 'strictEqual with same strings'); - -assert.deepStrictEqual({ a: 1 }, { a: 1 }, 'deepStrictEqual with same objects'); -assert.deepStrictEqual([1, 2], [1, 2], 'deepStrictEqual with same arrays'); - -assert.doesNotThrow(() => 1 + 1, 'doesNotThrow with non-throwing function'); - -assert.notEqual(1, 2, 'notEqual with different numbers'); - -assert.notStrictEqual(1, true, 'notStrictEqual with different types'); - -assert.notDeepEqual({ a: 1 }, { a: 2 }, 'notDeepEqual with different objects'); - -assert.notStrictEqual( - 1, - '1', - 'notStrictEqual with loosely equal but not strictly equal values' -); - -assert.notDeepStrictEqual( - { a: 1 }, - { a: '1' }, - 'notDeepStrictEqual with loosely equal but not strictly deep equal objects' -); - -// Simple tests to check boolean values -assert.ok(true, 'Should be true'); -assert.ok(!false, 'Negating false should be true'); - -// Test to check equality of numbers -assert.equal(2 + 2, 4, '2 + 2 should equal 4'); -assert.notEqual(2 + 2, 5, '2 + 2 should not equal 5'); - -// Test to check strict equality -assert.strictEqual(2 * 2, 4, '2 * 2 should be strictly equal to 4'); -assert.notStrictEqual(2 * 2, '4', '2 * 2 should not be strictly equal to "4"'); - -// Test to check deep equality -assert.deepEqual( - [2, 3, 4], - [2, 3, 4], - 'Arrays [2, 3, 4] should be deeply equal' -); -assert.notDeepEqual( - [2, 3, 4], - [4, 5, 6], - 'Arrays [2, 3, 4] and [4, 5, 6] should not be deeply equal' -); - -// Tests to check deep and strict equality -assert.deepStrictEqual( - { a: 1, b: 2 }, - { a: 1, b: 2 }, - 'Objects { a: 1, b: 2 } should be deeply and strictly equal' -); -assert.notDeepStrictEqual( - { a: 1 }, - { a: '1' }, - 'Objects { a: 1 } and { a: "1" } should not be deeply and strictly equal' -); - -// Testing numeric comparisons -assert.ok(3 > 2, '3 should be greater than 2'); -assert.notStrictEqual(2, '2', '2 should not be strictly equal to "2"'); - -// Testing string operations -assert.equal( - 'Hello'.toUpperCase(), - 'HELLO', - 'toUpperCase should convert to all upper case' -); -assert.notEqual( - 'Hello'.toLowerCase(), - 'HELLO', - 'toLowerCase should not match the upper case version' -); - -// Testing array operations -assert.deepEqual( - [1, 2, 3].reverse(), - [3, 2, 1], - 'Reversing [1, 2, 3] should give [3, 2, 1]' -); -assert.notDeepStrictEqual( - [1, 2, 3], - [1, 2, '3'], - '[1, 2, 3] should not be deeply strictly equal to [1, 2, "3"]' -); - -// Testing object mutations -const obj = { a: 1 }; - -// Testing async functions - -describe('ifError Test Suite', { background: false, icon: 'πŸ”¬' }); - -assert.ifError(null, 'ifError did not throw an error for null'); -assert.ifError(undefined, 'ifError did not throw an error for undefined'); -function callbackFunction(cb: (err: Error | null, result?: string) => void) { - // Simula uma operação que nΓ£o lanΓ§a um erro - cb(null, 'no error'); -} -if (!nodeVersion || nodeVersion > 8) { - describe('doesNotThrow Test Suite', { background: false, icon: 'πŸ”¬' }); - - assert.throws(() => { - throw new Error('error'); - }, 'throws with throwing function'); - - assert.doesNotThrow(() => { - obj.a = 2; - }, 'Changing property should not throw'); - assert.strictEqual(obj.a, 2, 'Property a should be 2 after mutation'); - - // Test to check functions that do or do not throw errors - assert.doesNotThrow(() => { - return 42; - }, 'Should not throw an exception for a function returning 42'); - assert.throws(() => { - throw new Error('Test error'); - }, 'Should throw an exception for a function that generates an error'); - - assert.doesNotThrow( - () => - callbackFunction((err) => { - assert.ifError(err); - }), - 'Should not throw an error for a callback function that does not error' +test(() => { + assert(true, 'ok (default) with true'); + assert(1, 'ok (default) with 1'); + assert('string', 'ok (default) with string'); + assert([], 'ok (default) with empty array'); + assert({}, 'ok (default) with empty object'); + assert(() => {}, 'ok (default) with empty function'); + assert(3 > 2, 'ok (default) 3 should be greater than 2'); +}); + +test(() => { + assert.ok(true, 'ok with true'); + assert.ok(1, 'ok with 1'); + assert.ok('string', 'ok with string'); + assert.ok([], 'ok with empty array'); + assert.ok({}, 'ok with empty object'); + assert.ok(() => {}, 'ok with empty function'); + assert.ok(3 > 2, '3 should be greater than 2'); +}); + +test(() => { + assert.equal(1, 1, 'equal with same numbers'); + assert.equal('text', 'text', 'equal with same strings'); + assert.equal(2 + 2, 4, '2 + 2 should equal 4'); + assert.equal( + 'Hello'.toUpperCase(), + 'HELLO', + 'toUpperCase should convert to all upper case' ); - - assert.doesNotThrow( - () => 42, - 'Should not throw an error for a function returning a number' +}); + +test(() => { + assert.deepEqual({ a: 1 }, { a: 1 }, 'deepEqual with same objects'); + assert.deepEqual([1, 2], [1, 2], 'deepEqual with same arrays'); + assert.deepEqual( + [2, 3, 4], + [2, 3, 4], + 'Arrays [2, 3, 4] should be deeply equal' ); - - assert.doesNotThrow( - () => 'no error', - 'Should not throw an error for a function returning a string' + assert.deepEqual( + [1, 2, 3].reverse(), + [3, 2, 1], + 'Reversing [1, 2, 3] should give [3, 2, 1]' ); - - assert.throws(() => { - throw new Error('Test error'); - }, 'Should throw an error for a function that actually throws'); - - assert.doesNotThrow( - () => 'no error', - 'Should not throw an error for an async function that resolves' +}); + +test(() => { + assert.strictEqual(1, 1, 'strictEqual with same numbers'); + assert.strictEqual('text', 'text', 'strictEqual with same strings'); + assert.strictEqual(2 * 2, 4, '2 * 2 should be strictly equal to 4'); +}); + +test(() => { + assert.deepStrictEqual( + { a: 1 }, + { a: 1 }, + 'deepStrictEqual with same objects' ); - - describe('throws Test Suite', { background: false, icon: 'πŸ”¬' }); - - const functionThatThrows = () => { - throw new Error('Specific error'); - }; - - assert.throws( - functionThatThrows, - new Error('Specific error'), - 'Should throw the specific error' + assert.deepStrictEqual([1, 2], [1, 2], 'deepStrictEqual with same arrays'); + assert.deepStrictEqual( + { a: 1, b: 2 }, + { a: 1, b: 2 }, + 'Objects { a: 1, b: 2 } should be deeply and strictly equal' ); - - assert.throws( - functionThatThrows, - /Specific error/, - 'Should throw an error matching the regex' +}); + +test(() => { + assert.doesNotThrow(() => 1 + 1, 'doesNotThrow with non-throwing function'); +}); + +test(() => { + assert.notEqual(1, 2, 'notEqual with different numbers'); + assert.notEqual(2 + 2, 5, '2 + 2 should not equal 5'); + assert.notEqual( + 'Hello'.toLowerCase(), + 'HELLO', + 'toLowerCase should not match the upper case version' ); - - assert.throws( - functionThatThrows, - // @ts-expect-error: Testing unexpected error type for demonstration - (err) => err.message === 'Specific error', - 'Should throw an error where the message equals the specific string' +}); + +test(() => { + assert.notStrictEqual(1, true, 'notStrictEqual with different types'); + assert.notStrictEqual( + 1, + '1', + 'notStrictEqual with loosely equal but not strictly equal values' ); -} - -if (!nodeVersion || nodeVersion > 12) { - describe('match Test Suite', { background: false, icon: 'πŸ”¬' }); - - // Testing regex matches - const text = 'sample text'; - assert.match(text, /sample/, 'Text should match the regex'); - assert.doesNotMatch(text, /notpresent/, 'Text should not match the regex'); - - describe('doesNotMatch Test Suite', { background: false, icon: 'πŸ”¬' }); - assert.doesNotMatch( - 'abc', - /123/, - 'String "abc" should not match the pattern /123/' - ); - - assert.doesNotMatch( - '', - /\d/, - 'Empty string should not match the pattern /d/' + assert.notStrictEqual( + 2 * 2, + '4', + '2 * 2 should not be strictly equal to "4"' ); - - assert.doesNotMatch( - 'abc', - /\d+/, - 'String "abc" should not match the pattern /d+/' + assert.notStrictEqual(2, '2', '2 should not be strictly equal to "2"'); +}); + +test(() => { + assert.notDeepEqual( + { a: 1 }, + { a: 2 }, + 'notDeepEqual with different objects' ); -} - -if (!nodeVersion || nodeVersion > 10) { - describe('rejects Test Suite', { background: false, icon: 'πŸ”¬' }); - const asyncFunctionThatRejects = async () => { - await Promise.reject(new Error('Async error')); - }; - const asyncFunctionThatFails = () => - new Promise((_, reject) => - setTimeout(() => reject(new Error('Failed')), 100) - ); - - assert.rejects( - // eslint-disable-next-line require-await - async () => asyncFunctionThatFails(), - new Error('Failed'), - 'Async function should reject with an error' + assert.notDeepEqual( + [2, 3, 4], + [4, 5, 6], + 'Arrays [2, 3, 4] and [4, 5, 6] should not be deeply equal' ); - assert.rejects( - asyncFunctionThatRejects, - new Error('Async error'), - 'Should reject with an Error object with "Async error" message' +}); + +test(() => { + assert.notDeepStrictEqual( + { a: 1 }, + { a: '1' }, + 'notDeepStrictEqual with loosely equal but not strictly deep equal objects' ); - assert.rejects( - () => Promise.reject('Simple rejection'), - (err) => err === 'Simple rejection', - 'Should handle rejection with a simple string message' + assert.notDeepStrictEqual( + [1, 2, 3], + [1, 2, '3'], + '[1, 2, 3] should not be deeply strictly equal to [1, 2, "3"]' ); - - assert.rejects( - asyncFunctionThatRejects, - new Error('Async error'), - 'Should reject with the specified error message' + assert.notDeepStrictEqual( + { a: 1 }, + { a: '1' }, + 'Objects { a: 1 } and { a: "1" } should not be deeply and strictly equal' ); +}); - describe('doesNotReject Test Suite', { background: false, icon: 'πŸ”¬' }); - // Test where the promise resolves successfully - const asyncFunctionThatResolves = () => { - return Promise.resolve('Resolved successfully'); - }; +const callbackFunction = (cb: (err: Error | null, result?: string) => void) => { + cb(null, 'no error'); +}; + +test(() => { + assert.ifError(null, 'ifError did not throw an error for null'); + assert.ifError(undefined, 'ifError did not throw an error for undefined'); +}); + +test(() => { + if (!nodeVersion || nodeVersion > 8) { + const obj = { a: 1 }; + + const functionThatThrows = () => { + throw new Error('Specific error'); + }; + + test(() => { + assert.throws(() => { + throw new Error('error'); + }, 'throws with throwing function'); + assert.throws(() => { + throw new Error('Test error'); + }, 'Should throw an exception for a function that generates an error'); + assert.throws(() => { + throw new Error('Test error'); + }, 'Should throw an error for a function that actually throws'); + assert.throws( + functionThatThrows, + new Error('Specific error'), + 'Should throw the specific error' + ); + + assert.throws( + functionThatThrows, + /Specific error/, + 'Should throw an error matching the regex' + ); + + assert.throws( + functionThatThrows, + (err) => err instanceof Error && err.message === 'Specific error', + 'Should throw an error where the message equals the specific string' + ); + }); - // This should pass because the function resolves - assert.doesNotReject( - asyncFunctionThatResolves, - 'Should not reject for a function that resolves' - ); + test(() => { + assert.doesNotThrow(() => { + obj.a = 2; + }, 'Changing property should not throw'); + assert.strictEqual(obj.a, 2, 'Property a should be 2 after mutation'); + + // Test to check functions that do or do not throw errors + assert.doesNotThrow(() => { + return 42; + }, 'Should not throw an exception for a function returning 42'); + + assert.doesNotThrow( + () => + callbackFunction((err) => { + assert.ifError(err); + }), + 'Should not throw an error for a callback function that does not error' + ); + + assert.doesNotThrow( + () => 42, + 'Should not throw an error for a function returning a number' + ); + + assert.doesNotThrow( + () => 'no error', + 'Should not throw an error for a function returning a string' + ); + + assert.doesNotThrow( + () => 'no error', + 'Should not throw an error for an async function that resolves' + ); + }); + } +}); - // Test with a promise that resolves immediately - assert.doesNotReject( - Promise.resolve('Immediate resolve'), - 'Should not reject for an immediately resolving promise' - ); +test(() => { + if (!nodeVersion || nodeVersion > 12) { + const text = 'sample text'; - // Test where the promise could reject but does not - const asyncFunctionThatCouldReject = () => { - return new Promise((resolve) => { - setTimeout(() => { - resolve('Delayed resolve'); - }, 100); + test(() => { + assert.match(text, /sample/, 'Text should match the regex'); }); - }; - assert.doesNotReject( - asyncFunctionThatCouldReject, - 'Should not reject for a function that could reject but resolves instead' - ); - - // Test using async function but with no rejection happening - assert.doesNotReject( - () => Promise.resolve('Async function with no rejection'), - 'Should handle async functions that do not reject' - ); + test(() => { + assert.doesNotMatch( + text, + /notpresent/, + 'Text should not match the regex' + ); + assert.doesNotMatch( + 'abc', + /123/, + 'String "abc" should not match the pattern /123/' + ); + assert.doesNotMatch( + '', + /\d/, + 'Empty string should not match the pattern /d/' + ); + assert.doesNotMatch( + 'abc', + /\d+/, + 'String "abc" should not match the pattern /d+/' + ); + }); + } +}); + +test(() => { + if (!nodeVersion || nodeVersion > 10) { + const asyncFunctionThatRejects = async () => + await Promise.reject(new Error('Async error')); + + const asyncFunctionThatResolves = () => + Promise.resolve('Resolved successfully'); + + const asyncFunctionThatFails = () => + new Promise((_, reject) => reject(new Error('Failed'))); + + const asyncFunctionThatCouldReject = () => + new Promise((resolve) => resolve(undefined)); + + test(() => { + assert.rejects( + async () => await asyncFunctionThatFails(), + new Error('Failed'), + 'Async function should reject with an error' + ); + assert.rejects( + asyncFunctionThatRejects, + new Error('Async error'), + 'Should reject with an Error object with "Async error" message' + ); + assert.rejects( + () => Promise.reject('Simple rejection'), + (err) => err === 'Simple rejection', + 'Should handle rejection with a simple string message' + ); + assert.rejects( + asyncFunctionThatRejects, + new Error('Async error'), + 'Should reject with the specified error message' + ); + }); - // Ensure it handles cases where no arguments are passed to doesNotReject - assert.doesNotReject( - asyncFunctionThatResolves, - 'Should handle cases with no specific error argument in doesNotReject' - ); -} + test(() => { + assert.doesNotReject( + asyncFunctionThatResolves, + 'Should not reject for a function that resolves' + ); + assert.doesNotReject( + Promise.resolve('Immediate resolve'), + 'Should not reject for an immediately resolving promise' + ); + assert.doesNotReject( + asyncFunctionThatCouldReject, + 'Should not reject for a function that could reject but resolves instead' + ); + assert.doesNotReject( + () => Promise.resolve('Async function with no rejection'), + 'Should handle async functions that do not reject' + ); + assert.doesNotReject( + asyncFunctionThatResolves, + 'Should handle cases with no specific error argument in doesNotReject' + ); + }); + } +});