@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/bin/wdio.js +7 -1
- package/build/commands/config.d.ts +3 -3
- package/build/commands/config.d.ts.map +1 -1
- package/build/commands/config.js +58 -69
- package/build/commands/index.d.ts +2 -0
- package/build/commands/index.d.ts.map +1 -0
- package/build/commands/index.js +5 -0
- package/build/commands/install.d.ts +3 -3
- package/build/commands/install.d.ts.map +1 -1
- package/build/commands/install.js +28 -35
- package/build/commands/repl.d.ts +5 -5
- package/build/commands/repl.d.ts.map +1 -1
- package/build/commands/repl.js +15 -29
- package/build/commands/run.d.ts +7 -5
- package/build/commands/run.d.ts.map +1 -1
- package/build/commands/run.js +54 -33
- package/build/constants.d.ts +16 -2
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +53 -48
- package/build/index.d.ts +4 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +24 -41
- package/build/interface.d.ts +3 -3
- package/build/interface.d.ts.map +1 -1
- package/build/interface.js +57 -52
- package/build/launcher.d.ts +4 -4
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +81 -61
- package/build/types.d.ts +2 -2
- package/build/types.d.ts.map +1 -1
- package/build/types.js +1 -2
- package/build/utils.d.ts +8 -1
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +102 -92
- package/build/watcher.d.ts +1 -1
- package/build/watcher.d.ts.map +1 -1
- package/build/watcher.js +25 -24
- package/package.json +32 -27
package/build/utils.js
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
205
|
-
|
|
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
|
|
201
|
+
return fs.writeFile(path.join(process.cwd(), answers.isUsingTypeScript ? 'test' : '', filename), renderedTpl);
|
|
210
202
|
}
|
|
211
|
-
|
|
212
|
-
const validateServiceAnswers = (answers) => {
|
|
203
|
+
export const validateServiceAnswers = (answers) => {
|
|
213
204
|
let result = true;
|
|
214
|
-
Object.entries(
|
|
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
|
-
|
|
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') ?
|
|
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', ...
|
|
234
|
+
return { capabilities: { browserName: 'Chrome', ...ANDROID_CONFIG, ...optionalCapabilites } };
|
|
245
235
|
}
|
|
246
236
|
else if (/ios/.test(arg.option)) {
|
|
247
|
-
return { capabilities: { browserName: 'Safari', ...
|
|
237
|
+
return { capabilities: { browserName: 'Safari', ...IOS_CONFIG, ...optionalCapabilites } };
|
|
248
238
|
}
|
|
249
239
|
else if (/(js|ts)$/.test(arg.option)) {
|
|
250
|
-
const config = new
|
|
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 = (
|
|
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
|
-
|
|
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.
|
|
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
|
-
? [
|
|
304
|
+
? [path.join(TEMPLATE_ROOT_DIR, 'cucumber')]
|
|
312
305
|
: (answers.framework === 'mocha'
|
|
313
|
-
? [
|
|
314
|
-
: [
|
|
306
|
+
? [path.join(TEMPLATE_ROOT_DIR, 'mocha')]
|
|
307
|
+
: [path.join(TEMPLATE_ROOT_DIR, 'jasmine')]);
|
|
315
308
|
if (answers.usePageObjects) {
|
|
316
|
-
testFiles.push(
|
|
309
|
+
testFiles.push(path.join(TEMPLATE_ROOT_DIR, 'pageobjects'));
|
|
317
310
|
}
|
|
318
|
-
const files = (await Promise.all(testFiles.map((dirPath) => (
|
|
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}/${
|
|
315
|
+
? `${answers.destPageObjectRootPath}/${path.basename(file)}`
|
|
323
316
|
: file.includes('step_definition')
|
|
324
317
|
? `${answers.stepDefinitions}`
|
|
325
|
-
: `${answers.destSpecRootPath}/${
|
|
326
|
-
|
|
327
|
-
await
|
|
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
|
-
|
|
331
|
-
async function getAnswers(yes) {
|
|
323
|
+
export async function getAnswers(yes) {
|
|
332
324
|
return yes
|
|
333
|
-
?
|
|
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
|
|
346
|
+
: await inquirer.prompt(QUESTIONNAIRE);
|
|
355
347
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const
|
|
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
|
-
?
|
|
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
|
-
?
|
|
366
|
-
:
|
|
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
|
-
|
|
382
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/build/watcher.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Workers } from '@wdio/types';
|
|
2
|
-
import { RunCommandArguments, ValueKeyIteratee } from './types
|
|
2
|
+
import type { RunCommandArguments, ValueKeyIteratee } from './types';
|
|
3
3
|
declare type Spec = string | string[];
|
|
4
4
|
export default class Watcher {
|
|
5
5
|
private _configFile;
|
package/build/watcher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
17
|
+
this._launcher = new Launcher(this._configFile, this._args, true);
|
|
19
18
|
const specs = this._launcher.configParser.getSpecs();
|
|
20
|
-
const capSpecs = this._launcher.isMultiremote ? [] : (
|
|
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 = (
|
|
28
|
-
|
|
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
|
-
|
|
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
|
|
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 = (
|
|
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 = (
|
|
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
|
|
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.
|
|
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
|
+
"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.
|
|
33
|
-
"@types/
|
|
34
|
-
"@types/
|
|
35
|
-
"@types/lodash.
|
|
36
|
-
"@types/lodash.
|
|
37
|
-
"@types/
|
|
38
|
-
"@types/
|
|
39
|
-
"@
|
|
40
|
-
"@wdio/
|
|
41
|
-
"@wdio/logger": "7.
|
|
42
|
-
"@wdio/protocols": "7.20.
|
|
43
|
-
"@wdio/types": "7.20.
|
|
44
|
-
"@wdio/utils": "7.20.
|
|
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": "^
|
|
47
|
-
"chokidar": "^3.
|
|
48
|
-
"cli-spinners": "^2.1
|
|
49
|
-
"ejs": "^3.
|
|
50
|
-
"
|
|
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.
|
|
58
|
-
"yargs": "^17.
|
|
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
|
-
"
|
|
65
|
-
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@types/node": "^18.0.0"
|
|
69
|
+
},
|
|
70
|
+
"gitHead": "428a9d729ae6231968a60908732fa3f607d195e9"
|
|
66
71
|
}
|