@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 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
 
@@ -1,2 +1,3 @@
1
1
  export declare const BROWSER_DESCRIPTION: readonly ["device", "os", "osVersion", "os_version", "browserName", "browser", "browserVersion", "browser_version"];
2
+ export declare const VALID_APP_EXTENSION: string[];
2
3
  //# sourceMappingURL=constants.d.ts.map
@@ -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"}
@@ -1,7 +1,4 @@
1
- "use strict";
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 {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,MAAM,YAAY,CAAA;AAC7C,OAAO,mBAAmB,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjD,eAAe,mBAAmB,CAAA;AAClC,eAAO,MAAM,QAAQ,6BAAuB,CAAA;AAC5C,cAAc,SAAS,CAAA;AAEvB,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW,CAAC;QAClB,UAAU,aAAc,SAAQ,kBAAkB;SAAG;KACxD;CACJ"}
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
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
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';
@@ -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): void | Promise<unknown>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,yBAAyB,MAAM,oBAAoB,CAAA;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAIlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAI5C,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;IAqBvC,SAAS,CAAE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB;IA6DtF,UAAU;CAkCb"}
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
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
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['bstack:options'] = {};
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['bstack:options'] = {};
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
- if (Array.isArray(capabilities)) {
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 TestingBot tunnel boot time
101
+ * measure BrowserStack tunnel boot time
89
102
  */
90
- const obs = new perf_hooks_1.PerformanceObserver((list) => {
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
- perf_hooks_1.performance.mark('tbTunnelStart');
109
+ performance.mark('tbTunnelStart');
97
110
  return Promise.race([
98
- (0, util_1.promisify)(this.browserstackLocal.start.bind(this.browserstackLocal))(opts),
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
- perf_hooks_1.performance.mark('tbTunnelEnd');
108
- perf_hooks_1.performance.measure('bootTime', 'tbTunnelStart', 'tbTunnelEnd');
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
- var _a;
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;
@@ -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;
@@ -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;AAIhF,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"}
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
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const logger_1 = __importDefault(require("@wdio/logger"));
7
- const got_1 = __importDefault(require("got"));
8
- const util_1 = require("./util");
9
- const log = (0, logger_1.default)('@wdio/browserstack-service');
10
- class BrowserstackService {
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 = (0, util_1.getParentSuiteName)(this._fullTitle, testSuiteName);
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
- var _a;
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
- var _a, _b, _c;
142
- const browserDesiredCapabilities = ((_b = (_a = this._browser) === null || _a === void 0 ? void 0 : _a.capabilities) !== null && _b !== void 0 ? _b : {});
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 = (0, util_1.getBrowserCapabilities)(_browser, this._caps, browserName);
165
- return (0, util_1.isBrowserstackCapability)(cap);
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 got_1.default.put(sessionUrl, {
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 (0, got_1.default)(sessionUrl, {
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 = (0, util_1.getBrowserCapabilities)(this._browser, this._caps, browserName);
194
- const browserString = (0, util_1.getBrowserDescription)(capabilities);
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
@@ -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
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -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,WAEvE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAUpF"}
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
- "use strict";
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 constants_1.BROWSER_DESCRIPTION
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 && cap['bstack:options']);
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
- exports.isBrowserstackCapability = isBrowserstackCapability;
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.6",
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": ">=12.0.0"
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.19.0",
28
- "@wdio/types": "7.20.3",
29
- "browserstack-local": "^1.4.5",
30
- "got": "^11.0.2",
31
- "webdriverio": "7.20.6"
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
- "types": "./build/index.d.ts",
40
- "gitHead": "fa9e48262ff068012040bdff88675502acaf648b"
44
+ "gitHead": "428a9d729ae6231968a60908732fa3f607d195e9"
41
45
  }