testem 3.18.0 → 3.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api.js +1 -1
- package/lib/app.js +42 -49
- package/lib/browser_launcher.js +5 -6
- package/lib/config.js +66 -50
- package/lib/launcher.js +7 -11
- package/lib/log.js +92 -0
- package/lib/process-ctl.js +20 -6
- package/lib/reporters/dev/index.js +2 -1
- package/lib/reporters/dev/split_log_panel.js +1 -1
- package/lib/runners/browser_test_runner.js +12 -7
- package/lib/runners/hook_runner.js +13 -11
- package/lib/runners/process_test_runner.js +5 -5
- package/lib/runners/tap_process_test_runner.js +5 -6
- package/lib/runners/to-result.js +1 -1
- package/lib/server/index.js +31 -30
- package/lib/tap_consumer.js +2 -2
- package/lib/utils/browser-args.js +1 -1
- package/lib/utils/esbuild-browser-polyfills.js +46 -0
- package/lib/utils/esbuild-buffer-inject.js +6 -0
- package/lib/utils/fileutils.js +15 -10
- package/lib/utils/is-win.js +0 -2
- package/lib/utils/known-browsers.js +14 -12
- package/lib/utils/posix.js +13 -0
- package/lib/utils/process.js +21 -11
- package/lib/utils/promises.js +130 -0
- package/lib/utils/report-file.js +1 -3
- package/lib/utils/reporter.js +3 -3
- package/lib/utils/run-timeout.js +4 -4
- package/lib/utils/signal-listeners.js +9 -7
- package/package.json +14 -15
package/lib/api.js
CHANGED
package/lib/app.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
const EventEmitter = require('events').EventEmitter;
|
|
4
|
-
const
|
|
4
|
+
const { fromCallback, using, disposer, mapLimit } = require('./utils/promises');
|
|
5
5
|
const Path = require('path');
|
|
6
|
-
const log = require('
|
|
6
|
+
const log = require('./log');
|
|
7
7
|
const StyledString = require('styled_string');
|
|
8
8
|
const _ = require('lodash');
|
|
9
9
|
|
|
@@ -64,16 +64,16 @@ module.exports = class App extends EventEmitter {
|
|
|
64
64
|
start(cb) {
|
|
65
65
|
log.info('Starting ' + this.config.appMode);
|
|
66
66
|
|
|
67
|
-
return
|
|
67
|
+
return using(SignalListeners.with(), signalListeners => {
|
|
68
68
|
signalListeners.on('signal', err => this.exit(err));
|
|
69
69
|
|
|
70
|
-
return
|
|
70
|
+
return using(Reporter.with(this, this.stdoutStream, this.reportFileName), reporter => {
|
|
71
71
|
this.reporter = reporter;
|
|
72
72
|
|
|
73
|
-
return
|
|
74
|
-
return
|
|
75
|
-
return
|
|
76
|
-
return
|
|
73
|
+
return using(this.fileWatch(), () => {
|
|
74
|
+
return using(this.getServer(), () => {
|
|
75
|
+
return using(this.getRunners(), () => {
|
|
76
|
+
return using(this.runHook('on_start'), () => {
|
|
77
77
|
let w = this.waitForTests();
|
|
78
78
|
|
|
79
79
|
if (cb) {
|
|
@@ -86,15 +86,15 @@ module.exports = class App extends EventEmitter {
|
|
|
86
86
|
|
|
87
87
|
this.emit('tests-finish');
|
|
88
88
|
|
|
89
|
-
return
|
|
89
|
+
return using(this.runHook('on_exit'), () => {});
|
|
90
90
|
}).catch(error => {
|
|
91
91
|
log.error(error);
|
|
92
92
|
log.info('Stopping ' + this.config.appMode);
|
|
93
93
|
|
|
94
94
|
this.emit('tests-error');
|
|
95
95
|
|
|
96
|
-
return new
|
|
97
|
-
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
using(this.runHook('on_exit'), () => {}).then(() => {
|
|
98
98
|
reject(error);
|
|
99
99
|
});
|
|
100
100
|
});
|
|
@@ -103,14 +103,14 @@ module.exports = class App extends EventEmitter {
|
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
105
|
});
|
|
106
|
-
}).
|
|
106
|
+
}).then(() => this.cleanExit(), err => this.cleanExit(err));
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
waitForTests() {
|
|
110
110
|
log.info('Waiting for tests.');
|
|
111
111
|
|
|
112
112
|
if (this.exited) {
|
|
113
|
-
return
|
|
113
|
+
return Promise.reject(this.exitErr || new Error('Testem exited before running any tests.'));
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
let run = this.triggerRun('Start');
|
|
@@ -119,7 +119,7 @@ module.exports = class App extends EventEmitter {
|
|
|
119
119
|
run.then(() => this.exit());
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
return new
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
123
|
this.on('testFinish', resolve);
|
|
124
124
|
this.on('testError', reject);
|
|
125
125
|
});
|
|
@@ -142,23 +142,23 @@ module.exports = class App extends EventEmitter {
|
|
|
142
142
|
|
|
143
143
|
stopCurrentRun() {
|
|
144
144
|
if (!this.currentRun) {
|
|
145
|
-
return
|
|
145
|
+
return Promise.resolve();
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
return
|
|
148
|
+
return Promise.all([ this.stopRunners(), this.currentRun ]);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
runTests() {
|
|
152
152
|
if (this.paused) {
|
|
153
|
-
return
|
|
153
|
+
return Promise.resolve();
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
log.info('Running tests...');
|
|
157
157
|
|
|
158
158
|
this.reporter.onStart('testem', { launcherId: 0 });
|
|
159
159
|
|
|
160
|
-
return
|
|
161
|
-
return
|
|
160
|
+
return using(this.runHook('before_tests'), () => {
|
|
161
|
+
return using(RunTimeout.with(this.config.get('timeout')), timeout => {
|
|
162
162
|
this.testSuiteTimeout = timeout;
|
|
163
163
|
|
|
164
164
|
timeout.on('timeout', () => {
|
|
@@ -176,7 +176,7 @@ module.exports = class App extends EventEmitter {
|
|
|
176
176
|
|
|
177
177
|
return this.currentRun;
|
|
178
178
|
}).then(() => {
|
|
179
|
-
return
|
|
179
|
+
return using(this.runHook('after_tests'), () => {});
|
|
180
180
|
});
|
|
181
181
|
}).catch(err => {
|
|
182
182
|
if (err.hideFromReporter) {
|
|
@@ -221,7 +221,7 @@ module.exports = class App extends EventEmitter {
|
|
|
221
221
|
return;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
startServer(
|
|
224
|
+
startServer() {
|
|
225
225
|
log.info('Starting server');
|
|
226
226
|
this.server = new Server(this.config);
|
|
227
227
|
this.server.on('file-requested', this.onFileRequested.bind(this));
|
|
@@ -229,11 +229,11 @@ module.exports = class App extends EventEmitter {
|
|
|
229
229
|
this.server.on('browser-relogin', this.onBrowserRelogin.bind(this));
|
|
230
230
|
this.server.on('server-error', this.onServerError.bind(this));
|
|
231
231
|
|
|
232
|
-
return this.server.start()
|
|
232
|
+
return this.server.start();
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
getServer() {
|
|
236
|
-
return this.startServer()
|
|
236
|
+
return disposer(Promise.resolve(this.startServer()), () => this.stopServer());
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
onFileRequested(filepath) {
|
|
@@ -294,12 +294,12 @@ module.exports = class App extends EventEmitter {
|
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
fileWatch() {
|
|
297
|
-
return this.configureFileWatch()
|
|
297
|
+
return disposer(Promise.resolve(this.configureFileWatch()), () => {});
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
configureFileWatch(
|
|
300
|
+
configureFileWatch() {
|
|
301
301
|
if (this.config.get('disable_watching')) {
|
|
302
|
-
return
|
|
302
|
+
return Promise.resolve();
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
this.fileWatcher = new FileWatcher(this.config);
|
|
@@ -316,7 +316,7 @@ module.exports = class App extends EventEmitter {
|
|
|
316
316
|
this.triggerRun('Config changed');
|
|
317
317
|
});
|
|
318
318
|
} else {
|
|
319
|
-
|
|
319
|
+
using(this.runHook('on_change', {file: filepath}), () => {
|
|
320
320
|
this.triggerRun('File changed: ' + filepath);
|
|
321
321
|
});
|
|
322
322
|
}
|
|
@@ -333,13 +333,13 @@ module.exports = class App extends EventEmitter {
|
|
|
333
333
|
view.setErrorPopupMessage(new StyledString(text + '\n ').foreground('megenta'));
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
-
return
|
|
336
|
+
return Promise.resolve();
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
getRunners() {
|
|
340
|
-
return
|
|
340
|
+
return disposer(fromCallback(callback => {
|
|
341
341
|
this.createRunners(callback);
|
|
342
|
-
})
|
|
342
|
+
}), () => {
|
|
343
343
|
return this.killRunners();
|
|
344
344
|
});
|
|
345
345
|
}
|
|
@@ -385,45 +385,38 @@ module.exports = class App extends EventEmitter {
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
withTestTimeout() {
|
|
388
|
-
return this.startClock()
|
|
388
|
+
return disposer(this.startClock(), () => {
|
|
389
389
|
return this.cancelExistingTimeout();
|
|
390
390
|
});
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
singleRun(timeout) {
|
|
394
394
|
let limit = this.config.get('parallel');
|
|
395
|
+
let concurrency = (limit && limit >= 1) ? parseInt(limit) : Infinity;
|
|
395
396
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (limit && limit >= 1) {
|
|
399
|
-
options.concurrency = parseInt(limit);
|
|
400
|
-
} else {
|
|
401
|
-
options.concurrency = Infinity;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return Bluebird.map(this.runners, (runner) => {
|
|
397
|
+
return mapLimit(this.runners, concurrency, runner => {
|
|
405
398
|
if (this.exited) {
|
|
406
399
|
let e = new Error('Run canceled.');
|
|
407
400
|
e.hideFromReporter = true;
|
|
408
|
-
return
|
|
401
|
+
return Promise.reject(e);
|
|
409
402
|
}
|
|
410
403
|
if (this.restarting) {
|
|
411
|
-
return
|
|
404
|
+
return Promise.resolve();
|
|
412
405
|
}
|
|
413
406
|
return timeout.try(() => runner.start());
|
|
414
|
-
}
|
|
407
|
+
});
|
|
415
408
|
}
|
|
416
409
|
|
|
417
410
|
wrapUp(err) {
|
|
418
411
|
this.exit(err);
|
|
419
412
|
}
|
|
420
413
|
|
|
421
|
-
stopServer(
|
|
414
|
+
stopServer() {
|
|
422
415
|
if (!this.server) {
|
|
423
|
-
return
|
|
416
|
+
return Promise.resolve();
|
|
424
417
|
}
|
|
425
418
|
|
|
426
|
-
return this.server.stop()
|
|
419
|
+
return this.server.stop();
|
|
427
420
|
}
|
|
428
421
|
|
|
429
422
|
getExitCode() {
|
|
@@ -442,17 +435,17 @@ module.exports = class App extends EventEmitter {
|
|
|
442
435
|
}
|
|
443
436
|
|
|
444
437
|
stopRunners() {
|
|
445
|
-
return
|
|
438
|
+
return Promise.all(this.runners.map(runner => {
|
|
446
439
|
if (typeof runner.stop === 'function') {
|
|
447
440
|
return runner.stop();
|
|
448
441
|
}
|
|
449
442
|
|
|
450
443
|
return runner.exit();
|
|
451
|
-
});
|
|
444
|
+
}));
|
|
452
445
|
}
|
|
453
446
|
|
|
454
447
|
killRunners() {
|
|
455
|
-
return
|
|
448
|
+
return Promise.all(this.runners.map(runner => runner.exit()));
|
|
456
449
|
}
|
|
457
450
|
|
|
458
451
|
launchers() {
|
package/lib/browser_launcher.js
CHANGED
|
@@ -8,10 +8,9 @@ This file more or less figures out how to launch any browser on any platform.
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
var Bluebird = require('bluebird');
|
|
12
|
-
|
|
13
11
|
var fileutils = require('./utils/fileutils');
|
|
14
12
|
var envWithLocalPath = require('./utils/env-with-local-path');
|
|
13
|
+
const { filter, asCallback } = require('./utils/promises');
|
|
15
14
|
|
|
16
15
|
var executableExists = function(exe, config) {
|
|
17
16
|
return fileutils.executableExists(exe, { env: envWithLocalPath(config) });
|
|
@@ -24,7 +23,7 @@ function getAvailableBrowsers(config, browsers, cb) {
|
|
|
24
23
|
b.protocol = 'browser';
|
|
25
24
|
});
|
|
26
25
|
|
|
27
|
-
return
|
|
26
|
+
return filter(browsers, function(browser) {
|
|
28
27
|
return isInstalled(browser, config).then(function(result) {
|
|
29
28
|
if (!result) {
|
|
30
29
|
return false;
|
|
@@ -33,7 +32,7 @@ function getAvailableBrowsers(config, browsers, cb) {
|
|
|
33
32
|
browser.exe = result;
|
|
34
33
|
return true;
|
|
35
34
|
});
|
|
36
|
-
}).asCallback(cb);
|
|
35
|
+
}).then(...asCallback(cb));
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
function isInstalled(browser, config) {
|
|
@@ -50,11 +49,11 @@ function isInstalled(browser, config) {
|
|
|
50
49
|
|
|
51
50
|
function checkBrowser(browser, property, method) {
|
|
52
51
|
if (!browser[property]) {
|
|
53
|
-
return
|
|
52
|
+
return Promise.resolve(false);
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
if (Array.isArray(browser[property])) {
|
|
57
|
-
return
|
|
56
|
+
return filter(browser[property], method).then(function(result) {
|
|
58
57
|
if (result.length === 0) {
|
|
59
58
|
return false;
|
|
60
59
|
}
|
package/lib/config.js
CHANGED
|
@@ -12,12 +12,12 @@ or `testem.json` config file.
|
|
|
12
12
|
const os = require('os');
|
|
13
13
|
const fs = require('fs');
|
|
14
14
|
const yaml = require('js-yaml');
|
|
15
|
-
const log = require('
|
|
15
|
+
const log = require('./log');
|
|
16
16
|
const path = require('path');
|
|
17
|
-
const glob = require('glob');
|
|
17
|
+
const glob = require('glob').glob;
|
|
18
18
|
const url = require('url');
|
|
19
19
|
const querystring = require('querystring');
|
|
20
|
-
const
|
|
20
|
+
const { filter, reduce } = require('./utils/promises');
|
|
21
21
|
|
|
22
22
|
const browser_launcher = require('./browser_launcher');
|
|
23
23
|
const LauncherFactory = require('./launcher-factory');
|
|
@@ -28,7 +28,8 @@ const fileExists = require('./utils/fileutils').fileExists;
|
|
|
28
28
|
const _ = require('lodash');
|
|
29
29
|
|
|
30
30
|
const knownBrowsers = require('./utils/known-browsers');
|
|
31
|
-
const
|
|
31
|
+
const { convertToPosix } = require('./utils/posix');
|
|
32
|
+
const globAsync = glob;
|
|
32
33
|
|
|
33
34
|
class Config {
|
|
34
35
|
constructor(appMode, progOptions, config) {
|
|
@@ -71,7 +72,7 @@ class Config {
|
|
|
71
72
|
// Try all testem.json, testem.yml and testem.js
|
|
72
73
|
// testem.json gets precedence
|
|
73
74
|
let files = ['testem.json', '.testem.json', '.testem.yml', 'testem.yml', 'testem.js', '.testem.js', 'testem.cjs', '.testem.cjs'];
|
|
74
|
-
return
|
|
75
|
+
return filter(files.map(this.resolveConfigPath.bind(this)), fileExists).then(matched => {
|
|
75
76
|
let configFile = matched[0];
|
|
76
77
|
if (matched.length > 1) {
|
|
77
78
|
let baseNames = matched.map(fileName => path.basename(fileName));
|
|
@@ -157,28 +158,28 @@ class Config {
|
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
readYAML(configFile, callback) {
|
|
160
|
-
fs.readFile(configFile
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
return fs.promises.readFile(configFile)
|
|
162
|
+
.then(data => {
|
|
163
|
+
this.fileOptions = yaml.load(String(data));
|
|
164
|
+
}, () => {})
|
|
165
|
+
.then(() => {
|
|
166
|
+
if (callback) {
|
|
167
|
+
callback.call(this);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
readJSON(configFile, callback) {
|
|
172
|
-
fs.readFile(configFile
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.fileOptions = cfg;
|
|
173
|
+
return fs.promises.readFile(configFile)
|
|
174
|
+
.then(data => {
|
|
175
|
+
this.fileOptions = JSON.parse(data.toString());
|
|
176
176
|
this.progOptions.file = configFile;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
callback
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
}, () => {})
|
|
178
|
+
.then(() => {
|
|
179
|
+
if (callback) {
|
|
180
|
+
callback.call(this);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
mergeUrlAndQueryParams(urlString, queryParamsObj) {
|
|
@@ -398,7 +399,7 @@ class Config {
|
|
|
398
399
|
});
|
|
399
400
|
|
|
400
401
|
dontWant = dontWant.map(p => p ? this.resolvePath(p) : p);
|
|
401
|
-
|
|
402
|
+
return reduce(positiveWants, (allThatIWant, patternEntry) => {
|
|
402
403
|
let pattern = isa(patternEntry, String) ? patternEntry : patternEntry.src;
|
|
403
404
|
let attrs = patternEntry.attrs || [];
|
|
404
405
|
let patternUrl = url.parse(pattern);
|
|
@@ -409,33 +410,41 @@ class Config {
|
|
|
409
410
|
return allThatIWant.concat({ src: pattern, attrs: attrs });
|
|
410
411
|
}
|
|
411
412
|
|
|
412
|
-
return globAsync(this.resolvePath(pattern), { ignore: dontWant
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
413
|
+
return globAsync(convertToPosix(this.resolvePath(pattern)), { ignore: dontWant.map(convertToPosix) })
|
|
414
|
+
.then(files => files.sort())
|
|
415
|
+
.then(files => allThatIWant.concat(files.map(f => {
|
|
416
|
+
f = this.reverseResolvePath(f);
|
|
417
|
+
return { src: f, attrs: attrs };
|
|
418
|
+
})));
|
|
416
419
|
}, [])
|
|
417
420
|
.then(result => _.uniqBy(result, 'src'))
|
|
418
|
-
.
|
|
421
|
+
.then(result => {
|
|
422
|
+
if (callback) { callback(null, result); }
|
|
423
|
+
return result;
|
|
424
|
+
}, err => {
|
|
425
|
+
if (callback) { callback(err); }
|
|
426
|
+
throw err;
|
|
427
|
+
});
|
|
419
428
|
}
|
|
420
429
|
|
|
421
430
|
getSrcFiles(callback) {
|
|
422
431
|
let srcFiles = this.get('src_files') || '*.js';
|
|
423
432
|
let srcFilesIgnore = this.get('src_files_ignore') || '';
|
|
424
|
-
this.getFileSet(srcFiles, srcFilesIgnore, callback);
|
|
433
|
+
return this.getFileSet(srcFiles, srcFilesIgnore, callback);
|
|
425
434
|
}
|
|
426
435
|
|
|
427
436
|
getFooterScripts(callback) {
|
|
428
437
|
var want = this.get('footer_scripts') || [];
|
|
429
438
|
var dontWant = this.get('src_files_ignore') || '';
|
|
430
439
|
|
|
431
|
-
this.getFileSet(want, dontWant, callback);
|
|
440
|
+
return this.getFileSet(want, dontWant, callback);
|
|
432
441
|
}
|
|
433
442
|
|
|
434
443
|
|
|
435
444
|
getServeFiles(callback) {
|
|
436
445
|
let want = this.get('serve_files') || this.get('src_files') || '*.js';
|
|
437
446
|
let dontWant = this.get('serve_files_ignore') || this.get('src_files_ignore') || '';
|
|
438
|
-
this.getFileSet(want, dontWant, callback);
|
|
447
|
+
return this.getFileSet(want, dontWant, callback);
|
|
439
448
|
}
|
|
440
449
|
|
|
441
450
|
getUserDataDir() {
|
|
@@ -452,7 +461,7 @@ class Config {
|
|
|
452
461
|
|
|
453
462
|
getCSSFiles(callback) {
|
|
454
463
|
let want = this.get('css_files') || '';
|
|
455
|
-
this.getFileSet(want, '', callback);
|
|
464
|
+
return this.getFileSet(want, '', callback);
|
|
456
465
|
}
|
|
457
466
|
|
|
458
467
|
getAllOptions() {
|
|
@@ -472,7 +481,7 @@ class Config {
|
|
|
472
481
|
return options;
|
|
473
482
|
}
|
|
474
483
|
|
|
475
|
-
getTemplateData(cb) {
|
|
484
|
+
async getTemplateData(cb) {
|
|
476
485
|
let ret = {};
|
|
477
486
|
let options = this.getAllOptions();
|
|
478
487
|
let key;
|
|
@@ -487,24 +496,31 @@ class Config {
|
|
|
487
496
|
for (key in this.config) {
|
|
488
497
|
ret[key] = this.config[key];
|
|
489
498
|
}
|
|
490
|
-
this.getServeFiles((err, files) => {
|
|
491
|
-
let replaceSlashes = f => ({
|
|
492
|
-
src: f.src.replace(/\\/g, '/'),
|
|
493
|
-
attrs: f.attrs
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
ret.serve_files = files.map(replaceSlashes);
|
|
497
499
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
ret.footer_scripts = files;
|
|
502
|
-
if (cb) {
|
|
503
|
-
cb(err, ret);
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
});
|
|
500
|
+
const replaceSlashes = f => ({
|
|
501
|
+
src: f.src.replace(/\\/g, '/'),
|
|
502
|
+
attrs: f.attrs
|
|
507
503
|
});
|
|
504
|
+
|
|
505
|
+
try {
|
|
506
|
+
const [serveFiles, cssFiles, footerScripts] = await Promise.all([
|
|
507
|
+
this.getServeFiles(),
|
|
508
|
+
this.getCSSFiles(),
|
|
509
|
+
this.getFooterScripts()
|
|
510
|
+
]);
|
|
511
|
+
|
|
512
|
+
ret.serve_files = serveFiles.map(replaceSlashes);
|
|
513
|
+
ret.css_files = cssFiles.map(replaceSlashes);
|
|
514
|
+
ret.footer_scripts = footerScripts;
|
|
515
|
+
|
|
516
|
+
if (cb) {
|
|
517
|
+
cb(null, ret);
|
|
518
|
+
}
|
|
519
|
+
} catch (err) {
|
|
520
|
+
if (cb) {
|
|
521
|
+
cb(err, ret);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
508
524
|
}
|
|
509
525
|
}
|
|
510
526
|
|
package/lib/launcher.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
const log = require('
|
|
3
|
+
const log = require('./log');
|
|
4
4
|
const tmp = require('tmp');
|
|
5
5
|
const path = require('path');
|
|
6
|
-
const
|
|
6
|
+
const { fromCallback } = require('./utils/promises');
|
|
7
7
|
|
|
8
8
|
const template = require('./utils/strutils').template;
|
|
9
9
|
const ProcessCtl = require('./process-ctl');
|
|
@@ -54,15 +54,11 @@ module.exports = class Launcher {
|
|
|
54
54
|
const settings = this.settings;
|
|
55
55
|
this.setupBrowserTmpDir();
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
settings.setup.call(this, this.config, setupCallback);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
57
|
+
const setupPromise = settings.setup
|
|
58
|
+
? fromCallback(setupCallback => settings.setup.call(this, this.config, setupCallback))
|
|
59
|
+
: Promise.resolve();
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
}).then(() => this.doLaunch());
|
|
61
|
+
return setupPromise.then(() => this.doLaunch());
|
|
66
62
|
}
|
|
67
63
|
|
|
68
64
|
doLaunch() {
|
|
@@ -84,7 +80,7 @@ module.exports = class Launcher {
|
|
|
84
80
|
|
|
85
81
|
return this.processCtl.exec(cmd, options);
|
|
86
82
|
} else {
|
|
87
|
-
return
|
|
83
|
+
return Promise.reject(new Error('No command or exe/args specified for launcher ' + this.name));
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
86
|
|
package/lib/log.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const EventEmitter = require('events');
|
|
2
|
+
const procLog = require('proc-log').log;
|
|
3
|
+
|
|
4
|
+
class Log extends EventEmitter {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
this.stream = process.stderr;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
formatRecord(level, args) {
|
|
11
|
+
let prefix = '';
|
|
12
|
+
let message = '';
|
|
13
|
+
|
|
14
|
+
if (args.length === 1) {
|
|
15
|
+
message = args[0];
|
|
16
|
+
} else if (args.length >= 2) {
|
|
17
|
+
prefix = args[0] || '';
|
|
18
|
+
message = args.slice(1).join(' ');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
level,
|
|
23
|
+
prefix,
|
|
24
|
+
message: String(message)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
write(record) {
|
|
29
|
+
if (this.stream && typeof this.stream.write === 'function') {
|
|
30
|
+
this.stream.write(record.message + '\n');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
emitLog(level, args) {
|
|
35
|
+
const record = this.formatRecord(level, args);
|
|
36
|
+
|
|
37
|
+
this.emit(`log.${level}`, record);
|
|
38
|
+
this.write(record);
|
|
39
|
+
|
|
40
|
+
if (procLog && typeof procLog[level] === 'function') {
|
|
41
|
+
procLog[level](...args);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
error(...args) {
|
|
46
|
+
this.emitLog('error', args);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
notice(...args) {
|
|
50
|
+
this.emitLog('notice', args);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
warn(...args) {
|
|
54
|
+
this.emitLog('warn', args);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
info(...args) {
|
|
58
|
+
this.emitLog('info', args);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
verbose(...args) {
|
|
62
|
+
this.emitLog('verbose', args);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
http(...args) {
|
|
66
|
+
this.emitLog('http', args);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
silly(...args) {
|
|
70
|
+
this.emitLog('silly', args);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
timing(...args) {
|
|
74
|
+
this.emitLog('timing', args);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
pause() {
|
|
78
|
+
this.emit('log.pause');
|
|
79
|
+
if (procLog && typeof procLog.pause === 'function') {
|
|
80
|
+
procLog.pause();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
resume() {
|
|
85
|
+
this.emit('log.resume');
|
|
86
|
+
if (procLog && typeof procLog.resume === 'function') {
|
|
87
|
+
procLog.resume();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = new Log();
|