@wdio/cli 9.0.0-alpha.9 → 9.0.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 (86) hide show
  1. package/build/commands/config.d.ts.map +1 -1
  2. package/build/commands/repl.d.ts.map +1 -1
  3. package/build/commands/run.d.ts +14 -13
  4. package/build/commands/run.d.ts.map +1 -1
  5. package/build/constants.d.ts +83 -10
  6. package/build/constants.d.ts.map +1 -1
  7. package/build/index.cjs +46 -0
  8. package/build/index.d.cts +2 -0
  9. package/build/index.d.cts.map +1 -0
  10. package/build/index.js +3233 -4
  11. package/build/interface.d.ts +0 -1
  12. package/build/interface.d.ts.map +1 -1
  13. package/build/launcher.d.ts.map +1 -1
  14. package/build/run.d.ts.map +1 -1
  15. package/build/types.d.ts +3 -4
  16. package/build/types.d.ts.map +1 -1
  17. package/build/utils.d.ts +7 -11
  18. package/build/utils.d.ts.map +1 -1
  19. package/build/watcher.d.ts.map +1 -1
  20. package/package.json +20 -25
  21. package/build/cjs/index.d.ts +0 -2
  22. package/build/cjs/index.d.ts.map +0 -1
  23. package/build/cjs/index.js +0 -26
  24. package/build/cjs/package.json +0 -5
  25. package/build/commands/config.js +0 -197
  26. package/build/commands/index.js +0 -5
  27. package/build/commands/install.js +0 -109
  28. package/build/commands/repl.js +0 -50
  29. package/build/commands/run.js +0 -262
  30. package/build/constants.js +0 -909
  31. package/build/install.js +0 -38
  32. package/build/interface.js +0 -285
  33. package/build/launcher.js +0 -513
  34. package/build/run.js +0 -75
  35. package/build/templates/EjsHelpers.js +0 -59
  36. package/build/templates/EjsHelpers.ts +0 -84
  37. package/build/templates/exampleFiles/browser/Component.css.ejs +0 -121
  38. package/build/templates/exampleFiles/browser/Component.lit.ejs +0 -154
  39. package/build/templates/exampleFiles/browser/Component.lit.test.ejs +0 -24
  40. package/build/templates/exampleFiles/browser/Component.preact.ejs +0 -28
  41. package/build/templates/exampleFiles/browser/Component.preact.test.ejs +0 -59
  42. package/build/templates/exampleFiles/browser/Component.react.ejs +0 -29
  43. package/build/templates/exampleFiles/browser/Component.react.test.ejs +0 -58
  44. package/build/templates/exampleFiles/browser/Component.solid.ejs +0 -28
  45. package/build/templates/exampleFiles/browser/Component.solid.test.ejs +0 -58
  46. package/build/templates/exampleFiles/browser/Component.stencil.ejs +0 -43
  47. package/build/templates/exampleFiles/browser/Component.stencil.test.ejs +0 -45
  48. package/build/templates/exampleFiles/browser/Component.svelte.ejs +0 -47
  49. package/build/templates/exampleFiles/browser/Component.svelte.test.ejs +0 -58
  50. package/build/templates/exampleFiles/browser/Component.vue.ejs +0 -34
  51. package/build/templates/exampleFiles/browser/Component.vue.test.ejs +0 -62
  52. package/build/templates/exampleFiles/browser/standalone.test.ejs +0 -13
  53. package/build/templates/exampleFiles/cucumber/features/login.feature +0 -12
  54. package/build/templates/exampleFiles/cucumber/step_definitions/steps.js.ejs +0 -55
  55. package/build/templates/exampleFiles/mochaJasmine/test.e2e.js.ejs +0 -11
  56. package/build/templates/exampleFiles/pageobjects/login.page.js.ejs +0 -45
  57. package/build/templates/exampleFiles/pageobjects/page.js.ejs +0 -17
  58. package/build/templates/exampleFiles/pageobjects/secure.page.js.ejs +0 -20
  59. package/build/templates/exampleFiles/serenity-js/common/config/serenity.properties.ejs +0 -1
  60. package/build/templates/exampleFiles/serenity-js/common/serenity/github-api/GitHubStatus.ts.ejs +0 -41
  61. package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoList.ts.ejs +0 -100
  62. package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoListItem.ts.ejs +0 -36
  63. package/build/templates/exampleFiles/serenity-js/cucumber/step-definitions/steps.ts.ejs +0 -37
  64. package/build/templates/exampleFiles/serenity-js/cucumber/support/parameter.config.ts.ejs +0 -18
  65. package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/completing_items.feature.ejs +0 -23
  66. package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/narrative.md.ejs +0 -17
  67. package/build/templates/exampleFiles/serenity-js/jasmine/example.spec.ts.ejs +0 -86
  68. package/build/templates/exampleFiles/serenity-js/mocha/example.spec.ts.ejs +0 -88
  69. package/build/templates/snippets/afterTest.ejs +0 -20
  70. package/build/templates/snippets/capabilities.ejs +0 -57
  71. package/build/templates/snippets/cucumber.ejs +0 -50
  72. package/build/templates/snippets/electronTest.js.ejs +0 -7
  73. package/build/templates/snippets/jasmine.ejs +0 -20
  74. package/build/templates/snippets/macosTest.js.ejs +0 -11
  75. package/build/templates/snippets/mocha.ejs +0 -14
  76. package/build/templates/snippets/reporters.ejs +0 -14
  77. package/build/templates/snippets/serenity.ejs +0 -18
  78. package/build/templates/snippets/services.ejs +0 -18
  79. package/build/templates/snippets/testWithPO.js.ejs +0 -22
  80. package/build/templates/snippets/testWithoutPO.js.ejs +0 -19
  81. package/build/templates/snippets/vscodeTest.js.ejs +0 -9
  82. package/build/templates/wdio.conf.tpl.ejs +0 -422
  83. package/build/types.js +0 -1
  84. package/build/utils.js +0 -930
  85. package/build/watcher.js +0 -156
  86. /package/{LICENSE-MIT → LICENSE} +0 -0
