@wdio/browserstack-service 7.20.6 → 7.20.8-alpha.504
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/README.md +87 -11
- package/build/constants.d.ts +1 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +6 -4
- package/build/index.d.ts +3 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -25
- package/build/launcher.d.ts +9 -2
- package/build/launcher.d.ts.map +1 -1
- package/build/launcher.js +181 -69
- package/build/service.d.ts +1 -1
- package/build/service.d.ts.map +1 -1
- package/build/service.js +25 -28
- package/build/types.d.ts +21 -0
- package/build/types.d.ts.map +1 -1
- package/build/types.js +1 -2
- package/build/util.d.ts.map +1 -1
- package/build/util.js +12 -14
- package/package.json +15 -11
package/README.md
CHANGED
|
@@ -6,17 +6,7 @@ WebdriverIO Browserstack Service
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
The easiest way is to keep `@wdio/browserstack-service` as a devDependency in your `package.json
|
|
10
|
-
|
|
11
|
-
```json
|
|
12
|
-
{
|
|
13
|
-
"devDependencies": {
|
|
14
|
-
"@wdio/browserstack-service": "^7.16.3"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
You can simple do it by:
|
|
9
|
+
The easiest way is to keep `@wdio/browserstack-service` as a devDependency in your `package.json`, via:
|
|
20
10
|
|
|
21
11
|
```sh
|
|
22
12
|
npm install @wdio/browserstack-service --save-dev
|
|
@@ -67,6 +57,92 @@ Set this to true to kill the browserstack process on complete, without waiting f
|
|
|
67
57
|
Type: `Boolean`<br />
|
|
68
58
|
Default: `false`
|
|
69
59
|
|
|
60
|
+
### app
|
|
61
|
+
|
|
62
|
+
[Appium](https://appium.io/) set this with app file path available locally on your machine to use the app as [application under test](https://www.browserstack.com/docs/app-automate/appium/set-up-tests/specify-app) for Appium sessions.
|
|
63
|
+
|
|
64
|
+
Type: `String` or `JsonObject`<br />
|
|
65
|
+
Default: `undefined`
|
|
66
|
+
|
|
67
|
+
List of available app values:
|
|
68
|
+
|
|
69
|
+
#### path
|
|
70
|
+
|
|
71
|
+
Use local available app file path as application under test for appium.
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
services: [
|
|
75
|
+
['browserstack', {
|
|
76
|
+
app: '/path/to/local/app.apk'
|
|
77
|
+
// OR
|
|
78
|
+
app: {
|
|
79
|
+
path: '/path/to/local/app.apk'
|
|
80
|
+
}
|
|
81
|
+
}]
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Pass custom_id while app upload.
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
services: [
|
|
89
|
+
['browserstack', {
|
|
90
|
+
app: {
|
|
91
|
+
path: '/path/to/local/app.apk',
|
|
92
|
+
custom_id: 'custom_id'
|
|
93
|
+
}
|
|
94
|
+
}]
|
|
95
|
+
]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### id
|
|
99
|
+
|
|
100
|
+
Use app url returned after uploading app to BrowserStack.
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
services: [
|
|
104
|
+
['browserstack', {
|
|
105
|
+
app: 'bs://<app-id>'
|
|
106
|
+
// OR
|
|
107
|
+
app: {
|
|
108
|
+
id: 'bs://<app-id>'
|
|
109
|
+
}
|
|
110
|
+
}]
|
|
111
|
+
]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### custom_id
|
|
115
|
+
|
|
116
|
+
use custom_id of already uploaded apps
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
services: [
|
|
120
|
+
['browserstack', {
|
|
121
|
+
app: 'custom_id'
|
|
122
|
+
// OR
|
|
123
|
+
app: {
|
|
124
|
+
custom_id: 'custom_id'
|
|
125
|
+
}
|
|
126
|
+
}]
|
|
127
|
+
]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### shareable_id
|
|
131
|
+
|
|
132
|
+
use shareable_id of already uploaded apps
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
services: [
|
|
136
|
+
['browserstack', {
|
|
137
|
+
app: 'username/custom_id'
|
|
138
|
+
// OR
|
|
139
|
+
app: {
|
|
140
|
+
shareable_id: 'username/custom_id'
|
|
141
|
+
}
|
|
142
|
+
}]
|
|
143
|
+
]
|
|
144
|
+
```
|
|
145
|
+
|
|
70
146
|
### opts
|
|
71
147
|
Specified optional will be passed down to BrowserstackLocal.
|
|
72
148
|
|
package/build/constants.d.ts
CHANGED
package/build/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,qHAStB,CAAA"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,qHAStB,CAAA;AAEV,eAAO,MAAM,mBAAmB,UAI/B,CAAA"}
|
package/build/constants.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BROWSER_DESCRIPTION = void 0;
|
|
4
|
-
exports.BROWSER_DESCRIPTION = [
|
|
1
|
+
export const BROWSER_DESCRIPTION = [
|
|
5
2
|
'device',
|
|
6
3
|
'os',
|
|
7
4
|
'osVersion',
|
|
@@ -11,3 +8,8 @@ exports.BROWSER_DESCRIPTION = [
|
|
|
11
8
|
'browserVersion',
|
|
12
9
|
'browser_version'
|
|
13
10
|
];
|
|
11
|
+
export const VALID_APP_EXTENSION = [
|
|
12
|
+
'.apk',
|
|
13
|
+
'.aab',
|
|
14
|
+
'.ipa'
|
|
15
|
+
];
|
package/build/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import BrowserstackLauncher from './launcher';
|
|
2
|
-
import BrowserstackService from './service';
|
|
1
|
+
import BrowserstackLauncher from './launcher.js';
|
|
2
|
+
import BrowserstackService from './service.js';
|
|
3
3
|
import type { BrowserstackConfig } from './types';
|
|
4
4
|
export default BrowserstackService;
|
|
5
5
|
export declare const launcher: typeof BrowserstackLauncher;
|
|
6
|
-
export * from './types';
|
|
6
|
+
export * from './types.js';
|
|
7
7
|
declare global {
|
|
8
8
|
namespace WebdriverIO {
|
|
9
9
|
interface ServiceOption extends BrowserstackConfig {
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,MAAM,eAAe,CAAA;AAChD,OAAO,mBAAmB,MAAM,cAAc,CAAA;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjD,eAAe,mBAAmB,CAAA;AAClC,eAAO,MAAM,QAAQ,6BAAuB,CAAA;AAC5C,cAAc,YAAY,CAAA;AAE1B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW,CAAC;QAClB,UAAU,aAAc,SAAQ,kBAAkB;SAAG;KACxD;CACJ"}
|
package/build/index.js
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/* istanbul ignore file */
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
-
};
|
|
17
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
-
};
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.launcher = void 0;
|
|
22
|
-
const launcher_1 = __importDefault(require("./launcher"));
|
|
23
|
-
const service_1 = __importDefault(require("./service"));
|
|
24
|
-
exports.default = service_1.default;
|
|
25
|
-
exports.launcher = launcher_1.default;
|
|
26
|
-
__exportStar(require("./types"), exports);
|
|
2
|
+
import BrowserstackLauncher from './launcher.js';
|
|
3
|
+
import BrowserstackService from './service.js';
|
|
4
|
+
export default BrowserstackService;
|
|
5
|
+
export const launcher = BrowserstackLauncher;
|
|
6
|
+
export * from './types.js';
|
package/build/launcher.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as BrowserstackLocalLauncher from 'browserstack-local';
|
|
2
2
|
import type { Capabilities, Services, Options } from '@wdio/types';
|
|
3
|
-
import { BrowserstackConfig } from './types';
|
|
3
|
+
import type { BrowserstackConfig, App, AppConfig, AppUploadResponse } from './types';
|
|
4
4
|
declare type BrowserstackLocal = BrowserstackLocalLauncher.Local & {
|
|
5
5
|
pid?: number;
|
|
6
6
|
stop(callback: (err?: any) => void): void;
|
|
@@ -10,8 +10,15 @@ export default class BrowserstackLauncherService implements Services.ServiceInst
|
|
|
10
10
|
private _config;
|
|
11
11
|
browserstackLocal?: BrowserstackLocal;
|
|
12
12
|
constructor(_options: BrowserstackConfig & Options.Testrunner, capabilities: Capabilities.RemoteCapability, _config: Options.Testrunner);
|
|
13
|
-
onPrepare(config?: Options.Testrunner, capabilities?: Capabilities.RemoteCapabilities):
|
|
13
|
+
onPrepare(config?: Options.Testrunner, capabilities?: Capabilities.RemoteCapabilities): Promise<unknown>;
|
|
14
14
|
onComplete(): true | Promise<unknown> | undefined;
|
|
15
|
+
_uploadApp(app: App): Promise<AppUploadResponse>;
|
|
16
|
+
/**
|
|
17
|
+
* @param {String | AppConfig} appConfig <string>: should be "app file path" or "app_url" or "custom_id" or "shareable_id".
|
|
18
|
+
* <object>: only "path" and "custom_id" should coexist as multiple properties.
|
|
19
|
+
*/
|
|
20
|
+
_validateApp(appConfig: AppConfig | string): Promise<App>;
|
|
21
|
+
_updateCaps(capabilities?: Capabilities.RemoteCapabilities, capType?: string, value?: string): void;
|
|
15
22
|
}
|
|
16
23
|
export {};
|
|
17
24
|
//# sourceMappingURL=launcher.d.ts.map
|
package/build/launcher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,yBAAyB,MAAM,oBAAoB,CAAA;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAElE,OAAO,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAQpF,aAAK,iBAAiB,GAAG,yBAAyB,CAAC,KAAK,GAAG;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7C,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,2BAA4B,YAAW,QAAQ,CAAC,eAAe;IAI5E,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,OAAO;IALnB,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;gBAGzB,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACzD,YAAY,EAAE,YAAY,CAAC,gBAAgB,EACnC,OAAO,EAAE,OAAO,CAAC,UAAU;IAiCjC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA6E5F,UAAU;IAmCJ,UAAU,CAAC,GAAG,EAAC,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkBrD;;;OAGG;IACG,YAAY,CAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAyBhE,WAAW,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAC,MAAM;CA+C9F"}
|
package/build/launcher.js
CHANGED
|
@@ -1,39 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
const util_1 = require("util");
|
|
30
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
31
|
-
const BrowserstackLocalLauncher = __importStar(require("browserstack-local"));
|
|
32
|
-
const logger_1 = __importDefault(require("@wdio/logger"));
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
const package_json_1 = require("../package.json");
|
|
35
|
-
const log = (0, logger_1.default)('@wdio/browserstack-service');
|
|
36
|
-
class BrowserstackLauncherService {
|
|
1
|
+
import got from 'got';
|
|
2
|
+
import FormData from 'form-data';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import { performance, PerformanceObserver } from 'node:perf_hooks';
|
|
8
|
+
import { SevereServiceError } from 'webdriverio';
|
|
9
|
+
import * as BrowserstackLocalLauncher from 'browserstack-local';
|
|
10
|
+
import logger from '@wdio/logger';
|
|
11
|
+
import { VALID_APP_EXTENSION } from './constants.js';
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const { version: bstackServiceVersion } = require('../package.json');
|
|
14
|
+
const log = logger('@wdio/browserstack-service');
|
|
15
|
+
export default class BrowserstackLauncherService {
|
|
16
|
+
_options;
|
|
17
|
+
_config;
|
|
18
|
+
browserstackLocal;
|
|
37
19
|
constructor(_options, capabilities, _config) {
|
|
38
20
|
this._options = _options;
|
|
39
21
|
this._config = _config;
|
|
@@ -42,21 +24,70 @@ class BrowserstackLauncherService {
|
|
|
42
24
|
if (Array.isArray(capabilities)) {
|
|
43
25
|
capabilities.forEach((capability) => {
|
|
44
26
|
if (!capability['bstack:options']) {
|
|
45
|
-
capability
|
|
27
|
+
const extensionCaps = Object.keys(capability).filter((cap) => cap.includes(':'));
|
|
28
|
+
if (extensionCaps.length) {
|
|
29
|
+
capability['bstack:options'] = { wdioService: bstackServiceVersion };
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
capability['browserstack.wdioService'] = bstackServiceVersion;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
capability['bstack:options'].wdioService = bstackServiceVersion;
|
|
46
37
|
}
|
|
47
|
-
capability['bstack:options'].wdioService = package_json_1.version;
|
|
48
38
|
});
|
|
49
39
|
}
|
|
50
40
|
else if (typeof capabilities === 'object') {
|
|
51
41
|
Object.entries(capabilities).forEach(([, caps]) => {
|
|
52
42
|
if (!caps.capabilities['bstack:options']) {
|
|
53
|
-
caps.capabilities
|
|
43
|
+
const extensionCaps = Object.keys(caps.capabilities).filter((cap) => cap.includes(':'));
|
|
44
|
+
if (extensionCaps.length) {
|
|
45
|
+
caps.capabilities['bstack:options'] = { wdioService: bstackServiceVersion };
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
caps.capabilities['browserstack.wdioService'] = bstackServiceVersion;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
caps.capabilities['bstack:options'].wdioService = bstackServiceVersion;
|
|
54
53
|
}
|
|
55
|
-
caps.capabilities['bstack:options'].wdioService = package_json_1.version;
|
|
56
54
|
});
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
|
-
onPrepare(config, capabilities) {
|
|
57
|
+
async onPrepare(config, capabilities) {
|
|
58
|
+
/**
|
|
59
|
+
* Upload app to BrowserStack if valid file path to app is given.
|
|
60
|
+
* Update app value of capability directly if app_url, custom_id, shareable_id is given
|
|
61
|
+
*/
|
|
62
|
+
if (!this._options.app) {
|
|
63
|
+
log.info('app is not defined in browserstack-service config, skipping ...');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
let app = {};
|
|
67
|
+
let appConfig = this._options.app;
|
|
68
|
+
try {
|
|
69
|
+
app = await this._validateApp(appConfig);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new SevereServiceError(error);
|
|
73
|
+
}
|
|
74
|
+
if (VALID_APP_EXTENSION.includes(path.extname(app.app))) {
|
|
75
|
+
if (fs.existsSync(app.app)) {
|
|
76
|
+
let data;
|
|
77
|
+
data = await this._uploadApp(app);
|
|
78
|
+
log.info(`app upload completed: ${JSON.stringify(data)}`);
|
|
79
|
+
app.app = data.app_url;
|
|
80
|
+
}
|
|
81
|
+
else if (app.customId) {
|
|
82
|
+
app.app = app.customId;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new SevereServiceError(`[Invalid app path] app path ${app.app} is not correct, Provide correct path to app under test`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
log.info(`Using app: ${app.app}`);
|
|
89
|
+
this._updateCaps(capabilities, 'app', app.app);
|
|
90
|
+
}
|
|
60
91
|
if (!this._options.browserstackLocal) {
|
|
61
92
|
return log.info('browserstackLocal is not enabled - skipping...');
|
|
62
93
|
}
|
|
@@ -65,37 +96,19 @@ class BrowserstackLauncherService {
|
|
|
65
96
|
...this._options.opts
|
|
66
97
|
};
|
|
67
98
|
this.browserstackLocal = new BrowserstackLocalLauncher.Local();
|
|
68
|
-
|
|
69
|
-
capabilities.forEach((capability) => {
|
|
70
|
-
if (!capability['bstack:options']) {
|
|
71
|
-
capability['bstack:options'] = {};
|
|
72
|
-
}
|
|
73
|
-
capability['bstack:options'].local = true;
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
else if (typeof capabilities === 'object') {
|
|
77
|
-
Object.entries(capabilities).forEach(([, caps]) => {
|
|
78
|
-
if (!caps.capabilities['bstack:options']) {
|
|
79
|
-
caps.capabilities['bstack:options'] = {};
|
|
80
|
-
}
|
|
81
|
-
caps.capabilities['bstack:options'].local = true;
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
throw TypeError('Capabilities should be an object or Array!');
|
|
86
|
-
}
|
|
99
|
+
this._updateCaps(capabilities, 'local');
|
|
87
100
|
/**
|
|
88
|
-
* measure
|
|
101
|
+
* measure BrowserStack tunnel boot time
|
|
89
102
|
*/
|
|
90
|
-
const obs = new
|
|
103
|
+
const obs = new PerformanceObserver((list) => {
|
|
91
104
|
const entry = list.getEntries()[0];
|
|
92
105
|
log.info(`Browserstack Local successfully started after ${entry.duration}ms`);
|
|
93
106
|
});
|
|
94
107
|
obs.observe({ entryTypes: ['measure'] });
|
|
95
108
|
let timer;
|
|
96
|
-
|
|
109
|
+
performance.mark('tbTunnelStart');
|
|
97
110
|
return Promise.race([
|
|
98
|
-
|
|
111
|
+
promisify(this.browserstackLocal.start.bind(this.browserstackLocal))(opts),
|
|
99
112
|
new Promise((resolve, reject) => {
|
|
100
113
|
/* istanbul ignore next */
|
|
101
114
|
timer = setTimeout(function () {
|
|
@@ -104,8 +117,8 @@ class BrowserstackLauncherService {
|
|
|
104
117
|
})
|
|
105
118
|
]).then(function (result) {
|
|
106
119
|
clearTimeout(timer);
|
|
107
|
-
|
|
108
|
-
|
|
120
|
+
performance.mark('tbTunnelEnd');
|
|
121
|
+
performance.measure('bootTime', 'tbTunnelStart', 'tbTunnelEnd');
|
|
109
122
|
return Promise.resolve(result);
|
|
110
123
|
}, function (err) {
|
|
111
124
|
clearTimeout(timer);
|
|
@@ -122,8 +135,7 @@ class BrowserstackLauncherService {
|
|
|
122
135
|
let timer;
|
|
123
136
|
return Promise.race([
|
|
124
137
|
new Promise((resolve, reject) => {
|
|
125
|
-
|
|
126
|
-
(_a = this.browserstackLocal) === null || _a === void 0 ? void 0 : _a.stop((err) => {
|
|
138
|
+
this.browserstackLocal?.stop((err) => {
|
|
127
139
|
if (err) {
|
|
128
140
|
return reject(err);
|
|
129
141
|
}
|
|
@@ -142,5 +154,105 @@ class BrowserstackLauncherService {
|
|
|
142
154
|
return Promise.reject(err);
|
|
143
155
|
});
|
|
144
156
|
}
|
|
157
|
+
async _uploadApp(app) {
|
|
158
|
+
log.info(`uploading app ${app.app} ${app.customId ? `and custom_id: ${app.customId}` : ''} to browserstack`);
|
|
159
|
+
const form = new FormData();
|
|
160
|
+
if (app.app)
|
|
161
|
+
form.append('file', fs.createReadStream(app.app));
|
|
162
|
+
if (app.customId)
|
|
163
|
+
form.append('custom_id', app.customId);
|
|
164
|
+
const res = await got.post('https://api-cloud.browserstack.com/app-automate/upload', {
|
|
165
|
+
body: form,
|
|
166
|
+
username: this._config.user,
|
|
167
|
+
password: this._config.key
|
|
168
|
+
}).json().catch((err) => {
|
|
169
|
+
throw new SevereServiceError(`app upload failed ${err.message}`);
|
|
170
|
+
});
|
|
171
|
+
return res;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* @param {String | AppConfig} appConfig <string>: should be "app file path" or "app_url" or "custom_id" or "shareable_id".
|
|
175
|
+
* <object>: only "path" and "custom_id" should coexist as multiple properties.
|
|
176
|
+
*/
|
|
177
|
+
async _validateApp(appConfig) {
|
|
178
|
+
let app = {};
|
|
179
|
+
if (typeof appConfig === 'string') {
|
|
180
|
+
app.app = appConfig;
|
|
181
|
+
}
|
|
182
|
+
else if (typeof appConfig === 'object' && Object.keys(appConfig).length) {
|
|
183
|
+
if (Object.keys(appConfig).length > 2 || (Object.keys(appConfig).length === 2 && (!appConfig.path || !appConfig.custom_id))) {
|
|
184
|
+
throw new SevereServiceError(`keys ${Object.keys(appConfig)} can't co-exist as app values, use any one property from
|
|
185
|
+
{id<string>, path<string>, custom_id<string>, shareable_id<string>}, only "path" and "custom_id" can co-exist.`);
|
|
186
|
+
}
|
|
187
|
+
app.app = appConfig.id || appConfig.path || appConfig.custom_id || appConfig.shareable_id;
|
|
188
|
+
app.customId = appConfig.custom_id;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
throw new SevereServiceError('[Invalid format] app should be string or an object');
|
|
192
|
+
}
|
|
193
|
+
if (!app.app) {
|
|
194
|
+
throw new SevereServiceError(`[Invalid app property] supported properties are {id<string>, path<string>, custom_id<string>, shareable_id<string>}.
|
|
195
|
+
For more details please visit https://www.browserstack.com/docs/app-automate/appium/set-up-tests/specify-app ')`);
|
|
196
|
+
}
|
|
197
|
+
return app;
|
|
198
|
+
}
|
|
199
|
+
_updateCaps(capabilities, capType, value) {
|
|
200
|
+
if (Array.isArray(capabilities)) {
|
|
201
|
+
capabilities.forEach((capability) => {
|
|
202
|
+
if (!capability['bstack:options']) {
|
|
203
|
+
const extensionCaps = Object.keys(capability).filter((cap) => cap.includes(':'));
|
|
204
|
+
if (extensionCaps.length) {
|
|
205
|
+
if (capType === 'local') {
|
|
206
|
+
capability['bstack:options'] = { local: true };
|
|
207
|
+
}
|
|
208
|
+
else if (capType === 'app') {
|
|
209
|
+
capability['appium:app'] = value;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else if (capType === 'local') {
|
|
213
|
+
capability['browserstack.local'] = true;
|
|
214
|
+
}
|
|
215
|
+
else if (capType === 'app') {
|
|
216
|
+
capability['app'] = value;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else if (capType === 'local') {
|
|
220
|
+
capability['bstack:options'].local = true;
|
|
221
|
+
}
|
|
222
|
+
else if (capType === 'app') {
|
|
223
|
+
capability['appium:app'] = value;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
else if (typeof capabilities === 'object') {
|
|
228
|
+
Object.entries(capabilities).forEach(([, caps]) => {
|
|
229
|
+
if (!caps.capabilities['bstack:options']) {
|
|
230
|
+
const extensionCaps = Object.keys(caps.capabilities).filter((cap) => cap.includes(':'));
|
|
231
|
+
if (extensionCaps.length) {
|
|
232
|
+
if (capType === 'local') {
|
|
233
|
+
caps.capabilities['bstack:options'] = { local: true };
|
|
234
|
+
}
|
|
235
|
+
else if (capType === 'app') {
|
|
236
|
+
caps.capabilities['appium:app'] = value;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else if (capType === 'local') {
|
|
240
|
+
caps.capabilities['browserstack.local'] = true;
|
|
241
|
+
}
|
|
242
|
+
else if (capType === 'app') {
|
|
243
|
+
caps.capabilities['app'] = value;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else if (capType === 'local') {
|
|
247
|
+
caps.capabilities['bstack:options'].local = true;
|
|
248
|
+
}
|
|
249
|
+
else if (capType === 'app') {
|
|
250
|
+
caps.capabilities['appium:app'] = value;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
throw new SevereServiceError('Capabilities should be an object or Array!');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
145
258
|
}
|
|
146
|
-
exports.default = BrowserstackLauncherService;
|
package/build/service.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Services, Capabilities, Options, Frameworks } from '@wdio/types';
|
|
2
2
|
import type { Browser, MultiRemoteBrowser } from 'webdriverio';
|
|
3
|
-
import { BrowserstackConfig, MultiRemoteAction } from './types';
|
|
3
|
+
import type { BrowserstackConfig, MultiRemoteAction } from './types';
|
|
4
4
|
export default class BrowserstackService implements Services.ServiceInstance {
|
|
5
5
|
private _options;
|
|
6
6
|
private _caps;
|
package/build/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAG9D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAmB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAG9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAmB,MAAM,SAAS,CAAA;AAIrF,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,QAAQ,CAAC,eAAe;IASpE,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IAVnB,OAAO,CAAC,eAAe,CAAmD;IAC1E,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,iBAAiB,CAAe;IACxC,OAAO,CAAC,gBAAgB,CAA4D;IACpF,OAAO,CAAC,QAAQ,CAAC,CAAgD;IACjE,OAAO,CAAC,UAAU,CAAC,CAAQ;gBAGf,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EACjD,KAAK,EAAE,YAAY,CAAC,gBAAgB,EACpC,OAAO,EAAE,OAAO,CAAC,UAAU;IAYvC,WAAW,CAAE,EAAE,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC,YAAY,GAAG,YAAY,CAAC,mBAAmB,KAAK,IAAI;IAU7F;;;;OAIG;IACH,aAAa,CAAE,MAAM,EAAE,OAAO,CAAC,UAAU;IAYzC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC;IAepH,WAAW,CAAE,KAAK,EAAE,UAAU,CAAC,KAAK;IAIpC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IAKrD,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU;IAqB/E,KAAK,CAAE,MAAM,EAAE,MAAM;IAgBrB;;OAEG;IACH,aAAa,CAAE,KAAK,EAAE,UAAU,CAAC,KAAK;IAmBhC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IA2BzD,cAAc,IAAI,OAAO;IAOzB,UAAU,CAAE,WAAW,EAAE,GAAG;IAU5B,kBAAkB,CAAE,MAAM,EAAE,iBAAiB;IAqB7C,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG;IAUrC,gBAAgB;CAsBzB"}
|
package/build/service.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import logger from '@wdio/logger';
|
|
2
|
+
import got from 'got';
|
|
3
|
+
import { getBrowserDescription, getBrowserCapabilities, isBrowserstackCapability, getParentSuiteName } from './util.js';
|
|
4
|
+
const log = logger('@wdio/browserstack-service');
|
|
5
|
+
export default class BrowserstackService {
|
|
6
|
+
_options;
|
|
7
|
+
_caps;
|
|
8
|
+
_config;
|
|
9
|
+
_sessionBaseUrl = 'https://api.browserstack.com/automate/sessions';
|
|
10
|
+
_failReasons = [];
|
|
11
|
+
_scenariosThatRan = [];
|
|
12
|
+
_failureStatuses = ['failed', 'ambiguous', 'undefined', 'unknown'];
|
|
13
|
+
_browser;
|
|
14
|
+
_fullTitle;
|
|
11
15
|
constructor(_options, _caps, _config) {
|
|
12
16
|
this._options = _options;
|
|
13
17
|
this._caps = _caps;
|
|
14
18
|
this._config = _config;
|
|
15
|
-
this._sessionBaseUrl = 'https://api.browserstack.com/automate/sessions';
|
|
16
|
-
this._failReasons = [];
|
|
17
|
-
this._scenariosThatRan = [];
|
|
18
|
-
this._failureStatuses = ['failed', 'ambiguous', 'undefined', 'unknown'];
|
|
19
19
|
// added to maintain backward compatibility with webdriverIO v5
|
|
20
20
|
this._config || (this._config = _options);
|
|
21
21
|
// Cucumber specific
|
|
@@ -73,7 +73,7 @@ class BrowserstackService {
|
|
|
73
73
|
this._fullTitle = testSuiteName;
|
|
74
74
|
}
|
|
75
75
|
else if (this._fullTitle) {
|
|
76
|
-
this._fullTitle =
|
|
76
|
+
this._fullTitle = getParentSuiteName(this._fullTitle, testSuiteName);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
@@ -101,8 +101,7 @@ class BrowserstackService {
|
|
|
101
101
|
* For CucumberJS
|
|
102
102
|
*/
|
|
103
103
|
afterScenario(world) {
|
|
104
|
-
|
|
105
|
-
const status = (_a = world.result) === null || _a === void 0 ? void 0 : _a.status.toLowerCase();
|
|
104
|
+
const status = world.result?.status.toLowerCase();
|
|
106
105
|
if (status !== 'skipped') {
|
|
107
106
|
this._scenariosThatRan.push(world.pickle.name || 'unknown pickle name');
|
|
108
107
|
}
|
|
@@ -138,9 +137,8 @@ class BrowserstackService {
|
|
|
138
137
|
await this._printSessionURL();
|
|
139
138
|
}
|
|
140
139
|
_isAppAutomate() {
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
const desiredCapabilities = ((_c = this._caps) !== null && _c !== void 0 ? _c : {});
|
|
140
|
+
const browserDesiredCapabilities = (this._browser?.capabilities ?? {});
|
|
141
|
+
const desiredCapabilities = (this._caps ?? {});
|
|
144
142
|
return !!browserDesiredCapabilities['appium:app'] || !!desiredCapabilities['appium:app'] || !!browserDesiredCapabilities.app || !!desiredCapabilities.app;
|
|
145
143
|
}
|
|
146
144
|
_updateJob(requestBody) {
|
|
@@ -160,16 +158,16 @@ class BrowserstackService {
|
|
|
160
158
|
return action(_browser.sessionId);
|
|
161
159
|
}
|
|
162
160
|
return Promise.all(_browser.instances
|
|
163
|
-
.filter(browserName => {
|
|
164
|
-
const cap =
|
|
165
|
-
return
|
|
161
|
+
.filter((browserName) => {
|
|
162
|
+
const cap = getBrowserCapabilities(_browser, this._caps, browserName);
|
|
163
|
+
return isBrowserstackCapability(cap);
|
|
166
164
|
})
|
|
167
165
|
.map((browserName) => (action(_browser[browserName].sessionId, browserName))));
|
|
168
166
|
}
|
|
169
167
|
_update(sessionId, requestBody) {
|
|
170
168
|
const sessionUrl = `${this._sessionBaseUrl}/${sessionId}.json`;
|
|
171
169
|
log.debug(`Updating Browserstack session at ${sessionUrl} with request body: `, requestBody);
|
|
172
|
-
return
|
|
170
|
+
return got.put(sessionUrl, {
|
|
173
171
|
json: requestBody,
|
|
174
172
|
username: this._config.user,
|
|
175
173
|
password: this._config.key
|
|
@@ -182,7 +180,7 @@ class BrowserstackService {
|
|
|
182
180
|
await this._multiRemoteAction(async (sessionId, browserName) => {
|
|
183
181
|
const sessionUrl = `${this._sessionBaseUrl}/${sessionId}.json`;
|
|
184
182
|
log.debug(`Requesting Browserstack session URL at ${sessionUrl}`);
|
|
185
|
-
const response = await (
|
|
183
|
+
const response = await got(sessionUrl, {
|
|
186
184
|
username: this._config.user,
|
|
187
185
|
password: this._config.key,
|
|
188
186
|
responseType: 'json'
|
|
@@ -190,10 +188,9 @@ class BrowserstackService {
|
|
|
190
188
|
if (!this._browser) {
|
|
191
189
|
return;
|
|
192
190
|
}
|
|
193
|
-
const capabilities =
|
|
194
|
-
const browserString =
|
|
191
|
+
const capabilities = getBrowserCapabilities(this._browser, this._caps, browserName);
|
|
192
|
+
const browserString = getBrowserDescription(capabilities);
|
|
195
193
|
log.info(`${browserString} session: ${response.body.automation_session.browser_url}`);
|
|
196
194
|
});
|
|
197
195
|
}
|
|
198
196
|
}
|
|
199
|
-
exports.default = BrowserstackService;
|
package/build/types.d.ts
CHANGED
|
@@ -4,12 +4,33 @@ export interface SessionResponse {
|
|
|
4
4
|
};
|
|
5
5
|
}
|
|
6
6
|
export declare type MultiRemoteAction = (sessionId: string, browserName?: string) => Promise<any>;
|
|
7
|
+
export declare type AppConfig = {
|
|
8
|
+
id?: string;
|
|
9
|
+
path?: string;
|
|
10
|
+
custom_id?: string;
|
|
11
|
+
shareable_id?: string;
|
|
12
|
+
};
|
|
13
|
+
export interface AppUploadResponse {
|
|
14
|
+
app_url?: string;
|
|
15
|
+
custom_id?: string;
|
|
16
|
+
shareable_id?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface App {
|
|
19
|
+
app?: string;
|
|
20
|
+
customId?: string;
|
|
21
|
+
}
|
|
7
22
|
export interface BrowserstackConfig {
|
|
8
23
|
/**
|
|
9
24
|
* Set this to true to enable routing connections from Browserstack cloud through your computer.
|
|
10
25
|
* You will also need to set `browserstack.local` to true in browser capabilities.
|
|
11
26
|
*/
|
|
12
27
|
browserstackLocal?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Set this with app file path present locally on your device or
|
|
30
|
+
* app hashed id returned after uploading app to Browserstack or
|
|
31
|
+
* custom_id, sharable_id of the uploaded app
|
|
32
|
+
*/
|
|
33
|
+
app?: string | AppConfig;
|
|
13
34
|
/**
|
|
14
35
|
* Cucumber only. Set this to true to enable updating the session name to the Scenario name if only
|
|
15
36
|
* a single Scenario was ran. Useful when running in parallel
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAE5B,kBAAkB,EAAE;QAEhB,WAAW,EAAE,MAAM,CAAA;KACtB,CAAA;CACJ;AAED,oBAAY,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE1F,MAAM,WAAW,kBAAkB;IAC/B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAA;CACvD"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAE5B,kBAAkB,EAAE;QAEhB,WAAW,EAAE,MAAM,CAAA;KACtB,CAAA;CACJ;AAED,oBAAY,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE1F,oBAAY,SAAS,GAAG;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,GAAG;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,kBAAkB;IAC/B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAA;CACvD"}
|
package/build/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/build/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/C;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,CAAC,mBAAmB,UAa1E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,YAAY,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,MAAM,6BASzJ;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/C;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,CAAC,mBAAmB,UAa1E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,YAAY,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,MAAM,6BASzJ;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,YAAY,WAWvE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAUpF"}
|
package/build/util.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getParentSuiteName = exports.isBrowserstackCapability = exports.getBrowserCapabilities = exports.getBrowserDescription = void 0;
|
|
4
|
-
const constants_1 = require("./constants");
|
|
1
|
+
import { BROWSER_DESCRIPTION } from './constants.js';
|
|
5
2
|
/**
|
|
6
3
|
* get browser description for Browserstack service
|
|
7
4
|
* @param cap browser capablities
|
|
8
5
|
*/
|
|
9
|
-
function getBrowserDescription(cap) {
|
|
6
|
+
export function getBrowserDescription(cap) {
|
|
10
7
|
cap = cap || {};
|
|
11
8
|
if (cap['bstack:options']) {
|
|
12
9
|
cap = { ...cap, ...cap['bstack:options'] };
|
|
@@ -14,19 +11,18 @@ function getBrowserDescription(cap) {
|
|
|
14
11
|
/**
|
|
15
12
|
* These keys describe the browser the test was run on
|
|
16
13
|
*/
|
|
17
|
-
return
|
|
14
|
+
return BROWSER_DESCRIPTION
|
|
18
15
|
.map((k) => cap[k])
|
|
19
16
|
.filter(Boolean)
|
|
20
17
|
.join(' ');
|
|
21
18
|
}
|
|
22
|
-
exports.getBrowserDescription = getBrowserDescription;
|
|
23
19
|
/**
|
|
24
20
|
* get correct browser capabilities object in both multiremote and normal setups
|
|
25
21
|
* @param browser browser object
|
|
26
22
|
* @param caps browser capbilities object. In case of multiremote, the object itself should have a property named 'capabilities'
|
|
27
23
|
* @param browserName browser name in case of multiremote
|
|
28
24
|
*/
|
|
29
|
-
function getBrowserCapabilities(browser, caps, browserName) {
|
|
25
|
+
export function getBrowserCapabilities(browser, caps, browserName) {
|
|
30
26
|
if (!browser.isMultiremote) {
|
|
31
27
|
return { ...browser.capabilities, ...caps };
|
|
32
28
|
}
|
|
@@ -35,16 +31,19 @@ function getBrowserCapabilities(browser, caps, browserName) {
|
|
|
35
31
|
const cap = browserName && multiCaps[browserName] ? multiCaps[browserName].capabilities : {};
|
|
36
32
|
return { ...globalCap, ...cap };
|
|
37
33
|
}
|
|
38
|
-
exports.getBrowserCapabilities = getBrowserCapabilities;
|
|
39
34
|
/**
|
|
40
35
|
* check for browserstack W3C capabilities. Does not support legacy capabilities
|
|
41
36
|
* @param cap browser capabilities
|
|
42
37
|
*/
|
|
43
|
-
function isBrowserstackCapability(cap) {
|
|
44
|
-
return Boolean(cap &&
|
|
38
|
+
export function isBrowserstackCapability(cap) {
|
|
39
|
+
return Boolean(cap &&
|
|
40
|
+
cap['bstack:options'] &&
|
|
41
|
+
// return false if the only cap in bstack:options is wdioService,
|
|
42
|
+
// as that is added by the service and not present in user passed caps
|
|
43
|
+
!(Object.keys(cap['bstack:options']).length === 1 &&
|
|
44
|
+
cap['bstack:options'].wdioService));
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
function getParentSuiteName(fullTitle, testSuiteTitle) {
|
|
46
|
+
export function getParentSuiteName(fullTitle, testSuiteTitle) {
|
|
48
47
|
const fullTitleWords = fullTitle.split(' ');
|
|
49
48
|
const testSuiteTitleWords = testSuiteTitle.split(' ');
|
|
50
49
|
const shortestLength = Math.min(fullTitleWords.length, testSuiteTitleWords.length);
|
|
@@ -55,4 +54,3 @@ function getParentSuiteName(fullTitle, testSuiteTitle) {
|
|
|
55
54
|
}
|
|
56
55
|
return parentSuiteName.trim();
|
|
57
56
|
}
|
|
58
|
-
exports.getParentSuiteName = getParentSuiteName;
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wdio/browserstack-service",
|
|
3
|
-
"version": "7.20.
|
|
3
|
+
"version": "7.20.8-alpha.504+428a9d729",
|
|
4
4
|
"description": "WebdriverIO service for better Browserstack integration",
|
|
5
5
|
"author": "Adam Bjerstedt <abjerstedt@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-browserstack-service",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"main": "./build",
|
|
9
8
|
"engines": {
|
|
10
|
-
"node": ">=
|
|
9
|
+
"node": "^16.13 || >=18"
|
|
11
10
|
},
|
|
12
11
|
"repository": {
|
|
13
12
|
"type": "git",
|
|
14
|
-
"url": "git://github.com/webdriverio/webdriverio.git"
|
|
13
|
+
"url": "git://github.com/webdriverio/webdriverio.git",
|
|
14
|
+
"directory": "packages/wdio-browserstack-service"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
17
17
|
"webdriverio",
|
|
@@ -22,13 +22,18 @@
|
|
|
22
22
|
"bugs": {
|
|
23
23
|
"url": "https://github.com/webdriverio/webdriverio/issues"
|
|
24
24
|
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": "./build/index.js",
|
|
27
|
+
"types": "./build/index.d.ts",
|
|
28
|
+
"typeScriptVersion": "3.8.3",
|
|
25
29
|
"dependencies": {
|
|
26
30
|
"@types/node": "^18.0.0",
|
|
27
|
-
"@wdio/logger": "7.
|
|
28
|
-
"@wdio/types": "7.20.
|
|
29
|
-
"browserstack-local": "^1.
|
|
30
|
-
"
|
|
31
|
-
"
|
|
31
|
+
"@wdio/logger": "7.20.8-alpha.504+428a9d729",
|
|
32
|
+
"@wdio/types": "7.20.8-alpha.504+428a9d729",
|
|
33
|
+
"browserstack-local": "^1.5.1",
|
|
34
|
+
"form-data": "^4.0.0",
|
|
35
|
+
"got": "^12.1.0",
|
|
36
|
+
"webdriverio": "7.20.8-alpha.504+428a9d729"
|
|
32
37
|
},
|
|
33
38
|
"peerDependencies": {
|
|
34
39
|
"@wdio/cli": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
@@ -36,6 +41,5 @@
|
|
|
36
41
|
"publishConfig": {
|
|
37
42
|
"access": "public"
|
|
38
43
|
},
|
|
39
|
-
"
|
|
40
|
-
"gitHead": "fa9e48262ff068012040bdff88675502acaf648b"
|
|
44
|
+
"gitHead": "428a9d729ae6231968a60908732fa3f607d195e9"
|
|
41
45
|
}
|