1 | 'use strict';
|
2 |
|
3 | const log = require('npmlog');
|
4 | const tmp = require('tmp');
|
5 | const path = require('path');
|
6 | const Bluebird = require('bluebird');
|
7 |
|
8 | const template = require('./utils/strutils').template;
|
9 | const ProcessCtl = require('./process-ctl');
|
10 |
|
11 |
|
12 | tmp.setGracefulCleanup();
|
13 |
|
14 | module.exports = class Launcher {
|
15 | constructor(name, settings, config) {
|
16 | this.name = name;
|
17 | this.config = config;
|
18 | this.settings = settings;
|
19 | this.setupDefaultSettings();
|
20 | this.id = settings.id || String(Math.floor(Math.random() * 10000));
|
21 |
|
22 | this.processCtl = new ProcessCtl(name, config);
|
23 | }
|
24 |
|
25 | setupDefaultSettings() {
|
26 | let settings = this.settings;
|
27 | if (settings.protocol === 'tap' && !('hide_stdout' in settings)) {
|
28 | settings.hide_stdout = true;
|
29 | }
|
30 | }
|
31 |
|
32 | isProcess() {
|
33 | return this.settings.protocol !== 'browser';
|
34 | }
|
35 |
|
36 | protocol() {
|
37 | return this.settings.protocol || 'process';
|
38 | }
|
39 |
|
40 | commandLine() {
|
41 | if (this.settings.command) {
|
42 | return '"' + this.settings.command + '"';
|
43 | } else if (this.settings.exe) {
|
44 | return '"' + this.settings.exe +
|
45 | ' ' + this.getArgs().join(' ') + '"';
|
46 | }
|
47 | }
|
48 |
|
49 | start() {
|
50 | return this.launch();
|
51 | }
|
52 |
|
53 | launch() {
|
54 | const settings = this.settings;
|
55 | this.setupBrowserTmpDir();
|
56 |
|
57 | return Bluebird.resolve().asCallback(() => {
|
58 | if (settings.setup) {
|
59 | return Bluebird.fromCallback(setupCallback => {
|
60 | settings.setup.call(this, this.config, setupCallback);
|
61 | });
|
62 | }
|
63 |
|
64 | return Bluebird.resolve();
|
65 | }).then(() => this.doLaunch());
|
66 | }
|
67 |
|
68 | doLaunch() {
|
69 | let settings = this.settings;
|
70 | let options = {};
|
71 |
|
72 | if (settings.cwd) {
|
73 | options.cwd = settings.cwd;
|
74 | }
|
75 |
|
76 | if (settings.exe) {
|
77 | let args = this.getArgs();
|
78 | args = this.template(args);
|
79 |
|
80 | return this.processCtl.spawn(settings.exe, args, options);
|
81 | } else if (settings.command) {
|
82 | let cmd = this.template(settings.command);
|
83 | log.info('cmd: ' + cmd);
|
84 |
|
85 | return this.processCtl.exec(cmd, options);
|
86 | } else {
|
87 | return Bluebird.reject(new Error('No command or exe/args specified for launcher ' + this.name));
|
88 | }
|
89 | }
|
90 |
|
91 | getId() {
|
92 | return this.isProcess() ? -1 : this.id;
|
93 | }
|
94 |
|
95 | getUrl() {
|
96 | let baseUrl = this.config.get('url');
|
97 | let testPage = this.settings.test_page;
|
98 | let id = this.getId();
|
99 |
|
100 | return baseUrl + id + (testPage ? '/' + testPage : '');
|
101 | }
|
102 |
|
103 | getArgs() {
|
104 | let settings = this.settings;
|
105 | let url = this.getUrl();
|
106 | let args = [url];
|
107 | if (settings.args instanceof Array) {
|
108 | args = settings.args.concat(args);
|
109 | } else if (settings.args instanceof Function) {
|
110 | args = settings.args.call(this, this.config, url);
|
111 | }
|
112 | return args;
|
113 | }
|
114 |
|
115 | template(thing) {
|
116 | if (Array.isArray(thing)) {
|
117 | return thing.map(this.template, this);
|
118 | } else {
|
119 | let params = {
|
120 | cwd: this.config.cwd(),
|
121 | url: this.getUrl(),
|
122 | baseUrl: this.config.get('url'),
|
123 | port: this.config.get('port'),
|
124 | testPage: this.settings.test_page || '',
|
125 | id: this.getId()
|
126 | };
|
127 | return template(thing, params);
|
128 | }
|
129 | }
|
130 |
|
131 | setupBrowserTmpDir() {
|
132 | const userDataDir = this.config.getUserDataDir();
|
133 | const tmpPath = path.join(userDataDir, 'testem-' + this.id);
|
134 |
|
135 | this.browserTmpDirectory = tmp.dirSync({
|
136 | template: `${tmpPath}-XXXXXX`,
|
137 | unsafeCleanup: true
|
138 | });
|
139 | }
|
140 |
|
141 | browserTmpDir() {
|
142 | if (!this.browserTmpDirectory) {
|
143 | this.setupBrowserTmpDir();
|
144 | }
|
145 |
|
146 | return this.browserTmpDirectory.name;
|
147 | }
|
148 | };
|