codeceptjs 4.0.0-beta.2 → 4.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +2 -2
  2. package/bin/codecept.js +84 -81
  3. package/lib/actor.js +13 -13
  4. package/lib/ai.js +10 -13
  5. package/lib/assert/empty.js +20 -21
  6. package/lib/assert/equal.js +37 -39
  7. package/lib/assert/error.js +14 -14
  8. package/lib/assert/include.js +46 -47
  9. package/lib/assert/throws.js +13 -11
  10. package/lib/assert/truth.js +19 -22
  11. package/lib/assert.js +4 -2
  12. package/lib/cli.js +56 -49
  13. package/lib/codecept.js +145 -155
  14. package/lib/colorUtils.js +3 -3
  15. package/lib/command/configMigrate.js +58 -52
  16. package/lib/command/definitions.js +88 -89
  17. package/lib/command/dryRun.js +79 -81
  18. package/lib/command/generate.js +197 -188
  19. package/lib/command/gherkin/init.js +27 -16
  20. package/lib/command/gherkin/snippets.js +21 -21
  21. package/lib/command/gherkin/steps.js +8 -8
  22. package/lib/command/info.js +40 -38
  23. package/lib/command/init.js +290 -288
  24. package/lib/command/interactive.js +32 -32
  25. package/lib/command/list.js +26 -26
  26. package/lib/command/run-multiple/chunk.js +5 -5
  27. package/lib/command/run-multiple/collection.js +3 -3
  28. package/lib/command/run-multiple/run.js +6 -2
  29. package/lib/command/run-multiple.js +113 -93
  30. package/lib/command/run-rerun.js +20 -25
  31. package/lib/command/run-workers.js +64 -66
  32. package/lib/command/run.js +26 -29
  33. package/lib/command/utils.js +80 -65
  34. package/lib/command/workers/runTests.js +11 -12
  35. package/lib/config.js +10 -9
  36. package/lib/container.js +40 -48
  37. package/lib/data/context.js +60 -59
  38. package/lib/data/dataScenarioConfig.js +47 -47
  39. package/lib/data/dataTableArgument.js +29 -29
  40. package/lib/data/table.js +26 -20
  41. package/lib/event.js +163 -167
  42. package/lib/heal.js +14 -18
  43. package/lib/helper/AI.js +130 -41
  44. package/lib/helper/ApiDataFactory.js +74 -70
  45. package/lib/helper/Appium.js +416 -388
  46. package/lib/helper/ExpectHelper.js +40 -48
  47. package/lib/helper/FileSystem.js +80 -79
  48. package/lib/helper/GraphQL.js +44 -43
  49. package/lib/helper/GraphQLDataFactory.js +51 -51
  50. package/lib/helper/JSONResponse.js +65 -62
  51. package/lib/helper/Mochawesome.js +28 -28
  52. package/lib/helper/Nightmare.js +664 -571
  53. package/lib/helper/Playwright.js +1367 -1222
  54. package/lib/helper/Protractor.js +663 -635
  55. package/lib/helper/Puppeteer.js +1232 -1132
  56. package/lib/helper/REST.js +183 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -486
  59. package/lib/helper/WebDriver.js +1246 -1297
  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 +4 -4
  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 +4 -3
  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 +7 -8
  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 +7 -11
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +19 -15
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +45 -38
  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 +112 -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 -3
  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 -33
  136. package/package.json +67 -68
  137. package/translations/de-DE.js +2 -1
  138. package/translations/fr-FR.js +2 -2
  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 +423 -65
  148. package/typings/promiseBasedTypes.d.ts +41 -172
  149. package/typings/types.d.ts +43 -178
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
  152. package/lib/helper/MockServer.js +0 -223
@@ -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
  /**
@@ -480,38 +491,36 @@ class Appium extends Webdriver {
480
491
  * });
481
492
  * ```
482
493
  *
483
- * @param {*} fn
484
494
  */
485
- /* eslint-disable */
486
- async runInWeb(fn) {
487
- if (!this.isWeb) return;
488
- recorder.session.start('Web-only actions');
489
495
 
490
- recorder.add('restore from Web session', () => recorder.session.restore(), true);
491
- return recorder.promise();
496
+ async runInWeb() {
497
+ if (!this.isWeb) return
498
+ recorder.session.start('Web-only actions')
499
+
500
+ recorder.add('restore from Web session', () => recorder.session.restore(), true)
501
+ return recorder.promise()
492
502
  }
493
- /* eslint-enable */
494
503
 
495
- async _runWithCaps(caps, fn) {
504
+ _runWithCaps(caps, fn) {
496
505
  if (typeof caps === 'object') {
497
506
  for (const key in caps) {
498
507
  // skip if capabilities do not match
499
508
  if (this.config.desiredCapabilities[key] !== caps[key]) {
500
- return;
509
+ return
501
510
  }
502
511
  }
503
512
  }
504
513
  if (typeof caps === 'function') {
505
514
  if (!fn) {
506
- fn = caps;
515
+ fn = caps
507
516
  } else {
508
517
  // skip if capabilities are checked inside a function
509
- const enabled = caps(this.config.desiredCapabilities);
510
- if (!enabled) return;
518
+ const enabled = caps(this.config.desiredCapabilities)
519
+ if (!enabled) return
511
520
  }
512
521
  }
513
522
 
514
- fn();
523
+ fn()
515
524
  }
516
525
 
517
526
  /**
@@ -527,9 +536,9 @@ class Appium extends Webdriver {
527
536
  * Appium: support only Android
528
537
  */
529
538
  async checkIfAppIsInstalled(bundleId) {
530
- onlyForApps.call(this, supportedPlatform.android);
539
+ onlyForApps.call(this, supportedPlatform.android)
531
540
 
532
- return this.browser.isAppInstalled(bundleId);
541
+ return this.browser.isAppInstalled(bundleId)
533
542
  }
534
543
 
535
544
  /**
@@ -545,9 +554,9 @@ class Appium extends Webdriver {
545
554
  * Appium: support only Android
546
555
  */
547
556
  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);
557
+ onlyForApps.call(this, supportedPlatform.android)
558
+ const res = await this.browser.isAppInstalled(bundleId)
559
+ return truth(`app ${bundleId}`, 'to be installed').assert(res)
551
560
  }
