@wdio/cli 9.16.2 → 9.17.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.
Files changed (68) hide show
  1. package/build/commands/index.d.ts.map +1 -1
  2. package/build/commands/repl.d.ts.map +1 -1
  3. package/build/commands/run.d.ts +1 -1
  4. package/build/commands/run.d.ts.map +1 -1
  5. package/build/constants.d.ts +0 -235
  6. package/build/constants.d.ts.map +1 -1
  7. package/build/index.js +120 -1737
  8. package/build/interface.d.ts.map +1 -1
  9. package/build/types.d.ts +2 -74
  10. package/build/types.d.ts.map +1 -1
  11. package/build/utils.d.ts +1 -73
  12. package/build/utils.d.ts.map +1 -1
  13. package/build/watcher.d.ts.map +1 -1
  14. package/package.json +7 -7
  15. package/build/commands/config.d.ts +0 -74
  16. package/build/commands/config.d.ts.map +0 -1
  17. package/build/commands/install.d.ts +0 -12
  18. package/build/commands/install.d.ts.map +0 -1
  19. package/build/install.d.ts +0 -4
  20. package/build/install.d.ts.map +0 -1
  21. package/build/templates/EjsHelpers.d.ts +0 -18
  22. package/build/templates/EjsHelpers.d.ts.map +0 -1
  23. package/build/templates/exampleFiles/browser/Component.css.ejs +0 -121
  24. package/build/templates/exampleFiles/browser/Component.lit.ejs +0 -154
  25. package/build/templates/exampleFiles/browser/Component.lit.test.ejs +0 -24
  26. package/build/templates/exampleFiles/browser/Component.preact.ejs +0 -28
  27. package/build/templates/exampleFiles/browser/Component.preact.test.ejs +0 -59
  28. package/build/templates/exampleFiles/browser/Component.react.ejs +0 -29
  29. package/build/templates/exampleFiles/browser/Component.react.test.ejs +0 -58
  30. package/build/templates/exampleFiles/browser/Component.solid.ejs +0 -28
  31. package/build/templates/exampleFiles/browser/Component.solid.test.ejs +0 -58
  32. package/build/templates/exampleFiles/browser/Component.stencil.ejs +0 -43
  33. package/build/templates/exampleFiles/browser/Component.stencil.test.ejs +0 -45
  34. package/build/templates/exampleFiles/browser/Component.svelte.ejs +0 -47
  35. package/build/templates/exampleFiles/browser/Component.svelte.test.ejs +0 -58
  36. package/build/templates/exampleFiles/browser/Component.vue.ejs +0 -34
  37. package/build/templates/exampleFiles/browser/Component.vue.test.ejs +0 -62
  38. package/build/templates/exampleFiles/browser/standalone.test.ejs +0 -13
  39. package/build/templates/exampleFiles/cucumber/features/login.feature +0 -12
  40. package/build/templates/exampleFiles/cucumber/step_definitions/steps.js.ejs +0 -55
  41. package/build/templates/exampleFiles/mochaJasmine/test.e2e.js.ejs +0 -11
  42. package/build/templates/exampleFiles/pageobjects/login.page.js.ejs +0 -45
  43. package/build/templates/exampleFiles/pageobjects/page.js.ejs +0 -17
  44. package/build/templates/exampleFiles/pageobjects/secure.page.js.ejs +0 -20
  45. package/build/templates/exampleFiles/serenity-js/common/config/serenity.properties.ejs +0 -1
  46. package/build/templates/exampleFiles/serenity-js/common/serenity/github-api/GitHubStatus.ts.ejs +0 -41
  47. package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoList.ts.ejs +0 -100
  48. package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoListItem.ts.ejs +0 -36
  49. package/build/templates/exampleFiles/serenity-js/cucumber/step-definitions/steps.ts.ejs +0 -37
  50. package/build/templates/exampleFiles/serenity-js/cucumber/support/parameter.config.ts.ejs +0 -18
  51. package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/completing_items.feature.ejs +0 -23
  52. package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/narrative.md.ejs +0 -17
  53. package/build/templates/exampleFiles/serenity-js/jasmine/example.spec.ts.ejs +0 -86
  54. package/build/templates/exampleFiles/serenity-js/mocha/example.spec.ts.ejs +0 -88
  55. package/build/templates/snippets/afterTest.ejs +0 -20
  56. package/build/templates/snippets/capabilities.ejs +0 -57
  57. package/build/templates/snippets/cucumber.ejs +0 -50
  58. package/build/templates/snippets/electronTest.js.ejs +0 -7
  59. package/build/templates/snippets/jasmine.ejs +0 -20
  60. package/build/templates/snippets/macosTest.js.ejs +0 -11
  61. package/build/templates/snippets/mocha.ejs +0 -14
  62. package/build/templates/snippets/reporters.ejs +0 -14
  63. package/build/templates/snippets/serenity.ejs +0 -18
  64. package/build/templates/snippets/services.ejs +0 -18
  65. package/build/templates/snippets/testWithPO.js.ejs +0 -22
  66. package/build/templates/snippets/testWithoutPO.js.ejs +0 -19
  67. package/build/templates/snippets/vscodeTest.js.ejs +0 -9
  68. package/build/templates/wdio.conf.tpl.ejs +0 -412
package/build/index.js CHANGED
@@ -9,7 +9,7 @@ import "dotenv/config";
9
9
 
10
10
  // src/launcher.ts
11
11
  import exitHook from "async-exit-hook";
12
- import { resolve as resolve2 } from "import-meta-resolve";
12
+ import { resolve } from "import-meta-resolve";
13
13
  import logger3 from "@wdio/logger";
14
14
  import { validateConfig } from "@wdio/config";
15
15
  import { ConfigParser as ConfigParser2 } from "@wdio/config/node";
@@ -18,71 +18,20 @@ import { setupDriver, setupBrowser } from "@wdio/utils/node";
18
18
 
19
19
  // src/interface.ts
20
20
  import { EventEmitter } from "node:events";
21
- import chalk2, { supportsColor } from "chalk";
21
+ import chalk, { supportsColor } from "chalk";
22
22
  import logger2 from "@wdio/logger";
23
23
  import { SnapshotManager } from "@vitest/snapshot/manager";
24
24
 
25
25
  // src/utils.ts
26
- import fs2 from "node:fs/promises";
27
- import util, { promisify } from "node:util";
28
- import path2, { dirname } from "node:path";
29
- import { fileURLToPath } from "node:url";
30
- import { execSync, spawn } from "node:child_process";
26
+ import { promisify } from "node:util";
31
27
  import ejs from "ejs";
32
- import chalk from "chalk";
33
- import inquirer from "inquirer";
34
28
  import pickBy from "lodash.pickby";
35
29
  import logger from "@wdio/logger";
36
- import readDir from "recursive-readdir";
37
- import { $ } from "execa";
38
- import { readPackageUp } from "read-pkg-up";
39
- import { resolve } from "import-meta-resolve";
40
30
  import { SevereServiceError } from "webdriverio";
41
31
  import { ConfigParser } from "@wdio/config/node";
42
32
  import { CAPABILITY_KEYS } from "@wdio/protocols";
43
33
 
44
- // src/install.ts
45
- import { execa } from "execa";
46
- var installCommand = {
47
- npm: "install",
48
- pnpm: "add",
49
- yarn: "add",
50
- bun: "install"
51
- };
52
- var devFlag = {
53
- npm: "--save-dev",
54
- pnpm: "--save-dev",
55
- yarn: "--dev",
56
- bun: "--dev"
57
- };
58
- async function installPackages(cwd, packages, dev) {
59
- const pm = detectPackageManager();
60
- const devParam = dev ? devFlag[pm] : "";
61
- console.log("\n");
62
- const p = execa(pm, [installCommand[pm], ...packages, devParam], {
63
- cwd,
64
- stdout: process.stdout,
65
- stderr: process.stderr
66
- });
67
- const { stdout, stderr, exitCode } = await p;
68
- if (exitCode !== 0) {
69
- const cmd = getInstallCommand(pm, packages, dev);
70
- const customError = `\u26A0\uFE0F An unknown error happened! Please retry installing dependencies via "${cmd}"
71
-
72
- Error: ${stderr || stdout || "unknown"}`;
73
- console.error(customError);
74
- return false;
75
- }
76
- return true;
77
- }
78
- function getInstallCommand(pm, packages, dev) {
79
- const devParam = dev ? devFlag[pm] : "";
80
- return `${pm} ${installCommand[pm]} ${packages.join(" ")} ${devParam}`;
81
- }
82
-
83
34
  // src/constants.ts
84
- import fs from "node:fs";
85
- import path from "node:path";
86
35
  import module from "node:module";
87
36
  import { HOOK_DEFINITION } from "@wdio/utils";
88
37
  var require2 = module.createRequire(import.meta.url);
@@ -90,36 +39,7 @@ var pkgJSON = require2("../package.json");
90
39
  var pkg = pkgJSON;
91
40
  var CLI_EPILOGUE = `Documentation: https://webdriver.io
92
41
  @wdio/cli (v${pkg.version})`;
93
- var CONFIG_HELPER_INTRO = `
94
- ===============================
95
- \u{1F916} WDIO Configuration Wizard \u{1F9D9}
96
- ===============================
97
- `;
98
42
  var SUPPORTED_COMMANDS = ["run", "install", "config", "repl"];
