codeceptjs 4.0.0-beta.4 → 4.0.0-beta.6.esm-aria

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 (188) hide show
  1. package/README.md +89 -119
  2. package/bin/codecept.js +53 -54
  3. package/docs/webapi/clearCookie.mustache +1 -1
  4. package/lib/actor.js +70 -102
  5. package/lib/ai.js +131 -121
  6. package/lib/assert/empty.js +11 -12
  7. package/lib/assert/equal.js +16 -21
  8. package/lib/assert/error.js +2 -2
  9. package/lib/assert/include.js +11 -15
  10. package/lib/assert/throws.js +3 -5
  11. package/lib/assert/truth.js +10 -7
  12. package/lib/assert.js +18 -18
  13. package/lib/codecept.js +112 -101
  14. package/lib/colorUtils.js +48 -50
  15. package/lib/command/check.js +206 -0
  16. package/lib/command/configMigrate.js +13 -14
  17. package/lib/command/definitions.js +24 -36
  18. package/lib/command/dryRun.js +16 -16
  19. package/lib/command/generate.js +38 -39
  20. package/lib/command/gherkin/init.js +36 -38
  21. package/lib/command/gherkin/snippets.js +76 -74
  22. package/lib/command/gherkin/steps.js +21 -18
  23. package/lib/command/info.js +49 -15
  24. package/lib/command/init.js +41 -37
  25. package/lib/command/interactive.js +22 -13
  26. package/lib/command/list.js +11 -10
  27. package/lib/command/run-multiple/chunk.js +50 -47
  28. package/lib/command/run-multiple/collection.js +5 -5
  29. package/lib/command/run-multiple/run.js +3 -3
  30. package/lib/command/run-multiple.js +27 -47
  31. package/lib/command/run-rerun.js +6 -7
  32. package/lib/command/run-workers.js +15 -66
  33. package/lib/command/run.js +8 -8
  34. package/lib/command/utils.js +22 -21
  35. package/lib/command/workers/runTests.js +131 -241
  36. package/lib/config.js +111 -49
  37. package/lib/container.js +589 -244
  38. package/lib/data/context.js +16 -18
  39. package/lib/data/dataScenarioConfig.js +9 -9
  40. package/lib/data/dataTableArgument.js +7 -7
  41. package/lib/data/table.js +6 -12
  42. package/lib/effects.js +307 -0
  43. package/lib/els.js +160 -0
  44. package/lib/event.js +24 -19
  45. package/lib/globals.js +141 -0
  46. package/lib/heal.js +89 -81
  47. package/lib/helper/AI.js +3 -2
  48. package/lib/helper/ApiDataFactory.js +19 -19
  49. package/lib/helper/Appium.js +47 -51
  50. package/lib/helper/FileSystem.js +35 -15
  51. package/lib/helper/GraphQL.js +1 -1
  52. package/lib/helper/GraphQLDataFactory.js +4 -4
  53. package/lib/helper/JSONResponse.js +72 -45
  54. package/lib/helper/Mochawesome.js +14 -11
  55. package/lib/helper/Playwright.js +832 -434
  56. package/lib/helper/Puppeteer.js +393 -292
  57. package/lib/helper/REST.js +32 -27
  58. package/lib/helper/WebDriver.js +320 -219
  59. package/lib/helper/errors/ConnectionRefused.js +6 -6
  60. package/lib/helper/errors/ElementAssertion.js +11 -16
  61. package/lib/helper/errors/ElementNotFound.js +5 -9
  62. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +5 -5
  63. package/lib/helper/extras/Console.js +11 -11
  64. package/lib/helper/extras/PlaywrightLocator.js +110 -0
  65. package/lib/helper/extras/PlaywrightPropEngine.js +18 -18
  66. package/lib/helper/extras/PlaywrightRestartOpts.js +23 -23
  67. package/lib/helper/extras/Popup.js +22 -22
  68. package/lib/helper/extras/React.js +29 -30
  69. package/lib/helper/network/actions.js +33 -48
  70. package/lib/helper/network/utils.js +76 -83
  71. package/lib/helper/scripts/blurElement.js +6 -6
  72. package/lib/helper/scripts/focusElement.js +6 -6
  73. package/lib/helper/scripts/highlightElement.js +9 -9
  74. package/lib/helper/scripts/isElementClickable.js +34 -34
  75. package/lib/helper.js +2 -1
  76. package/lib/history.js +23 -20
  77. package/lib/hooks.js +10 -10
  78. package/lib/html.js +90 -100
  79. package/lib/index.js +48 -21
  80. package/lib/listener/config.js +8 -9
  81. package/lib/listener/emptyRun.js +54 -0
  82. package/lib/listener/exit.js +10 -12
  83. package/lib/listener/{retry.js → globalRetry.js} +10 -10
  84. package/lib/listener/globalTimeout.js +166 -0
  85. package/lib/listener/helpers.js +43 -24
  86. package/lib/listener/mocha.js +4 -5
  87. package/lib/listener/result.js +11 -0
  88. package/lib/listener/steps.js +26 -23
  89. package/lib/listener/store.js +20 -0
  90. package/lib/locator.js +213 -192
  91. package/lib/mocha/asyncWrapper.js +264 -0
  92. package/lib/mocha/bdd.js +167 -0
  93. package/lib/mocha/cli.js +341 -0
  94. package/lib/mocha/factory.js +160 -0
  95. package/lib/{interfaces → mocha}/featureConfig.js +33 -13
  96. package/lib/{interfaces → mocha}/gherkin.js +75 -45
  97. package/lib/mocha/hooks.js +121 -0
  98. package/lib/mocha/index.js +21 -0
  99. package/lib/mocha/inject.js +46 -0
  100. package/lib/{interfaces → mocha}/scenarioConfig.js +32 -8
  101. package/lib/mocha/suite.js +89 -0
  102. package/lib/mocha/test.js +178 -0
  103. package/lib/mocha/types.d.ts +42 -0
  104. package/lib/mocha/ui.js +229 -0
  105. package/lib/output.js +86 -64
  106. package/lib/parser.js +44 -44
  107. package/lib/pause.js +160 -139
  108. package/lib/plugin/analyze.js +403 -0
  109. package/lib/plugin/{autoLogin.js → auth.js} +137 -43
  110. package/lib/plugin/autoDelay.js +19 -15
  111. package/lib/plugin/coverage.js +22 -27
  112. package/lib/plugin/customLocator.js +5 -5
  113. package/lib/plugin/customReporter.js +53 -0
  114. package/lib/plugin/heal.js +49 -17
  115. package/lib/plugin/pageInfo.js +140 -0
  116. package/lib/plugin/pauseOnFail.js +4 -3
  117. package/lib/plugin/retryFailedStep.js +60 -19
  118. package/lib/plugin/screenshotOnFail.js +80 -83
  119. package/lib/plugin/stepByStepReport.js +70 -31
  120. package/lib/plugin/stepTimeout.js +7 -13
  121. package/lib/plugin/subtitles.js +10 -9
  122. package/lib/recorder.js +167 -126
  123. package/lib/rerun.js +94 -50
  124. package/lib/result.js +161 -0
  125. package/lib/secret.js +18 -17
  126. package/lib/session.js +95 -89
  127. package/lib/step/base.js +239 -0
  128. package/lib/step/comment.js +10 -0
  129. package/lib/step/config.js +50 -0
  130. package/lib/step/func.js +46 -0
  131. package/lib/step/helper.js +50 -0
  132. package/lib/step/meta.js +99 -0
  133. package/lib/step/record.js +74 -0
  134. package/lib/step/retry.js +11 -0
  135. package/lib/step/section.js +55 -0
  136. package/lib/step.js +18 -332
  137. package/lib/steps.js +54 -0
  138. package/lib/store.js +37 -5
  139. package/lib/template/heal.js +2 -11
  140. package/lib/timeout.js +60 -0
  141. package/lib/transform.js +8 -8
  142. package/lib/translation.js +32 -18
  143. package/lib/utils.js +354 -250
  144. package/lib/workerStorage.js +16 -16
  145. package/lib/workers.js +366 -282
  146. package/package.json +107 -95
  147. package/translations/de-DE.js +5 -4
  148. package/translations/fr-FR.js +5 -4
  149. package/translations/index.js +23 -9
  150. package/translations/it-IT.js +5 -4
  151. package/translations/ja-JP.js +5 -4
  152. package/translations/nl-NL.js +76 -0
  153. package/translations/pl-PL.js +5 -4
  154. package/translations/pt-BR.js +5 -4
  155. package/translations/ru-RU.js +5 -4
  156. package/translations/utils.js +18 -0
  157. package/translations/zh-CN.js +5 -4
  158. package/translations/zh-TW.js +5 -4
  159. package/typings/index.d.ts +177 -186
  160. package/typings/promiseBasedTypes.d.ts +3573 -5941
  161. package/typings/types.d.ts +4042 -6370
  162. package/lib/cli.js +0 -256
  163. package/lib/helper/ExpectHelper.js +0 -391
  164. package/lib/helper/Nightmare.js +0 -1504
  165. package/lib/helper/Protractor.js +0 -1863
  166. package/lib/helper/SoftExpectHelper.js +0 -381
  167. package/lib/helper/TestCafe.js +0 -1414
  168. package/lib/helper/clientscripts/nightmare.js +0 -213
  169. package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -43
  170. package/lib/helper/testcafe/testControllerHolder.js +0 -42
  171. package/lib/helper/testcafe/testcafe-utils.js +0 -62
  172. package/lib/interfaces/bdd.js +0 -81
  173. package/lib/listener/artifacts.js +0 -19
  174. package/lib/listener/timeout.js +0 -109
  175. package/lib/mochaFactory.js +0 -113
  176. package/lib/plugin/allure.js +0 -15
  177. package/lib/plugin/commentStep.js +0 -136
  178. package/lib/plugin/debugErrors.js +0 -67
  179. package/lib/plugin/eachElement.js +0 -127
  180. package/lib/plugin/fakerTransform.js +0 -49
  181. package/lib/plugin/retryTo.js +0 -127
  182. package/lib/plugin/selenoid.js +0 -384
  183. package/lib/plugin/standardActingHelpers.js +0 -3
  184. package/lib/plugin/tryTo.js +0 -115
  185. package/lib/plugin/wdio.js +0 -249
  186. package/lib/scenario.js +0 -224
  187. package/lib/ui.js +0 -236
  188. package/lib/within.js +0 -70
