create-wdio 9.0.0 → 9.17.0

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 (83) hide show
  1. package/README.md +12 -7
  2. package/assets/demo.gif +0 -0
  3. package/build/cli/config.d.ts +51 -0
  4. package/build/cli/config.d.ts.map +1 -0
  5. package/build/cli/install.d.ts +12 -0
  6. package/build/cli/install.d.ts.map +1 -0
  7. package/build/cli/utils.d.ts +18 -0
  8. package/build/cli/utils.d.ts.map +1 -0
  9. package/build/config/cli.d.ts +2 -0
  10. package/build/config/cli.d.ts.map +1 -0
  11. package/build/config/cli.js +1632 -0
  12. package/build/constants.d.ts +248 -0
  13. package/build/constants.d.ts.map +1 -0
  14. package/build/index.d.ts +4 -0
  15. package/build/index.d.ts.map +1 -0
  16. package/build/index.js +1018 -54
  17. package/build/install/cli.d.ts +2 -0
  18. package/build/install/cli.d.ts.map +1 -0
  19. package/build/install/cli.js +1719 -0
  20. package/build/install.d.ts +4 -0
  21. package/build/install.d.ts.map +1 -0
  22. package/build/templates/EjsHelpers.d.ts +18 -0
  23. package/build/templates/EjsHelpers.d.ts.map +1 -0
  24. package/build/templates/exampleFiles/browser/Component.css.ejs +121 -0
  25. package/build/templates/exampleFiles/browser/Component.lit.ejs +154 -0
  26. package/build/templates/exampleFiles/browser/Component.lit.test.ejs +24 -0
  27. package/build/templates/exampleFiles/browser/Component.preact.ejs +28 -0
  28. package/build/templates/exampleFiles/browser/Component.preact.test.ejs +59 -0
  29. package/build/templates/exampleFiles/browser/Component.react.ejs +29 -0
  30. package/build/templates/exampleFiles/browser/Component.react.test.ejs +58 -0
  31. package/build/templates/exampleFiles/browser/Component.solid.ejs +28 -0
  32. package/build/templates/exampleFiles/browser/Component.solid.test.ejs +58 -0
  33. package/build/templates/exampleFiles/browser/Component.stencil.ejs +43 -0
  34. package/build/templates/exampleFiles/browser/Component.stencil.test.ejs +45 -0
  35. package/build/templates/exampleFiles/browser/Component.svelte.ejs +47 -0
  36. package/build/templates/exampleFiles/browser/Component.svelte.test.ejs +58 -0
  37. package/build/templates/exampleFiles/browser/Component.vue.ejs +34 -0
  38. package/build/templates/exampleFiles/browser/Component.vue.test.ejs +62 -0
  39. package/build/templates/exampleFiles/browser/standalone.test.ejs +13 -0
  40. package/build/templates/exampleFiles/cucumber/features/login.feature +12 -0
  41. package/build/templates/exampleFiles/cucumber/step_definitions/steps.js.ejs +55 -0
  42. package/build/templates/exampleFiles/mochaJasmine/test.e2e.js.ejs +11 -0
  43. package/build/templates/exampleFiles/pageobjects/login.page.js.ejs +45 -0
  44. package/build/templates/exampleFiles/pageobjects/page.js.ejs +17 -0
  45. package/build/templates/exampleFiles/pageobjects/secure.page.js.ejs +20 -0
  46. package/build/templates/exampleFiles/serenity-js/common/config/serenity.properties.ejs +1 -0
  47. package/build/templates/exampleFiles/serenity-js/common/serenity/github-api/GitHubStatus.ts.ejs +41 -0
  48. package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoList.ts.ejs +100 -0
  49. package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoListItem.ts.ejs +36 -0
  50. package/build/templates/exampleFiles/serenity-js/cucumber/step-definitions/steps.ts.ejs +37 -0
  51. package/build/templates/exampleFiles/serenity-js/cucumber/support/parameter.config.ts.ejs +18 -0
  52. package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/completing_items.feature.ejs +23 -0
  53. package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/narrative.md.ejs +17 -0
  54. package/build/templates/exampleFiles/serenity-js/jasmine/example.spec.ts.ejs +86 -0
  55. package/build/templates/exampleFiles/serenity-js/mocha/example.spec.ts.ejs +88 -0
  56. package/build/templates/snippets/afterTest.ejs +20 -0
  57. package/build/templates/snippets/capabilities.ejs +57 -0
  58. package/build/templates/snippets/cucumber.ejs +50 -0
  59. package/build/templates/snippets/electronTest.js.ejs +7 -0
  60. package/build/templates/snippets/jasmine.ejs +20 -0
  61. package/build/templates/snippets/macosTest.js.ejs +11 -0
  62. package/build/templates/snippets/mocha.ejs +14 -0
  63. package/build/templates/snippets/reporters.ejs +14 -0
  64. package/build/templates/snippets/serenity.ejs +18 -0
  65. package/build/templates/snippets/services.ejs +18 -0
  66. package/build/templates/snippets/testWithPO.js.ejs +22 -0
  67. package/build/templates/snippets/testWithoutPO.js.ejs +19 -0
  68. package/build/templates/snippets/vscodeTest.js.ejs +9 -0
  69. package/build/templates/wdio.conf.tpl.ejs +412 -0
  70. package/build/types.d.ts +99 -0
  71. package/build/types.d.ts.map +1 -0
  72. package/build/utils/index.d.ts +2 -0
  73. package/build/utils/index.d.ts.map +1 -0
  74. package/build/utils/index.js +849 -0
  75. package/build/utils.d.ts +78 -0
  76. package/build/utils.d.ts.map +1 -0
  77. package/package.json +60 -41
  78. package/.eslintrc.cjs +0 -37
  79. package/__mocks__/commander.ts +0 -18
  80. package/build/constants.js +0 -51
  81. package/build/types.js +0 -1
  82. package/build/utils.js +0 -38
  83. package/vitest.config.ts +0 -23
