eltro: Fixed flow. before/after/beforeEach/afterEach now can be defined multiple times in a group. In addition, beforeEach and afterEach get called for each children of said group.
continuous-integration/appveyor/branch AppVeyor build failed Details

master
Jonatan Nilsson 2023-09-03 19:44:45 +00:00
parent c09a4c805e
commit 25f50483e1
2 changed files with 515 additions and 78 deletions

View File

@ -276,7 +276,9 @@ Eltro.prototype.__runTest = async function(stats, test, prefix = 'Test', child =
if (markRealTest.skipTest) {
process.stdout.write(' \x1b[94m- ' + markRealTest.name + '\x1b[0m\n')
} else if (!markRealTest.error) {
process.stdout.write(' \x1b[32m√\x1b[90m ' + markRealTest.name + ' (' + markRealTest.totalTime + 'ms)\x1b[0m\n')
if (!test.name.startsWith('~')) {
process.stdout.write(' \x1b[32m√\x1b[90m ' + markRealTest.name + ' (' + markRealTest.totalTime + 'ms)\x1b[0m\n')
}
} else if (prefix === 'Test') {
process.stdout.write(' \x1b[31m' + this.failedTests.length + ') ' + markRealTest.name + ' (' + markRealTest.totalTime + 'ms)\x1b[0m\n')
}
@ -298,14 +300,17 @@ Eltro.prototype.__runGroup = async function(g, stats) {
}
}
if (g.before) {
await this.__runTest(stats, g.before, 'Before')
if (g.before.error) return
for (let i = 0; i < g.before.length; i++) {
await this.__runTest(stats, g.before[i], 'Before')
if (g.before[i].error) return
}
}
for (let x = 0; x < g.tests.length; x++) {
if (!g.tests[x].skipTest && g.tests[x].isExclusive === g.hasExclusive) {
if (g.beforeEach) {
await this.__runTest(stats, g.beforeEach, 'Before each: ', g.tests[x])
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])
}
if (!g.tests[x].error) {
await this.__runTest(stats, g.tests[x])
}
@ -313,24 +318,26 @@ Eltro.prototype.__runGroup = async function(g, stats) {
await this.__runTest(stats, g.tests[x])
}
if (g.afterEach) {
await this.__runTest(stats, g.afterEach, 'After each: ', g.tests[x])
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
}
}
}
}
for (let x = 0; x < g.groups.length; x++) {
if (!g.groups[x].skipTest && g.hasExclusive === (g.groups[x].hasExclusive || g.groups[x].isExclusive)) {
if (g.beforeEach) {
await this.__runTest(stats, g.beforeEach, g.groups[x].name + ': ', g.beforeEach)
if (g.beforeEach.error) continue
}
await this.__runGroup(g.groups[x], stats)
if (g.afterEach) {
await this.__runTest(stats, g.afterEach, g.groups[x].name + ': ', g.afterEach)
}
}
}
if (g.after) {
await this.__runTest(stats, g.after, 'After')
for (let i = 0; i < g.after.length && !g.after.error; i++) {
await this.__runTest(stats, g.after[i], 'After')
}
}
}
@ -360,11 +367,9 @@ Eltro.prototype.run = async function() {
if (this.reporter === 'test') {
if (this.logger && this.logger.log) {
if (this.failedTests.length) {
for (let x = 0; x < this.failedTests.length; x++) {
let test = this.failedTests[x];
this.logger.log(test.name, test.error)
}
for (let x = 0; x < this.failedTests.length; x++) {
let test = this.failedTests[x];
this.logger.log(test.name, test.error)
}
}
} else if (this.reporter) {
@ -406,30 +411,48 @@ Eltro.prototype.resetFilename = function() {
}
let beforesandafters = [
['before', 'Before'],
['after', 'After'],
['beforeEach', 'Before each'],
['afterEach', 'After each'],
['before', '~Before', false],
['after', '~After', false],
['beforeEach', '~Before each', true],
['afterEach', '~After each', true],
]
beforesandafters.forEach(function(item) {
Eltro.prototype[item[0]] = function(func) {
let beforeAfter = item[0]
let fullName = item[1]
let bringToChildren = item[2]
Eltro.prototype[beforeAfter] = function(func) {
if (!this.activeGroup) {
throw new Error('Tests outside groups are not allowed.')
}
let test = new Test(this, this.activeGroup, item[1] + ': ' + this.activeGroup.name, func)
let test = func
if (!(test instanceof Test)) {
test = new Test(this, this.activeGroup, fullName + ': ' + this.activeGroup.name, func)
}
if (this.temporary.timeout || this.activeGroup.customTimeout) {
test.timeout(this.temporary.timeout || this.activeGroup.customTimeout)
this.temporary.timeout = 0
}
this.activeGroup[item[0]] = test
this.activeGroup[beforeAfter] = this.activeGroup[beforeAfter] || []
this.activeGroup[beforeAfter].push(test)
if (bringToChildren) {
for (let group of this.activeGroup.groups) {
group[beforeAfter].push(test)
}
}
return test
}
})
let bringToChildren = ['beforeEach', 'afterEach']
Eltro.prototype.describe = function(name, func) {
let before = this.activeGroup
@ -458,6 +481,16 @@ Eltro.prototype.describe = function(name, func) {
this.temporary.only = false
}
if (before) {
for (let beforeAfter of bringToChildren) {
if (!before[beforeAfter]) continue
for (let test of before[beforeAfter]) {
this[beforeAfter](test)
}
}
}
func()
this.activeGroup = before

View File

@ -52,23 +52,74 @@ e.describe('#before()', function() {
assert.strictEqual(secondBefore, 1)
assert.strictEqual(thirdBefore, 4)
})
})
e.test('should support multiple functions in describe group', async function() {
let assertRan = 0
let firstBefore = -1
let secondBefore = -1
let thirdBefore = -1
let fourthBefore = -1
e.describe('#beforeEach()', function() {
e.test('should support functions in describe group and run before each test and group', async function() {
const t = CreateT()
t.begin()
t.describe('', function() {
let outside = 0
t.before(function() {
firstBefore = assertRan
})
t.describe('', function() {
t.before(function() {
thirdBefore = assertRan
})
t.test('', function() { assertRan++ })
t.test('', function() { assertRan++ })
t.test('', function() { assertRan++ })
})
t.describe('', function() {
t.before(function() {
fourthBefore = assertRan
})
t.test('', function() { assertRan++ })
})
t.test('', function() { assertRan++ })
t.before(function() {
secondBefore = assertRan
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(assertRan, 5)
assert.strictEqual(stats.passed, 5)
assert.strictEqual(firstBefore, 0)
assert.strictEqual(secondBefore, 0)
assert.strictEqual(thirdBefore, 1)
assert.strictEqual(fourthBefore, 4)
})
})
e.describe('#beforeEach()', function() {
e.test('should support functions in describe group and run before each test and each test in every group', async function() {
let outside = 0
const t = CreateT()
t.begin()
t.describe('', function() {
t.beforeEach(function() {
outside++
})
t.describe('', function() {
t.before(function() {
assert.strictEqual(outside, 2)
})
let inside = 0
t.before(function() {
assert.strictEqual(outside, 1)
})
t.beforeEach(function() {
inside++
})
@ -79,11 +130,12 @@ e.describe('#beforeEach()', function() {
})
t.describe('', function() {
t.before(function() {
assert.strictEqual(outside, 3)
})
let insideSecond = 0
let insideSecond = 0
t.before(function() {
assert.strictEqual(outside, 4)
})
t.beforeEach(function() {
assert.strictEqual(insideSecond, 0)
insideSecond++
@ -99,6 +151,97 @@ e.describe('#beforeEach()', function() {
assert.strictEqual(stats.passed, 5)
assert.strictEqual(stats.failed, 0)
assert.strictEqual(stats.skipped, 0)
assert.strictEqual(outside, 5)
})
e.test('should work even if before is specifed after all the tests', async function() {
let outside = 0
const t = CreateT()
t.begin()
t.describe('', function() {
t.describe('', function() {
let inside = 0
t.before(function() {
assert.strictEqual(outside, 1)
})
t.test('', function() { assert.strictEqual(inside, 1) })
t.test('', function() { assert.strictEqual(inside, 2) })
t.test('', function() { assert.strictEqual(inside, 3) })
t.beforeEach(function() {
inside++
})
})
t.describe('', function() {
let insideSecond = 0
t.before(function() {
assert.strictEqual(outside, 4)
})
t.test('', function() { assert.strictEqual(insideSecond, 1) })
t.beforeEach(function() {
assert.strictEqual(insideSecond, 0)
insideSecond++
})
})
t.test('', function() { assert.strictEqual(outside, 1) })
t.beforeEach(function() {
outside++
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(stats.passed, 5)
assert.strictEqual(stats.failed, 0)
assert.strictEqual(stats.skipped, 0)
assert.strictEqual(outside, 5)
})
e.test('should support multiple beforeEach', async function() {
let outside = 0
let inside = 0
const t = CreateT()
t.begin()
t.describe('', function() {
t.beforeEach(function() {
outside++
})
t.describe('', function() {
t.beforeEach(function() {
inside++
})
t.test('', function() { assert.strictEqual(inside, 2) })
t.test('', function() { assert.strictEqual(inside, 4) })
t.test('', function() { assert.strictEqual(inside, 6) })
t.beforeEach(function() {
inside++
})
})
t.test('', function() { assert.strictEqual(outside, 2) })
t.beforeEach(function() {
outside++
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(stats.passed, 4)
assert.strictEqual(stats.failed, 0)
assert.strictEqual(stats.skipped, 0)
assert.strictEqual(outside, 8)
})
e.test('should be able to keep track of every error that occurs', async function() {
@ -112,6 +255,7 @@ e.describe('#beforeEach()', function() {
t.describe('CCCC', function() {
t.test('', function() { })
t.test('', function() { })
})
t.describe('DDDD', function() {
@ -121,20 +265,24 @@ e.describe('#beforeEach()', function() {
t.test('AAAA', function() { })
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 3)
assert.strictEqual(t.logger.log.callCount, 3)
assert.match(t.logger.log.firstCall[1].message, /1/)
assert.match(t.logger.log.firstCall[0], /before each/i)
assert.match(t.logger.log.firstCall[0], /AAAA/)
assert.match(t.logger.log.firstCall[0], /BBBB/)
assert.match(t.logger.log.secondCall[1].message, /2/)
assert.match(t.logger.log.secondCall[0], /before each/i)
assert.match(t.logger.log.secondCall[0], /CCCC/)
assert.match(t.logger.log.secondCall[0], /BBBB/)
assert.match(t.logger.log.thirdCall[1].message, /3/)
assert.match(t.logger.log.thirdCall[0], /before each/i)
assert.match(t.logger.log.thirdCall[0], /DDDD/)
assert.match(t.logger.log.thirdCall[0], /BBBB/)
assert.strictEqual(t.failedTests.length, 4)
assert.strictEqual(t.logger.log.callCount, 4)
assert.match(t.logger.log.getCallN(1)[1].message, /1/)
assert.match(t.logger.log.getCallN(1)[0], /before each/i)
assert.match(t.logger.log.getCallN(1)[0], /AAAA/)
assert.match(t.logger.log.getCallN(1)[0], /BBBB/)
assert.match(t.logger.log.getCallN(2)[1].message, /2/)
assert.match(t.logger.log.getCallN(2)[0], /before each/i)
assert.match(t.logger.log.getCallN(2)[0], /CCCC/)
assert.match(t.logger.log.getCallN(2)[0], /BBBB/)
assert.match(t.logger.log.getCallN(3)[1].message, /3/)
assert.match(t.logger.log.getCallN(3)[0], /before each/i)
assert.match(t.logger.log.getCallN(3)[0], /CCCC/)
assert.match(t.logger.log.getCallN(3)[0], /BBBB/)
assert.match(t.logger.log.getCallN(4)[1].message, /4/)
assert.match(t.logger.log.getCallN(4)[0], /before each/i)
assert.match(t.logger.log.getCallN(4)[0], /DDDD/)
assert.match(t.logger.log.getCallN(4)[0], /BBBB/)
})
})
@ -179,6 +327,81 @@ e.describe('#after()', function() {
assert.strictEqual(secondAfter, 4)
assert.strictEqual(thirdAfter, 5)
})
e.test('should support multiple functions in describe group', async function() {
let assertRan = 0
let firstAfter = -1
let secondAfter = -1
let thirdAfter = -1
let fourthAfter = -1
const t = CreateT()
t.begin()
t.describe('', function() {
t.after(function() {
firstAfter = assertRan
})
t.describe('', function() {
t.after(function() {
thirdAfter = assertRan
})
t.test('', function() { assertRan++ })
t.test('', function() { assertRan++ })
t.test('', function() { assertRan++ })
})
t.describe('', function() {
t.after(function() {
fourthAfter = assertRan
})
t.test('', function() { assertRan++ })
})
t.test('', function() { assertRan++ })
t.after(function() {
secondAfter = assertRan
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(stats.passed, 5)
assert.strictEqual(assertRan, 5)
assert.strictEqual(firstAfter, 5)
assert.strictEqual(secondAfter, 5)
assert.strictEqual(thirdAfter, 4)
assert.strictEqual(fourthAfter, 5)
})
e.test('should log even if it throws and test throws', async function() {
const assertError = new Error('test')
const t = CreateT()
t.begin()
t.describe('', function() {
t.after(function() { throw assertError })
t.describe('', function() {
t.after(function() { throw assertError })
t.test('', function() { throw assertError })
t.test('', function() { })
t.test('', function() { throw assertError })
})
t.test('', function() { throw assertError })
t.after(function() { throw assertError })
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 6)
assert.strictEqual(stats.passed, 1)
for (let failedTest of t.failedTests) {
assert.strictEqual(failedTest.error, assertError)
}
})
})
e.describe('#afterEach()', function() {
@ -187,14 +410,16 @@ e.describe('#afterEach()', function() {
t.begin()
t.describe('', function() {
let outside = 0
t.afterEach(function() {
outside++
})
t.describe('', function() {
let inside = 0
t.before(function() { assert.strictEqual(outside, 1) })
let inside = 0
t.afterEach(function() {
inside++
})
@ -206,10 +431,11 @@ e.describe('#afterEach()', function() {
t.after(function() { assert.strictEqual(inside, 3) })
})
t.describe('', function() {
t.before(function() { assert.strictEqual(outside, 2) })
t.describe('', function() {
let inside = 0
t.before(function() { assert.strictEqual(outside, 4) })
let inside = 0
t.afterEach(function() {
inside++
})
@ -221,7 +447,185 @@ e.describe('#afterEach()', function() {
t.test('', function() { assert.strictEqual(outside, 0) })
t.after(function() { assert.strictEqual(outside, 3) })
t.after(function() { assert.strictEqual(outside, 5) })
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(stats.passed, 5)
assert.strictEqual(stats.failed, 0)
assert.strictEqual(stats.skipped, 0)
})
e.test('should work even if after is specified after the tests', async function() {
const t = CreateT()
t.begin()
t.describe('', function() {
let outside = 0
t.describe('', function() {
let inside = 0
t.before(function() { assert.strictEqual(outside, 1) })
t.test('', function() { assert.strictEqual(inside, 0) })
t.test('', function() { assert.strictEqual(inside, 1) })
t.test('', function() { assert.strictEqual(inside, 2) })
t.after(function() { assert.strictEqual(inside, 3) })
t.afterEach(function() {
inside++
})
})
t.describe('', function() {
let inside = 0
t.before(function() { assert.strictEqual(outside, 4) })
t.test('', function() { assert.strictEqual(inside, 0) })
t.after(function() { assert.strictEqual(inside, 1) })
t.afterEach(function() {
inside++
})
})
t.test('', function() { assert.strictEqual(outside, 0) })
t.after(function() { assert.strictEqual(outside, 5) })
t.afterEach(function() {
outside++
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
assert.strictEqual(stats.passed, 5)
assert.strictEqual(stats.failed, 0)
assert.strictEqual(stats.skipped, 0)
})
e.test('should run even if each test throws', async function() {
let outside = 0
let inside = 0
const assertError = new Error('test')
const t = CreateT()
t.begin()
t.describe('', function() {
t.describe('', function() {
t.test('', function() { throw assertError })
t.test('', function() { throw assertError })
t.test('', function() { throw assertError })
t.afterEach(function() {
inside++
})
})
t.test('', function() { throw assertError })
t.afterEach(function() {
outside++
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 4)
for (let failedTest of t.failedTests) {
assert.strictEqual(failedTest.error, assertError)
}
assert.strictEqual(stats.passed, 0)
assert.strictEqual(stats.failed, 4)
assert.strictEqual(stats.skipped, 0)
assert.strictEqual(outside, 4)
assert.strictEqual(inside, 3)
})
e.test('should log even if afterEach fails', async function() {
const assertError = new Error('test')
const t = CreateT()
t.begin()
t.describe('', function() {
t.describe('', function() {
t.test('', function() { throw assertError })
t.test('', function() { throw assertError })
t.test('', function() { throw assertError })
t.afterEach(function() { throw assertError })
})
t.test('', function() { throw assertError })
t.afterEach(function() { throw assertError })
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 8)
for (let failedTest of t.failedTests) {
assert.strictEqual(failedTest.error, assertError)
}
assert.strictEqual(stats.passed, 0)
assert.strictEqual(stats.failed, 8)
assert.strictEqual(stats.skipped, 0)
})
e.test('should support multiple afterEach', async function() {
const t = CreateT()
t.begin()
t.describe('', function() {
let outside = 0
t.afterEach(function() {
outside++
})
t.describe('', function() {
let inside = 0
t.before(function() { assert.strictEqual(outside, 2) })
t.afterEach(function() {
inside++
})
t.test('', function() { assert.strictEqual(inside, 0) })
t.test('', function() { assert.strictEqual(inside, 2) })
t.test('', function() { assert.strictEqual(inside, 4) })
t.after(function() { assert.strictEqual(inside, 6) })
t.afterEach(function() {
inside++
})
})
t.describe('', function() {
let inside = 0
t.before(function() { assert.strictEqual(outside, 8) })
t.afterEach(function() {
inside++
})
t.test('', function() { assert.strictEqual(inside, 0) })
t.after(function() { assert.strictEqual(inside, 2) })
t.afterEach(function() {
inside++
})
})
t.test('', function() { assert.strictEqual(outside, 0) })
t.after(function() { assert.strictEqual(outside, 10) })
t.afterEach(function() {
outside++
})
})
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 0)
@ -254,26 +658,26 @@ e.describe('#afterEach()', function() {
let stats = await t.run()
assert.strictEqual(t.failedTests.length, 5)
assert.strictEqual(t.logger.log.callCount, 5)
assert.match(t.logger.log.getCall(0)[1].message, /1/)
assert.match(t.logger.log.getCall(0)[0], /after each/i)
assert.match(t.logger.log.getCall(0)[0], /AAAA/)
assert.match(t.logger.log.getCall(0)[0], /YYYY/)
assert.match(t.logger.log.getCall(1)[1].message, /2/)
assert.match(t.logger.log.getCall(1)[0], /after each/i)
assert.match(t.logger.log.getCall(1)[0], /BBBB/)
assert.match(t.logger.log.getCall(1)[0], /YYYY/)
assert.match(t.logger.log.getCall(2)[1].message, /3/)
assert.match(t.logger.log.getCall(2)[0], /after each/i)
assert.match(t.logger.log.getCall(2)[0], /CCCC/)
assert.match(t.logger.log.getCall(2)[0], /YYYY/)
assert.match(t.logger.log.getCall(3)[1].message, /4/)
assert.match(t.logger.log.getCall(3)[0], /after each/i)
assert.match(t.logger.log.getCall(3)[0], /HHHH/)
assert.match(t.logger.log.getCall(3)[0], /YYYY/)
assert.match(t.logger.log.getCall(4)[1].message, /5/)
assert.match(t.logger.log.getCall(4)[0], /after each/i)
assert.match(t.logger.log.getCall(4)[0], /JJJJ/)
assert.match(t.logger.log.getCall(4)[0], /YYYY/)
assert.match(t.logger.log.getCallN(1)[1].message, /1/)
assert.match(t.logger.log.getCallN(1)[0], /after each/i)
assert.match(t.logger.log.getCallN(1)[0], /AAAA/)
assert.match(t.logger.log.getCallN(1)[0], /YYYY/)
assert.match(t.logger.log.getCallN(2)[1].message, /2/)
assert.match(t.logger.log.getCallN(2)[0], /after each/i)
assert.match(t.logger.log.getCallN(2)[0], /BBBB/)
assert.match(t.logger.log.getCallN(2)[0], /YYYY/)
assert.match(t.logger.log.getCallN(3)[1].message, /3/)
assert.match(t.logger.log.getCallN(3)[0], /after each/i)
assert.match(t.logger.log.getCallN(3)[0], /CCCC/)
assert.match(t.logger.log.getCallN(3)[0], /YYYY/)
assert.match(t.logger.log.getCallN(4)[1].message, /4/)
assert.match(t.logger.log.getCallN(4)[0], /after each/i)
assert.match(t.logger.log.getCallN(4)[0], /HHHH/)
assert.match(t.logger.log.getCallN(4)[0], /YYYY/)
assert.match(t.logger.log.getCallN(5)[1].message, /5/)
assert.match(t.logger.log.getCallN(5)[0], /after each/i)
assert.match(t.logger.log.getCallN(5)[0], /JJJJ/)
assert.match(t.logger.log.getCallN(5)[0], /YYYY/)
})
})