99
- var PMs = ["npm", "yarn", "pnpm", "bun"];
100
- var SUPPORTED_CONFIG_FILE_EXTENSION = ["js", "ts", "mjs", "mts", "cjs", "cts"];
101
- var configHelperSuccessMessage = ({ projectRootDir, runScript, extraInfo = "" }) => `
102
- \u{1F916} Successfully setup project at ${projectRootDir} \u{1F389}
103
-
104
- Join our Discord Community Server and instantly find answers to your issues or queries. Or just join and say hi \u{1F44B}!
105
- \u{1F517} https://discord.webdriver.io
106
-
107
- Visit the project on GitHub to report bugs \u{1F41B} or raise feature requests \u{1F4A1}:
108
- \u{1F517} https://github.com/webdriverio/webdriverio
109
- ${extraInfo}
110
- To run your tests, execute:
111
- $ cd ${projectRootDir}
112
- $ npm run ${runScript}
113
- `;
114
- var CONFIG_HELPER_SERENITY_BANNER = `
115
- Learn more about Serenity/JS:
116
- \u{1F517} https://serenity-js.org/
117
- \u{1F517} https://serenity-js.org/handbook/test-runners/webdriverio/
118
- `;
119
- var DEPENDENCIES_INSTALLATION_MESSAGE = `
120
- To install dependencies, execute:
121
- %s
122
- `;
123
43
  var ANDROID_CONFIG = {
124
44
  platformName: "Android",
125
45
  automationName: "UiAutomator2",
@@ -130,667 +50,7 @@ var IOS_CONFIG = {
130
50
  automationName: "XCUITest",
131
51
  deviceName: "iPhone Simulator"
132
52
  };
133
- var SUPPORTED_PACKAGES = {
134
- runner: [
135
- { name: "E2E Testing - of Web or Mobile Applications", value: "@wdio/local-runner$--$local$--$e2e" },
136
- { name: "Component or Unit Testing - in the browser\n > https://webdriver.io/docs/component-testing", value: "@wdio/browser-runner$--$browser$--$component" },
137
- { name: "Desktop Testing - of Electron Applications\n > https://webdriver.io/docs/desktop-testing/electron", value: "@wdio/local-runner$--$local$--$electron" },
138
- { name: "Desktop Testing - of MacOS Applications\n > https://webdriver.io/docs/desktop-testing/macos", value: "@wdio/local-runner$--$local$--$macos" },
139
- { name: "VS Code Extension Testing\n > https://webdriver.io/docs/vscode-extension-testing", value: "@wdio/local-runner$--$local$--$vscode" },
140
- { name: "Roku Testing - of OTT apps running on RokuOS\n > https://webdriver.io/docs/wdio-roku-service", value: "@wdio/local-runner$--$local$--$roku" }
141
- ],
142
- framework: [
143
- { name: "Mocha (https://mochajs.org/)", value: "@wdio/mocha-framework$--$mocha" },
144
- { name: "Mocha with Serenity/JS (https://serenity-js.org/)", value: "@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$mocha" },
145
- { name: "Jasmine (https://jasmine.github.io/)", value: "@wdio/jasmine-framework$--$jasmine" },
146
- { name: "Jasmine with Serenity/JS (https://serenity-js.org/)", value: "@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$jasmine" },
147
- { name: "Cucumber (https://cucumber.io/)", value: "@wdio/cucumber-framework$--$cucumber" },
148
- { name: "Cucumber with Serenity/JS (https://serenity-js.org/)", value: "@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$cucumber" }
149
- ],
150
- reporter: [
151
- { name: "spec", value: "@wdio/spec-reporter$--$spec", checked: true },
152
- { name: "dot", value: "@wdio/dot-reporter$--$dot" },
153
- { name: "junit", value: "@wdio/junit-reporter$--$junit" },
154
- { name: "allure", value: "@wdio/allure-reporter$--$allure" },
155
- { name: "sumologic", value: "@wdio/sumologic-reporter$--$sumologic" },
156
- { name: "concise", value: "@wdio/concise-reporter$--$concise" },
157
- { name: "json", value: "@wdio/json-reporter$--$json" },
158
- // external
159
- { name: "reportportal", value: "wdio-reportportal-reporter$--$reportportal" },
160
- { name: "video", value: "wdio-video-reporter$--$video" },
161
- { name: "cucumber-json", value: "wdio-cucumberjs-json-reporter$--$cucumberjs-json" },
162
- { name: "mochawesome", value: "wdio-mochawesome-reporter$--$mochawesome" },
163
- { name: "timeline", value: "wdio-timeline-reporter$--$timeline" },
164
- { name: "html-nice", value: "wdio-html-nice-reporter$--$html-nice" },
165
- { name: "slack", value: "@moroo/wdio-slack-reporter$--$slack" },
166
- { name: "teamcity", value: "wdio-teamcity-reporter$--$teamcity" },
167
- { name: "delta", value: "@delta-reporter/wdio-delta-reporter-service$--$delta" },
168
- { name: "testrail", value: "@wdio/testrail-reporter$--$testrail" },
169
- { name: "light", value: "wdio-light-reporter$--$light" },
170
- { name: "wdio-json-html-reporter", value: "wdio-json-html-reporter$--$jsonhtml" }
171
- ],
172
- plugin: [
173
- { name: "wait-for: utilities that provide functionalities to wait for certain conditions till a defined task is complete.\n > https://www.npmjs.com/package/wdio-wait-for", value: "wdio-wait-for$--$wait-for" },
174
- { name: "angular-component-harnesses: support for Angular component test harnesses\n > https://www.npmjs.com/package/@badisi/wdio-harness", value: "@badisi/wdio-harness$--$harness" },
175
- { name: "Testing Library: utilities that encourage good testing practices laid down by dom-testing-library.\n > https://testing-library.com/docs/webdriverio-testing-library/intro", value: "@testing-library/webdriverio$--$testing-library" }
176
- ],
177
- service: [
178
- // internal or community driver services
179
- { name: "visual", value: "@wdio/visual-service$--$visual" },
180
- { name: "vite", value: "wdio-vite-service$--$vite" },
181
- { name: "nuxt", value: "wdio-nuxt-service$--$nuxt" },
182
- { name: "firefox-profile", value: "@wdio/firefox-profile-service$--$firefox-profile" },
183
- { name: "gmail", value: "wdio-gmail-service$--$gmail" },
184
- { name: "sauce", value: "@wdio/sauce-service$--$sauce" },
185
- { name: "testingbot", value: "@wdio/testingbot-service$--$testingbot" },
186
- { name: "browserstack", value: "@wdio/browserstack-service$--$browserstack" },
187
- { name: "lighthouse", value: "@wdio/lighthouse-service$--$lighthouse" },
188
- { name: "vscode", value: "wdio-vscode-service$--$vscode" },
189
- { name: "electron", value: "wdio-electron-service$--$electron" },
190
- { name: "appium", value: "@wdio/appium-service$--$appium" },
191
- // external
192
- { name: "eslinter-service", value: "wdio-eslinter-service$--$eslinter" },
193
- { name: "lambdatest", value: "wdio-lambdatest-service$--$lambdatest" },
194
- { name: "zafira-listener", value: "wdio-zafira-listener-service$--$zafira-listener" },
195
- { name: "reportportal", value: "wdio-reportportal-service$--$reportportal" },
196
- { name: "docker", value: "wdio-docker-service$--$docker" },
197
- { name: "ui5", value: "wdio-ui5-service$--$ui5" },
198
- { name: "wiremock", value: "wdio-wiremock-service$--$wiremock" },
199
- { name: "ng-apimock", value: "wdio-ng-apimock-service$--$ng-apimock" },
200
- { name: "slack", value: "wdio-slack-service$--$slack" },
201
- { name: "cucumber-viewport-logger", value: "wdio-cucumber-viewport-logger-service$--$cucumber-viewport-logger" },
202
- { name: "intercept", value: "wdio-intercept-service$--$intercept" },
203
- { name: "docker", value: "wdio-docker-service$--$docker" },
204
- { name: "novus-visual-regression", value: "wdio-novus-visual-regression-service$--$novus-visual-regression" },
205
- { name: "rerun", value: "wdio-rerun-service$--$rerun" },
206
- { name: "winappdriver", value: "wdio-winappdriver-service$--$winappdriver" },
207
- { name: "ywinappdriver", value: "wdio-ywinappdriver-service$--$ywinappdriver" },
208
- { name: "performancetotal", value: "wdio-performancetotal-service$--$performancetotal" },
209
- { name: "cleanuptotal", value: "wdio-cleanuptotal-service$--$cleanuptotal" },
210
- { name: "aws-device-farm", value: "wdio-aws-device-farm-service$--$aws-device-farm" },
211
- { name: "ms-teams", value: "wdio-ms-teams-service$--$ms-teams" },
212
- { name: "tesults", value: "wdio-tesults-service$--$tesults" },
213
- { name: "azure-devops", value: "@gmangiapelo/wdio-azure-devops-service$--$azure-devops" },
214
- { name: "google-Chat", value: "wdio-google-chat-service$--$google-chat" },
215
- { name: "qmate-service", value: "@sap_oss/wdio-qmate-service$--$qmate-service" },
216
- { name: "robonut", value: "wdio-robonut-service$--$robonut" },
217
- { name: "qunit", value: "wdio-qunit-service$--$qunit" },
218
- { name: "roku", value: "wdio-roku-service$--$roku" }
219
- ]
220
- };
221
- var SUPPORTED_BROWSER_RUNNER_PRESETS = [
222
- { name: "Lit (https://lit.dev/)", value: "$--$" },
223
- { name: "Vue.js (https://vuejs.org/)", value: "@vitejs/plugin-vue$--$vue" },
224
- { name: "Svelte (https://svelte.dev/)", value: "@sveltejs/vite-plugin-svelte$--$svelte" },
225
- { name: "SolidJS (https://www.solidjs.com/)", value: "vite-plugin-solid$--$solid" },
226
- { name: "StencilJS (https://stenciljs.com/)", value: "$--$stencil" },
227
- { name: "React (https://reactjs.org/)", value: "@vitejs/plugin-react$--$react" },
228
- { name: "Preact (https://preactjs.com/)", value: "@preact/preset-vite$--$preact" },
229
- { name: "Other", value: null }
230
- ];
231
- var TESTING_LIBRARY_PACKAGES = {
232
- react: "@testing-library/react",
233
- preact: "@testing-library/preact",
234
- vue: "@testing-library/vue",
235
- svelte: "@testing-library/svelte",
236
- solid: "solid-testing-library"
237
- };
238
- var BackendChoice = /* @__PURE__ */ ((BackendChoice2) => {
239
- BackendChoice2["Local"] = "On my local machine";
240
- BackendChoice2["Experitest"] = "In the cloud using Experitest";
241
- BackendChoice2["Saucelabs"] = "In the cloud using Sauce Labs";
242
- BackendChoice2["Browserstack"] = "In the cloud using BrowserStack";
243
- BackendChoice2["OtherVendors"] = "In the cloud using Testingbot or LambdaTest or a different service";
244
- BackendChoice2["Grid"] = "I have my own Selenium cloud";
245
- return BackendChoice2;
246
- })(BackendChoice || {});
247
- var ElectronBuildToolChoice = /* @__PURE__ */ ((ElectronBuildToolChoice2) => {
248
- ElectronBuildToolChoice2["ElectronForge"] = "Electron Forge (https://www.electronforge.io/)";
249
- ElectronBuildToolChoice2["ElectronBuilder"] = "electron-builder (https://www.electron.build/)";
250
- ElectronBuildToolChoice2["SomethingElse"] = "Something else";
251
- return ElectronBuildToolChoice2;
252
- })(ElectronBuildToolChoice || {});
253
- var ProtocolOptions = /* @__PURE__ */ ((ProtocolOptions2) => {
254
- ProtocolOptions2["HTTPS"] = "https";
255
- ProtocolOptions2["HTTP"] = "http";
256
- return ProtocolOptions2;
257
- })(ProtocolOptions || {});
258
- var RegionOptions = /* @__PURE__ */ ((RegionOptions2) => {
259
- RegionOptions2["US"] = "us";
260
- RegionOptions2["EU"] = "eu";
261
- return RegionOptions2;
262
- })(RegionOptions || {});
263
- var E2E_ENVIRONMENTS = [
264
- { name: "Web - web applications in the browser", value: "web" },
265
- { name: "Mobile - native, hybrid and mobile web apps, on Android or iOS", value: "mobile" }
266
- ];
267
- var MOBILE_ENVIRONMENTS = [
268
- { name: "Android - native, hybrid and mobile web apps, tested on emulators and real devices\n > using UiAutomator2 (https://www.npmjs.com/package/appium-uiautomator2-driver)", value: "android" },
269
- { name: "iOS - applications on iOS, iPadOS, and tvOS\n > using XCTest (https://appium.github.io/appium-xcuitest-driver)", value: "ios" }
270
- ];
271
- var BROWSER_ENVIRONMENTS = [
272
- { name: "Chrome", value: "chrome", checked: true },
273
- { name: "Firefox", value: "firefox" },
274
- { name: "Safari", value: "safari" },
275
- { name: "Microsoft Edge", value: "MicrosoftEdge" }
276
- ];
277
- function isBrowserRunner(answers) {
278
- return answers.runner === SUPPORTED_PACKAGES.runner[1].value;
279
- }
280
- function usesSerenity(answers) {
281
- return answers.framework.includes("serenity-js");
282
- }
283
- function getTestingPurpose(answers) {
284
- return convertPackageHashToObject(answers.runner).purpose;
285
- }
286
- var isNuxtProject = [
287
- path.join(process.cwd(), "nuxt.config.js"),
288
- path.join(process.cwd(), "nuxt.config.ts"),
289
- path.join(process.cwd(), "nuxt.config.mjs"),
290
- path.join(process.cwd(), "nuxt.config.mts")
291
- ].map((p) => {
292
- try {
293
- fs.accessSync(p);
294
- return true;
295
- } catch {
296
- return false;
297
- }
298
- }).some(Boolean);
299
- function selectDefaultService(serviceNames) {
300
- serviceNames = Array.isArray(serviceNames) ? serviceNames : [serviceNames];
301
- return SUPPORTED_PACKAGES.service.filter(({ name }) => serviceNames.includes(name)).map(({ value }) => value);
302
- }
303
- function prioServiceOrderFor(serviceNamesParam) {
304
- const serviceNames = Array.isArray(serviceNamesParam) ? serviceNamesParam : [serviceNamesParam];
305
- let services = SUPPORTED_PACKAGES.service;
306
- for (const serviceName of serviceNames) {
307
- const index = services.findIndex(({ name }) => name === serviceName);
308
- services = [services[index], ...services.slice(0, index), ...services.slice(index + 1)];
309
- }
310
- return services;
311
- }
312
- var QUESTIONNAIRE = [{
313
- type: "list",
314
- name: "runner",
315
- message: "What type of testing would you like to do?",
316
- choices: SUPPORTED_PACKAGES.runner
317
- }, {
318
- type: "list",
319
- name: "preset",
320
- message: "Which framework do you use for building components?",
321
- choices: SUPPORTED_BROWSER_RUNNER_PRESETS,
322
- // only ask if there are more than 1 runner to pick from
323
- when: (
324
- /* istanbul ignore next */
325
- isBrowserRunner
326
- )
327
- }, {
328
- type: "confirm",
329
- name: "installTestingLibrary",
330
- message: "Do you like to use Testing Library (https://testing-library.com/) as test utility?",
331
- default: true,
332
- // only ask if there are more than 1 runner to pick from
333
- when: (
334
- /* istanbul ignore next */
335
- (answers) => isBrowserRunner(answers) && /**
336
- * Only show if Testing Library has an add-on for framework
337
- */
338
- answers.preset && TESTING_LIBRARY_PACKAGES[convertPackageHashToObject(answers.preset).short]
339
- )
340
- }, {
341
- type: "list",
342
- name: "electronBuildTool",
343
- message: "Which tool are you using to build your Electron app?",
344
- choices: Object.values(ElectronBuildToolChoice),
345
- when: (
346
- /* instanbul ignore next */
347
- (answers) => getTestingPurpose(answers) === "electron"
348
- )
349
- }, {
350
- type: "input",
351
- name: "electronAppBinaryPath",
352
- message: "What is the path to the binary of your built Electron app?",
353
- when: (
354
- /* istanbul ignore next */
355
- (answers) => getTestingPurpose(answers) === "electron" && answers.electronBuildTool === "Something else" /* SomethingElse */
356
- )
357
- }, {
358
- type: "list",
359
- name: "backend",
360
- message: "Where is your automation backend located?",
361
- choices: Object.values(BackendChoice),
362
- when: (
363
- /* instanbul ignore next */
364
- (answers) => getTestingPurpose(answers) === "e2e"
365
- )
366
- }, {
367
- type: "list",
368
- name: "e2eEnvironment",
369
- message: "Which environment you would like to automate?",
370
- choices: E2E_ENVIRONMENTS,
371
- default: "web",
372
- when: (
373
- /* istanbul ignore next */
374
- (answers) => getTestingPurpose(answers) === "e2e"
375
- )
376
- }, {
377
- type: "list",
378
- name: "mobileEnvironment",
379
- message: "Which mobile environment you'd like to automate?",
380
- choices: MOBILE_ENVIRONMENTS,
381
- when: (
382
- /* instanbul ignore next */
383
- (answers) => getTestingPurpose(answers) === "e2e" && answers.e2eEnvironment === "mobile"
384
- )
385
- }, {
386
- type: "checkbox",
387
- name: "browserEnvironment",
388
- message: "With which browser should we start?",
389
- choices: BROWSER_ENVIRONMENTS,
390
- when: (
391
- /* instanbul ignore next */
392
- (answers) => getTestingPurpose(answers) === "e2e" && answers.e2eEnvironment === "web"
393
- )
394
- }, {
395
- type: "input",
396
- name: "hostname",
397
- message: "What is the host address of that cloud service?",
398
- when: (
399
- /* istanbul ignore next */
400
- (answers) => answers.backend && answers.backend.indexOf("different service") > -1
401
- )
402
- }, {
403
- type: "input",
404
- name: "port",
405
- message: "What is the port on which that service is running?",
406
- default: "80",
407
- when: (
408
- /* istanbul ignore next */
409
- (answers) => answers.backend && answers.backend.indexOf("different service") > -1
410
- )
411
- }, {
412
- type: "input",
413
- name: "expEnvAccessKey",
414
- message: "Access key from Experitest Cloud",
415
- default: "EXPERITEST_ACCESS_KEY",
416
- when: (
417
- /* istanbul ignore next */
418
- (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */
419
- )
420
- }, {
421
- type: "input",
422
- name: "expEnvHostname",
423
- message: "Environment variable for cloud url",
424
- default: "example.experitest.com",
425
- when: (
426
- /* istanbul ignore next */
427
- (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */
428
- )
429
- }, {
430
- type: "input",
431
- name: "expEnvPort",
432
- message: "Environment variable for port",
433
- default: "443",
434
- when: (
435
- /* istanbul ignore next */
436
- (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */
437
- )
438
- }, {
439
- type: "list",
440
- name: "expEnvProtocol",
441
- message: "Choose a protocol for environment variable",
442
- default: "https" /* HTTPS */,
443
- choices: Object.values(ProtocolOptions),
444
- when: (
445
- /* istanbul ignore next */
446
- (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */ && answers.expEnvPort !== "80" && answers.expEnvPort !== "443"
447
- )
448
- }, {
449
- type: "input",
450
- name: "env_user",
451
- message: "Environment variable for username",
452
- default: "LT_USERNAME",
453
- when: (
454
- /* istanbul ignore next */
455
- (answers) => answers.backend && answers.backend.indexOf("LambdaTest") > -1 && answers.hostname.indexOf("lambdatest.com") > -1
456
- )
457
- }, {
458
- type: "input",
459
- name: "env_key",
460
- message: "Environment variable for access key",
461
- default: "LT_ACCESS_KEY",
462
- when: (
463
- /* istanbul ignore next */
464
- (answers) => answers.backend && answers.backend.indexOf("LambdaTest") > -1 && answers.hostname.indexOf("lambdatest.com") > -1
465
- )
466
- }, {
467
- type: "input",
468
- name: "env_user",
469
- message: "Environment variable for username",
470
- default: "BROWSERSTACK_USERNAME",
471
- when: (
472
- /* istanbul ignore next */
473
- (answers) => answers.backend === "In the cloud using BrowserStack" /* Browserstack */
474
- )
475
- }, {
476
- type: "input",
477
- name: "env_key",
478
- message: "Environment variable for access key",
479
- default: "BROWSERSTACK_ACCESS_KEY",
480
- when: (
481
- /* istanbul ignore next */
482
- (answers) => answers.backend === "In the cloud using BrowserStack" /* Browserstack */
483
- )
484
- }, {
485
- type: "input",
486
- name: "env_user",
487
- message: "Environment variable for username",
488
- default: "SAUCE_USERNAME",
489
- when: (
490
- /* istanbul ignore next */
491
- (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */
492
- )
493
- }, {
494
- type: "input",
495
- name: "env_key",
496
- message: "Environment variable for access key",
497
- default: "SAUCE_ACCESS_KEY",
498
- when: (
499
- /* istanbul ignore next */
500
- (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */
501
- )
502
- }, {
503
- type: "list",
504
- name: "region",
505
- message: "In which region do you want to run your Sauce Labs tests in?",
506
- choices: Object.values(RegionOptions),
507
- when: (
508
- /* istanbul ignore next */
509
- (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */
510
- )
511
- }, {
512
- type: "confirm",
513
- name: "useSauceConnect",
514
- message: "Are you testing a local application and need Sauce Connect to be set-up?\nRead more on Sauce Connect at: https://docs.saucelabs.com/secure-connections/#sauce-connect-proxy",
515
- default: isNuxtProject,
516
- when: (
517
- /* istanbul ignore next */
518
- (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */ && !isNuxtProject
519
- )
520
- }, {
521
- type: "input",
522
- name: "hostname",
523
- message: "What is the IP or URI to your Selenium standalone or grid server?",
524
- default: "localhost",
525
- when: (
526
- /* istanbul ignore next */
527
- (answers) => answers.backend && answers.backend.toString().indexOf("own Selenium cloud") > -1
528
- )
529
- }, {
530
- type: "input",
531
- name: "port",
532
- message: "What is the port which your Selenium standalone or grid server is running on?",
533
- default: "4444",
534
- when: (
535
- /* istanbul ignore next */
536
- (answers) => answers.backend && answers.backend.toString().indexOf("own Selenium cloud") > -1
537
- )
538
- }, {
539
- type: "input",
540
- name: "path",
541
- message: "What is the path to your browser driver or grid server?",
542
- default: "/",
543
- when: (
544
- /* istanbul ignore next */
545
- (answers) => answers.backend && answers.backend.toString().indexOf("own Selenium cloud") > -1
546
- )
547
- }, {
548
- type: "list",
549
- name: "framework",
550
- message: "Which framework do you want to use?",
551
- choices: (
552
- /* instanbul ignore next */
553
- (answers) => {
554
- if (isBrowserRunner(answers)) {
555
- return SUPPORTED_PACKAGES.framework.slice(0, 1);
556
- }
557
- if (getTestingPurpose(answers) === "electron") {
558
- return SUPPORTED_PACKAGES.framework.filter(
559
- ({ value }) => !value.startsWith("@serenity-js")
560
- );
561
- }
562
- return SUPPORTED_PACKAGES.framework;
563
- }
564
- )
565
- }, {
566
- type: "confirm",
567
- name: "isUsingTypeScript",
568
- message: "Do you want to use Typescript to write tests?",
569
- when: (
570
- /* istanbul ignore next */
571
- (answers) => {
572
- if (answers.preset?.includes("stencil")) {
573
- return false;
574
- }
575
- return true;
576
- }
577
- ),
578
- default: (
579
- /* istanbul ignore next */
580
- (answers) => answers.preset?.includes("stencil") || detectCompiler(answers)
581
- )
582
- }, {
583
- type: "confirm",
584
- name: "generateTestFiles",
585
- message: "Do you want WebdriverIO to autogenerate some test files?",
586
- default: true,
587
- when: (
588
- /* istanbul ignore next */
589
- (answers) => {
590
- if (["vscode", "electron", "macos"].includes(getTestingPurpose(answers)) && answers.framework.includes("cucumber")) {
591
- return false;
592
- }
593
- return true;
594
- }
595
- )
596
- }, {
597
- type: "input",
598
- name: "specs",
599
- message: "What should be the location of your spec files?",
600
- default: (
601
- /* istanbul ignore next */
602
- (answers) => {
603
- const pattern = isBrowserRunner(answers) ? "src/**/*.test" : "test/specs/**/*";
604
- return getDefaultFiles(answers, pattern);
605
- }
606
- ),
607
- when: (
608
- /* istanbul ignore next */
609
- (answers) => answers.generateTestFiles && /(mocha|jasmine)/.test(answers.framework)
610
- )
611
- }, {
612
- type: "input",
613
- name: "specs",
614
- message: "What should be the location of your feature files?",
615
- default: (answers) => getDefaultFiles(answers, "features/**/*.feature"),
616
- when: (
617
- /* istanbul ignore next */
618
- (answers) => answers.generateTestFiles && answers.framework.includes("cucumber")
619
- )
620
- }, {
621
- type: "input",
622
- name: "stepDefinitions",
623
- message: "What should be the location of your step definitions?",
624
- default: (answers) => getDefaultFiles(answers, "features/step-definitions/steps"),
625
- when: (
626
- /* istanbul ignore next */
627
- (answers) => answers.generateTestFiles && answers.framework.includes("cucumber")
628
- )
629
- }, {
630
- type: "confirm",
631
- name: "usePageObjects",
632
- message: "Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)?",
633
- default: true,
634
- when: (
635
- /* istanbul ignore next */
636
- (answers) => answers.generateTestFiles && /**
637
- * page objects aren't common for component testing
638
- */
639
- !isBrowserRunner(answers) && /**
640
- * and also not needed when running VS Code tests since the service comes with
641
- * its own page object implementation, nor when running Electron or MacOS tests
642
- */
643
- !["vscode", "electron", "macos"].includes(getTestingPurpose(answers)) && /**
644
- * Serenity/JS generates Lean Page Objects by default, so there's no need to ask about it
645
- * See https://serenity-js.org/handbook/web-testing/page-objects-pattern/
646
- */
647
- !usesSerenity(answers)
648
- )
649
- }, {
650
- type: "input",
651
- name: "pages",
652
- message: "Where are your page objects located?",
653
- default: (
654
- /* istanbul ignore next */
655
- (answers) => answers.framework.match(/(mocha|jasmine)/) ? getDefaultFiles(answers, "test/pageobjects/**/*") : getDefaultFiles(answers, "features/pageobjects/**/*")
656
- ),
657
- when: (
658
- /* istanbul ignore next */
659
- (answers) => answers.generateTestFiles && answers.usePageObjects
660
- )
661
- }, {
662
- type: "input",
663
- name: "serenityLibPath",
664
- message: "What should be the location of your Serenity/JS Screenplay Pattern library?",
665
- default: (
666
- /* istanbul ignore next */
667
- async (answers) => {
668
- const projectRootDir = await getProjectRoot(answers);
669
- const specsDir = path.resolve(projectRootDir, path.dirname(answers.specs || "").replace(/\*\*$/, ""));
670
- return path.resolve(specsDir, "..", "serenity");
671
- }
672
- ),
673
- when: (
674
- /* istanbul ignore next */
675
- (answers) => answers.generateTestFiles && usesSerenity(answers)
676
- )
677
- }, {
678
- type: "checkbox",
679
- name: "reporters",
680
- message: "Which reporter do you want to use?",
681
- choices: SUPPORTED_PACKAGES.reporter
682
- }, {
683
- type: "checkbox",
684
- name: "plugins",
685
- message: "Do you want to add a plugin to your test setup?",
686
- choices: SUPPORTED_PACKAGES.plugin,
687
- default: []
688
- }, {
689
- type: "confirm",
690
- name: "includeVisualTesting",
691
- message: "Would you like to include Visual Testing to your setup? For more information see https://webdriver.io/docs/visual-testing!",
692
- default: false,
693
- when: (
694
- /* istanbul ignore next */
695
- (answers) => {
696
- return ["e2e", "component"].includes(getTestingPurpose(answers));
697
- }
698
- )
699
- }, {
700
- type: "checkbox",
701
- name: "services",
702
- message: "Do you want to add a service to your test setup?",
703
- choices: (answers) => {
704
- const services = [];
705
- if (answers.backend === "In the cloud using BrowserStack" /* Browserstack */) {
706
- services.push("browserstack");
707
- } else if (answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */) {
708
- services.push("sauce");
709
- }
710
- if (answers.e2eEnvironment === "mobile") {
711
- services.push("appium");
712
- }
713
- if (getTestingPurpose(answers) === "e2e" && isNuxtProject) {
714
- services.push("nuxt");
715
- }
716
- if (getTestingPurpose(answers) === "vscode") {
717
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "vscode")];
718
- } else if (getTestingPurpose(answers) === "electron") {
719
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "electron")];
720
- } else if (getTestingPurpose(answers) === "macos") {
721
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "appium")];
722
- } else if (getTestingPurpose(answers) === "roku") {
723
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "roku")];
724
- }
725
- return prioServiceOrderFor(services);
726
- },
727
- default: (answers) => {
728
- const defaultServices = [];
729
- if (answers.backend === "In the cloud using BrowserStack" /* Browserstack */) {
730
- defaultServices.push("browserstack");
731
- } else if (answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */) {
732
- defaultServices.push("sauce");
733
- }
734
- if (answers.e2eEnvironment === "mobile" || getTestingPurpose(answers) === "macos") {
735
- defaultServices.push("appium");
736
- }
737
- if (getTestingPurpose(answers) === "vscode") {
738
- defaultServices.push("vscode");
739
- } else if (getTestingPurpose(answers) === "electron") {
740
- defaultServices.push("electron");
741
- } else if (getTestingPurpose(answers) === "roku") {
742
- defaultServices.push("roku");
743
- }
744
- if (isNuxtProject) {
745
- defaultServices.push("nuxt");
746
- }
747
- if (answers.includeVisualTesting) {
748
- defaultServices.push("visual");
749
- }
750
- return selectDefaultService(defaultServices);
751
- }
752
- }, {
753
- type: "input",
754
- name: "outputDir",
755
- message: "In which directory should the xunit reports get stored?",
756
- default: "./",
757
- when: (
758
- /* istanbul ignore next */
759
- (answers) => answers.reporters.includes("junit")
760
- )
761
- }, {
762
- type: "input",
763
- name: "outputDir",
764
- message: "In which directory should the json reports get stored?",
765
- default: "./",
766
- when: (
767
- /* istanbul ignore next */
768
- (answers) => answers.reporters.includes("json")
769
- )
770
- }, {
771
- type: "input",
772
- name: "outputDir",
773
- message: "In which directory should the mochawesome json reports get stored?",
774
- default: "./",
775
- when: (
776
- /* istanbul ignore next */
777
- (answers) => answers.reporters.includes("mochawesome")
778
- )
779
- }, {
780
- type: "confirm",
781
- name: "npmInstall",
782
- message: () => `Do you want me to run \`${detectPackageManager()} install\``,
783
- default: true
784
- }];
785
53
  var SUPPORTED_SNAPSHOTSTATE_OPTIONS = ["all", "new", "none"];
786
- var COMMUNITY_PACKAGES_WITH_TS_SUPPORT = [
787
- "wdio-electron-service",
788
- "wdio-vscode-service",
789
- "wdio-nuxt-service",
790
- "wdio-vite-service",
791
- "wdio-gmail-service",
792
- "wdio-roku-service"
793
- ];
794
54
  var TESTRUNNER_DEFAULTS = {
795
55
  /**
796
56
  * Define specs for test execution. You can either specify a glob
@@ -1054,63 +314,8 @@ var WORKER_GROUPLOGS_MESSAGES = {
1054
314
  ***** List of steps of WorkerID=[${cid}] that preceded the error above *****`
1055
315
  };
1056
316
 
1057
- // src/templates/EjsHelpers.ts
1058
- var EjsHelpers = class {
1059
- useTypeScript;
1060
- useEsm;
1061
- constructor(config) {
1062
- this.useTypeScript = config.useTypeScript ?? false;
1063
- this.useEsm = config.useEsm ?? false;
1064
- }
1065
- if(condition, trueValue, falseValue = "") {
1066
- return condition ? trueValue : falseValue;
1067
- }
1068
- ifTs = (trueValue, falseValue = "") => this.if(this.useTypeScript, trueValue, falseValue);
1069
- ifEsm = (trueValue, falseValue = "") => this.if(this.useEsm, trueValue, falseValue);
1070
- param(name, type) {
1071
- return this.useTypeScript ? `${name}: ${type}` : name;
1072
- }
1073
- returns(type) {
1074
- return this.useTypeScript ? `: ${type}` : "";
1075
- }
1076
- import(exports, moduleId) {
1077
- const individualExports = exports.split(",").map((id) => id.trim());
1078
- const imports = this.useTypeScript ? individualExports : individualExports.filter((id) => !id.startsWith("type "));
1079
- if (!imports.length) {
1080
- return "";
1081
- }
1082
- const modulePath = this.modulePathFrom(moduleId);
1083
- return this.useEsm || this.useTypeScript ? `import { ${imports.join(", ")} } from '${modulePath}'` : `const { ${imports.join(", ")} } = require('${modulePath}')`;
1084
- }
1085
- modulePathFrom(moduleId) {
1086
- if (!(moduleId.startsWith(".") && this.useEsm)) {
1087
- return moduleId;
1088
- }
1089
- if (moduleId.endsWith("/") && this.useEsm) {
1090
- return moduleId + "index.js";
1091
- }
1092
- return moduleId + ".js";
1093
- }
1094
- export(keyword, name) {
1095
- if (this.useTypeScript) {
1096
- return `export ${keyword} ${name}`;
1097
- }
1098
- if (this.useEsm) {
1099
- return `export ${keyword} ${name}`;
1100
- }
1101
- if (["class", "function"].includes(keyword)) {
1102
- return `module.exports.${name} = ${keyword} ${name}`;
1103
- }
1104
- return `module.exports.${name}`;
1105
- }
1106
- };
1107
-
1108
317
  // src/utils.ts
1109
318
  var log = logger("@wdio/cli:utils");
1110
- var __dirname = dirname(fileURLToPath(import.meta.url));
1111
- var NPM_COMMAND = /^win/.test(process.platform) ? "npm.cmd" : "npm";
1112
- var VERSION_REGEXP = /(\d+)\.(\d+)\.(\d+)-(alpha|beta|)\.(\d+)\+(.+)/g;
1113
- var TEMPLATE_ROOT_DIR = path2.join(__dirname, "templates", "exampleFiles");
1114
319
  var renderFile = promisify(ejs.renderFile);
1115
320
  var HookError = class extends SevereServiceError {
1116
321
  origin;
@@ -1167,13 +372,13 @@ async function runLauncherHook(hook, ...args) {
1167
372
  }
1168
373
  })).catch(catchFn);
1169
374
  }
1170
- async function runOnCompleteHook(onCompleteHook, config, capabilities, exitCode, results) {
375
+ async function runOnCompleteHook(onCompleteHook, config3, capabilities, exitCode, results) {
1171
376
  if (typeof onCompleteHook === "function") {
1172
377
  onCompleteHook = [onCompleteHook];
1173
378
  }
1174
379
  return Promise.all(onCompleteHook.map(async (hook) => {
1175
380
  try {
1176
- await hook(exitCode, config, capabilities, results);
381
+ await hook(exitCode, config3, capabilities, results);
1177
382
  return 0;
1178
383
  } catch (err) {
1179
384
  log.error(`Error in onCompleteHook: ${err.stack}`);
@@ -1191,96 +396,6 @@ function getRunnerName(caps = {}) {
1191
396
  }
1192
397
  return runner;
1193
398
  }
1194
- function buildNewConfigArray(str, type, change) {
1195
- const newStr = str.split(`${type}s: `)[1].replace(/'/g, "");
1196
- const newArray = newStr.match(/(\w*)/gmi)?.filter((e) => !!e).concat([change]) || [];
1197
- return str.replace("// ", "").replace(
1198
- new RegExp(`(${type}s: )((.*\\s*)*)`),
1199
- `$1[${newArray.map((e) => `'${e}'`)}]`
1200
- );
1201
- }
1202
- function buildNewConfigString(str, type, change) {
1203
- return str.replace(new RegExp(`(${type}: )('\\w*')`), `$1'${change}'`);
1204
- }
1205
- function findInConfig(config, type) {
1206
- let regexStr = `[\\/\\/]*[\\s]*${type}s: [\\s]*\\[([\\s]*['|"]\\w*['|"],*)*[\\s]*\\]`;
1207
- if (type === "framework") {
1208
- regexStr = `[\\/\\/]*[\\s]*${type}: ([\\s]*['|"]\\w*['|"])`;
1209
- }
1210
- const regex = new RegExp(regexStr, "gmi");
1211
- return config.match(regex);
1212
- }
1213
- function replaceConfig(config, type, name) {
1214
- if (type === "framework") {
1215
- return buildNewConfigString(config, type, name);
1216
- }
1217
- const match = findInConfig(config, type);
1218
- if (!match || match.length === 0) {
1219
- return;
1220
- }
1221
- const text = match.pop() || "";
1222
- return config.replace(text, buildNewConfigArray(text, type, name));
1223
- }
1224
- function addServiceDeps(names, packages, update = false) {
1225
- if (names.some(({ short }) => short === "appium")) {
1226
- const result = execSync("appium --version || echo APPIUM_MISSING", { stdio: "pipe" }).toString().trim();
1227
- if (result === "APPIUM_MISSING") {
1228
- packages.push("appium");
1229
- } else if (update) {
1230
- console.log(
1231
- "\n=======",
1232
- "\nUsing globally installed appium",
1233
- result,
1234
- "\nPlease add the following to your wdio.conf.js:",
1235
- "\nappium: { command: 'appium' }",
1236
- "\n=======\n"
1237
- );
1238
- }
1239
- }
1240
- }
1241
- function convertPackageHashToObject(pkg2, hash = "$--$") {
1242
- const [p, short, purpose] = pkg2.split(hash);
1243
- return { package: p, short, purpose };
1244
- }
1245
- function getSerenityPackages(answers) {
1246
- const framework = convertPackageHashToObject(answers.framework);
1247
- if (framework.package !== "@serenity-js/webdriverio") {
1248
- return [];
1249
- }
1250
- const packages = {
1251
- cucumber: [
1252
- "@cucumber/cucumber",
1253
- "@serenity-js/cucumber"
1254
- ],
1255
- mocha: [
1256
- "@serenity-js/mocha",
1257
- "mocha"
1258
- ],
1259
- jasmine: [
1260
- "@serenity-js/jasmine",
1261
- "jasmine"
1262
- ],
1263
- common: [
1264
- "@serenity-js/assertions",
1265
- "@serenity-js/console-reporter",
1266
- "@serenity-js/core",
1267
- "@serenity-js/rest",
1268
- "@serenity-js/serenity-bdd",
1269
- "@serenity-js/web",
1270
- "npm-failsafe",
1271
- "rimraf"
1272
- ]
1273
- };
1274
- if (answers.isUsingTypeScript) {
1275
- packages.mocha.push("@types/mocha");
1276
- packages.jasmine.push("@types/jasmine");
1277
- packages.common.push("@types/node");
1278
- }
1279
- return [
1280
- ...packages[framework.purpose],
1281
- ...packages.common
1282
- ].filter(Boolean).sort();
1283
- }
1284
399
  async function getCapabilities(arg) {
1285
400
  const optionalCapabilites = {
1286
401
  platformVersion: arg.platformVersion,
@@ -1300,16 +415,16 @@ async function getCapabilities(arg) {
1300
415
  } else if (/ios/.test(arg.option)) {
1301
416
  return { capabilities: { browserName: "Safari", ...IOS_CONFIG, ...optionalCapabilites } };
1302
417
  } else if (/(js|ts)$/.test(arg.option)) {
1303
- const config = new ConfigParser(arg.option);
418
+ const config3 = new ConfigParser(arg.option);
1304
419
  try {
1305
- await config.initialize();
420
+ await config3.initialize();
1306
421
  } catch (e) {
1307
422
  throw Error(e.code === "MODULE_NOT_FOUND" ? `Config File not found: ${arg.option}` : `Could not parse ${arg.option}, failed with error: ${e.message}`);
1308
423
  }
1309
424
  if (typeof arg.capabilities === "undefined") {
1310
425
  throw Error("Please provide index/named property of capability to use from the capabilities array/object in wdio config file");
1311
426
  }
1312
- let requiredCaps = config.getCapabilities();
427
+ let requiredCaps = config3.getCapabilities();
1313
428
  requiredCaps = // multi capabilities
1314
429
  requiredCaps[parseInt(arg.capabilities, 10)] || // multiremote
1315
430
  requiredCaps[arg.capabilities];
@@ -1321,465 +436,6 @@ async function getCapabilities(arg) {
1321
436
  }
1322
437
  return { capabilities: { browserName: arg.option } };
1323
438
  }
1324
- async function detectCompiler(answers) {
1325
- if (answers.createPackageJSON) {
1326
- return false;
1327
- }
1328
- const root = await getProjectRoot(answers);
1329
- const hasRootTSConfig = await fs2.access(path2.resolve(root, "tsconfig.json")).then(() => true, () => false);
1330
- return hasRootTSConfig;
1331
- }
1332
- async function generateTestFiles(answers) {
1333
- if (answers.serenityAdapter) {
1334
- return generateSerenityExamples(answers);
1335
- }
1336
- if (answers.runner === "local") {
1337
- return generateLocalRunnerTestFiles(answers);
1338
- }
1339
- return generateBrowserRunnerTestFiles(answers);
1340
- }
1341
- var TSX_BASED_FRAMEWORKS = ["react", "preact", "solid", "stencil"];
1342
- async function generateBrowserRunnerTestFiles(answers) {
1343
- const isUsingFramework = typeof answers.preset === "string";
1344
- const preset = getPreset(answers);
1345
- const tplRootDir = path2.join(TEMPLATE_ROOT_DIR, "browser");
1346
- await fs2.mkdir(answers.destSpecRootPath, { recursive: true });
1347
- if (isUsingFramework) {
1348
- const renderedCss = await renderFile(path2.join(tplRootDir, "Component.css.ejs"), { answers });
1349
- await fs2.writeFile(path2.join(answers.destSpecRootPath, "Component.css"), renderedCss);
1350
- }
1351
- const testExt = `${answers.isUsingTypeScript ? "ts" : "js"}${TSX_BASED_FRAMEWORKS.includes(preset) ? "x" : ""}`;
1352
- const fileExt = ["svelte", "vue"].includes(preset) ? preset : testExt;
1353
- if (preset) {
1354
- const componentOutFileName = `Component.${fileExt}`;
1355
- const renderedComponent = await renderFile(path2.join(tplRootDir, `Component.${preset}.ejs`), { answers });
1356
- await fs2.writeFile(path2.join(answers.destSpecRootPath, componentOutFileName), renderedComponent);
1357
- }
1358
- const componentFileName = preset ? `Component.${preset}.test.ejs` : "standalone.test.ejs";
1359
- const renderedTest = await renderFile(path2.join(tplRootDir, componentFileName), { answers });
1360
- await fs2.writeFile(path2.join(answers.destSpecRootPath, `Component.test.${testExt}`), renderedTest);
1361
- }
1362
- async function generateLocalRunnerTestFiles(answers) {
1363
- const testFiles = answers.framework === "cucumber" ? [path2.join(TEMPLATE_ROOT_DIR, "cucumber")] : [path2.join(TEMPLATE_ROOT_DIR, "mochaJasmine")];
1364
- if (answers.usePageObjects) {
1365
- testFiles.push(path2.join(TEMPLATE_ROOT_DIR, "pageobjects"));
1366
- }
1367
- const files = (await Promise.all(testFiles.map((dirPath) => readDir(
1368
- dirPath,
1369
- [(file, stats) => !stats.isDirectory() && !(file.endsWith(".ejs") || file.endsWith(".feature"))]
1370
- )))).reduce((cur, acc) => [...acc, ...cur], []);
1371
- await Promise.all(files.map(async (file) => {
1372
- const renderedTpl = await renderFile(file, { answers });
1373
- const isJSX = answers.preset && TSX_BASED_FRAMEWORKS.includes(answers.preset);
1374
- const fileEnding = (answers.isUsingTypeScript ? ".ts" : ".js") + (isJSX ? "x" : "");
1375
- const destPath = (file.endsWith("page.js.ejs") ? path2.join(answers.destPageObjectRootPath, path2.basename(file)) : file.includes("step_definition") ? path2.join(answers.destStepRootPath, path2.basename(file)) : path2.join(answers.destSpecRootPath, path2.basename(file))).replace(/\.ejs$/, "").replace(/\.js$/, fileEnding);
1376
- await fs2.mkdir(path2.dirname(destPath), { recursive: true });
1377
- await fs2.writeFile(destPath, renderedTpl);
1378
- }));
1379
- }
1380
- async function generateSerenityExamples(answers) {
1381
- const templateDirectories = Object.entries({
1382
- [answers.projectRootDir]: path2.join(TEMPLATE_ROOT_DIR, "serenity-js", "common", "config"),
1383
- [answers.destSpecRootPath]: path2.join(TEMPLATE_ROOT_DIR, "serenity-js", answers.serenityAdapter),
1384
- [answers.destSerenityLibRootPath]: path2.join(TEMPLATE_ROOT_DIR, "serenity-js", "common", "serenity")
1385
- });
1386
- await Promise.all(templateDirectories.map(async ([destinationRootDir, templateRootDir]) => {
1387
- const pathsToTemplates = await readDir(templateRootDir);
1388
- await Promise.all(pathsToTemplates.map(async (pathToTemplate) => {
1389
- const extension = answers.isUsingTypeScript ? ".ts" : ".js";
1390
- const destination = path2.join(destinationRootDir, path2.relative(templateRootDir, pathToTemplate)).replace(/\.ejs$/, "").replace(/\.ts$/, extension);
1391
- const contents = await renderFile(
1392
- pathToTemplate,
1393
- { answers, _: new EjsHelpers({ useEsm: answers.esmSupport, useTypeScript: answers.isUsingTypeScript }) }
1394
- );
1395
- await fs2.mkdir(path2.dirname(destination), { recursive: true });
1396
- await fs2.writeFile(destination, contents);
1397
- }));
1398
- }));
1399
- }
1400
- async function getAnswers(yes) {
1401
- if (yes) {
1402
- const ignoredQuestions = ["e2eEnvironment"];
1403
- const filterdQuestionaire = QUESTIONNAIRE.filter((question) => !ignoredQuestions.includes(question.name));
1404
- const answers2 = {};
1405
- for (const question of filterdQuestionaire) {
1406
- if (question.when && !question.when(answers2)) {
1407
- continue;
1408
- }
1409
- Object.assign(answers2, {
1410
- [question.name]: typeof question.default !== "undefined" ? typeof question.default === "function" ? await question.default(answers2) : question.default : question.choices && question.choices.length ? typeof question.choices === "function" ? question.choices(answers2)[0].value ? question.choices(answers2)[0].value : question.choices(answers2)[0] : question.choices[0].value ? question.type === "checkbox" ? [question.choices[0].value] : question.choices[0].value : question.choices[0] : {}
1411
- });
1412
- }
1413
- answers2.isUsingTypeScript = await answers2.isUsingTypeScript;
1414
- answers2.specs = await answers2.specs;
1415
- answers2.pages = await answers2.pages;
1416
- return answers2;
1417
- }
1418
- const projectProps = await getProjectProps(process.cwd());
1419
- const isProjectExisting = Boolean(projectProps);
1420
- const nameInPackageJsonIsNotCreateWdioDefault = projectProps?.packageJson?.name !== "my-new-project";
1421
- const projectName = projectProps?.packageJson?.name ? ` named "${projectProps.packageJson.name}"` : "";
1422
- const projectRootQuestions = [
1423
- {
1424
- type: "confirm",
1425
- name: "createPackageJSON",
1426
- default: true,
1427
- message: `Couldn't find a package.json in "${process.cwd()}" or any of the parent directories, do you want to create one?`,
1428
- when: !isProjectExisting
1429
- },
1430
- {
1431
- type: "confirm",
1432
- name: "projectRootCorrect",
1433
- default: true,
1434
- message: `A project${projectName} was detected at "${projectProps?.path}", correct?`,
1435
- when: isProjectExisting && nameInPackageJsonIsNotCreateWdioDefault
1436
- },
1437
- {
1438
- type: "input",
1439
- name: "projectRoot",
1440
- message: "What is the project root for your test project?",
1441
- default: projectProps?.path,
1442
- // only ask if there are more than 1 runner to pick from
1443
- when: (
1444
- /* istanbul ignore next */
1445
- (answers2) => isProjectExisting && nameInPackageJsonIsNotCreateWdioDefault && !answers2.projectRootCorrect
1446
- )
1447
- }
1448
- ];
1449
- const answers = await inquirer.prompt(projectRootQuestions);
1450
- if (answers.createPackageJSON) {
1451
- answers.projectRoot = process.cwd();
1452
- }
1453
- return inquirer.prompt(QUESTIONNAIRE, answers);
1454
- }
1455
- function generatePathfromAnswer(answers, projectRootDir) {
1456
- return path2.resolve(
1457
- projectRootDir,
1458
- path2.dirname(answers) === "." ? path2.resolve(answers) : path2.dirname(answers)
1459
- );
1460
- }
1461
- function getPathForFileGeneration(answers, projectRootDir) {
1462
- const specAnswer = answers.specs || "";
1463
- const stepDefinitionAnswer = answers.stepDefinitions || "";
1464
- const pageObjectAnswer = answers.pages || "";
1465
- const destSpecRootPath = generatePathfromAnswer(specAnswer, projectRootDir).replace(/\*\*$/, "");
1466
- const destStepRootPath = generatePathfromAnswer(stepDefinitionAnswer, projectRootDir);
1467
- const destPageObjectRootPath = answers.usePageObjects ? generatePathfromAnswer(pageObjectAnswer, projectRootDir).replace(/\*\*$/, "") : "";
1468
- const destSerenityLibRootPath = usesSerenity(answers) ? path2.resolve(projectRootDir, answers.serenityLibPath || "serenity") : "";
1469
- const relativePath = answers.generateTestFiles && answers.usePageObjects ? !(convertPackageHashToObject(answers.framework).short === "cucumber") ? path2.relative(destSpecRootPath, destPageObjectRootPath) : path2.relative(destStepRootPath, destPageObjectRootPath) : "";
1470
- return {
1471
- destSpecRootPath,
1472
- destStepRootPath,
1473
- destPageObjectRootPath,
1474
- destSerenityLibRootPath,
1475
- relativePath: relativePath.replaceAll(path2.sep, "/")
1476
- };
1477
- }
1478
- async function getDefaultFiles(answers, pattern) {
1479
- const rootdir = await getProjectRoot(answers);
1480
- const presetPackage = convertPackageHashToObject(answers.preset || "");
1481
- const isJSX = TSX_BASED_FRAMEWORKS.includes(presetPackage.short || "");
1482
- const val = pattern.endsWith(".feature") ? path2.join(rootdir, pattern) : answers?.isUsingTypeScript ? `${path2.join(rootdir, pattern)}.ts${isJSX ? "x" : ""}` : `${path2.join(rootdir, pattern)}.js${isJSX ? "x" : ""}`;
1483
- return val;
1484
- }
1485
- function specifyVersionIfNeeded(packagesToInstall, version, npmTag) {
1486
- const { value } = version.matchAll(VERSION_REGEXP).next();
1487
- const [major, minor, patch, tagName, build] = (value || []).slice(1, -1);
1488
- return packagesToInstall.map((p) => {
1489
- if (p.startsWith("@wdio") && p !== "@wdio/visual-service" || ["webdriver", "webdriverio"].includes(p)) {
1490
- const tag = major && npmTag === "latest" ? `^${major}.${minor}.${patch}-${tagName}.${build}` : npmTag;
1491
- return `${p}@${tag}`;
1492
- }
1493
- return p;
1494
- });
1495
- }
1496
- async function getProjectProps(cwd = process.cwd()) {
1497
- try {
1498
- const { packageJson, path: packageJsonPath } = await readPackageUp({ cwd }) || {};
1499
- if (!packageJson || !packageJsonPath) {
1500
- return void 0;
1501
- }
1502
- return {
1503
- esmSupported: packageJson.type === "module" || typeof packageJson.module === "string",
1504
- packageJson,
1505
- path: path2.dirname(packageJsonPath)
1506
- };
1507
- } catch {
1508
- return void 0;
1509
- }
1510
- }
1511
- function runProgram(command5, args, options) {
1512
- const child = spawn(command5, args, { stdio: "inherit", ...options });
1513
- return new Promise((resolve3, reject) => {
1514
- let error;
1515
- child.on("error", (e) => error = e);
1516
- child.on("close", (code) => {
1517
- if (code !== 0) {
1518
- return reject(new Error(
1519
- error && error.message || `Error calling: ${command5} ${args.join(" ")}`
1520
- ));
1521
- }
1522
- resolve3();
1523
- });
1524
- });
1525
- }
1526
- async function createPackageJSON(parsedAnswers) {
1527
- const packageJsonExists = await fs2.access(path2.resolve(process.cwd(), "package.json")).then(() => true, () => false);
1528
- if (packageJsonExists) {
1529
- return;
1530
- }
1531
- if (parsedAnswers.createPackageJSON === false) {
1532
- if (!packageJsonExists) {
1533
- console.log(`No WebdriverIO configuration found in "${parsedAnswers.wdioConfigPath}"`);
1534
- return !process.env.WDIO_UNIT_TESTS && process.exit(0);
1535
- }
1536
- return;
1537
- }
1538
- if (parsedAnswers.createPackageJSON) {
1539
- console.log(`Creating a ${chalk.bold("package.json")} for the directory...`);
1540
- await fs2.writeFile(path2.resolve(process.cwd(), "package.json"), JSON.stringify({
1541
- name: "webdriverio-tests",
1542
- version: "0.0.0",
1543
- private: true,
1544
- license: "ISC",
1545
- type: "module",
1546
- dependencies: {},
1547
- devDependencies: {}
1548
- }, null, 2));
1549
- console.log(chalk.green(chalk.bold("\u2714 Success!\n")));
1550
- }
1551
- }
1552
- var SEP = "\n- ";
1553
- async function npmInstall(parsedAnswers, npmTag) {
1554
- const servicePackages = parsedAnswers.rawAnswers.services.map((service) => convertPackageHashToObject(service));
1555
- const presetPackage = convertPackageHashToObject(parsedAnswers.rawAnswers.preset || "");
1556
- if (parsedAnswers.installTestingLibrary && TESTING_LIBRARY_PACKAGES[presetPackage.short]) {
1557
- parsedAnswers.packagesToInstall.push(
1558
- TESTING_LIBRARY_PACKAGES[presetPackage.short],
1559
- "@testing-library/jest-dom"
1560
- );
1561
- }
1562
- if (presetPackage.short === "solid") {
1563
- parsedAnswers.packagesToInstall.push("solid-js");
1564
- }
1565
- if (parsedAnswers.includeVisualTesting) {
1566
- parsedAnswers.packagesToInstall.push("@wdio/visual-service");
1567
- }
1568
- const preset = getPreset(parsedAnswers);
1569
- if (preset === "lit") {
1570
- parsedAnswers.packagesToInstall.push("lit");
1571
- }
1572
- if (preset === "stencil") {
1573
- parsedAnswers.packagesToInstall.push("@stencil/core");
1574
- }
1575
- if (presetPackage.short === "react") {
1576
- parsedAnswers.packagesToInstall.push("react");
1577
- if (!parsedAnswers.installTestingLibrary) {
1578
- parsedAnswers.packagesToInstall.push("react-dom");
1579
- }
1580
- }
1581
- if (parsedAnswers.framework === "jasmine" && parsedAnswers.isUsingTypeScript) {
1582
- parsedAnswers.packagesToInstall.push("@types/jasmine");
1583
- }
1584
- if (parsedAnswers.purpose === "macos") {
1585
- parsedAnswers.packagesToInstall.push("appium-mac2-driver");
1586
- }
1587
- if (parsedAnswers.mobileEnvironment === "android") {
1588
- parsedAnswers.packagesToInstall.push("appium-uiautomator2-driver");
1589
- }
1590
- if (parsedAnswers.mobileEnvironment === "ios") {
1591
- parsedAnswers.packagesToInstall.push("appium-xcuitest-driver");
1592
- }
1593
- addServiceDeps(servicePackages, parsedAnswers.packagesToInstall);
1594
- parsedAnswers.packagesToInstall = specifyVersionIfNeeded(parsedAnswers.packagesToInstall, pkg.version, npmTag);
1595
- const cwd = await getProjectRoot(parsedAnswers);
1596
- const pm = detectPackageManager();
1597
- if (parsedAnswers.npmInstall) {
1598
- console.log(`Installing packages using ${pm}:${SEP}${parsedAnswers.packagesToInstall.join(SEP)}`);
1599
- const success = await installPackages(cwd, parsedAnswers.packagesToInstall, true);
1600
- if (success) {
1601
- console.log(chalk.green(chalk.bold("\u2714 Success!\n")));
1602
- }
1603
- } else {
1604
- const installationCommand = getInstallCommand(pm, parsedAnswers.packagesToInstall, true);
1605
- console.log(util.format(DEPENDENCIES_INSTALLATION_MESSAGE, installationCommand));
1606
- }
1607
- }
1608
- function detectPackageManager() {
1609
- if (!process.env.npm_config_user_agent) {
1610
- return "npm";
1611
- }
1612
- const detectedPM = process.env.npm_config_user_agent.split("/")[0].toLowerCase();
1613
- const matchedPM = PMs.find((pm) => pm.toLowerCase() === detectedPM);
1614
- return matchedPM || "npm";
1615
- }
1616
- async function setupTypeScript(parsedAnswers) {
1617
- if (!parsedAnswers.isUsingTypeScript) {
1618
- return;
1619
- }
1620
- if (parsedAnswers.hasRootTSConfig) {
1621
- return;
1622
- }
1623
- console.log("Setting up TypeScript...");
1624
- const frameworkPackage = convertPackageHashToObject(parsedAnswers.rawAnswers.framework);
1625
- const servicePackages = parsedAnswers.rawAnswers.services.map((service) => convertPackageHashToObject(service));
1626
- const serenityTypes = parsedAnswers.serenityAdapter === "jasmine" ? ["jasmine"] : [];
1627
- const types = [
1628
- "node",
1629
- ...parsedAnswers.framework === "jasmine" ? ["jasmine"] : [],
1630
- "@wdio/globals/types",
1631
- ...parsedAnswers.framework === "jasmine" ? ["expect-webdriverio/jasmine"] : ["expect-webdriverio"],
1632
- ...parsedAnswers.serenityAdapter ? serenityTypes : [frameworkPackage.package],
1633
- ...parsedAnswers.runner === "browser" ? ["@wdio/browser-runner"] : [],
1634
- ...servicePackages.filter((service) => (
1635
- /**
1636
- * given that we know that all "official" services have
1637
- * typescript support we only include them
1638
- */
1639
- service.package.startsWith("@wdio") || /**
1640
- * also include community maintained packages with known
1641
- * support for TypeScript
1642
- */
1643
- COMMUNITY_PACKAGES_WITH_TS_SUPPORT.includes(service.package)
1644
- )).map((service) => service.package)
1645
- ];
1646
- const preset = getPreset(parsedAnswers);
1647
- const config = {
1648
- compilerOptions: {
1649
- // compiler
1650
- moduleResolution: "node",
1651
- module: !parsedAnswers.esmSupport ? "commonjs" : "ESNext",
1652
- target: "es2022",
1653
- lib: ["es2022", "dom"],
1654
- types,
1655
- skipLibCheck: true,
1656
- // bundler
1657
- noEmit: true,
1658
- allowImportingTsExtensions: true,
1659
- resolveJsonModule: true,
1660
- isolatedModules: true,
1661
- // linting
1662
- strict: true,
1663
- noUnusedLocals: true,
1664
- noUnusedParameters: true,
1665
- noFallthroughCasesInSwitch: true,
1666
- ...Object.assign(
1667
- preset === "lit" ? {
1668
- experimentalDecorators: true,
1669
- useDefineForClassFields: false
1670
- } : {},
1671
- preset === "react" ? {
1672
- jsx: "react-jsx"
1673
- } : {},
1674
- preset === "preact" ? {
1675
- jsx: "react-jsx",
1676
- jsxImportSource: "preact"
1677
- } : {},
1678
- preset === "solid" ? {
1679
- jsx: "preserve",
1680
- jsxImportSource: "solid-js"
1681
- } : {},
1682
- preset === "stencil" ? {
1683
- experimentalDecorators: true,
1684
- jsx: "react",
1685
- jsxFactory: "h",
1686
- jsxFragmentFactory: "Fragment"
1687
- } : {}
1688
- )
1689
- },
1690
- include: preset === "svelte" ? ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] : preset === "vue" ? ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] : ["test", "wdio.conf.ts"]
1691
- };
1692
- if (parsedAnswers.framework === "cucumber") {
1693
- config.include.push("features");
1694
- }
1695
- await fs2.mkdir(path2.dirname(parsedAnswers.tsConfigFilePath), { recursive: true });
1696
- await fs2.writeFile(
1697
- parsedAnswers.tsConfigFilePath,
1698
- JSON.stringify(config, null, 4)
1699
- );
1700
- console.log(chalk.green(chalk.bold("\u2714 Success!\n")));
1701
- }
1702
- function getPreset(parsedAnswers) {
1703
- const isUsingFramework = typeof parsedAnswers.preset === "string";
1704
- return isUsingFramework ? parsedAnswers.preset || "lit" : "";
1705
- }
1706
- async function createWDIOConfig(parsedAnswers) {
1707
- try {
1708
- console.log("Creating a WebdriverIO config file...");
1709
- const tplPath = path2.resolve(__dirname, "templates", "wdio.conf.tpl.ejs");
1710
- const renderedTpl = await renderFile(tplPath, {
1711
- answers: parsedAnswers,
1712
- _: new EjsHelpers({ useEsm: parsedAnswers.esmSupport, useTypeScript: parsedAnswers.isUsingTypeScript })
1713
- });
1714
- await fs2.writeFile(parsedAnswers.wdioConfigPath, renderedTpl);
1715
- console.log(chalk.green(chalk.bold("\u2714 Success!\n")));
1716
- if (parsedAnswers.generateTestFiles) {
1717
- console.log("Autogenerating test files...");
1718
- await generateTestFiles(parsedAnswers);
1719
- console.log(chalk.green(chalk.bold("\u2714 Success!\n")));
1720
- }
1721
- } catch (err) {
1722
- throw new Error(`\u26A0\uFE0F Couldn't write config file: ${err.stack}`);
1723
- }
1724
- }
1725
- async function getProjectRoot(parsedAnswers) {
1726
- if (parsedAnswers?.createPackageJSON && parsedAnswers.projectRoot) {
1727
- return parsedAnswers.projectRoot;
1728
- }
1729
- const root = (await getProjectProps())?.path;
1730
- if (!root) {
1731
- throw new Error("Could not find project root directory with a package.json");
1732
- }
1733
- return !parsedAnswers || parsedAnswers.projectRootCorrect ? root : parsedAnswers.projectRoot || process.cwd();
1734
- }
1735
- async function createWDIOScript(parsedAnswers) {
1736
- const rootDir = await getProjectRoot(parsedAnswers);
1737
- const pathToWdioConfig = `./${path2.join(".", parsedAnswers.wdioConfigPath.replace(rootDir, ""))}`;
1738
- const wdioScripts = {
1739
- "wdio": `wdio run ${pathToWdioConfig}`
1740
- };
1741
- const serenityScripts = {
1742
- "serenity": "failsafe serenity:clean wdio serenity:report",
1743
- "serenity:clean": "rimraf target",
1744
- "wdio": `wdio run ${pathToWdioConfig}`,
1745
- "serenity:report": "serenity-bdd run"
1746
- };
1747
- const scripts = parsedAnswers.serenityAdapter ? serenityScripts : wdioScripts;
1748
- for (const [script, command5] of Object.entries(scripts)) {
1749
- const args = ["pkg", "set", `scripts.${script}=${command5}`];
1750
- try {
1751
- console.log(`Adding ${chalk.bold(`"${script}"`)} script to package.json`);
1752
- await runProgram(NPM_COMMAND, args, { cwd: parsedAnswers.projectRootDir });
1753
- } catch (err) {
1754
- const [preArgs, scriptPath] = args.join(" ").split("=");
1755
- console.error(
1756
- `\u26A0\uFE0F Couldn't add script to package.json: "${err.message}", you can add it manually by running:
1757
-
1758
- ${NPM_COMMAND} ${preArgs}="${scriptPath}"`
1759
- );
1760
- return false;
1761
- }
1762
- }
1763
- console.log(chalk.green(chalk.bold("\u2714 Success!")));
1764
- return true;
1765
- }
1766
- async function runAppiumInstaller(parsedAnswers) {
1767
- if (parsedAnswers.e2eEnvironment !== "mobile") {
1768
- return;
1769
- }
1770
- const answer = await inquirer.prompt({
1771
- name: "continueWithAppiumSetup",
1772
- message: "Continue with Appium setup using appium-installer (https://github.com/AppiumTestDistribution/appium-installer)?",
1773
- type: "confirm",
1774
- default: true
1775
- });
1776
- if (!answer.continueWithAppiumSetup) {
1777
- return console.log(
1778
- "Ok! You can learn more about setting up mobile environments in the Appium docs at https://appium.io/docs/en/latest/quickstart/"
1779
- );
1780
- }
1781
- return $({ stdio: "inherit" })`npx appium-installer`;
1782
- }
1783
439
  var cucumberTypes = {
1784
440
  paths: "array",
1785
441
  backtrace: "boolean",
@@ -1936,28 +592,28 @@ var WDIOCLInterface = class extends EventEmitter {
1936
592
  }
1937
593
  onStart() {
1938
594
  const shardNote = this.#hasShard() ? ` (Shard ${this._config.shard.current} of ${this._config.shard.total})` : "";
1939
- this.log(chalk2.bold(`
1940
- Execution of ${chalk2.blue(this.totalWorkerCnt)} workers${shardNote} started at`), this._start.toISOString());
595
+ this.log(chalk.bold(`
596
+ Execution of ${chalk.blue(this.totalWorkerCnt)} workers${shardNote} started at`), this._start.toISOString());
1941
597
  if (this._inDebugMode) {
1942
- this.log(chalk2.bgYellow(chalk2.black("DEBUG mode enabled!")));
598
+ this.log(chalk.bgYellow(chalk.black("DEBUG mode enabled!")));
1943
599
  }
1944
600
  if (this._isWatchMode) {
1945
- this.log(chalk2.bgYellow(chalk2.black("WATCH mode enabled!")));
601
+ this.log(chalk.bgYellow(chalk.black("WATCH mode enabled!")));
1946
602
  }
1947
603
  this.log("");
1948
604
  }
1949
605
  onSpecRunning(rid) {
1950
- this.onJobComplete(rid, this._jobs.get(rid), 0, chalk2.bold(chalk2.cyan("RUNNING")));
606
+ this.onJobComplete(rid, this._jobs.get(rid), 0, chalk.bold(chalk.cyan("RUNNING")));
1951
607
  }
1952
608
  onSpecRetry(rid, job, retries = 0) {
1953
609
  const delayMsg = this._specFileRetriesDelay > 0 ? ` after ${this._specFileRetriesDelay}s` : "";
1954
- this.onJobComplete(rid, job, retries, chalk2.bold(chalk2.yellow("RETRYING") + delayMsg));
610
+ this.onJobComplete(rid, job, retries, chalk.bold(chalk.yellow("RETRYING") + delayMsg));
1955
611
  }
1956
612
  onSpecPass(rid, job, retries = 0) {
1957
- this.onJobComplete(rid, job, retries, chalk2.bold(chalk2.green("PASSED")));
613
+ this.onJobComplete(rid, job, retries, chalk.bold(chalk.green("PASSED")));
1958
614
  }
1959
615
  onSpecFailure(rid, job, retries = 0) {
1960
- this.onJobComplete(rid, job, retries, chalk2.bold(chalk2.red("FAILED")));
616
+ this.onJobComplete(rid, job, retries, chalk.bold(chalk.red("FAILED")));
1961
617
  }
1962
618
  onSpecSkip(rid, job) {
1963
619
  this.onJobComplete(rid, job, 0, "SKIPPED", log2.info);
@@ -1978,8 +634,8 @@ Execution of ${chalk2.blue(this.totalWorkerCnt)} workers${shardNote} started at`
1978
634
  message: payload.error?.message || (typeof payload.error === "string" ? payload.error : "Unknown error."),
1979
635
  stack: payload.error?.stack
1980
636
  };
1981
- return this.log(`[${payload.cid}]`, `${chalk2.red(error.type)} in "${payload.fullTitle}"
1982
- ${chalk2.red(error.stack || error.message)}`);
637
+ return this.log(`[${payload.cid}]`, `${chalk.red(error.type)} in "${payload.fullTitle}"
638
+ ${chalk.red(error.stack || error.message)}`);
1983
639
  }
1984
640
  getFilenames(specs = []) {
1985
641
  if (specs.length > 0) {
@@ -2033,10 +689,10 @@ ${chalk2.red(error.stack || error.message)}`);
2033
689
  }