package/build/index.js CHANGED
@@ -1,58 +1,1022 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import chalk from 'chalk';
4
- import semver from 'semver';
5
- import { Command } from 'commander';
6
- import { runProgram, shouldUseYarn, getPackageVersion } from './utils.js';
7
- import { ASCII_ROBOT, PROGRAM_TITLE, UNSUPPORTED_NODE_VERSION, DEFAULT_NPM_TAG } from './constants.js';
8
- const WDIO_COMMAND = 'wdio';
9
- let projectDir;
10
- export async function run(operation = createWebdriverIO) {
11
- const version = await getPackageVersion();
12
- /**
13
- * print program ASCII art
1
+ // src/index.ts
2
+ import fs3 from "node:fs/promises";
3
+ import path3 from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { execSync as execSync2 } from "node:child_process";
6
+ import chalk3 from "chalk";
7
+ import semver from "semver";
8
+ import { Command } from "commander";
9
+ import { resolve } from "import-meta-resolve";
10
+
11
+ // src/utils.ts
12
+ import url from "node:url";
13
+ import path2 from "node:path";
14
+ import util, { promisify } from "node:util";
15
+ import fs2 from "node:fs/promises";
16
+ import { execSync } from "node:child_process";
17
+ import readDir from "recursive-readdir";
18
+ import { $ } from "execa";
19
+ import { readPackageUp } from "read-pkg-up";
20
+ import inquirer from "inquirer";
21
+ import ejs from "ejs";
22
+ import spawn from "cross-spawn";
23
+
24
+ // package.json
25
+ var package_default = {
26
+ name: "create-wdio",
27
+ version: "9.0.0",
28
+ description: "Install and setup a WebdriverIO project with all its dependencies in a single run",
29
+ author: "WebdriverIO Team <mail@webdriver.io>",
30
+ homepage: "https://github.com/webdriverio/webdriverio/tree/main/packages/create-wdio",
31
+ license: "MIT",
32
+ type: "module",
33
+ exports: {
34
+ ".": {
35
+ types: "./build/index.d.ts",
36
+ import: "./build/index.js",
37
+ importSource: "./src/index.ts"
38
+ },
39
+ "./config/cli": {
40
+ types: "./build/config/cli.d.ts",
41
+ import: "./build/config/cli.js",
42
+ importSource: "./src/config/cli.ts"
43
+ },
44
+ "./install/cli": {
45
+ types: "./build/install/cli.d.ts",
46
+ import: "./build/install/cli.js",
47
+ importSource: "./src/install/cli.ts"
48
+ },
49
+ "./utils": {
50
+ types: "./build/utils/index.d.ts",
51
+ import: "./build/utils/index.js",
52
+ importSource: "./src/utils/index.ts"
53
+ }
54
+ },
55
+ types: "./build/index.d.ts",
56
+ typeScriptVersion: "3.8.3",
57
+ engines: {
58
+ node: ">=12.0.0"
59
+ },
60
+ repository: {
61
+ type: "git",
62
+ url: "git+https://github.com/webdriverio/webdriverio.git",
63
+ directory: "packages/create-wdio"
64
+ },
65
+ keywords: [
66
+ "webdriverio",
67
+ "create-wdio",
68
+ "wdio",
69
+ "installer",
70
+ "e2e"
71
+ ],
72
+ bugs: {
73
+ url: "https://github.com/webdriverio/webdriverio/issues"
74
+ },
75
+ bin: {
76
+ "create-wdio": "./bin/wdio.js"
77
+ },
78
+ dependencies: {
79
+ chalk: "^5.3.0",
80
+ commander: "^14.0.0",
81
+ "cross-spawn": "^7.0.3",
82
+ ejs: "^3.1.10",
83
+ execa: "^9.6.0",
84
+ "import-meta-resolve": "^4.1.0",
85
+ inquirer: "^12.7.0",
86
+ "normalize-package-data": "^7.0.0",
87
+ "read-pkg-up": "^10.1.0",
88
+ "recursive-readdir": "^2.2.3",
89
+ semver: "^7.6.3",
90
+ "type-fest": "^4.41.0",
91
+ yargs: "^17.7.2"
92
+ },
93
+ devDependencies: {
94
+ "@types/cross-spawn": "^6.0.6",
95
+ "@types/ejs": "^3.1.5",
96
+ "@types/fs-extra": "^11.0.4",
97
+ "@types/normalize-package-data": "^2.4.4",
98
+ "@types/semver": "^7.5.8",
99
+ "@types/yargs": "^17.0.33"
100
+ },
101
+ publishConfig: {
102
+ access: "public"
103
+ }
104
+ };
105
+
106
+ // src/constants.ts
107
+ import path from "node:path";
108
+ import fs from "node:fs";
109
+ import chalk from "chalk";
110
+ var colorItBold = chalk.bold.rgb(234, 89, 6);
111
+ var colorIt = chalk.rgb(234, 89, 6);
112
+ var DEFAULT_NPM_TAG = "latest";
113
+ var ASCII_ROBOT = `
114
+ -:...........................-:.
115
+ + +
116
+ \`\` + \`...\` \`...\` + \`
117
+ ./+/ + .:://:::\` \`::///::\` \` + ++/.
118
+ .+oo+ + /:+ooo+-/ /-+ooo+-/ ./ + +oo+.
119
+ -ooo+ + /-+ooo+-/ /-+ooo+-/ .: + +ooo.
120
+ -+o+ + \`::///:-\` \`::///::\` + +o+-
121
+ \`\`. /. \`\`\`\`\` \`\`\`\`\` .: .\`\`
122
+ .----------------------------.
123
+ \`-::::::::::::::::::::::::::::::::::::::::-\`
124
+ .+oooo/:------------------------------:/oooo+.
125
+ \`.--/oooo- :oooo/--.\`
126
+ .::-\`\`:oooo\` .oooo-\`\`-::.
127
+ ./-\` -oooo\`--.: :.-- .oooo- \`-/.
128
+ -/\` \`-/oooo////////////////////////////////////oooo/.\` \`/-
129
+ \`+\` \`/+oooooooooooooooooooooooooooooooooooooooooooooooo+:\` .+\`
130
+ -/ +o/.:oooooooooooooooooooooooooooooooooooooooooooo:-/o/ +.
131
+ -/ .o+ -oooosoooososssssooooo------------------:oooo- \`oo\` +.
132
+ -/ .o+ -oooodooohyyssosshoooo\` .oooo- oo. +.
133
+ -/ .o+ -oooodooysdooooooyyooo\` \`.--.\`\` .:::-oooo- oo. +.
134
+ -/ .o+ -oooodoyyodsoooooyyooo.//-..-:/:.\`.//.\`./oooo- oo. +.
135
+ -/ .o+ -oooohsyoooyysssysoooo+-\` \`-:::. .oooo- oo. +.
136
+ -/ .o+ -ooooosooooooosooooooo+//////////////////oooo- oo. +.
137
+ -/ .o+ -oooooooooooooooooooooooooooooooooooooooooooo- oo. +.
138
+ -/ .o+ -oooooooooooooooooooooooooooooooooooooooooooo- oo. +.
139
+ -+////o+\` -oooo---:///:----://::------------------:oooo- \`oo////+-
140
+ +ooooooo/\`-oooo\`\`:-\`\`\`.:\`.:.\`.+/- .::::::::::\` .oooo-\`+ooooooo+
141
+ oooooooo+\`-oooo\`-- \`/\` .:+ -/-\`/\` .:::::::::: .oooo-.+oooooooo
142
+ +-/+://-/ -oooo-\`:\`.o-\`:.:-\`\`\`\`.: .///:\`\`\`\`\`\` -oooo-\`/-//:+:-+
143
+ : :..--:-:.+ooo+/://o+/-.-:////:-....-::::-....--/+ooo+.:.:--.-- /
144
+ - /./\`-:-\` .:///+/ooooo/+///////////////+++ooooo/+///:. .-:.\`+./ :
145
+ :-:/. :\`ooooo\`/\` .:.ooooo : ./---
146
+ :\`ooooo\`/\` .:.ooooo :
147
+ :\`ooooo./\` .:-ooooo :
148
+ :\`ooooo./\` .:-ooooo :
149
+ \`...:-+++++:/. ./:+++++-:...\`
150
+ :-.\`\`\`\`\`\`\`\`/../ /.-:\`\`\`\`\`\`\`\`.:-
151
+ -/::::::::://:/+ \`+/:+::::::::::+.
152
+ :oooooooooooo++/ +++oooooooooooo-
153
+ `;
154
+ var PROGRAM_TITLE = `
155
+ ${colorItBold("Webdriver.IO")}
156
+ ${colorIt("Next-gen browser and mobile automation")}
157
+ ${colorIt("test framework for Node.js")}
158
+ `;
159
+ var UNSUPPORTED_NODE_VERSION = `\u26A0\uFE0F Unsupported Node.js Version Error \u26A0\uFE0F
160
+ You are using Node.js ${process.version} which is too old to be used with WebdriverIO.
161
+ Please update to Node.js v20 to continue.
162
+ `;
163
+ var INSTALL_COMMAND = {
164
+ npm: "install",
165
+ pnpm: "add",
166
+ yarn: "add",
167
+ bun: "install"
168
+ };
169
+ var EXECUTER = {
170
+ npm: "npx",
171
+ pnpm: "pnpm",
172
+ yarn: "yarn",
173
+ bun: "bunx"
174
+ };
175
+ var EXECUTE_COMMAND = {
176
+ npm: "",
177
+ pnpm: "exec",
178
+ yarn: "exec",
179
+ bun: ""
180
+ };
181
+ var DEV_FLAG = {
182
+ npm: "--save-dev",
183
+ pnpm: "--save-dev",
184
+ yarn: "--dev",
185
+ bun: "--dev"
186
+ };
187
+ var SUPPORTED_PACKAGE_MANAGERS = Object.keys(INSTALL_COMMAND);
188
+ var CLI_EPILOGUE = `Documentation: https://webdriver.io
189
+ @wdio/cli (v${package_default.version})`;
190
+ var SUPPORTED_PACKAGES = {
191
+ runner: [
192
+ { name: "E2E Testing - of Web or Mobile Applications", value: "@wdio/local-runner$--$local$--$e2e" },
193
+ { name: "Component or Unit Testing - in the browser\n > https://webdriver.io/docs/component-testing", value: "@wdio/browser-runner$--$browser$--$component" },
194
+ { name: "Desktop Testing - of Electron Applications\n > https://webdriver.io/docs/desktop-testing/electron", value: "@wdio/local-runner$--$local$--$electron" },
195
+ { name: "Desktop Testing - of MacOS Applications\n > https://webdriver.io/docs/desktop-testing/macos", value: "@wdio/local-runner$--$local$--$macos" },
196
+ { name: "VS Code Extension Testing\n > https://webdriver.io/docs/vscode-extension-testing", value: "@wdio/local-runner$--$local$--$vscode" },
197
+ { name: "Roku Testing - of OTT apps running on RokuOS\n > https://webdriver.io/docs/wdio-roku-service", value: "@wdio/local-runner$--$local$--$roku" }
198
+ ],
199
+ framework: [
200
+ { name: "Mocha (https://mochajs.org/)", value: "@wdio/mocha-framework$--$mocha" },
201
+ { name: "Mocha with Serenity/JS (https://serenity-js.org/)", value: "@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$mocha" },
202
+ { name: "Jasmine (https://jasmine.github.io/)", value: "@wdio/jasmine-framework$--$jasmine" },
203
+ { name: "Jasmine with Serenity/JS (https://serenity-js.org/)", value: "@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$jasmine" },
204
+ { name: "Cucumber (https://cucumber.io/)", value: "@wdio/cucumber-framework$--$cucumber" },
205
+ { name: "Cucumber with Serenity/JS (https://serenity-js.org/)", value: "@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$cucumber" }
206
+ ],
207
+ reporter: [
208
+ { name: "spec", value: "@wdio/spec-reporter$--$spec", checked: true },
209
+ { name: "dot", value: "@wdio/dot-reporter$--$dot" },
210
+ { name: "junit", value: "@wdio/junit-reporter$--$junit" },
211
+ { name: "allure", value: "@wdio/allure-reporter$--$allure" },
212
+ { name: "sumologic", value: "@wdio/sumologic-reporter$--$sumologic" },
213
+ { name: "concise", value: "@wdio/concise-reporter$--$concise" },
214
+ { name: "json", value: "@wdio/json-reporter$--$json" },
215
+ // external
216
+ { name: "reportportal", value: "wdio-reportportal-reporter$--$reportportal" },
217
+ { name: "video", value: "wdio-video-reporter$--$video" },
218
+ { name: "cucumber-json", value: "wdio-cucumberjs-json-reporter$--$cucumberjs-json" },
219
+ { name: "mochawesome", value: "wdio-mochawesome-reporter$--$mochawesome" },
220
+ { name: "timeline", value: "wdio-timeline-reporter$--$timeline" },
221
+ { name: "html-nice", value: "wdio-html-nice-reporter$--$html-nice" },
222
+ { name: "slack", value: "@moroo/wdio-slack-reporter$--$slack" },
223
+ { name: "teamcity", value: "wdio-teamcity-reporter$--$teamcity" },
224
+ { name: "delta", value: "@delta-reporter/wdio-delta-reporter-service$--$delta" },
225
+ { name: "testrail", value: "@wdio/testrail-reporter$--$testrail" },
226
+ { name: "light", value: "wdio-light-reporter$--$light" },
227
+ { name: "wdio-json-html-reporter", value: "wdio-json-html-reporter$--$jsonhtml" }
228
+ ],
229
+ plugin: [
230
+ { 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" },
231
+ { name: "angular-component-harnesses: support for Angular component test harnesses\n > https://www.npmjs.com/package/@badisi/wdio-harness", value: "@badisi/wdio-harness$--$harness" },
232
+ { 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" }
233
+ ],
234
+ service: [
235
+ // internal or community driver services
236
+ { name: "visual", value: "@wdio/visual-service$--$visual" },
237
+ { name: "vite", value: "wdio-vite-service$--$vite" },
238
+ { name: "nuxt", value: "wdio-nuxt-service$--$nuxt" },
239
+ { name: "firefox-profile", value: "@wdio/firefox-profile-service$--$firefox-profile" },
240
+ { name: "gmail", value: "wdio-gmail-service$--$gmail" },
241
+ { name: "sauce", value: "@wdio/sauce-service$--$sauce" },
242
+ { name: "testingbot", value: "@wdio/testingbot-service$--$testingbot" },
243
+ { name: "browserstack", value: "@wdio/browserstack-service$--$browserstack" },
244
+ { name: "lighthouse", value: "@wdio/lighthouse-service$--$lighthouse" },
245
+ { name: "vscode", value: "wdio-vscode-service$--$vscode" },
246
+ { name: "electron", value: "wdio-electron-service$--$electron" },
247
+ { name: "appium", value: "@wdio/appium-service$--$appium" },
248
+ // external
249
+ { name: "eslinter-service", value: "wdio-eslinter-service$--$eslinter" },
250
+ { name: "lambdatest", value: "wdio-lambdatest-service$--$lambdatest" },
251
+ { name: "zafira-listener", value: "wdio-zafira-listener-service$--$zafira-listener" },
252
+ { name: "reportportal", value: "wdio-reportportal-service$--$reportportal" },
253
+ { name: "docker", value: "wdio-docker-service$--$docker" },
254
+ { name: "ui5", value: "wdio-ui5-service$--$ui5" },
255
+ { name: "wiremock", value: "wdio-wiremock-service$--$wiremock" },
256
+ { name: "ng-apimock", value: "wdio-ng-apimock-service$--$ng-apimock" },
257
+ { name: "slack", value: "wdio-slack-service$--$slack" },
258
+ { name: "cucumber-viewport-logger", value: "wdio-cucumber-viewport-logger-service$--$cucumber-viewport-logger" },
259
+ { name: "intercept", value: "wdio-intercept-service$--$intercept" },
260
+ { name: "docker", value: "wdio-docker-service$--$docker" },
261
+ { name: "novus-visual-regression", value: "wdio-novus-visual-regression-service$--$novus-visual-regression" },
262
+ { name: "rerun", value: "wdio-rerun-service$--$rerun" },
263
+ { name: "winappdriver", value: "wdio-winappdriver-service$--$winappdriver" },
264
+ { name: "ywinappdriver", value: "wdio-ywinappdriver-service$--$ywinappdriver" },
265
+ { name: "performancetotal", value: "wdio-performancetotal-service$--$performancetotal" },
266
+ { name: "cleanuptotal", value: "wdio-cleanuptotal-service$--$cleanuptotal" },
267
+ { name: "aws-device-farm", value: "wdio-aws-device-farm-service$--$aws-device-farm" },
268
+ { name: "ms-teams", value: "wdio-ms-teams-service$--$ms-teams" },
269
+ { name: "tesults", value: "wdio-tesults-service$--$tesults" },
270
+ { name: "azure-devops", value: "@gmangiapelo/wdio-azure-devops-service$--$azure-devops" },
271
+ { name: "google-Chat", value: "wdio-google-chat-service$--$google-chat" },
272
+ { name: "qmate-service", value: "@sap_oss/wdio-qmate-service$--$qmate-service" },
273
+ { name: "robonut", value: "wdio-robonut-service$--$robonut" },
274
+ { name: "qunit", value: "wdio-qunit-service$--$qunit" },
275
+ { name: "roku", value: "wdio-roku-service$--$roku" },
276
+ { name: "obsidian", value: "wdio-obsidian-service$--$obsidian" }
277
+ ]
278
+ };
279
+ var isNuxtProject = [
280
+ path.join(process.cwd(), "nuxt.config.js"),
281
+ path.join(process.cwd(), "nuxt.config.ts"),
282
+ path.join(process.cwd(), "nuxt.config.mjs"),
283
+ path.join(process.cwd(), "nuxt.config.mts")
284
+ ].map((p) => {
285
+ try {
286
+ fs.accessSync(p);
287
+ return true;
288
+ } catch {
289
+ return false;
290
+ }
291
+ }).some(Boolean);
292
+ function usesSerenity(answers) {
293
+ return answers.framework.includes("serenity-js");
294
+ }
295
+ var ProtocolOptions = /* @__PURE__ */ ((ProtocolOptions2) => {
296
+ ProtocolOptions2["HTTPS"] = "https";
297
+ ProtocolOptions2["HTTP"] = "http";
298
+ return ProtocolOptions2;
299
+ })(ProtocolOptions || {});
300
+ var BackendChoice = /* @__PURE__ */ ((BackendChoice2) => {
301
+ BackendChoice2["Local"] = "On my local machine";
302
+ BackendChoice2["Experitest"] = "In the cloud using Experitest";
303
+ BackendChoice2["Saucelabs"] = "In the cloud using Sauce Labs";
304
+ BackendChoice2["Browserstack"] = "In the cloud using BrowserStack";
305
+ BackendChoice2["OtherVendors"] = "In the cloud using Testingbot or LambdaTest or a different service";
306
+ BackendChoice2["Grid"] = "I have my own Selenium cloud";
307
+ return BackendChoice2;
308
+ })(BackendChoice || {});
309
+ var RegionOptions = /* @__PURE__ */ ((RegionOptions2) => {
310
+ RegionOptions2["US"] = "us";
311
+ RegionOptions2["EU"] = "eu";
312
+ return RegionOptions2;
313
+ })(RegionOptions || {});
314
+ var ElectronBuildToolChoice = /* @__PURE__ */ ((ElectronBuildToolChoice2) => {
315
+ ElectronBuildToolChoice2["ElectronForge"] = "Electron Forge (https://www.electronforge.io/)";
316
+ ElectronBuildToolChoice2["ElectronBuilder"] = "electron-builder (https://www.electron.build/)";
317
+ ElectronBuildToolChoice2["SomethingElse"] = "Something else";
318
+ return ElectronBuildToolChoice2;
319
+ })(ElectronBuildToolChoice || {});
320
+ var SUPPORTED_BROWSER_RUNNER_PRESETS = [
321
+ { name: "Lit (https://lit.dev/)", value: "$--$" },
322
+ { name: "Vue.js (https://vuejs.org/)", value: "@vitejs/plugin-vue$--$vue" },
323
+ { name: "Svelte (https://svelte.dev/)", value: "@sveltejs/vite-plugin-svelte$--$svelte" },
324
+ { name: "SolidJS (https://www.solidjs.com/)", value: "vite-plugin-solid$--$solid" },
325
+ { name: "StencilJS (https://stenciljs.com/)", value: "$--$stencil" },
326
+ { name: "React (https://reactjs.org/)", value: "@vitejs/plugin-react$--$react" },
327
+ { name: "Preact (https://preactjs.com/)", value: "@preact/preset-vite$--$preact" },
328
+ { name: "Other", value: null }
329
+ ];
330
+ function isBrowserRunner(answers) {
331
+ return answers.runner === SUPPORTED_PACKAGES.runner[1].value;
332
+ }
333
+ function getTestingPurpose(answers) {
334
+ return convertPackageHashToObject(answers.runner).purpose;
335
+ }
336
+ var TESTING_LIBRARY_PACKAGES = {
337
+ react: "@testing-library/react",
338
+ preact: "@testing-library/preact",
339
+ vue: "@testing-library/vue",
340
+ svelte: "@testing-library/svelte",
341
+ solid: "solid-testing-library"
342
+ };
343
+ var E2E_ENVIRONMENTS = [
344
+ { name: "Web - web applications in the browser", value: "web" },
345
+ { name: "Mobile - native, hybrid and mobile web apps, on Android or iOS", value: "mobile" }
346
+ ];
347
+ var MOBILE_ENVIRONMENTS = [
348
+ { 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" },
349
+ { name: "iOS - applications on iOS, iPadOS, and tvOS\n > using XCTest (https://appium.github.io/appium-xcuitest-driver)", value: "ios" }
350
+ ];
351
+ var BROWSER_ENVIRONMENTS = [
352
+ { name: "Chrome", value: "chrome", checked: true },
353
+ { name: "Firefox", value: "firefox" },
354
+ { name: "Safari", value: "safari" },
355
+ { name: "Microsoft Edge", value: "MicrosoftEdge" }
356
+ ];
357
+ function selectDefaultService(serviceNames) {
358
+ serviceNames = Array.isArray(serviceNames) ? serviceNames : [serviceNames];
359
+ return SUPPORTED_PACKAGES.service.filter(({ name }) => serviceNames.includes(name)).map(({ value }) => value);
360
+ }
361
+ function prioServiceOrderFor(serviceNamesParam) {
362
+ const serviceNames = Array.isArray(serviceNamesParam) ? serviceNamesParam : [serviceNamesParam];
363
+ let services = SUPPORTED_PACKAGES.service;
364
+ for (const serviceName of serviceNames) {
365
+ const index = services.findIndex(({ name }) => name === serviceName);
366
+ services = [services[index], ...services.slice(0, index), ...services.slice(index + 1)];
367
+ }
368
+ return services;
369
+ }
370
+ var QUESTIONNAIRE = [{
371
+ type: "list",
372
+ name: "runner",
373
+ message: "What type of testing would you like to do?",
374
+ choices: SUPPORTED_PACKAGES.runner
375
+ }, {
376
+ type: "list",
377
+ name: "preset",
378
+ message: "Which framework do you use for building components?",
379
+ choices: SUPPORTED_BROWSER_RUNNER_PRESETS,
380
+ // only ask if there are more than 1 runner to pick from
381
+ when: (
382
+ /* istanbul ignore next */
383
+ isBrowserRunner
384
+ )
385
+ }, {
386
+ type: "confirm",
387
+ name: "installTestingLibrary",
388
+ message: "Do you like to use Testing Library (https://testing-library.com/) as test utility?",
389
+ default: true,
390
+ // only ask if there are more than 1 runner to pick from
391
+ when: (
392
+ /* istanbul ignore next */
393
+ (answers) => isBrowserRunner(answers) && /**
394
+ * Only show if Testing Library has an add-on for framework
14
395
  */
15
- if (!(process.argv.includes('--version') || process.argv.includes('-v'))) {
16
- console.log(ASCII_ROBOT, PROGRAM_TITLE);
396
+ answers.preset && TESTING_LIBRARY_PACKAGES[convertPackageHashToObject(answers.preset).short]
397
+ )
398
+ }, {
399
+ type: "list",
400
+ name: "electronBuildTool",
401
+ message: "Which tool are you using to build your Electron app?",
402
+ choices: Object.values(ElectronBuildToolChoice),
403
+ when: (
404
+ /* instanbul ignore next */
405
+ (answers) => getTestingPurpose(answers) === "electron"
406
+ )
407
+ }, {
408
+ type: "input",
409
+ name: "electronAppBinaryPath",
410
+ message: "What is the path to the binary of your built Electron app?",
411
+ when: (
412
+ /* istanbul ignore next */
413
+ (answers) => getTestingPurpose(answers) === "electron" && answers.electronBuildTool === "Something else" /* SomethingElse */
414
+ )
415
+ }, {
416
+ type: "list",
417
+ name: "backend",
418
+ message: "Where is your automation backend located?",
419
+ choices: Object.values(BackendChoice),
420
+ when: (
421
+ /* instanbul ignore next */
422
+ (answers) => getTestingPurpose(answers) === "e2e"
423
+ )
424
+ }, {
425
+ type: "list",
426
+ name: "e2eEnvironment",
427
+ message: "Which environment you would like to automate?",
428
+ choices: E2E_ENVIRONMENTS,
429
+ default: "web",
430
+ when: (
431
+ /* istanbul ignore next */
432
+ (answers) => getTestingPurpose(answers) === "e2e"
433
+ )
434
+ }, {
435
+ type: "list",
436
+ name: "mobileEnvironment",
437
+ message: "Which mobile environment you'd like to automate?",
438
+ choices: MOBILE_ENVIRONMENTS,
439
+ when: (
440
+ /* instanbul ignore next */
441
+ (answers) => getTestingPurpose(answers) === "e2e" && answers.e2eEnvironment === "mobile"
442
+ )
443
+ }, {
444
+ type: "checkbox",
445
+ name: "browserEnvironment",
446
+ message: "With which browser should we start?",
447
+ choices: BROWSER_ENVIRONMENTS,
448
+ when: (
449
+ /* instanbul ignore next */
450
+ (answers) => getTestingPurpose(answers) === "e2e" && answers.e2eEnvironment === "web"
451
+ )
452
+ }, {
453
+ type: "input",
454
+ name: "hostname",
455
+ message: "What is the host address of that cloud service?",
456
+ when: (
457
+ /* istanbul ignore next */
458
+ (answers) => answers.backend && answers.backend.indexOf("different service") > -1
459
+ )
460
+ }, {
461
+ type: "input",
462
+ name: "port",
463
+ message: "What is the port on which that service is running?",
464
+ default: "80",
465
+ when: (
466
+ /* istanbul ignore next */
467
+ (answers) => answers.backend && answers.backend.indexOf("different service") > -1
468
+ )
469
+ }, {
470
+ type: "input",
471
+ name: "expEnvAccessKey",
472
+ message: "Access key from Experitest Cloud",
473
+ default: "EXPERITEST_ACCESS_KEY",
474
+ when: (
475
+ /* istanbul ignore next */
476
+ (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */
477
+ )
478
+ }, {
479
+ type: "input",
480
+ name: "expEnvHostname",
481
+ message: "Environment variable for cloud url",
482
+ default: "example.experitest.com",
483
+ when: (
484
+ /* istanbul ignore next */
485
+ (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */
486
+ )
487
+ }, {
488
+ type: "input",
489
+ name: "expEnvPort",
490
+ message: "Environment variable for port",
491
+ default: "443",
492
+ when: (
493
+ /* istanbul ignore next */
494
+ (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */
495
+ )
496
+ }, {
497
+ type: "list",
498
+ name: "expEnvProtocol",
499
+ message: "Choose a protocol for environment variable",
500
+ default: "https" /* HTTPS */,
501
+ choices: Object.values(ProtocolOptions),
502
+ when: (
503
+ /* istanbul ignore next */
504
+ (answers) => answers.backend === "In the cloud using Experitest" /* Experitest */ && answers.expEnvPort !== "80" && answers.expEnvPort !== "443"
505
+ )
506
+ }, {
507
+ type: "input",
508
+ name: "env_user",
509
+ message: "Environment variable for username",
510
+ default: "LT_USERNAME",
511
+ when: (
512
+ /* istanbul ignore next */
513
+ (answers) => answers.backend && answers.backend.indexOf("LambdaTest") > -1 && answers.hostname.indexOf("lambdatest.com") > -1
514
+ )
515
+ }, {
516
+ type: "input",
517
+ name: "env_key",
518
+ message: "Environment variable for access key",
519
+ default: "LT_ACCESS_KEY",
520
+ when: (
521
+ /* istanbul ignore next */
522
+ (answers) => answers.backend && answers.backend.indexOf("LambdaTest") > -1 && answers.hostname.indexOf("lambdatest.com") > -1
523
+ )
524
+ }, {
525
+ type: "input",
526
+ name: "env_user",
527
+ message: "Environment variable for username",
528
+ default: "BROWSERSTACK_USERNAME",
529
+ when: (
530
+ /* istanbul ignore next */
531
+ (answers) => answers.backend === "In the cloud using BrowserStack" /* Browserstack */
532
+ )
533
+ }, {
534
+ type: "input",
535
+ name: "env_key",
536
+ message: "Environment variable for access key",
537
+ default: "BROWSERSTACK_ACCESS_KEY",
538
+ when: (
539
+ /* istanbul ignore next */
540
+ (answers) => answers.backend === "In the cloud using BrowserStack" /* Browserstack */
541
+ )
542
+ }, {
543
+ type: "input",
544
+ name: "env_user",
545
+ message: "Environment variable for username",
546
+ default: "SAUCE_USERNAME",
547
+ when: (
548
+ /* istanbul ignore next */
549
+ (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */
550
+ )
551
+ }, {
552
+ type: "input",
553
+ name: "env_key",
554
+ message: "Environment variable for access key",
555
+ default: "SAUCE_ACCESS_KEY",
556
+ when: (
557
+ /* istanbul ignore next */
558
+ (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */
559
+ )
560
+ }, {
561
+ type: "list",
562
+ name: "region",
563
+ message: "In which region do you want to run your Sauce Labs tests in?",
564
+ choices: Object.values(RegionOptions),
565
+ when: (
566
+ /* istanbul ignore next */
567
+ (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */
568
+ )
569
+ }, {
570
+ type: "confirm",
571
+ name: "useSauceConnect",
572
+ 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",
573
+ default: isNuxtProject,
574
+ when: (
575
+ /* istanbul ignore next */
576
+ (answers) => answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */ && !isNuxtProject
577
+ )
578
+ }, {
579
+ type: "input",
580
+ name: "hostname",
581
+ message: "What is the IP or URI to your Selenium standalone or grid server?",
582
+ default: "localhost",
583
+ when: (
584
+ /* istanbul ignore next */
585
+ (answers) => answers.backend && answers.backend.toString().indexOf("own Selenium cloud") > -1
586
+ )
587
+ }, {
588
+ type: "input",
589
+ name: "port",
590
+ message: "What is the port which your Selenium standalone or grid server is running on?",
591
+ default: "4444",
592
+ when: (
593
+ /* istanbul ignore next */
594
+ (answers) => answers.backend && answers.backend.toString().indexOf("own Selenium cloud") > -1
595
+ )
596
+ }, {
597
+ type: "input",
598
+ name: "path",
599
+ message: "What is the path to your browser driver or grid server?",
600
+ default: "/",
601
+ when: (
602
+ /* istanbul ignore next */
603
+ (answers) => answers.backend && answers.backend.toString().indexOf("own Selenium cloud") > -1
604
+ )
605
+ }, {
606
+ type: "list",
607
+ name: "framework",
608
+ message: "Which framework do you want to use?",
609
+ choices: (
610
+ /* instanbul ignore next */
611
+ (answers) => {
612
+ if (isBrowserRunner(answers)) {
613
+ return SUPPORTED_PACKAGES.framework.slice(0, 1);
614
+ }
615
+ if (getTestingPurpose(answers) === "electron") {
616
+ return SUPPORTED_PACKAGES.framework.filter(
617
+ ({ value }) => !value.startsWith("@serenity-js")
618
+ );
619
+ }
620
+ return SUPPORTED_PACKAGES.framework;
621
+ }
622
+ )
623
+ }, {
624
+ type: "confirm",
625
+ name: "isUsingTypeScript",
626
+ message: "Do you want to use Typescript to write tests?",
627
+ when: (
628
+ /* istanbul ignore next */
629
+ (answers) => {
630
+ if (answers.preset?.includes("stencil")) {
631
+ return false;
632
+ }
633
+ return true;
634
+ }
635
+ ),
636
+ default: (
637
+ /* istanbul ignore next */
638
+ (answers) => answers.preset?.includes("stencil") || detectCompiler(answers)
639
+ )
640
+ }, {
641
+ type: "confirm",
642
+ name: "generateTestFiles",
643
+ message: "Do you want WebdriverIO to autogenerate some test files?",
644
+ default: true,
645
+ when: (
646
+ /* istanbul ignore next */
647
+ (answers) => {
648
+ if (["vscode", "electron", "macos"].includes(getTestingPurpose(answers)) && answers.framework.includes("cucumber")) {
649
+ return false;
650
+ }
651
+ return true;
17
652
  }
18
- /**
19
- * ensure right Node.js version is used
653
+ )
654
+ }, {
655
+ type: "input",
656
+ name: "specs",
657
+ message: "What should be the location of your spec files?",
658
+ default: (
659
+ /* istanbul ignore next */
660
+ (answers) => {
661
+ const pattern = isBrowserRunner(answers) ? "src/**/*.test" : "test/specs/**/*";
662
+ return getDefaultFiles(answers, pattern);
663
+ }
664
+ ),
665
+ when: (
666
+ /* istanbul ignore next */
667
+ (answers) => answers.generateTestFiles && /(mocha|jasmine)/.test(answers.framework)
668
+ )
669
+ }, {
670
+ type: "input",
671
+ name: "specs",
672
+ message: "What should be the location of your feature files?",
673
+ default: (answers) => getDefaultFiles(answers, "features/**/*.feature"),
674
+ when: (
675
+ /* istanbul ignore next */
676
+ (answers) => answers.generateTestFiles && answers.framework.includes("cucumber")
677
+ )
678
+ }, {
679
+ type: "input",
680
+ name: "stepDefinitions",
681
+ message: "What should be the location of your step definitions?",
682
+ default: (answers) => getDefaultFiles(answers, "features/step-definitions/steps"),
683
+ when: (
684
+ /* istanbul ignore next */
685
+ (answers) => answers.generateTestFiles && answers.framework.includes("cucumber")
686
+ )
687
+ }, {
688
+ type: "confirm",
689
+ name: "usePageObjects",
690
+ message: "Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)?",
691
+ default: true,
692
+ when: (
693
+ /* istanbul ignore next */
694
+ (answers) => answers.generateTestFiles && /**
695
+ * page objects aren't common for component testing
696
+ */
697
+ !isBrowserRunner(answers) && /**
698
+ * and also not needed when running VS Code tests since the service comes with
699
+ * its own page object implementation, nor when running Electron or MacOS tests
20
700
  */
21
- const unsupportedNodeVersion = !semver.satisfies(process.version, '>=16');
22
- if (unsupportedNodeVersion) {
23
- console.log(chalk.yellow(UNSUPPORTED_NODE_VERSION));
24
- return;
25
- }
26
- const program = new Command(WDIO_COMMAND)
27
- .version(version, '-v, --version')
28
- .arguments('[project-path]')
29
- .usage(`${chalk.green('[project-path]')} [options]`)
30
- .action(name => (projectDir = name))
31
- .option('-t, --npm-tag <tag>', 'Which NPM version you like to install, e.g. @next', DEFAULT_NPM_TAG)
32
- .option('-u, --use-yarn', 'Use Yarn package manager to install packages', false)
33
- .option('-v, --verbose', 'print additional logs')
34
- .option('-y, --yes', 'will fill in all config defaults without prompting', false)
35
- .option('-d, --dev', 'Install all packages as into devDependencies', true)
36
- .allowUnknownOption()
37
- .on('--help', () => console.log())
38
- .parse(process.argv);
39
- return operation(program.opts());
40
- }
41
- export async function createWebdriverIO(opts) {
42
- const useYarn = typeof opts.useYarn === 'boolean'
43
- ? opts.useYarn
44
- : await shouldUseYarn();
45
- const npmTag = opts.npmTag.startsWith('@') ? opts.npmTag : `@${opts.npmTag}`;
46
- const root = path.resolve(process.cwd(), projectDir || '');
47
- const rootDirExists = await fs.access(root).then(() => true, () => false);
48
- if (!rootDirExists) {
49
- await fs.mkdir(root, { recursive: true });
50
- }
51
- console.log(`\nInstalling ${chalk.bold('@wdio/cli')} to initialize project.`);
52
- const logLevel = opts.verbose ? 'trace' : 'error';
53
- const command = useYarn ? 'yarnpkg' : 'npm';
54
- const args = useYarn
55
- ? ['add', ...(opts.dev ? ['-D'] : []), '--exact', '--cwd', root, `@wdio/cli${npmTag}`]
56
- : ['install', opts.dev ? '--save-dev' : '--save', '--loglevel', logLevel, `@wdio/cli${npmTag}`];
57
- await runProgram(command, args, { cwd: root, stdio: 'ignore' });
701
+ !["vscode", "electron", "macos"].includes(getTestingPurpose(answers)) && /**
702
+ * Serenity/JS generates Lean Page Objects by default, so there's no need to ask about it
703
+ * See https://serenity-js.org/handbook/web-testing/page-objects-pattern/
704
+ */
705
+ !usesSerenity(answers)
706
+ )
707
+ }, {
708
+ type: "input",
709
+ name: "pages",
710
+ message: "Where are your page objects located?",
711
+ default: (
712
+ /* istanbul ignore next */
713
+ (answers) => answers.framework.match(/(mocha|jasmine)/) ? getDefaultFiles(answers, "test/pageobjects/**/*") : getDefaultFiles(answers, "features/pageobjects/**/*")
714
+ ),
715
+ when: (
716
+ /* istanbul ignore next */
717
+ (answers) => answers.generateTestFiles && answers.usePageObjects
718
+ )
719
+ }, {
720
+ type: "input",
721
+ name: "serenityLibPath",
722
+ message: "What should be the location of your Serenity/JS Screenplay Pattern library?",
723
+ default: (
724
+ /* istanbul ignore next */
725
+ async (answers) => {
726
+ const projectRootDir = await getProjectRoot(answers);
727
+ const specsDir = path.resolve(projectRootDir, path.dirname(answers.specs || "").replace(/\*\*$/, ""));
728
+ return path.resolve(specsDir, "..", "serenity");
729
+ }
730
+ ),
731
+ when: (
732
+ /* istanbul ignore next */
733
+ (answers) => answers.generateTestFiles && usesSerenity(answers)
734
+ )
735
+ }, {
736
+ type: "checkbox",
737
+ name: "reporters",
738
+ message: "Which reporter do you want to use?",
739
+ choices: SUPPORTED_PACKAGES.reporter
740
+ }, {
741
+ type: "checkbox",
742
+ name: "plugins",
743
+ message: "Do you want to add a plugin to your test setup?",
744
+ choices: SUPPORTED_PACKAGES.plugin,
745
+ default: []
746
+ }, {
747
+ type: "confirm",
748
+ name: "includeVisualTesting",
749
+ message: "Would you like to include Visual Testing to your setup? For more information see https://webdriver.io/docs/visual-testing!",
750
+ default: false,
751
+ when: (
752
+ /* istanbul ignore next */
753
+ (answers) => {
754
+ return ["e2e", "component"].includes(getTestingPurpose(answers));
755
+ }
756
+ )
757
+ }, {
758
+ type: "checkbox",
759
+ name: "services",
760
+ message: "Do you want to add a service to your test setup?",
761
+ choices: (answers) => {
762
+ const services = [];
763
+ if (answers.backend === "In the cloud using BrowserStack" /* Browserstack */) {
764
+ services.push("browserstack");
765
+ } else if (answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */) {
766
+ services.push("sauce");
767
+ }
768
+ if (answers.e2eEnvironment === "mobile") {
769
+ services.push("appium");
770
+ }
771
+ if (getTestingPurpose(answers) === "e2e" && isNuxtProject) {
772
+ services.push("nuxt");
773
+ }
774
+ if (getTestingPurpose(answers) === "vscode") {
775
+ return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "vscode")];
776
+ } else if (getTestingPurpose(answers) === "electron") {
777
+ return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "electron")];
778
+ } else if (getTestingPurpose(answers) === "macos") {
779
+ return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "appium")];
780
+ } else if (getTestingPurpose(answers) === "roku") {
781
+ return [SUPPORTED_PACKAGES.service.find(({ name }) => name === "roku")];
782
+ }
783
+ return prioServiceOrderFor(services);
784
+ },
785
+ default: (answers) => {
786
+ const defaultServices = [];
787
+ if (answers.backend === "In the cloud using BrowserStack" /* Browserstack */) {
788
+ defaultServices.push("browserstack");
789
+ } else if (answers.backend === "In the cloud using Sauce Labs" /* Saucelabs */) {
790
+ defaultServices.push("sauce");
791
+ }
792
+ if (answers.e2eEnvironment === "mobile" || getTestingPurpose(answers) === "macos") {
793
+ defaultServices.push("appium");
794
+ }
795
+ if (getTestingPurpose(answers) === "vscode") {
796
+ defaultServices.push("vscode");
797
+ } else if (getTestingPurpose(answers) === "electron") {
798
+ defaultServices.push("electron");
799
+ } else if (getTestingPurpose(answers) === "roku") {
800
+ defaultServices.push("roku");
801
+ }
802
+ if (isNuxtProject) {
803
+ defaultServices.push("nuxt");
804
+ }
805
+ if (answers.includeVisualTesting) {
806
+ defaultServices.push("visual");
807
+ }
808
+ return selectDefaultService(defaultServices);
809
+ }
810
+ }, {
811
+ type: "input",
812
+ name: "outputDir",
813
+ message: "In which directory should the xunit reports get stored?",
814
+ default: "./",
815
+ when: (
816
+ /* istanbul ignore next */
817
+ (answers) => answers.reporters.includes("junit")
818
+ )
819
+ }, {
820
+ type: "input",
821
+ name: "outputDir",
822
+ message: "In which directory should the json reports get stored?",
823
+ default: "./",
824
+ when: (
825
+ /* istanbul ignore next */
826
+ (answers) => answers.reporters.includes("json")
827
+ )
828
+ }, {
829
+ type: "input",
830
+ name: "outputDir",
831
+ message: "In which directory should the mochawesome json reports get stored?",
832
+ default: "./",
833
+ when: (
834
+ /* istanbul ignore next */
835
+ (answers) => answers.reporters.includes("mochawesome")
836
+ )
837
+ }, {
838
+ type: "confirm",
839
+ name: "npmInstall",
840
+ message: () => `Do you want me to run \`${detectPackageManager()} install\``,
841
+ default: true
842
+ }];
843
+
844
+ // src/utils.ts
845
+ import chalk2 from "chalk";
846
+
847
+ // src/install.ts
848
+ import { execa } from "execa";
849
+
850
+ // src/utils.ts
851
+ var NPM_COMMAND = /^win/.test(process.platform) ? "npm.cmd" : "npm";
852
+ var __dirname = path2.dirname(url.fileURLToPath(import.meta.url));
853
+ process.on("SIGINT", () => printAndExit(void 0, "SIGINT"));
854
+ var TEMPLATE_ROOT_DIR = path2.join(__dirname, "templates", "exampleFiles");
855
+ function runProgram(command, args, options) {
856
+ const child = spawn(command, args, { stdio: "inherit", ...options });
857
+ return new Promise((resolve2, rejects) => {
858
+ let error;
859
+ child.on("error", (e) => error = e);
860
+ child.on("close", (code, signal) => {
861
+ if (code !== 0) {
862
+ const errorMessage = error && error.message || `Error calling: ${command} ${args.join(" ")}`;
863
+ printAndExit(errorMessage, signal);
864
+ return rejects(errorMessage);
865
+ }
866
+ resolve2();
867
+ });
868
+ });
869
+ }
870
+ async function getPackageVersion() {
871
+ try {
872
+ const pkgJsonPath = path2.join(__dirname, "..", "package.json");
873
+ const pkg = JSON.parse((await fs2.readFile(pkgJsonPath)).toString());
874
+ return `v${pkg.version}`;
875
+ } catch {
876
+ }
877
+ return "unknown";
878
+ }
879
+ function printAndExit(error, signal) {
880
+ if (signal === "SIGINT") {
881
+ console.log("\n\nGoodbye \u{1F44B}");
882
+ } else {
883
+ console.log(`
884
+
885
+ \u26A0\uFE0F Ups, something went wrong${error ? `: ${error}` : ""}!`);
886
+ }
887
+ process.exit(1);
888
+ }
889
+ function convertPackageHashToObject(pkg, hash = "$--$") {
890
+ const [p, short, purpose] = pkg.split(hash);
891
+ return { package: p, short, purpose };
892
+ }
893
+ async function getProjectProps(cwd = process.cwd()) {
894
+ try {
895
+ const { packageJson, path: packageJsonPath } = await readPackageUp({ cwd }) || {};
896
+ if (!packageJson || !packageJsonPath) {
897
+ return void 0;
898
+ }
899
+ return {
900
+ esmSupported: packageJson.type === "module" || typeof packageJson.module === "string",
901
+ packageJson,
902
+ path: path2.dirname(packageJsonPath)
903
+ };
904
+ } catch {
905
+ return void 0;
906
+ }
907
+ }
908
+ async function getProjectRoot(parsedAnswers) {
909
+ if (parsedAnswers?.createPackageJSON && parsedAnswers.projectRoot) {
910
+ return parsedAnswers.projectRoot;
911
+ }
912
+ const root = (await getProjectProps())?.path;
913
+ if (!root) {
914
+ throw new Error("Could not find project root directory with a package.json");
915
+ }
916
+ return !parsedAnswers || parsedAnswers.projectRootCorrect ? root : parsedAnswers.projectRoot || process.cwd();
917
+ }
918
+ var renderFile = promisify(ejs.renderFile);
919
+ function detectPackageManager() {
920
+ if (!process.env.npm_config_user_agent) {
921
+ return "npm";
922
+ }
923
+ const detectedPM = process.env.npm_config_user_agent.split("/")[0].toLowerCase();
924
+ const matchedPM = SUPPORTED_PACKAGE_MANAGERS.find((pm) => pm.toLowerCase() === detectedPM);
925
+ return matchedPM || "npm";
926
+ }
927
+ async function getDefaultFiles(answers, pattern) {
928
+ const rootDir = await getProjectRoot(answers);
929
+ const presetPackage = convertPackageHashToObject(answers.preset || "");
930
+ const isJSX = TSX_BASED_FRAMEWORKS.includes(presetPackage.short || "");
931
+ 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" : ""}`;
932
+ return val;
933
+ }
934
+ var TSX_BASED_FRAMEWORKS = ["react", "preact", "solid", "stencil"];
935
+ async function detectCompiler(answers) {
936
+ if (answers.createPackageJSON) {
937
+ return false;
938
+ }
939
+ const root = await getProjectRoot(answers);
940
+ const hasRootTSConfig = await fs2.access(path2.resolve(root, "tsconfig.json")).then(() => true, () => false);
941
+ return hasRootTSConfig;
942
+ }
943
+
944
+ // src/index.ts
945
+ var WDIO_COMMAND = "wdio";
946
+ var projectDir;
947
+ async function run(operation = createWebdriverIO) {
948
+ const version = await getPackageVersion();
949
+ if (!(process.argv.includes("--version") || process.argv.includes("-v"))) {
950
+ console.log(ASCII_ROBOT, PROGRAM_TITLE);
951
+ }
952
+ const unsupportedNodeVersion = !semver.satisfies(process.version, ">=18.18.0");
953
+ if (unsupportedNodeVersion) {
954
+ console.log(chalk3.yellow(UNSUPPORTED_NODE_VERSION));
955
+ return;
956
+ }
957
+ const program = new Command(WDIO_COMMAND).version(version, "-v, --version").arguments("[project-path]").usage(`${chalk3.green("[project-path]")} [options]`).action((name) => projectDir = name).option("-t, --npm-tag <tag>", "Which NPM version you like to install, e.g. @next", DEFAULT_NPM_TAG).option("-y, --yes", "will fill in all config defaults without prompting", false).option("-d, --dev", "Install all packages as into devDependencies", true).allowUnknownOption().on("--help", () => console.log()).parse(process.argv);
958
+ return operation(program.opts());
959
+ }
960
+ function detectPackageManager2() {
961
+ if (!process.env.npm_config_user_agent) {
962
+ return "npm";
963
+ }
964
+ const detectedPM = process.env.npm_config_user_agent.split("/")[0].toLowerCase();
965
+ const matchedPM = SUPPORTED_PACKAGE_MANAGERS.find((pm) => pm.toLowerCase() === detectedPM);
966
+ return matchedPM || "npm";
967
+ }
968
+ async function createWebdriverIO(opts) {
969
+ const npmTag = opts.npmTag.startsWith("@") ? opts.npmTag : `@${opts.npmTag}`;
970
+ const root = path3.resolve(process.cwd(), projectDir || "");
971
+ const pm = detectPackageManager2();
972
+ const hasPackageJson = await fs3.access(path3.resolve(root, "package.json")).then(() => true).catch(() => false);
973
+ if (!hasPackageJson) {
974
+ await fs3.mkdir(root, { recursive: true });
975
+ await fs3.writeFile(path3.resolve(root, "package.json"), JSON.stringify({
976
+ name: root.substring(root.lastIndexOf(path3.sep) + 1),
977
+ type: "module"
978
+ }, null, 2));
979
+ }
980
+ const cliInstalled = await isCLIInstalled(root);
981
+ if (!cliInstalled) {
982
+ console.log(`
983
+ Installing ${chalk3.bold("@wdio/cli")} to initialize project...`);
984
+ const args = [INSTALL_COMMAND[pm]];
985
+ if (opts.dev) {
986
+ args.push(DEV_FLAG[pm]);
987
+ }
988
+ args.push(`@wdio/cli${npmTag}`);
989
+ await runProgram(pm, args, { cwd: root, stdio: "ignore" });
990
+ console.log(chalk3.green.bold("\u2714 Success!"));
991
+ }
992
+ return runProgram(EXECUTER[pm], [
993
+ EXECUTE_COMMAND[pm],
994
+ WDIO_COMMAND,
995
+ "config",
996
+ ...opts.yes ? ["--yes"] : [],
997
+ ...opts.npmTag ? ["--npm-tag", opts.npmTag] : []
998
+ ].filter((i) => !!i), { cwd: root });
999
+ }
1000
+ async function isCLIInstalled(path4) {
1001
+ try {
1002
+ resolve("@wdio/cli", pathToFileURL(path4).href);
1003
+ return true;
1004
+ } catch {
1005
+ try {
1006
+ const output = execSync2("npm ls -g", {
1007
+ encoding: "utf-8",
1008
+ stdio: ["ignore", "pipe", "ignore"]
1009
+ });
1010
+ if (output.includes("@wdio/cli")) {
1011
+ return true;
1012
+ }
1013
+ } catch {
1014
+ return false;
1015
+ }
1016
+ return false;
1017
+ }
58
1018
  }
1019
+ export {
1020
+ createWebdriverIO,
1021
+ run
1022
+ };