diff --git a/lib/listener/globalTimeout.js b/lib/listener/globalTimeout.js index fc77decc5..6bb7dd1fe 100644 --- a/lib/listener/globalTimeout.js +++ b/lib/listener/globalTimeout.js @@ -2,8 +2,10 @@ const event = require('../event') const output = require('../output') const recorder = require('../recorder') const Config = require('../config') -const { timeouts } = require('../store') +const store = require('../store') +const debug = require('debug')('codeceptjs:timeout') const { TIMEOUT_ORDER } = require('../step/timeout') +const { BeforeSuiteHook, AfterSuiteHook } = require('../mocha/hooks') module.exports = function () { let timeout @@ -11,16 +13,30 @@ module.exports = function () { let currentTest let currentTimeout - if (!timeouts) { + if (!store.timeouts) { console.log('Timeouts were disabled') return } + // disable timeout for BeforeSuite/AfterSuite hooks + // add separate configs to them? + event.dispatcher.on(event.hook.started, hook => { + if (hook instanceof BeforeSuiteHook) { + timeout = null + suiteTimeout = [] + } + if (hook instanceof AfterSuiteHook) { + timeout = null + suiteTimeout = [] + } + }) + event.dispatcher.on(event.suite.before, suite => { suiteTimeout = [] let timeoutConfig = Config.get('timeout') if (timeoutConfig) { + debug('config:', timeoutConfig) if (!Number.isNaN(+timeoutConfig)) { checkForSeconds(timeoutConfig) suiteTimeout.push(timeoutConfig) @@ -40,6 +56,8 @@ module.exports = function () { if (suite.totalTimeout) suiteTimeout.push(suite.totalTimeout) output.log(`Timeouts: ${suiteTimeout}`) + + if (suiteTimeout.length > 0) debug(suite.title, 'timeout', suiteTimeout) }) event.dispatcher.on(event.test.before, test => { @@ -64,6 +82,13 @@ module.exports = function () { timeout = test.totalTimeout || testTimeout || suiteTimeout[suiteTimeout.length - 1] if (!timeout) return + + debug(test.title, 'timeout', { + 'config from file': testTimeout, + 'suite timeout': suiteTimeout, + 'dynamic config': test.totalTimeout, + }) + currentTimeout = timeout output.debug(`Test Timeout: ${timeout}s`) timeout *= 1000 @@ -80,18 +105,32 @@ module.exports = function () { event.dispatcher.on(event.step.before, step => { if (typeof timeout !== 'number') return + if (!store.timeouts) { + debug('step', step.toCode().trim(), 'timeout disabled') + return + } + if (timeout < 0) { + debug('Previous steps timed out, setting timeout to 0.01s') step.setTimeout(0.01, TIMEOUT_ORDER.testOrSuite) } else { + debug(`Setting timeout ${timeout}ms for step ${step.toCode().trim()}`) step.setTimeout(timeout, TIMEOUT_ORDER.testOrSuite) } }) event.dispatcher.on(event.step.finished, step => { + if (!store.timeouts) { + debug('step', step.toCode().trim(), 'timeout disabled') + return + } + if (typeof timeout === 'number' && !Number.isNaN(timeout)) timeout -= step.duration if (typeof timeout === 'number' && timeout <= 0 && recorder.isRunning()) { + debug(`step ${step.toCode().trim()} timed out`) if (currentTest && currentTest.callback) { + debug(`Failing test ${currentTest.title} with timeout ${currentTimeout}s`) recorder.reset() // replace mocha timeout with custom timeout currentTest.timeout(0)