2023-09-02 08:23:26 +00:00
|
|
|
/// <reference path="./eltro.d.ts"/>
|
2022-01-11 09:43:48 +00:00
|
|
|
import * as readline from 'readline'
|
2022-07-04 10:23:41 +00:00
|
|
|
import { runWithCallbackSafe } from './callback.mjs'
|
2020-03-31 17:27:36 +00:00
|
|
|
import { printError } from './cli.mjs'
|
|
|
|
|
2021-06-02 12:08:22 +00:00
|
|
|
function Group(e, name) {
|
|
|
|
this.e = e
|
2020-03-31 17:27:36 +00:00
|
|
|
this.name = name
|
2020-04-01 16:42:13 +00:00
|
|
|
this.hasExclusive = false
|
2021-06-02 12:08:22 +00:00
|
|
|
this.parent = null
|
|
|
|
this.groups = []
|
2020-03-31 17:27:36 +00:00
|
|
|
this.tests = []
|
2021-06-02 12:08:22 +00:00
|
|
|
this.customTimeout = null
|
|
|
|
this.skipTest = false
|
|
|
|
this.isExclusive = false
|
2021-06-18 02:06:08 +00:00
|
|
|
this.before = null
|
|
|
|
this.after = null
|
2022-01-11 09:37:05 +00:00
|
|
|
this.beforeEach = null
|
|
|
|
this.afterEach = null
|
2021-06-02 12:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Group.prototype.timeout = function(time) {
|
|
|
|
this.customTimeout = time
|
|
|
|
}
|
|
|
|
|
|
|
|
Group.prototype.skip = function() {
|
|
|
|
this.skipTest = true
|
|
|
|
}
|
|
|
|
|
|
|
|
Group.prototype.__hasonly = function(markHas) {
|
|
|
|
if (this.skipTest) return
|
|
|
|
|
|
|
|
// Set hasExclusive with either mark or existing value
|
|
|
|
// Some groups might have .only() but that doesn't mean
|
|
|
|
// the children have .only() buut they should still be run
|
|
|
|
this.hasExclusive = this.hasExclusive || markHas
|
|
|
|
|
|
|
|
// Travel upwards to the root mark all the groups along the way
|
|
|
|
let g = this.parent
|
|
|
|
while (g) {
|
|
|
|
// If the parent has skipped marked, we definitely don't wanna
|
|
|
|
// mark that we have tests with exclusivity on.
|
|
|
|
if (g.skipTest) return
|
|
|
|
|
|
|
|
g.hasExclusive = true
|
|
|
|
g = g.parent
|
|
|
|
}
|
|
|
|
|
|
|
|
this.e.hasExclusive = true
|
|
|
|
}
|
|
|
|
|
|
|
|
Group.prototype.only = function() {
|
|
|
|
this.isExclusive = true
|
|
|
|
this.__hasonly(false)
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-01 16:42:13 +00:00
|
|
|
function Test(e, group, name, func) {
|
|
|
|
this.e = e
|
|
|
|
this.group = group
|
2020-03-31 17:27:36 +00:00
|
|
|
this.skipTest = false
|
2020-04-01 16:42:13 +00:00
|
|
|
this.isExclusive = false
|
2020-03-31 17:27:36 +00:00
|
|
|
this.customTimeout = null
|
2021-06-18 02:06:08 +00:00
|
|
|
this.isBasic = false
|
2020-03-31 17:27:36 +00:00
|
|
|
this.name = name
|
|
|
|
this.func = func
|
|
|
|
this.error = null
|
2023-09-02 08:23:26 +00:00
|
|
|
this.startTime = null
|
|
|
|
this.totalTime = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
Test.prototype.calculateTime = function() {
|
|
|
|
let end = process.hrtime(this.startTime)
|
|
|
|
this.totalTime = (end[0] * 1000 + Math.round(end[1] / 1000000))
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Test.prototype.timeout = function(time) {
|
|
|
|
this.customTimeout = time
|
|
|
|
}
|
|
|
|
|
|
|
|
Test.prototype.skip = function() {
|
|
|
|
this.skipTest = true
|
|
|
|
}
|
|
|
|
|
2020-04-01 16:42:13 +00:00
|
|
|
Test.prototype.only = function() {
|
2022-03-02 14:25:56 +00:00
|
|
|
if (!this.e.ignoreOnly) {
|
|
|
|
this.isExclusive = true
|
|
|
|
this.group.__hasonly(true)
|
|
|
|
}
|
2020-04-01 16:42:13 +00:00
|
|
|
}
|
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
Test.prototype.clone = function(prefix = '') {
|
|
|
|
var t = new Test(this.e, this.group, prefix + this.name, this.func)
|
|
|
|
let properties = ['skipTest', 'isExclusive', 'customTimeout', 'isBasic', 'error']
|
|
|
|
for (let key of properties) {
|
|
|
|
t[key] = this[key]
|
|
|
|
}
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
let stack = []
|
|
|
|
function captureUnknownErrors(e) {
|
|
|
|
stack.push(e)
|
|
|
|
}
|
|
|
|
function cancelCaptureUnknown(e) {
|
|
|
|
stack.splice(stack.indexOf(e), 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
process.on('uncaughtException', function(err) {
|
|
|
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
|
|
if (stack[i].captureOutsideExceptions) {
|
|
|
|
stack[i].captureOutsideExceptions(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
console.error('-- UNCAUGHT EXCPEPTION OUTSIDE OF TEST RUNNER --')
|
|
|
|
console.error(err)
|
|
|
|
})
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
function Eltro() {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process = process
|
2020-03-31 17:27:36 +00:00
|
|
|
this.__timeout = 2000
|
2020-04-01 16:42:13 +00:00
|
|
|
this.hasExclusive = false
|
2020-03-31 17:27:36 +00:00
|
|
|
this.reporter = 'list'
|
2020-04-01 15:35:33 +00:00
|
|
|
this.Eltro = Eltro
|
2021-06-02 12:08:22 +00:00
|
|
|
this.fileGroupMap = new Map()
|
|
|
|
this.groups = []
|
2020-04-01 17:16:46 +00:00
|
|
|
this.activeGroup = null
|
2020-03-31 17:27:36 +00:00
|
|
|
this.failedTests = []
|
|
|
|
this.hasTests = false
|
2023-09-28 09:33:43 +00:00
|
|
|
this.starting = null
|
2022-03-02 14:25:56 +00:00
|
|
|
this.ignoreOnly = false
|
2022-01-11 09:37:05 +00:00
|
|
|
this.logger = null
|
2020-03-31 17:27:36 +00:00
|
|
|
this.filename = ''
|
|
|
|
this.prefix = ''
|
2020-04-01 16:42:13 +00:00
|
|
|
this.temporary = {
|
|
|
|
timeout: 0,
|
|
|
|
skip: false,
|
|
|
|
only: false
|
|
|
|
}
|
2020-04-01 17:16:46 +00:00
|
|
|
this.describeTemporary = {
|
|
|
|
timeout: 0,
|
|
|
|
skip: false,
|
|
|
|
only: false
|
|
|
|
}
|
2023-09-02 08:23:26 +00:00
|
|
|
this.captureOutsideExceptions = null
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
Eltro.prototype.begin = function() {
|
2020-03-31 17:27:36 +00:00
|
|
|
if (this.starting) {
|
2020-04-01 15:35:33 +00:00
|
|
|
console.warn('WARNING: Multiple calls to Eltro.begin were done.')
|
2023-09-28 09:33:43 +00:00
|
|
|
console.warn(this.starting)
|
|
|
|
console.warn(new Error('Second call'))
|
2020-03-31 17:27:36 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
this.hasTests = false
|
2023-09-28 09:33:43 +00:00
|
|
|
this.starting = new Error('First call')
|
2020-03-31 17:27:36 +00:00
|
|
|
this.filename = ''
|
|
|
|
this.prefix = ''
|
2021-06-02 12:08:22 +00:00
|
|
|
this.fileGroupMap.clear()
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
Eltro.prototype.__runTest = async function(stats, test, prefix = 'Test', child = null) {
|
2024-09-20 19:09:20 +00:00
|
|
|
if (this.reporter === 'list' && prefix === 'Test') {
|
|
|
|
this.process.stdout.write(' \x1b[90m? ' + test.name + '\x1b[0m')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
let markRealTest = child || test
|
|
|
|
|
2020-03-31 17:27:36 +00:00
|
|
|
if (!test.skipTest) {
|
2022-01-11 09:37:05 +00:00
|
|
|
let err = await new Promise((resolve, reject) => {
|
2023-09-28 09:33:43 +00:00
|
|
|
if (test.error) {
|
|
|
|
return reject(test.error)
|
|
|
|
}
|
|
|
|
if (!test.func) {
|
|
|
|
return reject(new Error(`Test ${test.name} was missing function`))
|
|
|
|
}
|
2023-09-02 08:23:26 +00:00
|
|
|
this.captureOutsideExceptions = reject
|
2020-03-31 17:27:36 +00:00
|
|
|
// Flag to check if we finished
|
|
|
|
let finished = false
|
|
|
|
let timeout = test.customTimeout || this.__timeout
|
|
|
|
|
|
|
|
// Timeout timer in case test times out
|
|
|
|
let timer = setTimeout(function() {
|
|
|
|
if (finished === true) return
|
2023-09-02 08:23:26 +00:00
|
|
|
|
|
|
|
test.calculateTime()
|
2020-03-31 17:27:36 +00:00
|
|
|
reject(new Error('timeout of ' + timeout + 'ms exceeded. Ensure the done() callback is being called in this test.'))
|
|
|
|
}, timeout)
|
|
|
|
|
|
|
|
// start the test runner
|
|
|
|
try {
|
|
|
|
// Does it accept a callback
|
|
|
|
let checkIsCallback = (test.func.toString()).match(/^(function)? *\([^\)]+\)/)
|
|
|
|
let promise
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
test.startTime = process.hrtime()
|
2020-03-31 17:27:36 +00:00
|
|
|
// If the test requires callback, wrap it in a promise where callback
|
|
|
|
// either resolves or rejects that promise
|
|
|
|
if (checkIsCallback) {
|
2022-07-04 10:23:41 +00:00
|
|
|
promise = runWithCallbackSafe(test)
|
2020-03-31 17:27:36 +00:00
|
|
|
} else {
|
|
|
|
// Function doesn't require a callback, run it directly
|
|
|
|
promise = test.func()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the function we ran returned a promise
|
|
|
|
if (promise && promise.then && typeof(promise.then === 'function')) {
|
|
|
|
// If the promise from the function succeeded, resolve our promise.
|
|
|
|
// Otherwise reject it
|
|
|
|
promise.then(function() {
|
|
|
|
// check if our test had already finished and if so, do nothing
|
|
|
|
if (finished === true) return
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
test.calculateTime()
|
2020-03-31 17:27:36 +00:00
|
|
|
finished = true
|
|
|
|
clearTimeout(timer)
|
|
|
|
resolve()
|
|
|
|
}, function(err) {
|
|
|
|
// check if our test had already finished and if so, do nothing
|
|
|
|
if (finished === true) return
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
test.calculateTime()
|
2020-03-31 17:27:36 +00:00
|
|
|
finished = true
|
|
|
|
clearTimeout(timer)
|
|
|
|
reject(err)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
// check if our test had already finished and if so, do nothing
|
|
|
|
if (finished === true) return
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
test.calculateTime()
|
2020-03-31 17:27:36 +00:00
|
|
|
// Possible this was a synchronous test, pass immediately
|
|
|
|
finished = true
|
|
|
|
clearTimeout(timer)
|
|
|
|
resolve()
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
// check if our test had already finished and if so, do nothing
|
|
|
|
if (finished === true) return
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
test.calculateTime()
|
2020-03-31 17:27:36 +00:00
|
|
|
// An error occured while running function. Possible exception
|
|
|
|
// during a synchronous test or something else.
|
|
|
|
finished = true
|
|
|
|
clearTimeout(timer)
|
|
|
|
reject(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(function() {
|
2021-06-18 02:06:08 +00:00
|
|
|
if (prefix === 'Test') {
|
|
|
|
stats.passed++
|
|
|
|
}
|
2022-01-11 09:37:05 +00:00
|
|
|
return null
|
|
|
|
}, (err) => {
|
2021-06-02 15:30:45 +00:00
|
|
|
let saveError = err
|
|
|
|
if (!saveError) {
|
2021-06-18 02:06:08 +00:00
|
|
|
saveError = new Error(prefix + ' promise rejected with empty message')
|
2021-06-02 15:30:45 +00:00
|
|
|
} else if (typeof(saveError) !== 'object' || saveError.message == null || saveError.stack == null) {
|
|
|
|
try {
|
2021-06-18 02:06:08 +00:00
|
|
|
saveError = new Error(prefix + ' promise rejected with ' + JSON.stringify(saveError))
|
2021-06-02 15:30:45 +00:00
|
|
|
} catch (parseError) {
|
2021-06-18 02:06:08 +00:00
|
|
|
saveError = new Error(prefix + ' promise rejected with ' + saveError + ' (Error stringifying: ' + parseError.message + ')')
|
2021-06-02 15:30:45 +00:00
|
|
|
}
|
|
|
|
saveError.originalError = err
|
|
|
|
}
|
2022-01-11 09:37:05 +00:00
|
|
|
return saveError
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
)
|
2022-01-11 09:37:05 +00:00
|
|
|
|
|
|
|
if (err) {
|
|
|
|
markRealTest.error = err
|
|
|
|
this.failedTests.push(markRealTest.clone(child ? prefix : ''))
|
|
|
|
|
|
|
|
stats.failed++
|
|
|
|
}
|
2020-03-31 17:27:36 +00:00
|
|
|
} else {
|
|
|
|
stats.skipped++
|
|
|
|
}
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
this.captureOutsideExceptions = null
|
|
|
|
|
2020-03-31 17:27:36 +00:00
|
|
|
if (this.reporter === 'list') {
|
2024-09-20 19:09:20 +00:00
|
|
|
readline.clearLine(this.process.stdout, 0)
|
|
|
|
readline.cursorTo(this.process.stdout, 0, null)
|
2022-01-11 09:37:05 +00:00
|
|
|
if (markRealTest.skipTest) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' \x1b[94m- ' + markRealTest.name + '\x1b[0m\n')
|
2022-01-11 09:37:05 +00:00
|
|
|
} else if (!markRealTest.error) {
|
2023-09-03 19:44:45 +00:00
|
|
|
if (!test.name.startsWith('~')) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' \x1b[32m√\x1b[90m ' + markRealTest.name + ' (' + markRealTest.totalTime + 'ms)\x1b[0m\n')
|
2023-09-03 19:44:45 +00:00
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
} else if (prefix === 'Test') {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' \x1b[31m' + this.failedTests.length + ') ' + markRealTest.name + ' (' + markRealTest.totalTime + 'ms)\x1b[0m\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
} else if (this.reporter === 'dot') {
|
2022-01-11 09:37:05 +00:00
|
|
|
if (markRealTest.skipTest) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write('\x1b[94m.\x1b[0m')
|
|
|
|
} else if (markRealTest.error) {
|
|
|
|
this.process.stdout.write('\x1b[31m.\x1b[0m')
|
2021-06-18 02:06:08 +00:00
|
|
|
} else if (prefix === 'Test') {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write('\x1b[32m.\x1b[0m')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-02 12:08:22 +00:00
|
|
|
Eltro.prototype.__runGroup = async function(g, stats) {
|
|
|
|
if (g.tests.length) {
|
|
|
|
if (this.reporter === 'list') {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' ' + g.name + '\n')
|
2021-06-02 12:08:22 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
if (g.before) {
|
2023-09-03 19:44:45 +00:00
|
|
|
for (let i = 0; i < g.before.length; i++) {
|
|
|
|
await this.__runTest(stats, g.before[i], 'Before')
|
|
|
|
if (g.before[i].error) return
|
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
for (let x = 0; x < g.tests.length; x++) {
|
|
|
|
if (!g.tests[x].skipTest && g.tests[x].isExclusive === g.hasExclusive) {
|
2022-01-11 09:37:05 +00:00
|
|
|
if (g.beforeEach) {
|
2023-09-03 19:44:45 +00:00
|
|
|
for (let i = 0; i < g.beforeEach.length && !g.tests[x].error; i++) {
|
|
|
|
await this.__runTest(stats, g.beforeEach[i], 'Before each: ', g.tests[x])
|
|
|
|
}
|
2022-01-11 09:37:05 +00:00
|
|
|
if (!g.tests[x].error) {
|
|
|
|
await this.__runTest(stats, g.tests[x])
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
await this.__runTest(stats, g.tests[x])
|
|
|
|
}
|
|
|
|
if (g.afterEach) {
|
2023-09-03 19:44:45 +00:00
|
|
|
let oldError = g.tests[x].error
|
|
|
|
g.tests[x].error = null
|
|
|
|
for (let i = 0; i < g.afterEach.length && !g.tests[x].error; i++) {
|
|
|
|
await this.__runTest(stats, g.afterEach[i], 'After each: ', g.tests[x])
|
|
|
|
}
|
|
|
|
if (oldError) {
|
|
|
|
g.tests[x].error = oldError
|
|
|
|
}
|
2022-01-11 09:37:05 +00:00
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (let x = 0; x < g.groups.length; x++) {
|
2022-01-11 09:37:05 +00:00
|
|
|
if (!g.groups[x].skipTest && g.hasExclusive === (g.groups[x].hasExclusive || g.groups[x].isExclusive)) {
|
|
|
|
await this.__runGroup(g.groups[x], stats)
|
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
if (g.after) {
|
2023-09-03 19:44:45 +00:00
|
|
|
for (let i = 0; i < g.after.length && !g.after.error; i++) {
|
|
|
|
await this.__runTest(stats, g.after[i], 'After')
|
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
}
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
Eltro.prototype.run = async function() {
|
2022-01-11 09:37:05 +00:00
|
|
|
if (this.reporter && this.reporter !== 'test') {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write('' + '\n')
|
|
|
|
this.process.stdout.write('' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
captureUnknownErrors(this)
|
|
|
|
|
2020-03-31 17:27:36 +00:00
|
|
|
let stats = {
|
|
|
|
passed: 0,
|
|
|
|
failed: 0,
|
|
|
|
skipped: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
let start = process.hrtime()
|
2021-06-02 12:08:22 +00:00
|
|
|
for (let i = 0; i < this.groups.length; i++) {
|
|
|
|
if (!this.groups[i].skipTest && this.hasExclusive === (this.groups[i].hasExclusive || this.groups[i].isExclusive)) {
|
|
|
|
await this.__runGroup(this.groups[i], stats)
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
let end = process.hrtime(start)
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
cancelCaptureUnknown(this)
|
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
if (this.reporter === 'test') {
|
|
|
|
if (this.logger && this.logger.log) {
|
2023-09-03 19:44:45 +00:00
|
|
|
for (let x = 0; x < this.failedTests.length; x++) {
|
|
|
|
let test = this.failedTests[x];
|
|
|
|
this.logger.log(test.name, test.error)
|
2022-01-11 09:37:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (this.reporter) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write('' + '\n')
|
|
|
|
this.process.stdout.write('' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
if (stats.passed) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' \x1b[32m' + stats.passed + ' passing \x1b[90m(' + (end[0] * 1000 + Math.round(end[1] / 1000000)) + 'ms)\x1b[0m' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
if (stats.failed) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' \x1b[31m' + stats.failed + ' failing\x1b[0m' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
if (stats.skipped) {
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' \x1b[94m' + stats.skipped + ' pending\x1b[0m' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write('' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
|
|
|
|
if (this.failedTests.length) {
|
|
|
|
for (let x = 0; x < this.failedTests.length; x++) {
|
|
|
|
let test = this.failedTests[x];
|
2024-09-20 19:09:20 +00:00
|
|
|
this.process.stdout.write(' ' + (x + 1) + ') ' + test.name + ':' + '\n')
|
2020-03-31 17:27:36 +00:00
|
|
|
printError(test.error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
return stats
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
Eltro.prototype.setFilename = function(filename) {
|
2021-06-02 12:08:22 +00:00
|
|
|
if (!this.fileGroupMap.has(filename)) {
|
|
|
|
let g = new Group(this, filename + ':')
|
|
|
|
this.groups.push(g)
|
|
|
|
this.fileGroupMap.set(filename, g)
|
|
|
|
}
|
|
|
|
this.activeGroup = this.fileGroupMap.get(filename)
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
Eltro.prototype.resetFilename = function() {
|
2021-06-02 12:08:22 +00:00
|
|
|
this.activeGroup = null
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
let beforesandafters = [
|
2023-09-03 19:44:45 +00:00
|
|
|
['before', '~Before', false],
|
|
|
|
['after', '~After', false],
|
|
|
|
['beforeEach', '~Before each', true],
|
|
|
|
['afterEach', '~After each', true],
|
2022-01-11 09:37:05 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
beforesandafters.forEach(function(item) {
|
2023-09-03 19:44:45 +00:00
|
|
|
let beforeAfter = item[0]
|
|
|
|
let fullName = item[1]
|
|
|
|
let bringToChildren = item[2]
|
|
|
|
|
|
|
|
Eltro.prototype[beforeAfter] = function(func) {
|
2022-01-11 09:37:05 +00:00
|
|
|
if (!this.activeGroup) {
|
|
|
|
throw new Error('Tests outside groups are not allowed.')
|
|
|
|
}
|
2023-09-03 19:44:45 +00:00
|
|
|
|
|
|
|
let test = func
|
|
|
|
|
|
|
|
if (!(test instanceof Test)) {
|
|
|
|
test = new Test(this, this.activeGroup, fullName + ': ' + this.activeGroup.name, func)
|
|
|
|
}
|
2021-06-18 02:06:08 +00:00
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
if (this.temporary.timeout || this.activeGroup.customTimeout) {
|
|
|
|
test.timeout(this.temporary.timeout || this.activeGroup.customTimeout)
|
|
|
|
this.temporary.timeout = 0
|
|
|
|
}
|
2023-09-03 19:44:45 +00:00
|
|
|
|
|
|
|
this.activeGroup[beforeAfter] = this.activeGroup[beforeAfter] || []
|
|
|
|
this.activeGroup[beforeAfter].push(test)
|
|
|
|
|
|
|
|
if (bringToChildren) {
|
|
|
|
for (let group of this.activeGroup.groups) {
|
|
|
|
group[beforeAfter].push(test)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-11 09:37:05 +00:00
|
|
|
return test
|
|
|
|
}
|
|
|
|
})
|
2021-06-18 02:06:08 +00:00
|
|
|
|
2023-09-03 19:44:45 +00:00
|
|
|
let bringToChildren = ['beforeEach', 'afterEach']
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
Eltro.prototype.describe = function(name, func) {
|
2021-06-02 12:08:22 +00:00
|
|
|
let before = this.activeGroup
|
2020-04-01 17:16:46 +00:00
|
|
|
|
2021-06-02 12:08:22 +00:00
|
|
|
let prefix = before ? before.name + ' ' : ''
|
|
|
|
|
|
|
|
this.activeGroup = new Group(this, prefix + name)
|
2020-04-01 17:16:46 +00:00
|
|
|
|
2020-03-31 17:27:36 +00:00
|
|
|
if (before) {
|
2021-06-02 12:08:22 +00:00
|
|
|
before.groups.push(this.activeGroup)
|
|
|
|
this.activeGroup.parent = before
|
|
|
|
this.activeGroup.customTimeout = before.customTimeout
|
2020-03-31 17:27:36 +00:00
|
|
|
} else {
|
2021-06-02 12:08:22 +00:00
|
|
|
this.groups.push(this.activeGroup)
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
|
|
|
|
if (this.temporary.timeout) {
|
|
|
|
this.activeGroup.timeout(this.temporary.timeout)
|
|
|
|
this.temporary.timeout = 0
|
|
|
|
}
|
|
|
|
if (this.temporary.skip) {
|
|
|
|
this.activeGroup.skip()
|
|
|
|
this.temporary.skip = false
|
|
|
|
}
|
|
|
|
if (this.temporary.only) {
|
|
|
|
this.activeGroup.only()
|
|
|
|
this.temporary.only = false
|
|
|
|
}
|
|
|
|
|
2023-09-03 19:44:45 +00:00
|
|
|
if (before) {
|
|
|
|
for (let beforeAfter of bringToChildren) {
|
|
|
|
if (!before[beforeAfter]) continue
|
|
|
|
|
|
|
|
for (let test of before[beforeAfter]) {
|
|
|
|
this[beforeAfter](test)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-31 17:27:36 +00:00
|
|
|
func()
|
2021-06-02 12:08:22 +00:00
|
|
|
|
|
|
|
this.activeGroup = before
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-01 16:42:13 +00:00
|
|
|
Eltro.prototype.timeout = function(time) {
|
|
|
|
this.temporary.timeout = time
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
|
|
|
Eltro.prototype.skip = function() {
|
|
|
|
this.temporary.skip = true
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
|
|
|
Eltro.prototype.only = function() {
|
2022-03-02 14:25:56 +00:00
|
|
|
if (!this.ignoreOnly) {
|
|
|
|
this.temporary.only = true
|
|
|
|
}
|
2020-04-01 16:42:13 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
Eltro.prototype.test = function(name, func) {
|
2021-06-02 12:08:22 +00:00
|
|
|
if (!this.activeGroup) {
|
|
|
|
throw new Error('Tests outside groups are not allowed.')
|
2020-03-31 17:27:36 +00:00
|
|
|
}
|
2020-04-01 16:42:13 +00:00
|
|
|
|
2023-09-28 09:33:43 +00:00
|
|
|
let test = new Test(
|
|
|
|
this,
|
|
|
|
this.activeGroup,
|
|
|
|
[this.activeGroup.name.trim(), (name || '').trim()].filter(x => x).join(' '),
|
|
|
|
func
|
|
|
|
)
|
2021-06-02 12:08:22 +00:00
|
|
|
this.activeGroup.tests.push(test)
|
|
|
|
|
2023-09-28 09:33:43 +00:00
|
|
|
if (name == null) {
|
|
|
|
test.error = new Error(`An empty test or missing name under ${this.activeGroup.name.trim()} was found`)
|
|
|
|
}
|
|
|
|
|
2021-06-02 12:08:22 +00:00
|
|
|
if (this.temporary.only && !this.temporary.skip) {
|
2020-04-01 16:42:13 +00:00
|
|
|
test.only()
|
|
|
|
this.temporary.only = false
|
2020-04-01 17:16:46 +00:00
|
|
|
} else if (this.temporary.only) {
|
|
|
|
this.temporary.only = false
|
2020-04-01 16:42:13 +00:00
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
if (this.temporary.skip) {
|
2020-04-01 16:42:13 +00:00
|
|
|
test.skip()
|
|
|
|
this.temporary.skip = false
|
|
|
|
}
|
2021-06-02 12:08:22 +00:00
|
|
|
if (this.temporary.timeout || this.activeGroup.customTimeout) {
|
|
|
|
test.timeout(this.temporary.timeout || this.activeGroup.customTimeout)
|
2020-04-01 16:42:13 +00:00
|
|
|
this.temporary.timeout = 0
|
|
|
|
}
|
2020-03-31 17:27:36 +00:00
|
|
|
return test
|
|
|
|
}
|
|
|
|
|
2020-04-01 15:35:33 +00:00
|
|
|
export default new Eltro()
|