@wdio/cli 7.20.7 → 7.20.8-alpha.504

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/build/utils.js CHANGED
@@ -1,36 +1,37 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getDefaultFiles = exports.getPathForFileGeneration = exports.getAnswers = exports.generateTestFiles = exports.hasPackage = exports.hasFile = exports.getCapabilities = exports.validateServiceAnswers = exports.renderConfigurationFile = exports.convertPackageHashToObject = exports.addServiceDeps = exports.replaceConfig = exports.findInConfig = exports.getRunnerName = exports.runOnCompleteHook = exports.runLauncherHook = exports.runServiceHook = exports.HookError = void 0;
7
- const fs_extra_1 = __importDefault(require("fs-extra"));
8
- const ejs_1 = __importDefault(require("ejs"));
9
- const path_1 = __importDefault(require("path"));
10
- const lodash_pickby_1 = __importDefault(require("lodash.pickby"));
11
- const inquirer_1 = __importDefault(require("inquirer"));
12
- const logger_1 = __importDefault(require("@wdio/logger"));
13
- const recursive_readdir_1 = __importDefault(require("recursive-readdir"));
14
- const webdriverio_1 = require("webdriverio");
15
- const child_process_1 = require("child_process");
16
- const util_1 = require("util");
17
- const config_1 = require("@wdio/config");
18
- const protocols_1 = require("@wdio/protocols");
19
- const constants_1 = require("./constants");
20
- const log = (0, logger_1.default)('@wdio/cli:utils');
21
- const TEMPLATE_ROOT_DIR = path_1.default.join(__dirname, 'templates', 'exampleFiles');
22
- const renderFile = (0, util_1.promisify)(ejs_1.default.renderFile);
23
- class HookError extends webdriverio_1.SevereServiceError {
1
+ import fs from 'node:fs/promises';
2
+ import fsSync from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { createRequire } from 'node:module';
6
+ import { execSync } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+ import ejs from 'ejs';
9
+ import path from 'node:path';
10
+ import inquirer from 'inquirer';
11
+ import pickBy from 'lodash.pickby';
12
+ import logger from '@wdio/logger';
13
+ import readDir from 'recursive-readdir';
14
+ import { SevereServiceError } from 'webdriverio';
15
+ import { ConfigParser } from '@wdio/config';
16
+ import { CAPABILITY_KEYS } from '@wdio/protocols';
17
+ import { EXCLUSIVE_SERVICES, ANDROID_CONFIG, IOS_CONFIG, QUESTIONNAIRE, COMMUNITY_PACKAGES_WITH_V8_SUPPORT } from './constants.js';
18
+ const require = createRequire(import.meta.url);
19
+ const log = logger('@wdio/cli:utils');
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+ const VERSION_REGEXP = /(\d+)\.(\d+)\.(\d+)-(alpha|beta|)\.(\d+)\+(.+)/g;
22
+ const TEMPLATE_ROOT_DIR = path.join(__dirname, 'templates', 'exampleFiles');
23
+ const renderFile = promisify(ejs.renderFile);
24
+ export class HookError extends SevereServiceError {
25
+ origin;
24
26
  constructor(message, origin) {
25
27
  super(message);
26
28
  this.origin = origin;
27
29
  }
28
30
  }
29
- exports.HookError = HookError;
30
31
  /**
31
32
  * run service launch sequences
32
33
  */
33
- async function runServiceHook(launcher, hookName, ...args) {
34
+ export async function runServiceHook(launcher, hookName, ...args) {
34
35
  const start = Date.now();
35
36
  return Promise.all(launcher.map(async (service) => {
36
37
  try {
@@ -40,7 +41,7 @@ async function runServiceHook(launcher, hookName, ...args) {
40
41
  }
41
42
  catch (err) {
42
43
  const message = `A service failed in the '${hookName}' hook\n${err.stack}\n\n`;
43
- if (err instanceof webdriverio_1.SevereServiceError) {
44
+ if (err instanceof SevereServiceError) {
44
45
  return { status: 'rejected', reason: message, origin: hookName };
45
46
  }
46
47
  log.error(`${message}Continue...`);
@@ -55,20 +56,19 @@ async function runServiceHook(launcher, hookName, ...args) {
55
56
  }
56
57
  });
57
58
  }
58
- exports.runServiceHook = runServiceHook;
59
59
  /**
60
60
  * Run hook in service launcher
61
61
  * @param {Array|Function} hook - can be array of functions or single function
62
62
  * @param {Object} config
63
63
  * @param {Object} capabilities
64
64
  */
65
- async function runLauncherHook(hook, ...args) {
65
+ export async function runLauncherHook(hook, ...args) {
66
66
  if (typeof hook === 'function') {
67
67
  hook = [hook];
68
68
  }
69
69
  const catchFn = (e) => {
70
70
  log.error(`Error in hook: ${e.stack}`);
71
- if (e instanceof webdriverio_1.SevereServiceError) {
71
+ if (e instanceof SevereServiceError) {
72
72
  throw new HookError(e.message, hook[0].name);
73
73
  }
74
74
  };
@@ -81,7 +81,6 @@ async function runLauncherHook(hook, ...args) {
81
81
  }
82
82
  })).catch(catchFn);
83
83
  }
84
- exports.runLauncherHook = runLauncherHook;
85
84
  /**
86
85
  * Run onCompleteHook in Launcher
87
86
  * @param {Array|Function} onCompleteHook - can be array of functions or single function
@@ -90,7 +89,7 @@ exports.runLauncherHook = runLauncherHook;
90
89
  * @param {*} exitCode
91
90
  * @param {*} results
92
91
  */
93
- async function runOnCompleteHook(onCompleteHook, config, capabilities, exitCode, results) {
92
+ export async function runOnCompleteHook(onCompleteHook, config, capabilities, exitCode, results) {
94
93
  if (typeof onCompleteHook === 'function') {
95
94
  onCompleteHook = [onCompleteHook];
96
95
  }
@@ -101,18 +100,17 @@ async function runOnCompleteHook(onCompleteHook, config, capabilities, exitCode,
101
100
  }
102
101
  catch (err) {
103
102
  log.error(`Error in onCompleteHook: ${err.stack}`);
104
- if (err instanceof webdriverio_1.SevereServiceError) {
103
+ if (err instanceof SevereServiceError) {
105
104
  throw new HookError(err.message, 'onComplete');
106
105
  }
107
106
  return 1;
108
107
  }
109
108
  }));
110
109
  }
111
- exports.runOnCompleteHook = runOnCompleteHook;
112
110
  /**
113
111
  * get runner identification by caps
114
112
  */
115
- function getRunnerName(caps = {}) {
113
+ export function getRunnerName(caps = {}) {
116
114
  let runner = caps.browserName ||
117
115
  caps.appPackage ||
118
116
  caps.appWaitActivity ||
@@ -128,13 +126,11 @@ function getRunnerName(caps = {}) {
128
126
  }
129
127
  return runner;
130
128
  }
131
- exports.getRunnerName = getRunnerName;
132
129
  function buildNewConfigArray(str, type, change) {
133
- var _a;
134
130
  const newStr = str
135
131
  .split(`${type}s: `)[1]
136
132
  .replace(/'/g, '');
137
- let newArray = ((_a = newStr.match(/(\w*)/gmi)) === null || _a === void 0 ? void 0 : _a.filter(e => !!e).concat([change])) || [];
133
+ let newArray = newStr.match(/(\w*)/gmi)?.filter(e => !!e).concat([change]) || [];
138
134
  return str
139
135
  .replace('// ', '')
140
136
  .replace(new RegExp(`(${type}s: )((.*\\s*)*)`), `$1[${newArray.map(e => `'${e}'`)}]`);
@@ -142,7 +138,7 @@ function buildNewConfigArray(str, type, change) {
142
138
  function buildNewConfigString(str, type, change) {
143
139
  return str.replace(new RegExp(`(${type}: )('\\w*')`), `$1'${change}'`);
144
140
  }
145
- function findInConfig(config, type) {
141
+ export function findInConfig(config, type) {
146
142
  let regexStr = `[\\/\\/]*[\\s]*${type}s: [\\s]*\\[([\\s]*['|"]\\w*['|"],*)*[\\s]*\\]`;
147
143
  if (type === 'framework') {
148
144
  regexStr = `[\\/\\/]*[\\s]*${type}: ([\\s]*['|"]\\w*['|"])`;
@@ -150,8 +146,7 @@ function findInConfig(config, type) {
150
146
  const regex = new RegExp(regexStr, 'gmi');
151
147
  return config.match(regex);
152
148
  }
153
- exports.findInConfig = findInConfig;
154
- function replaceConfig(config, type, name) {
149
+ export function replaceConfig(config, type, name) {
155
150
  if (type === 'framework') {
156
151
  return buildNewConfigString(config, type, name);
157
152
  }
@@ -162,8 +157,7 @@ function replaceConfig(config, type, name) {
162
157
  const text = match.pop() || '';
163
158
  return config.replace(text, buildNewConfigArray(text, type, name));
164
159
  }
165
- exports.replaceConfig = replaceConfig;
166
- function addServiceDeps(names, packages, update = false) {
160
+ export function addServiceDeps(names, packages, update = false) {
167
161
  /**
168
162
  * automatically install latest Chromedriver if `wdio-chromedriver-service`
169
163
  * was selected for install
@@ -180,7 +174,7 @@ function addServiceDeps(names, packages, update = false) {
180
174
  * was selected for install
181
175
  */
182
176
  if (names.some(({ short }) => short === 'appium')) {
183
- const result = (0, child_process_1.execSync)('appium --version || echo APPIUM_MISSING').toString().trim();
177
+ const result = execSync('appium --version || echo APPIUM_MISSING').toString().trim();
184
178
  if (result === 'APPIUM_MISSING') {
185
179
  packages.push('appium');
186
180
  }
@@ -190,28 +184,25 @@ function addServiceDeps(names, packages, update = false) {
190
184
  }
191
185
  }
192
186
  }
193
- exports.addServiceDeps = addServiceDeps;
194
187
  /**
195
188
  * @todo add JSComments
196
189
  */
197
- function convertPackageHashToObject(pkg, hash = '$--$') {
190
+ export function convertPackageHashToObject(pkg, hash = '$--$') {
198
191
  const splitHash = pkg.split(hash);
199
192
  return {
200
193
  package: splitHash[0],
201
194
  short: splitHash[1]
202
195
  };
203
196
  }
204
- exports.convertPackageHashToObject = convertPackageHashToObject;
205
- async function renderConfigurationFile(answers) {
206
- const tplPath = path_1.default.join(__dirname, 'templates/wdio.conf.tpl.ejs');
197
+ export async function renderConfigurationFile(answers) {
198
+ const tplPath = path.join(__dirname, 'templates/wdio.conf.tpl.ejs');
207
199
  const filename = `wdio.conf.${answers.isUsingTypeScript ? 'ts' : 'js'}`;
208
200
  const renderedTpl = await renderFile(tplPath, { answers });
209
- return fs_extra_1.default.promises.writeFile(path_1.default.join(process.cwd(), answers.isUsingTypeScript ? 'test' : '', filename), renderedTpl);
201
+ return fs.writeFile(path.join(process.cwd(), answers.isUsingTypeScript ? 'test' : '', filename), renderedTpl);
210
202
  }
211
- exports.renderConfigurationFile = renderConfigurationFile;
212
- const validateServiceAnswers = (answers) => {
203
+ export const validateServiceAnswers = (answers) => {
213
204
  let result = true;
214
- Object.entries(constants_1.EXCLUSIVE_SERVICES).forEach(([name, { services, message }]) => {
205
+ Object.entries(EXCLUSIVE_SERVICES).forEach(([name, { services, message }]) => {
215
206
  const exists = answers.some(answer => answer.includes(name));
216
207
  const hasExclusive = services.some(service => answers.some(answer => answer.includes(service)));
217
208
  if (exists && hasExclusive) {
@@ -220,8 +211,7 @@ const validateServiceAnswers = (answers) => {
220
211
  });
221
212
  return result;
222
213
  };
223
- exports.validateServiceAnswers = validateServiceAnswers;
224
- function getCapabilities(arg) {
214
+ export function getCapabilities(arg) {
225
215
  const optionalCapabilites = {
226
216
  platformVersion: arg.platformVersion,
227
217
  udid: arg.udid,
@@ -235,19 +225,19 @@ function getCapabilities(arg) {
235
225
  return {
236
226
  capabilities: {
237
227
  app: arg.option,
238
- ...(arg.option.endsWith('apk') ? constants_1.ANDROID_CONFIG : constants_1.IOS_CONFIG),
228
+ ...(arg.option.endsWith('apk') ? ANDROID_CONFIG : IOS_CONFIG),
239
229
  ...optionalCapabilites,
240
230
  }
241
231
  };
242
232
  }
243
233
  else if (/android/.test(arg.option)) {
244
- return { capabilities: { browserName: 'Chrome', ...constants_1.ANDROID_CONFIG, ...optionalCapabilites } };
234
+ return { capabilities: { browserName: 'Chrome', ...ANDROID_CONFIG, ...optionalCapabilites } };
245
235
  }
246
236
  else if (/ios/.test(arg.option)) {
247
- return { capabilities: { browserName: 'Safari', ...constants_1.IOS_CONFIG, ...optionalCapabilites } };
237
+ return { capabilities: { browserName: 'Safari', ...IOS_CONFIG, ...optionalCapabilites } };
248
238
  }
249
239
  else if (/(js|ts)$/.test(arg.option)) {
250
- const config = new config_1.ConfigParser();
240
+ const config = new ConfigParser();
251
241
  config.autoCompile();
252
242
  try {
253
243
  config.addConfigFile(arg.option);
@@ -265,7 +255,7 @@ function getCapabilities(arg) {
265
255
  requiredCaps[parseInt(arg.capabilities, 10)] ||
266
256
  // multiremote
267
257
  requiredCaps[arg.capabilities]);
268
- const requiredW3CCaps = (0, lodash_pickby_1.default)(requiredCaps, (_, key) => protocols_1.CAPABILITY_KEYS.includes(key) || key.includes(':'));
258
+ const requiredW3CCaps = pickBy(requiredCaps, (_, key) => CAPABILITY_KEYS.includes(key) || key.includes(':'));
269
259
  if (!Object.keys(requiredW3CCaps).length) {
270
260
  throw Error(`No capability found in given config file with the provided capability indexed/named property: ${arg.capabilities}. Please check the capability in your wdio config file.`);
271
261
  }
@@ -273,26 +263,30 @@ function getCapabilities(arg) {
273
263
  }
274
264
  return { capabilities: { browserName: arg.option } };
275
265
  }
276
- exports.getCapabilities = getCapabilities;
277
266
  /**
278
267
  * Check if file exists in current work directory
279
268
  * @param {string} filename to check existance for
280
269
  */
281
- function hasFile(filename) {
282
- return fs_extra_1.default.existsSync(path_1.default.join(process.cwd(), filename));
270
+ export function hasFile(filename) {
271
+ try {
272
+ fsSync.accessSync(path.join(process.cwd(), filename));
273
+ return true;
274
+ }
275
+ catch (err) {
276
+ return false;
277
+ }
283
278
  }
284
- exports.hasFile = hasFile;
285
279
  /**
286
280
  * Check if package is installed
287
281
  * @param {string} package to check existance for
288
282
  */
289
- function hasPackage(pkg) {
283
+ export function hasPackage(pkg) {
290
284
  try {
291
285
  /**
292
286
  * this is only for testing purposes as we want to check whether
293
287
  * we add `@babel/register` to the packages to install when resolving fails
294
288
  */
295
- if (process.env.JEST_WORKER_ID && process.env.WDIO_TEST_THROW_RESOLVE) {
289
+ if (process.env.VITEST_WORKER_ID && process.env.WDIO_TEST_THROW_RESOLVE) {
296
290
  throw new Error('resolve error');
297
291
  }
298
292
  require.resolve(pkg);
@@ -302,35 +296,33 @@ function hasPackage(pkg) {
302
296
  return false;
303
297
  }
304
298
  }
305
- exports.hasPackage = hasPackage;
306
299
  /**
307
300
  * generate test files based on CLI answers
308
301
  */
309
- async function generateTestFiles(answers) {
302
+ export async function generateTestFiles(answers) {
310
303
  const testFiles = answers.framework === 'cucumber'
311
- ? [path_1.default.join(TEMPLATE_ROOT_DIR, 'cucumber')]
304
+ ? [path.join(TEMPLATE_ROOT_DIR, 'cucumber')]
312
305
  : (answers.framework === 'mocha'
313
- ? [path_1.default.join(TEMPLATE_ROOT_DIR, 'mocha')]
314
- : [path_1.default.join(TEMPLATE_ROOT_DIR, 'jasmine')]);
306
+ ? [path.join(TEMPLATE_ROOT_DIR, 'mocha')]
307
+ : [path.join(TEMPLATE_ROOT_DIR, 'jasmine')]);
315
308
  if (answers.usePageObjects) {
316
- testFiles.push(path_1.default.join(TEMPLATE_ROOT_DIR, 'pageobjects'));
309
+ testFiles.push(path.join(TEMPLATE_ROOT_DIR, 'pageobjects'));
317
310
  }
318
- const files = (await Promise.all(testFiles.map((dirPath) => (0, recursive_readdir_1.default)(dirPath, [(file, stats) => !stats.isDirectory() && !(file.endsWith('.ejs') || file.endsWith('.feature'))])))).reduce((cur, acc) => [...acc, ...(cur)], []);
311
+ const files = (await Promise.all(testFiles.map((dirPath) => readDir(dirPath, [(file, stats) => !stats.isDirectory() && !(file.endsWith('.ejs') || file.endsWith('.feature'))])))).reduce((cur, acc) => [...acc, ...(cur)], []);
319
312
  for (const file of files) {
320
313
  const renderedTpl = await renderFile(file, answers);
321
314
  let destPath = (file.endsWith('page.js.ejs')
322
- ? `${answers.destPageObjectRootPath}/${path_1.default.basename(file)}`
315
+ ? `${answers.destPageObjectRootPath}/${path.basename(file)}`
323
316
  : file.includes('step_definition')
324
317
  ? `${answers.stepDefinitions}`
325
- : `${answers.destSpecRootPath}/${path_1.default.basename(file)}`).replace(/\.ejs$/, '').replace(/\.js$/, answers.isUsingTypeScript ? '.ts' : '.js');
326
- fs_extra_1.default.ensureDirSync(path_1.default.dirname(destPath));
327
- await fs_extra_1.default.promises.writeFile(destPath, renderedTpl);
318
+ : `${answers.destSpecRootPath}/${path.basename(file)}`).replace(/\.ejs$/, '').replace(/\.js$/, answers.isUsingTypeScript ? '.ts' : '.js');
319
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
320
+ await fs.writeFile(destPath, renderedTpl);
328
321
  }
329
322
  }
330
- exports.generateTestFiles = generateTestFiles;
331
- async function getAnswers(yes) {
323
+ export async function getAnswers(yes) {
332
324
  return yes
333
- ? constants_1.QUESTIONNAIRE.reduce((answers, question) => Object.assign(answers, question.when && !question.when(answers)
325
+ ? QUESTIONNAIRE.reduce((answers, question) => Object.assign(answers, question.when && !question.when(answers)
334
326
  /**
335
327
  * set nothing if question doesn't apply
336
328
  */
@@ -351,19 +343,18 @@ async function getAnswers(yes) {
351
343
  : question.choices[0]
352
344
  : {}
353
345
  }), {})
354
- : await inquirer_1.default.prompt(constants_1.QUESTIONNAIRE);
346
+ : await inquirer.prompt(QUESTIONNAIRE);
355
347
  }
356
- exports.getAnswers = getAnswers;
357
- function getPathForFileGeneration(answers) {
358
- const destSpecRootPath = path_1.default.join(process.cwd(), path_1.default.dirname(answers.specs || '').replace(/\*\*$/, ''));
359
- const destStepRootPath = path_1.default.join(process.cwd(), path_1.default.dirname(answers.stepDefinitions || ''));
348
+ export function getPathForFileGeneration(answers) {
349
+ const destSpecRootPath = path.join(process.cwd(), path.dirname(answers.specs || '').replace(/\*\*$/, ''));
350
+ const destStepRootPath = path.join(process.cwd(), path.dirname(answers.stepDefinitions || ''));
360
351
  const destPageObjectRootPath = answers.usePageObjects
361
- ? path_1.default.join(process.cwd(), path_1.default.dirname(answers.pages || '').replace(/\*\*$/, ''))
352
+ ? path.join(process.cwd(), path.dirname(answers.pages || '').replace(/\*\*$/, ''))
362
353
  : '';
363
354
  let relativePath = (answers.generateTestFiles && answers.usePageObjects)
364
355
  ? !(convertPackageHashToObject(answers.framework).short === 'cucumber')
365
- ? path_1.default.relative(destSpecRootPath, destPageObjectRootPath)
366
- : path_1.default.relative(destStepRootPath, destPageObjectRootPath)
356
+ ? path.relative(destSpecRootPath, destPageObjectRootPath)
357
+ : path.relative(destStepRootPath, destPageObjectRootPath)
367
358
  : '';
368
359
  /**
369
360
  * On Windows, path.relative can return backslashes that could be interpreted as espace sequences in strings
@@ -378,11 +369,30 @@ function getPathForFileGeneration(answers) {
378
369
  relativePath: relativePath
379
370
  };
380
371
  }
381
- exports.getPathForFileGeneration = getPathForFileGeneration;
382
- function getDefaultFiles(answers, filePath) {
383
- var _a;
384
- return ((_a = answers === null || answers === void 0 ? void 0 : answers.isUsingCompiler) === null || _a === void 0 ? void 0 : _a.toString().includes('TypeScript'))
372
+ export function getDefaultFiles(answers, filePath) {
373
+ return answers?.isUsingCompiler?.toString().includes('TypeScript')
385
374
  ? `${filePath}.ts`
386
375
  : `${filePath}.js`;
387
376
  }
388
- exports.getDefaultFiles = getDefaultFiles;
377
+ /**
378
+ * Ensure core WebdriverIO packages have the same version as cli so that if someone
379
+ * installs `@wdio/cli@next` and runs the wizard, all related packages have the same version.
380
+ * running `matchAll` to a version like "8.0.0-alpha.249+4bc237701", results in:
381
+ * ['8.0.0-alpha.249+4bc237701', '8', '0', '0', 'alpha', '249', '4bc237701']
382
+ */
383
+ export function specifyVersionIfNeeded(packagesToInstall, version) {
384
+ const { value } = version.matchAll(VERSION_REGEXP).next();
385
+ if (value) {
386
+ const [major, minor, patch, tagName, build] = value.slice(1, -1); // drop commit bit
387
+ return packagesToInstall.map((p) => {
388
+ if (p.startsWith('@wdio') || ['devtools', 'webdriver', 'webdriverio'].includes(p)) {
389
+ return `${p}@^${major}.${minor}.${patch}-${tagName}.${build}`;
390
+ }
391
+ if (COMMUNITY_PACKAGES_WITH_V8_SUPPORT.includes(p)) {
392
+ return `${p}@next`;
393
+ }
394
+ return p;
395
+ });
396
+ }
397
+ return packagesToInstall;
398
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Workers } from '@wdio/types';
2
- import { RunCommandArguments, ValueKeyIteratee } from './types.js';
2
+ import type { RunCommandArguments, ValueKeyIteratee } from './types';
3
3
  declare type Spec = string | string[];
4
4
  export default class Watcher {
5
5
  private _configFile;
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAgB,OAAO,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIlE,aAAK,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;AAC7B,MAAM,CAAC,OAAO,OAAO,OAAO;IAKpB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,KAAK;IALjB,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,MAAM,CAAQ;gBAGV,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,YAAY,CAAC;IAYpD,KAAK;IAwCX;;;;OAIG;IACH,eAAe,CAAE,UAAU,UAAO,UAChB,MAAM;IA6BxB;;;;;OAKG;IACH,UAAU,CAAE,SAAS,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU;IAiB7H;;;OAGG;IACH,GAAG,CAAE,MAAM,GAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,IAAI,CAAA;KAAO;IAuC9E,OAAO;CAGV"}
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAgB,OAAO,EAAE,MAAM,aAAa,CAAA;AAGxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAIpE,aAAK,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;AAC7B,MAAM,CAAC,OAAO,OAAO,OAAO;IAKpB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,KAAK;IALjB,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,MAAM,CAAQ;gBAGV,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,YAAY,CAAC;IAYpD,KAAK;IAwCX;;;;OAIG;IACH,eAAe,CAAE,UAAU,UAAO,UAChB,MAAM;IA6BxB;;;;;OAKG;IACH,UAAU,CAAE,SAAS,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU;IAqB7H;;;OAGG;IACH,GAAG,CAAE,MAAM,GAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,IAAI,CAAA;KAAO;IAuC9E,OAAO;CAGV"}
package/build/watcher.js CHANGED
@@ -1,31 +1,30 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const chokidar_1 = __importDefault(require("chokidar"));
7
- const logger_1 = __importDefault(require("@wdio/logger"));
8
- const lodash_pickby_1 = __importDefault(require("lodash.pickby"));
9
- const lodash_flattendeep_1 = __importDefault(require("lodash.flattendeep"));
10
- const lodash_union_1 = __importDefault(require("lodash.union"));
11
- const launcher_1 = __importDefault(require("./launcher"));
12
- const log = (0, logger_1.default)('@wdio/cli:watch');
13
- class Watcher {
1
+ import chokidar from 'chokidar';
2
+ import logger from '@wdio/logger';
3
+ import pickBy from 'lodash.pickby';
4
+ import flattenDeep from 'lodash.flattendeep';
5
+ import union from 'lodash.union';
6
+ import Launcher from './launcher.js';
7
+ const log = logger('@wdio/cli:watch');
8
+ export default class Watcher {
9
+ _configFile;
10
+ _args;
11
+ _launcher;
12
+ _specs;
14
13
  constructor(_configFile, _args) {
15
14
  this._configFile = _configFile;
16
15
  this._args = _args;
17
16
  log.info('Starting launcher in watch mode');
18
- this._launcher = new launcher_1.default(this._configFile, this._args, true);
17
+ this._launcher = new Launcher(this._configFile, this._args, true);
19
18
  const specs = this._launcher.configParser.getSpecs();
20
- const capSpecs = this._launcher.isMultiremote ? [] : (0, lodash_union_1.default)((0, lodash_flattendeep_1.default)(this._launcher.configParser.getCapabilities().map(cap => cap.specs || [])));
19
+ const capSpecs = this._launcher.isMultiremote ? [] : union(flattenDeep(this._launcher.configParser.getCapabilities().map(cap => cap.specs || [])));
21
20
  this._specs = [...specs, ...capSpecs];
22
21
  }
23
22
  async watch() {
24
23
  /**
25
24
  * listen on spec changes and rerun specific spec file
26
25
  */
27
- let flattenedSpecs = (0, lodash_flattendeep_1.default)(this._specs);
28
- chokidar_1.default.watch(flattenedSpecs, { ignoreInitial: true })
26
+ let flattenedSpecs = flattenDeep(this._specs);
27
+ chokidar.watch(flattenedSpecs, { ignoreInitial: true })
29
28
  .on('add', this.getFileListener())
30
29
  .on('change', this.getFileListener());
31
30
  /**
@@ -33,7 +32,7 @@ class Watcher {
33
32
  */
34
33
  const { filesToWatch } = this._launcher.configParser.getConfig();
35
34
  if (filesToWatch.length) {
36
- chokidar_1.default.watch(filesToWatch, { ignoreInitial: true })
35
+ chokidar.watch(filesToWatch, { ignoreInitial: true })
37
36
  .on('add', this.getFileListener(false))
38
37
  .on('change', this.getFileListener(false));
39
38
  }
@@ -52,7 +51,7 @@ class Watcher {
52
51
  if (Object.values(workers).find((w) => w.isBusy)) {
53
52
  return;
54
53
  }
55
- this._launcher.interface.finalise();
54
+ this._launcher.interface?.finalise();
56
55
  }));
57
56
  }
58
57
  /**
@@ -95,15 +94,18 @@ class Watcher {
95
94
  * @return Object with workers, e.g. {'0-0': { ... }}
96
95
  */
97
96
  getWorkers(predicate, includeBusyWorker) {
97
+ if (!this._launcher.runner) {
98
+ throw new Error('Internal Error: no runner initialised, call run() first');
99
+ }
98
100
  let workers = this._launcher.runner.workerPool;
99
101
  if (typeof predicate === 'function') {
100
- workers = (0, lodash_pickby_1.default)(workers, predicate);
102
+ workers = pickBy(workers, predicate);
101
103
  }
102
104
  /**
103
105
  * filter out busy workers, only skip if explicitly desired
104
106
  */
105
107
  if (!includeBusyWorker) {
106
- workers = (0, lodash_pickby_1.default)(workers, (worker) => !worker.isBusy);
108
+ workers = pickBy(workers, (worker) => !worker.isBusy);
107
109
  }
108
110
  return workers;
109
111
  }
@@ -121,7 +123,7 @@ class Watcher {
121
123
  /**
122
124
  * don't do anything if no worker was found
123
125
  */
124
- if (Object.keys(workers).length === 0) {
126
+ if (Object.keys(workers).length === 0 || !this._launcher.interface) {
125
127
  return;
126
128
  }
127
129
  /**
@@ -144,7 +146,6 @@ class Watcher {
144
146
  }
145
147
  }
146
148
  cleanUp() {
147
- this._launcher.interface.setup();
149
+ this._launcher.interface?.setup();
148
150
  }
149
151
  }
150
- exports.default = Watcher;
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@wdio/cli",
3
- "version": "7.20.7",
3
+ "version": "7.20.8-alpha.504+428a9d729",
4
4
  "description": "WebdriverIO testrunner command line interface",
5
5
  "author": "Christian Bromann <mail@bromann.dev>",
6
6
  "homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-cli",
7
7
  "license": "MIT",
8
- "main": "./build/index",
9
8
  "bin": {
10
9
  "wdio": "./bin/wdio.js"
11
10
  },
12
11
  "engines": {
13
- "node": ">=12.0.0"
12
+ "node": "^16.13 || >=18"
14
13
  },
15
14
  "scripts": {
16
15
  "copy": "copyfiles -u 1 -V \"src/templates/**/*\" ./build/"
17
16
  },
18
17
  "repository": {
19
18
  "type": "git",
20
- "url": "git://github.com/webdriverio/webdriverio.git"
19
+ "url": "git://github.com/webdriverio/webdriverio.git",
20
+ "directory": "packages/wdio-cli"
21
21
  },
22
22
  "keywords": [
23
23
  "webdriver",
@@ -28,39 +28,44 @@
28
28
  "bugs": {
29
29
  "url": "https://github.com/webdriverio/webdriverio/issues"
30
30
  },
31
+ "type": "module",
32
+ "exports": "./build/index.js",
33
+ "types": "./build/index.d.ts",
34
+ "typeScriptVersion": "3.8.3",
31
35
  "dependencies": {
32
- "@types/ejs": "^3.0.5",
33
- "@types/fs-extra": "^9.0.4",
34
- "@types/inquirer": "^8.1.2",
35
- "@types/lodash.flattendeep": "^4.4.6",
36
- "@types/lodash.pickby": "^4.6.6",
37
- "@types/lodash.union": "^4.6.6",
38
- "@types/node": "^18.0.0",
39
- "@types/recursive-readdir": "^2.2.0",
40
- "@wdio/config": "7.20.7",
41
- "@wdio/logger": "7.19.0",
42
- "@wdio/protocols": "7.20.6",
43
- "@wdio/types": "7.20.7",
44
- "@wdio/utils": "7.20.7",
36
+ "@types/ejs": "^3.1.1",
37
+ "@types/inquirer": "^9.0.0",
38
+ "@types/lodash.flattendeep": "^4.4.7",
39
+ "@types/lodash.pickby": "^4.6.7",
40
+ "@types/lodash.union": "^4.6.7",
41
+ "@types/recursive-readdir": "^2.2.1",
42
+ "@types/yargs": "^17.0.10",
43
+ "@wdio/config": "7.20.8-alpha.504+428a9d729",
44
+ "@wdio/globals": "7.20.8-alpha.504+428a9d729",
45
+ "@wdio/logger": "7.20.8-alpha.504+428a9d729",
46
+ "@wdio/protocols": "7.20.8-alpha.504+428a9d729",
47
+ "@wdio/types": "7.20.8-alpha.504+428a9d729",
48
+ "@wdio/utils": "7.20.8-alpha.504+428a9d729",
45
49
  "async-exit-hook": "^2.0.1",
46
- "chalk": "^4.0.0",
47
- "chokidar": "^3.0.0",
48
- "cli-spinners": "^2.1.0",
49
- "ejs": "^3.0.1",
50
- "fs-extra": "^10.0.0",
51
- "inquirer": "8.2.4",
50
+ "chalk": "^5.0.1",
51
+ "chokidar": "^3.5.3",
52
+ "cli-spinners": "^2.6.1",
53
+ "ejs": "^3.1.8",
54
+ "inquirer": "9.1.2",
52
55
  "lodash.flattendeep": "^4.4.0",
53
56
  "lodash.pickby": "^4.6.0",
54
57
  "lodash.union": "^4.6.0",
55
58
  "mkdirp": "^1.0.4",
56
59
  "recursive-readdir": "^2.2.2",
57
- "webdriverio": "7.20.7",
58
- "yargs": "^17.0.0",
60
+ "webdriverio": "7.20.8-alpha.504+428a9d729",
61
+ "yargs": "^17.5.1",
59
62
  "yarn-install": "^1.0.0"
60
63
  },
61
64
  "publishConfig": {
62
65
  "access": "public"
63
66
  },
64
- "types": "./build/index.d.ts",
65
- "gitHead": "21b8b61453f4749d87eca3e4d7d6e5e2cb60f043"
67
+ "devDependencies": {
68
+ "@types/node": "^18.0.0"
69
+ },
70
+ "gitHead": "428a9d729ae6231968a60908732fa3f607d195e9"
66
71
  }