552
561
 
553
562
  /**
@@ -563,9 +572,9 @@ class Appium extends Webdriver {
563
572
  * Appium: support only Android
564
573
  */
565
574
  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);
575
+ onlyForApps.call(this, supportedPlatform.android)
576
+ const res = await this.browser.isAppInstalled(bundleId)
577
+ return truth(`app ${bundleId}`, 'not to be installed').negate(res)
569
578
  }
570
579
 
571
580
  /**
@@ -580,8 +589,8 @@ class Appium extends Webdriver {
580
589
  * Appium: support only Android
581
590
  */
582
591
  async installApp(path) {
583
- onlyForApps.call(this, supportedPlatform.android);
584
- return this.browser.installApp(path);
592
+ onlyForApps.call(this, supportedPlatform.android)
593
+ return this.browser.installApp(path)
585
594
  }
586
595
 
587
596
  /**
@@ -597,13 +606,13 @@ class Appium extends Webdriver {
597
606
  * @param {string} [bundleId] ID of bundle
598
607
  */
599
608
  async removeApp(appId, bundleId) {
600
- onlyForApps.call(this, supportedPlatform.android);
609
+ onlyForApps.call(this, supportedPlatform.android)
601
610
 
602
611
  return this.axios({
603
612
  method: 'post',
604
613
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/device/remove_app`,
605
614
  data: { appId, bundleId },
606
- });
615
+ })
607
616
  }
608
617
 
609
618
  /**
@@ -615,11 +624,11 @@ class Appium extends Webdriver {
615
624
  *
616
625
  */
617
626
  async resetApp() {
618
- onlyForApps.call(this);
627
+ onlyForApps.call(this)
619
628
  return this.axios({
620
629
  method: 'post',
621
630
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/app/reset`,
622
- });
631
+ })
623
632
  }
624
633
 
625
634
  /**
@@ -634,9 +643,9 @@ class Appium extends Webdriver {
634
643
  * Appium: support only Android
635
644
  */
636
645
  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);
646
+ onlyForApps.call(this, supportedPlatform.android)
647
+ const res = await this.browser.getCurrentActivity()
648
+ return truth('current activity', `to be ${currentActivity}`).assert(res === currentActivity)
640
649
  }
641
650
 
642
651
  /**
@@ -651,9 +660,9 @@ class Appium extends Webdriver {
651
660
  * Appium: support only Android
652
661
  */
653
662
  async seeDeviceIsLocked() {
654
- onlyForApps.call(this, supportedPlatform.android);
655
- const res = await this.browser.isLocked();
656
- return truth('device', 'to be locked').assert(res);
663
+ onlyForApps.call(this, supportedPlatform.android)
664
+ const res = await this.browser.isLocked()
665
+ return truth('device', 'to be locked').assert(res)
657
666
  }
658
667
 
659
668
  /**
@@ -668,9 +677,9 @@ class Appium extends Webdriver {
668
677
  * Appium: support only Android
669
678
  */
670
679
  async seeDeviceIsUnlocked() {
671
- onlyForApps.call(this, supportedPlatform.android);
672
- const res = await this.browser.isLocked();
673
- return truth('device', 'to be locked').negate(res);
680
+ onlyForApps.call(this, supportedPlatform.android)
681
+ const res = await this.browser.isLocked()
682
+ return truth('device', 'to be locked').negate(res)
674
683
  }
675
684
 
676
685
  /**
@@ -688,15 +697,15 @@ class Appium extends Webdriver {
688
697
  * Appium: support Android and iOS
689
698
  */
690
699
  async seeOrientationIs(orientation) {
691
- onlyForApps.call(this);
700
+ onlyForApps.call(this)
692
701
 
693
702
  const res = await this.axios({
694
703
  method: 'get',
695
704
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
696
- });
705
+ })
697
706
 
698
- const currentOrientation = res.data.value;
699
- return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation);
707
+ const currentOrientation = res.data.value
708
+ return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation)
700
709
  }
701
710
 
702
711
  /**
@@ -712,13 +721,13 @@ class Appium extends Webdriver {
712
721
  * Appium: support Android and iOS
713
722
  */
714
723
  async setOrientation(orientation) {
715
- onlyForApps.call(this);
724
+ onlyForApps.call(this)
716
725
 
717
726
  return this.axios({
718
727
  method: 'post',
719
728
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
720
729
  data: { orientation },
721
- });
730
+ })
722
731
  }
723
732
 
724
733
  /**
@@ -733,8 +742,8 @@ class Appium extends Webdriver {
733
742
  * Appium: support Android and iOS
734
743
  */
735
744
  async grabAllContexts() {
736
- onlyForApps.call(this);
737
- return this.browser.getContexts();
745
+ onlyForApps.call(this)
746
+ return this.browser.getContexts()
738
747
  }
739
748
 
740
749
  /**
@@ -749,8 +758,8 @@ class Appium extends Webdriver {
749
758
  * Appium: support Android and iOS
750
759
  */
751
760
  async grabContext() {
752
- onlyForApps.call(this);
753
- return this.browser.getContext();
761
+ onlyForApps.call(this)
762
+ return this.browser.getContext()
754
763
  }
755
764
 
756
765
  /**
@@ -765,8 +774,8 @@ class Appium extends Webdriver {
765
774
  * Appium: support only Android
766
775
  */
767
776
  async grabCurrentActivity() {
768
- onlyForApps.call(this, supportedPlatform.android);
769
- return this.browser.getCurrentActivity();
777
+ onlyForApps.call(this, supportedPlatform.android)
778
+ return this.browser.getCurrentActivity()
770
779
  }
771
780
 
772
781
  /**
@@ -783,14 +792,14 @@ class Appium extends Webdriver {
783
792
  * Appium: support only Android
784
793
  */
785
794
  async grabNetworkConnection() {
786
- onlyForApps.call(this, supportedPlatform.android);
787
- const res = await this.browser.getNetworkConnection();
795
+ onlyForApps.call(this, supportedPlatform.android)
796
+ const res = await this.browser.getNetworkConnection()
788
797
  return {
789
798
  value: res,
790
799
  inAirplaneMode: res.inAirplaneMode,
791
800
  hasWifi: res.hasWifi,
792
801
  hasData: res.hasData,
793
- };
802
+ }
794
803
  }
795
804
 
796
805
  /**
@@ -805,10 +814,10 @@ class Appium extends Webdriver {
805
814
  * Appium: support Android and iOS
806
815
  */
807
816
  async grabOrientation() {
808
- onlyForApps.call(this);
809
- const res = await this.browser.orientation();
810
- this.debugSection('Orientation', res);
811
- return res;
817
+ onlyForApps.call(this)
818
+ const res = await this.browser.orientation()
819
+ this.debugSection('Orientation', res)
820
+ return res
812
821
  }
813
822
 
814
823
  /**
@@ -823,10 +832,10 @@ class Appium extends Webdriver {
823
832
  * Appium: support Android and iOS
824
833
  */
825
834
  async grabSettings() {
826
- onlyForApps.call(this);
827
- const res = await this.browser.getSettings();
828
- this.debugSection('Settings', JSON.stringify(res));
829
- return res;
835
+ onlyForApps.call(this)
836
+ const res = await this.browser.getSettings()
837
+ this.debugSection('Settings', JSON.stringify(res))
838
+ return res
830
839
  }
831
840
 
832
841
  /**
@@ -835,7 +844,7 @@ class Appium extends Webdriver {
835
844
  * @param {*} context the context to switch to
836
845
  */
837
846
  async switchToContext(context) {
838
- return this.browser.switchContext(context);
847
+ return this.browser.switchContext(context)
839
848
  }
840
849
 
841
850
  /**
@@ -855,17 +864,17 @@ class Appium extends Webdriver {
855
864
  * @param {string} [context]
856
865
  */
857
866
  async switchToWeb(context) {
858
- this.isWeb = true;
859
- this.defaultContext = 'body';
867
+ this.isWeb = true
868
+ this.defaultContext = 'body'
860
869
 
861
- if (context) return this.switchToContext(context);
862
- const contexts = await this.grabAllContexts();
863
- this.debugSection('Contexts', contexts.toString());
870
+ if (context) return this.switchToContext(context)
871
+ const contexts = await this.grabAllContexts()
872
+ this.debugSection('Contexts', contexts.toString())
864
873
  for (const idx in contexts) {
865
- if (contexts[idx].match(/^WEBVIEW/)) return this.switchToContext(contexts[idx]);
874
+ if (contexts[idx].match(/^WEBVIEW/)) return this.switchToContext(contexts[idx])
866
875
  }
867
876
 
868
- throw new Error('No WEBVIEW could be guessed, please specify one in params');
877
+ throw new Error('No WEBVIEW could be guessed, please specify one in params')
869
878
  }
870
879
 
871
880
  /**
@@ -882,11 +891,11 @@ class Appium extends Webdriver {
882
891
  * @return {Promise<void>}
883
892
  */
884
893
  async switchToNative(context = null) {
885
- this.isWeb = false;
886
- this.defaultContext = '//*';
894
+ this.isWeb = false
895
+ this.defaultContext = '//*'
887
896
 
888
- if (context) return this.switchToContext(context);
889
- return this.switchToContext('NATIVE_APP');
897
+ if (context) return this.switchToContext(context)
898
+ return this.switchToContext('NATIVE_APP')
890
899
  }
891
900
 
892
901
  /**
@@ -903,8 +912,8 @@ class Appium extends Webdriver {
903
912
  * @return {Promise<void>}
904
913
  */
905
914
  async startActivity(appPackage, appActivity) {
906
- onlyForApps.call(this, supportedPlatform.android);
907
- return this.browser.startActivity(appPackage, appActivity);
915
+ onlyForApps.call(this, supportedPlatform.android)
916
+ return this.browser.startActivity(appPackage, appActivity)
908
917
  }
909
918
 
910
919
  /**
@@ -929,8 +938,8 @@ class Appium extends Webdriver {
929
938
  * @return {Promise<number>}
930
939
  */
931
940
  async setNetworkConnection(value) {
932
- onlyForApps.call(this, supportedPlatform.android);
933
- return this.browser.setNetworkConnection(value);
941
+ onlyForApps.call(this, supportedPlatform.android)
942
+ return this.browser.setNetworkConnection(value)
934
943
  }
935
944
 
936
945
  /**
@@ -945,8 +954,8 @@ class Appium extends Webdriver {
945
954
  * Appium: support Android and iOS
946
955
  */
947
956
  async setSettings(settings) {
948
- onlyForApps.call(this);
949
- return this.browser.settings(settings);
957
+ onlyForApps.call(this)
958
+ return this.browser.settings(settings)
950
959
  }
951
960
 
952
961
  /**
@@ -967,9 +976,9 @@ class Appium extends Webdriver {
967
976
  * @param {string} [key] Optional key
968
977
  */
969
978
  async hideDeviceKeyboard(strategy, key) {
970
- onlyForApps.call(this);
971
- strategy = strategy || 'tapOutside';
972
- return this.browser.hideKeyboard(strategy, key);
979
+ onlyForApps.call(this)
980
+ strategy = strategy || 'tapOutside'
981
+ return this.browser.hideKeyboard(strategy, key)
973
982
  }
974
983
 
975
984
  /**
@@ -986,8 +995,8 @@ class Appium extends Webdriver {
986
995
  * Appium: support only Android
987
996
  */
988
997
  async sendDeviceKeyEvent(keyValue) {
989
- onlyForApps.call(this, supportedPlatform.android);
990
- return this.browser.pressKeyCode(keyValue);
998
+ onlyForApps.call(this, supportedPlatform.android)
999
+ return this.browser.pressKeyCode(keyValue)
991
1000
  }
992
1001
 
993
1002
  /**
@@ -1002,8 +1011,8 @@ class Appium extends Webdriver {
1002
1011
  * Appium: support only Android
1003
1012
  */
1004
1013
  async openNotifications() {
1005
- onlyForApps.call(this, supportedPlatform.android);
1006
- return this.browser.openNotifications();
1014
+ onlyForApps.call(this, supportedPlatform.android)
1015
+ return this.browser.openNotifications()
1007
1016
  }
1008
1017
 
1009
1018
  /**
@@ -1022,13 +1031,13 @@ class Appium extends Webdriver {
1022
1031
  * Appium: support Android and iOS
1023
1032
  */
1024
1033
  async makeTouchAction(locator, action) {
1025
- onlyForApps.call(this);
1026
- const element = await this.browser.$(parseLocator.call(this, locator));
1034
+ onlyForApps.call(this)
1035
+ const element = await this.browser.$(parseLocator.call(this, locator))
1027
1036
 
1028
1037
  return this.browser.touchAction({
1029
1038
  action,
1030
1039
  element,
1031
- });
1040
+ })
1032
1041
  }
1033
1042
 
1034
1043
  /**
@@ -1045,7 +1054,7 @@ class Appium extends Webdriver {
1045
1054
  * @param {*} locator
1046
1055
  */
1047
1056
  async tap(locator) {
1048
- return this.makeTouchAction(locator, 'tap');
1057
+ return this.makeTouchAction(locator, 'tap')
1049
1058
  }
1050
1059
 
1051
1060
  /**
@@ -1066,14 +1075,16 @@ class Appium extends Webdriver {
1066
1075
  *
1067
1076
  * Appium: support Android and iOS
1068
1077
  */
1069
- /* eslint-disable */
1078
+
1070
1079
  async swipe(locator, xoffset, yoffset, speed = 1000) {
1071
- onlyForApps.call(this);
1072
- const res = await this.browser.$(parseLocator.call(this, locator));
1080
+ onlyForApps.call(this)
1081
+ const res = await this.browser.$(parseLocator.call(this, locator))
1073
1082
  // 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 });
1083
+ return this.performSwipe(await res.getLocation(), {
1084
+ x: (await res.getLocation()).x + xoffset,
1085
+ y: (await res.getLocation()).y + yoffset,
1086
+ })
1075
1087
  }
1076
- /* eslint-enable */
1077
1088
 
1078
1089
  /**
1079
1090
  * Perform a swipe on the screen.
@@ -1088,42 +1099,44 @@ class Appium extends Webdriver {
1088
1099
  * Appium: support Android and iOS
1089
1100
  */
1090
1101
  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',
1102
+ await this.browser.performActions([
1103
+ {
1104
+ id: uuidv4(),
1105
+ type: 'pointer',
1106
+ parameters: {
1107
+ pointerType: 'touch',
1108
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',
1119
- },
1120
- {
1121
- button: 1,
1122
- type: 'pointerUp',
1123
- },
1124
- ],
1125
- }]);
1126
- await this.browser.pause(1000);
1109
+ actions: [
1110
+ {
1111
+ duration: 0,
1112
+ x: from.x,
1113
+ y: from.y,
1114
+ type: 'pointerMove',
1115
+ origin: 'viewport',
1116
+ },
1117
+ {
1118
+ button: 1,
1119
+ type: 'pointerDown',
1120
+ },
1121
+ {
1122
+ duration: 200,
1123
+ type: 'pause',
1124
+ },
1125
+ {
1126
+ duration: 600,
1127
+ x: to.x,
1128
+ y: to.y,
1129
+ type: 'pointerMove',
1130
+ origin: 'viewport',
1131
+ },
1132
+ {
1133
+ button: 1,
1134
+ type: 'pointerUp',
1135
+ },
1136
+ ],
1137
+ },
1138
+ ])
1139
+ await this.browser.pause(1000)
1127
1140
  }
1128
1141
 
1129
1142
  /**
@@ -1144,14 +1157,14 @@ class Appium extends Webdriver {
1144
1157
  * Appium: support Android and iOS
1145
1158
  */
1146
1159
  async swipeDown(locator, yoffset = 1000, speed) {
1147
- onlyForApps.call(this);
1160
+ onlyForApps.call(this)
1148
1161
 
1149
1162
  if (!speed) {
1150
- speed = yoffset;
1151
- yoffset = 100;
1163
+ speed = yoffset
1164
+ yoffset = 100
1152
1165
  }
1153
1166
 
1154
- return this.swipe(parseLocator.call(this, locator), 0, yoffset, speed);
1167
+ return this.swipe(parseLocator.call(this, locator), 0, yoffset, speed)
1155
1168
  }
1156
1169
 
1157
1170
  /**
@@ -1173,13 +1186,13 @@ class Appium extends Webdriver {
1173
1186
  * Appium: support Android and iOS
1174
1187
  */
1175
1188
  async swipeLeft(locator, xoffset = 1000, speed) {
1176
- onlyForApps.call(this);
1189
+ onlyForApps.call(this)
1177
1190
  if (!speed) {
1178
- speed = xoffset;
1179
- xoffset = 100;
1191
+ speed = xoffset
1192
+ xoffset = 100
1180
1193
  }
1181
1194
 
1182
- return this.swipe(parseLocator.call(this, locator), -xoffset, 0, speed);
1195
+ return this.swipe(parseLocator.call(this, locator), -xoffset, 0, speed)
1183
1196
  }
1184
1197
 
1185
1198
  /**
@@ -1200,13 +1213,13 @@ class Appium extends Webdriver {
1200
1213
  * Appium: support Android and iOS
1201
1214
  */
1202
1215
  async swipeRight(locator, xoffset = 1000, speed) {
1203
- onlyForApps.call(this);
1216
+ onlyForApps.call(this)
1204
1217
  if (!speed) {
1205
- speed = xoffset;
1206
- xoffset = 100;
1218
+ speed = xoffset
1219
+ xoffset = 100
1207
1220
  }
1208
1221
 
1209
- return this.swipe(parseLocator.call(this, locator), xoffset, 0, speed);
1222
+ return this.swipe(parseLocator.call(this, locator), xoffset, 0, speed)
1210
1223
  }
1211
1224
 
1212
1225
  /**
@@ -1227,14 +1240,14 @@ class Appium extends Webdriver {
1227
1240
  * Appium: support Android and iOS
1228
1241
  */
1229
1242
  async swipeUp(locator, yoffset = 1000, speed) {
1230
- onlyForApps.call(this);
1243
+ onlyForApps.call(this)
1231
1244
 
1232
1245
  if (!speed) {
1233
- speed = yoffset;
1234
- yoffset = 100;
1246
+ speed = yoffset
1247
+ yoffset = 100
1235
1248
  }
1236
1249
 
1237
- return this.swipe(parseLocator.call(this, locator), 0, -yoffset, speed);
1250
+ return this.swipe(parseLocator.call(this, locator), 0, -yoffset, speed)
1238
1251
  }
1239
1252
 
1240
1253
  /**
@@ -1261,55 +1274,66 @@ class Appium extends Webdriver {
1261
1274
  * Appium: support Android and iOS
1262
1275
  */
1263
1276
  async swipeTo(searchableLocator, scrollLocator, direction, timeout, offset, speed) {
1264
- onlyForApps.call(this);
1265
- direction = direction || 'down';
1277
+ onlyForApps.call(this)
1278
+ direction = direction || 'down'
1266
1279
  switch (direction) {
1267
1280
  case 'down':
1268
- direction = 'swipeDown';
1269
- break;
1281
+ direction = 'swipeDown'
1282
+ break
1270
1283
  case 'up':
1271
- direction = 'swipeUp';
1272
- break;
1284
+ direction = 'swipeUp'
1285
+ break
1273
1286
  case 'left':
1274
- direction = 'swipeLeft';
1275
- break;
1287
+ direction = 'swipeLeft'
1288
+ break
1276
1289
  case 'right':
1277
- direction = 'swipeRight';
1278
- break;
1290
+ direction = 'swipeRight'
1291
+ break
1279
1292
  }
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;
1293
+ timeout = timeout || this.options.waitForTimeoutInSeconds
1294
+
1295
+ const errorMsg = `element ("${searchableLocator}") still not visible after ${timeout}seconds`
1296
+ const browser = this.browser
1297
+ let err = false
1298
+ let currentSource
1299
+ return browser
1300
+ .waitUntil(
1301
+ () => {
1302
+ if (err) {
1303
+ return new Error(`Scroll to the end and element ${searchableLocator} was not found`)
1295
1304
  }
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)
1305
+ return browser
1306
+ .$$(parseLocator.call(this, searchableLocator))
1307
+ .then((els) => els.length && els[0].isDisplayed())
1308
+ .then((res) => {
1309
+ if (res) {
1310
+ return true
1311
+ }
1312
+ return this[direction](scrollLocator, offset, speed)
1313
+ .getSource()
1314
+ .then((source) => {
1315
+ if (source === currentSource) {
1316
+ err = true
1317
+ } else {
1318
+ currentSource = source
1319
+ return false
1320
+ }
1321
+ })
1322
+ })
1323
+ },
1324
+ timeout * 1000,
1325
+ errorMsg,
1326
+ )
1306
1327
  .catch((e) => {
1307
1328
  if (e.message.indexOf('timeout') && e.type !== 'NoSuchElement') {
1308
- throw new AssertionFailedError({ customMessage: `Scroll to the end and element ${searchableLocator} was not found` }, '');
1329
+ throw new AssertionFailedError(
1330
+ { customMessage: `Scroll to the end and element ${searchableLocator} was not found` },
1331
+ '',
1332
+ )
1309
1333
  } else {
1310
- throw e;
1334
+ throw e
1311
1335
  }
1312
- });
1336
+ })
1313
1337
  }
1314
1338
 
1315
1339
  /**
@@ -1341,8 +1365,8 @@ class Appium extends Webdriver {
1341
1365
  * @param {Array} actions Array of touch actions
1342
1366
  */
1343
1367
  async touchPerform(actions) {
1344
- onlyForApps.call(this);
1345
- return this.browser.touchPerform(actions);
1368
+ onlyForApps.call(this)
1369
+ return this.browser.touchPerform(actions)
1346
1370
  }
1347
1371
 
1348
1372
  /**
@@ -1361,13 +1385,15 @@ class Appium extends Webdriver {
1361
1385
  * Appium: support Android and iOS
1362
1386
  */
1363
1387
  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
- }));
1388
+ onlyForApps.call(this)
1389
+ return this.browser.pullFile(path).then((res) =>
1390
+ fs.writeFile(dest, Buffer.from(res, 'base64'), (err) => {
1391
+ if (err) {
1392
+ return false
1393
+ }
1394
+ return true
1395
+ }),
1396
+ )
1371
1397
  }
1372
1398
 
1373
1399
  /**
@@ -1382,8 +1408,8 @@ class Appium extends Webdriver {
1382
1408
  * Appium: support only iOS
1383
1409
  */
1384
1410
  async shakeDevice() {
1385
- onlyForApps.call(this, 'iOS');
1386
- return this.browser.shake();
1411
+ onlyForApps.call(this, 'iOS')
1412
+ return this.browser.shake()
1387
1413
  }
1388
1414
 
1389
1415
  /**
@@ -1400,8 +1426,8 @@ class Appium extends Webdriver {
1400
1426
  * Appium: support only iOS
1401
1427
  */
1402
1428
  async rotate(x, y, duration, radius, rotation, touchCount) {
1403
- onlyForApps.call(this, 'iOS');
1404
- return this.browser.rotate(x, y, duration, radius, rotation, touchCount);
1429
+ onlyForApps.call(this, 'iOS')
1430
+ return this.browser.rotate(x, y, duration, radius, rotation, touchCount)
1405
1431
  }
1406
1432
 
1407
1433
  /**
@@ -1414,8 +1440,8 @@ class Appium extends Webdriver {
1414
1440
  * Appium: support only iOS
1415
1441
  */
1416
1442
  async setImmediateValue(id, value) {
1417
- onlyForApps.call(this, 'iOS');
1418
- return this.browser.setImmediateValue(id, value);
1443
+ onlyForApps.call(this, 'iOS')
1444
+ return this.browser.setImmediateValue(id, value)
1419
1445
  }
1420
1446
 
1421
1447
  /**
@@ -1433,9 +1459,9 @@ class Appium extends Webdriver {
1433
1459
  * TODO: not tested
1434
1460
  */
1435
1461
  async simulateTouchId(match) {
1436
- onlyForApps.call(this, 'iOS');
1437
- match = match || true;
1438
- return this.browser.touchId(match);
1462
+ onlyForApps.call(this, 'iOS')
1463
+ match = match || true
1464
+ return this.browser.touchId(match)
1439
1465
  }
1440
1466
 
1441
1467
  /**
@@ -1450,8 +1476,8 @@ class Appium extends Webdriver {
1450
1476
  * Appium: support both Android and iOS
1451
1477
  */
1452
1478
  async closeApp() {
1453
- onlyForApps.call(this);
1454
- return this.browser.closeApp();
1479
+ onlyForApps.call(this)
1480
+ return this.browser.closeApp()
1455
1481
  }
1456
1482
 
1457
1483
  /**
@@ -1459,8 +1485,8 @@ class Appium extends Webdriver {
1459
1485
  *
1460
1486
  */
1461
1487
  async appendField(field, value) {
1462
- if (this.isWeb) return super.appendField(field, value);
1463
- return super.appendField(parseLocator.call(this, field), value);
1488
+ if (this.isWeb) return super.appendField(field, value)
1489
+ return super.appendField(parseLocator.call(this, field), value)
1464
1490
  }
1465
1491
 
1466
1492
  /**
@@ -1468,8 +1494,8 @@ class Appium extends Webdriver {
1468
1494
  *
1469
1495
  */
1470
1496
  async checkOption(field) {
1471
- if (this.isWeb) return super.checkOption(field);
1472
- return super.checkOption(parseLocator.call(this, field));
1497
+ if (this.isWeb) return super.checkOption(field)
1498
+ return super.checkOption(parseLocator.call(this, field))
1473
1499
  }
1474
1500
 
1475
1501
  /**
@@ -1477,8 +1503,8 @@ class Appium extends Webdriver {
1477
1503
  *
1478
1504
  */
1479
1505
  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));
1506
+ if (this.isWeb) return super.click(locator, context)
1507
+ return super.click(parseLocator.call(this, locator), parseLocator.call(this, context))
1482
1508
  }
1483
1509
 
1484
1510
  /**
@@ -1486,16 +1512,16 @@ class Appium extends Webdriver {
1486
1512
  *
1487
1513
  */
1488
1514
  async dontSeeCheckboxIsChecked(field) {
1489
- if (this.isWeb) return super.dontSeeCheckboxIsChecked(field);
1490
- return super.dontSeeCheckboxIsChecked(parseLocator.call(this, field));
1515
+ if (this.isWeb) return super.dontSeeCheckboxIsChecked(field)
1516
+ return super.dontSeeCheckboxIsChecked(parseLocator.call(this, field))
1491
1517
  }
1492
1518
 
1493
1519
  /**
1494
1520
  * {{> dontSeeElement }}
1495
1521
  */
1496
1522
  async dontSeeElement(locator) {
1497
- if (this.isWeb) return super.dontSeeElement(locator);
1498
- return super.dontSeeElement(parseLocator.call(this, locator));
1523
+ if (this.isWeb) return super.dontSeeElement(locator)
1524
+ return super.dontSeeElement(parseLocator.call(this, locator))
1499
1525
  }
1500
1526
 
1501
1527
  /**
@@ -1503,17 +1529,17 @@ class Appium extends Webdriver {
1503
1529
  *
1504
1530
  */
1505
1531
  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);
1532
+ const _value = typeof value === 'boolean' ? value : value.toString()
1533
+ if (this.isWeb) return super.dontSeeInField(field, _value)
1534
+ return super.dontSeeInField(parseLocator.call(this, field), _value)
1509
1535
  }
1510
1536
 
1511
1537
  /**
1512
1538
  * {{> dontSee }}
1513
1539
  */
1514
1540
  async dontSee(text, context = null) {
1515
- if (this.isWeb) return super.dontSee(text, context);
1516
- return super.dontSee(text, parseLocator.call(this, context));
1541
+ if (this.isWeb) return super.dontSee(text, context)
1542
+ return super.dontSee(text, parseLocator.call(this, context))
1517
1543
  }
1518
1544
 
1519
1545
  /**
@@ -1521,9 +1547,9 @@ class Appium extends Webdriver {
1521
1547
  *
1522
1548
  */
1523
1549
  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);
1550
+ value = value.toString()
1551
+ if (this.isWeb) return super.fillField(field, value)
1552
+ return super.fillField(parseLocator.call(this, field), value)
1527
1553
  }
1528
1554
 
1529
1555
  /**
@@ -1531,8 +1557,8 @@ class Appium extends Webdriver {
1531
1557
  *
1532
1558
  */
1533
1559
  async grabTextFromAll(locator) {
1534
- if (this.isWeb) return super.grabTextFromAll(locator);
1535
- return super.grabTextFromAll(parseLocator.call(this, locator));
1560
+ if (this.isWeb) return super.grabTextFromAll(locator)
1561
+ return super.grabTextFromAll(parseLocator.call(this, locator))
1536
1562
  }
1537
1563
 
1538
1564
  /**
@@ -1540,16 +1566,16 @@ class Appium extends Webdriver {
1540
1566
  *
1541
1567
  */
1542
1568
  async grabTextFrom(locator) {
1543
- if (this.isWeb) return super.grabTextFrom(locator);
1544
- return super.grabTextFrom(parseLocator.call(this, locator));
1569
+ if (this.isWeb) return super.grabTextFrom(locator)
1570
+ return super.grabTextFrom(parseLocator.call(this, locator))
1545
1571
  }
1546
1572
 
1547
1573
  /**
1548
1574
  * {{> grabNumberOfVisibleElements }}
1549
1575
  */
1550
1576
  async grabNumberOfVisibleElements(locator) {
1551
- if (this.isWeb) return super.grabNumberOfVisibleElements(locator);
1552
- return super.grabNumberOfVisibleElements(parseLocator.call(this, locator));
1577
+ if (this.isWeb) return super.grabNumberOfVisibleElements(locator)
1578
+ return super.grabNumberOfVisibleElements(parseLocator.call(this, locator))
1553
1579
  }
1554
1580
 
1555
1581
  /**
@@ -1558,8 +1584,8 @@ class Appium extends Webdriver {
1558
1584
  * {{> grabAttributeFrom }}
1559
1585
  */
1560
1586
  async grabAttributeFrom(locator, attr) {
1561
- if (this.isWeb) return super.grabAttributeFrom(locator, attr);
1562
- return super.grabAttributeFrom(parseLocator.call(this, locator), attr);
1587
+ if (this.isWeb) return super.grabAttributeFrom(locator, attr)
1588
+ return super.grabAttributeFrom(parseLocator.call(this, locator), attr)
1563
1589
  }
1564
1590
 
1565
1591
  /**
@@ -1567,8 +1593,8 @@ class Appium extends Webdriver {
1567
1593
  * {{> grabAttributeFromAll }}
1568
1594
  */
1569
1595
  async grabAttributeFromAll(locator, attr) {
1570
- if (this.isWeb) return super.grabAttributeFromAll(locator, attr);
1571
- return super.grabAttributeFromAll(parseLocator.call(this, locator), attr);
1596
+ if (this.isWeb) return super.grabAttributeFromAll(locator, attr)
1597
+ return super.grabAttributeFromAll(parseLocator.call(this, locator), attr)
1572
1598
  }
1573
1599
 
1574
1600
  /**
@@ -1576,8 +1602,8 @@ class Appium extends Webdriver {
1576
1602
  *
1577
1603
  */
1578
1604
  async grabValueFromAll(locator) {
1579
- if (this.isWeb) return super.grabValueFromAll(locator);
1580
- return super.grabValueFromAll(parseLocator.call(this, locator));
1605
+ if (this.isWeb) return super.grabValueFromAll(locator)
1606
+ return super.grabValueFromAll(parseLocator.call(this, locator))
1581
1607
  }
1582
1608
 
1583
1609
  /**
@@ -1585,8 +1611,8 @@ class Appium extends Webdriver {
1585
1611
  *
1586
1612
  */
1587
1613
  async grabValueFrom(locator) {
1588
- if (this.isWeb) return super.grabValueFrom(locator);
1589
- return super.grabValueFrom(parseLocator.call(this, locator));
1614
+ if (this.isWeb) return super.grabValueFrom(locator)
1615
+ return super.grabValueFrom(parseLocator.call(this, locator))
1590
1616
  }
1591
1617
 
1592
1618
  /**
@@ -1601,7 +1627,7 @@ class Appium extends Webdriver {
1601
1627
  * @return {Promise<void>}
1602
1628
  */
1603
1629
  async saveScreenshot(fileName) {
1604
- return super.saveScreenshot(fileName, false);
1630
+ return super.saveScreenshot(fileName, false)
1605
1631
  }
1606
1632
 
1607
1633
  /**
@@ -1610,7 +1636,7 @@ class Appium extends Webdriver {
1610
1636
  * Supported only for web testing
1611
1637
  */
1612
1638
  async scrollIntoView(locator, scrollIntoViewOptions) {
1613
- if (this.isWeb) return super.scrollIntoView(locator, scrollIntoViewOptions);
1639
+ if (this.isWeb) return super.scrollIntoView(locator, scrollIntoViewOptions)
1614
1640
  }
1615
1641
 
1616
1642
  /**
@@ -1618,8 +1644,8 @@ class Appium extends Webdriver {
1618
1644
  *
1619
1645
  */
1620
1646
  async seeCheckboxIsChecked(field) {
1621
- if (this.isWeb) return super.seeCheckboxIsChecked(field);
1622
- return super.seeCheckboxIsChecked(parseLocator.call(this, field));
1647
+ if (this.isWeb) return super.seeCheckboxIsChecked(field)
1648
+ return super.seeCheckboxIsChecked(parseLocator.call(this, field))
1623
1649
  }
1624
1650
 
1625
1651
  /**
@@ -1627,8 +1653,8 @@ class Appium extends Webdriver {
1627
1653
  *
1628
1654
  */
1629
1655
  async seeElement(locator) {
1630
- if (this.isWeb) return super.seeElement(locator);
1631
- return super.seeElement(parseLocator.call(this, locator));
1656
+ if (this.isWeb) return super.seeElement(locator)
1657
+ return super.seeElement(parseLocator.call(this, locator))
1632
1658
  }
1633
1659
 
1634
1660
  /**
@@ -1636,9 +1662,9 @@ class Appium extends Webdriver {
1636
1662
  *
1637
1663
  */
1638
1664
  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);
1665
+ const _value = typeof value === 'boolean' ? value : value.toString()
1666
+ if (this.isWeb) return super.seeInField(field, _value)
1667
+ return super.seeInField(parseLocator.call(this, field), _value)
1642
1668
  }
1643
1669
 
1644
1670
  /**
@@ -1646,8 +1672,8 @@ class Appium extends Webdriver {
1646
1672
  *
1647
1673
  */
1648
1674
  async see(text, context) {
1649
- if (this.isWeb) return super.see(text, context);
1650
- return super.see(text, parseLocator.call(this, context));
1675
+ if (this.isWeb) return super.see(text, context)
1676
+ return super.see(text, parseLocator.call(this, context))
1651
1677
  }
1652
1678
 
1653
1679
  /**
@@ -1656,8 +1682,8 @@ class Appium extends Webdriver {
1656
1682
  * Supported only for web testing
1657
1683
  */
1658
1684
  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');
1685
+ if (this.isWeb) return super.selectOption(select, option)
1686
+ throw new Error("Should be used only in Web context. In native context use 'click' method instead")
1661
1687
  }
1662
1688
 
1663
1689
  /**
@@ -1665,8 +1691,8 @@ class Appium extends Webdriver {
1665
1691
  *
1666
1692
  */
