codi-test-framework
Advanced tools
Comparing version 1.0.19 to 1.0.20
{ | ||
"name": "codi-test-framework", | ||
"version": "1.0.19", | ||
"version": "1.0.20", | ||
"description": "A simple test framework for JavaScript", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -15,3 +15,3 @@ import assertions from "./assertions/_assertions.js"; | ||
const version = "v1.0.19"; | ||
const version = "v1.0.20"; | ||
@@ -18,0 +18,0 @@ // Create the codi object to hold all exports |
@@ -1,2 +0,2 @@ | ||
import chalk from 'chalk'; | ||
import chalk from "chalk"; | ||
/** | ||
@@ -7,162 +7,158 @@ * Class representing the state of test execution | ||
class TestState { | ||
constructor() { | ||
/** @type {number} Number of passed tests */ | ||
this.passedTests = 0; | ||
/** @type {number} Number of failed tests */ | ||
this.failedTests = 0; | ||
/** @type {Array} Stack of active test suites */ | ||
this.suiteStack = {}; | ||
/** @type {number|null} Test start time */ | ||
this.startTime = null; | ||
/** @type {object} options */ | ||
this.options = {}; | ||
} | ||
constructor() { | ||
/** @type {number} Number of passed tests */ | ||
this.passedTests = 0; | ||
/** @type {number} Number of failed tests */ | ||
this.failedTests = 0; | ||
/** @type {Array} Stack of active test suites */ | ||
this.suiteStack = {}; | ||
/** @type {number|null} Test start time */ | ||
this.startTime = null; | ||
/** @type {object} options */ | ||
this.options = {}; | ||
} | ||
setOptions(options) { | ||
this.options = { | ||
...this.options, | ||
...options | ||
}; | ||
} | ||
setOptions(options) { | ||
this.options = { | ||
...this.options, | ||
...options, | ||
}; | ||
} | ||
resetCounters() { | ||
this.passedTests = 0; | ||
this.failedTests = 0; | ||
this.suiteStack = {}; | ||
} | ||
resetCounters() { | ||
this.passedTests = 0; | ||
this.failedTests = 0; | ||
this.suiteStack = {}; | ||
} | ||
startTimer() { | ||
this.startTime = performance.now(); | ||
} | ||
startTimer() { | ||
this.startTime = performance.now(); | ||
} | ||
getExecutionTime() { | ||
return ((performance.now() - this.startTime) / 1000).toFixed(2); | ||
getExecutionTime() { | ||
return ((performance.now() - this.startTime) / 1000).toFixed(2); | ||
} | ||
/** | ||
* Add a new suite to the stack and register it | ||
* @method | ||
* @param {object} suite - Test suite to add | ||
*/ | ||
pushSuite(suite) { | ||
let parentSuite = ""; | ||
// Get parent suite if exists | ||
if (suite.parentId) { | ||
parentSuite = this.getSuite(suite.parentId); | ||
} else { | ||
if (this.suiteStack[suite.id]) { | ||
console.warn( | ||
chalk.yellow(`There is already a Suite with the ID: ${suite.id}`), | ||
); | ||
suite.id = suite.name + suite.id; | ||
} | ||
} | ||
/** | ||
* Add a new suite to the stack and register it | ||
* @method | ||
* @param {object} suite - Test suite to add | ||
*/ | ||
pushSuite(suite) { | ||
// Create nested suite structure | ||
const nestedSuite = { | ||
...suite, | ||
children: [], | ||
tests: [], | ||
}; | ||
let parentSuite = ''; | ||
// Get parent suite if exists | ||
if (suite.parentId) { | ||
parentSuite = this.getSuite(suite.parentId) | ||
} | ||
else { | ||
if (this.suiteStack[suite.id]) { | ||
console.warn(chalk.yellow(`There is already a Suite with the ID: ${suite.id}`)); | ||
suite.id = suite.name + suite.id; | ||
} | ||
} | ||
// Create nested suite structure | ||
const nestedSuite = { | ||
...suite, | ||
children: [], | ||
tests: [] | ||
}; | ||
// Add to parent's children if exists | ||
if (parentSuite) { | ||
parentSuite.children.push(nestedSuite); | ||
} else { | ||
this.suiteStack[suite.id] = nestedSuite; | ||
} | ||
return nestedSuite; | ||
// Add to parent's children if exists | ||
if (parentSuite) { | ||
parentSuite.children.push(nestedSuite); | ||
} else { | ||
this.suiteStack[suite.id] = nestedSuite; | ||
} | ||
/** | ||
* Get suite by id. | ||
* @method | ||
* @param {string} path - Full suite path | ||
* @returns {object|undefined} Found suite | ||
*/ | ||
getSuite(parentId) { | ||
let suite = this.suiteStack[parentId]; | ||
return nestedSuite; | ||
} | ||
if (suite) { | ||
return suite; | ||
} | ||
/** | ||
* Get suite by id. | ||
* @method | ||
* @param {string} path - Full suite path | ||
* @returns {object|undefined} Found suite | ||
*/ | ||
getSuite(parentId) { | ||
let suite = this.suiteStack[parentId]; | ||
return this.searchSuiteStack(parentId, this.suiteStack); | ||
if (suite) { | ||
return suite; | ||
} | ||
return this.searchSuiteStack(parentId, this.suiteStack); | ||
} | ||
/** | ||
* Search the stack on each child | ||
* @param {string} parentId | ||
* @param {object} suiteStack | ||
* @returns {object} | ||
*/ | ||
searchSuiteStack(parentId, suiteStack) { | ||
// Helper function to search recursively through children | ||
function searchRecursively(suite) { | ||
// Check if current suite matches the ID | ||
if (suite.id === parentId) { | ||
return suite; | ||
} | ||
/** | ||
* Search the stack on each child | ||
* @param {string} parentId | ||
* @param {object} suiteStack | ||
* @returns {object} | ||
*/ | ||
searchSuiteStack(parentId, suiteStack) { | ||
// Helper function to search recursively through children | ||
function searchRecursively(suite) { | ||
// Check if current suite matches the ID | ||
if (suite.id === parentId) { | ||
return suite; | ||
} | ||
// If suite has children, search through them | ||
if (suite.children && suite.children.length > 0) { | ||
for (const child of suite.children) { | ||
const result = searchRecursively(child); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
} | ||
return null; | ||
// If suite has children, search through them | ||
if (suite.children && suite.children.length > 0) { | ||
for (const child of suite.children) { | ||
const result = searchRecursively(child); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
} | ||
// Search through each top-level suite in the stack | ||
for (const nestedSuite of Object.values(suiteStack)) { | ||
const result = searchRecursively(nestedSuite); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
return null; | ||
return null; | ||
} | ||
/** | ||
* Add test to a specific suite | ||
* @method | ||
* @param {string} suitePath - Full suite path | ||
* @param {object} test - Test case to add | ||
*/ | ||
addTestToSuite(suite, test) { | ||
suite.tests.push(test); | ||
// Search through each top-level suite in the stack | ||
for (const nestedSuite of Object.values(suiteStack)) { | ||
const result = searchRecursively(nestedSuite); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
printSummary() { | ||
return null; | ||
} | ||
Object.keys(this.suiteStack).forEach(id => { | ||
printSuite(this.suiteStack[id], 0, this.options); | ||
}); | ||
/** | ||
* Add test to a specific suite | ||
* @method | ||
* @param {string} suitePath - Full suite path | ||
* @param {object} test - Test case to add | ||
*/ | ||
addTestToSuite(suite, test) { | ||
suite.tests.push(test); | ||
} | ||
console.log(chalk.bold.cyan('\nTest Summary:')); | ||
console.log(chalk.green(` Passed: ${this.passedTests}`)); | ||
console.log(chalk.red(` Failed: ${this.failedTests}`)); | ||
console.log(chalk.blue(` Time: ${this.getExecutionTime()}s`)); | ||
printSummary() { | ||
Object.keys(this.suiteStack).forEach((id) => { | ||
printSuite(this.suiteStack[id], 0, this.options); | ||
}); | ||
} | ||
console.log(chalk.bold.cyan("\nTest Summary:")); | ||
console.log(chalk.green(` Passed: ${this.passedTests}`)); | ||
console.log(chalk.red(` Failed: ${this.failedTests}`)); | ||
console.log(chalk.blue(` Time: ${this.getExecutionTime()}s`)); | ||
} | ||
// Track all running tests | ||
testTracker = { | ||
pendingTests: new Set(), | ||
addTest: function (promise) { | ||
this.pendingTests.add(promise); | ||
promise.finally(() => this.pendingTests.delete(promise)); | ||
}, | ||
waitForAll: function () { | ||
return Promise.all(Array.from(this.pendingTests)); | ||
} | ||
}; | ||
// Track all running tests | ||
testTracker = { | ||
pendingTests: new Set(), | ||
addTest: function (promise) { | ||
this.pendingTests.add(promise); | ||
promise.finally(() => this.pendingTests.delete(promise)); | ||
}, | ||
waitForAll: function () { | ||
return Promise.all(Array.from(this.pendingTests)); | ||
}, | ||
}; | ||
} | ||
@@ -172,32 +168,59 @@ | ||
const printSuite = (suite, indent, options) => { | ||
const indentation = ' '.repeat(indent); | ||
const indentation = " ".repeat(indent); | ||
// Print suite's tests | ||
let results = suite.tests; | ||
if (options.quiet) { | ||
results = results.filter(result => result.status === 'failed'); | ||
// Print suite's tests | ||
let results = suite.tests; | ||
let hasFailingChildren = false; | ||
if (options.quiet) { | ||
results = results.filter((result) => result.status === "failed"); | ||
} | ||
// In TestState.js | ||
function hasFailingTests(suite) { | ||
// Base case: check current suite's tests | ||
if (suite.tests?.iterable?.some((test) => test.status === "failed")) { | ||
return true; | ||
} | ||
// Print suite name | ||
if (suite.children.length > 0 || results.length > 0) { | ||
console.log('\n' + indentation + chalk.yellow(chalk.bold(suite.name))); | ||
// Recursive case: check children | ||
if (suite.children) { | ||
return suite.children.some((child) => hasFailingTests(child)); | ||
} | ||
results.forEach(result => { | ||
if (result.status === 'failed') { | ||
console.log(indentation + chalk.red(` └─ ⛔ ${result.name} (${result.duration.toFixed(2)}ms)`)); | ||
console.log(indentation + chalk.red(` ${result.error.message}`)); | ||
} else { | ||
console.log(indentation + chalk.green(` └─ ✅ ${result.name} (${result.duration.toFixed(2)}ms)`)); | ||
} | ||
}); | ||
return false; | ||
} | ||
// Print child suites | ||
if (suite.children) { | ||
suite.children.forEach(child => printSuite(child, indent + 1, options)); | ||
// Your original code modified: | ||
if (suite.children) { | ||
hasFailingChildren = suite.children.some((child) => hasFailingTests(child)); | ||
} | ||
// Print suite name | ||
if (suite.children.length > 0 || results.length > 0 || hasFailingChildren) { | ||
console.log("\n" + indentation + chalk.yellow(chalk.bold(suite.name))); | ||
} | ||
results.forEach((result) => { | ||
if (result.status === "failed") { | ||
console.log( | ||
indentation + | ||
chalk.red(` └─ ⛔ ${result.name} (${result.duration.toFixed(2)}ms)`), | ||
); | ||
console.log(indentation + chalk.red(` ${result.error.message}`)); | ||
} else { | ||
console.log( | ||
indentation + | ||
chalk.green( | ||
` └─ ✅ ${result.name} (${result.duration.toFixed(2)}ms)`, | ||
), | ||
); | ||
} | ||
}); | ||
// Print child suites | ||
if (suite.children) { | ||
suite.children.forEach((child) => printSuite(child, indent + 1, options)); | ||
} | ||
}; | ||
export const state = new TestState(); | ||
export const state = new TestState(); |
import { runWebTestFunction } from "../src/runners/webRunner.js"; | ||
import { describe, it, assertEqual } from '../src/_codi.js'; | ||
import { describe, it, assertEqual } from "../src/_codi.js"; | ||
// Main test execution | ||
const results = await runWebTestFunction(async () => { | ||
const results = await runWebTestFunction( | ||
async () => { | ||
// Sequential setup tests | ||
@@ -11,27 +12,31 @@ await setupTests(); | ||
await Promise.all([ | ||
batchOne(), | ||
batchTwo(), | ||
batchThree(), | ||
batchFour() | ||
batchOne(), | ||
batchTwo(), | ||
batchThree(), | ||
batchFour(), | ||
batchFive(), | ||
batchSix(), | ||
]); | ||
}, { | ||
quiet: false, | ||
showSummary: true | ||
}); | ||
}, | ||
{ | ||
quiet: true, | ||
showSummary: true, | ||
}, | ||
); | ||
// Sequential setup tests | ||
async function setupTests() { | ||
describe({ name: 'Setup Tests', id: 'setup' }, async () => { | ||
it({ name: 'Should initilise setup', parentId: 'setup' }, async () => { | ||
await simulateDelay(250); | ||
assertEqual(true, true, 'Workspace initialized'); | ||
console.log('Test 1') | ||
}); | ||
describe({ name: "Setup Tests", id: "setup" }, async () => { | ||
it({ name: "Should initilise setup", parentId: "setup" }, async () => { | ||
await simulateDelay(250); | ||
assertEqual(true, true, "Workspace initialized"); | ||
console.log("Test 1"); | ||
}); | ||
it({ name: 'Should do some more setup', parentId: 'setup' }, async () => { | ||
await simulateDelay(150); | ||
assertEqual(true, true, 'Query system ready'); | ||
console.log('Test 2') | ||
}); | ||
it({ name: "Should do some more setup", parentId: "setup" }, async () => { | ||
await simulateDelay(150); | ||
assertEqual(true, true, "Query system ready"); | ||
console.log("Test 2"); | ||
}); | ||
}); | ||
} | ||
@@ -41,21 +46,21 @@ | ||
async function batchOne() { | ||
describe({ name: 'batch_1', id: '1' }, async () => { | ||
await Promise.all([ | ||
it({ name: 'Test 1.1', parentId: '1' }, async () => { | ||
await simulateDelay(100); | ||
assertEqual(true, true, 'Test 1.1 passed'); | ||
console.log('Test 4') | ||
}), | ||
it({ name: 'Test 1.2', parentId: '1' }, async () => { | ||
await simulateDelay(75); | ||
assertEqual(true, true, 'Test 1.2 passed'); | ||
console.log('Test 5') | ||
}), | ||
it({ name: 'Test 1.3', parentId: '1' }, async () => { | ||
await simulateDelay(50); | ||
assertEqual(false, false, 'Test 1.3 passed'); | ||
console.log('Test 6') | ||
}) | ||
]); | ||
}); | ||
describe({ name: "batch_1", id: "1" }, async () => { | ||
await Promise.all([ | ||
it({ name: "Test 1.1", parentId: "1" }, async () => { | ||
await simulateDelay(100); | ||
assertEqual(true, true, "Test 1.1 passed"); | ||
console.log("Test 4"); | ||
}), | ||
it({ name: "Test 1.2", parentId: "1" }, async () => { | ||
await simulateDelay(75); | ||
assertEqual(true, true, "Test 1.2 passed"); | ||
console.log("Test 5"); | ||
}), | ||
it({ name: "Test 1.3", parentId: "1" }, async () => { | ||
await simulateDelay(50); | ||
assertEqual(false, false, "Test 1.3 passed"); | ||
console.log("Test 6"); | ||
}), | ||
]); | ||
}); | ||
} | ||
@@ -65,21 +70,21 @@ | ||
async function batchTwo() { | ||
describe({ name: 'batch_2', id: '2', parentId: '1' }, async () => { | ||
Promise.all([ | ||
it({ name: 'Test 2.1', parentId: '2' }, async () => { | ||
await simulateDelay(125); | ||
assertEqual(true, true, 'Test 2.1 passed'); | ||
console.log('Test 7') | ||
}), | ||
it({ name: 'Test 2.2', parentId: '2' }, async () => { | ||
await simulateDelay(150); | ||
assertEqual(1, 2, 'This test should fail'); | ||
console.log('Test 8') | ||
}), | ||
it({ name: 'Test 2.3', parentId: '2' }, async () => { | ||
await simulateDelay(175); | ||
assertEqual(true, true, 'Test 2.3 passed'); | ||
console.log('Test 9') | ||
}) | ||
]); | ||
}); | ||
describe({ name: "batch_2", id: "2", parentId: "1" }, async () => { | ||
Promise.all([ | ||
it({ name: "Test 2.1", parentId: "2" }, async () => { | ||
await simulateDelay(125); | ||
assertEqual(true, true, "Test 2.1 passed"); | ||
console.log("Test 7"); | ||
}), | ||
it({ name: "Test 2.2", parentId: "2" }, async () => { | ||
await simulateDelay(150); | ||
assertEqual(1, 2, "This test should fail"); | ||
console.log("Test 8"); | ||
}), | ||
it({ name: "Test 2.3", parentId: "2" }, async () => { | ||
await simulateDelay(175); | ||
assertEqual(true, true, "Test 2.3 passed"); | ||
console.log("Test 9"); | ||
}), | ||
]); | ||
}); | ||
} | ||
@@ -89,49 +94,87 @@ | ||
async function batchThree() { | ||
describe({ name: 'batch_3', id: '3', parentId: '2' }, async () => { | ||
await Promise.all([ | ||
it({ name: 'Test 3.1', parentId: '3' }, async () => { | ||
await simulateDelay(200); | ||
assertEqual(true, true, 'Test 3.1 passed'); | ||
console.log('Test 10') | ||
}), | ||
it({ name: 'Test 3.2', parentId: '3' }, async () => { | ||
await simulateDelay(225); | ||
assertEqual(true, true, 'Test 4.2 passed'); | ||
console.log('Test 11') | ||
}), | ||
it({ name: 'Test 3.3', parentId: '3' }, async () => { | ||
await simulateDelay(250); | ||
assertEqual({ a: 1 }, { a: 1 }, 'Test 3.3 passed'); | ||
console.log('Test 12') | ||
}) | ||
]); | ||
}); | ||
describe({ name: "batch_3", id: "3", parentId: "2" }, async () => { | ||
await Promise.all([ | ||
it({ name: "Test 3.1", parentId: "3" }, async () => { | ||
await simulateDelay(200); | ||
assertEqual(true, true, "Test 3.1 passed"); | ||
console.log("Test 10"); | ||
}), | ||
it({ name: "Test 3.2", parentId: "3" }, async () => { | ||
await simulateDelay(225); | ||
assertEqual(true, true, "Test 4.2 passed"); | ||
console.log("Test 11"); | ||
}), | ||
it({ name: "Test 3.3", parentId: "3" }, async () => { | ||
await simulateDelay(250); | ||
assertEqual({ a: 1 }, { a: 1 }, "Test 3.3 passed"); | ||
console.log("Test 12"); | ||
}), | ||
]); | ||
}); | ||
} | ||
async function batchFour() { | ||
describe({ name: 'batch_4', id: '4', parentId: '3' }, async () => { | ||
await Promise.all([ | ||
it({ name: 'Test 4.1', parentId: '4' }, async () => { | ||
await simulateDelay(900); | ||
assertEqual(true, true, 'Test 4.1 passed'); | ||
console.log('Test 13') | ||
}), | ||
it({ name: 'Test 4.2', parentId: '4' }, async () => { | ||
await simulateDelay(3600); | ||
assertEqual(true, true, 'Test 4.2 passed'); | ||
console.log('Test 14') | ||
}), | ||
it({ name: 'Test 4.3', parentId: '4' }, async () => { | ||
await simulateDelay(500); | ||
assertEqual({ a: 1 }, { a: 2 }, 'Test 4.3 failed'); | ||
console.log('Test 15') | ||
}) | ||
]); | ||
}); | ||
describe({ name: "batch_4", id: "4", parentId: "3" }, async () => { | ||
await Promise.all([ | ||
it({ name: "Test 4.1", parentId: "4" }, async () => { | ||
await simulateDelay(900); | ||
assertEqual(true, true, "Test 4.1 passed"); | ||
console.log("Test 13"); | ||
}), | ||
it({ name: "Test 4.2", parentId: "4" }, async () => { | ||
await simulateDelay(3600); | ||
assertEqual(true, true, "Test 4.2 passed"); | ||
console.log("Test 14"); | ||
}), | ||
it({ name: "Test 4.3", parentId: "4" }, async () => { | ||
await simulateDelay(500); | ||
assertEqual({ a: 1 }, { a: 2 }, "Test 4.3 failed"); | ||
console.log("Test 15"); | ||
}), | ||
]); | ||
}); | ||
} | ||
async function batchFive() { | ||
describe({ name: "batch_5", id: "5" }, async () => { | ||
await Promise.all([ | ||
it({ name: "Test 5.1", parentId: "5" }, async () => { | ||
assertEqual(true, true, "Test 5.1 passed"); | ||
console.log("Test 16"); | ||
}), | ||
it({ name: "Test 5.2", parentId: "5" }, async () => { | ||
assertEqual(true, true, "Test 4.2 passed"); | ||
console.log("Test 17"); | ||
}), | ||
it({ name: "Test 5.3", parentId: "5" }, async () => { | ||
assertEqual({ a: 1 }, { a: 1 }, "Test 5.3 failed"); | ||
console.log("Test 18"); | ||
}), | ||
]); | ||
}); | ||
} | ||
async function batchSix() { | ||
describe({ name: "batch_6", id: "6", parentId: "5" }, async () => { | ||
await Promise.all([ | ||
it({ name: "Test 6.1", parentId: "6" }, async () => { | ||
assertEqual(true, true, "Test 6.1 passed"); | ||
console.log("Test 19"); | ||
}), | ||
it({ name: "Test 6.2", parentId: "6" }, async () => { | ||
assertEqual(true, true, "Test 6.2 passed"); | ||
console.log("Test 20"); | ||
}), | ||
it({ name: "Test 6.3", parentId: "6" }, async () => { | ||
assertEqual({ a: 1 }, { a: 2 }, "Test 6.3 failed"); | ||
console.log("Test 21"); | ||
}), | ||
]); | ||
}); | ||
} | ||
function simulateDelay(ms) { | ||
return new Promise(resolve => setTimeout(resolve, ms)); | ||
return new Promise((resolve) => setTimeout(resolve, ms)); | ||
} | ||
// console.log(results); | ||
// console.log(results); |
Sorry, the diff of this file is not supported yet
43595
1099