Created
March 31, 2023 21:13
-
-
Save libetl/60eb8b5337f5ef11c622e83da993e619 to your computer and use it in GitHub Desktop.
test-runner.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let currentSuiteName = ""; | |
let testPromises: (() => Promise<any>)[] = []; | |
let beforeAllHooks: (() => void | Promise<void>)[] = []; | |
let afterAllHooks: (() => void | Promise<void>)[] = []; | |
let beforeEachHooks: (() => void)[] = []; | |
let afterEachHooks: (() => void)[] = []; | |
let testsInError: { [testName: string]: Error } = {}; | |
export const describe = async (suiteName: string, callback: Function) => { | |
currentSuiteName = suiteName; | |
await new Promise((resolve) => { | |
const waitUntilNoPromise = setInterval(() => { | |
if (testPromises.length === 0) { | |
clearInterval(waitUntilNoPromise); | |
resolve(void 0); | |
} | |
}, 1000); | |
}); | |
callback(); | |
await testPromises.reduce( | |
(acc, other) => acc.then(() => other()), | |
Promise.resolve(void 0) | |
); | |
beforeAllHooks = []; | |
afterAllHooks = []; | |
beforeEachHooks = []; | |
afterEachHooks = []; | |
testPromises = []; | |
if (Object.entries(testsInError).length) { | |
console.log(testsInError); | |
testsInError = {}; | |
} | |
}; | |
export const beforeEach = (callback: () => void | Promise<void>) => | |
beforeEachHooks.push(callback); | |
export const afterEach = (callback: () => void | Promise<void>) => | |
afterEachHooks.push(callback); | |
export const beforeAll = (callback: () => void | Promise<void>) => | |
beforeAllHooks.push(callback); | |
export const afterAll = (callback: () => void | Promise<void>) => | |
afterAllHooks.push(callback); | |
export const it = async (testName: string, testCase: Function) => { | |
if (testPromises.length === 0) { | |
for (let beforeAllHook of beforeAllHooks) | |
testPromises.push(() => Promise.resolve(void 0).then(beforeAllHook)); | |
for (let afterAllHook of afterAllHooks) | |
testPromises.push(() => Promise.resolve(void 0).then(afterAllHook)); | |
} | |
const callback = | |
testCase.length === 1 | |
? (resolve: Function) => | |
testCase(() => { | |
for (let afterEachHook of afterEachHooks) afterEachHook(); | |
return resolve(); | |
}) | |
: async (resolve: Function) => { | |
const result = await testCase(); | |
for (let afterEachHook of afterEachHooks) afterEachHook(); | |
return resolve(result); | |
}; | |
testPromises.splice(beforeAllHooks.length, 0, () => | |
new Promise((resolve, reject) => { | |
try { | |
for (let beforeEachHook of beforeEachHooks) beforeEachHook(); | |
const result = callback(resolve); | |
if (result instanceof Promise) { | |
return result.catch((e) => { | |
for (let afterEachHook of afterEachHooks) afterEachHook(); | |
return reject(e); | |
}); | |
} | |
return result; | |
} catch (e) { | |
for (let afterEachHook of afterEachHooks) afterEachHook(); | |
return reject(e); | |
} | |
}).catch((e) => { | |
const error = new Error( | |
`test-runner error at ${currentSuiteName} - ${testName} ; ${ | |
e.message ?? "" | |
}` | |
); | |
error.stack = e; | |
testsInError[testName] = e; | |
return Promise.resolve(void 0); | |
}) | |
); | |
}; | |
export const mockImplementation = (callback: Function = () => {}) => { | |
let invocations: number = 0; | |
const watchedFunction = (...args: any[]) => { | |
invocations++; | |
return callback(...args); | |
}; | |
watchedFunction.getInvocationsNumber = () => invocations; | |
return watchedFunction; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment