codeceptjs 4.0.0-beta.1 → 4.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/bin/codecept.js +84 -81
  2. package/lib/actor.js +13 -13
  3. package/lib/ai.js +10 -13
  4. package/lib/assert/empty.js +20 -21
  5. package/lib/assert/equal.js +37 -39
  6. package/lib/assert/error.js +14 -14
  7. package/lib/assert/include.js +46 -47
  8. package/lib/assert/throws.js +13 -11
  9. package/lib/assert/truth.js +19 -22
  10. package/lib/assert.js +4 -2
  11. package/lib/cli.js +57 -49
  12. package/lib/codecept.js +142 -155
  13. package/lib/colorUtils.js +3 -3
  14. package/lib/command/configMigrate.js +58 -52
  15. package/lib/command/definitions.js +88 -89
  16. package/lib/command/dryRun.js +71 -68
  17. package/lib/command/generate.js +197 -188
  18. package/lib/command/gherkin/init.js +27 -16
  19. package/lib/command/gherkin/snippets.js +20 -20
  20. package/lib/command/gherkin/steps.js +8 -8
  21. package/lib/command/info.js +40 -38
  22. package/lib/command/init.js +290 -288
  23. package/lib/command/interactive.js +32 -32
  24. package/lib/command/list.js +26 -26
  25. package/lib/command/run-multiple/chunk.js +5 -5
  26. package/lib/command/run-multiple/collection.js +3 -3
  27. package/lib/command/run-multiple/run.js +6 -2
  28. package/lib/command/run-multiple.js +113 -93
  29. package/lib/command/run-rerun.js +20 -25
  30. package/lib/command/run-workers.js +64 -66
  31. package/lib/command/run.js +26 -29
  32. package/lib/command/utils.js +80 -65
  33. package/lib/command/workers/runTests.js +10 -10
  34. package/lib/config.js +10 -9
  35. package/lib/container.js +40 -48
  36. package/lib/data/context.js +60 -59
  37. package/lib/data/dataScenarioConfig.js +47 -47
  38. package/lib/data/dataTableArgument.js +29 -29
  39. package/lib/data/table.js +26 -20
  40. package/lib/event.js +163 -167
  41. package/lib/heal.js +13 -17
  42. package/lib/helper/AI.js +130 -41
  43. package/lib/helper/ApiDataFactory.js +73 -69
  44. package/lib/helper/Appium.js +413 -382
  45. package/lib/helper/ExpectHelper.js +40 -48
  46. package/lib/helper/FileSystem.js +80 -79
  47. package/lib/helper/GraphQL.js +44 -43
  48. package/lib/helper/GraphQLDataFactory.js +50 -50
  49. package/lib/helper/JSONResponse.js +65 -62
  50. package/lib/helper/Mochawesome.js +28 -28
  51. package/lib/helper/MockServer.js +12 -14
  52. package/lib/helper/Nightmare.js +662 -566
  53. package/lib/helper/Playwright.js +1361 -1216
  54. package/lib/helper/Protractor.js +663 -627
  55. package/lib/helper/Puppeteer.js +1231 -1128
  56. package/lib/helper/REST.js +159 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -484
  59. package/lib/helper/WebDriver.js +1297 -1156
  60. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  61. package/lib/helper/errors/ConnectionRefused.js +1 -1
  62. package/lib/helper/errors/ElementAssertion.js +2 -2
  63. package/lib/helper/errors/ElementNotFound.js +2 -2
  64. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  65. package/lib/helper/extras/Console.js +1 -1
  66. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  67. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  68. package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
  69. package/lib/helper/extras/Popup.js +1 -1
  70. package/lib/helper/extras/React.js +3 -3
  71. package/lib/helper/network/actions.js +14 -7
  72. package/lib/helper/network/utils.js +3 -2
  73. package/lib/helper/scripts/blurElement.js +1 -1
  74. package/lib/helper/scripts/focusElement.js +1 -1
  75. package/lib/helper/scripts/highlightElement.js +1 -1
  76. package/lib/helper/scripts/isElementClickable.js +1 -1
  77. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  78. package/lib/helper/testcafe/testcafe-utils.js +6 -7
  79. package/lib/helper.js +1 -3
  80. package/lib/history.js +6 -5
  81. package/lib/hooks.js +6 -6
  82. package/lib/html.js +7 -7
  83. package/lib/index.js +25 -41
  84. package/lib/interfaces/bdd.js +47 -64
  85. package/lib/interfaces/featureConfig.js +19 -19
  86. package/lib/interfaces/gherkin.js +124 -118
  87. package/lib/interfaces/scenarioConfig.js +29 -29
  88. package/lib/listener/artifacts.js +9 -9
  89. package/lib/listener/config.js +24 -24
  90. package/lib/listener/exit.js +12 -12
  91. package/lib/listener/helpers.js +42 -42
  92. package/lib/listener/mocha.js +11 -11
  93. package/lib/listener/retry.js +32 -30
  94. package/lib/listener/steps.js +50 -53
  95. package/lib/listener/timeout.js +54 -54
  96. package/lib/locator.js +6 -10
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +6 -10
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +40 -33
  101. package/lib/plugin/allure.js +15 -15
  102. package/lib/plugin/autoDelay.js +29 -37
  103. package/lib/plugin/autoLogin.js +70 -65
  104. package/lib/plugin/commentStep.js +18 -18
  105. package/lib/plugin/coverage.js +115 -67
  106. package/lib/plugin/customLocator.js +21 -20
  107. package/lib/plugin/debugErrors.js +24 -24
  108. package/lib/plugin/eachElement.js +38 -38
  109. package/lib/plugin/fakerTransform.js +6 -6
  110. package/lib/plugin/heal.js +67 -108
  111. package/lib/plugin/pauseOnFail.js +11 -11
  112. package/lib/plugin/retryFailedStep.js +32 -39
  113. package/lib/plugin/retryTo.js +46 -40
  114. package/lib/plugin/screenshotOnFail.js +109 -87
  115. package/lib/plugin/selenoid.js +131 -118
  116. package/lib/plugin/standardActingHelpers.js +2 -8
  117. package/lib/plugin/stepByStepReport.js +110 -91
  118. package/lib/plugin/stepTimeout.js +24 -23
  119. package/lib/plugin/subtitles.js +34 -35
  120. package/lib/plugin/tryTo.js +40 -30
  121. package/lib/plugin/wdio.js +78 -75
  122. package/lib/recorder.js +14 -17
  123. package/lib/rerun.js +11 -10
  124. package/lib/scenario.js +25 -23
  125. package/lib/secret.js +4 -2
  126. package/lib/session.js +10 -10
  127. package/lib/step.js +12 -9
  128. package/lib/store.js +2 -3
  129. package/lib/transform.js +1 -1
  130. package/lib/translation.js +7 -8
  131. package/lib/ui.js +12 -14
  132. package/lib/utils.js +70 -72
  133. package/lib/within.js +10 -10
  134. package/lib/workerStorage.js +27 -25
  135. package/lib/workers.js +29 -32
  136. package/package.json +56 -57
  137. package/translations/de-DE.js +1 -1
  138. package/translations/fr-FR.js +1 -1
  139. package/translations/index.js +9 -13
  140. package/translations/it-IT.js +1 -1
  141. package/translations/ja-JP.js +1 -1
  142. package/translations/pl-PL.js +1 -1
  143. package/translations/pt-BR.js +1 -1
  144. package/translations/ru-RU.js +1 -1
  145. package/translations/zh-CN.js +1 -1
  146. package/translations/zh-TW.js +1 -1
  147. package/typings/index.d.ts +415 -65
  148. package/typings/promiseBasedTypes.d.ts +32 -0
  149. package/typings/types.d.ts +32 -0
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
@@ -1,25 +1,26 @@
1
- import fs from 'fs';
2
- import { default as axios } from 'axios';
3
- import { v4 as uuidv4 } from 'uuid';
4
- import Webdriver from './WebDriver';
5
- import AssertionFailedError from '../assert/error.js';
6
- import { truth } from '../assert/truth';
7
- import recorder from '../recorder.js';
8
- import Locator from '../locator.js';
9
- import ConnectionRefused from './errors/ConnectionRefused.js';
10
-
11
- let webdriverio;
12
-
13
- const mobileRoot = '//*';
14
- const webRoot = 'body';
1
+ let webdriverio
2
+
3
+ const fs = require('fs')
4
+ const axios = require('axios').default
5
+ const { v4: uuidv4 } = require('uuid')
6
+
7
+ const Webdriver = require('./WebDriver')
8
+ const AssertionFailedError = require('../assert/error')
9
+ const { truth } = require('../assert/truth')
10
+ const recorder = require('../recorder')
11
+ const Locator = require('../locator')
12
+ const ConnectionRefused = require('./errors/ConnectionRefused')
13
+
14
+ const mobileRoot = '//*'
15
+ const webRoot = 'body'
15
16
  const supportedPlatform = {
16
17
  android: 'Android',
17
18
  iOS: 'iOS',
18
- };
19
+ }
19
20
 
