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