1667
1693
  async waitForElement(locator, sec = null) {
1668
- if (this.isWeb) return super.waitForElement(locator, sec);
1669
- return super.waitForElement(parseLocator.call(this, locator), sec);
1694
+ if (this.isWeb) return super.waitForElement(locator, sec)
1695
+ return super.waitForElement(parseLocator.call(this, locator), sec)
1670
1696
  }
1671
1697
 
1672
1698
  /**
@@ -1674,8 +1700,8 @@ class Appium extends Webdriver {
1674
1700
  *
1675
1701
  */
1676
1702
  async waitForVisible(locator, sec = null) {
1677
- if (this.isWeb) return super.waitForVisible(locator, sec);
1678
- return super.waitForVisible(parseLocator.call(this, locator), sec);
1703
+ if (this.isWeb) return super.waitForVisible(locator, sec)
1704
+ return super.waitForVisible(parseLocator.call(this, locator), sec)
1679
1705
  }
1680
1706
 
1681
1707
  /**
@@ -1683,8 +1709,8 @@ class Appium extends Webdriver {
1683
1709
  *
1684
1710
  */
1685
1711
  async waitForInvisible(locator, sec = null) {
1686
- if (this.isWeb) return super.waitForInvisible(locator, sec);
1687
- return super.waitForInvisible(parseLocator.call(this, locator), sec);
1712
+ if (this.isWeb) return super.waitForInvisible(locator, sec)
1713
+ return super.waitForInvisible(parseLocator.call(this, locator), sec)
1688
1714
  }
1689
1715
 
1690
1716
  /**
@@ -1692,74 +1718,76 @@ class Appium extends Webdriver {
1692
1718
  *
1693
1719
  */
1694
1720
  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));
1721
+ if (this.isWeb) return super.waitForText(text, sec, context)
1722
+ return super.waitForText(text, sec, parseLocator.call(this, context))
1697
1723
  }
1698
1724
  }
1699
1725
 
1700
1726
  function parseLocator(locator) {
1701
- if (!locator) return null;
1727
+ if (!locator) return null
1702
1728
 
1703
1729
  if (typeof locator === 'object') {
1704
1730
  if (locator.web && this.isWeb) {
1705
- return parseLocator.call(this, locator.web);
1731
+ return parseLocator.call(this, locator.web)
1706
1732
  }
1707
1733
 
1708
1734
  if (locator.android && this.platform === 'android') {
1709
1735
  if (typeof locator.android === 'string') {
1710
- return parseLocator.call(this, locator.android);
1736
+ return parseLocator.call(this, locator.android)
1711
1737
  }
1712
1738
  // The locator is an Android DataMatcher or ViewMatcher locator so return as is
1713
- return locator.android;
1739
+ return locator.android
1714
1740
  }
1715
1741
 
1716
1742
  if (locator.ios && this.platform === 'ios') {
1717
- return parseLocator.call(this, locator.ios);
1743
+ return parseLocator.call(this, locator.ios)
1718
1744
  }
1719
1745
  }
1720
1746
 
1721
1747
  if (typeof locator === 'string') {
1722
- if (locator[0] === '~') return locator;
1723
- if (locator.substr(0, 2) === '//') return locator;
1748
+ if (locator[0] === '~') return locator
1749
+ if (locator.substr(0, 2) === '//') return locator
1724
1750
  if (locator[0] === '#' && !this.isWeb) {
1725
1751
  // hook before webdriverio supports native # locators
1726
- return parseLocator.call(this, { id: locator.slice(1) });
1752
+ return parseLocator.call(this, { id: locator.slice(1) })
1727
1753
  }
1728
1754
 
1729
1755
  if (this.platform === 'android' && !this.isWeb) {
1730
- const isNativeLocator = /^\-?android=?/.exec(locator);
1731
- return isNativeLocator
1732
- ? locator
1733
- : `android=new UiSelector().text("${locator}")`;
1756
+ const isNativeLocator = /^\-?android=?/.exec(locator)
1757
+ return isNativeLocator ? locator : `android=new UiSelector().text("${locator}")`
1734
1758
  }
1735
1759
  }
1736
1760
 
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();
1761
+ locator = new Locator(locator, 'xpath')
1762
+ if (locator.type === 'css' && !this.isWeb)
1763
+ throw new Error(
1764
+ 'Unable to use css locators in apps. Locator strategies for this request: xpath, id, class name or accessibility id',
1765
+ )
1766
+ if (locator.type === 'name' && !this.isWeb)
1767
+ throw new Error("Can't locate element by name in Native context. Use either ID, class name or accessibility id")
1768
+ if (locator.type === 'id' && !this.isWeb && this.platform === 'android') return `//*[@resource-id='${locator.value}']`
1769
+ return locator.simplify()
1742
1770
  }
1743
1771
 
1744
1772
  // in the end of a file
1745
1773
  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);
1774
+ const stack = new Error().stack || ''
1775
+ const re = /Appium.(\w+)/g
1776
+ const caller = stack.split('\n')[2].trim()
1777
+ const m = re.exec(caller)
1750
1778
 
1751
1779
  if (!m) {
1752
- throw new Error(`Invalid caller ${caller}`);
1780
+ throw new Error(`Invalid caller ${caller}`)
1753
1781
  }
1754
1782
 
1755
- const callerName = m[1] || m[2];
1783
+ const callerName = m[1] || m[2]
1756
1784
  if (!expectedPlatform) {
1757
1785
  if (!this.platform) {
1758
- throw new Error(`${callerName} method can be used only with apps`);
1786
+ throw new Error(`${callerName} method can be used only with apps`)
1759
1787
  }
1760
1788
  } else if (this.platform !== expectedPlatform.toLowerCase()) {
1761
- throw new Error(`${callerName} method can be used only with ${expectedPlatform} apps`);
1789
+ throw new Error(`${callerName} method can be used only with ${expectedPlatform} apps`)
1762
1790
  }
1763
1791
  }
1764
1792
 
1765
- export default Appium;
1793
+ module.exports = Appium