@wdio/utils 9.0.0-alpha.9 → 9.0.4
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/envDetector.d.ts +3 -3
- package/build/envDetector.d.ts.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1902 -24
- package/build/initializeServices.d.ts +3 -3
- package/build/initializeServices.d.ts.map +1 -1
- package/build/monad.d.ts.map +1 -1
- package/build/node/manager.d.ts +2 -2
- package/build/node/manager.d.ts.map +1 -1
- package/build/node/startWebDriver.d.ts +2 -3
- package/build/node/startWebDriver.d.ts.map +1 -1
- package/build/node/utils.d.ts.map +1 -1
- package/build/node.js +473 -0
- package/build/pIteration.d.ts.map +1 -1
- package/build/shim.d.ts.map +1 -1
- package/build/startWebDriver.d.ts +2 -3
- package/build/startWebDriver.d.ts.map +1 -1
- package/build/test-framework/errorHandler.d.ts.map +1 -1
- package/build/test-framework/testFnWrapper.d.ts.map +1 -1
- package/build/test-framework/testInterfaceWrapper.d.ts.map +1 -1
- package/build/utils.d.ts +11 -2
- package/build/utils.d.ts.map +1 -1
- package/package.json +10 -11
- package/build/constants.js +0 -114
- package/build/envDetector.js +0 -251
- package/build/initializePlugin.js +0 -38
- package/build/initializeServices.js +0 -159
- package/build/monad.js +0 -196
- package/build/node/index.js +0 -3
- package/build/node/manager.js +0 -106
- package/build/node/startWebDriver.js +0 -140
- package/build/node/utils.js +0 -285
- package/build/pIteration.js +0 -347
- package/build/shim.js +0 -293
- package/build/startWebDriver.js +0 -20
- package/build/test-framework/errorHandler.js +0 -33
- package/build/test-framework/index.js +0 -4
- package/build/test-framework/testFnWrapper.js +0 -97
- package/build/test-framework/testInterfaceWrapper.js +0 -162
- package/build/test-framework/types.js +0 -1
- package/build/utils.js +0 -320
- /package/{LICENSE-MIT → LICENSE} +0 -0
package/build/utils.js
DELETED
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { SUPPORTED_BROWSERNAMES, DEFAULT_PROTOCOL, DEFAULT_HOSTNAME, DEFAULT_PATH } from './constants.js';
|
|
2
|
-
const SCREENSHOT_REPLACEMENT = '"<Screenshot[base64]>"';
|
|
3
|
-
const SCRIPT_PLACEHOLDER = '"<Script[base64]>"';
|
|
4
|
-
const REGEX_SCRIPT_NAME = /return \((async )?function (\w+)/;
|
|
5
|
-
const SLASH = '/';
|
|
6
|
-
function assertPath(path) {
|
|
7
|
-
if (typeof path !== 'string') {
|
|
8
|
-
throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
export function isAbsolute(p) {
|
|
12
|
-
assertPath(p);
|
|
13
|
-
return p.length > 0 && p.charCodeAt(0) === SLASH.codePointAt(0);
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* overwrite native element commands with user defined
|
|
17
|
-
* @param {object} propertiesObject propertiesObject
|
|
18
|
-
*/
|
|
19
|
-
export function overwriteElementCommands(propertiesObject) {
|
|
20
|
-
const elementOverrides = propertiesObject.__elementOverrides__
|
|
21
|
-
? propertiesObject.__elementOverrides__.value
|
|
22
|
-
: {};
|
|
23
|
-
for (const [commandName, userDefinedCommand] of Object.entries(elementOverrides)) {
|
|
24
|
-
if (typeof userDefinedCommand !== 'function') {
|
|
25
|
-
throw new Error('overwriteCommand: commands be overwritten only with functions, command: ' + commandName);
|
|
26
|
-
}
|
|
27
|
-
if (!propertiesObject[commandName]) {
|
|
28
|
-
throw new Error('overwriteCommand: no command to be overwritten: ' + commandName);
|
|
29
|
-
}
|
|
30
|
-
if (typeof propertiesObject[commandName].value !== 'function') {
|
|
31
|
-
throw new Error('overwriteCommand: only functions can be overwritten, command: ' + commandName);
|
|
32
|
-
}
|
|
33
|
-
const origCommand = propertiesObject[commandName].value;
|
|
34
|
-
delete propertiesObject[commandName];
|
|
35
|
-
const newCommand = function (...args) {
|
|
36
|
-
const element = this;
|
|
37
|
-
return userDefinedCommand.apply(element, [
|
|
38
|
-
function origCommandFunction() {
|
|
39
|
-
const context = this || element; // respect explicite context binding, use element as default
|
|
40
|
-
return origCommand.apply(context, arguments);
|
|
41
|
-
},
|
|
42
|
-
...args
|
|
43
|
-
]);
|
|
44
|
-
};
|
|
45
|
-
propertiesObject[commandName] = {
|
|
46
|
-
value: newCommand,
|
|
47
|
-
configurable: true
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
delete propertiesObject.__elementOverrides__;
|
|
51
|
-
propertiesObject.__elementOverrides__ = { value: {} };
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* get command call structure
|
|
55
|
-
* (for logging purposes)
|
|
56
|
-
*/
|
|
57
|
-
export function commandCallStructure(commandName, args, unfurl = false) {
|
|
58
|
-
const callArgs = args.map((arg) => {
|
|
59
|
-
if (typeof arg === 'string' && (arg.startsWith('!function(') || arg.startsWith('return (function') || arg.startsWith('return (async function'))) {
|
|
60
|
-
arg = '<fn>';
|
|
61
|
-
}
|
|
62
|
-
else if (typeof arg === 'string' &&
|
|
63
|
-
/**
|
|
64
|
-
* the isBase64 method returns for xPath values like
|
|
65
|
-
* "/html/body/a" a true value which is why we should
|
|
66
|
-
* include a command check in here.
|
|
67
|
-
*/
|
|
68
|
-
!commandName.startsWith('findElement') &&
|
|
69
|
-
isBase64(arg)) {
|
|
70
|
-
arg = SCREENSHOT_REPLACEMENT;
|
|
71
|
-
}
|
|
72
|
-
else if (typeof arg === 'string') {
|
|
73
|
-
arg = `"${arg}"`;
|
|
74
|
-
}
|
|
75
|
-
else if (typeof arg === 'function') {
|
|
76
|
-
arg = '<fn>';
|
|
77
|
-
}
|
|
78
|
-
else if (arg === null) {
|
|
79
|
-
arg = 'null';
|
|
80
|
-
}
|
|
81
|
-
else if (typeof arg === 'object') {
|
|
82
|
-
arg = unfurl ? JSON.stringify(arg) : '<object>';
|
|
83
|
-
}
|
|
84
|
-
else if (typeof arg === 'undefined') {
|
|
85
|
-
arg = typeof arg;
|
|
86
|
-
}
|
|
87
|
-
return arg;
|
|
88
|
-
}).join(', ');
|
|
89
|
-
return `${commandName}(${callArgs})`;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* transforms WebDriver result for log stream to avoid unnecessary long
|
|
93
|
-
* result strings e.g. if it contains a screenshot
|
|
94
|
-
* @param {object} result WebDriver response body
|
|
95
|
-
*/
|
|
96
|
-
export function transformCommandLogResult(result) {
|
|
97
|
-
if (typeof result.file === 'string' && isBase64(result.file)) {
|
|
98
|
-
return SCREENSHOT_REPLACEMENT;
|
|
99
|
-
}
|
|
100
|
-
else if (typeof result.script === 'string' && isBase64(result.script)) {
|
|
101
|
-
return SCRIPT_PLACEHOLDER;
|
|
102
|
-
}
|
|
103
|
-
else if (typeof result.script === 'string' && result.script.match(REGEX_SCRIPT_NAME)) {
|
|
104
|
-
const newScript = result.script.match(REGEX_SCRIPT_NAME)[2];
|
|
105
|
-
return { ...result, script: `${newScript}(...) [${Buffer.byteLength(result.script, 'utf-8')} bytes]` };
|
|
106
|
-
}
|
|
107
|
-
else if (typeof result.script === 'string' && result.script.startsWith('!function(')) {
|
|
108
|
-
return { ...result, script: `<minified function> [${Buffer.byteLength(result.script, 'utf-8')} bytes]` };
|
|
109
|
-
}
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* checks if command argument is valid according to specification
|
|
114
|
-
*
|
|
115
|
-
* @param {*} arg command argument
|
|
116
|
-
* @param {Object} expectedType parameter type (e.g. `number`, `string[]` or `(number|string)`)
|
|
117
|
-
* @return {Boolean} true if argument is valid
|
|
118
|
-
*/
|
|
119
|
-
export function isValidParameter(arg, expectedType) {
|
|
120
|
-
let shouldBeArray = false;
|
|
121
|
-
if (expectedType.slice(-2) === '[]') {
|
|
122
|
-
expectedType = expectedType.slice(0, -2);
|
|
123
|
-
shouldBeArray = true;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* check type of each individual array element
|
|
127
|
-
*/
|
|
128
|
-
if (shouldBeArray) {
|
|
129
|
-
if (!Array.isArray(arg)) {
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
/**
|
|
135
|
-
* transform to array to have a unified check
|
|
136
|
-
*/
|
|
137
|
-
arg = [arg];
|
|
138
|
-
}
|
|
139
|
-
for (const argEntity of arg) {
|
|
140
|
-
const argEntityType = getArgumentType(argEntity);
|
|
141
|
-
if (!argEntityType.match(expectedType)) {
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* get type of command argument
|
|
149
|
-
*/
|
|
150
|
-
export function getArgumentType(arg) {
|
|
151
|
-
return arg === null ? 'null' : typeof arg;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Utility to import modules with user friendly error message
|
|
155
|
-
* @param moduleName The name of the module to import
|
|
156
|
-
* @param namedImport The name of the import to return
|
|
157
|
-
* @returns The imported module
|
|
158
|
-
*/
|
|
159
|
-
export async function userImport(moduleName, namedImport = 'default') {
|
|
160
|
-
try {
|
|
161
|
-
const mod = await import(moduleName);
|
|
162
|
-
if (namedImport in mod) {
|
|
163
|
-
return mod[namedImport];
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
catch (err) {
|
|
167
|
-
throw new Error(`Couldn't import "${moduleName}"! Do you have it installed? If not run "npm install ${moduleName}"!`);
|
|
168
|
-
}
|
|
169
|
-
throw new Error(`Couldn't find "${namedImport}" in module "${moduleName}"`);
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Allows to safely require a package, it only throws if the package was found
|
|
173
|
-
* but failed to load due to syntax errors
|
|
174
|
-
* @param {string} name of package
|
|
175
|
-
* @return {object} package content
|
|
176
|
-
*/
|
|
177
|
-
export async function safeImport(name) {
|
|
178
|
-
let importPath = name;
|
|
179
|
-
try {
|
|
180
|
-
/**
|
|
181
|
-
* Initially we will search for the package by using the standard package
|
|
182
|
-
* resolution starting from the path given by 'import.meta.url' (which
|
|
183
|
-
* returns the path to this file). The default mechanism will then search
|
|
184
|
-
* upwards through the hierarchy in the file system in node_modules directories
|
|
185
|
-
* until it finds the package or reaches the root of the file system.
|
|
186
|
-
*
|
|
187
|
-
* In the case where a user has installed the @wdio/cli package globally,
|
|
188
|
-
* then clearly the search will be performed in the global area and not
|
|
189
|
-
* in the project specific area. Consequently, if the package we are
|
|
190
|
-
* looking for is installed within the project it will not be found and
|
|
191
|
-
* then we also need to search in the project, we do that by defining
|
|
192
|
-
* 'localNodeModules' and searching from that also.
|
|
193
|
-
*
|
|
194
|
-
* Note that import-meta-resolve will resolve to CJS no ESM export is found.
|
|
195
|
-
* Only in Node.js environments
|
|
196
|
-
*/
|
|
197
|
-
if (!globalThis.window) {
|
|
198
|
-
const { resolve } = await import('import-meta-resolve');
|
|
199
|
-
try {
|
|
200
|
-
importPath = await resolve(name, import.meta.url);
|
|
201
|
-
}
|
|
202
|
-
catch (err) {
|
|
203
|
-
const { join } = await import('node:path');
|
|
204
|
-
const { pathToFileURL } = await import('node:url');
|
|
205
|
-
const localNodeModules = join(process.cwd(), 'node_modules');
|
|
206
|
-
try {
|
|
207
|
-
importPath = await resolve(name, pathToFileURL(localNodeModules).toString());
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch (err) {
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
try {
|
|
219
|
-
const pkg = await import(importPath);
|
|
220
|
-
/**
|
|
221
|
-
* CJS packages build with TS imported through an ESM context can end up being this:
|
|
222
|
-
*
|
|
223
|
-
* [Module: null prototype] {
|
|
224
|
-
* __esModule: true,
|
|
225
|
-
* default: {
|
|
226
|
-
* launcher: [class SmokeServiceLauncher],
|
|
227
|
-
* default: [class SmokeService]
|
|
228
|
-
* },
|
|
229
|
-
* launcher: [class SmokeServiceLauncher]
|
|
230
|
-
* }
|
|
231
|
-
*
|
|
232
|
-
* In order to not have the testrunner ignore importing a service we should double check if
|
|
233
|
-
* a nested default is given and return that.
|
|
234
|
-
*/
|
|
235
|
-
if (pkg.default && pkg.default.default) {
|
|
236
|
-
return pkg.default;
|
|
237
|
-
}
|
|
238
|
-
return pkg;
|
|
239
|
-
}
|
|
240
|
-
catch (e) {
|
|
241
|
-
throw new Error(`Couldn't initialize "${name}".\n${e.stack}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* is function async
|
|
246
|
-
* @param {Function} fn function to check
|
|
247
|
-
* @return {Boolean} true provided function is async
|
|
248
|
-
*/
|
|
249
|
-
export function isFunctionAsync(fn) {
|
|
250
|
-
return (fn.constructor && fn.constructor.name === 'AsyncFunction') || fn.name === 'async';
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* filter out arguments passed to specFn & hookFn, don't allow callbacks
|
|
254
|
-
* as there is no need for user to call e.g. `done()`
|
|
255
|
-
*/
|
|
256
|
-
export function filterSpecArgs(args) {
|
|
257
|
-
return args.filter((arg) => typeof arg !== 'function');
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* checks if provided string is Base64
|
|
261
|
-
* @param {string} str string to check
|
|
262
|
-
* @return {boolean} `true` if the provided string is Base64
|
|
263
|
-
*/
|
|
264
|
-
export function isBase64(str) {
|
|
265
|
-
if (typeof str !== 'string') {
|
|
266
|
-
throw new Error('Expected string but received invalid type.');
|
|
267
|
-
}
|
|
268
|
-
const len = str.length;
|
|
269
|
-
const notBase64 = /[^A-Z0-9+/=]/i;
|
|
270
|
-
if (!len || len % 4 !== 0 || notBase64.test(str)) {
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
const firstPaddingChar = str.indexOf('=');
|
|
274
|
-
return (firstPaddingChar === -1 ||
|
|
275
|
-
firstPaddingChar === len - 1 ||
|
|
276
|
-
(firstPaddingChar === len - 2 && str[len - 1] === '='));
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* sleep
|
|
280
|
-
* @param {number=0} ms number in ms to sleep
|
|
281
|
-
*/
|
|
282
|
-
export const sleep = (ms = 0) => new Promise((r) => setTimeout(r, ms));
|
|
283
|
-
/**
|
|
284
|
-
* Checks if the provided WebdriverIO capabilities object is related to Appium.
|
|
285
|
-
*
|
|
286
|
-
* @param {WebdriverIO.Capabilities} caps - The capabilities object to check.
|
|
287
|
-
* @returns {boolean} Returns true if the provided capabilities are related to Appium, false otherwise.
|
|
288
|
-
*/
|
|
289
|
-
export function isAppiumCapability(caps) {
|
|
290
|
-
return Boolean(caps &&
|
|
291
|
-
// @ts-expect-error outdated jsonwp cap
|
|
292
|
-
(caps.automationName || caps['appium:automationName'] || caps.deviceName || caps.appiumVersion));
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* helper method to determine if we need to setup a browser driver
|
|
296
|
-
* which is:
|
|
297
|
-
* - whenever the user has set connection options that differ
|
|
298
|
-
* from the default, or a port is set
|
|
299
|
-
* - whenever the user defines `user` and `key` which later will
|
|
300
|
-
* update the connection options
|
|
301
|
-
*/
|
|
302
|
-
export function definesRemoteDriver(options) {
|
|
303
|
-
return Boolean((options.protocol && options.protocol !== DEFAULT_PROTOCOL) ||
|
|
304
|
-
(options.hostname && options.hostname !== DEFAULT_HOSTNAME) ||
|
|
305
|
-
Boolean(options.port) ||
|
|
306
|
-
(options.path && options.path !== DEFAULT_PATH) ||
|
|
307
|
-
Boolean(options.user && options.key));
|
|
308
|
-
}
|
|
309
|
-
export function isChrome(browserName) {
|
|
310
|
-
return Boolean(browserName && SUPPORTED_BROWSERNAMES.chrome.includes(browserName.toLowerCase()));
|
|
311
|
-
}
|
|
312
|
-
export function isSafari(browserName) {
|
|
313
|
-
return Boolean(browserName && SUPPORTED_BROWSERNAMES.safari.includes(browserName.toLowerCase()));
|
|
314
|
-
}
|
|
315
|
-
export function isFirefox(browserName) {
|
|
316
|
-
return Boolean(browserName && SUPPORTED_BROWSERNAMES.firefox.includes(browserName.toLowerCase()));
|
|
317
|
-
}
|
|
318
|
-
export function isEdge(browserName) {
|
|
319
|
-
return Boolean(browserName && SUPPORTED_BROWSERNAMES.edge.includes(browserName.toLowerCase()));
|
|
320
|
-
}
|
/package/{LICENSE-MIT → LICENSE}
RENAMED
|
File without changes
|