1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const events_1 = require("events");
|
4 | const q = require("q");
|
5 | const selenium_webdriver_1 = require("selenium-webdriver");
|
6 | const util = require("util");
|
7 | const browser_1 = require("./browser");
|
8 | const driverProviders_1 = require("./driverProviders");
|
9 | const logger_1 = require("./logger");
|
10 | const plugins_1 = require("./plugins");
|
11 | const ptor_1 = require("./ptor");
|
12 | const helper = require("./util");
|
13 | let logger = new logger_1.Logger('runner');
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 | class Runner extends events_1.EventEmitter {
|
27 | constructor(config) {
|
28 | super();
|
29 | |
30 |
|
31 |
|
32 |
|
33 |
|
34 | this.exit_ = function (exitCode) {
|
35 | return helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode])
|
36 | .then((returned) => {
|
37 | if (typeof returned === 'number') {
|
38 | return returned;
|
39 | }
|
40 | else {
|
41 | return exitCode;
|
42 | }
|
43 | });
|
44 | };
|
45 | this.config_ = config;
|
46 | if (config.v8Debug) {
|
47 |
|
48 | process['_debugProcess'](process.pid);
|
49 | }
|
50 | if (config.nodeDebug) {
|
51 | process['_debugProcess'](process.pid);
|
52 | let flow = selenium_webdriver_1.promise.controlFlow();
|
53 | this.ready_ = flow.execute(() => {
|
54 | let nodedebug = require('child_process').fork('debug', ['localhost:5858']);
|
55 | process.on('exit', function () {
|
56 | nodedebug.kill('SIGTERM');
|
57 | });
|
58 | nodedebug.on('exit', function () {
|
59 | process.exit(1);
|
60 | });
|
61 | }, 'start the node debugger').then(() => {
|
62 | return flow.timeout(1000, 'waiting for debugger to attach');
|
63 | });
|
64 | }
|
65 | if (config.capabilities && config.capabilities.seleniumAddress) {
|
66 | config.seleniumAddress = config.capabilities.seleniumAddress;
|
67 | }
|
68 | this.loadDriverProvider_(config);
|
69 | this.setTestPreparer(config.onPrepare);
|
70 | }
|
71 | |
72 |
|
73 |
|
74 |
|
75 |
|
76 | setTestPreparer(filenameOrFn) {
|
77 | this.preparer_ = filenameOrFn;
|
78 | }
|
79 | |
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 | runTestPreparer(extraFlags) {
|
87 | let unknownFlags = this.config_.unknownFlags_ || [];
|
88 | if (extraFlags) {
|
89 | unknownFlags = unknownFlags.filter((f) => extraFlags.indexOf(f) === -1);
|
90 | }
|
91 | if (unknownFlags.length > 0 && !this.config_.disableChecks) {
|
92 |
|
93 | logger.warn('Ignoring unknown extra flags: ' + unknownFlags.join(', ') + '. This will be' +
|
94 | ' an error in future versions, please use --disableChecks flag to disable the ' +
|
95 | ' Protractor CLI flag checks. ');
|
96 | }
|
97 | return this.plugins_.onPrepare().then(() => {
|
98 | return helper.runFilenameOrFn_(this.config_.configDir, this.preparer_);
|
99 | });
|
100 | }
|
101 | |
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | afterEach() {
|
110 | let ret;
|
111 | this.frameworkUsesAfterEach = true;
|
112 | if (this.config_.restartBrowserBetweenTests) {
|
113 | this.restartPromise = this.restartPromise || q(ptor_1.protractor.browser.restart());
|
114 | ret = this.restartPromise;
|
115 | this.restartPromise = undefined;
|
116 | }
|
117 | return ret || q();
|
118 | }
|
119 | |
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | loadDriverProvider_(config) {
|
131 | this.config_ = config;
|
132 | this.driverprovider_ = driverProviders_1.buildDriverProvider(this.config_);
|
133 | }
|
134 | |
135 |
|
136 |
|
137 |
|
138 |
|
139 | getConfig() {
|
140 | return this.config_;
|
141 | }
|
142 | |
143 |
|
144 |
|
145 |
|
146 | controlFlow() {
|
147 | return selenium_webdriver_1.promise.controlFlow();
|
148 | }
|
149 | |
150 |
|
151 |
|
152 |
|
153 | setupGlobals_(browser_) {
|
154 |
|
155 | ptor_1.protractor.browser = browser_;
|
156 | ptor_1.protractor.$ = browser_.$;
|
157 | ptor_1.protractor.$$ = browser_.$$;
|
158 | ptor_1.protractor.element = browser_.element;
|
159 | ptor_1.protractor.by = ptor_1.protractor.By = browser_1.ProtractorBrowser.By;
|
160 | ptor_1.protractor.ExpectedConditions = browser_.ExpectedConditions;
|
161 | if (!this.config_.noGlobals) {
|
162 |
|
163 | global.browser = browser_;
|
164 | global.$ = browser_.$;
|
165 | global.$$ = browser_.$$;
|
166 | global.element = browser_.element;
|
167 | global.by = global.By = ptor_1.protractor.By;
|
168 | global.ExpectedConditions = ptor_1.protractor.ExpectedConditions;
|
169 | }
|
170 | global.protractor = ptor_1.protractor;
|
171 | if (!this.config_.skipSourceMapSupport) {
|
172 |
|
173 | require('source-map-support').install();
|
174 | }
|
175 |
|
176 |
|
177 | global.DartObject = function (o) {
|
178 | this.o = o;
|
179 | };
|
180 | }
|
181 | |
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | createBrowser(plugins, parentBrowser) {
|
194 | let config = this.config_;
|
195 | let driver = this.driverprovider_.getNewDriver();
|
196 | let blockingProxyUrl;
|
197 | if (config.useBlockingProxy) {
|
198 | blockingProxyUrl = this.driverprovider_.getBPUrl();
|
199 | }
|
200 | let initProperties = {
|
201 | baseUrl: config.baseUrl,
|
202 | rootElement: config.rootElement,
|
203 | untrackOutstandingTimeouts: config.untrackOutstandingTimeouts,
|
204 | params: config.params,
|
205 | getPageTimeout: config.getPageTimeout,
|
206 | allScriptsTimeout: config.allScriptsTimeout,
|
207 | debuggerServerPort: config.debuggerServerPort,
|
208 | ng12Hybrid: config.ng12Hybrid,
|
209 | waitForAngularEnabled: true
|
210 | };
|
211 | if (parentBrowser) {
|
212 | initProperties.baseUrl = parentBrowser.baseUrl;
|
213 | initProperties.rootElement = parentBrowser.angularAppRoot();
|
214 | initProperties.untrackOutstandingTimeouts = !parentBrowser.trackOutstandingTimeouts_;
|
215 | initProperties.params = parentBrowser.params;
|
216 | initProperties.getPageTimeout = parentBrowser.getPageTimeout;
|
217 | initProperties.allScriptsTimeout = parentBrowser.allScriptsTimeout;
|
218 | initProperties.debuggerServerPort = parentBrowser.debuggerServerPort;
|
219 | initProperties.ng12Hybrid = parentBrowser.ng12Hybrid;
|
220 | initProperties.waitForAngularEnabled = parentBrowser.waitForAngularEnabled();
|
221 | }
|
222 | let browser_ = new browser_1.ProtractorBrowser(driver, initProperties.baseUrl, initProperties.rootElement, initProperties.untrackOutstandingTimeouts, blockingProxyUrl);
|
223 | browser_.params = initProperties.params;
|
224 | browser_.plugins_ = plugins || new plugins_1.Plugins({});
|
225 | if (initProperties.getPageTimeout) {
|
226 | browser_.getPageTimeout = initProperties.getPageTimeout;
|
227 | }
|
228 | if (initProperties.allScriptsTimeout) {
|
229 | browser_.allScriptsTimeout = initProperties.allScriptsTimeout;
|
230 | }
|
231 | if (initProperties.debuggerServerPort) {
|
232 | browser_.debuggerServerPort = initProperties.debuggerServerPort;
|
233 | }
|
234 | if (initProperties.ng12Hybrid) {
|
235 | browser_.ng12Hybrid = initProperties.ng12Hybrid;
|
236 | }
|
237 | browser_.ready =
|
238 | browser_.ready
|
239 | .then(() => {
|
240 | return browser_.waitForAngularEnabled(initProperties.waitForAngularEnabled);
|
241 | })
|
242 | .then(() => {
|
243 | return driver.manage().timeouts().setScriptTimeout(initProperties.allScriptsTimeout || 0);
|
244 | })
|
245 | .then(() => {
|
246 | return browser_;
|
247 | });
|
248 | browser_.getProcessedConfig = () => {
|
249 | return selenium_webdriver_1.promise.when(config);
|
250 | };
|
251 | browser_.forkNewDriverInstance =
|
252 | (useSameUrl, copyMockModules, copyConfigUpdates = true) => {
|
253 | let newBrowser = this.createBrowser(plugins);
|
254 | if (copyMockModules) {
|
255 | newBrowser.mockModules_ = browser_.mockModules_;
|
256 | }
|
257 | if (useSameUrl) {
|
258 | newBrowser.ready = newBrowser.ready
|
259 | .then(() => {
|
260 | return browser_.driver.getCurrentUrl();
|
261 | })
|
262 | .then((url) => {
|
263 | return newBrowser.get(url);
|
264 | })
|
265 | .then(() => {
|
266 | return newBrowser;
|
267 | });
|
268 | }
|
269 | return newBrowser;
|
270 | };
|
271 | let replaceBrowser = () => {
|
272 | let newBrowser = browser_.forkNewDriverInstance(false, true);
|
273 | if (browser_ === ptor_1.protractor.browser) {
|
274 | this.setupGlobals_(newBrowser);
|
275 | }
|
276 | return newBrowser;
|
277 | };
|
278 | browser_.restart = () => {
|
279 |
|
280 |
|
281 |
|
282 | if (browser_.controlFlowIsEnabled()) {
|
283 | return browser_.restartSync().ready;
|
284 | }
|
285 | else {
|
286 | return this.driverprovider_.quitDriver(browser_.driver)
|
287 | .then(replaceBrowser)
|
288 | .then(newBrowser => newBrowser.ready);
|
289 | }
|
290 | };
|
291 | browser_.restartSync = () => {
|
292 | if (!browser_.controlFlowIsEnabled()) {
|
293 | throw TypeError('Unable to use `browser.restartSync()` when the control flow is disabled');
|
294 | }
|
295 | this.driverprovider_.quitDriver(browser_.driver);
|
296 | return replaceBrowser();
|
297 | };
|
298 | return browser_;
|
299 | }
|
300 | |
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 | shutdown_() {
|
307 | return driverProviders_1.DriverProvider.quitDrivers(this.driverprovider_, this.driverprovider_.getExistingDrivers());
|
308 | }
|
309 | |
310 |
|
311 |
|
312 |
|
313 |
|
314 |
|
315 | run() {
|
316 | let testPassed;
|
317 | let plugins = this.plugins_ = new plugins_1.Plugins(this.config_);
|
318 | let pluginPostTestPromises;
|
319 | let browser_;
|
320 | let results;
|
321 | if (this.config_.framework !== 'explorer' && !this.config_.specs.length) {
|
322 | throw new Error('Spec patterns did not match any files.');
|
323 | }
|
324 | if (this.config_.SELENIUM_PROMISE_MANAGER != null) {
|
325 | selenium_webdriver_1.promise.USE_PROMISE_MANAGER = this.config_.SELENIUM_PROMISE_MANAGER;
|
326 | }
|
327 | if (this.config_.webDriverLogDir || this.config_.highlightDelay) {
|
328 | this.config_.useBlockingProxy = true;
|
329 | }
|
330 |
|
331 | return q(this.ready_)
|
332 | .then(() => {
|
333 |
|
334 |
|
335 | return this.driverprovider_.setupEnv();
|
336 | })
|
337 | .then(() => {
|
338 |
|
339 | browser_ = this.createBrowser(plugins);
|
340 | this.setupGlobals_(browser_);
|
341 | return browser_.ready.then(browser_.getSession)
|
342 | .then((session) => {
|
343 | logger.debug('WebDriver session successfully started with capabilities ' +
|
344 | util.inspect(session.getCapabilities()));
|
345 | }, (err) => {
|
346 | logger.error('Unable to start a WebDriver session.');
|
347 | throw err;
|
348 | });
|
349 |
|
350 | })
|
351 | .then(() => {
|
352 | return plugins.setup();
|
353 |
|
354 | })
|
355 | .then(() => {
|
356 |
|
357 |
|
358 | let frameworkPath = '';
|
359 | if (this.config_.framework === 'jasmine' || this.config_.framework === 'jasmine2') {
|
360 | frameworkPath = './frameworks/jasmine.js';
|
361 | }
|
362 | else if (this.config_.framework === 'mocha') {
|
363 | frameworkPath = './frameworks/mocha.js';
|
364 | }
|
365 | else if (this.config_.framework === 'debugprint') {
|
366 |
|
367 | frameworkPath = './frameworks/debugprint.js';
|
368 | }
|
369 | else if (this.config_.framework === 'explorer') {
|
370 |
|
371 | frameworkPath = './frameworks/explorer.js';
|
372 | }
|
373 | else if (this.config_.framework === 'custom') {
|
374 | if (!this.config_.frameworkPath) {
|
375 | throw new Error('When config.framework is custom, ' +
|
376 | 'config.frameworkPath is required.');
|
377 | }
|
378 | frameworkPath = this.config_.frameworkPath;
|
379 | }
|
380 | else {
|
381 | throw new Error('config.framework (' + this.config_.framework + ') is not a valid framework.');
|
382 | }
|
383 | if (this.config_.restartBrowserBetweenTests) {
|
384 |
|
385 | let restartDriver = () => {
|
386 | if (!this.frameworkUsesAfterEach) {
|
387 | this.restartPromise = q(browser_.restart());
|
388 | }
|
389 | };
|
390 | this.on('testPass', restartDriver);
|
391 | this.on('testFail', restartDriver);
|
392 | }
|
393 |
|
394 |
|
395 |
|
396 |
|
397 | pluginPostTestPromises = [];
|
398 | this.on('testPass', (testInfo) => {
|
399 | pluginPostTestPromises.push(plugins.postTest(true, testInfo));
|
400 | });
|
401 | this.on('testFail', (testInfo) => {
|
402 | pluginPostTestPromises.push(plugins.postTest(false, testInfo));
|
403 | });
|
404 | logger.debug('Running with spec files ' + this.config_.specs);
|
405 | return require(frameworkPath).run(this, this.config_.specs);
|
406 |
|
407 | })
|
408 | .then((testResults) => {
|
409 | results = testResults;
|
410 | return q.all(pluginPostTestPromises);
|
411 |
|
412 | })
|
413 | .then(() => {
|
414 | return plugins.teardown();
|
415 |
|
416 | })
|
417 | .then(() => {
|
418 | results = helper.joinTestLogs(results, plugins.getResults());
|
419 | this.emit('testsDone', results);
|
420 | testPassed = results.failedCount === 0;
|
421 | if (this.driverprovider_.updateJob) {
|
422 | return this.driverprovider_.updateJob({ 'passed': testPassed }).then(() => {
|
423 | return this.driverprovider_.teardownEnv();
|
424 | });
|
425 | }
|
426 | else {
|
427 | return this.driverprovider_.teardownEnv();
|
428 | }
|
429 |
|
430 | })
|
431 | .then(() => {
|
432 | return plugins.postResults();
|
433 |
|
434 | })
|
435 | .then(() => {
|
436 | let exitCode = testPassed ? 0 : 1;
|
437 | return this.exit_(exitCode);
|
438 | })
|
439 | .fin(() => {
|
440 | return this.shutdown_();
|
441 | });
|
442 | }
|
443 | }
|
444 | exports.Runner = Runner;
|
445 |
|
\ | No newline at end of file |