source: trip-planner-front/node_modules/karma/lib/launcher.js@ 59329aa

Last change on this file since 59329aa was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 5.3 KB
Line 
1'use strict'
2
3const Jobs = require('qjobs')
4
5const log = require('./logger').create('launcher')
6
7const baseDecorator = require('./launchers/base').decoratorFactory
8const captureTimeoutDecorator = require('./launchers/capture_timeout').decoratorFactory
9const retryDecorator = require('./launchers/retry').decoratorFactory
10const processDecorator = require('./launchers/process').decoratorFactory
11
12// TODO(vojta): remove once nobody uses it
13const baseBrowserDecoratorFactory = function (
14 baseLauncherDecorator,
15 captureTimeoutLauncherDecorator,
16 retryLauncherDecorator,
17 processLauncherDecorator,
18 processKillTimeout
19) {
20 return function (launcher) {
21 baseLauncherDecorator(launcher)
22 captureTimeoutLauncherDecorator(launcher)
23 retryLauncherDecorator(launcher)
24 processLauncherDecorator(launcher, processKillTimeout)
25 }
26}
27
28class Launcher {
29 constructor (server, emitter, injector) {
30 this._server = server
31 this._emitter = emitter
32 this._injector = injector
33 this._browsers = []
34 this._lastStartTime = null
35
36 // Attach list of dependency injection parameters to methods.
37 this.launch.$inject = [
38 'config.browsers',
39 'config.concurrency'
40 ]
41
42 this.launchSingle.$inject = [
43 'config.protocol',
44 'config.hostname',
45 'config.port',
46 'config.urlRoot',
47 'config.upstreamProxy',
48 'config.processKillTimeout'
49 ]
50
51 this._emitter.on('exit', (callback) => this.killAll(callback))
52 }
53
54 getBrowserById (id) {
55 return this._browsers.find((browser) => browser.id === id)
56 }
57
58 launchSingle (protocol, hostname, port, urlRoot, upstreamProxy, processKillTimeout) {
59 if (upstreamProxy) {
60 protocol = upstreamProxy.protocol
61 hostname = upstreamProxy.hostname
62 port = upstreamProxy.port
63 urlRoot = upstreamProxy.path + urlRoot.substr(1)
64 }
65
66 return (name) => {
67 let browser
68 const locals = {
69 id: ['value', Launcher.generateId()],
70 name: ['value', name],
71 processKillTimeout: ['value', processKillTimeout],
72 baseLauncherDecorator: ['factory', baseDecorator],
73 captureTimeoutLauncherDecorator: ['factory', captureTimeoutDecorator],
74 retryLauncherDecorator: ['factory', retryDecorator],
75 processLauncherDecorator: ['factory', processDecorator],
76 baseBrowserDecorator: ['factory', baseBrowserDecoratorFactory]
77 }
78
79 // TODO(vojta): determine script from name
80 if (name.includes('/')) {
81 name = 'Script'
82 }
83
84 try {
85 browser = this._injector.createChild([locals], ['launcher:' + name]).get('launcher:' + name)
86 } catch (e) {
87 if (e.message.includes(`No provider for "launcher:${name}"`)) {
88 log.error(`Cannot load browser "${name}": it is not registered! Perhaps you are missing some plugin?`)
89 } else {
90 log.error(`Cannot load browser "${name}"!\n ` + e.stack)
91 }
92
93 this._emitter.emit('load_error', 'launcher', name)
94 return
95 }
96
97 this.jobs.add((args, done) => {
98 log.info(`Starting browser ${browser.displayName || browser.name}`)
99
100 browser.on('browser_process_failure', () => done(browser.error))
101
102 browser.on('done', () => {
103 if (!browser.error && browser.state !== browser.STATE_RESTARTING) {
104 done(null, browser)
105 }
106 })
107
108 browser.start(`${protocol}//${hostname}:${port}${urlRoot}`)
109 }, [])
110
111 this.jobs.run()
112 this._browsers.push(browser)
113 }
114 }
115
116 launch (names, concurrency) {
117 log.info(`Launching browsers ${names.join(', ')} with concurrency ${concurrency === Infinity ? 'unlimited' : concurrency}`)
118 this.jobs = new Jobs({ maxConcurrency: concurrency })
119
120 this._lastStartTime = Date.now()
121
122 if (this._server.loadErrors.length) {
123 this.jobs.add((args, done) => done(), [])
124 } else {
125 names.forEach((name) => this._injector.invoke(this.launchSingle, this)(name))
126 }
127
128 this.jobs.on('end', (err) => {
129 log.debug('Finished all browsers')
130
131 if (err) {
132 log.error(err)
133 }
134 })
135
136 this.jobs.run()
137
138 return this._browsers
139 }
140
141 kill (id, callback) {
142 callback = callback || function () {}
143 const browser = this.getBrowserById(id)
144
145 if (browser) {
146 browser.forceKill().then(callback)
147 return true
148 }
149 process.nextTick(callback)
150 return false
151 }
152
153 restart (id) {
154 const browser = this.getBrowserById(id)
155 if (browser) {
156 browser.restart()
157 return true
158 }
159 return false
160 }
161
162 killAll (callback) {
163 callback = callback || function () {}
164 log.debug('Disconnecting all browsers')
165
166 if (!this._browsers.length) {
167 return process.nextTick(callback)
168 }
169
170 Promise.all(
171 this._browsers
172 .map((browser) => browser.forceKill())
173 ).then(callback)
174 }
175
176 areAllCaptured () {
177 return this._browsers.every((browser) => browser.isCaptured())
178 }
179
180 markCaptured (id) {
181 const browser = this.getBrowserById(id)
182 if (browser) {
183 browser.markCaptured()
184 log.debug(`${browser.name} (id ${browser.id}) captured in ${(Date.now() - this._lastStartTime) / 1000} secs`)
185 }
186 }
187
188 static generateId () {
189 return Math.floor(Math.random() * 100000000).toString()
190 }
191}
192
193Launcher.factory = function (server, emitter, injector) {
194 return new Launcher(server, emitter, injector)
195}
196
197Launcher.factory.$inject = ['server', 'emitter', 'injector']
198
199exports.Launcher = Launcher
Note: See TracBrowser for help on using the repository browser.