20
21
  const vendorPrefix = {
21
22
  appium: 'appium',
22
- };
23
+ }
23
24
 
24
25
  /**
25
26
  * Appium helper extends [Webdriver](http://codecept.io/helpers/WebDriver/) helper.
@@ -174,19 +175,21 @@ class Appium extends Webdriver {
174
175
 
175
176
  // @ts-ignore
176
177
  constructor(config) {
177
- super(config);
178
+ super(config)
178
179
 
179
- this.isRunning = false;
180
+ this.isRunning = false
180
181
  if (config.appiumV2 === true) {
181
- this.appiumV2 = true;
182
+ this.appiumV2 = true
182
183
  }
183
- this.axios = axios.create();
184
+ this.axios = axios.create()
184
185
 
185
- webdriverio = require('webdriverio');
186
+ webdriverio = require('webdriverio')
186
187
  if (!config.appiumV2) {
187
- console.log('The Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. Please migrating to Appium 2.x by adding appiumV2: true to your config.');
188
- console.log('More info: https://bit.ly/appium-v2-migration');
189
- console.log('This Appium 1.x support will be removed in next major release.');
188
+ console.log(
189
+ 'The Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. Please migrating to Appium 2.x by adding appiumV2: true to your config.',
190
+ )
191
+ console.log('More info: https://bit.ly/appium-v2-migration')
192
+ console.log('This Appium 1.x support will be removed in next major release.')
190
193
  }
191
194
  }
192
195
 
@@ -203,7 +206,7 @@ class Appium extends Webdriver {
203
206
  }
204
207
  }
205
208
  }
206
- `);
209
+ `)
207
210
  }
208
211
 
209
212
  // set defaults
@@ -224,166 +227,174 @@ class Appium extends Webdriver {
224
227
  timeouts: {
225
228
  script: 0, // ms
226
229
  },
227
- };
230
+ }
228
231
 
229
232
  // override defaults with config
230
- config = Object.assign(defaults, config);
233
+ config = Object.assign(defaults, config)
231
234
 
232
- config.baseUrl = config.url || config.baseUrl;
235
+ config.baseUrl = config.url || config.baseUrl
233
236
  if (config.desiredCapabilities && Object.keys(config.desiredCapabilities).length) {
234
- config.capabilities = this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities;
237
+ config.capabilities =
238
+ this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities
235
239
  }
236
240
 
237
241
  if (this.appiumV2) {
238
- config.capabilities[`${vendorPrefix.appium}:deviceName`] = config[`${vendorPrefix.appium}:device`] || config.capabilities[`${vendorPrefix.appium}:deviceName`];
239
- config.capabilities[`${vendorPrefix.appium}:browserName`] = config[`${vendorPrefix.appium}:browser`] || config.capabilities[`${vendorPrefix.appium}:browserName`];
240
- config.capabilities[`${vendorPrefix.appium}:app`] = config[`${vendorPrefix.appium}:app`] || config.capabilities[`${vendorPrefix.appium}:app`];
241
- config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] = config[`${vendorPrefix.appium}:tunnelIdentifier`] || config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`]; // Adding the code to connect to sauce labs via sauce tunnel
242
+ config.capabilities[`${vendorPrefix.appium}:deviceName`] =
243
+ config[`${vendorPrefix.appium}:device`] || config.capabilities[`${vendorPrefix.appium}:deviceName`]
244
+ config.capabilities[`${vendorPrefix.appium}:browserName`] =
245
+ config[`${vendorPrefix.appium}:browser`] || config.capabilities[`${vendorPrefix.appium}:browserName`]
246
+ config.capabilities[`${vendorPrefix.appium}:app`] =
247
+ config[`${vendorPrefix.appium}:app`] || config.capabilities[`${vendorPrefix.appium}:app`]
248
+ config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] =
249
+ config[`${vendorPrefix.appium}:tunnelIdentifier`] ||
250
+ config.capabilities[`${vendorPrefix.appium}:tunnelIdentifier`] // Adding the code to connect to sauce labs via sauce tunnel
242
251
  } else {
243
- config.capabilities.deviceName = config.device || config.capabilities.deviceName;
244
- config.capabilities.browserName = config.browser || config.capabilities.browserName;
245
- config.capabilities.app = config.app || config.capabilities.app;
246
- config.capabilities.tunnelIdentifier = config.tunnelIdentifier || config.capabilities.tunnelIdentifier; // Adding the code to connect to sauce labs via sauce tunnel
252
+ config.capabilities.deviceName = config.device || config.capabilities.deviceName
253
+ config.capabilities.browserName = config.browser || config.capabilities.browserName
254
+ config.capabilities.app = config.app || config.capabilities.app
255
+ config.capabilities.tunnelIdentifier = config.tunnelIdentifier || config.capabilities.tunnelIdentifier // Adding the code to connect to sauce labs via sauce tunnel
247
256
  }
248
257
 
249
- config.capabilities.platformName = config.platform || config.capabilities.platformName;
250
- config.waitForTimeoutInSeconds = config.waitForTimeout / 1000; // convert to seconds
258
+ config.capabilities.platformName = config.platform || config.capabilities.platformName
259
+ config.waitForTimeoutInSeconds = config.waitForTimeout / 1000 // convert to seconds
251
260
 
252
261
  // [CodeceptJS compatible] transform host to hostname
253
- config.hostname = config.host || config.hostname;
262
+ config.hostname = config.host || config.hostname
254
263
 
255
264
  if (!config.app && config.capabilities.browserName) {
256
- this.isWeb = true;
257
- this.root = webRoot;
265
+ this.isWeb = true
266
+ this.root = webRoot
258
267
  } else {
259
- this.isWeb = false;
260
- this.root = mobileRoot;
268
+ this.isWeb = false
269
+ this.root = mobileRoot
261
270
  }
262
271
 
263
- this.platform = null;
272
+ this.platform = null
264
273
  if (config.capabilities[`${vendorPrefix.appium}:platformName`]) {
265
- this.platform = config.capabilities[`${vendorPrefix.appium}:platformName`].toLowerCase();
274
+ this.platform = config.capabilities[`${vendorPrefix.appium}:platformName`].toLowerCase()
266
275
  }
267
276
 
268
277
  if (config.capabilities.platformName) {
269
- this.platform = config.capabilities.platformName.toLowerCase();
278
+ this.platform = config.capabilities.platformName.toLowerCase()
270
279
  }
271
280
 
272
- return config;
281
+ return config
273
282
  }
274
283
 
275
284
  _convertAppiumV2Caps(capabilities) {
276
- const _convertedCaps = {};
285
+ const _convertedCaps = {}
277
286
  for (const [key, value] of Object.entries(capabilities)) {
278
287
  if (!key.startsWith(vendorPrefix.appium)) {
279
288
  if (key !== 'platformName' && key !== 'bstack:options') {
280
- _convertedCaps[`${vendorPrefix.appium}:${key}`] = value;
289
+ _convertedCaps[`${vendorPrefix.appium}:${key}`] = value
281
290
  } else {
282
- _convertedCaps[`${key}`] = value;
291
+ _convertedCaps[`${key}`] = value
283
292
  }
284
293
  } else {
285
- _convertedCaps[`${key}`] = value;
294
+ _convertedCaps[`${key}`] = value
286
295
  }
287
296
  }
288
- return _convertedCaps;
297
+ return _convertedCaps
289
298
  }
290
299
 
291
300
  static _config() {
292
- return [{
293
- name: 'app',
294
- message: 'Application package. Path to file or url',
295
- default: 'http://localhost',
296
- }, {
297
- name: 'platform',
298
- message: 'Mobile Platform',
299
- type: 'list',
300
- choices: ['iOS', supportedPlatform.android],
301
- default: supportedPlatform.android,
302
- }, {
303
- name: 'device',
304
- message: 'Device to run tests on',
305
- default: 'emulator',
306
- }];
301
+ return [
302
+ {
303
+ name: 'app',
304
+ message: 'Application package. Path to file or url',
305
+ default: 'http://localhost',
306
+ },
307
+ {
308
+ name: 'platform',
309
+ message: 'Mobile Platform',
310
+ type: 'list',
311
+ choices: ['iOS', supportedPlatform.android],
312
+ default: supportedPlatform.android,
313
+ },
314
+ {
315
+ name: 'device',
316
+ message: 'Device to run tests on',
317
+ default: 'emulator',
318
+ },
319
+ ]
307
320
  }
308
321
 
309
322
  async _startBrowser() {
310
323
  if (this.appiumV2 === true) {
311
- this.options.capabilities = this._convertAppiumV2Caps(this.options.capabilities);
312
- this.options.desiredCapabilities = this._convertAppiumV2Caps(this.options.desiredCapabilities);
324
+ this.options.capabilities = this._convertAppiumV2Caps(this.options.capabilities)
325
+ this.options.desiredCapabilities = this._convertAppiumV2Caps(this.options.desiredCapabilities)
313
326
  }
314
327
 
315
328
  try {
316
329
  if (this.options.multiremote) {
317
- this.browser = await webdriverio.multiremote(this.options.multiremote);
330
+ this.browser = await webdriverio.multiremote(this.options.multiremote)
318
331
  } else {
319
- this.browser = await webdriverio.remote(this.options);
332
+ this.browser = await webdriverio.remote(this.options)
320
333
  }
321
334
  } catch (err) {
322
335
  if (err.toString().indexOf('ECONNREFUSED')) {
323
- throw new ConnectionRefused(err);
336
+ throw new ConnectionRefused(err)
324
337
  }
325
- throw err;
338
+ throw err
326
339
  }
327
- this.$$ = this.browser.$$.bind(this.browser);
340
+ this.$$ = this.browser.$$.bind(this.browser)
328
341
 
329
- this.isRunning = true;
342
+ this.isRunning = true
330
343
  if (this.options.timeouts && this.isWeb) {
331
- await this.defineTimeout(this.options.timeouts);
344
+ await this.defineTimeout(this.options.timeouts)
332
345
  }
333
346
  if (this.options.windowSize === 'maximize' && !this.platform) {
334
- const res = await this.browser.execute('return [screen.width, screen.height]');
347
+ const res = await this.browser.execute('return [screen.width, screen.height]')
335
348
  return this.browser.windowHandleSize({
336
349
  width: res.value[0],
337
350
  height: res.value[1],
338
- });
351
+ })
339
352
  }
340
353
  if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0 && !this.platform) {
341
- const dimensions = this.options.windowSize.split('x');
354
+ const dimensions = this.options.windowSize.split('x')
342
355
  await this.browser.windowHandleSize({
343
356
  width: dimensions[0],
344
357
  height: dimensions[1],
345
- });
358
+ })
346
359
  }
347
360
  }
348
361
 
349
362
  async _after() {
350
- if (!this.isRunning) return;
363
+ if (!this.isRunning) return
351
364
  if (this.options.restart) {
352
- this.isRunning = false;
353
- return this.browser.deleteSession();
365
+ this.isRunning = false
366
+ return this.browser.deleteSession()
354
367
  }
355
368
  if (this.isWeb && !this.platform) {
356
- return super._after();
369
+ return super._after()
357
370
  }
358
371
  }
359
372
 
360
373
  async _withinBegin(context) {
361
374
  if (this.isWeb) {
362
- return super._withinBegin(context);
375
+ return super._withinBegin(context)
363
376
  }
364
377
  if (context === 'webview') {
365
- return this.switchToWeb();
378
+ return this.switchToWeb()
366
379
  }
367
380
  if (typeof context === 'object') {
368
- if (context.web) return this.switchToWeb(context.web);
369
- if (context.webview) return this.switchToWeb(context.webview);
381
+ if (context.web) return this.switchToWeb(context.web)
382
+ if (context.webview) return this.switchToWeb(context.webview)
370
383
  }
371
- return this.switchToContext(context);
384
+ return this.switchToContext(context)
372
385
  }
373
386
 
374
387
  _withinEnd() {
375
388
  if (this.isWeb) {
376
- return super._withinEnd();
389
+ return super._withinEnd()
377
390
  }
378
- return this.switchToNative();
391
+ return this.switchToNative()
379
392
  }
380
393
 
381
394
  _buildAppiumEndpoint() {
382
- const {
383
- protocol, port, hostname, path,
384
- } = this.browser.options;
395
+ const { protocol, port, hostname, path } = this.browser.options
385
396
  // Build path to Appium REST API endpoint
386
- return `${protocol}://${hostname}:${port}${path}`;
397
+ return `${protocol}://${hostname}:${port}${path}`
387
398
  }
388
399
 
389
400
  /**
@@ -421,11 +432,11 @@ class Appium extends Webdriver {
421
432
  * @param {*} fn
422
433
  */
