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 CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- const log = require('npmlog');
3
+ const log = require('./log');
4
4
  const Config = require('./config');
5
5
  const EventEmitter = require('events').EventEmitter;
6
6
  const fs = require('fs');
package/lib/app.js CHANGED
@@ -1,9 +1,9 @@
1
1
 
2
2
 
3
3
  const EventEmitter = require('events').EventEmitter;
4
- const Bluebird = require('bluebird');
4
+ const { fromCallback, using, disposer, mapLimit } = require('./utils/promises');
5
5
  const Path = require('path');
6
- const log = require('npmlog');
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 Bluebird.using(SignalListeners.with(), signalListeners => {
67
+ return using(SignalListeners.with(), signalListeners => {
68
68
  signalListeners.on('signal', err => this.exit(err));
69
69
 
70
- return Bluebird.using(Reporter.with(this, this.stdoutStream, this.reportFileName), reporter => {
70
+ return using(Reporter.with(this, this.stdoutStream, this.reportFileName), reporter => {
71
71
  this.reporter = reporter;
72
72
 
73
- return Bluebird.using(this.fileWatch(), () => {
74
- return Bluebird.using(this.getServer(), () => {
75
- return Bluebird.using(this.getRunners(), () => {
76
- return Bluebird.using(this.runHook('on_start'), () => {
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 Bluebird.using(this.runHook('on_exit'), () => {});
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 Bluebird((resolve, reject) => {
97
- Bluebird.using(this.runHook('on_exit'), () => {}).then(() => {
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
- }).asCallback(this.cleanExit);
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 Bluebird.reject(this.exitErr || new Error('Testem exited before running any tests.'));
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 Bluebird.Promise((resolve, reject) => {
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 Bluebird.resolve();
145
+ return Promise.resolve();
146
146
  }
147
147
 
148
- return Bluebird.all([ this.stopRunners(), this.currentRun ]);
148
+ return Promise.all([ this.stopRunners(), this.currentRun ]);
149
149
  }
150
150
 
151
151
  runTests() {
152
152
  if (this.paused) {
153
- return Bluebird.resolve();
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 Bluebird.using(this.runHook('before_tests'), () => {
161
- return Bluebird.using(RunTimeout.with(this.config.get('timeout')), timeout => {
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 Bluebird.using(this.runHook('after_tests'), () => {});
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(callback) {
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().asCallback(callback);
232
+ return this.server.start();
233
233
  }
234
234
 
235
235
  getServer() {
236
- return this.startServer().disposer(() => this.stopServer());
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().disposer(() => {});
297
+ return disposer(Promise.resolve(this.configureFileWatch()), () => {});
298
298
  }
299
299
 
300
- configureFileWatch(cb) {
300
+ configureFileWatch() {
301
301
  if (this.config.get('disable_watching')) {
302
- return Bluebird.resolve().asCallback(cb);
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
- Bluebird.using(this.runHook('on_change', {file: filepath}), () => {
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 Bluebird.resolve().asCallback(cb);
336
+ return Promise.resolve();
337
337
  }
338
338
 
339
339
  getRunners() {
340
- return Bluebird.fromCallback(callback => {
340
+ return disposer(fromCallback(callback => {
341
341
  this.createRunners(callback);
342
- }).disposer(() => {
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().disposer(() => {
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
- let options = {};
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 Bluebird.reject(e);
401
+ return Promise.reject(e);
409
402
  }
410
403
  if (this.restarting) {
411
- return Bluebird.resolve();
404
+ return Promise.resolve();
412
405
  }
413
406
  return timeout.try(() => runner.start());
414
- }, options);
407
+ });
415
408
  }
416
409
 
417
410
  wrapUp(err) {
418
411
  this.exit(err);
419
412
  }
420
413
 
421
- stopServer(callback) {
414
+ stopServer() {
422
415
  if (!this.server) {
423
- return Bluebird.resolve().asCallback(callback);
416
+ return Promise.resolve();
424
417
  }
425
418
 
426
- return this.server.stop().asCallback(callback);
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 Bluebird.each(this.runners, runner => {
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 Bluebird.each(this.runners, runner => runner.exit());
448
+ return Promise.all(this.runners.map(runner => runner.exit()));
456
449
  }
457
450
 
458
451
  launchers() {
@@ -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 Bluebird.filter(browsers, function(browser) {
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 Bluebird.resolve(false);
52
+ return Promise.resolve(false);
54
53
  }
55
54
 
56
55
  if (Array.isArray(browser[property])) {
57
- return Bluebird.filter(browser[property], method).then(function(result) {
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('npmlog');
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 Bluebird = require('bluebird');
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 globAsync = Bluebird.promisify(glob);
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 Bluebird.filter(files.map(this.resolveConfigPath.bind(this)), fileExists).then(matched => {
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, (err, data) => {
161
- if (!err) {
162
- let cfg = yaml.load(String(data));
163
- this.fileOptions = cfg;
164
- }
165
- if (callback) {
166
- callback.call(this);
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, (err, data) => {
173
- if (!err) {
174
- let cfg = JSON.parse(data.toString());
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
- if (callback) {
179
- callback.call(this);
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
- Bluebird.reduce(positiveWants, (allThatIWant, patternEntry) => {
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 }).then(files => allThatIWant.concat(files.map(f => {
413
- f = this.reverseResolvePath(f);
414
- return { src: f, attrs: attrs };
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
- .asCallback(callback);
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
- this.getCSSFiles((err, files) => {
499
- ret.css_files = files.map(replaceSlashes);
500
- this.getFooterScripts((err, files) => {
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('npmlog');
3
+ const log = require('./log');
4
4
  const tmp = require('tmp');
5
5
  const path = require('path');
6
- const Bluebird = require('bluebird');
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
- return Bluebird.resolve().asCallback(() => {
58
- if (settings.setup) {
59
- return Bluebird.fromCallback(setupCallback => {
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
- return Bluebird.resolve();
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 Bluebird.reject(new Error('No command or exe/args specified for launcher ' + this.name));
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();