@@ -1,909 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { createRequire } from 'node:module';
4
- import { HOOK_DEFINITION } from '@wdio/utils';
5
- import { detectCompiler, getDefaultFiles, convertPackageHashToObject, getProjectRoot, detectPackageManager, } from './utils.js';
6
- const require = createRequire(import.meta.url);
7
- export const pkg = require('../package.json');
8
- export const CLI_EPILOGUE = `Documentation: https://webdriver.io\n@wdio/cli (v${pkg.version})`;
9
- export const CONFIG_HELPER_INTRO = `
10
- ===============================
11
- 🤖 WDIO Configuration Wizard 🧙
12
- ===============================
13
- `;
14
- export const PMs = ['npm', 'yarn', 'pnpm', 'bun'];
15
- export const SUPPORTED_CONFIG_FILE_EXTENSION = ['js', 'ts', 'mjs', 'mts', 'cjs', 'cts'];
16
- export const configHelperSuccessMessage = ({ projectRootDir, runScript, extraInfo = '' }) => `
17
- 🤖 Successfully setup project at ${projectRootDir} 🎉
18
-
19
- Join our Discord Community Server and instantly find answers to your issues or queries. Or just join and say hi 👋!
20
- 🔗 https://discord.webdriver.io
21
-
22
- Visit the project on GitHub to report bugs 🐛 or raise feature requests 💡:
23
- 🔗 https://github.com/webdriverio/webdriverio
24
- ${extraInfo}
25
- To run your tests, execute:
26
- $ cd ${projectRootDir}
27
- $ npm run ${runScript}
28
- `;
29
- export const CONFIG_HELPER_SERENITY_BANNER = `
30
- Learn more about Serenity/JS:
31
- 🔗 https://serenity-js.org
32
- `;
33
- export const DEPENDENCIES_INSTALLATION_MESSAGE = `
34
- To install dependencies, execute:
35
- %s
36
- `;
37
- export const NPM_INSTALL = '';
38
- export const ANDROID_CONFIG = {
39
- platformName: 'Android',
40
- automationName: 'UiAutomator2',
41
- deviceName: 'Test'
42
- };
43
- export const IOS_CONFIG = {
44
- platformName: 'iOS',
45
- automationName: 'XCUITest',
46
- deviceName: 'iPhone Simulator'
47
- };
48
- export var CompilerOptions;
49
- (function (CompilerOptions) {
50
- CompilerOptions["Babel"] = "Babel (https://babeljs.io/)";
51
- CompilerOptions["TS"] = "TypeScript (https://www.typescriptlang.org/)";
52
- CompilerOptions["Nil"] = "No!";
53
- })(CompilerOptions || (CompilerOptions = {}));
54
- /**
55
- * We have to use a string hash for value because InquirerJS default values do not work if we have
56
- * objects as a `value` to be stored from the user's answers.
57
- */
58
- export const SUPPORTED_PACKAGES = {
59
- runner: [
60
- { name: 'E2E Testing - of Web or Mobile Applications', value: '@wdio/local-runner$--$local$--$e2e' },
61
- { name: 'Component or Unit Testing - in the browser\n > https://webdriver.io/docs/component-testing', value: '@wdio/browser-runner$--$browser$--$component' },
62
- { name: 'Desktop Testing - of Electron Applications\n > https://webdriver.io/docs/desktop-testing/electron', value: '@wdio/local-runner$--$local$--$electron' },
63
- { name: 'Desktop Testing - of MacOS Applications\n > https://webdriver.io/docs/desktop-testing/macos', value: '@wdio/local-runner$--$local$--$macos' },
64
- { name: 'VS Code Extension Testing\n > https://webdriver.io/docs/vscode-extension-testing', value: '@wdio/local-runner$--$local$--$vscode' }
65
- ],
66
- framework: [
67
- { name: 'Mocha (https://mochajs.org/)', value: '@wdio/mocha-framework$--$mocha' },
68
- { name: 'Mocha with Serenity/JS (https://serenity-js.org/)', value: '@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$mocha' },
69
- { name: 'Jasmine (https://jasmine.github.io/)', value: '@wdio/jasmine-framework$--$jasmine' },
70
- { name: 'Jasmine with Serenity/JS (https://serenity-js.org/)', value: '@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$jasmine' },
71
- { name: 'Cucumber (https://cucumber.io/)', value: '@wdio/cucumber-framework$--$cucumber' },
72
- { name: 'Cucumber with Serenity/JS (https://serenity-js.org/)', value: '@serenity-js/webdriverio$--$@serenity-js/webdriverio$--$cucumber' },
73
- ],
74
- reporter: [
75
- { name: 'spec', value: '@wdio/spec-reporter$--$spec' },
76
- { name: 'dot', value: '@wdio/dot-reporter$--$dot' },
77
- { name: 'junit', value: '@wdio/junit-reporter$--$junit' },
78
- { name: 'allure', value: '@wdio/allure-reporter$--$allure' },
79
- { name: 'sumologic', value: '@wdio/sumologic-reporter$--$sumologic' },
80
- { name: 'concise', value: '@wdio/concise-reporter$--$concise' },
81
- { name: 'json', value: '@wdio/json-reporter$--$json' },
82
- // external
83
- { name: 'reportportal', value: 'wdio-reportportal-reporter$--$reportportal' },
84
- { name: 'video', value: 'wdio-video-reporter$--$video' },
85
- { name: 'cucumber-json', value: 'wdio-cucumberjs-json-reporter$--$cucumberjs-json' },
86
- { name: 'mochawesome', value: 'wdio-mochawesome-reporter$--$mochawesome' },
87
- { name: 'timeline', value: 'wdio-timeline-reporter$--$timeline' },
88
- { name: 'html-nice', value: 'wdio-html-nice-reporter$--$html-nice' },
89
- { name: 'slack', value: '@moroo/wdio-slack-reporter$--$slack' },
90
- { name: 'teamcity', value: 'wdio-teamcity-reporter$--$teamcity' },
91
- { name: 'delta', value: '@delta-reporter/wdio-delta-reporter-service$--$delta' },
92
- { name: 'testrail', value: '@wdio/testrail-reporter$--$testrail' },
93
- { name: 'light', value: 'wdio-light-reporter$--$light' }
94
- ],
95
- plugin: [
96
- { 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' },
97
- { name: 'angular-component-harnesses: support for Angular component test harnesses\n > https://www.npmjs.com/package/@badisi/wdio-harness', value: '@badisi/wdio-harness$--$harness' },
98
- { 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' }
99
- ],
100
- service: [
101
- // internal or community driver services
102
- { name: 'visual', value: '@wdio/visual-service$--$visual' },
103
- { name: 'vite', value: 'wdio-vite-service$--$vite' },
104
- { name: 'nuxt', value: 'wdio-nuxt-service$--$nuxt' },
105
- { name: 'firefox-profile', value: '@wdio/firefox-profile-service$--$firefox-profile' },
106
- { name: 'gmail', value: 'wdio-gmail-service$--$gmail' },
107
- { name: 'sauce', value: '@wdio/sauce-service$--$sauce' },
108
- { name: 'testingbot', value: '@wdio/testingbot-service$--$testingbot' },
109
- { name: 'browserstack', value: '@wdio/browserstack-service$--$browserstack' },
110
- { name: 'devtools', value: '@wdio/devtools-service$--$devtools' },
111
- { name: 'vscode', value: 'wdio-vscode-service$--$vscode' },
112
- { name: 'electron', value: 'wdio-electron-service$--$electron' },
113
- { name: 'appium', value: '@wdio/appium-service$--$appium' },
114
- // external
115
- { name: 'eslinter-service', value: 'wdio-eslinter-service$--$eslinter' },
116
- { name: 'lambdatest', value: 'wdio-lambdatest-service$--$lambdatest' },
117
- { name: 'zafira-listener', value: 'wdio-zafira-listener-service$--$zafira-listener' },
118
- { name: 'reportportal', value: 'wdio-reportportal-service$--$reportportal' },
119
- { name: 'docker', value: 'wdio-docker-service$--$docker' },
120
- { name: 'ui5', value: 'wdio-ui5-service$--$ui5' },
121
- { name: 'wiremock', value: 'wdio-wiremock-service$--$wiremock' },
122
- { name: 'ng-apimock', value: 'wdio-ng-apimock-service$--$ng-apimock' },
123
- { name: 'slack', value: 'wdio-slack-service$--$slack' },
124
- { name: 'cucumber-viewport-logger', value: 'wdio-cucumber-viewport-logger-service$--$cucumber-viewport-logger' },
125
- { name: 'intercept', value: 'wdio-intercept-service$--$intercept' },
126
- { name: 'docker', value: 'wdio-docker-service$--$docker' },
127
- { name: 'novus-visual-regression', value: 'wdio-novus-visual-regression-service$--$novus-visual-regression' },
128
- { name: 'rerun', value: 'wdio-rerun-service$--$rerun' },
129
- { name: 'winappdriver', value: 'wdio-winappdriver-service$--$winappdriver' },
130
- { name: 'ywinappdriver', value: 'wdio-ywinappdriver-service$--$ywinappdriver' },
131
- { name: 'performancetotal', value: 'wdio-performancetotal-service$--$performancetotal' },
132
- { name: 'cleanuptotal', value: 'wdio-cleanuptotal-service$--$cleanuptotal' },
133
- { name: 'aws-device-farm', value: 'wdio-aws-device-farm-service$--$aws-device-farm' },
134
- { name: 'ocr-native-apps', value: 'wdio-ocr-service$--$ocr-native-apps' },
135
- { name: 'ms-teams', value: 'wdio-ms-teams-service$--$ms-teams' },
136
- { name: 'tesults', value: 'wdio-tesults-service$--$tesults' },
137
- { name: 'azure-devops', value: '@gmangiapelo/wdio-azure-devops-service$--$azure-devops' },
138
- { name: 'google-Chat', value: 'wdio-google-chat-service$--$google-chat' },
139
- { name: 'qmate-service', value: '@sap_oss/wdio-qmate-service$--$qmate-service' },
140
- { name: 'vitaqai', value: 'wdio-vitaqai-service$--$vitaqai' },
141
- { name: 'robonut', value: 'wdio-robonut-service$--$robonut' },
142
- { name: 'qunit', value: 'wdio-qunit-service$--$qunit' }
143
- ]
144
- };
145
- export const SUPPORTED_BROWSER_RUNNER_PRESETS = [
146
- { name: 'Lit (https://lit.dev/)', value: '$--$' },
147
- { name: 'Vue.js (https://vuejs.org/)', value: '@vitejs/plugin-vue$--$vue' },
148
- { name: 'Svelte (https://svelte.dev/)', value: '@sveltejs/vite-plugin-svelte$--$svelte' },
149
- { name: 'SolidJS (https://www.solidjs.com/)', value: 'vite-plugin-solid$--$solid' },
150
- { name: 'StencilJS (https://stenciljs.com/)', value: '$--$stencil' },
151
- { name: 'React (https://reactjs.org/)', value: '@vitejs/plugin-react$--$react' },
152
- { name: 'Preact (https://preactjs.com/)', value: '@preact/preset-vite$--$preact' },
153
- { name: 'Other', value: false }
154
- ];
155
- export const TESTING_LIBRARY_PACKAGES = {
156
- react: '@testing-library/react',
157
- preact: '@testing-library/preact',
158
- vue: '@testing-library/vue',
159
- svelte: '@testing-library/svelte',
160
- solid: 'solid-testing-library'
161
- };
162
- export var BackendChoice;
163
- (function (BackendChoice) {
164
- BackendChoice["Local"] = "On my local machine";
165
- BackendChoice["Experitest"] = "In the cloud using Experitest";
166
- BackendChoice["Saucelabs"] = "In the cloud using Sauce Labs";
167
- BackendChoice["Browserstack"] = "In the cloud using BrowserStack";
168
- BackendChoice["OtherVendors"] = "In the cloud using Testingbot or LambdaTest or a different service";
169
- BackendChoice["Grid"] = "I have my own Selenium cloud";
170
- })(BackendChoice || (BackendChoice = {}));
171
- export var ElectronBuildToolChoice;
172
- (function (ElectronBuildToolChoice) {
173
- ElectronBuildToolChoice["ElectronForge"] = "Electron Forge (https://www.electronforge.io/)";
174
- ElectronBuildToolChoice["ElectronBuilder"] = "electron-builder (https://www.electron.build/)";
175
- ElectronBuildToolChoice["SomethingElse"] = "Something else";
176
- })(ElectronBuildToolChoice || (ElectronBuildToolChoice = {}));
177
- var ProtocolOptions;
178
- (function (ProtocolOptions) {
179
- ProtocolOptions["HTTPS"] = "https";
180
- ProtocolOptions["HTTP"] = "http";
181
- })(ProtocolOptions || (ProtocolOptions = {}));
182
- export var RegionOptions;
183
- (function (RegionOptions) {
184
- RegionOptions["US"] = "us";
185
- RegionOptions["EU"] = "eu";
186
- RegionOptions["APAC"] = "apac";
187
- })(RegionOptions || (RegionOptions = {}));
188
- export const E2E_ENVIRONMENTS = [
189
- { name: 'Web - web applications in the browser', value: 'web' },
190
- { name: 'Mobile - native, hybrid and mobile web apps, on Android or iOS', value: 'mobile' }
191
- ];
192
- export const MOBILE_ENVIRONMENTS = [
193
- { 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' },
194
- { name: 'iOS - applications on iOS, iPadOS, and tvOS\n > using XCTest (https://appium.github.io/appium-xcuitest-driver)', value: 'ios' }
195
- ];
196
- export const BROWSER_ENVIRONMENTS = [
197
- { name: 'Chrome', value: 'chrome' },
198
- { name: 'Firefox', value: 'firefox' },
199
- { name: 'Safari', value: 'safari' },
200
- { name: 'Microsoft Edge', value: 'MicrosoftEdge' }
201
- ];
202
- function isBrowserRunner(answers) {
203
- return answers.runner === SUPPORTED_PACKAGES.runner[1].value;
204
- }
205
- export function usesSerenity(answers) {
206
- return answers.framework.includes('serenity-js');
207
- }
208
- function getTestingPurpose(answers) {
209
- return convertPackageHashToObject(answers.runner).purpose;
210
- }
211
- export const isNuxtProject = await Promise.all([
212
- path.join(process.cwd(), 'nuxt.config.js'),
213
- path.join(process.cwd(), 'nuxt.config.ts'),
214
- path.join(process.cwd(), 'nuxt.config.mjs'),
215
- path.join(process.cwd(), 'nuxt.config.mts')
216
- ].map((p) => fs.access(p).then(() => true, () => false))).then((res) => res.some(Boolean), () => false);
217
- function selectDefaultService(serviceNames) {
218
- serviceNames = Array.isArray(serviceNames) ? serviceNames : [serviceNames];
219
- return SUPPORTED_PACKAGES.service
220
- /* istanbul ignore next */
221
- .filter(({ name }) => serviceNames.includes(name))
222
- .map(({ value }) => value);
223
- }
224
- function prioServiceOrderFor(serviceNamesParam) {
225
- const serviceNames = Array.isArray(serviceNamesParam) ? serviceNamesParam : [serviceNamesParam];
226
- let services = SUPPORTED_PACKAGES.service;
227
- for (const serviceName of serviceNames) {
228
- const index = services.findIndex(({ name }) => name === serviceName);
229
- services = [services[index], ...services.slice(0, index), ...services.slice(index + 1)];
230
- }
231
- return services;
232
- }
233
- export const QUESTIONNAIRE = [{
234
- type: 'list',
235
- name: 'runner',
236
- message: 'What type of testing would you like to do?',
237
- choices: SUPPORTED_PACKAGES.runner
238
- }, {
239
- type: 'list',
240
- name: 'preset',
241
- message: 'Which framework do you use for building components?',
242
- choices: SUPPORTED_BROWSER_RUNNER_PRESETS,
243
- // only ask if there are more than 1 runner to pick from
244
- when: /* istanbul ignore next */ isBrowserRunner
245
- }, {
246
- type: 'confirm',
247
- name: 'installTestingLibrary',
248
- message: 'Do you like to use Testing Library (https://testing-library.com/) as test utility?',
249
- default: true,
250
- // only ask if there are more than 1 runner to pick from
251
- when: /* istanbul ignore next */ (answers) => (isBrowserRunner(answers) &&
252
- /**
253
- * Only show if Testing Library has an add-on for framework
254
- */
255
- answers.preset && TESTING_LIBRARY_PACKAGES[convertPackageHashToObject(answers.preset).short])
256
- }, {
257
- type: 'list',
258
- name: 'electronBuildTool',
259
- message: 'Which tool are you using to build your Electron app?',
260
- choices: Object.values(ElectronBuildToolChoice),
261
- when: /* instanbul ignore next */ (answers) => getTestingPurpose(answers) === 'electron'
262
- }, {
263
- type: 'input',
264
- name: 'electronAppBinaryPath',
265
- message: 'What is the path to the binary of your built Electron app?',
266
- when: /* istanbul ignore next */ (answers) => getTestingPurpose(answers) === 'electron' && (answers.electronBuildTool === ElectronBuildToolChoice.SomethingElse)
267
- }, {
268
- type: 'list',
269
- name: 'backend',
270
- message: 'Where is your automation backend located?',
271
- choices: Object.values(BackendChoice),
272
- when: /* instanbul ignore next */ (answers) => getTestingPurpose(answers) === 'e2e'
273
- }, {
274
- type: 'list',
275
- name: 'e2eEnvironment',
276
- message: 'Which environment you would like to automate?',
277
- choices: E2E_ENVIRONMENTS,
278
- default: 'web',
279
- when: /* istanbul ignore next */ (answers) => getTestingPurpose(answers) === 'e2e'
280
- }, {
281
- type: 'list',
282
- name: 'mobileEnvironment',
283
- message: 'Which mobile environment you\'ld like to automate?',
284
- choices: MOBILE_ENVIRONMENTS,
285
- when: /* instanbul ignore next */ (answers) => (getTestingPurpose(answers) === 'e2e' &&
286
- answers.e2eEnvironment === 'mobile')
287
- }, {
288
- type: 'checkbox',
289
- name: 'browserEnvironment',
290
- message: 'With which browser should we start?',
291
- choices: BROWSER_ENVIRONMENTS,
292
- default: ['chrome'],
293
- when: /* instanbul ignore next */ (answers) => (getTestingPurpose(answers) === 'e2e' &&
294
- answers.e2eEnvironment === 'web')
295
- }, {
296
- type: 'input',
297
- name: 'hostname',
298
- message: 'What is the host address of that cloud service?',
299
- when: /* istanbul ignore next */ (answers) => answers.backend && answers.backend.indexOf('different service') > -1
300
- }, {
301
- type: 'input',
302
- name: 'port',
303
- message: 'What is the port on which that service is running?',
304
- default: '80',
305
- when: /* istanbul ignore next */ (answers) => answers.backend && answers.backend.indexOf('different service') > -1
306
- }, {
307
- type: 'input',
308
- name: 'expEnvAccessKey',
309
- message: 'Access key from Experitest Cloud',
310
- default: 'EXPERITEST_ACCESS_KEY',
311
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Experitest
312
- }, {
313
- type: 'input',
314
- name: 'expEnvHostname',
315
- message: 'Environment variable for cloud url',
316
- default: 'example.experitest.com',
317
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Experitest
318
- }, {
319
- type: 'input',
320
- name: 'expEnvPort',
321
- message: 'Environment variable for port',
322
- default: '443',
323
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Experitest
324
- }, {
325
- type: 'list',
326
- name: 'expEnvProtocol',
327
- message: 'Choose a protocol for environment variable',
328
- default: ProtocolOptions.HTTPS,
329
- choices: Object.values(ProtocolOptions),
330
- when: /* istanbul ignore next */ (answers) => (answers.backend === BackendChoice.Experitest &&
331
- answers.expEnvPort !== '80' &&
332
- answers.expEnvPort !== '443')
333
- }, {
334
- type: 'input',
335
- name: 'env_user',
336
- message: 'Environment variable for username',
337
- default: 'LT_USERNAME',
338
- when: /* istanbul ignore next */ (answers) => (answers.backend && answers.backend.indexOf('LambdaTest') > -1 &&
339
- answers.hostname.indexOf('lambdatest.com') > -1)
340
- }, {
341
- type: 'input',
342
- name: 'env_key',
343
- message: 'Environment variable for access key',
344
- default: 'LT_ACCESS_KEY',
345
- when: /* istanbul ignore next */ (answers) => (answers.backend && answers.backend.indexOf('LambdaTest') > -1 &&
346
- answers.hostname.indexOf('lambdatest.com') > -1)
347
- }, {
348
- type: 'input',
349
- name: 'env_user',
350
- message: 'Environment variable for username',
351
- default: 'BROWSERSTACK_USERNAME',
352
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Browserstack
353
- }, {
354
- type: 'input',
355
- name: 'env_key',
356
- message: 'Environment variable for access key',
357
- default: 'BROWSERSTACK_ACCESS_KEY',
358
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Browserstack
359
- }, {
360
- type: 'input',
361
- name: 'env_user',
362
- message: 'Environment variable for username',
363
- default: 'SAUCE_USERNAME',
364
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Saucelabs
365
- }, {
366
- type: 'input',
367
- name: 'env_key',
368
- message: 'Environment variable for access key',
369
- default: 'SAUCE_ACCESS_KEY',
370
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Saucelabs
371
- }, {
372
- type: 'list',
373
- name: 'region',
374
- message: 'In which region do you want to run your Sauce Labs tests in?',
375
- choices: Object.values(RegionOptions),
376
- when: /* istanbul ignore next */ (answers) => answers.backend === BackendChoice.Saucelabs
377
- }, {
378
- type: 'confirm',
379
- name: 'useSauceConnect',
380
- message: ('Are you testing a local application and need Sauce Connect to be set-up?\n' +
381
- 'Read more on Sauce Connect at: https://wiki.saucelabs.com/display/DOCS/Sauce+Connect+Proxy'),
382
- default: isNuxtProject,
383
- when: /* istanbul ignore next */ (answers) => (answers.backend === BackendChoice.Saucelabs &&
384
- !isNuxtProject)
385
- }, {
386
- type: 'input',
387
- name: 'hostname',
388
- message: 'What is the IP or URI to your Selenium standalone or grid server?',
389
- default: 'localhost',
390
- when: /* istanbul ignore next */ (answers) => answers.backend && answers.backend.toString().indexOf('own Selenium cloud') > -1
391
- }, {
392
- type: 'input',
393
- name: 'port',
394
- message: 'What is the port which your Selenium standalone or grid server is running on?',
395
- default: '4444',
396
- when: /* istanbul ignore next */ (answers) => answers.backend && answers.backend.toString().indexOf('own Selenium cloud') > -1
397
- }, {
398
- type: 'input',
399
- name: 'path',
400
- message: 'What is the path to your browser driver or grid server?',
401
- default: '/',
402
- when: /* istanbul ignore next */ (answers) => answers.backend && answers.backend.toString().indexOf('own Selenium cloud') > -1
403
- }, {
404
- type: 'list',
405
- name: 'framework',
406
- message: 'Which framework do you want to use?',
407
- choices: /* instanbul ignore next */ (answers) => {
408
- /**
409
- * browser runner currently supports only Mocha framework
410
- */
411
- if (isBrowserRunner(answers)) {
412
- return SUPPORTED_PACKAGES.framework.slice(0, 1);
413
- }
414
- /**
415
- * Serenity tests don't come with proper ElectronJS example files
416
- */
417
- if (getTestingPurpose(answers) === 'electron') {
418
- return SUPPORTED_PACKAGES.framework.filter(({ value }) => !value.startsWith('@serenity-js'));
419
- }
420
- return SUPPORTED_PACKAGES.framework;
421
- }
422
- }, {
423
- type: 'list',
424
- name: 'isUsingCompiler',
425
- message: 'Do you want to use a compiler?',
426
- choices: (answers) => {
427
- /**
428
- * StencilJS only supports TypeScript
429
- */
430
- if (answers.preset && answers.preset.includes('stencil')) {
431
- return [CompilerOptions.TS];
432
- }
433
- return Object.values(CompilerOptions);
434
- },
435
- default: /* istanbul ignore next */ (answers) => detectCompiler(answers)
436
- }, {
437
- type: 'confirm',
438
- name: 'generateTestFiles',
439
- message: 'Do you want WebdriverIO to autogenerate some test files?',
440
- default: true,
441
- when: /* istanbul ignore next */ (answers) => {
442
- /**
443
- * we only have examples for Mocha and Jasmine
444
- */
445
- if (['vscode', 'electron', 'macos'].includes(getTestingPurpose(answers)) && answers.framework.includes('cucumber')) {
446
- return false;
447
- }
448
- return true;
449
- }
450
- }, {
451
- type: 'input',
452
- name: 'specs',
453
- message: 'What should be the location of your spec files?',
454
- default: /* istanbul ignore next */ (answers) => {
455
- const pattern = isBrowserRunner(answers) ? 'src/**/*.test' : 'test/specs/**/*';
456
- return getDefaultFiles(answers, pattern);
457
- },
458
- when: /* istanbul ignore next */ (answers) => answers.generateTestFiles && answers.framework.match(/(mocha|jasmine)/)
459
- }, {
460
- type: 'input',
461
- name: 'specs',
462
- message: 'What should be the location of your feature files?',
463
- default: (answers) => getDefaultFiles(answers, 'features/**/*.feature'),
464
- when: /* istanbul ignore next */ (answers) => answers.generateTestFiles && answers.framework.includes('cucumber')
465
- }, {
466
- type: 'input',
467
- name: 'stepDefinitions',
468
- message: 'What should be the location of your step definitions?',
469
- default: (answers) => getDefaultFiles(answers, 'features/step-definitions/steps'),
470
- when: /* istanbul ignore next */ (answers) => answers.generateTestFiles && answers.framework.includes('cucumber')
471
- }, {
472
- type: 'confirm',
473
- name: 'usePageObjects',
474
- message: 'Do you want to use page objects (https://martinfowler.com/bliki/PageObject.html)?',
475
- default: true,
476
- when: /* istanbul ignore next */ (answers) => (answers.generateTestFiles &&
477
- /**
478
- * page objects aren't common for component testing
479
- */
480
- !isBrowserRunner(answers) &&
481
- /**
482
- * and also not needed when running VS Code tests since the service comes with
483
- * its own page object implementation, nor when running Electron or MacOS tests
484
- */
485
- !['vscode', 'electron', 'macos'].includes(getTestingPurpose(answers)) &&
486
- /**
487
- * Serenity/JS generates Lean Page Objects by default, so there's no need to ask about it
488
- * See https://serenity-js.org/handbook/web-testing/page-objects-pattern/
489
- */
490
- !usesSerenity(answers))
491
- }, {
492
- type: 'input',
493
- name: 'pages',
494
- message: 'Where are your page objects located?',
495
- default: /* istanbul ignore next */ (answers) => (answers.framework.match(/(mocha|jasmine)/)
496
- ? getDefaultFiles(answers, 'test/pageobjects/**/*')
497
- : getDefaultFiles(answers, 'features/pageobjects/**/*')),
498
- when: /* istanbul ignore next */ (answers) => answers.generateTestFiles && answers.usePageObjects
499
- }, {
500
- type: 'input',
501
- name: 'serenityLibPath',
502
- message: 'What should be the location of your Serenity/JS Screenplay Pattern library?',
503
- default: /* istanbul ignore next */ async (answers) => {
504
- const projectRootDir = await getProjectRoot(answers);
505
- const specsDir = path.resolve(projectRootDir, path.dirname(answers.specs || '').replace(/\*\*$/, ''));
506
- return path.resolve(specsDir, '..', 'serenity');
507
- },
508
- when: /* istanbul ignore next */ (answers) => answers.generateTestFiles && usesSerenity(answers)
509
- }, {
510
- type: 'checkbox',
511
- name: 'reporters',
512
- message: 'Which reporter do you want to use?',
513
- choices: SUPPORTED_PACKAGES.reporter,
514
- // @ts-ignore
515
- default: [SUPPORTED_PACKAGES.reporter.find(
516
- /* istanbul ignore next */
517
- ({ name }) => name === 'spec').value
518
- ]
519
- }, {
520
- type: 'checkbox',
521
- name: 'plugins',
522
- message: 'Do you want to add a plugin to your test setup?',
523
- choices: SUPPORTED_PACKAGES.plugin,
524
- default: []
525
- }, {
526
- type: 'confirm',
527
- name: 'includeVisualTesting',
528
- message: 'Would you like to include Visual Testing to your setup? For more information see https://webdriver.io/docs/visual-testing!',
529
- default: false,
530
- when: /* istanbul ignore next */ (answers) => {
531
- /**
532
- * visual testing mostly makes sense for e2e and component tests
533
- */
534
- return ['e2e', 'component'].includes(getTestingPurpose(answers));
535
- }
536
- }, {
537
- type: 'checkbox',
538
- name: 'services',
539
- message: 'Do you want to add a service to your test setup?',
540
- choices: (answers) => {
541
- const services = [];
542
- if (answers.backend === BackendChoice.Browserstack) {
543
- services.push('browserstack');
544
- }
545
- else if (answers.backend === BackendChoice.Saucelabs) {
546
- services.push('sauce');
547
- }
548
- if (answers.e2eEnvironment === 'mobile') {
549
- services.push('appium');
550
- }
551
- if (getTestingPurpose(answers) === 'e2e' && isNuxtProject) {
552
- services.push('nuxt');
553
- }
554
- if (getTestingPurpose(answers) === 'vscode') {
555
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === 'vscode')];
556
- }
557
- else if (getTestingPurpose(answers) === 'electron') {
558
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === 'electron')];
559
- }
560
- else if (getTestingPurpose(answers) === 'macos') {
561
- return [SUPPORTED_PACKAGES.service.find(({ name }) => name === 'appium')];
562
- }
563
- return prioServiceOrderFor(services);
564
- },
565
- default: (answers) => {
566
- const defaultServices = [];
567
- if (answers.backend === BackendChoice.Browserstack) {
568
- defaultServices.push('browserstack');
569
- }
570
- else if (answers.backend === BackendChoice.Saucelabs) {
571
- defaultServices.push('sauce');
572
- }
573
- if (answers.e2eEnvironment === 'mobile' || getTestingPurpose(answers) === 'macos') {
574
- defaultServices.push('appium');
575
- }
576
- if (getTestingPurpose(answers) === 'vscode') {
577
- defaultServices.push('vscode');
578
- }
579
- else if (getTestingPurpose(answers) === 'electron') {
580
- defaultServices.push('electron');
581
- }
582
- if (isNuxtProject) {
583
- defaultServices.push('nuxt');
584
- }
585
- if (answers.includeVisualTesting) {
586
- defaultServices.push('visual');
587
- }
588
- return selectDefaultService(defaultServices);
589
- }
590
- }, {
591
- type: 'input',
592
- name: 'outputDir',
593
- message: 'In which directory should the xunit reports get stored?',
594
- default: './',
595
- when: /* istanbul ignore next */ (answers) => answers.reporters.includes('junit')
596
- }, {
597
- type: 'input',
598
- name: 'outputDir',
599
- message: 'In which directory should the json reports get stored?',
600
- default: './',
601
- when: /* istanbul ignore next */ (answers) => answers.reporters.includes('json')
602
- }, {
603
- type: 'input',
604
- name: 'outputDir',
605
- message: 'In which directory should the mochawesome json reports get stored?',
606
- default: './',
607
- when: /* istanbul ignore next */ (answers) => answers.reporters.includes('mochawesome')
608
- }, {
609
- type: 'confirm',
610
- name: 'npmInstall',
611
- message: () => `Do you want me to run \`${detectPackageManager()} install\``,
612
- default: true
613
- }];
614
- const SUPPORTED_SNAPSHOTSTATE_OPTIONS = ['all', 'new', 'none'];
615
- export const COMMUNITY_PACKAGES_WITH_TS_SUPPORT = [
616
- 'wdio-electron-service',
617
- 'wdio-vscode-service',
618
- 'wdio-nuxt-service',
619
- 'wdio-vite-service',
620
- 'wdio-gmail-service'
621
- ];
622
- export const TESTRUNNER_DEFAULTS = {
623
- /**
624
- * Define specs for test execution. You can either specify a glob
625
- * pattern to match multiple files at once or wrap a glob or set of
626
- * paths into an array to run them within a single worker process.
627
- */
628
- specs: {
629
- type: 'object',
630
- validate: (param) => {
631
- if (!Array.isArray(param)) {
632
- throw new Error('the "specs" option needs to be a list of strings');
633
- }
634
- }
635
- },
636
- /**
637
- * exclude specs from test execution
638
- */
639
- exclude: {
640
- type: 'object',
641
- validate: (param) => {
642
- if (!Array.isArray(param)) {
643
- throw new Error('the "exclude" option needs to be a list of strings');
644
- }
645
- }
646
- },
647
- /**
648
- * key/value definition of suites (named by key) and a list of specs as value
649
- * to specify a specific set of tests to execute
650
- */
651
- suites: {
652
- type: 'object'
653
- },
654
- /**
655
- * Project root directory path.
656
- */
657
- rootDir: {
658
- type: 'string'
659
- },
660
- /**
661
- * If you only want to run your tests until a specific amount of tests have failed use
662
- * bail (default is 0 - don't bail, run all tests).
663
- */
664
- bail: {
665
- type: 'number',
666
- default: 0
667
- },
668
- /**
669
- * supported test framework by wdio testrunner
670
- */
671
- framework: {
672
- type: 'string'
673
- },
674
- /**
675
- * capabilities of WebDriver sessions
676
- */
677
- capabilities: {
678
- type: 'object',
679
- validate: (param) => {
680
- /**
681
- * should be an object
682
- */
683
- if (!Array.isArray(param)) {
684
- if (typeof param === 'object') {
685
- return true;
686
- }
687
- throw new Error('the "capabilities" options needs to be an object or a list of objects');
688
- }
689
- /**
690
- * or an array of objects
691
- */
692
- for (const option of param) {
693
- if (typeof option === 'object') { // Check does not work recursively
694
- continue;
695
- }
696
- throw new Error('expected every item of a list of capabilities to be of type object');
697
- }
698
- return true;
699
- },
700
- required: true
701
- },
702
- /**
703
- * list of reporters to use, a reporter can be either a string or an object with
704
- * reporter options, e.g.:
705
- * [
706
- * 'dot',
707
- * {
708
- * name: 'spec',
709
- * outputDir: __dirname + '/reports'
710
- * }
711
- * ]
712
- */
713
- reporters: {
714
- type: 'object',
715
- validate: (param) => {
716
- /**
717
- * option must be an array
718
- */
719
- if (!Array.isArray(param)) {
720
- throw new Error('the "reporters" options needs to be a list of strings');
721
- }
722
- const isValidReporter = (option) => ((typeof option === 'string') ||
723
- (typeof option === 'function'));
724
- /**
725
- * array elements must be:
726
- */
727
- for (const option of param) {
728
- /**
729
- * either a string or a function (custom reporter)
730
- */
731
- if (isValidReporter(option)) {
732
- continue;
733
- }
734
- /**
735
- * or an array with the name of the reporter as first element and the options
736
- * as second element
737
- */
738
- if (Array.isArray(option) &&
739
- typeof option[1] === 'object' &&
740
- isValidReporter(option[0])) {
741
- continue;
742
- }
743
- throw new Error('a reporter should be either a string in the format "wdio-<reportername>-reporter" ' +
744
- 'or a function/class. Please see the docs for more information on custom reporters ' +
745
- '(https://webdriver.io/docs/customreporter)');
746
- }
747
- return true;
748
- }
749
- },
750
- /**
751
- * set of WDIO services to use
752
- */
753
- services: {
754
- type: 'object',
755
- validate: (param) => {
756
- /**
757
- * should be an array
758
- */
759
- if (!Array.isArray(param)) {
760
- throw new Error('the "services" options needs to be a list of strings and/or arrays');
761
- }
762
- /**
763
- * with arrays and/or strings
764
- */
765
- for (const option of param) {
766
- if (!Array.isArray(option)) {
767
- if (typeof option === 'string') {
768
- continue;
769
- }
770
- throw new Error('the "services" options needs to be a list of strings and/or arrays');
771
- }
772
- }
773
- return true;
774
- },
775
- default: []
776
- },
777
- /**
778
- * Node arguments to specify when launching child processes
779
- */
780
- execArgv: {
781
- type: 'object',
782
- validate: (param) => {
783
- if (!Array.isArray(param)) {
784
- throw new Error('the "execArgv" options needs to be a list of strings');
785
- }
786
- },
787
- default: []
788
- },
789
- /**
790
- * amount of instances to be allowed to run in total
791
- */
792
- maxInstances: {
793
- type: 'number'
794
- },
795
- /**
796
- * amount of instances to be allowed to run per capability
797
- */
798
- maxInstancesPerCapability: {
799
- type: 'number'
800
- },
801
- /**
802
- * whether or not testrunner should inject `browser`, `$` and `$$` as
803
- * global environment variables
804
- */
805
- injectGlobals: {
806
- type: 'boolean'
807
- },
808
- /**
809
- * Set to true if you want to update your snapshots.
810
- */
811
- updateSnapshots: {
812
- type: 'string',
813
- default: SUPPORTED_SNAPSHOTSTATE_OPTIONS[1],
814
- validate: (param) => {
815
- if (param && !SUPPORTED_SNAPSHOTSTATE_OPTIONS.includes(param)) {
816
- throw new Error(`the "updateSnapshots" options needs to be one of "${SUPPORTED_SNAPSHOTSTATE_OPTIONS.join('", "')}"`);
817
- }
818
- }
819
- },
820
- /**
821
- * Overrides default snapshot path. For example, to store snapshots next to test files.
822
- */
823
- resolveSnapshotPath: {
824
- type: 'function',
825
- validate: (param) => {
826
- if (param && typeof param !== 'function') {
827
- throw new Error('the "resolveSnapshotPath" options needs to be a function');
828
- }
829
- }
830
- },
831
- /**
832
- * The number of times to retry the entire specfile when it fails as a whole
833
- */
834
- specFileRetries: {
835
- type: 'number',
836
- default: 0
837
- },
838
- /**
839
- * Delay in seconds between the spec file retry attempts
840
- */
841
- specFileRetriesDelay: {
842
- type: 'number',
843
- default: 0
844
- },
845
- /**
846
- * Whether or not retried spec files should be retried immediately or deferred to the end of the queue
847
- */
848
- specFileRetriesDeferred: {
849
- type: 'boolean',
850
- default: true
851
- },
852
- /**
853
- * whether or not print the log output grouped by test files
854
- */
855
- groupLogsByTestSpec: {
856
- type: 'boolean',
857
- default: false
858
- },
859
- /**
860
- * list of strings to watch of `wdio` command is called with `--watch` flag
861
- */
862
- filesToWatch: {
863
- type: 'object',
864
- validate: (param) => {
865
- if (!Array.isArray(param)) {
866
- throw new Error('the "filesToWatch" option needs to be a list of strings');
867
- }
868
- }
869
- },
870
- shard: {
871
- type: 'object',
872
- validate: (param) => {
873
- if (typeof param !== 'object') {
874
- throw new Error('the "shard" options needs to be an object');
875
- }
876
- const p = param;
877
- if (typeof p.current !== 'number' || typeof p.total !== 'number') {
878
- throw new Error('the "shard" option needs to have "current" and "total" properties with number values');
879
- }
880
- if (p.current < 0 || p.current > p.total) {
881
- throw new Error('the "shard.current" value has to be between 0 and "shard.total"');
882
- }
883
- }
884
- },
885
- /**
886
- * hooks
887
- */
888
- onPrepare: HOOK_DEFINITION,
889
- onWorkerStart: HOOK_DEFINITION,
890
- onWorkerEnd: HOOK_DEFINITION,
891
- before: HOOK_DEFINITION,
892
- beforeSession: HOOK_DEFINITION,
893
- beforeSuite: HOOK_DEFINITION,
894
- beforeHook: HOOK_DEFINITION,
895
- beforeTest: HOOK_DEFINITION,
896
- afterTest: HOOK_DEFINITION,
897
- afterHook: HOOK_DEFINITION,
898
- afterSuite: HOOK_DEFINITION,
899
- afterSession: HOOK_DEFINITION,
900
- after: HOOK_DEFINITION,
901
- onComplete: HOOK_DEFINITION,
902
- onReload: HOOK_DEFINITION,
903
- beforeAssertion: HOOK_DEFINITION,
904
- afterAssertion: HOOK_DEFINITION
905
- };
906
- export const WORKER_GROUPLOGS_MESSAGES = {
907
- normalExit: (cid) => `\n***** List of steps of WorkerID=[${cid}] *****`,
908
- exitWithError: (cid) => `\n***** List of steps of WorkerID=[${cid}] that preceded the error above *****`
909
- };