@@ -1,7 +1,6 @@
1
- const path = require('path')
2
-
3
- const Helper = require('@codeceptjs/helper')
4
- const REST = require('./REST')
1
+ import path from 'path'
2
+ import Helper from '@codeceptjs/helper'
3
+ import REST from './REST.js'
5
4
 
6
5
  /**
7
6
  * Helper for managing remote data using REST API.
@@ -217,15 +216,16 @@ class ApiDataFactory extends Helper {
217
216
  }
218
217
 
219
218
  this.created = {}
220
- Object.keys(this.factories).forEach((f) => (this.created[f] = []))
219
+ Object.keys(this.factories).forEach(f => (this.created[f] = []))
221
220
  }
222
221
 
223
222
  static _checkRequirements() {
224
223
  try {
225
- require('axios')
226
- require('rosie')
224
+ // In ESM, dependencies are already imported at the top
225
+ // The import will fail at module load time if dependencies are missing
226
+ return null
227
227
  } catch (e) {
228
- return ['axios', 'rosie']
228
+ return ['axios']
229
229
  }
230
230
  }
231
231
 
@@ -265,8 +265,8 @@ class ApiDataFactory extends Helper {
265
265
  * @param {*} [options] options for programmatically generate the attributes
266
266
  * @returns {Promise<*>}
267
267
  */