2034
690
  logHookError(error) {
2035
691
  if (error instanceof HookError) {
2036
- return this.log(`${chalk2.red(error.name)} in "${error.origin}"
2037
- ${chalk2.red(error.stack || error.message)}`);
692
+ return this.log(`${chalk.red(error.name)} in "${error.origin}"
693
+ ${chalk.red(error.stack || error.message)}`);
2038
694
  }
2039
- return this.log(`${chalk2.red(error.name)}: ${chalk2.red(error.stack || error.message)}`);
695
+ return this.log(`${chalk.red(error.name)}: ${chalk.red(error.stack || error.message)}`);
2040
696
  }
2041
697
  /**
2042
698
  * event handler that is triggered when runner sends up events
@@ -2047,7 +703,7 @@ ${chalk2.red(error.stack || error.message)}`);
2047
703
  return;
2048
704
  }
2049
705
  if (event.origin === "debugger" && event.name === "start") {
2050
- this.log(chalk2.yellow(event.params.introMessage));
706
+ this.log(chalk.yellow(event.params.introMessage));
2051
707
  this._inDebugMode = true;
2052
708
  return this._inDebugMode;
2053
709
  }
@@ -2067,7 +723,7 @@ ${chalk2.red(error.stack || error.message)}`);
2067
723
  if (event.name === "error") {
2068
724
  return this.log(
2069
725
  `[${event.cid}]`,
2070
- chalk2.white(chalk2.bgRed(chalk2.bold(" Error: "))),
726
+ chalk.white(chalk.bgRed(chalk.bold(" Error: "))),
2071
727
  event.content ? event.content.message || event.content.stack || event.content : ""
2072
728
  );
2073
729
  }
@@ -2097,30 +753,30 @@ ${chalk2.red(error.stack || error.message)}`);
2097
753
  const reporter = this._messages.reporter;
2098
754
  this._messages.reporter = {};
2099
755
  for (const [reporterName, messages] of Object.entries(reporter)) {
2100
- this.log("\n", chalk2.bold(chalk2.magenta(`"${reporterName}" Reporter:`)));
756
+ this.log("\n", chalk.bold(chalk.magenta(`"${reporterName}" Reporter:`)));
2101
757
  this.log(messages.join(""));
2102
758
  }
2103
759
  }
2104
760
  printSummary() {
2105
761
  const totalJobs = this.totalWorkerCnt - this.result.retries;
2106
762
  const elapsed = new Date(Date.now() - this._start.getTime()).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0];
2107
- const retries = this.result.retries ? chalk2.yellow(this.result.retries, "retries") + ", " : "";
2108
- const failed = this.result.failed ? chalk2.red(this.result.failed, "failed") + ", " : "";
2109
- const skipped = this._skippedSpecs > 0 ? chalk2.gray(this._skippedSpecs, "skipped") + ", " : "";
763
+ const retries = this.result.retries ? chalk.yellow(this.result.retries, "retries") + ", " : "";
764
+ const failed = this.result.failed ? chalk.red(this.result.failed, "failed") + ", " : "";
765
+ const skipped = this._skippedSpecs > 0 ? chalk.gray(this._skippedSpecs, "skipped") + ", " : "";
2110
766
  const percentCompleted = totalJobs ? Math.round(this.result.finished / totalJobs * 100) : 0;
2111
767
  const snapshotSummary = this.#snapshotManager.summary;
2112
768
  const snapshotNotes = [];
2113
769
  if (snapshotSummary.added > 0) {
2114
- snapshotNotes.push(chalk2.green(`${snapshotSummary.added} snapshot(s) added.`));
770
+ snapshotNotes.push(chalk.green(`${snapshotSummary.added} snapshot(s) added.`));
2115
771
  }
2116
772
  if (snapshotSummary.updated > 0) {
2117
- snapshotNotes.push(chalk2.yellow(`${snapshotSummary.updated} snapshot(s) updated.`));
773
+ snapshotNotes.push(chalk.yellow(`${snapshotSummary.updated} snapshot(s) updated.`));
2118
774
  }
2119
775
  if (snapshotSummary.unmatched > 0) {
2120
- snapshotNotes.push(chalk2.red(`${snapshotSummary.unmatched} snapshot(s) unmatched.`));
776
+ snapshotNotes.push(chalk.red(`${snapshotSummary.unmatched} snapshot(s) unmatched.`));
2121
777
  }
2122
778
  if (snapshotSummary.unchecked > 0) {
2123
- snapshotNotes.push(chalk2.gray(`${snapshotSummary.unchecked} snapshot(s) unchecked.`));
779
+ snapshotNotes.push(chalk.gray(`${snapshotSummary.unchecked} snapshot(s) unchecked.`));
2124
780
  }
2125
781
  if (snapshotNotes.length > 0) {
2126
782
  this.log("\nSnapshot Summary:");
@@ -2128,7 +784,7 @@ ${chalk2.red(error.stack || error.message)}`);
2128
784
  }
2129
785
  return this.log(
2130
786
  "\nSpec Files: ",
2131
- chalk2.green(this.result.passed, "passed") + ", " + retries + failed + skipped + totalJobs,
787
+ chalk.green(this.result.passed, "passed") + ", " + retries + failed + skipped + totalJobs,
2132
788
  "total",
2133
789
  `(${percentCompleted}% completed)`,
2134
790
  "in",
@@ -2174,13 +830,13 @@ var Launcher = class {
2174
830
  */