423
434
  async runOnIOS(caps, fn) {
424
- if (this.platform !== 'ios') return;
425
- recorder.session.start('iOS-only actions');
426
- await this._runWithCaps(caps, fn);
427
- await recorder.add('restore from iOS session', () => recorder.session.restore());
428
- return recorder.promise();
435
+ if (this.platform !== 'ios') return
436
+ recorder.session.start('iOS-only actions')
437
+ this._runWithCaps(caps, fn)
438
+ recorder.add('restore from iOS session', () => recorder.session.restore())
439
+ return recorder.promise()
429
440
  }
430
441
 
431
442
  /**
@@ -463,11 +474,11 @@ class Appium extends Webdriver {
463
474
  * @param {*} fn
464
475
  */
465
476
  async runOnAndroid(caps, fn) {
466
- if (this.platform !== 'android') return;
467
- recorder.session.start('Android-only actions');
468
- await this._runWithCaps(caps, fn);
469
- await recorder.add('restore from Android session', () => recorder.session.restore());
470
- return recorder.promise();
477
+ if (this.platform !== 'android') return
478
+ recorder.session.start('Android-only actions')
479
+ this._runWithCaps(caps, fn)
480
+ recorder.add('restore from Android session', () => recorder.session.restore())
481
+ return recorder.promise()
471
482
  }
472
483
 
473
484
  /**
@@ -484,34 +495,34 @@ class Appium extends Webdriver {
484
495
  */
485
496
  /* eslint-disable */
486
497
  async runInWeb(fn) {
487
- if (!this.isWeb) return;
488
- recorder.session.start('Web-only actions');
498
+ if (!this.isWeb) return
499
+ recorder.session.start('Web-only actions')
489
500
 
490
- recorder.add('restore from Web session', () => recorder.session.restore(), true);
491
- return recorder.promise();
501
+ recorder.add('restore from Web session', () => recorder.session.restore(), true)
502
+ return recorder.promise()
492
503
  }
493
504
  /* eslint-enable */
494
505
 
495
- async _runWithCaps(caps, fn) {
506
+ _runWithCaps(caps, fn) {
496
507
  if (typeof caps === 'object') {
497
508
  for (const key in caps) {
498
509
  // skip if capabilities do not match
499
510
  if (this.config.desiredCapabilities[key] !== caps[key]) {
500
- return;
511
+ return
501
512
  }
502
513
  }
503
514
  }
504
515
  if (typeof caps === 'function') {
505
516
  if (!fn) {
506
- fn = caps;
517
+ fn = caps
507
518
  } else {
508
519
  // skip if capabilities are checked inside a function
509
- const enabled = caps(this.config.desiredCapabilities);
510
- if (!enabled) return;
520
+ const enabled = caps(this.config.desiredCapabilities)
521
+ if (!enabled) return
511
522
  }
512
523
  }
513
524
 
514
- fn();
525
+ fn()
515
526
  }
516
527
 
517
528
  /**
@@ -527,9 +538,9 @@ class Appium extends Webdriver {
527
538
  * Appium: support only Android
528
539
  */
529
540
  async checkIfAppIsInstalled(bundleId) {
530
- onlyForApps.call(this, supportedPlatform.android);
541
+ onlyForApps.call(this, supportedPlatform.android)
531
542
 
532
- return this.browser.isAppInstalled(bundleId);
543
+ return this.browser.isAppInstalled(bundleId)
533
544
  }
534
545
 
535
546
  /**
@@ -545,9 +556,9 @@ class Appium extends Webdriver {
545
556
  * Appium: support only Android
546
557
  */
547
558
  async seeAppIsInstalled(bundleId) {
548
- onlyForApps.call(this, supportedPlatform.android);
549
- const res = await this.browser.isAppInstalled(bundleId);
550
- return truth(`app ${bundleId}`, 'to be installed').assert(res);
559
+ onlyForApps.call(this, supportedPlatform.android)
560
+ const res = await this.browser.isAppInstalled(bundleId)
561
+ return truth(`app ${bundleId}`, 'to be installed').assert(res)
551
562
  }
552
563
 
553
564
  /**
@@ -563,9 +574,9 @@ class Appium extends Webdriver {
563
574
  * Appium: support only Android
564
575
  */
565
576
  async seeAppIsNotInstalled(bundleId) {
566
- onlyForApps.call(this, supportedPlatform.android);
567
- const res = await this.browser.isAppInstalled(bundleId);
568
- return truth(`app ${bundleId}`, 'not to be installed').negate(res);
577
+ onlyForApps.call(this, supportedPlatform.android)
578
+ const res = await this.browser.isAppInstalled(bundleId)
579
+ return truth(`app ${bundleId}`, 'not to be installed').negate(res)
569
580
  }
570
581
 
571
582
  /**
@@ -580,8 +591,8 @@ class Appium extends Webdriver {
580
591
  * Appium: support only Android
581
592
  */
582
593
  async installApp(path) {
583
- onlyForApps.call(this, supportedPlatform.android);
584
- return this.browser.installApp(path);
594
+ onlyForApps.call(this, supportedPlatform.android)
595
+ return this.browser.installApp(path)
585
596
  }
586
597
 
587
598
  /**
@@ -597,13 +608,13 @@ class Appium extends Webdriver {
597
608
  * @param {string} [bundleId] ID of bundle
598
609
  */
599
610
  async removeApp(appId, bundleId) {
600
- onlyForApps.call(this, supportedPlatform.android);
611
+ onlyForApps.call(this, supportedPlatform.android)
601
612
 
602
613
  return this.axios({
603
614
  method: 'post',
604
615
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/device/remove_app`,
605
616
  data: { appId, bundleId },
606
- });
617
+ })
607
618
  }
608
619
 
609
620
  /**
@@ -615,11 +626,11 @@ class Appium extends Webdriver {
615
626
  *
616
627
  */
617
628
  async resetApp() {
618
- onlyForApps.call(this);
629
+ onlyForApps.call(this)
619
630
  return this.axios({
620
631
  method: 'post',
621
632
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/app/reset`,
622
- });
633
+ })
623
634
  }
624
635
 
625
636
  /**
@@ -634,9 +645,9 @@ class Appium extends Webdriver {
634
645
  * Appium: support only Android
635
646
  */
636
647
  async seeCurrentActivityIs(currentActivity) {
637
- onlyForApps.call(this, supportedPlatform.android);
638
- const res = await this.browser.getCurrentActivity();
639
- return truth('current activity', `to be ${currentActivity}`).assert(res === currentActivity);
648
+ onlyForApps.call(this, supportedPlatform.android)
649
+ const res = await this.browser.getCurrentActivity()
650
+ return truth('current activity', `to be ${currentActivity}`).assert(res === currentActivity)
640
651
  }
641
652
 
642
653
  /**
@@ -651,9 +662,9 @@ class Appium extends Webdriver {
651
662
  * Appium: support only Android
652
663
  */
653
664
  async seeDeviceIsLocked() {
654
- onlyForApps.call(this, supportedPlatform.android);
655
- const res = await this.browser.isLocked();
656
- return truth('device', 'to be locked').assert(res);
665
+ onlyForApps.call(this, supportedPlatform.android)
666
+ const res = await this.browser.isLocked()
667
+ return truth('device', 'to be locked').assert(res)
657
668
  }
658
669
 
659
670
  /**
@@ -668,9 +679,9 @@ class Appium extends Webdriver {
668
679
  * Appium: support only Android
669
680
  */
670
681
  async seeDeviceIsUnlocked() {
671
- onlyForApps.call(this, supportedPlatform.android);
672
- const res = await this.browser.isLocked();
673
- return truth('device', 'to be locked').negate(res);
682
+ onlyForApps.call(this, supportedPlatform.android)
683
+ const res = await this.browser.isLocked()
684
+ return truth('device', 'to be locked').negate(res)
674
685
  }
675
686
 
676
687
  /**
@@ -688,15 +699,15 @@ class Appium extends Webdriver {
688
699
  * Appium: support Android and iOS
689
700
  */
690
701
  async seeOrientationIs(orientation) {
691
- onlyForApps.call(this);
702
+ onlyForApps.call(this)
692
703
 
693
704
  const res = await this.axios({
694
705
  method: 'get',
695
706
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
696
- });
707
+ })
697
708
 
698
- const currentOrientation = res.data.value;
699
- return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation);
709
+ const currentOrientation = res.data.value
710
+ return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation)
700
711
  }
701
712
 
702
713
  /**
@@ -712,13 +723,13 @@ class Appium extends Webdriver {
712
723
  * Appium: support Android and iOS
713
724
  */
714
725
  async setOrientation(orientation) {
715
- onlyForApps.call(this);
726
+ onlyForApps.call(this)
716
727
 
717
728
  return this.axios({
718
729
  method: 'post',
719
730
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
720
731
  data: { orientation },
721
- });
732
+ })
722
733
  }
723
734
 
724
735
  /**
@@ -733,8 +744,8 @@ class Appium extends Webdriver {
733
744
  * Appium: support Android and iOS
734
745
  */
735
746
  async grabAllContexts() {
736
- onlyForApps.call(this);
737
- return this.browser.getContexts();
747
+ onlyForApps.call(this)
748
+ return this.browser.getContexts()
738
749
  }
739
750
 
740
751
  /**
@@ -749,8 +760,8 @@ class Appium extends Webdriver {
749
760
  * Appium: support Android and iOS
750
761
  */
751
762
  async grabContext() {
752
- onlyForApps.call(this);
753
- return this.browser.getContext();
763
+ onlyForApps.call(this)
764
+ return this.browser.getContext()
754
765
  }
755
766
 
756
767
  /**
@@ -765,8 +776,8 @@ class Appium extends Webdriver {
765
776
  * Appium: support only Android
766
777
  */
767
778
  async grabCurrentActivity() {
768
- onlyForApps.call(this, supportedPlatform.android);
769
- return this.browser.getCurrentActivity();
779
+ onlyForApps.call(this, supportedPlatform.android)
780
+ return this.browser.getCurrentActivity()
770
781
  }
771
782
 
772
783
  /**
@@ -783,14 +794,14 @@ class Appium extends Webdriver {
783
794
  * Appium: support only Android
784
795
  */
785
796
  async grabNetworkConnection() {
786
- onlyForApps.call(this, supportedPlatform.android);
787
- const res = await this.browser.getNetworkConnection();
797
+ onlyForApps.call(this, supportedPlatform.android)
798
+ const res = await this.browser.getNetworkConnection()
788
799
  return {
789
800
  value: res,
790
801
  inAirplaneMode: res.inAirplaneMode,
791
802
  hasWifi: res.hasWifi,
792
803
  hasData: res.hasData,
793
- };
804
+ }
794
805
  }
795
806
 
796
807
  /**
@@ -805,10 +816,10 @@ class Appium extends Webdriver {
805
816
  * Appium: support Android and iOS
806
817
  */
807
818
  async grabOrientation() {
808
- onlyForApps.call(this);
809
- const res = await this.browser.orientation();
810
- this.debugSection('Orientation', res);
811
- return res;
819
+ onlyForApps.call(this)
820
+ const res = await this.browser.orientation()
821
+ this.debugSection('Orientation', res)
822
+ return res
812
823
  }
813
824
 
814
825
  /**
@@ -823,10 +834,10 @@ class Appium extends Webdriver {
823
834
  * Appium: support Android and iOS
824
835
  */
825
836
  async grabSettings() {
826
- onlyForApps.call(this);
827
- const res = await this.browser.getSettings();
828
- this.debugSection('Settings', JSON.stringify(res));
829
- return res;
837
+ onlyForApps.call(this)
838
+ const res = await this.browser.getSettings()
839
+ this.debugSection('Settings', JSON.stringify(res))
840
+ return res
830
841
  }
831
842
 
832
843
  /**
@@ -835,7 +846,7 @@ class Appium extends Webdriver {
835
846
  * @param {*} context the context to switch to
836
847
  */
837
848
  async switchToContext(context) {
838
- return this.browser.switchContext(context);
849
+ return this.browser.switchContext(context)
839
850
  }
840
851
 
841
852
  /**
@@ -855,17 +866,17 @@ class Appium extends Webdriver {
855
866
  * @param {string} [context]
856
867
  */
857
868
  async switchToWeb(context) {
858
- this.isWeb = true;
859
- this.defaultContext = 'body';
869
+ this.isWeb = true
870
+ this.defaultContext = 'body'
860
871
 
861
- if (context) return this.switchToContext(context);
862
- const contexts = await this.grabAllContexts();
863
- this.debugSection('Contexts', contexts.toString());
872
+ if (context) return this.switchToContext(context)
873
+ const contexts = await this.grabAllContexts()
874
+ this.debugSection('Contexts', contexts.toString())
864
875
  for (const idx in contexts) {
865
- if (contexts[idx].match(/^WEBVIEW/)) return this.switchToContext(contexts[idx]);
876
+ if (contexts[idx].match(/^WEBVIEW/)) return this.switchToContext(contexts[idx])
866
877
  }
867
878
 
868
- throw new Error('No WEBVIEW could be guessed, please specify one in params');
879
+ throw new Error('No WEBVIEW could be guessed, please specify one in params')
869
880
  }
870
881
 
871
882
  /**
@@ -882,11 +893,11 @@ class Appium extends Webdriver {
882
893
  * @return {Promise<void>}
883
894
  */
884
895
  async switchToNative(context = null) {
885
- this.isWeb = false;
886
- this.defaultContext = '//*';
896
+ this.isWeb = false
897
+ this.defaultContext = '//*'
887
898
 
888
- if (context) return this.switchToContext(context);
889
- return this.switchToContext('NATIVE_APP');
899
+ if (context) return this.switchToContext(context)
900
+ return this.switchToContext('NATIVE_APP')
890
901
  }
891
902
 
892
903
  /**
@@ -903,8 +914,8 @@ class Appium extends Webdriver {
903
914
  * @return {Promise<void>}
904
915
  */
905
916
  async startActivity(appPackage, appActivity) {
906
- onlyForApps.call(this, supportedPlatform.android);
907
- return this.browser.startActivity(appPackage, appActivity);
917
+ onlyForApps.call(this, supportedPlatform.android)
918
+ return this.browser.startActivity(appPackage, appActivity)
908
919
  }
909
920
 
910
921
  /**
@@ -929,8 +940,8 @@ class Appium extends Webdriver {
929
940
  * @return {Promise<number>}
930
941
  */
931
942
  async setNetworkConnection(value) {
932
- onlyForApps.call(this, supportedPlatform.android);
933
- return this.browser.setNetworkConnection(value);
943
+ onlyForApps.call(this, supportedPlatform.android)
944
+ return this.browser.setNetworkConnection(value)
934
945
  }
935
946
 
936
947
  /**
@@ -945,8 +956,8 @@ class Appium extends Webdriver {
945
956
  * Appium: support Android and iOS
946
957
  */
947
958
  async setSettings(settings) {
948
- onlyForApps.call(this);
949
- return this.browser.settings(settings);
959
+ onlyForApps.call(this)
960
+ return this.browser.settings(settings)
950
961
  }
951
962
 
952
963
  /**
@@ -967,9 +978,9 @@ class Appium extends Webdriver {
967
978
  * @param {string} [key] Optional key
968
979
  */
969
980
  async hideDeviceKeyboard(strategy, key) {
970
- onlyForApps.call(this);
971
- strategy = strategy || 'tapOutside';
972
- return this.browser.hideKeyboard(strategy, key);
981
+ onlyForApps.call(this)
982
+ strategy = strategy || 'tapOutside'
983
+ return this.browser.hideKeyboard(strategy, key)
973
984
  }
974
985
 
975
986
  /**
@@ -986,8 +997,8 @@ class Appium extends Webdriver {
986
997
  * Appium: support only Android
987
998
  */
988
999
  async sendDeviceKeyEvent(keyValue) {
989
- onlyForApps.call(this, supportedPlatform.android);
990
- return this.browser.pressKeyCode(keyValue);
1000
+ onlyForApps.call(this, supportedPlatform.android)
1001
+ return this.browser.pressKeyCode(keyValue)
991
1002
  }
992
1003
 
993
1004
  /**
@@ -1002,8 +1013,8 @@ class Appium extends Webdriver {
1002
1013
  * Appium: support only Android
1003
1014
  */
1004
1015
  async openNotifications() {
1005
- onlyForApps.call(this, supportedPlatform.android);
1006
- return this.browser.openNotifications();
1016
+ onlyForApps.call(this, supportedPlatform.android)
1017
+ return this.browser.openNotifications()
1007
1018
  }
1008
1019
 
1009
1020
  /**
@@ -1022,13 +1033,13 @@ class Appium extends Webdriver {
1022
1033
  * Appium: support Android and iOS
1023
1034
  */
1024
1035
  async makeTouchAction(locator, action) {
1025
- onlyForApps.call(this);
1026
- const element = await this.browser.$(parseLocator.call(this, locator));
1036
+ onlyForApps.call(this)
1037
+ const element = await this.browser.$(parseLocator.call(this, locator))
1027
1038
 
1028
1039
  return this.browser.touchAction({
1029
1040
  action,
1030
1041
  element,
1031
- });
1042
+ })
1032
1043
  }
1033
1044
 
1034
1045
  /**
@@ -1045,7 +1056,7 @@ class Appium extends Webdriver {
1045
1056
  * @param {*} locator
1046
1057
  */
1047
1058
  async tap(locator) {
1048
- return this.makeTouchAction(locator, 'tap');
1059
+ return this.makeTouchAction(locator, 'tap')
1049
1060
  }
1050
1061
 
1051
1062
  /**
@@ -1068,10 +1079,13 @@ class Appium extends Webdriver {
1068
1079
  */
1069
1080
  /* eslint-disable */
1070
1081
  async swipe(locator, xoffset, yoffset, speed = 1000) {
1071
- onlyForApps.call(this);
1072
- const res = await this.browser.$(parseLocator.call(this, locator));
1082
+ onlyForApps.call(this)
1083
+ const res = await this.browser.$(parseLocator.call(this, locator))
1073
1084
  // if (!res.length) throw new ElementNotFound(locator, 'was not found in UI');
1074
- return this.performSwipe(await res.getLocation(), { x: (await res.getLocation()).x + xoffset, y: (await res.getLocation()).y + yoffset });
1085
+ return this.performSwipe(await res.getLocation(), {
1086
+ x: (await res.getLocation()).x + xoffset,
1087
+ y: (await res.getLocation()).y + yoffset,
1088
+ })
1075
1089
  }
1076
1090
  /* eslint-enable */
1077
1091
 
