@wdio/cli
Version:
WebdriverIO testrunner command line interface
125 lines (124 loc) • 4.99 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chokidar_1 = __importDefault(require("chokidar"));
const logger_1 = __importDefault(require("@wdio/logger"));
const lodash_pickby_1 = __importDefault(require("lodash.pickby"));
const lodash_flattendeep_1 = __importDefault(require("lodash.flattendeep"));
const lodash_union_1 = __importDefault(require("lodash.union"));
const launcher_1 = __importDefault(require("./launcher"));
const log = logger_1.default('@wdio/cli:watch');
class Watcher {
constructor(_configFile, _args) {
this._configFile = _configFile;
this._args = _args;
log.info('Starting launcher in watch mode');
this._launcher = new launcher_1.default(this._configFile, this._args, true);
const specs = this._launcher.configParser.getSpecs();
const capSpecs = this._launcher.isMultiremote ? [] : lodash_union_1.default(lodash_flattendeep_1.default(this._launcher.configParser.getCapabilities().map(cap => cap.specs || [])));
this._specs = [...specs, ...capSpecs];
}
async watch() {
/**
* listen on spec changes and rerun specific spec file
*/
chokidar_1.default.watch(this._specs, { ignoreInitial: true })
.on('add', this.getFileListener())
.on('change', this.getFileListener());
/**
* listen on filesToWatch changes an rerun complete suite
*/
const { filesToWatch } = this._launcher.configParser.getConfig();
if (filesToWatch.length) {
chokidar_1.default.watch(filesToWatch, { ignoreInitial: true })
.on('add', this.getFileListener(false))
.on('change', this.getFileListener(false));
}
/**
* run initial test suite
*/
await this._launcher.run();
/**
* clean interface once all worker finish
*/
const workers = this.getWorkers();
Object.values(workers).forEach((worker) => worker.on('exit', () => {
/**
* check if all workers have finished
*/
if (Object.values(workers).find((w) => w.isBusy)) {
return;
}
this._launcher.interface.finalise();
}));
}
/**
* return file listener callback that calls `run` method
* @param {Boolean} [passOnFile=true] if true pass on file change as parameter
* @return {Function} chokidar event callback
*/
getFileListener(passOnFile = true) {
return (spec) => {
// Do not pass the `spec` command line option to `this.run()`
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { spec: _specArg, ...args } = this._args;
return this.run({ ...args, ...(passOnFile ? { spec } : {}) });
};
}
/**
* helper method to get workers from worker pool of wdio runner
* @param predicate filter by property value (see lodash.pickBy)
* @param includeBusyWorker don't filter out busy worker (default: false)
* @return Object with workers, e.g. {'0-0': { ... }}
*/
getWorkers(predicate, includeBusyWorker) {
let workers = this._launcher.runner.workerPool;
if (typeof predicate === 'function') {
workers = lodash_pickby_1.default(workers, predicate);
}
/**
* filter out busy workers, only skip if explicitely desired
*/
if (!includeBusyWorker) {
workers = lodash_pickby_1.default(workers, (worker) => !worker.isBusy);
}
return workers;
}
/**
* run workers with params
* @param params parameters to run the worker with
*/
run(params = {}) {
const workers = this.getWorkers((params.spec ? (worker) => worker.specs.includes(params.spec) : undefined));
/**
* don't do anything if no worker was found
*/
if (Object.keys(workers).length === 0) {
return;
}
/**
* update total worker count interface
* ToDo: this should have a cleaner solution
*/
this._launcher.interface.totalWorkerCnt = Object.entries(workers).length;
/**
* clean up interface
*/
this.cleanUp();
/**
* trigger new run for non busy worker
*/
for (const [, worker] of Object.entries(workers)) {
const { cid, caps, specs, sessionId } = worker;
const args = Object.assign({ sessionId }, params);
worker.postMessage('run', args);
this._launcher.interface.emit('job:start', { cid, caps, specs });
}
}
cleanUp() {
this._launcher.interface.setup();
}
}
exports.default = Watcher;