UNPKG

als-document

Version:

A powerful HTML parser & DOM manipulation library for both backend and frontend.

169 lines (157 loc) 6.72 kB
class SimpleTest { static tests = []; static beforeEachCallback; static afterEachCallback; static nestingLevel = 0; static currentParent = []; static space = '' static results = {} static testTitle = '' static showFullError = false static colors = { bold:'\x1b[1m', cblue:'\x1b[34m', cred:'\x1b[31m', cgreen:'\x1b[32m', cgray:'\x1b[37m', reset:'\x1b[0m' } static delay = (ms,toResolve) => new Promise((resolve) => { setTimeout(() => {resolve(toResolve)}, ms); }); static describe(title, callback,pause=false) { if(pause) return let { nestingLevel, currentParent } = SimpleTest nestingLevel++; currentParent.push(title); callback(); currentParent.pop(); nestingLevel--; if (nestingLevel === 0) { SimpleTest.beforeEachCallback = null; // Clear beforeEachCallback after finishing the outermost describe block SimpleTest.afterEachCallback = null; // Clear beforeEachCallback after finishing the outermost describe block } } static beforeEach(callback) {SimpleTest.beforeEachCallback = callback;} static afterEach(callback) {SimpleTest.afterEachCallback = callback;} static beforeAll(callback) {SimpleTest.beforAllCallback = callback;} static afterAll(callback) {SimpleTest.afterAllCallback = callback;} static it(title, callback) { SimpleTest.tests.push({ titles: [...SimpleTest.currentParent, title], before: SimpleTest.beforeEachCallback, after:SimpleTest.afterEachCallback, test: callback, }); } static async runTests(consoleLog=true) { const {bold,cblue,cred,reset} = SimpleTest.colors SimpleTest.consoleLog = consoleLog let { tests,results,showFullError,beforAllCallback,afterAllCallback } = SimpleTest; let previousTitles = []; if(typeof beforAllCallback == 'function') await beforAllCallback() for(const test of tests) { let curentResult = results SimpleTest.space = test.titles.map(t => ' ').join(''); test.titles.forEach((title, index) => { if(curentResult[title] == undefined) { if(index == test.titles.length-1) curentResult[title] = [] else curentResult[title] = {} } curentResult = curentResult[title] if(previousTitles[index] !== title) { const indentation = ' '.repeat(index); console.log(bold+cblue+'%s'+reset,`${indentation} ${title}`); previousTitles[index] = title; } }); SimpleTest.curentResult = curentResult try { if (test.before) await test.before(); await test.test(); if (test.after) await test.after(); } catch (error) { if(showFullError) console.log(error) else console.log(`${SimpleTest.space}${cred}Error:${reset} ${error.message}`); curentResult.push({error}) } console.log('\n'); } if(typeof afterAllCallback == 'function') await afterAllCallback() } static assert(value,testTitle) { if(testTitle) SimpleTest.testTitle = testTitle SimpleTest.logResult(value) } static expect(value1) { let { logResult, isEqual } = SimpleTest const methods = { is: (text='') => { SimpleTest.testTitle = text; SimpleTest.not = false return methods; }, isNot: (text='') => { SimpleTest.testTitle = text; SimpleTest.not = true return methods; }, equalTo: (value2) => {logResult(value1 === value2);}, between(value2,value3) {logResult(value1 >= value2 && value1 <= value3);}, below(value2) {logResult(value1 < value2);}, above(value2) {logResult(value1 > value2);}, atLeast(value2) {logResult(value1 >= value2);}, atMost(value2) {logResult(value1 <= value2);}, sameAs: (value2) => {logResult(isEqual(value1, value2));}, defined: () => {logResult(value1 !== undefined);}, matchTo(pattern) {logResult(pattern.test(new RegExp(value1)));}, includes(value2) {logResult(value1.includes(value2));}, error: () => { if(typeof value1 !== 'function') return console.log('Expected value has to be function') try { let result = value1() if(result instanceof Error) logResult(true) else logResult(false); } catch (error) {logResult(true)} }, hasProperty: (property) => {logResult(Object.prototype.hasOwnProperty.call(value1, property));}, instanceof: (classType) => {logResult(value1.constructor.name == classType.name)}, closeTo(value2, decimalPlaces = 2) { const multiplier = 10 ** decimalPlaces; const roundedActual = Math.round(value1 * multiplier); const roundedExpected = Math.round(value2 * multiplier); const diff = Math.abs(roundedActual - roundedExpected) / multiplier; logResult(diff < 1 / multiplier); } }; return methods; } static logResult(result) { let {curentResult,testTitle,not,space,colors} = SimpleTest let {cgreen,cred,cgray,reset} = colors if(not) result = !result curentResult.push({result:result ? true : false,testTitle,error:null}) const status = result ? 'Success' : 'Failed'; const color = result ? cgreen : cred; if (testTitle == '') console.log(`${color}${space}${status}${reset}`); else console.log(`${space}${color}${status}: ${testTitle ? `${cgray}${testTitle}` : ''}`+reset,); SimpleTest.not = false SimpleTest.testTitle = '' } static isEqual(obj1, obj2, visited = new WeakMap()) { if (obj1 === obj2) return true; if (visited.has(obj1) && visited.get(obj1) === obj2) return true; const type1 = typeof obj1; const type2 = typeof obj2; if (type1 !== type2 || type1 !== 'object' || obj1 === null || obj2 === null) return false; visited.set(obj1, obj2); const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if(keys1.length !== keys2.length) return false; for (let key of keys1) { if (!keys2.includes(key) || !SimpleTest.isEqual(obj1[key], obj2[key], visited)) return false; } return true; }; } try {module.exports = SimpleTest} catch (error) {}