2175
831
  async run() {
2176
832
  await this.initialize();
2177
- const config = this.configParser.getConfig();
833
+ const config3 = this.configParser.getConfig();
2178
834
  const capabilities = this.configParser.getCapabilities();
2179
835
  this.isParallelMultiremote = Array.isArray(capabilities) && capabilities.every((cap) => Object.values(cap).length > 0 && Object.values(cap).every((c) => typeof c === "object" && c.capabilities));
2180
836
  this.isMultiremote = this.isParallelMultiremote || !Array.isArray(capabilities);
2181
- validateConfig(TESTRUNNER_DEFAULTS, { ...config, capabilities });
2182
- await enableFileLogging(config.outputDir);
2183
- logger3.setLogLevelsConfig(config.logLevels, config.logLevel);
837
+ validateConfig(TESTRUNNER_DEFAULTS, { ...config3, capabilities });
838
+ await enableFileLogging(config3.outputDir);
839
+ logger3.setLogLevelsConfig(config3.logLevels, config3.logLevel);
2184
840
  const totalWorkerCnt = Array.isArray(capabilities) ? capabilities.map((c) => {
2185
841
  if (this.isParallelMultiremote) {
2186
842
  const keys = Object.keys(c);
@@ -2191,28 +847,28 @@ var Launcher = class {
2191
847
  const cap = "alwaysMatch" in standaloneCaps ? standaloneCaps.alwaysMatch : standaloneCaps;
2192
848
  return this.configParser.getSpecs(cap["wdio:specs"], cap["wdio:exclude"]).length;
2193
849
  }).reduce((a, b) => a + b, 0) : 1;
2194
- this.interface = new WDIOCLInterface(config, totalWorkerCnt, this._isWatchMode);
2195
- config.runnerEnv.FORCE_COLOR = Number(this.interface.hasAnsiSupport).toString();
2196
- const [runnerName, runnerOptions] = Array.isArray(config.runner) ? config.runner : [config.runner, {}];
850
+ this.interface = new WDIOCLInterface(config3, totalWorkerCnt, this._isWatchMode);
851
+ config3.runnerEnv.FORCE_COLOR = Number(this.interface.hasAnsiSupport).toString();
852
+ const [runnerName, runnerOptions] = Array.isArray(config3.runner) ? config3.runner : [config3.runner, {}];
2197
853
  const Runner = (await initializePlugin(runnerName, "runner")).default;
2198
- this.runner = new Runner(runnerOptions, config);
854
+ this.runner = new Runner(runnerOptions, config3);
2199
855
  exitHook(this._exitHandler.bind(this));
2200
856
  let exitCode = 0;
2201
857
  let error = void 0;
2202
858
  const caps = this.configParser.getCapabilities();
2203
859
  try {
2204
- const { ignoredWorkerServices, launcherServices } = await initializeLauncherService(config, caps);
860
+ const { ignoredWorkerServices, launcherServices } = await initializeLauncherService(config3, caps);
2205
861
  this._launcher = launcherServices;
2206
862
  this._args.ignoredWorkerServices = ignoredWorkerServices;
2207
863
  await this.runner.initialize();
2208
864
  log3.info("Run onPrepare hook");
2209
- await runLauncherHook(config.onPrepare, config, caps);
2210
- await runServiceHook(this._launcher, "onPrepare", config, caps);
865
+ await runLauncherHook(config3.onPrepare, config3, caps);
866
+ await runServiceHook(this._launcher, "onPrepare", config3, caps);
2211
867
  await Promise.all([
2212
- setupDriver(config, caps),
2213
- setupBrowser(config, caps)
868
+ setupDriver(config3, caps),
869
+ setupBrowser(config3, caps)
2214
870
  ]);
2215
- exitCode = await this._runMode(config, caps);
871
+ exitCode = await this._runMode(config3, caps);
2216
872
  await logger3.waitForBuffer();
2217
873
  this.interface.finalise();
2218
874
  } catch (err) {
@@ -2225,7 +881,7 @@ var Launcher = class {
2225
881
  exitCode = exitCode || 1;
2226
882
  }
2227
883
  }
2228
- exitCode = await this.#runOnCompleteHook(config, caps, exitCode);
884
+ exitCode = await this.#runOnCompleteHook(config3, caps, exitCode);
2229
885
  }
2230
886
  if (error) {
2231
887
  this.interface.logHookError(error);
@@ -2240,7 +896,7 @@ var Launcher = class {
2240
896
  if (this.#isInitialized) {
2241
897
  return;
2242
898
  }
2243
- const tsxPath = resolve2("tsx", import.meta.url);
899
+ const tsxPath = resolve("tsx", import.meta.url);
2244
900
  if (!process.env.NODE_OPTIONS || !process.env.NODE_OPTIONS.includes(tsxPath)) {
2245
901
  const moduleLoaderFlag = nodeVersion("major") >= 21 || nodeVersion("major") === 20 && nodeVersion("minor") >= 6 || nodeVersion("major") === 18 && nodeVersion("minor") >= 19 ? "--import" : "--loader";
2246
902
  process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ""} ${moduleLoaderFlag} ${tsxPath}`;
@@ -2258,18 +914,18 @@ var Launcher = class {
2258
914
  * a user can use plugin service, e.g. shared store service is still
2259
915
  * available running hooks in this order
2260
916
  */
2261
- async #runOnCompleteHook(config, caps, exitCode) {
917
+ async #runOnCompleteHook(config3, caps, exitCode) {
2262
918
  log3.info("Run onComplete hook");
2263
- const onCompleteResults = await runOnCompleteHook(config.onComplete, config, caps, exitCode, this.interface.result);
919
+ const onCompleteResults = await runOnCompleteHook(config3.onComplete, config3, caps, exitCode, this.interface.result);
2264
920
  if (this._launcher) {
2265
- await runServiceHook(this._launcher, "onComplete", exitCode, config, caps);
921
+ await runServiceHook(this._launcher, "onComplete", exitCode, config3, caps);
2266
922
  }
2267
923
  return onCompleteResults.includes(1) ? 1 : exitCode;
2268
924
  }
2269
925
  /**
2270
926
  * run without triggering onPrepare/onComplete hooks
2271
927
  */
2272
- _runMode(config, caps) {
928
+ _runMode(config3, caps) {
2273
929
  if (
2274
930
  /**
2275
931
  * no caps were provided
@@ -2282,24 +938,24 @@ var Launcher = class {
2282
938
  */
2283
939
  !Array.isArray(caps) && Object.keys(caps).length === 0
2284
940
  ) {
2285
- return new Promise((resolve3) => {
941
+ return new Promise((resolve2) => {
2286
942
  log3.error("Missing capabilities, exiting with failure");
2287
- return resolve3(1);
943
+ return resolve2(1);
2288
944
  });
2289
945
  }
2290
- const specFileRetries = this._isWatchMode ? 0 : config.specFileRetries;
946
+ const specFileRetries = this._isWatchMode ? 0 : config3.specFileRetries;
2291
947
  let cid = 0;
2292
948
  if (this.isMultiremote && !this.isParallelMultiremote) {
2293
949
  this._schedule.push({
2294
950
  cid: cid++,
2295
951
  caps,
2296
952
  specs: this._formatSpecs(caps, specFileRetries),
2297
- availableInstances: config.maxInstances || 1,
953
+ availableInstances: config3.maxInstances || 1,
2298
954
  runningInstances: 0
2299
955
  });
2300
956
  } else {
2301
957
  for (const capabilities of caps) {
2302
- const availableInstances = this.isParallelMultiremote ? config.maxInstances || 1 : config.runner === "browser" ? 1 : capabilities["wdio:maxInstances"] || config.maxInstancesPerCapability;
958
+ const availableInstances = this.isParallelMultiremote ? config3.maxInstances || 1 : config3.runner === "browser" ? 1 : capabilities["wdio:maxInstances"] || config3.maxInstancesPerCapability;
2303
959
  this._schedule.push({
2304
960
  cid: cid++,
2305
961
  caps: capabilities,
@@ -2309,19 +965,19 @@ var Launcher = class {
2309
965
  });
2310
966
  }
2311
967
  }
2312
- return new Promise((resolve3) => {
2313
- this._resolve = resolve3;
968
+ return new Promise((resolve2) => {
969
+ this._resolve = resolve2;
2314
970
  if (Object.values(this._schedule).reduce((specCnt, schedule) => specCnt + schedule.specs.length, 0) === 0) {
2315
- const { total, current } = config.shard;
971
+ const { total, current } = config3.shard;
2316
972
  if (total > 1) {
2317
973
  log3.info(`No specs to execute in shard ${current}/${total}, exiting!`);
2318
- return resolve3(0);
974
+ return resolve2(0);
2319
975
  }
2320
976
  log3.error("No specs found to run, exiting with failure");
2321
- return resolve3(1);
977
+ return resolve2(1);
2322
978
  }
2323
979
  if (this._runSpecs()) {
2324
- resolve3(0);
980
+ resolve2(0);
2325
981
  }
2326
982
  });
2327
983
  }
@@ -2364,17 +1020,17 @@ var Launcher = class {
2364
1020
  if (this._hasTriggeredExitRoutine) {
2365
1021
  return true;
2366
1022
  }
2367
- const config = this.configParser.getConfig();
2368
- while (this._getNumberOfRunningInstances() < config.maxInstances) {
1023
+ const config3 = this.configParser.getConfig();
1024
+ while (this._getNumberOfRunningInstances() < config3.maxInstances) {
2369
1025
  const schedulableCaps = this._schedule.filter((session) => {
2370
- const filter = typeof config.bail !== "number" || config.bail < 1 || config.bail > this._runnerFailed;
1026
+ const filter = typeof config3.bail !== "number" || config3.bail < 1 || config3.bail > this._runnerFailed;
2371
1027
  if (!filter) {
2372
1028
  this._schedule.forEach((t) => {
2373
1029
  t.specs = [];
2374
1030
  });
2375
1031
  return false;
2376
1032
  }
2377
- if (this._getNumberOfRunningInstances() >= config.maxInstances) {
1033
+ if (this._getNumberOfRunningInstances() >= config3.maxInstances) {
2378
1034
  return false;
2379
1035
  }
2380
1036
  return session.availableInstances > 0 && session.specs.length > 0;
@@ -2420,9 +1076,9 @@ var Launcher = class {
2420
1076
  if (!this.runner || !this.interface) {
2421
1077
  throw new Error("Internal Error: no runner initialized, call run() first");
2422
1078
  }
2423
- const config = this.configParser.getConfig();
2424
- if (typeof config.specFileRetriesDelay === "number" && config.specFileRetries > 0 && config.specFileRetries !== retries) {
2425
- await sleep(config.specFileRetriesDelay * 1e3);
1079
+ const config3 = this.configParser.getConfig();
1080
+ if (typeof config3.specFileRetriesDelay === "number" && config3.specFileRetries > 0 && config3.specFileRetries !== retries) {
1081
+ await sleep(config3.specFileRetriesDelay * 1e3);
2426
1082
  }
2427
1083
  const runnerId = rid || this._getRunnerId(cid);
2428
1084
  const processNumber = this._runnerStarted + 1;
@@ -2445,13 +1101,13 @@ var Launcher = class {
2445
1101
  if (debugType) {
2446
1102
  debugArgs.push(`--${debugType}=${debugHost}${debugPort + processNumber}`);
2447
1103
  }
2448
- const capExecArgs = [...config.execArgv || []];
1104
+ const capExecArgs = [...config3.execArgv || []];
2449
1105
  const defaultArgs = capExecArgs.length ? process.execArgv : [];
2450
1106
  const execArgv = [...defaultArgs, ...debugArgs, ...capExecArgs];
2451
1107
  this._runnerStarted++;
2452
1108
  const workerCaps = structuredClone(caps);
2453
1109
  log3.info("Run onWorkerStart hook");
2454
- await runLauncherHook(config.onWorkerStart, runnerId, workerCaps, specs, this._args, execArgv).catch((error) => this._workerHookError(error));
1110
+ await runLauncherHook(config3.onWorkerStart, runnerId, workerCaps, specs, this._args, execArgv).catch((error) => this._workerHookError(error));
2455
1111
  await runServiceHook(this._launcher, "onWorkerStart", runnerId, workerCaps, specs, this._args, execArgv).catch((error) => this._workerHookError(error));
2456
1112
  const worker = await this.runner.run({
2457
1113
  cid: runnerId,
@@ -2463,8 +1119,8 @@ var Launcher = class {
2463
1119
  * Pass on user and key values to ensure they are available in the worker process when using
2464
1120
  * environment variables that were locally exported but not part of the environment.
2465
1121
  */
2466
- user: config.user,
2467
- key: config.key
1122
+ user: config3.user,
1123
+ key: config3.key
2468
1124
  },
2469
1125
  caps: workerCaps,
2470
1126
  specs,
@@ -2531,8 +1187,8 @@ var Launcher = class {
2531
1187
  this._schedule[cid].availableInstances++;
2532
1188
  this._schedule[cid].runningInstances--;
2533
1189
  log3.info("Run onWorkerEnd hook");
2534
- const config = this.configParser.getConfig();
2535
- await runLauncherHook(config.onWorkerEnd, rid, exitCode, specs, retries).catch((error) => this._workerHookError(error));
1190
+ const config3 = this.configParser.getConfig();
1191
+ await runLauncherHook(config3.onWorkerEnd, rid, exitCode, specs, retries).catch((error) => this._workerHookError(error));
2536
1192
  await runServiceHook(this._launcher, "onWorkerEnd", rid, exitCode, specs, retries).catch((error) => this._workerHookError(error));
2537
1193
  const shouldRunSpecs = this._runSpecs();
2538
1194
  const inWatchMode = this._isWatchMode && !this._hasTriggeredExitRoutine;
@@ -2574,317 +1230,43 @@ var Launcher = class {
2574
1230
  var launcher_default = Launcher;
2575
1231
 
2576
1232
  // src/run.ts
2577
- import path7 from "node:path";
1233
+ import path3 from "node:path";
2578
1234
  import yargs from "yargs";
2579
1235
  import { hideBin } from "yargs/helpers";
2580
1236
 
2581
- // src/commands/config.ts
2582
- var config_exports = {};
2583
- __export(config_exports, {
2584
- builder: () => builder,
2585
- canAccessConfigPath: () => canAccessConfigPath,
2586
- cmdArgs: () => cmdArgs,
2587
- command: () => command,
2588
- desc: () => desc,
2589
- formatConfigFilePaths: () => formatConfigFilePaths,
2590
- handler: () => handler,
2591
- missingConfigurationPrompt: () => missingConfigurationPrompt,
2592
- parseAnswers: () => parseAnswers,
2593
- runConfigCommand: () => runConfigCommand
2594
- });
2595
- import fs3 from "node:fs/promises";
2596
- import fss from "node:fs";
2597
- import path3 from "node:path";
2598
- import inquirer2 from "inquirer";
2599
- var hasYarnLock = false;
2600
- try {
2601
- fss.accessSync("yarn.lock");
2602
- hasYarnLock = true;
2603
- } catch {
2604
- hasYarnLock = false;
2605
- }
2606
- var command = "config";
2607
- var desc = "Initialize WebdriverIO and setup configuration in your current project.";
2608
- var cmdArgs = {
2609
- yarn: {
2610
- type: "boolean",
2611
- desc: "Install packages via Yarn package manager.",
2612
- default: hasYarnLock
2613
- },
2614
- yes: {
2615
- alias: "y",
2616
- desc: "will fill in all config defaults without prompting",
2617
- type: "boolean",
2618
- default: false
2619
- },
2620
- npmTag: {
2621
- alias: "t",
2622
- desc: "define NPM tag to use for WebdriverIO related packages",
2623
- type: "string",
2624
- default: "latest"
2625
- }
2626
- };
2627
- var builder = (yargs2) => {
2628
- return yargs2.options(cmdArgs).epilogue(CLI_EPILOGUE).help();
2629
- };
2630
- var parseAnswers = async function(yes) {
2631
- console.log(CONFIG_HELPER_INTRO);
2632
- const answers = await getAnswers(yes);
2633
- const frameworkPackage = convertPackageHashToObject(answers.framework);
2634
- const runnerPackage = convertPackageHashToObject(answers.runner || SUPPORTED_PACKAGES.runner[0].value);
2635
- const servicePackages = answers.services.map((service) => convertPackageHashToObject(service));
2636
- const pluginPackages = answers.plugins.map((plugin) => convertPackageHashToObject(plugin));
2637
- const serenityPackages = getSerenityPackages(answers);
2638
- const reporterPackages = answers.reporters.map((reporter) => convertPackageHashToObject(reporter));
2639
- const presetPackage = convertPackageHashToObject(answers.preset || "");
2640
- const projectProps = await getProjectProps(process.cwd());
2641
- const projectRootDir = await getProjectRoot(answers);
2642
- const packagesToInstall = [
2643
- runnerPackage.package,
2644
- frameworkPackage.package,
2645
- presetPackage.package,
2646
- ...reporterPackages.map((reporter) => reporter.package),
2647
- ...pluginPackages.map((plugin) => plugin.package),
2648
- ...servicePackages.map((service) => service.package),
2649
- ...serenityPackages
2650
- ].filter(Boolean);
2651
- const hasRootTSConfig = await fs3.access(path3.resolve(projectRootDir, "tsconfig.json")).then(() => true, () => false);
2652
- const tsConfigFilePath = !hasRootTSConfig ? path3.resolve(projectRootDir, "tsconfig.json") : answers.specs ? path3.resolve(
2653
- path3.dirname(answers.specs.split(path3.sep).filter((s) => !s.includes("*")).join(path3.sep)),
2654
- "tsconfig.json"
2655
- ) : path3.resolve(projectRootDir, `tsconfig.${runnerPackage.short === "local" ? "e2e" : "wdio"}.json`);
2656
- const parsedPaths = getPathForFileGeneration(answers, projectRootDir);
2657
- const isUsingTypeScript = answers.isUsingTypeScript;
2658
- const wdioConfigFilename = `wdio.conf.${isUsingTypeScript ? "ts" : "js"}`;
2659
- const wdioConfigPath = path3.resolve(projectRootDir, wdioConfigFilename);
2660
- return {
2661
- projectName: projectProps?.packageJson.name || "Test Suite",
2662
- // default values required in templates
2663
- ...{
2664
- usePageObjects: false,
2665
- installTestingLibrary: false
2666
- },
2667
- ...answers,
2668
- useSauceConnect: isNuxtProject || answers.useSauceConnect,
2669
- rawAnswers: answers,
2670
- runner: runnerPackage.short,
2671
- preset: presetPackage.short,
2672
- framework: frameworkPackage.short,
2673
- purpose: runnerPackage.purpose,
2674
- serenityAdapter: frameworkPackage.package === "@serenity-js/webdriverio" && frameworkPackage.purpose,
2675
- reporters: reporterPackages.map(({ short }) => short),
2676
- plugins: pluginPackages.map(({ short }) => short),
2677
- services: servicePackages.map(({ short }) => short),
2678
- specs: answers.specs && `./${path3.relative(projectRootDir, answers.specs).replaceAll(path3.sep, "/")}`,
2679
- stepDefinitions: answers.stepDefinitions && `./${path3.relative(projectRootDir, answers.stepDefinitions).replaceAll(path3.sep, "/")}`,
2680
- packagesToInstall,
2681
- isUsingTypeScript,
2682
- esmSupport: projectProps && !projectProps.esmSupported ? false : true,
2683
- isSync: false,
2684
- _async: "async ",
2685
- _await: "await ",
2686
- projectRootDir,
2687
- destSpecRootPath: parsedPaths.destSpecRootPath,
2688
- destStepRootPath: parsedPaths.destStepRootPath,
2689
- destPageObjectRootPath: parsedPaths.destPageObjectRootPath,
2690
- destSerenityLibRootPath: parsedPaths.destSerenityLibRootPath,
2691
- relativePath: parsedPaths.relativePath,
2692
- hasRootTSConfig,
2693
- tsConfigFilePath,
2694
- tsProject: `./${path3.relative(projectRootDir, tsConfigFilePath).replaceAll(path3.sep, "/")}`,
2695
- wdioConfigPath
2696
- };
2697
- };
2698
- async function runConfigCommand(parsedAnswers, npmTag) {
2699
- console.log("\n");
2700
- await createPackageJSON(parsedAnswers);
2701
- await setupTypeScript(parsedAnswers);
2702
- await npmInstall(parsedAnswers, npmTag);
2703
- await createWDIOConfig(parsedAnswers);
2704
- await createWDIOScript(parsedAnswers);
2705
- console.log(
2706
- configHelperSuccessMessage({
2707
- projectRootDir: parsedAnswers.projectRootDir,
2708
- runScript: parsedAnswers.serenityAdapter ? "serenity" : "wdio",
2709
- extraInfo: parsedAnswers.serenityAdapter ? CONFIG_HELPER_SERENITY_BANNER : ""
2710
- })
2711
- );
2712
- await runAppiumInstaller(parsedAnswers);
2713
- }
2714
- async function handler(argv, runConfigCmd = runConfigCommand) {
2715
- const parsedAnswers = await parseAnswers(argv.yes);
2716
- await runConfigCmd(parsedAnswers, argv.npmTag);
2717
- return {
2718
- success: true,
2719
- parsedAnswers,
2720
- installedPackages: parsedAnswers.packagesToInstall.map((pkg2) => pkg2.split("--")[0])
2721
- };
2722
- }
2723
- async function formatConfigFilePaths(config) {
2724
- const fullPath = path3.isAbsolute(config) ? config : path3.join(process.cwd(), config);
2725
- const fullPathNoExtension = fullPath.substring(0, fullPath.lastIndexOf(path3.extname(fullPath)));
2726
- return { fullPath, fullPathNoExtension };
2727
- }
2728
- async function canAccessConfigPath(configPathNoExtension, configPath) {
2729
- return new Promise((resolve3, reject) => {
2730
- if (configPath) {
2731
- fs3.access(configPath).then(() => resolve3(configPath), reject);
2732
- } else {
2733
- reject();
2734
- }
2735
- }).catch(() => Promise.all(SUPPORTED_CONFIG_FILE_EXTENSION.map(async (supportedExtension) => {
2736
- const configPathWithExtension = `${configPathNoExtension}.${supportedExtension}`;
2737
- return fs3.access(configPathWithExtension).then(() => configPathWithExtension, () => void 0);
2738
- })).then(
2739
- (configFilePaths) => configFilePaths.find(Boolean),
2740
- () => void 0
2741
- ));
2742
- }
2743
- async function missingConfigurationPrompt(command5, configPath, runConfigCmd = runConfigCommand) {
2744
- const message = `Could not execute "${command5}" due to missing configuration, file "${path3.parse(configPath).name}[.js/.ts]" not found! Would you like to create one?`;
2745
- const { config } = await inquirer2.prompt({
2746
- type: "confirm",
2747
- name: "config",
2748
- message,
2749
- default: false
2750
- });
2751
- if (!config) {
2752
- console.log(`No WebdriverIO configuration found in "${process.cwd()}"`);
2753
- if (!process.env.WDIO_UNIT_TESTS) {
2754
- process.exit(0);
2755
- }
2756
- return configPath;
2757
- }
2758
- const parsedAnswers = await parseAnswers(false);
2759
- await runConfigCmd(parsedAnswers, "latest");
2760
- return configPath;
2761
- }
1237
+ // src/commands/index.ts
1238
+ import { config as config2 } from "create-wdio/config/cli";
1239
+ import { install } from "create-wdio/install/cli";
2762
1240
 
2763
- // src/commands/install.ts
2764
- var install_exports = {};
2765
- __export(install_exports, {
1241
+ // src/commands/repl.ts
1242
+ var repl_exports = {};
1243
+ __export(repl_exports, {
2766
1244
  builder: () => builder2,
2767
1245
  cmdArgs: () => cmdArgs2,
2768
1246
  command: () => command2,
2769
1247
  desc: () => desc2,
2770
1248
  handler: () => handler2
2771
1249
  });
2772
- import fs4 from "node:fs/promises";
2773
- import path4 from "node:path";
2774
- var supportedInstallations = {
2775
- runner: SUPPORTED_PACKAGES.runner.map(({ value }) => convertPackageHashToObject(value)),
2776
- plugin: SUPPORTED_PACKAGES.plugin.map(({ value }) => convertPackageHashToObject(value)),
2777
- service: SUPPORTED_PACKAGES.service.map(({ value }) => convertPackageHashToObject(value)),
2778
- reporter: SUPPORTED_PACKAGES.reporter.map(({ value }) => convertPackageHashToObject(value)),
2779
- framework: SUPPORTED_PACKAGES.framework.map(({ value }) => convertPackageHashToObject(value))
2780
- };
2781
- var command2 = "install <type> <name>";
2782
- var desc2 = [
2783
- "Add a `reporter`, `service`, or `framework` to your WebdriverIO project.",
2784
- "The command installs the package from NPM, adds it to your package.json",
2785
- "and modifies the wdio.conf.js accordingly."
2786
- ].join(" ");
2787
- var cmdArgs2 = {
2788
- config: {
2789
- desc: "Location of your WDIO configuration (default: wdio.conf.(js|ts|cjs|mjs))"
2790
- }
2791
- };
2792
- var builder2 = (yargs2) => {
2793
- yargs2.options(cmdArgs2).epilogue(CLI_EPILOGUE).help();
2794
- for (const [type, plugins] of Object.entries(supportedInstallations)) {
2795
- for (const plugin of plugins) {
2796
- yargs2.example(`$0 install ${type} ${plugin.short}`, `Install ${plugin.package}`);
2797
- }
2798
- }
2799
- return yargs2;
2800
- };
2801
- async function handler2(argv) {
2802
- const { type, name, config } = argv;
2803
- if (!Object.keys(supportedInstallations).includes(type)) {
2804
- console.log(`Type ${type} is not supported.`);
2805
- process.exit(0);
2806
- return;
2807
- }
2808
- const options = supportedInstallations[type].map((pkg2) => pkg2.short);
2809
- if (!options.find((pkg2) => pkg2 === name)) {
2810
- console.log(
2811
- `Error: ${name} is not a supported ${type}.
2812
-
2813
- Available options for a ${type} are:
2814
- - ${options.join("\n- ")}`
2815
- );
2816
- process.exit(0);
2817
- return;
2818
- }
2819
- const defaultPath = path4.resolve(process.cwd(), "wdio.conf");
2820
- const wdioConfPathWithNoExtension = config ? (await formatConfigFilePaths(config)).fullPathNoExtension : defaultPath;
2821
- const wdioConfPath = await canAccessConfigPath(wdioConfPathWithNoExtension);
2822
- if (!wdioConfPath) {
2823
- try {
2824
- await missingConfigurationPrompt("install", wdioConfPathWithNoExtension);
2825
- return handler2(argv);
2826
- } catch {
2827
- process.exit(1);
2828
- return;
2829
- }
2830
- }
2831
- const configFile = await fs4.readFile(wdioConfPath, { encoding: "utf-8" });
2832
- const match = findInConfig(configFile, type);
2833
- const projectRoot = await getProjectRoot();
2834
- if (match && match[0].includes(name)) {
2835
- console.log(`The ${type} ${name} is already part of your configuration.`);
2836
- process.exit(0);
2837
- return;
2838
- }
2839
- const selectedPackage = supportedInstallations[type].find(({ short }) => short === name);
2840
- const pkgsToInstall = selectedPackage ? [selectedPackage.package] : [];
2841
- addServiceDeps(selectedPackage ? [selectedPackage] : [], pkgsToInstall, true);
2842
- const pm = detectPackageManager();
2843
- console.log(`Installing "${selectedPackage.package}" using ${pm}.`);
2844
- const success = await installPackages(projectRoot, pkgsToInstall, true);
2845
- if (!success) {
2846
- process.exit(1);
2847
- return;
2848
- }
2849
- console.log(`Package "${selectedPackage.package}" installed successfully.`);
2850
- const newConfig = replaceConfig(configFile, type, name);
2851
- if (!newConfig) {
2852
- throw new Error(`Couldn't find "${type}" property in ${path4.basename(wdioConfPath)}`);
2853
- }
2854
- await fs4.writeFile(wdioConfPath, newConfig, { encoding: "utf-8" });
2855
- console.log("Your wdio.conf.js file has been updated.");
2856
- process.exit(0);
2857
- }
2858
-
2859
- // src/commands/repl.ts
2860
- var repl_exports = {};
2861
- __export(repl_exports, {
2862
- builder: () => builder4,
2863
- cmdArgs: () => cmdArgs4,
2864
- command: () => command4,
2865
- desc: () => desc4,
2866
- handler: () => handler4
2867
- });
2868
1250
  import pickBy3 from "lodash.pickby";
2869
1251
  import { remote } from "webdriverio";
2870
1252
 
2871
1253
  // src/commands/run.ts
2872
1254
  var run_exports = {};
2873
1255
  __export(run_exports, {
2874
- builder: () => builder3,
2875
- cmdArgs: () => cmdArgs3,
2876
- command: () => command3,
2877
- desc: () => desc3,
2878
- handler: () => handler3,
1256
+ builder: () => builder,
1257
+ cmdArgs: () => cmdArgs,
1258
+ command: () => command,
1259
+ desc: () => desc,
1260
+ handler: () => handler,
2879
1261
  launch: () => launch,
2880
1262
  launchWithStdin: () => launchWithStdin
2881
1263
  });
2882
- import fs5 from "node:fs/promises";
2883
- import path6 from "node:path";
1264
+ import fs from "node:fs/promises";
1265
+ import path2 from "node:path";
2884
1266
 
2885
1267
  // src/watcher.ts
2886
1268
  import url from "node:url";
2887
- import path5 from "node:path";
1269
+ import path from "node:path";
2888
1270
  import chokidar from "chokidar";
2889
1271
  import pickBy2 from "lodash.pickby";
2890
1272
  import flattenDeep from "lodash.flattendeep";
@@ -2913,7 +1295,7 @@ var Watcher = class {
2913
1295
  const { filesToWatch } = this._launcher.configParser.getConfig();
2914
1296
  if (filesToWatch.length) {
2915
1297
  const pathService = new FileSystemPathService();
2916
- const rootDir = path5.dirname(path5.resolve(process.cwd(), this._configFile));
1298
+ const rootDir = path.dirname(path.resolve(process.cwd(), this._configFile));
2917
1299
  const globbedFilesToWatch = filesToWatch.map((file) => pathService.ensureAbsolutePath(file, rootDir));
2918
1300
  chokidar.watch(globbedFilesToWatch, { ignoreInitial: true }).on("add", this.getFileListener(false)).on("change", this.getFileListener(false));
2919
1301
  }
@@ -2990,8 +1372,8 @@ var Watcher = class {
2990
1372
  this.cleanUp();
2991
1373
  for (const [, worker] of Object.entries(workers)) {
2992
1374
  const { cid, capabilities, specs, sessionId } = worker;
2993
- const { hostname, path: path8, port, protocol, automationProtocol } = worker.config;
2994
- const args = Object.assign({ sessionId, baseUrl: worker.config.baseUrl, hostname, path: path8, port, protocol, automationProtocol }, params);
1375
+ const { hostname, path: path4, port, protocol, automationProtocol } = worker.config;
1376
+ const args = Object.assign({ sessionId, baseUrl: worker.config.baseUrl, hostname, path: path4, port, protocol, automationProtocol }, params);
2995
1377
  worker.postMessage("run", args);
2996
1378
  this._launcher.interface.emit("job:start", { cid, caps: capabilities, specs });
2997
1379
  }
@@ -3002,9 +1384,10 @@ var Watcher = class {
3002
1384
  };
3003
1385
 
3004
1386
  // src/commands/run.ts
3005
- var command3 = "run <configPath>";
3006
- var desc3 = "Run your WDIO configuration file to initialize your tests. (default)";
3007
- var cmdArgs3 = {
1387
+ import { config } from "create-wdio/config/cli";
1388
+ var command = "run <configPath>";
1389
+ var desc = "Run your WDIO configuration file to initialize your tests. (default)";
1390
+ var cmdArgs = {
3008
1391
  watch: {
3009
1392
  desc: "Run WebdriverIO in watch mode",
3010
1393
  type: "boolean"
@@ -3114,8 +1497,8 @@ var cmdArgs3 = {
3114
1497
  }
3115
1498
  }
3116
1499
  };
3117
- var builder3 = (yargs2) => {
3118
- return yargs2.options(cmdArgs3).example("$0 run wdio.conf.js --suite foobar", 'Run suite on testsuite "foobar"').example("$0 run wdio.conf.js --spec ./tests/e2e/a.js --spec ./tests/e2e/b.js", "Run suite on specific specs").example("$0 run wdio.conf.js --shard 1/4", "Run only the first shard of 4 shards").example("$0 run wdio.conf.js --mochaOpts.timeout 60000", "Run suite with custom Mocha timeout").example("$0 run wdio.conf.js --tsConfigPath=./configs/bdd-tsconfig.json", "Run suite with tsx using custom tsconfig.json").epilogue(CLI_EPILOGUE).help();
1500
+ var builder = (yargs2) => {
1501
+ return yargs2.options(cmdArgs).example("$0 run wdio.conf.js --suite foobar", 'Run suite on testsuite "foobar"').example("$0 run wdio.conf.js --spec ./tests/e2e/a.js --spec ./tests/e2e/b.js", "Run suite on specific specs").example("$0 run wdio.conf.js --shard 1/4", "Run only the first shard of 4 shards").example("$0 run wdio.conf.js --mochaOpts.timeout 60000", "Run suite with custom Mocha timeout").example("$0 run wdio.conf.js --tsConfigPath=./configs/bdd-tsconfig.json", "Run suite with tsx using custom tsconfig.json").epilogue(CLI_EPILOGUE).help();
3119
1502
  };
3120
1503
  function launchWithStdin(wdioConfPath, params) {
3121
1504
  let stdinData = "";
@@ -3145,26 +1528,26 @@ async function launch(wdioConfPath, params) {
3145
1528
  }
3146
1529
  });
3147
1530
  }
3148
- async function handler3(argv) {
1531
+ async function handler(argv) {
3149
1532
  const { configPath = "wdio.conf.js", ...params } = argv;
3150
- const wdioConf = await formatConfigFilePaths(configPath);
3151
- const confAccess = await canAccessConfigPath(wdioConf.fullPathNoExtension, wdioConf.fullPath);
1533
+ const wdioConf = await config.formatConfigFilePaths(configPath);
1534
+ const confAccess = await config.canAccessConfigPath(wdioConf.fullPathNoExtension, wdioConf.fullPath);
3152
1535
  if (!confAccess) {
3153
1536
  try {
3154
- await missingConfigurationPrompt("run", wdioConf.fullPathNoExtension);
1537
+ await config.missingConfigurationPrompt("run", wdioConf.fullPathNoExtension);
3155
1538
  if (process.env.WDIO_UNIT_TESTS) {
3156
1539
  return;
3157
1540
  }
3158
- return handler3(argv);
1541
+ return handler(argv);
3159
1542
  } catch {
3160
1543
  process.exit(1);
3161
1544
  }
3162
1545
  }
3163
- const tsConfigPathFromEnvVar = process.env.TSCONFIG_PATH && path6.resolve(process.cwd(), process.env.TSCONFIG_PATH) || process.env.TSX_TSCONFIG_PATH && path6.resolve(process.cwd(), process.env.TSX_TSCONFIG_PATH);
3164
- const tsConfigPathFromParams = params.tsConfigPath && path6.resolve(process.cwd(), params.tsConfigPath);
3165
- const tsConfigPathRelativeToWdioConfig = path6.join(path6.dirname(confAccess), "tsconfig.json");
1546
+ const tsConfigPathFromEnvVar = process.env.TSCONFIG_PATH && path2.resolve(process.cwd(), process.env.TSCONFIG_PATH) || process.env.TSX_TSCONFIG_PATH && path2.resolve(process.cwd(), process.env.TSX_TSCONFIG_PATH);
1547
+ const tsConfigPathFromParams = params.tsConfigPath && path2.resolve(process.cwd(), params.tsConfigPath);
1548
+ const tsConfigPathRelativeToWdioConfig = path2.join(path2.dirname(confAccess), "tsconfig.json");
3166
1549
  const localTSConfigPath = tsConfigPathFromEnvVar || tsConfigPathFromParams || tsConfigPathRelativeToWdioConfig;
3167
- const hasLocalTSConfig = await fs5.access(localTSConfigPath).then(() => true, () => false);
1550
+ const hasLocalTSConfig = await fs.access(localTSConfigPath).then(() => true, () => false);
3168
1551
  if (hasLocalTSConfig) {
3169
1552
  process.env.TSX_TSCONFIG_PATH = localTSConfigPath;
3170
1553
  }
@@ -3190,9 +1573,9 @@ var IGNORED_ARGS = [
3190
1573
  "jasmineOpts",
3191
1574
  "cucumberOpts"
3192
1575
  ];
3193
- var command4 = "repl <option> [capabilities]";
3194
- var desc4 = "Run WebDriver session in command line";
3195
- var cmdArgs4 = {
1576
+ var command2 = "repl <option> [capabilities]";
1577
+ var desc2 = "Run WebDriver session in command line";
1578
+ var cmdArgs2 = {
3196
1579
  platformVersion: {
3197
1580
  alias: "v",
3198
1581
  desc: "Version of OS for mobile devices",
@@ -3209,10 +1592,10 @@ var cmdArgs4 = {
3209
1592
  type: "string"
3210
1593
  }
3211
1594
  };
3212
- var builder4 = (yargs2) => {
3213
- return yargs2.options(pickBy3({ ...cmdArgs4, ...cmdArgs3 }, (_, key) => !IGNORED_ARGS.includes(key))).example("$0 repl firefox --path /", "Run repl locally").example("$0 repl chrome -u <SAUCE_USERNAME> -k <SAUCE_ACCESS_KEY>", "Run repl in Sauce Labs cloud").example("$0 repl android", "Run repl browser on launched Android device").example('$0 repl "./path/to/your_app.app"', "Run repl native app on iOS simulator").example('$0 repl ios -v 11.3 -d "iPhone 7" -u 123432abc', "Run repl browser on iOS device with capabilities").example('$0 repl "./path/to/wdio.config.js" 0 -p 9515', "Run repl using the first capability from the capabilty array in wdio.config.js").example('$0 repl "./path/to/wdio.config.js" "myChromeBrowser" -p 9515', "Run repl using a named multiremote capabilities in wdio.config.js").epilogue(CLI_EPILOGUE).help();
1595
+ var builder2 = (yargs2) => {
1596
+ return yargs2.options(pickBy3({ ...cmdArgs2, ...cmdArgs }, (_, key) => !IGNORED_ARGS.includes(key))).example("$0 repl firefox --path /", "Run repl locally").example("$0 repl chrome -u <SAUCE_USERNAME> -k <SAUCE_ACCESS_KEY>", "Run repl in Sauce Labs cloud").example("$0 repl android", "Run repl browser on launched Android device").example('$0 repl "./path/to/your_app.app"', "Run repl native app on iOS simulator").example('$0 repl ios -v 11.3 -d "iPhone 7" -u 123432abc', "Run repl browser on iOS device with capabilities").example('$0 repl "./path/to/wdio.config.js" 0 -p 9515', "Run repl using the first capability from the capabilty array in wdio.config.js").example('$0 repl "./path/to/wdio.config.js" "myChromeBrowser" -p 9515', "Run repl using a named multiremote capabilities in wdio.config.js").epilogue(CLI_EPILOGUE).help();
3214
1597
  };
3215
- var handler4 = async (argv) => {
1598
+ var handler2 = async (argv) => {
3216
1599
  const caps = await getCapabilities(argv);
3217
1600
  const client = await remote({ ...argv, ...caps });
3218
1601
  global.$ = client.$.bind(client);
@@ -3223,7 +1606,7 @@ var handler4 = async (argv) => {
3223
1606
  };
3224
1607
 
3225
1608
  // src/commands/index.ts
3226
- var commands = [config_exports, install_exports, repl_exports, run_exports];
1609
+ var commands = [config2, install, repl_exports, run_exports];
3227
1610
 
3228
1611
  // src/run.ts
3229
1612
  var DEFAULT_CONFIG_FILENAME = "wdio.conf.js";
@@ -3243,7 +1626,7 @@ async function run() {
3243
1626
 
3244
1627
  Commands:` }).version(pkg.version).epilogue(CLI_EPILOGUE);
3245
1628
  if (!process.argv.find((arg) => arg === "--help")) {
3246
- argv.options(cmdArgs3);
1629
+ argv.options(cmdArgs);
3247
1630
  }
3248
1631
  const params = await argv.parse();
3249
1632
  if (!params._ || params._.find((param) => SUPPORTED_COMMANDS.includes(param))) {
@@ -3251,14 +1634,14 @@ Commands:` }).version(pkg.version).epilogue(CLI_EPILOGUE);
3251
1634
  }
3252
1635
  const args = {
3253
1636
  ...params,
3254
- configPath: path7.resolve(process.cwd(), params._[0] && params._[0].toString() || DEFAULT_CONFIG_FILENAME)
1637
+ configPath: path3.resolve(process.cwd(), params._[0] && params._[0].toString() || DEFAULT_CONFIG_FILENAME)
3255
1638
  };
3256
1639
  try {
3257
- const cp = await handler3(args);
1640
+ const cp = await handler(args);
3258
1641
  return cp;
3259
1642
  } catch (err) {
3260
1643
  const output = await new Promise(
3261
- (resolve3) => yargs(hideBin(process.argv)).parse("--help", (err2, argv2, output2) => resolve3(output2))
1644
+ (resolve2) => yargs(hideBin(process.argv)).parse("--help", (err2, argv2, output2) => resolve2(output2))
3262
1645
  );
3263
1646
  console.error(`${output}
3264
1647