UNPKG

3.08 kBJavaScriptView Raw
1'use strict'
2
3const log = require('./logger').create()
4
5class Executor {
6 constructor (capturedBrowsers, config, emitter) {
7 this.capturedBrowsers = capturedBrowsers
8 this.config = config
9 this.emitter = emitter
10
11 this.executionScheduled = false
12 this.errorsScheduled = []
13 this.pendingCount = 0
14 this.runningBrowsers = null
15
16 this.emitter.on('run_complete', () => this.onRunComplete())
17 this.emitter.on('browser_complete', () => this.onBrowserComplete())
18 }
19
20 schedule () {
21 if (this.capturedBrowsers.length === 0) {
22 log.warn(`No captured browser, open ${this.config.protocol}//${this.config.hostname}:${this.config.port}${this.config.urlRoot}`)
23 return false
24 } else if (this.capturedBrowsers.areAllReady()) {
25 log.debug('All browsers are ready, executing')
26 log.debug(`Captured ${this.capturedBrowsers.length} browsers`)
27 this.executionScheduled = false
28 this.capturedBrowsers.clearResults()
29 this.pendingCount = this.capturedBrowsers.length
30 this.runningBrowsers = this.capturedBrowsers.clone()
31 this.emitter.emit('run_start', this.runningBrowsers)
32 this.socketIoSockets.emit('execute', this.config.client)
33 return true
34 } else {
35 log.info('Delaying execution, these browsers are not ready: ' + this.capturedBrowsers.getNonReady().join(', '))
36 this.executionScheduled = true
37 return false
38 }
39 }
40
41 /**
42 * Schedule an error to be reported
43 * @param {string} errorMessage
44 * @returns {boolean} a boolean indicating whether or not the error was handled synchronously
45 */
46 scheduleError (errorMessage) {
47 // We don't want to interfere with any running test.
48 // Verify that no test is running before reporting the error.
49 if (this.capturedBrowsers.areAllReady()) {
50 log.warn(errorMessage)
51 const errorResult = {
52 success: 0,
53 failed: 0,
54 skipped: 0,
55 error: errorMessage,
56 exitCode: 1
57 }
58 const noBrowsersStartedTests = []
59 this.emitter.emit('run_start', noBrowsersStartedTests) // A run cannot complete without being started
60 this.emitter.emit('run_complete', noBrowsersStartedTests, errorResult)
61 return true
62 } else {
63 this.errorsScheduled.push(errorMessage)
64 return false
65 }
66 }
67
68 onRunComplete () {
69 if (this.executionScheduled) {
70 this.schedule()
71 }
72 if (this.errorsScheduled.length) {
73 const errorsToReport = this.errorsScheduled
74 this.errorsScheduled = []
75 errorsToReport.forEach((error) => this.scheduleError(error))
76 }
77 }
78
79 onBrowserComplete () {
80 this.pendingCount--
81
82 if (!this.pendingCount) {
83 // Ensure run_complete is emitted in the next tick
84 // so it is never emitted before browser_complete
85 setTimeout(() => {
86 this.emitter.emit('run_complete', this.runningBrowsers, this.runningBrowsers.getResults())
87 })
88 }
89 }
90}
91
92Executor.factory = function (capturedBrowsers, config, emitter) {
93 return new Executor(capturedBrowsers, config, emitter)
94}
95
96module.exports = Executor