268
- have(factory, params, options) {
269
- const item = this._createItem(factory, params, options)
268
+ async have(factory, params, options) {
269
+ const item = await this._createItem(factory, params, options)
270
270
  this.debug(`Creating ${factory} ${JSON.stringify(item)}`)
271
271
  return this._requestCreate(factory, item)
272
272
  }
@@ -298,19 +298,22 @@ class ApiDataFactory extends Helper {
298
298
  return Promise.all(promises)
299
299
  }
300
300
 
301
- _createItem(model, data, options) {
301
+ async _createItem(model, data, options) {
302
302
  if (!this.factories[model]) {
303
303
  throw new Error(`Factory ${model} is not defined in config`)
304
304
  }
305
305
  let modulePath = this.factories[model].factory
306
306
  try {
307
307
  try {
308
- require.resolve(modulePath)
308
+ // Try to resolve the path as-is first
309
+ await import.meta.resolve(modulePath)
309
310
  } catch (e) {
311
+ // If not found, try relative to codecept_dir
310
312
  modulePath = path.join(global.codecept_dir, modulePath)
311
313
  }
312
314
  // check if the new syntax `export default new Factory()` is used and loads the builder, otherwise loads the module that used old syntax `module.exports = new Factory()`.
313
- const builder = require(modulePath).default || require(modulePath)
315
+ const module = await import(modulePath)
316
+ const builder = module.default || module
314
317
  return builder.build(data, options)
315
318
  } catch (err) {
316
319
  throw new Error(`Couldn't load factory file from ${modulePath}, check that
@@ -357,7 +360,7 @@ Current file error: ${err.message}`)
357
360
 
358
361
  request.baseURL = this.config.endpoint
359
362
 
360
- return this.restHelper._executeRequest(request).then((resp) => {
363
+ return this.restHelper._executeRequest(request).then(resp => {
361
364
  const id = this._fetchId(resp.data, factory)
362
365
  this.created[factory].push(id)
363
366
  this.debugSection('Created', `Id: ${id}`)
@@ -391,10 +394,7 @@ Current file error: ${err.message}`)
391
394
  request.baseURL = this.config.endpoint
392
395
 
393
396
  if (request.url.match(/^undefined/)) {
394
- return this.debugSection(
395
- 'Please configure the delete request in your ApiDataFactory helper',
396
- "delete: () => ({ method: 'DELETE', url: '/api/users' })",
397
- )
397
+ return this.debugSection('Please configure the delete request in your ApiDataFactory helper', "delete: () => ({ method: 'DELETE', url: '/api/users' })")
398
398
  }
399
399
 
400
400
  return this.restHelper._executeRequest(request).then(() => {
@@ -405,7 +405,7 @@ Current file error: ${err.message}`)
405
405
  }
406
406
  }
407
407
 
408
- module.exports = ApiDataFactory
408
+ export { ApiDataFactory as default }
409
409
 
410
410
  function createRequestFromFunction(param, data) {
411
411
  if (typeof param !== 'function') return
@@ -44,7 +44,7 @@ const vendorPrefix = {
44
44
  *
45
45
  * This helper should be configured in codecept.conf.ts or codecept.conf.js
46
46
  *
47
- * * `appiumV2`: set this to true if you want to run tests with AppiumV2. See more how to setup [here](https://codecept.io/mobile/#setting-up)
47
+ * * `appiumV2`: by default is true, set this to false if you want to run tests with AppiumV1. See more how to setup [here](https://codecept.io/mobile/#setting-up)
48
48
  * * `app`: Application path. Local path or remote URL to an .ipa or .apk file, or a .zip containing one of these. Alias to desiredCapabilities.appPackage
49
49
  * * `host`: (default: 'localhost') Appium host
50
50
  * * `port`: (default: '4723') Appium port
@@ -124,7 +124,7 @@ const vendorPrefix = {
124
124
  * {
125
125
  * helpers: {
126
126
  * Appium: {
127
- * appiumV2: true,
127
+ * appiumV2: true, // By default is true, set to false if you want to run against Appium v1
128
128
  * host: "hub-cloud.browserstack.com",
129
129
  * port: 4444,
130
130
  * user: process.env.BROWSERSTACK_USER,
@@ -178,16 +178,12 @@ class Appium extends Webdriver {
178
178
  super(config)
179
179
 
180
180
  this.isRunning = false
181
- if (config.appiumV2 === true) {
182
- this.appiumV2 = true
183
- }
181
+ this.appiumV2 = config.appiumV2 || true
184
182
  this.axios = axios.create()
185
183
 
186
184
  webdriverio = require('webdriverio')
187
185
  if (!config.appiumV2) {
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
- )
186
+ console.log('The Appium core team does not maintain Appium 1.x anymore since the 1st of January 2022. Appium 2.x is used by default.')
191
187
  console.log('More info: https://bit.ly/appium-v2-migration')
192
188
  console.log('This Appium 1.x support will be removed in next major release.')
193
189
  }
@@ -234,20 +230,14 @@ class Appium extends Webdriver {
234
230
 
235
231
  config.baseUrl = config.url || config.baseUrl
236
232
  if (config.desiredCapabilities && Object.keys(config.desiredCapabilities).length) {
237
- config.capabilities =
238
- this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities
233
+ config.capabilities = this.appiumV2 === true ? this._convertAppiumV2Caps(config.desiredCapabilities) : config.desiredCapabilities
239
234
  }
240
235
 
241
236
  if (this.appiumV2) {
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
237
+ config.capabilities[`${vendorPrefix.appium}:deviceName`] = config[`${vendorPrefix.appium}:device`] || config.capabilities[`${vendorPrefix.appium}:deviceName`]
238
+ config.capabilities[`${vendorPrefix.appium}:browserName`] = config[`${vendorPrefix.appium}:browser`] || config.capabilities[`${vendorPrefix.appium}:browserName`]
239
+ config.capabilities[`${vendorPrefix.appium}:app`] = config[`${vendorPrefix.appium}:app`] || config.capabilities[`${vendorPrefix.appium}:app`]
240
+ 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
251
241
  } else {
252
242
  config.capabilities.deviceName = config.device || config.capabilities.deviceName
253
243
  config.capabilities.browserName = config.browser || config.capabilities.browserName
@@ -393,8 +383,10 @@ class Appium extends Webdriver {
393
383
 
394
384
  _buildAppiumEndpoint() {
395
385
  const { protocol, port, hostname, path } = this.browser.options
386
+ // Ensure path does NOT end with a slash to prevent double slashes
387
+ const normalizedPath = path.replace(/\/$/, '')
396
388
  // Build path to Appium REST API endpoint
397
- return `${protocol}://${hostname}:${port}${path}`
389
+ return `${protocol}://${hostname}:${port}${normalizedPath}/session/${this.browser.sessionId}`
398
390
  }
399
391
 
400
392
  /**
@@ -610,7 +602,7 @@ class Appium extends Webdriver {
610
602
 
611
603
  return this.axios({
612
604
  method: 'post',
613
- url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/device/remove_app`,
605
+ url: `${this._buildAppiumEndpoint()}/appium/device/remove_app`,
614
606
  data: { appId, bundleId },
615
607
  })
616
608
  }
@@ -627,7 +619,7 @@ class Appium extends Webdriver {
627
619
  onlyForApps.call(this)
628
620
  return this.axios({
629
621
  method: 'post',
630
- url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/app/reset`,
622
+ url: `${this._buildAppiumEndpoint()}/appium/app/reset`,
631
623
  })
632
624
  }
633
625
 
@@ -701,7 +693,7 @@ class Appium extends Webdriver {
701
693
 
702
694
  const res = await this.axios({
703
695
  method: 'get',
704
- url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
696
+ url: `${this._buildAppiumEndpoint()}/orientation`,
705
697
  })
706
698
 
707
699
  const currentOrientation = res.data.value
@@ -725,7 +717,7 @@ class Appium extends Webdriver {
725
717
 
726
718
  return this.axios({
727
719
  method: 'post',
728
- url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
720
+ url: `${this._buildAppiumEndpoint()}/orientation`,
729
721
  data: { orientation },
730
722
  })
731
723
  }
@@ -964,21 +956,19 @@ class Appium extends Webdriver {
964
956
  * ```js
965
957
  * // taps outside to hide keyboard per default
966
958
  * I.hideDeviceKeyboard();
967
- * I.hideDeviceKeyboard('tapOutside');
968
- *
969
- * // or by pressing key
970
- * I.hideDeviceKeyboard('pressKey', 'Done');
971
959
  * ```
972
960
  *
973
961
  * Appium: support Android and iOS
974
962
  *
975
- * @param {'tapOutside' | 'pressKey'} [strategy] Desired strategy to close keyboard (‘tapOutside’ or ‘pressKey’)
976
- * @param {string} [key] Optional key
977
963
  */
978
- async hideDeviceKeyboard(strategy, key) {
964
+ async hideDeviceKeyboard() {
979
965
  onlyForApps.call(this)
980
- strategy = strategy || 'tapOutside'
981
- return this.browser.hideKeyboard(strategy, key)
966
+
967
+ return this.axios({
968
+ method: 'post',
969
+ url: `${this._buildAppiumEndpoint()}/appium/device/hide_keyboard`,
970
+ data: {},
971
+ })
982
972
  }
983
973
 
984
974
  /**
@@ -1054,7 +1044,13 @@ class Appium extends Webdriver {
1054
1044
  * @param {*} locator
1055
1045
  */
1056
1046
  async tap(locator) {
1057
- return this.makeTouchAction(locator, 'tap')
1047
+ const { elementId } = await this.browser.$(parseLocator.call(this, locator))
1048
+
1049
+ return this.axios({
1050
+ method: 'post',
1051
+ url: `${this._buildAppiumEndpoint()}/element/${elementId}/click`,
1052
+ data: {},
1053
+ })
1058
1054
  }
1059
1055
 
1060
1056
  /**
@@ -1304,14 +1300,14 @@ class Appium extends Webdriver {
1304
1300
  }
1305
1301
  return browser
1306
1302
  .$$(parseLocator.call(this, searchableLocator))
1307
- .then((els) => els.length && els[0].isDisplayed())
1308
- .then((res) => {
1303
+ .then(els => els.length && els[0].isDisplayed())
1304
+ .then(res => {
1309
1305
  if (res) {
1310
1306
  return true
1311
1307
  }
1312
1308
  return this[direction](scrollLocator, offset, speed)
1313
1309
  .getSource()
1314
- .then((source) => {
1310
+ .then(source => {
1315
1311
  if (source === currentSource) {
1316
1312
  err = true
1317
1313
  } else {
@@ -1324,12 +1320,9 @@ class Appium extends Webdriver {
1324
1320
  timeout * 1000,
1325
1321
  errorMsg,
1326
1322
  )
1327
- .catch((e) => {
1323
+ .catch(e => {
1328
1324
  if (e.message.indexOf('timeout') && e.type !== 'NoSuchElement') {
1329
- throw new AssertionFailedError(
1330
- { customMessage: `Scroll to the end and element ${searchableLocator} was not found` },
1331
- '',
1332
- )
1325
+ throw new AssertionFailedError({ customMessage: `Scroll to the end and element ${searchableLocator} was not found` }, '')
1333
1326
  } else {
1334
1327
  throw e
1335
1328
  }
@@ -1386,8 +1379,8 @@ class Appium extends Webdriver {
1386
1379
  */
1387
1380
  async pullFile(path, dest) {
1388
1381
  onlyForApps.call(this)
1389
- return this.browser.pullFile(path).then((res) =>
1390
- fs.writeFile(dest, Buffer.from(res, 'base64'), (err) => {
1382
+ return this.browser.pullFile(path).then(res =>
1383
+ fs.writeFile(dest, Buffer.from(res, 'base64'), err => {
1391
1384
  if (err) {
1392
1385
  return false
1393
1386
  }
@@ -1504,7 +1497,14 @@ class Appium extends Webdriver {
1504
1497
  */
1505
1498
  async click(locator, context) {
1506
1499
  if (this.isWeb) return super.click(locator, context)
1507
- return super.click(parseLocator.call(this, locator), parseLocator.call(this, context))
1500
+
1501
+ const { elementId } = await this.browser.$(parseLocator.call(this, locator), parseLocator.call(this, context))
1502
+
1503
+ return this.axios({
1504
+ method: 'post',
1505
+ url: `${this._buildAppiumEndpoint()}/element/${elementId}/click`,
1506
+ data: {},
1507
+ })
1508
1508
  }
1509
1509
 
1510
1510
  /**
@@ -1759,12 +1759,8 @@ function parseLocator(locator) {
1759
1759
  }
1760
1760
 
1761
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")
1762
+ 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')
1763
+ 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")
1768
1764
  if (locator.type === 'id' && !this.isWeb && this.platform === 'android') return `//*[@resource-id='${locator.value}']`
1769
1765
  return locator.simplify()
1770
1766
  }
@@ -1,11 +1,11 @@
1
- const assert = require('assert')
2
- const path = require('path')
3
- const fs = require('fs')
1
+ import assert from 'assert'
2
+ import path from 'path'
3
+ import fs from 'fs'
4
4
 
5
- const Helper = require('@codeceptjs/helper')
6
- const { fileExists } = require('../utils')
7
- const { fileIncludes } = require('../assert/include')
8
- const { fileEquals } = require('../assert/equal')
5
+ import Helper from '@codeceptjs/helper'
6
+ import { fileExists } from '../utils.js'
7
+ import { fileIncludes } from '../assert/include.js'
8
+ import { fileEquals } from '../assert/equal.js'
9
9
 
10
10
  /**
11
11
  * Helper for testing filesystem.
@@ -38,7 +38,12 @@ class FileSystem extends Helper {
38
38
  }
39
39
 
40
40
  _before() {
41
- this.debugSection('Dir', this.dir)
41
+ try {
42
+ this.debugSection('Dir', this.dir)
43
+ } catch (e) {
44
+ // Fallback debug for ESM transition
45
+ console.log(`[Dir] ${this.dir}`)
46
+ }
42
47
  }
43
48
 
44
49
  /**
@@ -48,7 +53,12 @@ class FileSystem extends Helper {
48
53
  */
49
54
  amInPath(openPath) {
50
55
  this.dir = path.join(global.codecept_dir, openPath)
51
- this.debugSection('Dir', this.dir)
56
+ try {
57
+ this.debugSection('Dir', this.dir)
58
+ } catch (e) {
59
+ // Fallback debug for ESM transition
60
+ console.log(`[Dir] ${this.dir}`)
61
+ }
52
62
  }
53
63
 
54
64
  /**
@@ -66,7 +76,12 @@ class FileSystem extends Helper {
66
76
  */
67
77
  seeFile(name) {
68
78
  this.file = path.join(this.dir, name)
69
- this.debugSection('File', this.file)
79
+ try {
80
+ this.debugSection('File', this.file)
81
+ } catch (e) {
82
+ // Fallback debug for ESM transition
83
+ console.log(`[File] ${this.file}`)
84
+ }
70
85
  assert.ok(fileExists(this.file), `File ${name} not found in ${this.dir}`)
71
86
  }
72
87
 
@@ -86,7 +101,12 @@ class FileSystem extends Helper {
86
101
  if (sec === 0) assert.fail('Use `seeFile` instead of waiting 0 seconds!')
87
102
  const waitTimeout = sec * 1000
88
103
  this.file = path.join(this.dir, name)
89
- this.debugSection('File', this.file)
104
+ try {
105
+ this.debugSection('File', this.file)
106
+ } catch (e) {
107
+ // Fallback debug for ESM transition
108
+ console.log(`[File] ${this.file}`)
109
+ }
90
110
  return isFileExists(this.file, waitTimeout).catch(() => {
91
111
  throw new Error(`file (${name}) still not present in directory ${this.dir} after ${waitTimeout / 1000} sec`)
92
112
  })
@@ -105,7 +125,7 @@ class FileSystem extends Helper {
105
125
  */
106
126
  seeFileNameMatching(text) {
107
127
  assert.ok(
108
- this.grabFileNames().some((file) => file.includes(text)),
128
+ this.grabFileNames().some(file => file.includes(text)),
109
129
  `File name which contains ${text} not found in ${this.dir}`,
110
130
  )
111
131
  }
@@ -175,11 +195,11 @@ class FileSystem extends Helper {
175
195
  * ```
176
196
  */
177
197
  grabFileNames() {
178
- return fs.readdirSync(this.dir).filter((item) => !fs.lstatSync(path.join(this.dir, item)).isDirectory())
198
+ return fs.readdirSync(this.dir).filter(item => !fs.lstatSync(path.join(this.dir, item)).isDirectory())
179
199
  }
180
200
  }
181
201
 
182
- module.exports = FileSystem
202
+ export { FileSystem as default }
183
203
 
184
204
  /**
185
205
  * @param {string} file
@@ -216,7 +236,7 @@ function isFileExists(file, timeout) {
216
236
  }
217
237
  })
218
238
 
219
- fs.access(file, fs.constants.R_OK, (err) => {
239
+ fs.access(file, fs.constants.R_OK, err => {
220
240
  if (!err) {
221
241
  clearTimeout(timer)
222
242
  watcher.close()
@@ -1,5 +1,5 @@
1
1
  const axios = require('axios').default
2
- const Helper = require('@codeceptjs/helper')
2
+ const HelperModule = require('@codeceptjs/helper')
3
3
 
4
4
  /**
5
5
  * GraphQL helper allows to send additional requests to a GraphQl endpoint during acceptance tests.
@@ -1,6 +1,6 @@
1
1
  const path = require('path')
2
2
 
3
- const Helper = require('@codeceptjs/helper')
3
+ const HelperModule = require('@codeceptjs/helper')
4
4
  const GraphQL = require('./GraphQL')
5
5
 
6
6
  /**
@@ -170,7 +170,7 @@ class GraphQLDataFactory extends Helper {
170
170
  this.factories = this.config.factories
171
171
 
172
172
  this.created = {}
173
- Object.keys(this.factories).forEach((f) => (this.created[f] = []))
173
+ Object.keys(this.factories).forEach(f => (this.created[f] = []))
174
174
  }
175
175
 
176
176
  static _checkRequirements() {
@@ -278,7 +278,7 @@ class GraphQLDataFactory extends Helper {
278
278
  */
279
279
  _requestCreate(operation, variables) {
280
280
  const { query } = this.factories[operation]
281
- return this.graphqlHelper.sendMutation(query, variables).then((response) => {
281
+ return this.graphqlHelper.sendMutation(query, variables).then(response => {
282
282
  const data = response.data.data[operation]
283
283
  this.created[operation].push(data)
284
284
  this.debugSection('Created', `record: ${data}`)
@@ -297,7 +297,7 @@ class GraphQLDataFactory extends Helper {
297
297
  const deleteOperation = this.factories[operation].revert(data)
298
298
  const { query, variables } = deleteOperation
299
299
 
300
- return this.graphqlHelper.sendMutation(query, variables).then((response) => {
300
+ return this.graphqlHelper.sendMutation(query, variables).then(response => {
301
301
  const idx = this.created[operation].indexOf(data)
302
302
  this.debugSection('Deleted', `record: ${response.data.data}`)
303
303
  this.created[operation].splice(idx, 1)