From c7cc67be7b5464bcd215d358a4f34f5a56cd8556 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 07:49:35 +0100 Subject: [PATCH 01/33] FIrst working version --- src/a02-assertions/package.json | 3 +- src/a02-assertions/verifiers/a02-loader.js | 29 +++++++++++++++++++ src/a02-assertions/verifiers/assert.verify.js | 21 ++++++++++++++ src/a02-assertions/verifiers/index.verify.js | 14 +++++++++ src/a02-assertions/verifiers/test.verify.js | 7 +++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/a02-assertions/verifiers/a02-loader.js create mode 100644 src/a02-assertions/verifiers/assert.verify.js create mode 100644 src/a02-assertions/verifiers/index.verify.js create mode 100644 src/a02-assertions/verifiers/test.verify.js diff --git a/src/a02-assertions/package.json b/src/a02-assertions/package.json index e548008..5644c28 100644 --- a/src/a02-assertions/package.json +++ b/src/a02-assertions/package.json @@ -8,7 +8,8 @@ "test": "test" }, "scripts": { - "test": "node --test" + "test": "node --test", + "verify": "node --test --loader=./verifiers/a02-loader.js test/index.test.js" }, "keywords": [], "author": "", diff --git a/src/a02-assertions/verifiers/a02-loader.js b/src/a02-assertions/verifiers/a02-loader.js new file mode 100644 index 0000000..85758d4 --- /dev/null +++ b/src/a02-assertions/verifiers/a02-loader.js @@ -0,0 +1,29 @@ +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': './test.verify.js', + 'node:assert': './assert.verify.js', + '../src/index.js': './index.verify.js' + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } diff --git a/src/a02-assertions/verifiers/assert.verify.js b/src/a02-assertions/verifiers/assert.verify.js new file mode 100644 index 0000000..7cf9588 --- /dev/null +++ b/src/a02-assertions/verifiers/assert.verify.js @@ -0,0 +1,21 @@ +import * as originalAssert from 'node:assert' + +const assert = new Proxy(originalAssert, { + get(target, prop) { + const originalMethod = target[prop] + + if (typeof originalMethod === 'function') { + return (...args) => { + console.log( + `Calling assert.${String(prop)} with arguments in the test`, + args + ) + return originalMethod.apply(target, args) + } + } + + return originalMethod + } +}) + +export default assert diff --git a/src/a02-assertions/verifiers/index.verify.js b/src/a02-assertions/verifiers/index.verify.js new file mode 100644 index 0000000..f961add --- /dev/null +++ b/src/a02-assertions/verifiers/index.verify.js @@ -0,0 +1,14 @@ +import { + sum as originalSum, + sumAsync as originalSumAsync +} from '../src/index.js' + +export function sum(...args) { + console.log('Sum called: ', ...args) + return originalSum(...args) +} + +export async function sumAsync(...args) { + console.log('Sum async called: ', ...args) + return originalSumAsync(...args) +} diff --git a/src/a02-assertions/verifiers/test.verify.js b/src/a02-assertions/verifiers/test.verify.js new file mode 100644 index 0000000..0e3a752 --- /dev/null +++ b/src/a02-assertions/verifiers/test.verify.js @@ -0,0 +1,7 @@ +import { test as originalTest } from 'node:test' +export const test = (...args) => { + console.log('Running new test...') + console.log(...args) + + return originalTest(...args) +} From 18e4474931e029a8dba987b50f366d34e83ec41d Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 08:24:41 +0100 Subject: [PATCH 02/33] WIP --- src/a02-assertions/package.json | 2 +- src/a02-assertions/verifiers/assert.verify.js | 5 +-- src/a02-assertions/verifiers/handler.js | 33 +++++++++++++++++++ src/a02-assertions/verifiers/index.verify.js | 12 ++----- src/a02-assertions/verifiers/test.verify.js | 9 ++--- 5 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 src/a02-assertions/verifiers/handler.js diff --git a/src/a02-assertions/package.json b/src/a02-assertions/package.json index 5644c28..d2c5369 100644 --- a/src/a02-assertions/package.json +++ b/src/a02-assertions/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test", - "verify": "node --test --loader=./verifiers/a02-loader.js test/index.test.js" + "verify": "node --test --loader=./verifiers/a02-loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a02-assertions/verifiers/assert.verify.js b/src/a02-assertions/verifiers/assert.verify.js index 7cf9588..1b23157 100644 --- a/src/a02-assertions/verifiers/assert.verify.js +++ b/src/a02-assertions/verifiers/assert.verify.js @@ -1,17 +1,18 @@ import * as originalAssert from 'node:assert' +import { mock } from 'node:test' const assert = new Proxy(originalAssert, { get(target, prop) { const originalMethod = target[prop] if (typeof originalMethod === 'function') { - return (...args) => { + return mock.fn((...args) => { console.log( `Calling assert.${String(prop)} with arguments in the test`, args ) return originalMethod.apply(target, args) - } + }) } return originalMethod diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js new file mode 100644 index 0000000..e81f252 --- /dev/null +++ b/src/a02-assertions/verifiers/handler.js @@ -0,0 +1,33 @@ +import { test } from './test.verify.js' +import assert from './assert.verify.js' +import { sum, sumAsync } from './index.verify.js' + +async function main() { + try { + await import('../test/index.test.js') + } catch (error) { + console.error('Error occurred in the test file:', error) + } +} + +main() + +// I'm creating this wrapper in order to be able to spy the process.exit +process.on('exit', () => { + console.log('Validating the test completeness...') + if (test.mock.calls.length < 2) + throw new Error( + 'You need to create a test for both the sum and sumAsync functions' + ) + + console.log( + 'Assert deepStrictEqual called: ', + assert.deepStrictEqual.mock.calls.length + ) + + if (sum.mock.calls.length < 1) + throw new Error('You need to call "sum" at least once in your test') + + if (sumAsync.mock.calls.length < 1) + throw new Error('You need to call "sumAsync" at least once in your test') +}) diff --git a/src/a02-assertions/verifiers/index.verify.js b/src/a02-assertions/verifiers/index.verify.js index f961add..4f1cb31 100644 --- a/src/a02-assertions/verifiers/index.verify.js +++ b/src/a02-assertions/verifiers/index.verify.js @@ -2,13 +2,7 @@ import { sum as originalSum, sumAsync as originalSumAsync } from '../src/index.js' +import { mock } from 'node:test' -export function sum(...args) { - console.log('Sum called: ', ...args) - return originalSum(...args) -} - -export async function sumAsync(...args) { - console.log('Sum async called: ', ...args) - return originalSumAsync(...args) -} +export const sum = mock.fn(originalSum) +export const sumAsync = mock.fn(originalSumAsync) diff --git a/src/a02-assertions/verifiers/test.verify.js b/src/a02-assertions/verifiers/test.verify.js index 0e3a752..1c6c6a0 100644 --- a/src/a02-assertions/verifiers/test.verify.js +++ b/src/a02-assertions/verifiers/test.verify.js @@ -1,7 +1,2 @@ -import { test as originalTest } from 'node:test' -export const test = (...args) => { - console.log('Running new test...') - console.log(...args) - - return originalTest(...args) -} +import { test as originalTest, mock } from 'node:test' +export const test = mock.fn(originalTest) From e7012a98561915e4ba29faa01c351b055c24934d Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 08:30:40 +0100 Subject: [PATCH 03/33] Asserts spy working --- src/a02-assertions/verifiers/assert.verify.js | 17 ++++++++++------- src/a02-assertions/verifiers/handler.js | 7 ++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/a02-assertions/verifiers/assert.verify.js b/src/a02-assertions/verifiers/assert.verify.js index 1b23157..51709a6 100644 --- a/src/a02-assertions/verifiers/assert.verify.js +++ b/src/a02-assertions/verifiers/assert.verify.js @@ -1,18 +1,21 @@ import * as originalAssert from 'node:assert' -import { mock } from 'node:test' + +// Since the mock.fn is not working as intended on the proxy +// For now I'm creating an externa array of calls +export const assertCalls = [] const assert = new Proxy(originalAssert, { get(target, prop) { const originalMethod = target[prop] if (typeof originalMethod === 'function') { - return mock.fn((...args) => { - console.log( - `Calling assert.${String(prop)} with arguments in the test`, - args - ) + return (...args) => { + assertCalls.push({ + method: prop, + arguments: args + }) return originalMethod.apply(target, args) - }) + } } return originalMethod diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index e81f252..947a43c 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -1,5 +1,5 @@ import { test } from './test.verify.js' -import assert from './assert.verify.js' +import { assertCalls } from './assert.verify.js' import { sum, sumAsync } from './index.verify.js' async function main() { @@ -20,10 +20,7 @@ process.on('exit', () => { 'You need to create a test for both the sum and sumAsync functions' ) - console.log( - 'Assert deepStrictEqual called: ', - assert.deepStrictEqual.mock.calls.length - ) + console.log('Assert deepStrictEqual called: ', assertCalls) if (sum.mock.calls.length < 1) throw new Error('You need to call "sum" at least once in your test') From 797be0f2738894b05d27f32a22d19030e51bd629 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 11:05:31 +0100 Subject: [PATCH 04/33] AsyncLocalStorage to get currentTestName --- src/a02-assertions/verifiers/assert.verify.js | 6 +++--- src/a02-assertions/verifiers/handler.js | 16 +++++++++++++++- src/a02-assertions/verifiers/test.verify.js | 15 ++++++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/a02-assertions/verifiers/assert.verify.js b/src/a02-assertions/verifiers/assert.verify.js index 51709a6..9005751 100644 --- a/src/a02-assertions/verifiers/assert.verify.js +++ b/src/a02-assertions/verifiers/assert.verify.js @@ -1,7 +1,6 @@ import * as originalAssert from 'node:assert' +import { getCurrentTestName } from './test.verify.js' -// Since the mock.fn is not working as intended on the proxy -// For now I'm creating an externa array of calls export const assertCalls = [] const assert = new Proxy(originalAssert, { @@ -12,7 +11,8 @@ const assert = new Proxy(originalAssert, { return (...args) => { assertCalls.push({ method: prop, - arguments: args + arguments: args, + testName: getCurrentTestName() }) return originalMethod.apply(target, args) } diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index 947a43c..aacb2c4 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -20,7 +20,21 @@ process.on('exit', () => { 'You need to create a test for both the sum and sumAsync functions' ) - console.log('Assert deepStrictEqual called: ', assertCalls) + if ( + typeof assertCalls.find( + a => a.testName === 'sum' && a.method === 'deepStrictEqual' + ) === 'undefined' + ) + throw new Error('You need to call "deepStrictEqual" inside the "sum" test') + + if ( + typeof assertCalls.find( + a => a.testName === 'sumAsync' && a.method === 'deepStrictEqual' + ) === 'undefined' + ) + throw new Error( + 'You need to call "deepStrictEqual" inside the "sumAsync" test' + ) if (sum.mock.calls.length < 1) throw new Error('You need to call "sum" at least once in your test') diff --git a/src/a02-assertions/verifiers/test.verify.js b/src/a02-assertions/verifiers/test.verify.js index 1c6c6a0..9af109c 100644 --- a/src/a02-assertions/verifiers/test.verify.js +++ b/src/a02-assertions/verifiers/test.verify.js @@ -1,2 +1,15 @@ +import { AsyncLocalStorage } from 'async_hooks' import { test as originalTest, mock } from 'node:test' -export const test = mock.fn(originalTest) + +const asyncLocalStorage = new AsyncLocalStorage() + +export const test = mock.fn((...args) => { + asyncLocalStorage.run(new Map([['testName', args[0]]]), () => { + return originalTest(...args) + }) +}) + +export function getCurrentTestName() { + const store = asyncLocalStorage.getStore() + return store ? store.get('testName') : undefined +} From 460bef866c8dbadc4375f4e33da4006c54537553 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 11:16:58 +0100 Subject: [PATCH 05/33] Refactor --- src/a02-assertions/verifiers/a02-loader.js | 4 ++-- src/a02-assertions/verifiers/handler.js | 4 ++-- {src/a02-assertions/verifiers => verify}/assert.verify.js | 0 {src/a02-assertions/verifiers => verify}/test.verify.js | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename {src/a02-assertions/verifiers => verify}/assert.verify.js (100%) rename {src/a02-assertions/verifiers => verify}/test.verify.js (100%) diff --git a/src/a02-assertions/verifiers/a02-loader.js b/src/a02-assertions/verifiers/a02-loader.js index 85758d4..6157f54 100644 --- a/src/a02-assertions/verifiers/a02-loader.js +++ b/src/a02-assertions/verifiers/a02-loader.js @@ -9,8 +9,8 @@ async function resolve(url, context, defaultResolve) { } const modulesToPatch = { - 'node:test': './test.verify.js', - 'node:assert': './assert.verify.js', + 'node:test': '../../../verify/test.verify.js', + 'node:assert': '../../../verify/assert.verify.js', '../src/index.js': './index.verify.js' } diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index aacb2c4..f4f6c2a 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -1,5 +1,5 @@ -import { test } from './test.verify.js' -import { assertCalls } from './assert.verify.js' +import { test } from '../../../verify/test.verify.js' +import { assertCalls } from '../../../verify/assert.verify.js' import { sum, sumAsync } from './index.verify.js' async function main() { diff --git a/src/a02-assertions/verifiers/assert.verify.js b/verify/assert.verify.js similarity index 100% rename from src/a02-assertions/verifiers/assert.verify.js rename to verify/assert.verify.js diff --git a/src/a02-assertions/verifiers/test.verify.js b/verify/test.verify.js similarity index 100% rename from src/a02-assertions/verifiers/test.verify.js rename to verify/test.verify.js From 471c7462719c33bd62e088b0a051283a0b692ed9 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 11:29:56 +0100 Subject: [PATCH 06/33] Top-level await --- src/a02-assertions/verifiers/handler.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index f4f6c2a..350d605 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -2,15 +2,7 @@ import { test } from '../../../verify/test.verify.js' import { assertCalls } from '../../../verify/assert.verify.js' import { sum, sumAsync } from './index.verify.js' -async function main() { - try { - await import('../test/index.test.js') - } catch (error) { - console.error('Error occurred in the test file:', error) - } -} - -main() +await import('../test/index.test.js') // I'm creating this wrapper in order to be able to spy the process.exit process.on('exit', () => { From 46abbcca93f22db8e69e6ad382decac9a70442e7 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 11:30:51 +0100 Subject: [PATCH 07/33] Wording fix --- src/a02-assertions/verifiers/handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index 350d605..16b378a 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -6,7 +6,7 @@ await import('../test/index.test.js') // I'm creating this wrapper in order to be able to spy the process.exit process.on('exit', () => { - console.log('Validating the test completeness...') + console.log('Validating the test completion...') if (test.mock.calls.length < 2) throw new Error( 'You need to create a test for both the sum and sumAsync functions' From a00615daf307ddccd9b8e647a6b8cf73eab11b7e Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 11:34:35 +0100 Subject: [PATCH 08/33] Refactpr --- src/a02-assertions/verifiers/handler.js | 56 ++++++++++++++----------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index 16b378a..a815902 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -7,30 +7,38 @@ await import('../test/index.test.js') // I'm creating this wrapper in order to be able to spy the process.exit process.on('exit', () => { console.log('Validating the test completion...') - if (test.mock.calls.length < 2) - throw new Error( - 'You need to create a test for both the sum and sumAsync functions' - ) - if ( - typeof assertCalls.find( - a => a.testName === 'sum' && a.method === 'deepStrictEqual' - ) === 'undefined' - ) - throw new Error('You need to call "deepStrictEqual" inside the "sum" test') + const expectations = [ + { + condition: test.mock.calls.length < 2, + message: + 'You need to create a test for both the sum and sumAsync functions' + }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sum' && a.method === 'deepStrictEqual' + ) === 'undefined', + message: 'You need to call "deepStrictEqual" inside the "sum" test' + }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sumAsync' && a.method === 'deepStrictEqual' + ) === 'undefined', + message: 'You need to call "deepStrictEqual" inside the "sumAsync" test' + }, + { + condition: sum.mock.calls.length < 1, + message: 'You need to call "sum" at least once in your test' + }, + { + condition: sumAsync.mock.calls.length < 1, + message: 'You need to call "sumAsync" at least once in your test' + } + ] - if ( - typeof assertCalls.find( - a => a.testName === 'sumAsync' && a.method === 'deepStrictEqual' - ) === 'undefined' - ) - throw new Error( - 'You need to call "deepStrictEqual" inside the "sumAsync" test' - ) - - if (sum.mock.calls.length < 1) - throw new Error('You need to call "sum" at least once in your test') - - if (sumAsync.mock.calls.length < 1) - throw new Error('You need to call "sumAsync" at least once in your test') + for (const expectation of expectations) { + if (expectation.condition) throw new Error(expectation.message) + } }) From 4d25bdf8105bcf45b377af1daa93c42d8ac344c2 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 12:23:33 +0100 Subject: [PATCH 09/33] A04 hooks verifiers --- src/a04-hooks/package.json | 1 + src/a04-hooks/verifiers/a04-hooks.js | 29 ++++++++++++++ src/a04-hooks/verifiers/handler.js | 50 +++++++++++++++++++++++++ src/a04-hooks/verifiers/index.verify.js | 47 +++++++++++++++++++++++ verify/test.verify.js | 39 ++++++++++++++++++- 5 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/a04-hooks/verifiers/a04-hooks.js create mode 100644 src/a04-hooks/verifiers/handler.js create mode 100644 src/a04-hooks/verifiers/index.verify.js diff --git a/src/a04-hooks/package.json b/src/a04-hooks/package.json index 6bbaa04..ba1400d 100644 --- a/src/a04-hooks/package.json +++ b/src/a04-hooks/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", + "verify": "node --test --loader=./verifiers/a04-hooks.js ./verifiers/handler.js", "solution": "node --test ./test/solution.test.js" }, "keywords": [], diff --git a/src/a04-hooks/verifiers/a04-hooks.js b/src/a04-hooks/verifiers/a04-hooks.js new file mode 100644 index 0000000..6157f54 --- /dev/null +++ b/src/a04-hooks/verifiers/a04-hooks.js @@ -0,0 +1,29 @@ +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': '../../../verify/test.verify.js', + 'node:assert': '../../../verify/assert.verify.js', + '../src/index.js': './index.verify.js' + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } diff --git a/src/a04-hooks/verifiers/handler.js b/src/a04-hooks/verifiers/handler.js new file mode 100644 index 0000000..5e669a8 --- /dev/null +++ b/src/a04-hooks/verifiers/handler.js @@ -0,0 +1,50 @@ +import { test } from '../../../verify/test.verify.js' +import { fnCalls } from './index.verify.js' + +await import('../test/index.test.js') + +// I'm creating this wrapper in order to be able to spy the process.exit +process.on('exit', () => { + console.log('Validating the test completion...') + + const expectations = [ + { + condition: test.mock.calls.length < 3, + message: 'You need to create a test for at least three cases' + }, + { + condition: + typeof fnCalls.find( + call => call.name === 'connectToDatabase' || call.caller === 'before' + ) === 'undefined', + message: 'You need to call "connectToDatabase" inside a "before" hook' + }, + { + condition: + typeof fnCalls.find( + call => call.name === 'createUser' || call.caller === 'beforeEach' + ) === 'undefined', + message: 'You need to call "createUser" inside a "beforeEach" hook' + }, + { + condition: + typeof fnCalls.find( + call => call.name === 'deleteUser' || call.caller === 'afterEach' + ) === 'undefined', + message: 'You need to call "deleteUser" inside a "afterEach" hook' + }, + { + condition: + typeof fnCalls.find( + call => + call.name === 'closeDatabaseConnection' || call.caller === 'after' + ) === 'undefined', + message: + 'You need to call "closeDatabaseConnection" inside a "after" hook' + } + ] + + for (const expectation of expectations) { + if (expectation.condition) throw new Error(expectation.message) + } +}) diff --git a/src/a04-hooks/verifiers/index.verify.js b/src/a04-hooks/verifiers/index.verify.js new file mode 100644 index 0000000..d75568f --- /dev/null +++ b/src/a04-hooks/verifiers/index.verify.js @@ -0,0 +1,47 @@ +import { + connectToDatabase as originalConnectToDatabase, + closeDatabaseConnection as originalCloseDatabaseConnection, + createUser as originalCreateUser, + authenticateUser as originalAuthenticateUser, + deleteUser as originalDeleteUser +} from '../src/index.js' +import { getHook } from '../../../verify/test.verify.js' +import { mock } from 'node:test' + +export const fnCalls = [] + +export const connectToDatabase = mock.fn((...args) => { + fnCalls.push({ + name: 'connectToDatabase', + caller: getHook() + }) + return originalConnectToDatabase(...args) +}) +export const closeDatabaseConnection = mock.fn((...args) => { + fnCalls.push({ + name: 'closeDatabaseConnection', + caller: getHook() + }) + return originalCloseDatabaseConnection(...args) +}) +export const createUser = mock.fn((...args) => { + fnCalls.push({ + name: 'createUser', + caller: getHook() + }) + return originalCreateUser(...args) +}) +export const authenticateUser = mock.fn((...args) => { + fnCalls.push({ + name: 'authenticateUser', + caller: getHook() + }) + return originalAuthenticateUser(...args) +}) +export const deleteUser = mock.fn((...args) => { + fnCalls.push({ + name: 'deleteUser', + caller: getHook() + }) + return originalDeleteUser(...args) +}) diff --git a/verify/test.verify.js b/verify/test.verify.js index 9af109c..c8e2223 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -1,5 +1,12 @@ import { AsyncLocalStorage } from 'async_hooks' -import { test as originalTest, mock } from 'node:test' +import { + test as originalTest, + before as originalBefore, + beforeEach as originalBeforeEach, + afterEach as originalAfterEach, + after as originalAfter, + mock +} from 'node:test' const asyncLocalStorage = new AsyncLocalStorage() @@ -8,8 +15,36 @@ export const test = mock.fn((...args) => { return originalTest(...args) }) }) - export function getCurrentTestName() { const store = asyncLocalStorage.getStore() return store ? store.get('testName') : undefined } + +export const before = mock.fn((...args) => { + asyncLocalStorage.run(new Map([['hook', 'before']]), () => { + return originalBefore(...args) + }) +}) + +export const beforeEach = mock.fn((...args) => { + asyncLocalStorage.run(new Map([['hook', 'beforeEach']]), () => { + return originalBeforeEach(...args) + }) +}) + +export const after = mock.fn((...args) => { + asyncLocalStorage.run(new Map([['hook', 'after']]), () => { + return originalAfter(...args) + }) +}) + +export const afterEach = mock.fn((...args) => { + asyncLocalStorage.run(new Map([['hook', 'afterEach']]), () => { + return originalAfterEach(...args) + }) +}) + +export function getHook() { + const store = asyncLocalStorage.getStore() + return store ? store.get('hook') : undefined +} From d15400904871f24ca1e0d455757ece5c5a1a74e7 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 13:44:50 +0100 Subject: [PATCH 10/33] a05 implemented --- src/a05-keywords/package.json | 1 + src/a05-keywords/verifiers/a05-keywords.js | 27 +++++++++++++++++++ src/a05-keywords/verifiers/handler.js | 31 ++++++++++++++++++++++ verify/test.verify.js | 9 ++++++- 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/a05-keywords/verifiers/a05-keywords.js create mode 100644 src/a05-keywords/verifiers/handler.js diff --git a/src/a05-keywords/package.json b/src/a05-keywords/package.json index f479d57..d226d94 100644 --- a/src/a05-keywords/package.json +++ b/src/a05-keywords/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", + "verify": "node --test --loader=./verifiers/a05-keywords.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a05-keywords/verifiers/a05-keywords.js b/src/a05-keywords/verifiers/a05-keywords.js new file mode 100644 index 0000000..3b67059 --- /dev/null +++ b/src/a05-keywords/verifiers/a05-keywords.js @@ -0,0 +1,27 @@ +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': '../../../verify/test.verify.js' + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } diff --git a/src/a05-keywords/verifiers/handler.js b/src/a05-keywords/verifiers/handler.js new file mode 100644 index 0000000..ce36174 --- /dev/null +++ b/src/a05-keywords/verifiers/handler.js @@ -0,0 +1,31 @@ +import { test, only, skip, todo } from '../../../verify/test.verify.js' + +await import('../test/index.test.js') + +// I'm creating this wrapper in order to be able to spy the process.exit +process.on('exit', () => { + console.log('Validating the test completion...') + + const expectations = [ + { + condition: test.mock.calls.length < 1, + message: 'You need to call "test" at least once' + }, + { + condition: only.mock.calls.length < 1, + message: 'You need to call "only" at least once' + }, + { + condition: skip.mock.calls.length < 1, + message: 'You need to call "skip" at least once' + }, + { + condition: todo.mock.calls.length < 1, + message: 'You need to call "todo" at least once' + } + ] + + for (const expectation of expectations) { + if (expectation.condition) throw new Error(expectation.message) + } +}) diff --git a/verify/test.verify.js b/verify/test.verify.js index c8e2223..30372bf 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -5,7 +5,10 @@ import { beforeEach as originalBeforeEach, afterEach as originalAfterEach, after as originalAfter, - mock + mock, + only as originalOnly, + skip as originalSkip, + todo as originalTodo } from 'node:test' const asyncLocalStorage = new AsyncLocalStorage() @@ -48,3 +51,7 @@ export function getHook() { const store = asyncLocalStorage.getStore() return store ? store.get('hook') : undefined } + +export const only = mock.fn(originalOnly) +export const skip = mock.fn(originalSkip) +export const todo = mock.fn(originalTodo) From 9b8434607197cb265ee82956a189efaf37bd09d6 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Tue, 13 Feb 2024 14:17:36 +0100 Subject: [PATCH 11/33] A06 mock chapter --- src/a06-mocks/package.json | 1 + src/a06-mocks/test/index.test.js | 6 +---- src/a06-mocks/verifiers/a06-mocks.js | 27 ++++++++++++++++++++++ src/a06-mocks/verifiers/handler.js | 19 ++++++++++++++++ verify/test.verify.js | 34 ++++++++++++++++++++-------- 5 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 src/a06-mocks/verifiers/a06-mocks.js create mode 100644 src/a06-mocks/verifiers/handler.js diff --git a/src/a06-mocks/package.json b/src/a06-mocks/package.json index c2aa3db..233445e 100644 --- a/src/a06-mocks/package.json +++ b/src/a06-mocks/package.json @@ -9,6 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", + "verify": "node --test --loader=./verifiers/a06-mocks.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a06-mocks/test/index.test.js b/src/a06-mocks/test/index.test.js index a867cdf..e9033ed 100644 --- a/src/a06-mocks/test/index.test.js +++ b/src/a06-mocks/test/index.test.js @@ -1,13 +1,9 @@ /* eslint-disable no-unused-vars */ -import assert from 'node:assert' -import { sum } from '../src/index.js' -import { test, mock } from 'node:test' +import { test } from 'node:test' test('spies on a sum', () => { // use the mockedSum spy to check // how many times its called before // and after being used // check when its called wich argoument has received, result, and error - - const mockedSum = mock.fn(sum) }) diff --git a/src/a06-mocks/verifiers/a06-mocks.js b/src/a06-mocks/verifiers/a06-mocks.js new file mode 100644 index 0000000..3b67059 --- /dev/null +++ b/src/a06-mocks/verifiers/a06-mocks.js @@ -0,0 +1,27 @@ +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': '../../../verify/test.verify.js' + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } diff --git a/src/a06-mocks/verifiers/handler.js b/src/a06-mocks/verifiers/handler.js new file mode 100644 index 0000000..1ed138a --- /dev/null +++ b/src/a06-mocks/verifiers/handler.js @@ -0,0 +1,19 @@ +import { mockCalls } from '../../../verify/test.verify.js' + +await import('../test/index.test.js') + +// I'm creating this wrapper in order to be able to spy the process.exit +process.on('exit', () => { + console.log('Validating the test completion...') + + const expectations = [ + { + condition: !mockCalls.includes('fn'), + message: 'You need to call "mock.fn" at least once' + } + ] + + for (const expectation of expectations) { + if (expectation.condition) throw new Error(expectation.message) + } +}) diff --git a/verify/test.verify.js b/verify/test.verify.js index 30372bf..1bef86c 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -5,7 +5,7 @@ import { beforeEach as originalBeforeEach, afterEach as originalAfterEach, after as originalAfter, - mock, + mock as originalMock, only as originalOnly, skip as originalSkip, todo as originalTodo @@ -13,7 +13,7 @@ import { const asyncLocalStorage = new AsyncLocalStorage() -export const test = mock.fn((...args) => { +export const test = originalMock.fn((...args) => { asyncLocalStorage.run(new Map([['testName', args[0]]]), () => { return originalTest(...args) }) @@ -23,25 +23,25 @@ export function getCurrentTestName() { return store ? store.get('testName') : undefined } -export const before = mock.fn((...args) => { +export const before = originalMock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'before']]), () => { return originalBefore(...args) }) }) -export const beforeEach = mock.fn((...args) => { +export const beforeEach = originalMock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'beforeEach']]), () => { return originalBeforeEach(...args) }) }) -export const after = mock.fn((...args) => { +export const after = originalMock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'after']]), () => { return originalAfter(...args) }) }) -export const afterEach = mock.fn((...args) => { +export const afterEach = originalMock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'afterEach']]), () => { return originalAfterEach(...args) }) @@ -52,6 +52,22 @@ export function getHook() { return store ? store.get('hook') : undefined } -export const only = mock.fn(originalOnly) -export const skip = mock.fn(originalSkip) -export const todo = mock.fn(originalTodo) +export const only = originalMock.fn(originalOnly) +export const skip = originalMock.fn(originalSkip) +export const todo = originalMock.fn(originalTodo) + +export const mockCalls = [] +export const mock = new Proxy(originalMock, { + get(target, prop) { + const originalMethod = target[prop] + + if (typeof originalMethod === 'function') { + return (...args) => { + mockCalls.push(prop) + return originalMethod.apply(target, args) + } + } + + return originalMethod + } +}) From 2b0718ab738afa431f35f280f3cd485a186a6d02 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 08:37:07 +0100 Subject: [PATCH 12/33] Loader --- src/a02-assertions/package.json | 2 +- .../verifiers/{a02-loader.js => loader.js} | 0 src/a04-hooks/package.json | 2 +- .../verifiers/{a04-hooks.js => loader.js} | 0 src/a05-keywords/package.json | 2 +- .../verifiers/{a05-keywords.js => loader.js} | 0 src/a06-mocks/package.json | 2 +- .../verifiers/{a06-mocks.js => loader.js} | 0 src/a12-context/package.json | 3 ++- src/a12-context/verifiers/handler.js | 24 +++++++++++++++++ src/a12-context/verifiers/index.verify.js | 8 ++++++ src/a12-context/verifiers/loader.js | 27 +++++++++++++++++++ 12 files changed, 65 insertions(+), 5 deletions(-) rename src/a02-assertions/verifiers/{a02-loader.js => loader.js} (100%) rename src/a04-hooks/verifiers/{a04-hooks.js => loader.js} (100%) rename src/a05-keywords/verifiers/{a05-keywords.js => loader.js} (100%) rename src/a06-mocks/verifiers/{a06-mocks.js => loader.js} (100%) create mode 100644 src/a12-context/verifiers/handler.js create mode 100644 src/a12-context/verifiers/index.verify.js create mode 100644 src/a12-context/verifiers/loader.js diff --git a/src/a02-assertions/package.json b/src/a02-assertions/package.json index d2c5369..b4ba476 100644 --- a/src/a02-assertions/package.json +++ b/src/a02-assertions/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test", - "verify": "node --test --loader=./verifiers/a02-loader.js ./verifiers/handler.js" + "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a02-assertions/verifiers/a02-loader.js b/src/a02-assertions/verifiers/loader.js similarity index 100% rename from src/a02-assertions/verifiers/a02-loader.js rename to src/a02-assertions/verifiers/loader.js diff --git a/src/a04-hooks/package.json b/src/a04-hooks/package.json index ba1400d..6e77bf7 100644 --- a/src/a04-hooks/package.json +++ b/src/a04-hooks/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=./verifiers/a04-hooks.js ./verifiers/handler.js", + "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js", "solution": "node --test ./test/solution.test.js" }, "keywords": [], diff --git a/src/a04-hooks/verifiers/a04-hooks.js b/src/a04-hooks/verifiers/loader.js similarity index 100% rename from src/a04-hooks/verifiers/a04-hooks.js rename to src/a04-hooks/verifiers/loader.js diff --git a/src/a05-keywords/package.json b/src/a05-keywords/package.json index d226d94..ac87d87 100644 --- a/src/a05-keywords/package.json +++ b/src/a05-keywords/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=./verifiers/a05-keywords.js ./verifiers/handler.js", + "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a05-keywords/verifiers/a05-keywords.js b/src/a05-keywords/verifiers/loader.js similarity index 100% rename from src/a05-keywords/verifiers/a05-keywords.js rename to src/a05-keywords/verifiers/loader.js diff --git a/src/a06-mocks/package.json b/src/a06-mocks/package.json index 233445e..0765114 100644 --- a/src/a06-mocks/package.json +++ b/src/a06-mocks/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=./verifiers/a06-mocks.js ./verifiers/handler.js", + "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a06-mocks/verifiers/a06-mocks.js b/src/a06-mocks/verifiers/loader.js similarity index 100% rename from src/a06-mocks/verifiers/a06-mocks.js rename to src/a06-mocks/verifiers/loader.js diff --git a/src/a12-context/package.json b/src/a12-context/package.json index ca14aa7..45b8daf 100644 --- a/src/a12-context/package.json +++ b/src/a12-context/package.json @@ -6,7 +6,8 @@ "main": "index.js", "scripts": { "test": "node --test", - "solution": "node --test ./test/solution.test.js" + "solution": "node --test ./test/solution.test.js", + "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a12-context/verifiers/handler.js b/src/a12-context/verifiers/handler.js new file mode 100644 index 0000000..9fad773 --- /dev/null +++ b/src/a12-context/verifiers/handler.js @@ -0,0 +1,24 @@ +import { test } from '../../../verify/test.verify.js' +import { assertCalls } from '../../../verify/assert.verify.js' +import { sum, sumAsync } from './index.verify.js' + +await import('../test/index.test.js') + +// I'm creating this wrapper in order to be able to spy the process.exit +process.on('exit', () => { + console.log('Validating the test completion...') + + console.log(test.mock.calls.length) + + const expectations = [ + { + condition: test.mock.calls.length < 8, + message: + 'You need to create a test for both the sum and sumAsync functions' + } + ] + + for (const expectation of expectations) { + if (expectation.condition) throw new Error(expectation.message) + } +}) diff --git a/src/a12-context/verifiers/index.verify.js b/src/a12-context/verifiers/index.verify.js new file mode 100644 index 0000000..4f1cb31 --- /dev/null +++ b/src/a12-context/verifiers/index.verify.js @@ -0,0 +1,8 @@ +import { + sum as originalSum, + sumAsync as originalSumAsync +} from '../src/index.js' +import { mock } from 'node:test' + +export const sum = mock.fn(originalSum) +export const sumAsync = mock.fn(originalSumAsync) diff --git a/src/a12-context/verifiers/loader.js b/src/a12-context/verifiers/loader.js new file mode 100644 index 0000000..3b67059 --- /dev/null +++ b/src/a12-context/verifiers/loader.js @@ -0,0 +1,27 @@ +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': '../../../verify/test.verify.js' + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } From e5a843c18b89842bb9885aeb0ebe65297d6edc98 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 08:49:59 +0100 Subject: [PATCH 13/33] A12 WIP --- src/a12-context/verifiers/handler.js | 9 ++------- src/a12-context/verifiers/index.verify.js | 8 -------- 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 src/a12-context/verifiers/index.verify.js diff --git a/src/a12-context/verifiers/handler.js b/src/a12-context/verifiers/handler.js index 9fad773..af2e3dd 100644 --- a/src/a12-context/verifiers/handler.js +++ b/src/a12-context/verifiers/handler.js @@ -1,6 +1,4 @@ import { test } from '../../../verify/test.verify.js' -import { assertCalls } from '../../../verify/assert.verify.js' -import { sum, sumAsync } from './index.verify.js' await import('../test/index.test.js') @@ -8,13 +6,10 @@ await import('../test/index.test.js') process.on('exit', () => { console.log('Validating the test completion...') - console.log(test.mock.calls.length) - const expectations = [ { - condition: test.mock.calls.length < 8, - message: - 'You need to create a test for both the sum and sumAsync functions' + condition: test.mock.calls.length !== 2, + message: 'You need to create two top-level tests' } ] diff --git a/src/a12-context/verifiers/index.verify.js b/src/a12-context/verifiers/index.verify.js deleted file mode 100644 index 4f1cb31..0000000 --- a/src/a12-context/verifiers/index.verify.js +++ /dev/null @@ -1,8 +0,0 @@ -import { - sum as originalSum, - sumAsync as originalSumAsync -} from '../src/index.js' -import { mock } from 'node:test' - -export const sum = mock.fn(originalSum) -export const sumAsync = mock.fn(originalSumAsync) From 2fd18951cd50d2a2678747f8762ec12f1dc522ff Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 09:30:22 +0100 Subject: [PATCH 14/33] A11 WIP --- src/a11-timers/package.json | 3 ++- src/a11-timers/verifiers/handler.js | 28 ++++++++++++++++++++++++++++ src/a11-timers/verifiers/loader.js | 27 +++++++++++++++++++++++++++ verify/test.verify.js | 16 ++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/a11-timers/verifiers/handler.js create mode 100644 src/a11-timers/verifiers/loader.js diff --git a/src/a11-timers/package.json b/src/a11-timers/package.json index 0ef2230..36fd524 100644 --- a/src/a11-timers/package.json +++ b/src/a11-timers/package.json @@ -6,7 +6,8 @@ "main": "index.js", "scripts": { "test": "node --test", - "solution": "node --test ./test/solution.test.js" + "solution": "node --test ./test/solution.test.js", + "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a11-timers/verifiers/handler.js b/src/a11-timers/verifiers/handler.js new file mode 100644 index 0000000..f2c3569 --- /dev/null +++ b/src/a11-timers/verifiers/handler.js @@ -0,0 +1,28 @@ +import { test } from '../../../verify/test.verify.js' +import { mockCalls } from '../../../verify/test.verify.js' + +await import('../test/index.test.js') + +// I'm creating this wrapper in order to be able to spy the process.exit +process.on('exit', () => { + console.log('Validating the test completion...') + + const expectations = [ + { + condition: !mockCalls.includes('timers.enable'), + message: 'You need to call "timers.enable" at least once' + }, + { + condition: !mockCalls.includes('timers.tick'), + message: 'You need to call "timers.tick" at least once' + }, + { + condition: !mockCalls.includes('timers.reset'), + message: 'You need to call "timers.reset" at least once' + } + ] + + for (const expectation of expectations) { + if (expectation.condition) throw new Error(expectation.message) + } +}) diff --git a/src/a11-timers/verifiers/loader.js b/src/a11-timers/verifiers/loader.js new file mode 100644 index 0000000..3b67059 --- /dev/null +++ b/src/a11-timers/verifiers/loader.js @@ -0,0 +1,27 @@ +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': '../../../verify/test.verify.js' + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } diff --git a/verify/test.verify.js b/verify/test.verify.js index 1bef86c..e6bcbfe 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -68,6 +68,22 @@ export const mock = new Proxy(originalMock, { } } + if (prop === 'timers') { + const timers = target[prop] + return new Proxy(timers, { + get(timersTarget, timersProp) { + const originalMethod = timersTarget[timersProp] + if (typeof originalMethod === 'function') { + return (...args) => { + mockCalls.push('timers.' + timersProp) + return originalMethod.apply(timersTarget, args) + } + } + return originalMethod + } + }) + } + return originalMethod } }) From c343abd55f576b11261634253f6579a98b251608 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 09:41:31 +0100 Subject: [PATCH 15/33] A11 WIP --- src/a11-timers/verifiers/handler.js | 13 ++++++++++++- src/a11-timers/verifiers/index.verify.js | 4 ++++ src/a11-timers/verifiers/loader.js | 4 +++- 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 src/a11-timers/verifiers/index.verify.js diff --git a/src/a11-timers/verifiers/handler.js b/src/a11-timers/verifiers/handler.js index f2c3569..54f740f 100644 --- a/src/a11-timers/verifiers/handler.js +++ b/src/a11-timers/verifiers/handler.js @@ -1,5 +1,6 @@ -import { test } from '../../../verify/test.verify.js' +import { delayedHello } from './index.verify.js' import { mockCalls } from '../../../verify/test.verify.js' +import { assertCalls } from '../../../verify/assert.verify.js' await import('../test/index.test.js') @@ -19,6 +20,16 @@ process.on('exit', () => { { condition: !mockCalls.includes('timers.reset'), message: 'You need to call "timers.reset" at least once' + }, + { + condition: delayedHello.mock.calls.length === 0, + message: 'You need to call "delayedHello" at least once' + }, + { + condition: + typeof assertCalls.find(a => a.method === 'strictEqual') === + 'undefined', + message: 'You need to call "strictEqual" inside the test' } ] diff --git a/src/a11-timers/verifiers/index.verify.js b/src/a11-timers/verifiers/index.verify.js new file mode 100644 index 0000000..0fe4ed4 --- /dev/null +++ b/src/a11-timers/verifiers/index.verify.js @@ -0,0 +1,4 @@ +import { delayedHello as originalDlayedHello } from '../src/index.js' +import { mock } from 'node:test' + +export const delayedHello = mock.fn(originalDlayedHello) diff --git a/src/a11-timers/verifiers/loader.js b/src/a11-timers/verifiers/loader.js index 3b67059..6157f54 100644 --- a/src/a11-timers/verifiers/loader.js +++ b/src/a11-timers/verifiers/loader.js @@ -9,7 +9,9 @@ async function resolve(url, context, defaultResolve) { } const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js' + 'node:test': '../../../verify/test.verify.js', + 'node:assert': '../../../verify/assert.verify.js', + '../src/index.js': './index.verify.js' } if (Object.keys(modulesToPatch).includes(url)) { From 9fd0f866868fabc3cd4aea182c8c90d69b6d5a8a Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 09:57:05 +0100 Subject: [PATCH 16/33] Test refactor --- verify/test.verify.js | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/verify/test.verify.js b/verify/test.verify.js index e6bcbfe..589547f 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -1,21 +1,11 @@ import { AsyncLocalStorage } from 'async_hooks' -import { - test as originalTest, - before as originalBefore, - beforeEach as originalBeforeEach, - afterEach as originalAfterEach, - after as originalAfter, - mock as originalMock, - only as originalOnly, - skip as originalSkip, - todo as originalTodo -} from 'node:test' +import t from 'node:test' const asyncLocalStorage = new AsyncLocalStorage() -export const test = originalMock.fn((...args) => { +export const test = t.mock.fn((...args) => { asyncLocalStorage.run(new Map([['testName', args[0]]]), () => { - return originalTest(...args) + return t.test(...args) }) }) export function getCurrentTestName() { @@ -23,27 +13,27 @@ export function getCurrentTestName() { return store ? store.get('testName') : undefined } -export const before = originalMock.fn((...args) => { +export const before = t.mock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'before']]), () => { - return originalBefore(...args) + return t.before(...args) }) }) -export const beforeEach = originalMock.fn((...args) => { +export const beforeEach = t.mock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'beforeEach']]), () => { - return originalBeforeEach(...args) + return t.beforeEach(...args) }) }) -export const after = originalMock.fn((...args) => { +export const after = t.mock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'after']]), () => { - return originalAfter(...args) + return t.after(...args) }) }) -export const afterEach = originalMock.fn((...args) => { +export const afterEach = t.mock.fn((...args) => { asyncLocalStorage.run(new Map([['hook', 'afterEach']]), () => { - return originalAfterEach(...args) + return t.afterEach(...args) }) }) @@ -52,12 +42,12 @@ export function getHook() { return store ? store.get('hook') : undefined } -export const only = originalMock.fn(originalOnly) -export const skip = originalMock.fn(originalSkip) -export const todo = originalMock.fn(originalTodo) +export const only = t.mock.fn(t.only) +export const skip = t.mock.fn(t.skip) +export const todo = t.mock.fn(t.todo) export const mockCalls = [] -export const mock = new Proxy(originalMock, { +export const mock = new Proxy(t.mock, { get(target, prop) { const originalMethod = target[prop] From 3d8fd442f01a7013a8a731cd10897c920f40b279 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 10:38:12 +0100 Subject: [PATCH 17/33] Loader refactor --- src/a02-assertions/package.json | 2 +- src/a02-assertions/verifiers/index.verify.js | 8 ----- verify/loader.js | 32 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 9 deletions(-) delete mode 100644 src/a02-assertions/verifiers/index.verify.js create mode 100644 verify/loader.js diff --git a/src/a02-assertions/package.json b/src/a02-assertions/package.json index b4ba476..533b0f8 100644 --- a/src/a02-assertions/package.json +++ b/src/a02-assertions/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test", - "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js" + "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a02-assertions/verifiers/index.verify.js b/src/a02-assertions/verifiers/index.verify.js deleted file mode 100644 index 4f1cb31..0000000 --- a/src/a02-assertions/verifiers/index.verify.js +++ /dev/null @@ -1,8 +0,0 @@ -import { - sum as originalSum, - sumAsync as originalSumAsync -} from '../src/index.js' -import { mock } from 'node:test' - -export const sum = mock.fn(originalSum) -export const sumAsync = mock.fn(originalSumAsync) diff --git a/verify/loader.js b/verify/loader.js new file mode 100644 index 0000000..1e1deef --- /dev/null +++ b/verify/loader.js @@ -0,0 +1,32 @@ +import path from 'path' + +async function resolve(url, context, defaultResolve) { + // To avoid circular dependencies + // We suppose that all the verifiers include "verify" in the name + if ( + typeof context.parentURL !== 'undefined' && + context.parentURL.includes('verify') + ) { + return defaultResolve(url, context, defaultResolve) + } + + const modulesToPatch = { + 'node:test': './test.verify.js', + 'node:assert': './assert.verify.js', + // We're always mocking the src in order to spy the calls + '../src/index.js': path.join(process.cwd(), 'verifiers', 'index.verify.js') + } + + if (Object.keys(modulesToPatch).includes(url)) { + return defaultResolve( + new URL(modulesToPatch[url], import.meta.url).href, + context, + defaultResolve + ) + } + + // For all other modules, use the default loader + return defaultResolve(url, context, defaultResolve) +} + +export { resolve } From ed6f292025be37dc3a7e235f2023db8b5c399498 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 10:45:40 +0100 Subject: [PATCH 18/33] Refactor --- src/a04-hooks/package.json | 2 +- src/a04-hooks/verifiers/loader.js | 29 ---------------------- src/a05-keywords/package.json | 2 +- src/a05-keywords/verifiers/index.verify.js | 5 ++++ src/a06-mocks/package.json | 2 +- src/a06-mocks/verifiers/index.verify.js | 4 +++ src/a11-timers/package.json | 2 +- src/a12-context/package.json | 2 +- src/a12-context/verifiers/index.verify.js | 5 ++++ 9 files changed, 19 insertions(+), 34 deletions(-) delete mode 100644 src/a04-hooks/verifiers/loader.js create mode 100644 src/a05-keywords/verifiers/index.verify.js create mode 100644 src/a06-mocks/verifiers/index.verify.js create mode 100644 src/a12-context/verifiers/index.verify.js diff --git a/src/a04-hooks/package.json b/src/a04-hooks/package.json index 6e77bf7..516dbdb 100644 --- a/src/a04-hooks/package.json +++ b/src/a04-hooks/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js", + "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js", "solution": "node --test ./test/solution.test.js" }, "keywords": [], diff --git a/src/a04-hooks/verifiers/loader.js b/src/a04-hooks/verifiers/loader.js deleted file mode 100644 index 6157f54..0000000 --- a/src/a04-hooks/verifiers/loader.js +++ /dev/null @@ -1,29 +0,0 @@ -async function resolve(url, context, defaultResolve) { - // To avoid circular dependencies - // We suppose that all the verifiers include "verify" in the name - if ( - typeof context.parentURL !== 'undefined' && - context.parentURL.includes('verify') - ) { - return defaultResolve(url, context, defaultResolve) - } - - const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js', - 'node:assert': '../../../verify/assert.verify.js', - '../src/index.js': './index.verify.js' - } - - if (Object.keys(modulesToPatch).includes(url)) { - return defaultResolve( - new URL(modulesToPatch[url], import.meta.url).href, - context, - defaultResolve - ) - } - - // For all other modules, use the default loader - return defaultResolve(url, context, defaultResolve) -} - -export { resolve } diff --git a/src/a05-keywords/package.json b/src/a05-keywords/package.json index ac87d87..96f5998 100644 --- a/src/a05-keywords/package.json +++ b/src/a05-keywords/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js", + "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a05-keywords/verifiers/index.verify.js b/src/a05-keywords/verifiers/index.verify.js new file mode 100644 index 0000000..667c241 --- /dev/null +++ b/src/a05-keywords/verifiers/index.verify.js @@ -0,0 +1,5 @@ +import { sum as originalSum, product as originalProduct } from '../src/index.js' +import { mock } from 'node:test' + +export const sum = mock.fn(originalSum) +export const product = mock.fn(originalProduct) diff --git a/src/a06-mocks/package.json b/src/a06-mocks/package.json index 0765114..2417b34 100644 --- a/src/a06-mocks/package.json +++ b/src/a06-mocks/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js", + "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a06-mocks/verifiers/index.verify.js b/src/a06-mocks/verifiers/index.verify.js new file mode 100644 index 0000000..f266290 --- /dev/null +++ b/src/a06-mocks/verifiers/index.verify.js @@ -0,0 +1,4 @@ +import { sum as originalSum } from '../src/index.js' +import { mock } from 'node:test' + +export const sum = mock.fn(originalSum) diff --git a/src/a11-timers/package.json b/src/a11-timers/package.json index 36fd524..5cb96c5 100644 --- a/src/a11-timers/package.json +++ b/src/a11-timers/package.json @@ -7,7 +7,7 @@ "scripts": { "test": "node --test", "solution": "node --test ./test/solution.test.js", - "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js" + "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a12-context/package.json b/src/a12-context/package.json index 45b8daf..c26f0e9 100644 --- a/src/a12-context/package.json +++ b/src/a12-context/package.json @@ -7,7 +7,7 @@ "scripts": { "test": "node --test", "solution": "node --test ./test/solution.test.js", - "verify": "node --test --loader=./verifiers/loader.js ./verifiers/handler.js" + "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a12-context/verifiers/index.verify.js b/src/a12-context/verifiers/index.verify.js new file mode 100644 index 0000000..f2b8dd1 --- /dev/null +++ b/src/a12-context/verifiers/index.verify.js @@ -0,0 +1,5 @@ +import { sum as originalSum, average as originalAverage } from '../src/index.js' +import { mock } from 'node:test' + +export const sum = mock.fn(originalSum) +export const average = mock.fn(originalAverage) From 92740bca0dc68cbc5d716ead36d2272673cb4e59 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 10:47:52 +0100 Subject: [PATCH 19/33] Removed files --- src/a02-assertions/verifiers/loader.js | 29 -------------------------- src/a05-keywords/verifiers/loader.js | 27 ------------------------ src/a06-mocks/verifiers/loader.js | 27 ------------------------ src/a11-timers/verifiers/loader.js | 29 -------------------------- src/a12-context/verifiers/loader.js | 27 ------------------------ 5 files changed, 139 deletions(-) delete mode 100644 src/a02-assertions/verifiers/loader.js delete mode 100644 src/a05-keywords/verifiers/loader.js delete mode 100644 src/a06-mocks/verifiers/loader.js delete mode 100644 src/a11-timers/verifiers/loader.js delete mode 100644 src/a12-context/verifiers/loader.js diff --git a/src/a02-assertions/verifiers/loader.js b/src/a02-assertions/verifiers/loader.js deleted file mode 100644 index 6157f54..0000000 --- a/src/a02-assertions/verifiers/loader.js +++ /dev/null @@ -1,29 +0,0 @@ -async function resolve(url, context, defaultResolve) { - // To avoid circular dependencies - // We suppose that all the verifiers include "verify" in the name - if ( - typeof context.parentURL !== 'undefined' && - context.parentURL.includes('verify') - ) { - return defaultResolve(url, context, defaultResolve) - } - - const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js', - 'node:assert': '../../../verify/assert.verify.js', - '../src/index.js': './index.verify.js' - } - - if (Object.keys(modulesToPatch).includes(url)) { - return defaultResolve( - new URL(modulesToPatch[url], import.meta.url).href, - context, - defaultResolve - ) - } - - // For all other modules, use the default loader - return defaultResolve(url, context, defaultResolve) -} - -export { resolve } diff --git a/src/a05-keywords/verifiers/loader.js b/src/a05-keywords/verifiers/loader.js deleted file mode 100644 index 3b67059..0000000 --- a/src/a05-keywords/verifiers/loader.js +++ /dev/null @@ -1,27 +0,0 @@ -async function resolve(url, context, defaultResolve) { - // To avoid circular dependencies - // We suppose that all the verifiers include "verify" in the name - if ( - typeof context.parentURL !== 'undefined' && - context.parentURL.includes('verify') - ) { - return defaultResolve(url, context, defaultResolve) - } - - const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js' - } - - if (Object.keys(modulesToPatch).includes(url)) { - return defaultResolve( - new URL(modulesToPatch[url], import.meta.url).href, - context, - defaultResolve - ) - } - - // For all other modules, use the default loader - return defaultResolve(url, context, defaultResolve) -} - -export { resolve } diff --git a/src/a06-mocks/verifiers/loader.js b/src/a06-mocks/verifiers/loader.js deleted file mode 100644 index 3b67059..0000000 --- a/src/a06-mocks/verifiers/loader.js +++ /dev/null @@ -1,27 +0,0 @@ -async function resolve(url, context, defaultResolve) { - // To avoid circular dependencies - // We suppose that all the verifiers include "verify" in the name - if ( - typeof context.parentURL !== 'undefined' && - context.parentURL.includes('verify') - ) { - return defaultResolve(url, context, defaultResolve) - } - - const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js' - } - - if (Object.keys(modulesToPatch).includes(url)) { - return defaultResolve( - new URL(modulesToPatch[url], import.meta.url).href, - context, - defaultResolve - ) - } - - // For all other modules, use the default loader - return defaultResolve(url, context, defaultResolve) -} - -export { resolve } diff --git a/src/a11-timers/verifiers/loader.js b/src/a11-timers/verifiers/loader.js deleted file mode 100644 index 6157f54..0000000 --- a/src/a11-timers/verifiers/loader.js +++ /dev/null @@ -1,29 +0,0 @@ -async function resolve(url, context, defaultResolve) { - // To avoid circular dependencies - // We suppose that all the verifiers include "verify" in the name - if ( - typeof context.parentURL !== 'undefined' && - context.parentURL.includes('verify') - ) { - return defaultResolve(url, context, defaultResolve) - } - - const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js', - 'node:assert': '../../../verify/assert.verify.js', - '../src/index.js': './index.verify.js' - } - - if (Object.keys(modulesToPatch).includes(url)) { - return defaultResolve( - new URL(modulesToPatch[url], import.meta.url).href, - context, - defaultResolve - ) - } - - // For all other modules, use the default loader - return defaultResolve(url, context, defaultResolve) -} - -export { resolve } diff --git a/src/a12-context/verifiers/loader.js b/src/a12-context/verifiers/loader.js deleted file mode 100644 index 3b67059..0000000 --- a/src/a12-context/verifiers/loader.js +++ /dev/null @@ -1,27 +0,0 @@ -async function resolve(url, context, defaultResolve) { - // To avoid circular dependencies - // We suppose that all the verifiers include "verify" in the name - if ( - typeof context.parentURL !== 'undefined' && - context.parentURL.includes('verify') - ) { - return defaultResolve(url, context, defaultResolve) - } - - const modulesToPatch = { - 'node:test': '../../../verify/test.verify.js' - } - - if (Object.keys(modulesToPatch).includes(url)) { - return defaultResolve( - new URL(modulesToPatch[url], import.meta.url).href, - context, - defaultResolve - ) - } - - // For all other modules, use the default loader - return defaultResolve(url, context, defaultResolve) -} - -export { resolve } From 2b9a57d5179dbb4b1987aa1e6520968850a7ff42 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:07:46 +0100 Subject: [PATCH 20/33] Update verify/test.verify.js Co-authored-by: Marco Ippolito --- verify/test.verify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verify/test.verify.js b/verify/test.verify.js index 589547f..1d1ebf2 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -39,7 +39,7 @@ export const afterEach = t.mock.fn((...args) => { export function getHook() { const store = asyncLocalStorage.getStore() - return store ? store.get('hook') : undefined + return store?.get('hook') } export const only = t.mock.fn(t.only) From 555008a489ecedf9219abfc856829951200dc98f Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:08:03 +0100 Subject: [PATCH 21/33] Update verify/loader.js Co-authored-by: Marco Ippolito --- verify/loader.js | 1 - 1 file changed, 1 deletion(-) diff --git a/verify/loader.js b/verify/loader.js index 1e1deef..ac14a7a 100644 --- a/verify/loader.js +++ b/verify/loader.js @@ -29,4 +29,3 @@ async function resolve(url, context, defaultResolve) { return defaultResolve(url, context, defaultResolve) } -export { resolve } From 3f06c080293da2d8f8b3513154258e884b8a30d7 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:08:12 +0100 Subject: [PATCH 22/33] Update verify/loader.js Co-authored-by: Marco Ippolito --- verify/loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verify/loader.js b/verify/loader.js index ac14a7a..5101a8c 100644 --- a/verify/loader.js +++ b/verify/loader.js @@ -1,6 +1,6 @@ import path from 'path' -async function resolve(url, context, defaultResolve) { +export async function resolve(url, context, defaultResolve) { // To avoid circular dependencies // We suppose that all the verifiers include "verify" in the name if ( From 2266c46b7eeeff74489b2981e0b40f34fae31e1a Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:08:19 +0100 Subject: [PATCH 23/33] Update verify/test.verify.js Co-authored-by: Marco Ippolito --- verify/test.verify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verify/test.verify.js b/verify/test.verify.js index 1d1ebf2..9c2cd85 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -10,7 +10,7 @@ export const test = t.mock.fn((...args) => { }) export function getCurrentTestName() { const store = asyncLocalStorage.getStore() - return store ? store.get('testName') : undefined + return store?.get('testName') } export const before = t.mock.fn((...args) => { From f8ca31a656a8985e5732db82748753b8540a37a1 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:15:36 +0100 Subject: [PATCH 24/33] Readd index --- src/a02-assertions/verifiers/index.verify.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/a02-assertions/verifiers/index.verify.js diff --git a/src/a02-assertions/verifiers/index.verify.js b/src/a02-assertions/verifiers/index.verify.js new file mode 100644 index 0000000..4f1cb31 --- /dev/null +++ b/src/a02-assertions/verifiers/index.verify.js @@ -0,0 +1,8 @@ +import { + sum as originalSum, + sumAsync as originalSumAsync +} from '../src/index.js' +import { mock } from 'node:test' + +export const sum = mock.fn(originalSum) +export const sumAsync = mock.fn(originalSumAsync) From 23501aed6399ef413cc51f274cda8353bde6b342 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:22:14 +0100 Subject: [PATCH 25/33] Reafactor test --- verify/test.verify.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/verify/test.verify.js b/verify/test.verify.js index 9c2cd85..9debe31 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -4,42 +4,40 @@ import t from 'node:test' const asyncLocalStorage = new AsyncLocalStorage() export const test = t.mock.fn((...args) => { - asyncLocalStorage.run(new Map([['testName', args[0]]]), () => { + asyncLocalStorage.run({ testName: args[0] }, () => { return t.test(...args) }) }) export function getCurrentTestName() { - const store = asyncLocalStorage.getStore() - return store?.get('testName') + return asyncLocalStorage.getStore().testName } export const before = t.mock.fn((...args) => { - asyncLocalStorage.run(new Map([['hook', 'before']]), () => { + asyncLocalStorage.run({ hook: 'before' }, () => { return t.before(...args) }) }) export const beforeEach = t.mock.fn((...args) => { - asyncLocalStorage.run(new Map([['hook', 'beforeEach']]), () => { + asyncLocalStorage.run({ hook: 'beforeEach' }, () => { return t.beforeEach(...args) }) }) export const after = t.mock.fn((...args) => { - asyncLocalStorage.run(new Map([['hook', 'after']]), () => { + asyncLocalStorage.run({ hook: 'after' }, () => { return t.after(...args) }) }) export const afterEach = t.mock.fn((...args) => { - asyncLocalStorage.run(new Map([['hook', 'afterEach']]), () => { + asyncLocalStorage.run({ hook: 'afterEach' }, () => { return t.afterEach(...args) }) }) export function getHook() { - const store = asyncLocalStorage.getStore() - return store?.get('hook') + return asyncLocalStorage.getStore().hook } export const only = t.mock.fn(t.only) From 12d8a268901d430276de793994f2d460bdf892f3 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 11:23:51 +0100 Subject: [PATCH 26/33] Fix linting error --- verify/loader.js | 1 - 1 file changed, 1 deletion(-) diff --git a/verify/loader.js b/verify/loader.js index 5101a8c..cf473ca 100644 --- a/verify/loader.js +++ b/verify/loader.js @@ -28,4 +28,3 @@ export async function resolve(url, context, defaultResolve) { // For all other modules, use the default loader return defaultResolve(url, context, defaultResolve) } - From 7f7ce645ee9795f80b3284c4c002e33f9551074f Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:28:56 +0100 Subject: [PATCH 27/33] Fix suite --- src/a04-hooks/test/index.test.js | 76 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/src/a04-hooks/test/index.test.js b/src/a04-hooks/test/index.test.js index 7a9bdab..f93c2e8 100644 --- a/src/a04-hooks/test/index.test.js +++ b/src/a04-hooks/test/index.test.js @@ -14,47 +14,45 @@ let user databaseConnection = await connectToDatabase() -test('Authentication Module Tests', async () => { - await test('should authenticate a valid user', async () => { - user = await createUser(databaseConnection, 'testuser', 'password123') - const result = await authenticateUser( - databaseConnection, - 'testuser', - 'password123' - ) - assert.strictEqual(result, true, 'Authentication should succeed') - await deleteUser(databaseConnection, user) - }) +test('should authenticate a valid user', async () => { + user = await createUser(databaseConnection, 'testuser', 'password123') + const result = await authenticateUser( + databaseConnection, + 'testuser', + 'password123' + ) + assert.strictEqual(result, true, 'Authentication should succeed') + await deleteUser(databaseConnection, user) +}) - await test('should reject invalid password', async () => { - user = await createUser(databaseConnection, 'testuser', 'password123') - const result = await authenticateUser( - databaseConnection, - 'testuser', - 'wrongpassword' - ) - assert.strictEqual( - result, - false, - 'Authentication should fail with incorrect password' - ) - await deleteUser(databaseConnection, user) - }) +test('should reject invalid password', async () => { + user = await createUser(databaseConnection, 'testuser', 'password123') + const result = await authenticateUser( + databaseConnection, + 'testuser', + 'wrongpassword' + ) + assert.strictEqual( + result, + false, + 'Authentication should fail with incorrect password' + ) + await deleteUser(databaseConnection, user) +}) - await test('should reject non-existing user', async () => { - user = await createUser(databaseConnection, 'testuser', 'password123') - const result = await authenticateUser( - databaseConnection, - 'nonexistentuser', - 'password123' - ) - assert.strictEqual( - result, - false, - 'Authentication should fail with non-existing user' - ) - await deleteUser(databaseConnection, user) - }) +test('should reject non-existing user', async () => { + user = await createUser(databaseConnection, 'testuser', 'password123') + const result = await authenticateUser( + databaseConnection, + 'nonexistentuser', + 'password123' + ) + assert.strictEqual( + result, + false, + 'Authentication should fail with non-existing user' + ) + await deleteUser(databaseConnection, user) }) await closeDatabaseConnection(databaseConnection) From 4904db86f8f17c61686340b5edf2cd9957a2f605 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:30:53 +0100 Subject: [PATCH 28/33] Fix --- src/a04-hooks/test/solution.test.js | 64 ++++++++++++++--------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/a04-hooks/test/solution.test.js b/src/a04-hooks/test/solution.test.js index 248f8a1..92bfdb5 100644 --- a/src/a04-hooks/test/solution.test.js +++ b/src/a04-hooks/test/solution.test.js @@ -27,39 +27,37 @@ afterEach(async () => { await deleteUser(databaseConnection, user) }) -test('Authentication Module Tests', async () => { - await test('should authenticate a valid user', async () => { - const result = await authenticateUser( - databaseConnection, - 'testuser', - 'password123' - ) - assert.strictEqual(result, true, 'Authentication should succeed') - }) +test('should authenticate a valid user', async () => { + const result = await authenticateUser( + databaseConnection, + 'testuser', + 'password123' + ) + assert.strictEqual(result, true, 'Authentication should succeed') +}) - await test('should reject invalid password', async () => { - const result = await authenticateUser( - databaseConnection, - 'testuser', - 'wrongpassword' - ) - assert.strictEqual( - result, - false, - 'Authentication should fail with incorrect password' - ) - }) +test('should reject invalid password', async () => { + const result = await authenticateUser( + databaseConnection, + 'testuser', + 'wrongpassword' + ) + assert.strictEqual( + result, + false, + 'Authentication should fail with incorrect password' + ) +}) - await test('should reject non-existing user', async () => { - const result = await authenticateUser( - databaseConnection, - 'nonexistentuser', - 'password123' - ) - assert.strictEqual( - result, - false, - 'Authentication should fail with non-existing user' - ) - }) +test('should reject non-existing user', async () => { + const result = await authenticateUser( + databaseConnection, + 'nonexistentuser', + 'password123' + ) + assert.strictEqual( + result, + false, + 'Authentication should fail with non-existing user' + ) }) From b5f344ec450894e03cf505ddee842868319a6cba Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:40:18 +0100 Subject: [PATCH 29/33] Context chapter fix --- slides.md | 18 +++++++++--------- src/a12-context/test/solution.test.js | 18 +++++++++--------- src/a12-context/verifiers/handler.js | 11 ++++++++--- verify/test.verify.js | 1 + 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/slides.md b/slides.md index 7445180..82ab3dc 100644 --- a/slides.md +++ b/slides.md @@ -603,7 +603,7 @@ test('delayedHello executes the callback after the specified delay', () => { - In this exercise about context, we will focus on child tests (also known as subtests) - In the file `index.test.js` you will find multiple tests for the `sum` and the `average` functions -- Group together all the subtests related to the same function +- Group together all the subtests related to the same function using the `describe` function --- @@ -611,16 +611,16 @@ test('delayedHello executes the callback after the specified delay', () => { ```javascript // Grouping tests for `sum` function -test('sum function tests', async t => { - await t.test('Sum works correctly with valid input', () => { +describe('sum function tests', () => { + test('Sum works correctly with valid input', () => { assert.deepStrictEqual(sum([1, 2, 3]), 6) }) - await t.test('Sum returns 0 in case of empty array', () => { + test('Sum returns 0 in case of empty array', () => { assert.deepStrictEqual(sum([]), 0) }) - await t.test('Sum throws in case of bad input', () => { + test('Sum throws in case of bad input', () => { assert.throws(() => sum('abc'), { message: 'Input must be an array of numbers' }) @@ -634,16 +634,16 @@ test('sum function tests', async t => { ```javascript // Grouping tests for `average` function -test('average function tests', async t => { - await t.test('Average works correctly with valid input', () => { +describe('average function tests', () => { + test('Average works correctly with valid input', () => { assert.deepStrictEqual(average([1, 2, 3]), 2) }) - await t.test('Average returns 0 in case of empty array', () => { + test('Average returns 0 in case of empty array', () => { assert.deepStrictEqual(average([]), 0) }) - await t.test('Average throws in case of bad input', () => { + test('Average throws in case of bad input', () => { assert.throws(() => average('abc'), { message: 'Input must be an array of numbers' }) diff --git a/src/a12-context/test/solution.test.js b/src/a12-context/test/solution.test.js index 5c188cc..b37d9aa 100644 --- a/src/a12-context/test/solution.test.js +++ b/src/a12-context/test/solution.test.js @@ -1,18 +1,18 @@ import { average, sum } from '../src/index.js' -import { test } from 'node:test' +import { test, describe } from 'node:test' import assert from 'node:assert' // Grouping tests for `sum` function -test('sum function tests', async t => { - await t.test('Sum works correctly with valid input', () => { +describe('sum function tests', () => { + test('Sum works correctly with valid input', () => { assert.deepStrictEqual(sum([1, 2, 3]), 6) }) - await t.test('Sum returns 0 in case of empty array', () => { + test('Sum returns 0 in case of empty array', () => { assert.deepStrictEqual(sum([]), 0) }) - await t.test('Sum throws in case of bad input', () => { + test('Sum throws in case of bad input', () => { assert.throws(() => sum('abc'), { message: 'Input must be an array of numbers' }) @@ -20,16 +20,16 @@ test('sum function tests', async t => { }) // Grouping tests for `average` function -test('average function tests', async t => { - await t.test('Average works correctly with valid input', () => { +describe('average function tests', () => { + test('Average works correctly with valid input', () => { assert.deepStrictEqual(average([1, 2, 3]), 2) }) - await t.test('Average returns 0 in case of empty array', () => { + test('Average returns 0 in case of empty array', () => { assert.deepStrictEqual(average([]), 0) }) - await t.test('Average throws in case of bad input', () => { + test('Average throws in case of bad input', () => { assert.throws(() => average('abc'), { message: 'Input must be an array of numbers' }) diff --git a/src/a12-context/verifiers/handler.js b/src/a12-context/verifiers/handler.js index af2e3dd..ad7ac15 100644 --- a/src/a12-context/verifiers/handler.js +++ b/src/a12-context/verifiers/handler.js @@ -1,4 +1,4 @@ -import { test } from '../../../verify/test.verify.js' +import { test, describe } from '../../../verify/test.verify.js' await import('../test/index.test.js') @@ -8,8 +8,13 @@ process.on('exit', () => { const expectations = [ { - condition: test.mock.calls.length !== 2, - message: 'You need to create two top-level tests' + condition: test.mock.calls.length !== 6, + message: 'You need to all the tests' + }, + { + condition: describe.mock.calls.length !== 2, + message: + 'You need to use "describe" to create the test suites for the average and sum function' } ] diff --git a/verify/test.verify.js b/verify/test.verify.js index 9debe31..cb3484c 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -43,6 +43,7 @@ export function getHook() { export const only = t.mock.fn(t.only) export const skip = t.mock.fn(t.skip) export const todo = t.mock.fn(t.todo) +export const describe = t.mock.fn(t.describe) export const mockCalls = [] export const mock = new Proxy(t.mock, { From b692190f52c0a4c503b2b2b8444166a89a6ac039 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:43:03 +0100 Subject: [PATCH 30/33] Revert refactor --- verify/test.verify.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/verify/test.verify.js b/verify/test.verify.js index cb3484c..b59b48d 100644 --- a/verify/test.verify.js +++ b/verify/test.verify.js @@ -4,40 +4,42 @@ import t from 'node:test' const asyncLocalStorage = new AsyncLocalStorage() export const test = t.mock.fn((...args) => { - asyncLocalStorage.run({ testName: args[0] }, () => { + asyncLocalStorage.run(new Map([['testName', args[0]]]), () => { return t.test(...args) }) }) export function getCurrentTestName() { - return asyncLocalStorage.getStore().testName + const store = asyncLocalStorage.getStore() + return store?.get('testName') } export const before = t.mock.fn((...args) => { - asyncLocalStorage.run({ hook: 'before' }, () => { + asyncLocalStorage.run(new Map([['hook', 'before']]), () => { return t.before(...args) }) }) export const beforeEach = t.mock.fn((...args) => { - asyncLocalStorage.run({ hook: 'beforeEach' }, () => { + asyncLocalStorage.run(new Map([['hook', 'beforeEach']]), () => { return t.beforeEach(...args) }) }) export const after = t.mock.fn((...args) => { - asyncLocalStorage.run({ hook: 'after' }, () => { + asyncLocalStorage.run(new Map([['hook', 'after']]), () => { return t.after(...args) }) }) export const afterEach = t.mock.fn((...args) => { - asyncLocalStorage.run({ hook: 'afterEach' }, () => { + asyncLocalStorage.run(new Map([['hook', 'afterEach']]), () => { return t.afterEach(...args) }) }) export function getHook() { - return asyncLocalStorage.getStore().hook + const store = asyncLocalStorage.getStore() + return store?.get('hook') } export const only = t.mock.fn(t.only) From 769f8e743880c6d480b9710961d8592dccb56037 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:46:42 +0100 Subject: [PATCH 31/33] Fix 04 operators --- src/a04-hooks/verifiers/handler.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/a04-hooks/verifiers/handler.js b/src/a04-hooks/verifiers/handler.js index 5e669a8..019f421 100644 --- a/src/a04-hooks/verifiers/handler.js +++ b/src/a04-hooks/verifiers/handler.js @@ -15,21 +15,21 @@ process.on('exit', () => { { condition: typeof fnCalls.find( - call => call.name === 'connectToDatabase' || call.caller === 'before' + call => call.name === 'connectToDatabase' && call.caller === 'before' ) === 'undefined', message: 'You need to call "connectToDatabase" inside a "before" hook' }, { condition: typeof fnCalls.find( - call => call.name === 'createUser' || call.caller === 'beforeEach' + call => call.name === 'createUser' && call.caller === 'beforeEach' ) === 'undefined', message: 'You need to call "createUser" inside a "beforeEach" hook' }, { condition: typeof fnCalls.find( - call => call.name === 'deleteUser' || call.caller === 'afterEach' + call => call.name === 'deleteUser' && call.caller === 'afterEach' ) === 'undefined', message: 'You need to call "deleteUser" inside a "afterEach" hook' }, @@ -37,7 +37,7 @@ process.on('exit', () => { condition: typeof fnCalls.find( call => - call.name === 'closeDatabaseConnection' || call.caller === 'after' + call.name === 'closeDatabaseConnection' && call.caller === 'after' ) === 'undefined', message: 'You need to call "closeDatabaseConnection" inside a "after" hook' From bbb12044e60e9e7768ab427a84c591178c03ec52 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:51:27 +0100 Subject: [PATCH 32/33] A02 assertions --- src/a02-assertions/verifiers/handler.js | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/a02-assertions/verifiers/handler.js b/src/a02-assertions/verifiers/handler.js index a815902..4a7acdd 100644 --- a/src/a02-assertions/verifiers/handler.js +++ b/src/a02-assertions/verifiers/handler.js @@ -21,6 +21,27 @@ process.on('exit', () => { ) === 'undefined', message: 'You need to call "deepStrictEqual" inside the "sum" test' }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sum' && a.method === 'ok' + ) === 'undefined', + message: 'You need to call "ok" inside the "sum" test' + }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sum' && a.method === 'doesNotThrow' + ) === 'undefined', + message: 'You need to call "doesNotThrow" inside the "sum" test' + }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sum' && a.method === 'throws' + ) === 'undefined', + message: 'You need to call "throws" inside the "sum" test' + }, { condition: typeof assertCalls.find( @@ -28,6 +49,27 @@ process.on('exit', () => { ) === 'undefined', message: 'You need to call "deepStrictEqual" inside the "sumAsync" test' }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sumAsync' && a.method === 'ok' + ) === 'undefined', + message: 'You need to call "ok" inside the "sumAsync" test' + }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sumAsync' && a.method === 'doesNotReject' + ) === 'undefined', + message: 'You need to call "doesNotReject" inside the "sumAsync" test' + }, + { + condition: + typeof assertCalls.find( + a => a.testName === 'sumAsync' && a.method === 'rejects' + ) === 'undefined', + message: 'You need to call "rejects" inside the "sumAsync" test' + }, { condition: sum.mock.calls.length < 1, message: 'You need to call "sum" at least once in your test' From 4277eadc4a5e7323d4066f83614331b14f43e389 Mon Sep 17 00:00:00 2001 From: Alfonso Graziano Date: Wed, 14 Feb 2024 14:53:29 +0100 Subject: [PATCH 33/33] Remove warnings --- src/a02-assertions/package.json | 2 +- src/a04-hooks/package.json | 2 +- src/a05-keywords/package.json | 2 +- src/a06-mocks/package.json | 2 +- src/a11-timers/package.json | 2 +- src/a12-context/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/a02-assertions/package.json b/src/a02-assertions/package.json index 533b0f8..cb39da3 100644 --- a/src/a02-assertions/package.json +++ b/src/a02-assertions/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test", - "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js" + "verify": "node --test NODE_NO_WARNINGS=1 --loader=../../verify/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a04-hooks/package.json b/src/a04-hooks/package.json index 516dbdb..d2899b9 100644 --- a/src/a04-hooks/package.json +++ b/src/a04-hooks/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js", + "verify": "node --test NODE_NO_WARNINGS=1 --loader=../../verify/loader.js ./verifiers/handler.js", "solution": "node --test ./test/solution.test.js" }, "keywords": [], diff --git a/src/a05-keywords/package.json b/src/a05-keywords/package.json index 96f5998..c57eb1e 100644 --- a/src/a05-keywords/package.json +++ b/src/a05-keywords/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js", + "verify": "node --test NODE_NO_WARNINGS=1 --loader=../../verify/loader.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a06-mocks/package.json b/src/a06-mocks/package.json index 2417b34..a1ab762 100644 --- a/src/a06-mocks/package.json +++ b/src/a06-mocks/package.json @@ -9,7 +9,7 @@ }, "scripts": { "test": "node --test ./test/index.test.js", - "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js", + "verify": "node --test NODE_NO_WARNINGS=1 --loader=../../verify/loader.js ./verifiers/handler.js", "solution": "node --test --test-only ./test/solution.test.js" }, "keywords": [], diff --git a/src/a11-timers/package.json b/src/a11-timers/package.json index 5cb96c5..9ca5571 100644 --- a/src/a11-timers/package.json +++ b/src/a11-timers/package.json @@ -7,7 +7,7 @@ "scripts": { "test": "node --test", "solution": "node --test ./test/solution.test.js", - "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js" + "verify": "node --test NODE_NO_WARNINGS=1 --loader=../../verify/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "", diff --git a/src/a12-context/package.json b/src/a12-context/package.json index c26f0e9..babb95c 100644 --- a/src/a12-context/package.json +++ b/src/a12-context/package.json @@ -7,7 +7,7 @@ "scripts": { "test": "node --test", "solution": "node --test ./test/solution.test.js", - "verify": "node --test --loader=../../verify/loader.js ./verifiers/handler.js" + "verify": "node --test NODE_NO_WARNINGS=1 --loader=../../verify/loader.js ./verifiers/handler.js" }, "keywords": [], "author": "",