@@ -1088,42 +1102,44 @@ class Appium extends Webdriver {
1088
1102
  * Appium: support Android and iOS
1089
1103
  */
1090
1104
  async performSwipe(from, to) {
1091
- await this.browser.performActions([{
1092
- id: uuidv4(),
1093
- type: 'pointer',
1094
- parameters: {
1095
- pointerType: 'touch',
1096
- },
1097
- actions: [
1098
- {
1099
- duration: 0,
1100
- x: from.x,
1101
- y: from.y,
1102
- type: 'pointerMove',
1103
- origin: 'viewport',
1104
- },
1105
- {
1106
- button: 1,
1107
- type: 'pointerDown',
1108
- },
1109
- {
1110
- duration: 200,
1111
- type: 'pause',
1112
- },
1113
- {
1114
- duration: 600,
1115
- x: to.x,
1116
- y: to.y,
1117
- type: 'pointerMove',
1118
- origin: 'viewport',
1105
+ await this.browser.performActions([
1106
+ {
1107
+ id: uuidv4(),
1108
+ type: 'pointer',
1109
+ parameters: {
1110
+ pointerType: 'touch',
1119
1111
  },
1120
- {
1121
- button: 1,
1122
- type: 'pointerUp',
1123
- },
1124
- ],
1125
- }]);
1126
- await this.browser.pause(1000);
1112
+ actions: [
1113
+ {
1114
+ duration: 0,
1115
+ x: from.x,
1116
+ y: from.y,
1117
+ type: 'pointerMove',
1118
+ origin: 'viewport',
1119
+ },
1120
+ {
1121
+ button: 1,
1122
+ type: 'pointerDown',
1123
+ },
1124
+ {
1125
+ duration: 200,
1126
+ type: 'pause',
1127
+ },
1128
+ {
1129
+ duration: 600,
1130
+ x: to.x,
1131
+ y: to.y,
1132
+ type: 'pointerMove',
1133
+ origin: 'viewport',
1134
+ },
1135
+ {
1136
+ button: 1,
1137
+ type: 'pointerUp',
1138
+ },
1139
+ ],
1140
+ },
1141
+ ])
1142
+ await this.browser.pause(1000)
1127
1143
  }
1128
1144
 
1129
1145
  /**
@@ -1144,14 +1160,14 @@ class Appium extends Webdriver {
1144
1160
  * Appium: support Android and iOS
1145
1161
  */
1146
1162
  async swipeDown(locator, yoffset = 1000, speed) {
1147
- onlyForApps.call(this);
1163
+ onlyForApps.call(this)
1148
1164
 
1149
1165
  if (!speed) {
1150
- speed = yoffset;
1151
- yoffset = 100;
1166
+ speed = yoffset
1167
+ yoffset = 100
1152
1168
  }
1153
1169
 
1154
- return this.swipe(parseLocator.call(this, locator), 0, yoffset, speed);
1170
+ return this.swipe(parseLocator.call(this, locator), 0, yoffset, speed)
1155
1171
  }
1156
1172
 
1157
1173
  /**
@@ -1173,13 +1189,13 @@ class Appium extends Webdriver {
1173
1189
  * Appium: support Android and iOS
1174
1190
  */
1175
1191
  async swipeLeft(locator, xoffset = 1000, speed) {
1176
- onlyForApps.call(this);
1192
+ onlyForApps.call(this)
1177
1193
  if (!speed) {
1178
- speed = xoffset;
1179
- xoffset = 100;
1194
+ speed = xoffset
1195
+ xoffset = 100
1180
1196
  }
1181
1197
 
1182
- return this.swipe(parseLocator.call(this, locator), -xoffset, 0, speed);
1198
+ return this.swipe(parseLocator.call(this, locator), -xoffset, 0, speed)
1183
1199
  }
1184
1200
 
1185
1201
  /**
@@ -1200,13 +1216,13 @@ class Appium extends Webdriver {
1200
1216
  * Appium: support Android and iOS
1201
1217
  */
1202
1218
  async swipeRight(locator, xoffset = 1000, speed) {
1203
- onlyForApps.call(this);
1219
+ onlyForApps.call(this)
1204
1220
  if (!speed) {
1205
- speed = xoffset;
1206
- xoffset = 100;
1221
+ speed = xoffset
1222
+ xoffset = 100
1207
1223
  }
1208
1224
 
1209
- return this.swipe(parseLocator.call(this, locator), xoffset, 0, speed);
1225
+ return this.swipe(parseLocator.call(this, locator), xoffset, 0, speed)
1210
1226
  }
1211
1227
 
1212
1228
  /**
@@ -1227,14 +1243,14 @@ class Appium extends Webdriver {
1227
1243
  * Appium: support Android and iOS
1228
1244
  */
1229
1245
  async swipeUp(locator, yoffset = 1000, speed) {
1230
- onlyForApps.call(this);
1246
+ onlyForApps.call(this)
1231
1247
 
1232
1248
  if (!speed) {
1233
- speed = yoffset;
1234
- yoffset = 100;
1249
+ speed = yoffset
1250
+ yoffset = 100
1235
1251
  }
1236
1252
 
1237
- return this.swipe(parseLocator.call(this, locator), 0, -yoffset, speed);
1253
+ return this.swipe(parseLocator.call(this, locator), 0, -yoffset, speed)
1238
1254
  }
1239
1255
 
1240
1256
  /**
@@ -1261,55 +1277,66 @@ class Appium extends Webdriver {
1261
1277
  * Appium: support Android and iOS
1262
1278
  */
1263
1279
  async swipeTo(searchableLocator, scrollLocator, direction, timeout, offset, speed) {
1264
- onlyForApps.call(this);
1265
- direction = direction || 'down';
1280
+ onlyForApps.call(this)
1281
+ direction = direction || 'down'
1266
1282
  switch (direction) {
1267
1283
  case 'down':
1268
- direction = 'swipeDown';
1269
- break;
1284
+ direction = 'swipeDown'
1285
+ break
1270
1286
  case 'up':
1271
- direction = 'swipeUp';
1272
- break;
1287
+ direction = 'swipeUp'
1288
+ break
1273
1289
  case 'left':
1274
- direction = 'swipeLeft';
1275
- break;
1290
+ direction = 'swipeLeft'
1291
+ break
1276
1292
  case 'right':
1277
- direction = 'swipeRight';
1278
- break;
1293
+ direction = 'swipeRight'
1294
+ break
1279
1295
  }
1280
- timeout = timeout || this.options.waitForTimeoutInSeconds;
1281
-
1282
- const errorMsg = `element ("${searchableLocator}") still not visible after ${timeout}seconds`;
1283
- const browser = this.browser;
1284
- let err = false;
1285
- let currentSource;
1286
- return browser.waitUntil(() => {
1287
- if (err) {
1288
- return new Error(`Scroll to the end and element ${searchableLocator} was not found`);
1289
- }
1290
- return browser.$$(parseLocator.call(this, searchableLocator))
1291
- .then(els => els.length && els[0].isDisplayed())
1292
- .then((res) => {
1293
- if (res) {
1294
- return true;
1296
+ timeout = timeout || this.options.waitForTimeoutInSeconds
1297
+
1298
+ const errorMsg = `element ("${searchableLocator}") still not visible after ${timeout}seconds`
1299
+ const browser = this.browser
1300
+ let err = false
1301
+ let currentSource
1302
+ return browser
1303
+ .waitUntil(
1304
+ () => {
1305
+ if (err) {
1306
+ return new Error(`Scroll to the end and element ${searchableLocator} was not found`)
1295
1307
  }
1296
- return this[direction](scrollLocator, offset, speed).getSource().then((source) => {
1297
- if (source === currentSource) {
1298
- err = true;
1299
- } else {
1300
- currentSource = source;
1301
- return false;
1302
- }
1303
- });
1304
- });
1305
- }, timeout * 1000, errorMsg)
1308
+ return browser
1309
+ .$$(parseLocator.call(this, searchableLocator))
1310
+ .then((els) => els.length && els[0].isDisplayed())
1311
+ .then((res) => {
1312
+ if (res) {
1313
+ return true
1314
+ }
1315
+ return this[direction](scrollLocator, offset, speed)
1316
+ .getSource()
1317
+ .then((source) => {
1318
+ if (source === currentSource) {
1319
+ err = true
1320
+ } else {
1321
+ currentSource = source
1322
+ return false
1323
+ }
1324
+ })
1325
+ })
1326
+ },
1327
+ timeout * 1000,
1328
+ errorMsg,
1329
+ )
1306
1330
  .catch((e) => {
1307
1331
  if (e.message.indexOf('timeout') && e.type !== 'NoSuchElement') {
1308
- throw new AssertionFailedError({ customMessage: `Scroll to the end and element ${searchableLocator} was not found` }, '');
1332
+ throw new AssertionFailedError(
1333
+ { customMessage: `Scroll to the end and element ${searchableLocator} was not found` },
1334
+ '',
1335
+ )
1309
1336
  } else {
1310
- throw e;
1337
+ throw e
1311
1338
  }
1312
- });
1339
+ })
1313
1340
  }
1314
1341
 
1315
1342
  /**
@@ -1341,8 +1368,8 @@ class Appium extends Webdriver {
1341
1368
  * @param {Array} actions Array of touch actions
1342
1369
  */
1343
1370
  async touchPerform(actions) {
1344
- onlyForApps.call(this);
1345
- return this.browser.touchPerform(actions);
1371
+ onlyForApps.call(this)
1372
+ return this.browser.touchPerform(actions)
1346
1373
  }
1347
1374
 
1348
1375
  /**
@@ -1361,13 +1388,15 @@ class Appium extends Webdriver {
1361
1388
  * Appium: support Android and iOS
1362
1389
  */
1363
1390
  async pullFile(path, dest) {
1364
- onlyForApps.call(this);
1365
- return this.browser.pullFile(path).then(res => fs.writeFile(dest, Buffer.from(res, 'base64'), (err) => {
1366
- if (err) {
1367
- return false;
1368
- }
1369
- return true;
1370
- }));
1391
+ onlyForApps.call(this)
1392
+ return this.browser.pullFile(path).then((res) =>
1393
+ fs.writeFile(dest, Buffer.from(res, 'base64'), (err) => {
1394
+ if (err) {
1395
+ return false
1396
+ }
1397
+ return true
1398
+ }),
1399
+ )
1371
1400
  }
1372
1401
 
1373
1402
  /**
@@ -1382,8 +1411,8 @@ class Appium extends Webdriver {
1382
1411
  * Appium: support only iOS
1383
1412
  */
1384
1413
  async shakeDevice() {
1385
- onlyForApps.call(this, 'iOS');
1386
- return this.browser.shake();
1414
+ onlyForApps.call(this, 'iOS')
1415
+ return this.browser.shake()
1387
1416
  }
1388
1417
 
1389
1418
  /**
@@ -1400,8 +1429,8 @@ class Appium extends Webdriver {
1400
1429
  * Appium: support only iOS
1401
1430
  */
1402
1431
  async rotate(x, y, duration, radius, rotation, touchCount) {
1403
- onlyForApps.call(this, 'iOS');
1404
- return this.browser.rotate(x, y, duration, radius, rotation, touchCount);
1432
+ onlyForApps.call(this, 'iOS')
1433
+ return this.browser.rotate(x, y, duration, radius, rotation, touchCount)
1405
1434
  }
1406
1435
 
1407
1436
  /**
@@ -1414,8 +1443,8 @@ class Appium extends Webdriver {
1414
1443
  * Appium: support only iOS
1415
1444
  */
1416
1445
  async setImmediateValue(id, value) {
1417
- onlyForApps.call(this, 'iOS');
1418
- return this.browser.setImmediateValue(id, value);
1446
+ onlyForApps.call(this, 'iOS')
1447
+ return this.browser.setImmediateValue(id, value)
1419
1448
  }
1420
1449
 
1421
1450
  /**
@@ -1433,9 +1462,9 @@ class Appium extends Webdriver {
1433
1462
  * TODO: not tested
1434
1463
  */
1435
1464
  async simulateTouchId(match) {
1436
- onlyForApps.call(this, 'iOS');
1437
- match = match || true;
1438
- return this.browser.touchId(match);
1465
+ onlyForApps.call(this, 'iOS')
1466
+ match = match || true
1467
+ return this.browser.touchId(match)
1439
1468
  }
1440
1469
 
1441
1470
  /**
@@ -1450,8 +1479,8 @@ class Appium extends Webdriver {
1450
1479
  * Appium: support both Android and iOS
1451
1480
  */
1452
1481
  async closeApp() {
1453
- onlyForApps.call(this);
1454
- return this.browser.closeApp();
1482
+ onlyForApps.call(this)
1483
+ return this.browser.closeApp()
1455
1484
  }
1456
1485
 
1457
1486
  /**
@@ -1459,8 +1488,8 @@ class Appium extends Webdriver {
1459
1488
  *
1460
1489
  */
1461
1490
  async appendField(field, value) {
1462
- if (this.isWeb) return super.appendField(field, value);
1463
- return super.appendField(parseLocator.call(this, field), value);
1491
+ if (this.isWeb) return super.appendField(field, value)
1492
+ return super.appendField(parseLocator.call(this, field), value)
1464
1493
  }
1465
1494
 
1466
1495
  /**
@@ -1468,8 +1497,8 @@ class Appium extends Webdriver {
1468
1497
  *
1469
1498
  */
1470
1499
  async checkOption(field) {
1471
- if (this.isWeb) return super.checkOption(field);
1472
- return super.checkOption(parseLocator.call(this, field));
1500
+ if (this.isWeb) return super.checkOption(field)
1501
+ return super.checkOption(parseLocator.call(this, field))
1473
1502
  }
1474
1503
 
1475
1504
  /**
@@ -1477,8 +1506,8 @@ class Appium extends Webdriver {
1477
1506
  *
1478
1507
  */
1479
1508
  async click(locator, context) {
1480
- if (this.isWeb) return super.click(locator, context);
1481
- return super.click(parseLocator.call(this, locator), parseLocator.call(this, context));
1509
+ if (this.isWeb) return super.click(locator, context)
1510
+ return super.click(parseLocator.call(this, locator), parseLocator.call(this, context))
1482
1511
  }
1483
1512
 
1484
1513
  /**
@@ -1486,16 +1515,16 @@ class Appium extends Webdriver {
1486
1515
  *
1487
1516
  */
1488
1517
  async dontSeeCheckboxIsChecked(field) {
1489
- if (this.isWeb) return super.dontSeeCheckboxIsChecked(field);
1490
- return super.dontSeeCheckboxIsChecked(parseLocator.call(this, field));
1518
+ if (this.isWeb) return super.dontSeeCheckboxIsChecked(field)
1519
+ return super.dontSeeCheckboxIsChecked(parseLocator.call(this, field))
1491
1520
  }
1492
1521
 
1493
1522
  /**
1494
1523
  * {{> dontSeeElement }}
1495
1524
  */
1496
1525
  async dontSeeElement(locator) {
1497
- if (this.isWeb) return super.dontSeeElement(locator);
1498
- return super.dontSeeElement(parseLocator.call(this, locator));
1526
+ if (this.isWeb) return super.dontSeeElement(locator)
1527
+ return super.dontSeeElement(parseLocator.call(this, locator))
1499
1528
  }
1500
1529
 
1501
1530
  /**
@@ -1503,17 +1532,17 @@ class Appium extends Webdriver {
1503
1532
  *
1504
1533
  */
1505
1534
  async dontSeeInField(field, value) {
1506
- const _value = (typeof value === 'boolean') ? value : value.toString();
1507
- if (this.isWeb) return super.dontSeeInField(field, _value);
1508
- return super.dontSeeInField(parseLocator.call(this, field), _value);
1535
+ const _value = typeof value === 'boolean' ? value : value.toString()
1536
+ if (this.isWeb) return super.dontSeeInField(field, _value)
1537
+ return super.dontSeeInField(parseLocator.call(this, field), _value)
1509
1538
  }
1510
1539
 
1511
1540
  /**
1512
1541
  * {{> dontSee }}
1513
1542
  */
1514
1543
  async dontSee(text, context = null) {
1515
- if (this.isWeb) return super.dontSee(text, context);
1516
- return super.dontSee(text, parseLocator.call(this, context));
1544
+ if (this.isWeb) return super.dontSee(text, context)
1545
+ return super.dontSee(text, parseLocator.call(this, context))
1517
1546
  }
1518
1547
 
1519
1548
  /**
@@ -1521,9 +1550,9 @@ class Appium extends Webdriver {
1521
1550
  *
1522
1551
  */
1523
1552
  async fillField(field, value) {
1524
- value = value.toString();
1525
- if (this.isWeb) return super.fillField(field, value);
1526
- return super.fillField(parseLocator.call(this, field), value);
1553
+ value = value.toString()
1554
+ if (this.isWeb) return super.fillField(field, value)
1555
+ return super.fillField(parseLocator.call(this, field), value)
1527
1556
  }
1528
1557
 
1529
1558
  /**
@@ -1531,8 +1560,8 @@ class Appium extends Webdriver {
1531
1560
  *
1532
1561
  */
1533
1562
  async grabTextFromAll(locator) {
1534
- if (this.isWeb) return super.grabTextFromAll(locator);
1535
- return super.grabTextFromAll(parseLocator.call(this, locator));
1563
+ if (this.isWeb) return super.grabTextFromAll(locator)
1564
+ return super.grabTextFromAll(parseLocator.call(this, locator))
1536
1565
  }
1537
1566
 
1538
1567
  /**
@@ -1540,16 +1569,16 @@ class Appium extends Webdriver {
1540
1569
  *
1541
1570
  */
1542
1571
  async grabTextFrom(locator) {
1543
- if (this.isWeb) return super.grabTextFrom(locator);
1544
- return super.grabTextFrom(parseLocator.call(this, locator));
1572
+ if (this.isWeb) return super.grabTextFrom(locator)
1573
+ return super.grabTextFrom(parseLocator.call(this, locator))
1545
1574
  }
1546
1575
 
1547
1576
  /**
1548
1577
  * {{> grabNumberOfVisibleElements }}
1549
1578
  */
1550
1579
  async grabNumberOfVisibleElements(locator) {
1551
- if (this.isWeb) return super.grabNumberOfVisibleElements(locator);
1552
- return super.grabNumberOfVisibleElements(parseLocator.call(this, locator));
1580
+ if (this.isWeb) return super.grabNumberOfVisibleElements(locator)
1581
+ return super.grabNumberOfVisibleElements(parseLocator.call(this, locator))
1553
1582
  }
1554
1583
 
1555
1584
  /**
@@ -1558,8 +1587,8 @@ class Appium extends Webdriver {
1558
1587
  * {{> grabAttributeFrom }}
1559
1588
  */
1560
1589
  async grabAttributeFrom(locator, attr) {
1561
- if (this.isWeb) return super.grabAttributeFrom(locator, attr);
1562
- return super.grabAttributeFrom(parseLocator.call(this, locator), attr);
1590
+ if (this.isWeb) return super.grabAttributeFrom(locator, attr)
1591
+ return super.grabAttributeFrom(parseLocator.call(this, locator), attr)
1563
1592
  }
1564
1593
 
1565
1594
  /**
@@ -1567,8 +1596,8 @@ class Appium extends Webdriver {
1567
1596
  * {{> grabAttributeFromAll }}
1568
1597
  */
1569
1598
  async grabAttributeFromAll(locator, attr) {
1570
- if (this.isWeb) return super.grabAttributeFromAll(locator, attr);
1571
- return super.grabAttributeFromAll(parseLocator.call(this, locator), attr);
1599
+ if (this.isWeb) return super.grabAttributeFromAll(locator, attr)
1600
+ return super.grabAttributeFromAll(parseLocator.call(this, locator), attr)
1572
1601
  }
1573
1602
 
1574
1603
  /**
@@ -1576,8 +1605,8 @@ class Appium extends Webdriver {
1576
1605
  *
1577
1606
  */
1578
1607
  async grabValueFromAll(locator) {
1579
- if (this.isWeb) return super.grabValueFromAll(locator);
1580
- return super.grabValueFromAll(parseLocator.call(this, locator));
1608
+ if (this.isWeb) return super.grabValueFromAll(locator)
1609
+ return super.grabValueFromAll(parseLocator.call(this, locator))
1581
1610
  }
1582
1611
 
1583
1612
  /**
@@ -1585,8 +1614,8 @@ class Appium extends Webdriver {
1585
1614
  *
1586
1615
  */
1587
1616
  async grabValueFrom(locator) {
1588
- if (this.isWeb) return super.grabValueFrom(locator);
1589
- return super.grabValueFrom(parseLocator.call(this, locator));
1617
+ if (this.isWeb) return super.grabValueFrom(locator)
1618
+ return super.grabValueFrom(parseLocator.call(this, locator))
1590
1619
  }
1591
1620
 
1592
1621
  /**
@@ -1601,7 +1630,7 @@ class Appium extends Webdriver {
1601
1630
  * @return {Promise<void>}
1602
1631
  */
1603
1632
  async saveScreenshot(fileName) {
1604
- return super.saveScreenshot(fileName, false);
1633
+ return super.saveScreenshot(fileName, false)
1605
1634
  }
1606
1635
 
1607
1636
  /**
@@ -1610,7 +1639,7 @@ class Appium extends Webdriver {
1610
1639
  * Supported only for web testing
1611
1640
  */
1612
1641
  async scrollIntoView(locator, scrollIntoViewOptions) {
1613
- if (this.isWeb) return super.scrollIntoView(locator, scrollIntoViewOptions);
1642
+ if (this.isWeb) return super.scrollIntoView(locator, scrollIntoViewOptions)
1614
1643
  }
1615
1644
 
1616
1645
  /**
@@ -1618,8 +1647,8 @@ class Appium extends Webdriver {
1618
1647
  *
1619
1648
  */
1620
1649
  async seeCheckboxIsChecked(field) {
1621
- if (this.isWeb) return super.seeCheckboxIsChecked(field);
1622
- return super.seeCheckboxIsChecked(parseLocator.call(this, field));
1650
+ if (this.isWeb) return super.seeCheckboxIsChecked(field)
1651
+ return super.seeCheckboxIsChecked(parseLocator.call(this, field))
1623
1652
  }
1624
1653
 
1625
1654
  /**
@@ -1627,8 +1656,8 @@ class Appium extends Webdriver {
1627
1656
  *
1628
1657
  */
1629
1658
  async seeElement(locator) {
1630
- if (this.isWeb) return super.seeElement(locator);
1631
- return super.seeElement(parseLocator.call(this, locator));
1659
+ if (this.isWeb) return super.seeElement(locator)
1660
+ return super.seeElement(parseLocator.call(this, locator))
1632
1661
  }
1633
1662
 
1634
1663
  /**
@@ -1636,9 +1665,9 @@ class Appium extends Webdriver {
1636
1665
  *
1637
1666
  */
1638
1667
  async seeInField(field, value) {
1639
- const _value = (typeof value === 'boolean') ? value : value.toString();
1640
- if (this.isWeb) return super.seeInField(field, _value);
1641
- return super.seeInField(parseLocator.call(this, field), _value);
1668
+ const _value = typeof value === 'boolean' ? value : value.toString()
1669
+ if (this.isWeb) return super.seeInField(field, _value)
1670
+ return super.seeInField(parseLocator.call(this, field), _value)
1642
1671
  }
1643
1672
 
1644
1673
  /**
@@ -1646,8 +1675,8 @@ class Appium extends Webdriver {
1646
1675
  *
1647
1676
  */
1648
1677
  async see(text, context) {
1649
- if (this.isWeb) return super.see(text, context);
1650
- return super.see(text, parseLocator.call(this, context));
1678
+ if (this.isWeb) return super.see(text, context)
1679
+ return super.see(text, parseLocator.call(this, context))
1651
1680
  }
1652
1681
 
1653
1682
  /**
@@ -1656,8 +1685,8 @@ class Appium extends Webdriver {
1656
1685
  * Supported only for web testing
1657
1686
  */
1658
1687
  async selectOption(select, option) {
1659
- if (this.isWeb) return super.selectOption(select, option);
1660
- throw new Error('Should be used only in Web context. In native context use \'click\' method instead');
1688
+ if (this.isWeb) return super.selectOption(select, option)
1689
+ throw new Error("Should be used only in Web context. In native context use 'click' method instead")
1661
1690
  }
1662
1691
 
1663
1692
  /**
@@ -1665,8 +1694,8 @@ class Appium extends Webdriver {
1665
1694
  *
1666
1695
  */
1667
1696
  async waitForElement(locator, sec = null) {
1668
- if (this.isWeb) return super.waitForElement(locator, sec);
1669
- return super.waitForElement(parseLocator.call(this, locator), sec);
1697
+ if (this.isWeb) return super.waitForElement(locator, sec)
1698
+ return super.waitForElement(parseLocator.call(this, locator), sec)
1670
1699
  }
1671
1700
 
1672
1701
  /**
@@ -1674,8 +1703,8 @@ class Appium extends Webdriver {
1674
1703
  *
1675
1704
  */
1676
1705
  async waitForVisible(locator, sec = null) {
1677
- if (this.isWeb) return super.waitForVisible(locator, sec);
1678
- return super.waitForVisible(parseLocator.call(this, locator), sec);
1706
+ if (this.isWeb) return super.waitForVisible(locator, sec)
1707
+ return super.waitForVisible(parseLocator.call(this, locator), sec)
1679
1708
  }
1680
1709
 
1681
1710
  /**
@@ -1683,8 +1712,8 @@ class Appium extends Webdriver {
1683
1712
  *
1684
1713
  */
1685
1714
  async waitForInvisible(locator, sec = null) {
1686
- if (this.isWeb) return super.waitForInvisible(locator, sec);
1687
- return super.waitForInvisible(parseLocator.call(this, locator), sec);
1715
+ if (this.isWeb) return super.waitForInvisible(locator, sec)
1716
+ return super.waitForInvisible(parseLocator.call(this, locator), sec)
1688
1717
  }
1689
1718
 
1690
1719
  /**
@@ -1692,74 +1721,76 @@ class Appium extends Webdriver {
1692
1721
  *
1693
1722
  */
1694
1723
  async waitForText(text, sec = null, context = null) {
1695
- if (this.isWeb) return super.waitForText(text, sec, context);
1696
- return super.waitForText(text, sec, parseLocator.call(this, context));
1724
+ if (this.isWeb) return super.waitForText(text, sec, context)
1725
+ return super.waitForText(text, sec, parseLocator.call(this, context))
1697
1726
  }
1698
1727
  }
