import e from '../lib/eltro.mjs' import { stub } from '../lib/sinon.mjs' import assert from '../lib/assert.mjs' function CreateT() { const t = new e.Eltro() t.reporter = 'test' t.logger = { log: stub() } return t } e.describe('#before()', function() { e.test('should support functions in describe group', async function() { let assertRan = 0 let firstBefore = 0 let secondBefore = 0 let thirdBefore = 0 const t = CreateT() t.begin() t.describe('', function() { t.before(function() { firstBefore = assertRan }) t.describe('', function() { t.before(function() { secondBefore = assertRan }) t.test('', function() { assertRan++ }) t.test('', function() { assertRan++ }) t.test('', function() { assertRan++ }) }) t.describe('', function() { t.before(function() { thirdBefore = assertRan }) t.test('', function() { assertRan++ }) }) t.test('', function() { 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, 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 const t = CreateT() t.begin() t.describe('', function() { 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() { let inside = 0 t.before(function() { assert.strictEqual(outside, 1) }) t.beforeEach(function() { inside++ }) t.test('', function() { assert.strictEqual(inside, 1) }) t.test('', function() { assert.strictEqual(inside, 2) }) t.test('', function() { assert.strictEqual(inside, 3) }) }) t.describe('', function() { let insideSecond = 0 t.before(function() { assert.strictEqual(outside, 4) }) t.beforeEach(function() { assert.strictEqual(insideSecond, 0) insideSecond++ }) t.test('', function() { assert.strictEqual(insideSecond, 1) }) }) t.test('', function() { assert.strictEqual(outside, 1) }) }) 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 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() { let counter = 0 const t = CreateT() t.begin() t.describe('BBBB', function() { t.beforeEach(function() { throw new Error(`Counter at ${++counter}`) }) t.describe('CCCC', function() { t.test('', function() { }) t.test('', function() { }) }) t.describe('DDDD', function() { t.test('', function() { }) }) t.test('AAAA', function() { }) }) let stats = await t.run() 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/) }) }) e.describe('#after()', function() { e.test('should support functions in describe group', async function() { let assertRan = 0 let firstAfter = 0 let secondAfter = 0 let thirdAfter = 0 const t = CreateT() t.begin() t.describe('', function() { t.after(function() { firstAfter = assertRan }) t.describe('', function() { t.after(function() { secondAfter = assertRan }) t.test('', function() { assertRan++ }) t.test('', function() { assertRan++ }) t.test('', function() { assertRan++ }) }) t.describe('', function() { t.after(function() { thirdAfter = assertRan }) t.test('', function() { assertRan++ }) }) t.test('', function() { 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, 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() { e.test('should support functions in describe group', 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, 1) }) t.afterEach(function() { inside++ }) 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.describe('', function() { let inside = 0 t.before(function() { assert.strictEqual(outside, 4) }) t.afterEach(function() { inside++ }) t.test('', function() { assert.strictEqual(inside, 0) }) t.after(function() { assert.strictEqual(inside, 1) }) }) t.test('', function() { assert.strictEqual(outside, 0) }) 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) assert.strictEqual(stats.passed, 5) assert.strictEqual(stats.failed, 0) assert.strictEqual(stats.skipped, 0) }) e.test('should be able to keep track of every error that occurs', async function() { let counter = 0 const t = CreateT() t.begin() t.describe('YYYY', function() { t.afterEach(function() { throw new Error(`Counter at ${++counter}`) }) t.describe('HHHH', function() { t.test('', function() { }) }) t.describe('JJJJ', function() { t.test('', function() { }) }) t.test('AAAA', function() { }) t.test('BBBB', function() { }) t.test('CCCC', function() { }) }) let stats = await t.run() assert.strictEqual(t.failedTests.length, 5) assert.strictEqual(t.logger.log.callCount, 5) 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/) }) }) let commonBeforeTests = ['before', 'beforeEach'] commonBeforeTests.forEach(function(before) { e.describe(`#${before}()`, function() { e.test('should not be possible outside of groups', async function() { const t = CreateT() t.begin() assert.throws(function() { t[before](function() {}) }, function(err) { assert.match(err.message, /group/i) return true }) }) e.test('should support functions in describe timing out', async function() { let assertRan = 0 const t = CreateT() t.begin() t.describe('', function() { t[before](function(cb) { }).timeout(50) t.test('', function() { assertRan++ }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.ok(t.failedTests[0].error) assert.match(t.failedTests[0].error.message, /50ms/) assert.strictEqual(assertRan, 0) }) e.test('should support functions in describe late timing out', async function() { let assertRan = 0 const t = CreateT() t.begin() t.describe('', function() { t[before](function(cb) { setTimeout(cb, 100) }).timeout(50) t.test('', function() { assertRan++ }) }) t.describe('', function() { t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.ok(t.failedTests[0].error) assert.match(t.failedTests[0].error.message, /50ms/) assert.strictEqual(assertRan, 2) }) e.test('should support functions in describe timing out in front', async function() { let assertRan = 0 const t = CreateT() t.begin() t.describe('', function() { t.timeout(25)[before](function(cb) { setTimeout(cb, 50) }) t.test('', function() { assertRan++ }) }) t.describe('', function() { t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.ok(t.failedTests[0].error) assert.match(t.failedTests[0].error.message, /25ms/) assert.strictEqual(assertRan, 2) }) e.test('should support functions in describe being promised', async function() { let assertIsTrue = false const t = CreateT() t.begin() t.describe('', function() { t[before](function() { return new Promise(function(res) { assertIsTrue = true res() }) }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 0) assert.strictEqual(assertIsTrue, true) }) e.test('should support functions in describe with callback', async function() { let assertIsTrue = false const t = CreateT() t.begin() t.describe('', function() { t[before](function(cb) { setTimeout(function() { assertIsTrue = true cb() }, 25) }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 0) assert.strictEqual(assertIsTrue, true) }) e.test('should support functions in describe with directly thrown errors', async function() { const assertError = new Error() const t = CreateT() t.begin() t.describe('', function() { t[before](function() { throw assertError }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.strictEqual(t.failedTests[0].error, assertError) }) e.test('should support functions in describe with rejected promises', async function() { const assertError = new Error() const t = CreateT() t.begin() t.describe('', function() { t[before](function() { return new Promise(function(res, rej) { rej(assertError) }) }) t.test('', function() {}) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.strictEqual(t.failedTests[0].error, assertError) }) e.test('should support functions in describe with callback rejected', async function() { const assertError = new Error() const t = CreateT() t.begin() t.describe('', function() { t[before](function(cb) { cb(assertError) }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.strictEqual(t.failedTests[0].error, assertError) }) }) }) let commonAfterTests = ['after', 'afterEach'] commonAfterTests.forEach(function(after) { e.describe(`#${after}()`, function() { e.test('should not be possible outside of groups', async function() { const t = CreateT() t.begin() assert.throws(function() { t[after](function() {}) }, function(err) { assert.match(err.message, /group/i) return true }) }) e.test('should support functions in describe, timing out', async function() { let assertRan = 0 const t = CreateT() t.begin() t.describe('', function() { t[after](function(cb) { }).timeout(50) t.test('', function() { assertRan++ }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.ok(t.failedTests[0].error) assert.match(t.failedTests[0].error.message, /50ms/) assert.strictEqual(assertRan, 1) }) e.test('should support functions in describe, late timing out', async function() { let assertRan = 0 const t = CreateT() t.begin() t.describe('', function() { t[after](function(cb) { setTimeout(cb, 100) }).timeout(50) t.test('', function() { assertRan++ }) }) t.describe('', function() { t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.ok(t.failedTests[0].error) assert.match(t.failedTests[0].error.message, /50ms/) assert.strictEqual(assertRan, 3) }) e.test('should support functions in describe, timing out in front', async function() { let assertRan = 0 const t = CreateT() t.begin() t.describe('', function() { t.timeout(25)[after](function(cb) { setTimeout(cb, 50) }) t.test('', function() { assertRan++ }) }) t.describe('', function() { t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) t.test('', function(cb) { assertRan++; setTimeout(cb, 25) }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.ok(t.failedTests[0].error) assert.match(t.failedTests[0].error.message, /25ms/) assert.strictEqual(assertRan, 3) }) e.test('should support functions in describe, being promised', async function() { let assertIsTrue = false const t = CreateT() t.begin() t.describe('', function() { t[after](function() { return new Promise(function(res) { assertIsTrue = true res() }) }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 0) assert.strictEqual(assertIsTrue, true) }) e.test('should support functions in describe, support callback', async function() { let assertIsTrue = false const t = CreateT() t.begin() t.describe('', function() { t[after](function(cb) { setTimeout(function() { assertIsTrue = true cb() }, 25) }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 0) assert.strictEqual(assertIsTrue, true) }) e.test('should support functions in describe, support directly thrown errors', async function() { const assertError = new Error() const t = CreateT() t.begin() t.describe('', function() { t[after](function() { throw assertError }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.strictEqual(t.failedTests[0].error, assertError) }) e.test('should support functions in describe, support rejected promises', async function() { const assertError = new Error() const t = CreateT() t.begin() t.describe('', function() { t[after](function() { return new Promise(function(res, rej) { rej(assertError) }) }) t.test('', function() {}) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.strictEqual(t.failedTests[0].error, assertError) }) e.test('should support functions in describe, support callback rejected', async function() { const assertError = new Error() const t = CreateT() t.begin() t.describe('', function() { t[after](function(cb) { cb(assertError) }) t.test('', function() { }) }) await t.run() assert.strictEqual(t.failedTests.length, 1) assert.strictEqual(t.failedTests[0].error, assertError) }) }) })