1699
1728
 
1700
1729
  function parseLocator(locator) {
1701
- if (!locator) return null;
1730
+ if (!locator) return null
1702
1731
 
1703
1732
  if (typeof locator === 'object') {
1704
1733
  if (locator.web && this.isWeb) {
1705
- return parseLocator.call(this, locator.web);
1734
+ return parseLocator.call(this, locator.web)
1706
1735
  }
1707
1736
 
1708
1737
  if (locator.android && this.platform === 'android') {
1709
1738
  if (typeof locator.android === 'string') {
1710
- return parseLocator.call(this, locator.android);
1739
+ return parseLocator.call(this, locator.android)
1711
1740
  }
1712
1741
  // The locator is an Android DataMatcher or ViewMatcher locator so return as is
1713
- return locator.android;
1742
+ return locator.android
1714
1743
  }
1715
1744
 
1716
1745
  if (locator.ios && this.platform === 'ios') {
1717
- return parseLocator.call(this, locator.ios);
1746
+ return parseLocator.call(this, locator.ios)
1718
1747
  }
1719
1748
  }
1720
1749
 
1721
1750
  if (typeof locator === 'string') {
1722
- if (locator[0] === '~') return locator;
1723
- if (locator.substr(0, 2) === '//') return locator;
1751
+ if (locator[0] === '~') return locator
1752
+ if (locator.substr(0, 2) === '//') return locator
1724
1753
  if (locator[0] === '#' && !this.isWeb) {
1725
1754
  // hook before webdriverio supports native # locators
1726
- return parseLocator.call(this, { id: locator.slice(1) });
1755
+ return parseLocator.call(this, { id: locator.slice(1) })
1727
1756
  }
1728
1757
 
1729
1758
  if (this.platform === 'android' && !this.isWeb) {
1730
- const isNativeLocator = /^\-?android=?/.exec(locator);
1731
- return isNativeLocator
1732
- ? locator
1733
- : `android=new UiSelector().text("${locator}")`;
1759
+ const isNativeLocator = /^\-?android=?/.exec(locator)
1760
+ return isNativeLocator ? locator : `android=new UiSelector().text("${locator}")`
1734
1761
  }
1735
1762
  }
1736
1763
 
1737
- locator = new Locator(locator, 'xpath');
1738
- if (locator.type === 'css' && !this.isWeb) throw new Error('Unable to use css locators in apps. Locator strategies for this request: xpath, id, class name or accessibility id');
1739
- if (locator.type === 'name' && !this.isWeb) throw new Error("Can't locate element by name in Native context. Use either ID, class name or accessibility id");
1740
- if (locator.type === 'id' && !this.isWeb && this.platform === 'android') return `//*[@resource-id='${locator.value}']`;
1741
- return locator.simplify();
1764
+ locator = new Locator(locator, 'xpath')
1765
+ if (locator.type === 'css' && !this.isWeb)
1766
+ throw new Error(
1767
+ 'Unable to use css locators in apps. Locator strategies for this request: xpath, id, class name or accessibility id',
1768
+ )
1769
+ if (locator.type === 'name' && !this.isWeb)
1770
+ throw new Error("Can't locate element by name in Native context. Use either ID, class name or accessibility id")
1771
+ if (locator.type === 'id' && !this.isWeb && this.platform === 'android') return `//*[@resource-id='${locator.value}']`
1772
+ return locator.simplify()
1742
1773
  }
1743
1774
 
1744
1775
  // in the end of a file
1745
1776
  function onlyForApps(expectedPlatform) {
1746
- const stack = new Error().stack || '';
1747
- const re = /Appium.(\w+)/g;
1748
- const caller = stack.split('\n')[2].trim();
1749
- const m = re.exec(caller);
1777
+ const stack = new Error().stack || ''
1778
+ const re = /Appium.(\w+)/g
1779
+ const caller = stack.split('\n')[2].trim()
1780
+ const m = re.exec(caller)
1750
1781
 
1751
1782
  if (!m) {
1752
- throw new Error(`Invalid caller ${caller}`);
1783
+ throw new Error(`Invalid caller ${caller}`)
1753
1784
  }
1754
1785
 
1755
- const callerName = m[1] || m[2];
1786
+ const callerName = m[1] || m[2]
1756
1787
  if (!expectedPlatform) {
1757
1788
  if (!this.platform) {
1758
- throw new Error(`${callerName} method can be used only with apps`);
1789
+ throw new Error(`${callerName} method can be used only with apps`)
1759
1790
  }
1760
1791
  } else if (this.platform !== expectedPlatform.toLowerCase()) {
1761
- throw new Error(`${callerName} method can be used only with ${expectedPlatform} apps`);
1792
+ throw new Error(`${callerName} method can be used only with ${expectedPlatform} apps`)
1762
1793
  }
1763
1794
  }
1764
1795
 
1765
- export default Appium;
1796
+ module.exports = Appium