codeceptjs 3.6.7 → 4.0.0-beta.1

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 (149) hide show
  1. package/bin/codecept.js +81 -84
  2. package/lib/actor.js +13 -13
  3. package/lib/ai.js +13 -10
  4. package/lib/assert/empty.js +21 -20
  5. package/lib/assert/equal.js +39 -37
  6. package/lib/assert/error.js +14 -14
  7. package/lib/assert/include.js +47 -46
  8. package/lib/assert/throws.js +11 -13
  9. package/lib/assert/truth.js +22 -19
  10. package/lib/assert.js +2 -4
  11. package/lib/cli.js +49 -57
  12. package/lib/codecept.js +155 -142
  13. package/lib/colorUtils.js +3 -3
  14. package/lib/command/configMigrate.js +52 -58
  15. package/lib/command/definitions.js +89 -88
  16. package/lib/command/dryRun.js +68 -71
  17. package/lib/command/generate.js +188 -197
  18. package/lib/command/gherkin/init.js +16 -27
  19. package/lib/command/gherkin/snippets.js +20 -20
  20. package/lib/command/gherkin/steps.js +8 -8
  21. package/lib/command/info.js +38 -40
  22. package/lib/command/init.js +288 -290
  23. package/lib/command/interactive.js +32 -32
  24. package/lib/command/list.js +26 -26
  25. package/lib/command/run-multiple/chunk.js +5 -5
  26. package/lib/command/run-multiple/collection.js +3 -3
  27. package/lib/command/run-multiple/run.js +2 -6
  28. package/lib/command/run-multiple.js +93 -113
  29. package/lib/command/run-rerun.js +25 -20
  30. package/lib/command/run-workers.js +66 -64
  31. package/lib/command/run.js +29 -26
  32. package/lib/command/utils.js +65 -80
  33. package/lib/command/workers/runTests.js +10 -10
  34. package/lib/config.js +9 -10
  35. package/lib/container.js +48 -40
  36. package/lib/data/context.js +59 -60
  37. package/lib/data/dataScenarioConfig.js +47 -47
  38. package/lib/data/dataTableArgument.js +29 -29
  39. package/lib/data/table.js +20 -26
  40. package/lib/dirname.js +5 -0
  41. package/lib/event.js +167 -163
  42. package/lib/heal.js +17 -13
  43. package/lib/helper/AI.js +41 -130
  44. package/lib/helper/ApiDataFactory.js +69 -73
  45. package/lib/helper/Appium.js +381 -412
  46. package/lib/helper/Expect.js +425 -0
  47. package/lib/helper/ExpectHelper.js +48 -40
  48. package/lib/helper/FileSystem.js +79 -80
  49. package/lib/helper/GraphQL.js +43 -44
  50. package/lib/helper/GraphQLDataFactory.js +50 -50
  51. package/lib/helper/JSONResponse.js +62 -65
  52. package/lib/helper/Mochawesome.js +28 -28
  53. package/lib/helper/MockServer.js +14 -12
  54. package/lib/helper/Nightmare.js +566 -662
  55. package/lib/helper/Playwright.js +1216 -1361
  56. package/lib/helper/Protractor.js +627 -663
  57. package/lib/helper/Puppeteer.js +1128 -1231
  58. package/lib/helper/REST.js +68 -159
  59. package/lib/helper/SoftExpectHelper.js +2 -2
  60. package/lib/helper/TestCafe.js +484 -490
  61. package/lib/helper/WebDriver.js +1156 -1297
  62. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  63. package/lib/helper/errors/ConnectionRefused.js +1 -1
  64. package/lib/helper/errors/ElementAssertion.js +2 -2
  65. package/lib/helper/errors/ElementNotFound.js +2 -2
  66. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  67. package/lib/helper/extras/Console.js +1 -1
  68. package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
  69. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  70. package/lib/helper/extras/PlaywrightRestartOpts.js +18 -21
  71. package/lib/helper/extras/Popup.js +1 -1
  72. package/lib/helper/extras/React.js +3 -3
  73. package/lib/helper/network/actions.js +7 -14
  74. package/lib/helper/network/utils.js +2 -3
  75. package/lib/helper/scripts/blurElement.js +1 -1
  76. package/lib/helper/scripts/focusElement.js +1 -1
  77. package/lib/helper/scripts/highlightElement.js +1 -1
  78. package/lib/helper/scripts/isElementClickable.js +1 -1
  79. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  80. package/lib/helper/testcafe/testcafe-utils.js +7 -6
  81. package/lib/helper.js +3 -1
  82. package/lib/history.js +5 -6
  83. package/lib/hooks.js +6 -6
  84. package/lib/html.js +7 -7
  85. package/lib/index.js +41 -25
  86. package/lib/interfaces/bdd.js +64 -47
  87. package/lib/interfaces/featureConfig.js +19 -19
  88. package/lib/interfaces/gherkin.js +118 -124
  89. package/lib/interfaces/scenarioConfig.js +29 -29
  90. package/lib/listener/artifacts.js +9 -9
  91. package/lib/listener/config.js +24 -24
  92. package/lib/listener/exit.js +12 -12
  93. package/lib/listener/helpers.js +42 -42
  94. package/lib/listener/mocha.js +11 -11
  95. package/lib/listener/retry.js +30 -32
  96. package/lib/listener/steps.js +53 -50
  97. package/lib/listener/timeout.js +54 -54
  98. package/lib/locator.js +10 -6
  99. package/lib/mochaFactory.js +15 -18
  100. package/lib/output.js +10 -6
  101. package/lib/parser.js +12 -15
  102. package/lib/pause.js +33 -40
  103. package/lib/plugin/allure.js +15 -15
  104. package/lib/plugin/autoDelay.js +37 -29
  105. package/lib/plugin/autoLogin.js +65 -70
  106. package/lib/plugin/commentStep.js +18 -18
  107. package/lib/plugin/coverage.js +67 -115
  108. package/lib/plugin/customLocator.js +20 -21
  109. package/lib/plugin/debugErrors.js +24 -24
  110. package/lib/plugin/eachElement.js +38 -38
  111. package/lib/plugin/fakerTransform.js +6 -6
  112. package/lib/plugin/heal.js +108 -67
  113. package/lib/plugin/pauseOnFail.js +11 -11
  114. package/lib/plugin/retryFailedStep.js +39 -32
  115. package/lib/plugin/retryTo.js +40 -46
  116. package/lib/plugin/screenshotOnFail.js +87 -109
  117. package/lib/plugin/selenoid.js +118 -131
  118. package/lib/plugin/standardActingHelpers.js +8 -2
  119. package/lib/plugin/stepByStepReport.js +91 -110
  120. package/lib/plugin/stepTimeout.js +23 -24
  121. package/lib/plugin/subtitles.js +35 -34
  122. package/lib/plugin/tryTo.js +30 -40
  123. package/lib/plugin/wdio.js +75 -78
  124. package/lib/recorder.js +17 -14
  125. package/lib/rerun.js +10 -11
  126. package/lib/scenario.js +23 -25
  127. package/lib/secret.js +2 -4
  128. package/lib/session.js +10 -10
  129. package/lib/step.js +9 -12
  130. package/lib/store.js +3 -2
  131. package/lib/transform.js +1 -1
  132. package/lib/translation.js +8 -7
  133. package/lib/ui.js +14 -12
  134. package/lib/utils.js +72 -70
  135. package/lib/within.js +10 -10
  136. package/lib/workerStorage.js +25 -27
  137. package/lib/workers.js +32 -29
  138. package/package.json +53 -51
  139. package/translations/de-DE.js +1 -1
  140. package/translations/fr-FR.js +1 -1
  141. package/translations/index.js +13 -9
  142. package/translations/it-IT.js +1 -1
  143. package/translations/ja-JP.js +1 -1
  144. package/translations/pl-PL.js +1 -1
  145. package/translations/pt-BR.js +1 -1
  146. package/translations/ru-RU.js +1 -1
  147. package/translations/zh-CN.js +1 -1
  148. package/translations/zh-TW.js +1 -1
  149. package/typings/index.d.ts +65 -415
@@ -1,29 +1,27 @@
1
1
  // @ts-nocheck
2
- const fs = require('fs')
3
- const assert = require('assert')
4
- const path = require('path')
5
- const qrcode = require('qrcode-terminal')
6
- const createTestCafe = require('testcafe')
7
- const { Selector, ClientFunction } = require('testcafe')
8
-
9
- const Helper = require('@codeceptjs/helper')
10
- const ElementNotFound = require('./errors/ElementNotFound')
11
- const testControllerHolder = require('./testcafe/testControllerHolder')
12
- const { mapError, createTestFile, createClientFunction } = require('./testcafe/testcafe-utils')
13
-
14
- const stringIncludes = require('../assert/include').includes
15
- const { urlEquals } = require('../assert/equal')
16
- const { empty } = require('../assert/empty')
17
- const { truth } = require('../assert/truth')
18
- const { xpathLocator, normalizeSpacesInString } = require('../utils')
19
- const Locator = require('../locator')
2
+ import fs from 'fs';
3
+
4
+ import assert from 'assert';
5
+ import path from 'path';
6
+ import qrcode from 'qrcode-terminal';
7
+ import createTestCafe, { Selector, ClientFunction } from 'testcafe';
8
+ import Helper from '@codeceptjs/helper';
9
+ import ElementNotFound from './errors/ElementNotFound.js';
10
+ import testControllerHolder from './testcafe/testControllerHolder';
11
+ import { mapError, createTestFile, createClientFunction } from './testcafe/testcafe-utils';
12
+
13
+ import { includes as stringIncludes } from '../assert/include.js';
14
+ import { urlEquals } from '../assert/equal.js';
15
+ import { empty } from '../assert/empty.js';
16
+ import { truth } from '../assert/truth';
17
+ import { xpathLocator, normalizeSpacesInString } from '../utils.js';
18
+ import Locator from '../locator.js';
20
19
 
21
20
  /**
22
21
  * Client Functions
23
22
  */
24
- const getPageUrl = (t) => ClientFunction(() => document.location.href).with({ boundTestRun: t })
25
- const getHtmlSource = (t) =>
26
- ClientFunction(() => document.getElementsByTagName('html')[0].innerHTML).with({ boundTestRun: t })
23
+ const getPageUrl = t => ClientFunction(() => document.location.href).with({ boundTestRun: t });
24
+ const getHtmlSource = t => ClientFunction(() => document.getElementsByTagName('html')[0].innerHTML).with({ boundTestRun: t });
27
25
 
28
26
  /**
29
27
  * Uses [TestCafe](https://github.com/DevExpress/testcafe) library to run cross-browser tests.
@@ -94,16 +92,16 @@ const getHtmlSource = (t) =>
94
92
  */
95
93
  class TestCafe extends Helper {
96
94
  constructor(config) {
97
- super(config)
95
+ super(config);
98
96
 
99
- this.testcafe = undefined // testcafe instance
100
- this.t = undefined // testcafe test controller
101
- this.dummyTestcafeFile // generated testcafe test file
97
+ this.testcafe = undefined; // testcafe instance
98
+ this.t = undefined; // testcafe test controller
99
+ this.dummyTestcafeFile; // generated testcafe test file
102
100
 
103
101
  // context is used for within() function.
104
102
  // It requires to have _withinBeginand _withinEnd implemented.
105
103
  // Inside _withinBegin we should define that all next element calls should be started from a specific element (this.context).
106
- this.context = undefined // TODO Not sure if this applies to testcafe
104
+ this.context = undefined; // TODO Not sure if this applies to testcafe
107
105
 
108
106
  this.options = {
109
107
  url: 'http://localhost',
@@ -118,15 +116,15 @@ class TestCafe extends Helper {
118
116
  disableScreenshots: false,
119
117
  windowSize: undefined,
120
118
  ...config,
121
- }
119
+ };
122
120
  }
123
121
 
124
122
  // TOOD Do a requirements check
125
123
  static _checkRequirements() {
126
124
  try {
127
- require('testcafe')
125
+ require('testcafe');
128
126
  } catch (e) {
129
- return ['testcafe@^1.1.0']
127
+ return ['testcafe@^1.1.0'];
130
128
  }
131
129
  }
132
130
 
@@ -135,36 +133,33 @@ class TestCafe extends Helper {
135
133
  { name: 'url', message: 'Base url of site to be tested', default: 'http://localhost' },
136
134
  { name: 'browser', message: 'Browser to be used', default: 'chrome' },
137
135
  {
138
- name: 'show',
139
- message: 'Show browser window',
140
- default: true,
141
- type: 'confirm',
136
+ name: 'show', message: 'Show browser window', default: true, type: 'confirm',
142
137
  },
143
- ]
138
+ ];
144
139
  }
145
140
 
146
141
  async _configureAndStartBrowser() {
147
- this.dummyTestcafeFile = createTestFile(global.output_dir) // create a dummy test file to get hold of the test controller
142
+ this.dummyTestcafeFile = createTestFile(global.output_dir); // create a dummy test file to get hold of the test controller
148
143
 
149
- this.iteration += 2 // Use different ports for each test run
144
+ this.iteration += 2; // Use different ports for each test run
150
145
  // @ts-ignore
151
- this.testcafe = await createTestCafe('', null, null)
146
+ this.testcafe = await createTestCafe('', null, null);
152
147
 
153
- this.debugSection('_before', 'Starting testcafe browser...')
148
+ this.debugSection('_before', 'Starting testcafe browser...');
154
149
 
155
- this.isRunning = true
150
+ this.isRunning = true;
156
151
 
157
152
  // TODO Do we have to cleanup the runner?
158
- const runner = this.testcafe.createRunner()
153
+ const runner = this.testcafe.createRunner();
159
154
 
160
- this.options.browser !== 'remote' ? this._startBrowser(runner) : this._startRemoteBrowser(runner)
155
+ this.options.browser !== 'remote' ? this._startBrowser(runner) : this._startRemoteBrowser(runner);
161
156
 
162
- this.t = await testControllerHolder.get()
163
- assert(this.t, 'Expected to have the testcafe test controller')
157
+ this.t = await testControllerHolder.get();
158
+ assert(this.t, 'Expected to have the testcafe test controller');
164
159
 
165
160
  if (this.options.windowSize && this.options.windowSize.indexOf('x') > 0) {
166
- const dimensions = this.options.windowSize.split('x')
167
- await this.t.resizeWindow(parseInt(dimensions[0], 10), parseInt(dimensions[1], 10))
161
+ const dimensions = this.options.windowSize.split('x');
162
+ await this.t.resizeWindow(parseInt(dimensions[0], 10), parseInt(dimensions[1], 10));
168
163
  }
169
164
  }
170
165
 
@@ -188,16 +183,16 @@ class TestCafe extends Helper {
188
183
  takeScreenshotsOnFails: true,
189
184
  })
190
185
  .catch((err) => {
191
- this.debugSection('_before', `Error ${err.toString()}`)
192
- this.isRunning = false
193
- this.testcafe.close()
194
- })
186
+ this.debugSection('_before', `Error ${err.toString()}`);
187
+ this.isRunning = false;
188
+ this.testcafe.close();
189
+ });
195
190
  }
196
191
 
197
192
  async _startRemoteBrowser(runner) {
198
- const remoteConnection = await this.testcafe.createBrowserConnection()
199
- console.log('Connect your device to the following URL or scan QR Code: ', remoteConnection.url)
200
- qrcode.generate(remoteConnection.url)
193
+ const remoteConnection = await this.testcafe.createBrowserConnection();
194
+ console.log('Connect your device to the following URL or scan QR Code: ', remoteConnection.url);
195
+ qrcode.generate(remoteConnection.url);
201
196
  remoteConnection.once('ready', () => {
202
197
  runner
203
198
  .src(this.dummyTestcafeFile)
@@ -209,67 +204,70 @@ class TestCafe extends Helper {
209
204
  skipUncaughtErrors: true,
210
205
  })
211
206
  .catch((err) => {
212
- this.debugSection('_before', `Error ${err.toString()}`)
213
- this.isRunning = false
214
- this.testcafe.close()
215
- })
216
- })
207
+ this.debugSection('_before', `Error ${err.toString()}`);
208
+ this.isRunning = false;
209
+ this.testcafe.close();
210
+ });
211
+ });
217
212
  }
218
213
 
219
214
  async _stopBrowser() {
220
- this.debugSection('_after', 'Stopping testcafe browser...')
215
+ this.debugSection('_after', 'Stopping testcafe browser...');
221
216
 
222
- testControllerHolder.free()
217
+ testControllerHolder.free();
223
218
  if (this.testcafe) {
224
- this.testcafe.close()
219
+ this.testcafe.close();
225
220
  }
226
221
 
227
- fs.unlinkSync(this.dummyTestcafeFile) // remove the dummy test
228
- this.t = undefined
222
+ fs.unlinkSync(this.dummyTestcafeFile); // remove the dummy test
223
+ this.t = undefined;
229
224
 
230
- this.isRunning = false
225
+ this.isRunning = false;
231
226
  }
232
227
 
233
- _init() {}
228
+ _init() {
229
+ }
234
230
 
235
231
  async _beforeSuite() {
236
232
  if (!this.options.restart && !this.options.manualStart && !this.isRunning) {
237
- this.debugSection('Session', 'Starting singleton browser session')
238
- return this._configureAndStartBrowser()
233
+ this.debugSection('Session', 'Starting singleton browser session');
234
+ return this._configureAndStartBrowser();
239
235
  }
240
236
  }
241
237
 
242
238
  async _before() {
243
- if (this.options.restart && !this.options.manualStart) return this._configureAndStartBrowser()
244
- if (!this.isRunning && !this.options.manualStart) return this._configureAndStartBrowser()
245
- this.context = null
239
+ if (this.options.restart && !this.options.manualStart) return this._configureAndStartBrowser();
240
+ if (!this.isRunning && !this.options.manualStart) return this._configureAndStartBrowser();
241
+ this.context = null;
246
242
  }
247
243
 
248
244
  async _after() {
249
- if (!this.isRunning) return
245
+ if (!this.isRunning) return;
250
246
 
251
247
  if (this.options.restart) {
252
- this.isRunning = false
253
- return this._stopBrowser()
248
+ this.isRunning = false;
249
+ return this._stopBrowser();
254
250
  }
255
251
 
256
- if (this.options.keepBrowserState) return
252
+ if (this.options.keepBrowserState) return;
257
253
 
258
254
  if (!this.options.keepCookies) {
259
- this.debugSection('Session', 'cleaning cookies and localStorage')
260
- await this.clearCookie()
255
+ this.debugSection('Session', 'cleaning cookies and localStorage');
256
+ await this.clearCookie();
261
257
 
262
258
  // TODO IMHO that should only happen when
263
- await this.executeScript(() => localStorage.clear()).catch((err) => {
264
- if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
265
- })
259
+ await this.executeScript(() => localStorage.clear())
260
+ .catch((err) => {
261
+ if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err;
262
+ });
266
263
  }
267
264
  }
268
265
 
269
- _afterSuite() {}
266
+ _afterSuite() {
267
+ }
270
268
 
271
269
  async _finishTest() {
272
- if (!this.options.restart && this.isRunning) return this._stopBrowser()
270
+ if (!this.options.restart && this.isRunning) return this._stopBrowser();
273
271
  }
274
272
 
275
273
  /**
@@ -292,7 +290,7 @@ class TestCafe extends Helper {
292
290
  * @param {function} fn async functuion that executed with TestCafe helper as argument
293
291
  */
294
292
  useTestCafeTo(description, fn) {
295
- return this._useTo(...arguments)
293
+ return this._useTo(...arguments);
296
294
  }
297
295
 
298
296
  /**
@@ -305,28 +303,29 @@ class TestCafe extends Helper {
305
303
  *
306
304
  */
307
305
  async _locate(locator) {
308
- return findElements.call(this, this.context, locator).catch(mapError)
306
+ return findElements.call(this, this.context, locator).catch(mapError);
309
307
  }
310
308
 
311
309
  async _withinBegin(locator) {
312
- const els = await this._locate(locator)
313
- assertElementExists(els, locator)
314
- this.context = await els.nth(0)
310
+ const els = await this._locate(locator);
311
+ assertElementExists(els, locator);
312
+ this.context = await els.nth(0);
315
313
  }
316
314
 
317
315
  async _withinEnd() {
318
- this.context = null
316
+ this.context = null;
319
317
  }
320
318
 
321
319
  /**
322
320
  * {{> amOnPage }}
323
321
  */
324
322
  async amOnPage(url) {
325
- if (!/^\w+\:\/\//.test(url)) {
326
- url = this.options.url + url
323
+ if (!(/^\w+\:\/\//.test(url))) {
324
+ url = this.options.url + url;
327
325
  }
328
326
 
329
- return this.t.navigateTo(url).catch(mapError)
327
+ return this.t.navigateTo(url)
328
+ .catch(mapError);
330
329
  }
331
330
 
332
331
  /**
@@ -334,10 +333,10 @@ class TestCafe extends Helper {
334
333
  */
335
334
  async resizeWindow(width, height) {
336
335
  if (width === 'maximize') {
337
- return this.t.maximizeWindow().catch(mapError)
336
+ return this.t.maximizeWindow().catch(mapError);
338
337
  }
339
338
 
340
- return this.t.resizeWindow(width, height).catch(mapError)
339
+ return this.t.resizeWindow(width, height).catch(mapError);
341
340
  }
342
341
 
343
342
  /**
@@ -345,16 +344,13 @@ class TestCafe extends Helper {
345
344
  *
346
345
  */
347
346
  async focus(locator) {
348
- const els = await this._locate(locator)
349
- await assertElementExists(els, locator, 'Element to focus')
350
- const element = await els.nth(0)
347
+ const els = await this._locate(locator);
348
+ await assertElementExists(els, locator, 'Element to focus');
349
+ const element = await els.nth(0);
351
350
 
352
- const focusElement = ClientFunction(() => element().focus(), {
353
- boundTestRun: this.t,
354
- dependencies: { element },
355
- })
351
+ const focusElement = ClientFunction(() => element().focus(), { boundTestRun: this.t, dependencies: { element } });
356
352
 
357
- return focusElement()
353
+ return focusElement();
358
354
  }
359
355
 
360
356
  /**
@@ -362,13 +358,13 @@ class TestCafe extends Helper {
362
358
  *
363
359
  */
364
360
  async blur(locator) {
365
- const els = await this._locate(locator)
366
- await assertElementExists(els, locator, 'Element to blur')
367
- const element = await els.nth(0)
361
+ const els = await this._locate(locator);
362
+ await assertElementExists(els, locator, 'Element to blur');
363
+ const element = await els.nth(0);
368
364
 
369
- const blurElement = ClientFunction(() => element().blur(), { boundTestRun: this.t, dependencies: { element } })
365
+ const blurElement = ClientFunction(() => element().blur(), { boundTestRun: this.t, dependencies: { element } });
370
366
 
371
- return blurElement()
367
+ return blurElement();
372
368
  }
373
369
 
374
370
  /**
@@ -376,7 +372,7 @@ class TestCafe extends Helper {
376
372
  *
377
373
  */
378
374
  async click(locator, context = null) {
379
- return proceedClick.call(this, locator, context)
375
+ return proceedClick.call(this, locator, context);
380
376
  }
381
377
 
382
378
  /**
@@ -384,7 +380,7 @@ class TestCafe extends Helper {
384
380
  */
385
381
  async refreshPage() {
386
382
  // eslint-disable-next-line no-restricted-globals
387
- return this.t.eval(() => location.reload(true), { boundTestRun: this.t }).catch(mapError)
383
+ return this.t.eval(() => location.reload(true), { boundTestRun: this.t }).catch(mapError);
388
384
  }
389
385
 
390
386
  /**
@@ -392,33 +388,37 @@ class TestCafe extends Helper {
392
388
  *
393
389
  */
394
390
  async waitForVisible(locator, sec) {
395
- const timeout = sec ? sec * 1000 : undefined
391
+ const timeout = sec ? sec * 1000 : undefined;
396
392
 
397
393
  return (await findElements.call(this, this.context, locator))
398
394
  .with({ visibilityCheck: true, timeout })()
399
- .catch(mapError)
395
+ .catch(mapError);
400
396
  }
401
397
 
402
398
  /**
403
399
  * {{> fillField }}
404
400
  */
405
401
  async fillField(field, value) {
406
- const els = await findFields.call(this, field)
407
- assertElementExists(els, field, 'Field')
408
- const el = await els.nth(0)
409
- return this.t.typeText(el, value.toString(), { replace: true }).catch(mapError)
402
+ const els = await findFields.call(this, field);
403
+ assertElementExists(els, field, 'Field');
404
+ const el = await els.nth(0);
405
+ return this.t
406
+ .typeText(el, value.toString(), { replace: true })
407
+ .catch(mapError);
410
408
  }
411
409
 
412
410
  /**
413
411
  * {{> clearField }}
414
412
  */
415
413
  async clearField(field) {
416
- const els = await findFields.call(this, field)
417
- assertElementExists(els, field, 'Field')
418
- const el = await els.nth(0)
414
+ const els = await findFields.call(this, field);
415
+ assertElementExists(els, field, 'Field');
416
+ const el = await els.nth(0);
419
417
 
420
- const res = await this.t.selectText(el).pressKey('delete')
421
- return res
418
+ const res = await this.t
419
+ .selectText(el)
420
+ .pressKey('delete');
421
+ return res;
422
422
  }
423
423
 
424
424
  /**
@@ -426,11 +426,13 @@ class TestCafe extends Helper {
426
426
  *
427
427
  */
428
428
  async appendField(field, value) {
429
- const els = await findFields.call(this, field)
430
- assertElementExists(els, field, 'Field')
431
- const el = await els.nth(0)
429
+ const els = await findFields.call(this, field);
430
+ assertElementExists(els, field, 'Field');
431
+ const el = await els.nth(0);
432
432
 
433
- return this.t.typeText(el, value.toString(), { replace: false }).catch(mapError)
433
+ return this.t
434
+ .typeText(el, value.toString(), { replace: false })
435
+ .catch(mapError);
434
436
  }
435
437
 
436
438
  /**
@@ -438,12 +440,14 @@ class TestCafe extends Helper {
438
440
  *
439
441
  */
440
442
  async attachFile(field, pathToFile) {
441
- const els = await findFields.call(this, field)
442
- assertElementExists(els, field, 'Field')
443
- const el = await els.nth(0)
444
- const file = path.join(global.codecept_dir, pathToFile)
443
+ const els = await findFields.call(this, field);
444
+ assertElementExists(els, field, 'Field');
445
+ const el = await els.nth(0);
446
+ const file = path.join(global.codecept_dir, pathToFile);
445
447
 
446
- return this.t.setFilesToUpload(el, [file]).catch(mapError)
448
+ return this.t
449
+ .setFilesToUpload(el, [file])
450
+ .catch(mapError);
447
451
  }
448
452
 
449
453
  /**
@@ -452,11 +456,11 @@ class TestCafe extends Helper {
452
456
  * {{ keys }}
453
457
  */
454
458
  async pressKey(key) {
455
- assert(key, 'Expected a sequence of keys or key combinations')
459
+ assert(key, 'Expected a sequence of keys or key combinations');
456
460
 
457
461
  return this.t
458
462
  .pressKey(key.toLowerCase()) // testcafe keys are lowercase
459
- .catch(mapError)
463
+ .catch(mapError);
460
464
  }
461
465
 
462
466
  /**
@@ -464,10 +468,12 @@ class TestCafe extends Helper {
464
468
  *
465
469
  */
466
470
  async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
467
- const els = (await findElements.call(this, this.context, locator)).filterVisible()
468
- await assertElementExists(els, locator)
471
+ const els = (await findElements.call(this, this.context, locator)).filterVisible();
472
+ await assertElementExists(els, locator);
469
473
 
470
- return this.t.hover(els.nth(0), { offsetX, offsetY }).catch(mapError)
474
+ return this.t
475
+ .hover(els.nth(0), { offsetX, offsetY })
476
+ .catch(mapError);
471
477
  }
472
478
 
473
479
  /**
@@ -475,15 +481,17 @@ class TestCafe extends Helper {
475
481
  *
476
482
  */
477
483
  async doubleClick(locator, context = null) {
478
- let matcher
484
+ let matcher;
479
485
  if (context) {
480
- const els = await this._locate(context)
481
- await assertElementExists(els, context)
482
- matcher = await els.nth(0)
486
+ const els = await this._locate(context);
487
+ await assertElementExists(els, context);
488
+ matcher = await els.nth(0);
483
489
  }
484
490
 
485
- const els = (await findClickable.call(this, matcher, locator)).filterVisible()
486
- return this.t.doubleClick(els.nth(0)).catch(mapError)
491
+ const els = (await findClickable.call(this, matcher, locator)).filterVisible();
492
+ return this.t
493
+ .doubleClick(els.nth(0))
494
+ .catch(mapError);
487
495
  }
488
496
 
489
497
  /**
@@ -491,34 +499,40 @@ class TestCafe extends Helper {
491
499
  *
492
500
  */
493
501
  async rightClick(locator, context = null) {
494
- let matcher
502
+ let matcher;
495
503
  if (context) {
496
- const els = await this._locate(context)
497
- await assertElementExists(els, context)
498
- matcher = await els.nth(0)
504
+ const els = await this._locate(context);
505
+ await assertElementExists(els, context);
506
+ matcher = await els.nth(0);
499
507
  }
500
- const els = (await findClickable.call(this, matcher, locator)).filterVisible()
501
- assertElementExists(els, locator)
502
- return this.t.rightClick(els.nth(0)).catch(mapError)
508
+ const els = (await findClickable.call(this, matcher, locator)).filterVisible();
509
+ assertElementExists(els, locator);
510
+ return this.t
511
+ .rightClick(els.nth(0))
512
+ .catch(mapError);
503
513
  }
504
514
 
505
515
  /**
506
516
  * {{> checkOption }}
507
517
  */
508
518
  async checkOption(field, context = null) {
509
- const el = await findCheckable.call(this, field, context)
519
+ const el = await findCheckable.call(this, field, context);
510
520
 
511
- return this.t.click(el).catch(mapError)
521
+ return this.t
522
+ .click(el)
523
+ .catch(mapError);
512
524
  }
513
525
 
514
526
  /**
515
527
  * {{> uncheckOption }}
516
528
  */
517
529
  async uncheckOption(field, context = null) {
518
- const el = await findCheckable.call(this, field, context)
530
+ const el = await findCheckable.call(this, field, context);
519
531
 
520
532
  if (await el.checked) {
521
- return this.t.click(el).catch(mapError)
533
+ return this.t
534
+ .click(el)
535
+ .catch(mapError);
522
536
  }
523
537
  }
524
538
 
@@ -526,56 +540,58 @@ class TestCafe extends Helper {
526
540
  * {{> seeCheckboxIsChecked }}
527
541
  */
528
542
  async seeCheckboxIsChecked(field) {
529
- return proceedIsChecked.call(this, 'assert', field)
543
+ return proceedIsChecked.call(this, 'assert', field);
530
544
  }
531
545
 
532
546
  /**
533
547
  * {{> dontSeeCheckboxIsChecked }}
534
548
  */
535
549
  async dontSeeCheckboxIsChecked(field) {
536
- return proceedIsChecked.call(this, 'negate', field)
550
+ return proceedIsChecked.call(this, 'negate', field);
537
551
  }
538
552
 
539
553
  /**
540
554
  * {{> selectOption }}
541
555
  */
542
556
  async selectOption(select, option) {
543
- const els = await findFields.call(this, select)
544
- assertElementExists(els, select, 'Selectable field')
557
+ const els = await findFields.call(this, select);
558
+ assertElementExists(els, select, 'Selectable field');
545
559
 
546
- const el = await els.filterVisible().nth(0)
560
+ const el = await els.filterVisible().nth(0);
547
561
 
548
562
  if ((await el.tagName).toLowerCase() !== 'select') {
549
- throw new Error('Element is not <select>')
563
+ throw new Error('Element is not <select>');
550
564
  }
551
- if (!Array.isArray(option)) option = [option]
565
+ if (!Array.isArray(option)) option = [option];
552
566
 
553
567
  // TODO As far as I understand the testcafe docs this should do a multi-select
554
568
  // but it does not work
555
569
  // const clickOpts = { ctrl: option.length > 1 };
556
- await this.t.click(el).catch(mapError)
570
+ await this.t.click(el).catch(mapError);
557
571
 
558
572
  for (const key of option) {
559
- const opt = key
573
+ const opt = key;
560
574
 
561
- let optEl
575
+ let optEl;
562
576
  try {
563
- optEl = el.child('option').withText(opt)
577
+ optEl = el.child('option').withText(opt);
564
578
  if (await optEl.count) {
565
- await this.t.click(optEl).catch(mapError)
566
- continue
579
+ await this.t.click(optEl).catch(mapError);
580
+ continue;
567
581
  }
568
582
  // eslint-disable-next-line no-empty
569
- } catch (err) {}
583
+ } catch (err) {
584
+ }
570
585
 
571
586
  try {
572
- const sel = `[value="${opt}"]`
573
- optEl = el.find(sel)
587
+ const sel = `[value="${opt}"]`;
588
+ optEl = el.find(sel);
574
589
  if (await optEl.count) {
575
- await this.t.click(optEl).catch(mapError)
590
+ await this.t.click(optEl).catch(mapError);
576
591
  }
577
592
  // eslint-disable-next-line no-empty
578
- } catch (err) {}
593
+ } catch (err) {
594
+ }
579
595
  }
580
596
  }
581
597
 
@@ -583,28 +599,28 @@ class TestCafe extends Helper {
583
599
  * {{> seeInCurrentUrl }}
584
600
  */
585
601
  async seeInCurrentUrl(url) {
586
- stringIncludes('url').assert(url, await getPageUrl(this.t)().catch(mapError))
602
+ stringIncludes('url').assert(url, await getPageUrl(this.t)().catch(mapError));
587
603
  }
588
604
 
589
605
  /**
590
606
  * {{> dontSeeInCurrentUrl }}
591
607
  */
592
608
  async dontSeeInCurrentUrl(url) {
593
- stringIncludes('url').negate(url, await getPageUrl(this.t)().catch(mapError))
609
+ stringIncludes('url').negate(url, await getPageUrl(this.t)().catch(mapError));
594
610
  }
595
611
 
596
612
  /**
597
613
  * {{> seeCurrentUrlEquals }}
598
614
  */
599
615
  async seeCurrentUrlEquals(url) {
600
- urlEquals(this.options.url).assert(url, await getPageUrl(this.t)().catch(mapError))
616
+ urlEquals(this.options.url).assert(url, await getPageUrl(this.t)().catch(mapError));
601
617
  }
602
618
 
603
619
  /**
604
620
  * {{> dontSeeCurrentUrlEquals }}
605
621
  */
606
622
  async dontSeeCurrentUrlEquals(url) {
607
- urlEquals(this.options.url).negate(url, await getPageUrl(this.t)().catch(mapError))
623
+ urlEquals(this.options.url).negate(url, await getPageUrl(this.t)().catch(mapError));
608
624
  }
609
625
 
610
626
  /**
@@ -612,14 +628,16 @@ class TestCafe extends Helper {
612
628
  *
613
629
  */
614
630
  async see(text, context = null) {
615
- let els
631
+ let els;
616
632
  if (context) {
617
- els = (await findElements.call(this, this.context, context)).withText(normalizeSpacesInString(text))
633
+ els = (await findElements.call(this, this.context, context)).withText(normalizeSpacesInString(text));
618
634
  } else {
619
- els = (await findElements.call(this, this.context, '*')).withText(normalizeSpacesInString(text))
635
+ els = (await findElements.call(this, this.context, '*')).withText(normalizeSpacesInString(text));
620
636
  }
621
637
 
622
- return this.t.expect(els.filterVisible().count).gt(0, `No element with text "${text}" found`).catch(mapError)
638
+ return this.t
639
+ .expect(els.filterVisible().count).gt(0, `No element with text "${text}" found`)
640
+ .catch(mapError);
623
641
  }
624
642
 
625
643
  /**
@@ -627,61 +645,56 @@ class TestCafe extends Helper {
627
645
  *
628
646
  */
629
647
  async dontSee(text, context = null) {
630
- let els
648
+ let els;
631
649
  if (context) {
632
- els = (await findElements.call(this, this.context, context)).withText(text)
650
+ els = (await findElements.call(this, this.context, context)).withText(text);
633
651
  } else {
634
- els = (await findElements.call(this, this.context, 'body')).withText(text)
652
+ els = (await findElements.call(this, this.context, 'body')).withText(text);
635
653
  }
636
654
 
637
655
  return this.t
638
- .expect(els.filterVisible().count)
639
- .eql(0, `Element with text "${text}" can still be seen`)
640
- .catch(mapError)
656
+ .expect(els.filterVisible().count).eql(0, `Element with text "${text}" can still be seen`)
657
+ .catch(mapError);
641
658
  }
642
659
 
643
660
  /**
644
661
  * {{> seeElement }}
645
662
  */
646
663
  async seeElement(locator) {
647
- const exists = (await findElements.call(this, this.context, locator)).filterVisible().exists
664
+ const exists = (await findElements.call(this, this.context, locator)).filterVisible().exists;
648
665
  return this.t
649
- .expect(exists)
650
- .ok(`No element "${new Locator(locator)}" found`)
651
- .catch(mapError)
666
+ .expect(exists).ok(`No element "${(new Locator(locator))}" found`)
667
+ .catch(mapError);
652
668
  }
653
669
 
654
670
  /**
655
671
  * {{> dontSeeElement }}
656
672
  */
657
673
  async dontSeeElement(locator) {
658
- const exists = (await findElements.call(this, this.context, locator)).filterVisible().exists
674
+ const exists = (await findElements.call(this, this.context, locator)).filterVisible().exists;
659
675
  return this.t
660
- .expect(exists)
661
- .notOk(`Element "${new Locator(locator)}" is still visible`)
662
- .catch(mapError)
676
+ .expect(exists).notOk(`Element "${(new Locator(locator))}" is still visible`)
677
+ .catch(mapError);
663
678
  }
664
679
 
665
680
  /**
666
681
  * {{> seeElementInDOM }}
667
682
  */
668
683
  async seeElementInDOM(locator) {
669
- const exists = (await findElements.call(this, this.context, locator)).exists
684
+ const exists = (await findElements.call(this, this.context, locator)).exists;
670
685
  return this.t
671
- .expect(exists)
672
- .ok(`No element "${new Locator(locator)}" found in DOM`)
673
- .catch(mapError)
686
+ .expect(exists).ok(`No element "${(new Locator(locator))}" found in DOM`)
687
+ .catch(mapError);
674
688
  }
675
689
 
676
690
  /**
677
691
  * {{> dontSeeElementInDOM }}
678
692
  */
679
693
  async dontSeeElementInDOM(locator) {
680
- const exists = (await findElements.call(this, this.context, locator)).exists
694
+ const exists = (await findElements.call(this, this.context, locator)).exists;
681
695
  return this.t
682
- .expect(exists)
683
- .notOk(`Element "${new Locator(locator)}" is still in DOM`)
684
- .catch(mapError)
696
+ .expect(exists).notOk(`Element "${(new Locator(locator))}" is still in DOM`)
697
+ .catch(mapError);
685
698
  }
686
699
 
687
700
  /**
@@ -689,45 +702,48 @@ class TestCafe extends Helper {
689
702
  *
690
703
  */
691
704
  async seeNumberOfVisibleElements(locator, num) {
692
- const count = (await findElements.call(this, this.context, locator)).filterVisible().count
693
- return this.t.expect(count).eql(num).catch(mapError)
705
+ const count = (await findElements.call(this, this.context, locator)).filterVisible().count;
706
+ return this.t
707
+ .expect(count).eql(num)
708
+ .catch(mapError);
694
709
  }
695
710
 
696
711
  /**
697
712
  * {{> grabNumberOfVisibleElements }}
698
713
  */
699
714
  async grabNumberOfVisibleElements(locator) {
700
- const count = (await findElements.call(this, this.context, locator)).filterVisible().count
701
- return count
715
+ const count = (await findElements.call(this, this.context, locator)).filterVisible().count;
716
+ return count;
702
717
  }
703
718
 
704
719
  /**
705
720
  * {{> seeInField }}
706
721
  */
707
722
  async seeInField(field, value) {
708
- const _value = typeof value === 'boolean' ? value : value.toString()
723
+ const _value = (typeof value === 'boolean') ? value : value.toString();
709
724
  // const expectedValue = findElements.call(this, this.context, field).value;
710
- const els = await findFields.call(this, field)
711
- assertElementExists(els, field, 'Field')
712
- const el = await els.nth(0)
725
+ const els = await findFields.call(this, field);
726
+ assertElementExists(els, field, 'Field');
727
+ const el = await els.nth(0);
713
728
 
714
729
  return this.t
715
- .expect(await el.value)
716
- .eql(_value)
717
- .catch(mapError)
730
+ .expect(await el.value).eql(_value)
731
+ .catch(mapError);
718
732
  }
719
733
 
720
734
  /**
721
735
  * {{> dontSeeInField }}
722
736
  */
723
737
  async dontSeeInField(field, value) {
724
- const _value = typeof value === 'boolean' ? value : value.toString()
738
+ const _value = (typeof value === 'boolean') ? value : value.toString();
725
739
  // const expectedValue = findElements.call(this, this.context, field).value;
726
- const els = await findFields.call(this, field)
727
- assertElementExists(els, field, 'Field')
728
- const el = await els.nth(0)
740
+ const els = await findFields.call(this, field);
741
+ assertElementExists(els, field, 'Field');
742
+ const el = await els.nth(0);
729
743
 
730
- return this.t.expect(el.value).notEql(_value).catch(mapError)
744
+ return this.t
745
+ .expect(el.value).notEql(_value)
746
+ .catch(mapError);
731
747
  }
732
748
 
733
749
  /**
@@ -738,24 +754,26 @@ class TestCafe extends Helper {
738
754
  * ```
739
755
  */
740
756
  async seeTextEquals(text, context = null) {
741
- const expectedText = findElements.call(this, context, undefined).textContent
742
- return this.t.expect(expectedText).eql(text).catch(mapError)
757
+ const expectedText = findElements.call(this, context, undefined).textContent;
758
+ return this.t
759
+ .expect(expectedText).eql(text)
760
+ .catch(mapError);
743
761
  }
744
762
 
745
763
  /**
746
764
  * {{> seeInSource }}
747
765
  */
748
766
  async seeInSource(text) {
749
- const source = await getHtmlSource(this.t)()
750
- stringIncludes('HTML source of a page').assert(text, source)
767
+ const source = await getHtmlSource(this.t)();
768
+ stringIncludes('HTML source of a page').assert(text, source);
751
769
  }
752
770
 
753
771
  /**
754
772
  * {{> dontSeeInSource }}
755
773
  */
756
774
  async dontSeeInSource(text) {
757
- const source = await getHtmlSource(this.t)()
758
- stringIncludes('HTML source of a page').negate(text, source)
775
+ const source = await getHtmlSource(this.t)();
776
+ stringIncludes('HTML source of a page').negate(text, source);
759
777
  }
760
778
 
761
779
  /**
@@ -763,14 +781,14 @@ class TestCafe extends Helper {
763
781
  *
764
782
  */
765
783
  async saveElementScreenshot(locator, fileName) {
766
- const outputFile = path.join(global.output_dir, fileName)
784
+ const outputFile = path.join(global.output_dir, fileName);
767
785
 
768
- const sel = await findElements.call(this, this.context, locator)
769
- assertElementExists(sel, locator)
770
- const firstElement = await sel.filterVisible().nth(0)
786
+ const sel = await findElements.call(this, this.context, locator);
787
+ assertElementExists(sel, locator);
788
+ const firstElement = await sel.filterVisible().nth(0);
771
789
 
772
- this.debug(`Screenshot of ${new Locator(locator)} element has been saved to ${outputFile}`)
773
- return this.t.takeElementScreenshot(firstElement, fileName)
790
+ this.debug(`Screenshot of ${(new Locator(locator))} element has been saved to ${outputFile}`);
791
+ return this.t.takeElementScreenshot(firstElement, fileName);
774
792
  }
775
793
 
776
794
  /**
@@ -778,20 +796,20 @@ class TestCafe extends Helper {
778
796
  */
779
797
  // TODO Implement full page screenshots
780
798
  async saveScreenshot(fileName) {
781
- const outputFile = path.join(global.output_dir, fileName)
782
- this.debug(`Screenshot is saving to ${outputFile}`)
799
+ const outputFile = path.join(global.output_dir, fileName);
800
+ this.debug(`Screenshot is saving to ${outputFile}`);
783
801
 
784
802
  // TODO testcafe automatically creates thumbnail images (which cant be turned off)
785
- return this.t.takeScreenshot(fileName)
803
+ return this.t.takeScreenshot(fileName);
786
804
  }
787
805
 
788
806
  /**
789
807
  * {{> wait }}
790
808
  */
791
809
  async wait(sec) {
792
- return new Promise((done) => {
793
- setTimeout(done, sec * 1000)
794
- })
810
+ return new Promise(((done) => {
811
+ setTimeout(done, sec * 1000);
812
+ }));
795
813
  }
796
814
 
797
815
  /**
@@ -800,99 +818,99 @@ class TestCafe extends Helper {
800
818
  * If a function returns a Promise It will wait for its resolution.
801
819
  */
802
820
  async executeScript(fn, ...args) {
803
- const browserFn = createClientFunction(fn, args).with({ boundTestRun: this.t })
804
- return browserFn()
821
+ const browserFn = createClientFunction(fn, args).with({ boundTestRun: this.t });
822
+ return browserFn();
805
823
  }
806
824
 
807
825
  /**
808
826
  * {{> grabTextFromAll }}
809
827
  */
810
828
  async grabTextFromAll(locator) {
811
- const sel = await findElements.call(this, this.context, locator)
812
- const length = await sel.count
813
- const texts = []
829
+ const sel = await findElements.call(this, this.context, locator);
830
+ const length = await sel.count;
831
+ const texts = [];
814
832
  for (let i = 0; i < length; i++) {
815
- texts.push(await sel.nth(i).innerText)
833
+ texts.push(await sel.nth(i).innerText);
816
834
  }
817
835
 
818
- return texts
836
+ return texts;
819
837
  }
820
838
 
821
839
  /**
822
840
  * {{> grabTextFrom }}
823
841
  */
824
842
  async grabTextFrom(locator) {
825
- const sel = await findElements.call(this, this.context, locator)
826
- assertElementExists(sel, locator)
827
- const texts = await this.grabTextFromAll(locator)
843
+ const sel = await findElements.call(this, this.context, locator);
844
+ assertElementExists(sel, locator);
845
+ const texts = await this.grabTextFromAll(locator);
828
846
  if (texts.length > 1) {
829
- this.debugSection('GrabText', `Using first element out of ${texts.length}`)
847
+ this.debugSection('GrabText', `Using first element out of ${texts.length}`);
830
848
  }
831
849
 
832
- return texts[0]
850
+ return texts[0];
833
851
  }
834
852
 
835
853
  /**
836
854
  * {{> grabAttributeFrom }}
837
855
  */
838
856
  async grabAttributeFromAll(locator, attr) {
839
- const sel = await findElements.call(this, this.context, locator)
840
- const length = await sel.count
841
- const attrs = []
857
+ const sel = await findElements.call(this, this.context, locator);
858
+ const length = await sel.count;
859
+ const attrs = [];
842
860
  for (let i = 0; i < length; i++) {
843
- attrs.push(await (await sel.nth(i)).getAttribute(attr))
861
+ attrs.push(await (await sel.nth(i)).getAttribute(attr));
844
862
  }
845
863
 
846
- return attrs
864
+ return attrs;
847
865
  }
848
866
 
849
867
  /**
850
868
  * {{> grabAttributeFrom }}
851
869
  */
852
870
  async grabAttributeFrom(locator, attr) {
853
- const sel = await findElements.call(this, this.context, locator)
854
- assertElementExists(sel, locator)
855
- const attrs = await this.grabAttributeFromAll(locator, attr)
871
+ const sel = await findElements.call(this, this.context, locator);
872
+ assertElementExists(sel, locator);
873
+ const attrs = await this.grabAttributeFromAll(locator, attr);
856
874
  if (attrs.length > 1) {
857
- this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`)
875
+ this.debugSection('GrabAttribute', `Using first element out of ${attrs.length}`);
858
876
  }
859
877
 
860
- return attrs[0]
878
+ return attrs[0];
861
879
  }
862
880
 
863
881
  /**
864
882
  * {{> grabValueFromAll }}
865
883
  */
866
884
  async grabValueFromAll(locator) {
867
- const sel = await findElements.call(this, this.context, locator)
868
- const length = await sel.count
869
- const values = []
885
+ const sel = await findElements.call(this, this.context, locator);
886
+ const length = await sel.count;
887
+ const values = [];
870
888
  for (let i = 0; i < length; i++) {
871
- values.push(await (await sel.nth(i)).value)
889
+ values.push(await (await sel.nth(i)).value);
872
890
  }
873
891
 
874
- return values
892
+ return values;
875
893
  }
876
894
 
877
895
  /**
878
896
  * {{> grabValueFrom }}
879
897
  */
880
898
  async grabValueFrom(locator) {
881
- const sel = await findElements.call(this, this.context, locator)
882
- assertElementExists(sel, locator)
883
- const values = await this.grabValueFromAll(locator)
899
+ const sel = await findElements.call(this, this.context, locator);
900
+ assertElementExists(sel, locator);
901
+ const values = await this.grabValueFromAll(locator);
884
902
  if (values.length > 1) {
885
- this.debugSection('GrabValue', `Using first element out of ${values.length}`)
903
+ this.debugSection('GrabValue', `Using first element out of ${values.length}`);
886
904
  }
887
905
 
888
- return values[0]
906
+ return values[0];
889
907
  }
890
908
 
891
909
  /**
892
910
  * {{> grabSource }}
893
911
  */
894
912
  async grabSource() {
895
- return ClientFunction(() => document.documentElement.innerHTML).with({ boundTestRun: this.t })()
913
+ return ClientFunction(() => document.documentElement.innerHTML).with({ boundTestRun: this.t })();
896
914
  }
897
915
 
898
916
  /**
@@ -905,30 +923,28 @@ class TestCafe extends Helper {
905
923
  */
906
924
  async grabBrowserLogs() {
907
925
  // TODO Must map?
908
- return this.t.getBrowserConsoleMessages()
926
+ return this.t.getBrowserConsoleMessages();
909
927
  }
910
928
 
911
929
  /**
912
930
  * {{> grabCurrentUrl }}
913
931
  */
914
932
  async grabCurrentUrl() {
915
- return ClientFunction(() => document.location.href).with({ boundTestRun: this.t })()
933
+ return ClientFunction(() => document.location.href).with({ boundTestRun: this.t })();
916
934
  }
917
935
 
918
936
  /**
919
937
  * {{> grabPageScrollPosition }}
920
938
  */
921
939
  async grabPageScrollPosition() {
922
- return ClientFunction(() => ({ x: window.pageXOffset, y: window.pageYOffset })).with({ boundTestRun: this.t })()
940
+ return ClientFunction(() => ({ x: window.pageXOffset, y: window.pageYOffset })).with({ boundTestRun: this.t })();
923
941
  }
924
942
 
925
943
  /**
926
944
  * {{> scrollPageToTop }}
927
945
  */
928
946
  scrollPageToTop() {
929
- return ClientFunction(() => window.scrollTo(0, 0))
930
- .with({ boundTestRun: this.t })()
931
- .catch(mapError)
947
+ return ClientFunction(() => window.scrollTo(0, 0)).with({ boundTestRun: this.t })().catch(mapError);
932
948
  }
933
949
 
934
950
  /**
@@ -936,15 +952,16 @@ class TestCafe extends Helper {
936
952
  */
937
953
  scrollPageToBottom() {
938
954
  return ClientFunction(() => {
939
- const body = document.body
940
- const html = document.documentElement
941
- window.scrollTo(
942
- 0,
943
- Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
944
- )
945
- })
946
- .with({ boundTestRun: this.t })()
947
- .catch(mapError)
955
+ const body = document.body;
956
+ const html = document.documentElement;
957
+ window.scrollTo(0, Math.max(
958
+ body.scrollHeight,
959
+ body.offsetHeight,
960
+ html.clientHeight,
961
+ html.scrollHeight,
962
+ html.offsetHeight,
963
+ ));
964
+ }).with({ boundTestRun: this.t })().catch(mapError);
948
965
  }
949
966
 
950
967
  /**
@@ -952,30 +969,30 @@ class TestCafe extends Helper {
952
969
  */
953
970
  async scrollTo(locator, offsetX = 0, offsetY = 0) {
954
971
  if (typeof locator === 'number' && typeof offsetX === 'number') {
955
- offsetY = offsetX
956
- offsetX = locator
957
- locator = null
972
+ offsetY = offsetX;
973
+ offsetX = locator;
974
+ locator = null;
958
975
  }
959
976
 
960
977
  const scrollBy = ClientFunction((offset) => {
961
978
  if (window && window.scrollBy && offset) {
962
- window.scrollBy(offset.x, offset.y)
979
+ window.scrollBy(offset.x, offset.y);
963
980
  }
964
- }).with({ boundTestRun: this.t })
981
+ }).with({ boundTestRun: this.t });
965
982
 
966
983
  if (locator) {
967
- const els = await this._locate(locator)
968
- assertElementExists(els, locator, 'Element')
969
- const el = await els.nth(0)
970
- const x = (await el.offsetLeft) + offsetX
971
- const y = (await el.offsetTop) + offsetY
984
+ const els = await this._locate(locator);
985
+ assertElementExists(els, locator, 'Element');
986
+ const el = await els.nth(0);
987
+ const x = (await el.offsetLeft) + offsetX;
988
+ const y = (await el.offsetTop) + offsetY;
972
989
 
973
- return scrollBy({ x, y }).catch(mapError)
990
+ return scrollBy({ x, y }).catch(mapError);
974
991
  }
975
992
 
976
- const x = offsetX
977
- const y = offsetY
978
- return scrollBy({ x, y }).catch(mapError)
993
+ const x = offsetX;
994
+ const y = offsetY;
995
+ return scrollBy({ x, y }).catch(mapError);
979
996
  }
980
997
 
981
998
  /**
@@ -983,15 +1000,15 @@ class TestCafe extends Helper {
983
1000
  */
984
1001
  async switchTo(locator) {
985
1002
  if (Number.isInteger(locator)) {
986
- throw new Error('Not supported switching to iframe by number')
1003
+ throw new Error('Not supported switching to iframe by number');
987
1004
  }
988
1005
 
989
1006
  if (!locator) {
990
- return this.t.switchToMainWindow()
1007
+ return this.t.switchToMainWindow();
991
1008
  }
992
1009
 
993
- const el = await findElements.call(this, this.context, locator)
994
- return this.t.switchToIframe(el)
1010
+ const el = await findElements.call(this, this.context, locator);
1011
+ return this.t.switchToIframe(el);
995
1012
  }
996
1013
 
997
1014
  // TODO Add url assertions
@@ -1001,20 +1018,17 @@ class TestCafe extends Helper {
1001
1018
  */
1002
1019
  async setCookie(cookie) {
1003
1020
  if (Array.isArray(cookie)) {
1004
- throw new Error('cookie array is not supported')
1021
+ throw new Error('cookie array is not supported');
1005
1022
  }
1006
1023
 
1007
- cookie.path = cookie.path || '/'
1024
+ cookie.path = cookie.path || '/';
1008
1025
  // cookie.expires = cookie.expires || (new Date()).toUTCString();
1009
1026
 
1010
- const setCookie = ClientFunction(
1011
- () => {
1012
- document.cookie = `${cookie.name}=${cookie.value};path=${cookie.path};expires=${cookie.expires};`
1013
- },
1014
- { dependencies: { cookie } },
1015
- ).with({ boundTestRun: this.t })
1027
+ const setCookie = ClientFunction(() => {
1028
+ document.cookie = `${cookie.name}=${cookie.value};path=${cookie.path};expires=${cookie.expires};`;
1029
+ }, { dependencies: { cookie } }).with({ boundTestRun: this.t });
1016
1030
 
1017
- return setCookie()
1031
+ return setCookie();
1018
1032
  }
1019
1033
 
1020
1034
  /**
@@ -1022,16 +1036,16 @@ class TestCafe extends Helper {
1022
1036
  *
1023
1037
  */
1024
1038
  async seeCookie(name) {
1025
- const cookie = await this.grabCookie(name)
1026
- empty(`cookie ${name} to be set`).negate(cookie)
1039
+ const cookie = await this.grabCookie(name);
1040
+ empty(`cookie ${name} to be set`).negate(cookie);
1027
1041
  }
1028
1042
 
1029
1043
  /**
1030
1044
  * {{> dontSeeCookie }}
1031
1045
  */
1032
1046
  async dontSeeCookie(name) {
1033
- const cookie = await this.grabCookie(name)
1034
- empty(`cookie ${name} not to be set`).assert(cookie)
1047
+ const cookie = await this.grabCookie(name);
1048
+ empty(`cookie ${name} not to be set`).assert(cookie);
1035
1049
  }
1036
1050
 
1037
1051
  /**
@@ -1042,153 +1056,141 @@ class TestCafe extends Helper {
1042
1056
  async grabCookie(name) {
1043
1057
  if (!name) {
1044
1058
  const getCookie = ClientFunction(() => {
1045
- return document.cookie.split(';').map((c) => c.split('='))
1046
- }).with({ boundTestRun: this.t })
1047
- const cookies = await getCookie()
1048
- return cookies.map((cookie) => ({ name: cookie[0].trim(), value: cookie[1] }))
1059
+ return document.cookie.split(';').map(c => c.split('='));
1060
+ }).with({ boundTestRun: this.t });
1061
+ const cookies = await getCookie();
1062
+ return cookies.map(cookie => ({ name: cookie[0].trim(), value: cookie[1] }));
1049
1063
  }
1050
- const getCookie = ClientFunction(
1051
- () => {
1052
- // eslint-disable-next-line prefer-template
1053
- const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)')
1054
- return v ? v[2] : null
1055
- },
1056
- { dependencies: { name } },
1057
- ).with({ boundTestRun: this.t })
1058
- const value = await getCookie()
1059
- if (value) return { name, value }
1064
+ const getCookie = ClientFunction(() => {
1065
+ // eslint-disable-next-line prefer-template
1066
+ const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
1067
+ return v ? v[2] : null;
1068
+ }, { dependencies: { name } }).with({ boundTestRun: this.t });
1069
+ const value = await getCookie();
1070
+ if (value) return { name, value };
1060
1071
  }
1061
1072
 
1062
1073
  /**
1063
1074
  * {{> clearCookie }}
1064
1075
  */
1065
1076
  async clearCookie(cookieName) {
1066
- const clearCookies = ClientFunction(
1067
- () => {
1068
- const cookies = document.cookie.split(';')
1069
-
1070
- for (let i = 0; i < cookies.length; i++) {
1071
- const cookie = cookies[i]
1072
- const eqPos = cookie.indexOf('=')
1073
- const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie
1074
- if (cookieName === undefined || name === cookieName) {
1075
- document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`
1076
- }
1077
+ const clearCookies = ClientFunction(() => {
1078
+ const cookies = document.cookie.split(';');
1079
+
1080
+ for (let i = 0; i < cookies.length; i++) {
1081
+ const cookie = cookies[i];
1082
+ const eqPos = cookie.indexOf('=');
1083
+ const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
1084
+ if (cookieName === undefined || name === cookieName) {
1085
+ document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;
1077
1086
  }
1078
- },
1079
- { dependencies: { cookieName } },
1080
- ).with({ boundTestRun: this.t })
1087
+ }
1088
+ }, { dependencies: { cookieName } }).with({ boundTestRun: this.t });
1081
1089
 
1082
- return clearCookies()
1090
+ return clearCookies();
1083
1091
  }
1084
1092
 
1085
1093
  /**
1086
1094
  * {{> waitInUrl }}
1087
1095
  */
1088
1096
  async waitInUrl(urlPart, sec = null) {
1089
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1097
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1090
1098
 
1091
- const clientFn = createClientFunction(
1092
- (urlPart) => {
1093
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
1094
- return currUrl.indexOf(urlPart) > -1
1095
- },
1096
- [urlPart],
1097
- ).with({ boundTestRun: this.t })
1099
+ const clientFn = createClientFunction((urlPart) => {
1100
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
1101
+ return currUrl.indexOf(urlPart) > -1;
1102
+ }, [urlPart]).with({ boundTestRun: this.t });
1098
1103
 
1099
1104
  return waitForFunction(clientFn, waitTimeout).catch(async () => {
1100
- const currUrl = await this.grabCurrentUrl()
1101
- throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
1102
- })
1105
+ const currUrl = await this.grabCurrentUrl();
1106
+ throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`);
1107
+ });
1103
1108
  }
1104
1109
 
1105
1110
  /**
1106
1111
  * {{> waitUrlEquals }}
1107
1112
  */
1108
1113
  async waitUrlEquals(urlPart, sec = null) {
1109
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1114
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1110
1115
 
1111
- const baseUrl = this.options.url
1116
+ const baseUrl = this.options.url;
1112
1117
  if (urlPart.indexOf('http') < 0) {
1113
- urlPart = baseUrl + urlPart
1118
+ urlPart = baseUrl + urlPart;
1114
1119
  }
1115
1120
 
1116
- const clientFn = createClientFunction(
1117
- (urlPart) => {
1118
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
1119
- return currUrl === urlPart
1120
- },
1121
- [urlPart],
1122
- ).with({ boundTestRun: this.t })
1121
+ const clientFn = createClientFunction((urlPart) => {
1122
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
1123
+ return currUrl === urlPart;
1124
+ }, [urlPart]).with({ boundTestRun: this.t });
1123
1125
 
1124
1126
  return waitForFunction(clientFn, waitTimeout).catch(async () => {
1125
- const currUrl = await this.grabCurrentUrl()
1126
- throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
1127
- })
1127
+ const currUrl = await this.grabCurrentUrl();
1128
+ throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`);
1129
+ });
1128
1130
  }
1129
1131
 
1130
1132
  /**
1131
1133
  * {{> waitForFunction }}
1132
1134
  */
1133
1135
  async waitForFunction(fn, argsOrSec = null, sec = null) {
1134
- let args = []
1136
+ let args = [];
1135
1137
  if (argsOrSec) {
1136
1138
  if (Array.isArray(argsOrSec)) {
1137
- args = argsOrSec
1139
+ args = argsOrSec;
1138
1140
  } else if (typeof argsOrSec === 'number') {
1139
- sec = argsOrSec
1141
+ sec = argsOrSec;
1140
1142
  }
1141
1143
  }
1142
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1144
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1143
1145
 
1144
- const clientFn = createClientFunction(fn, args).with({ boundTestRun: this.t })
1146
+ const clientFn = createClientFunction(fn, args).with({ boundTestRun: this.t });
1145
1147
 
1146
- return waitForFunction(clientFn, waitTimeout)
1148
+ return waitForFunction(clientFn, waitTimeout);
1147
1149
  }
1148
1150
 
1149
1151
  /**
1150
1152
  * {{> waitNumberOfVisibleElements }}
1151
1153
  */
1152
1154
  async waitNumberOfVisibleElements(locator, num, sec) {
1153
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1155
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1154
1156
 
1155
1157
  return this.t
1156
1158
  .expect(createSelector(locator).with({ boundTestRun: this.t }).filterVisible().count)
1157
- .eql(num, `The number of elements (${new Locator(locator)}) is not ${num} after ${sec} sec`, {
1158
- timeout: waitTimeout,
1159
- })
1160
- .catch(mapError)
1159
+ .eql(num, `The number of elements (${(new Locator(locator))}) is not ${num} after ${sec} sec`, { timeout: waitTimeout })
1160
+ .catch(mapError);
1161
1161
  }
1162
1162
 
1163
1163
  /**
1164
1164
  * {{> waitForElement }}
1165
1165
  */
1166
1166
  async waitForElement(locator, sec) {
1167
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1167
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1168
1168
 
1169
- return this.t.expect(createSelector(locator).with({ boundTestRun: this.t }).exists).ok({ timeout: waitTimeout })
1169
+ return this.t
1170
+ .expect(createSelector(locator).with({ boundTestRun: this.t }).exists)
1171
+ .ok({ timeout: waitTimeout });
1170
1172
  }
1171
1173
 
1172
1174
  /**
1173
1175
  * {{> waitToHide }}
1174
1176
  */
1175
1177
  async waitToHide(locator, sec) {
1176
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1178
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1177
1179
 
1178
1180
  return this.t
1179
1181
  .expect(createSelector(locator).filterHidden().with({ boundTestRun: this.t }).exists)
1180
- .notOk({ timeout: waitTimeout })
1182
+ .notOk({ timeout: waitTimeout });
1181
1183
  }
1182
1184
 
1183
1185
  /**
1184
1186
  * {{> waitForInvisible }}
1185
1187
  */
1186
1188
  async waitForInvisible(locator, sec) {
1187
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1189
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1188
1190
 
1189
1191
  return this.t
1190
1192
  .expect(createSelector(locator).filterVisible().with({ boundTestRun: this.t }).exists)
1191
- .ok({ timeout: waitTimeout })
1193
+ .ok({ timeout: waitTimeout });
1192
1194
  }
1193
1195
 
1194
1196
  /**
@@ -1196,221 +1198,213 @@ class TestCafe extends Helper {
1196
1198
  *
1197
1199
  */
1198
1200
  async waitForText(text, sec = null, context = null) {
1199
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1201
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1200
1202
 
1201
- let els
1203
+ let els;
1202
1204
  if (context) {
1203
- els = await findElements.call(this, this.context, context)
1204
- await this.t.expect(els.exists).ok(`Context element ${context} not found`, { timeout: waitTimeout })
1205
+ els = (await findElements.call(this, this.context, context));
1206
+ await this.t
1207
+ .expect(els.exists)
1208
+ .ok(`Context element ${context} not found`, { timeout: waitTimeout });
1205
1209
  } else {
1206
- els = await findElements.call(this, this.context, '*')
1210
+ els = (await findElements.call(this, this.context, '*'));
1207
1211
  }
1208
1212
 
1209
1213
  return this.t
1210
1214
  .expect(els.withText(text).filterVisible().exists)
1211
1215
  .ok(`No element with text "${text}" found in ${context || 'body'}`, { timeout: waitTimeout })
1212
- .catch(mapError)
1216
+ .catch(mapError);
1213
1217
  }
1214
1218
  }
1215
1219
 
1216
1220
  async function waitForFunction(browserFn, waitTimeout) {
1217
- const pause = () =>
1218
- new Promise((done) => {
1219
- setTimeout(done, 50)
1220
- })
1221
+ const pause = () => new Promise((done => {
1222
+ setTimeout(done, 50);
1223
+ }));
1221
1224
 
1222
- const start = Date.now()
1225
+ const start = Date.now();
1223
1226
  // eslint-disable-next-line no-constant-condition
1224
1227
  while (true) {
1225
- let result
1228
+ let result;
1226
1229
  try {
1227
- result = await browserFn()
1230
+ result = await browserFn();
1228
1231
  // eslint-disable-next-line no-empty
1229
1232
  } catch (err) {
1230
- throw new Error(`Error running function ${err.toString()}`)
1233
+ throw new Error(`Error running function ${err.toString()}`);
1231
1234
  }
1232
1235
 
1233
- if (result) return result
1236
+ if (result) return result;
1234
1237
 
1235
- const duration = Date.now() - start
1238
+ const duration = (Date.now() - start);
1236
1239
  if (duration > waitTimeout) {
1237
- throw new Error('waitForFunction timed out')
1240
+ throw new Error('waitForFunction timed out');
1238
1241
  }
1239
- await pause() // make polling
1242
+ await pause(); // make polling
1240
1243
  }
1241
1244
  }
1242
1245
 
1243
1246
  const createSelector = (locator) => {
1244
- locator = new Locator(locator, 'css')
1245
- if (locator.isXPath()) return elementByXPath(locator.value)
1246
- return Selector(locator.simplify())
1247
- }
1247
+ locator = new Locator(locator, 'css');
1248
+ if (locator.isXPath()) return elementByXPath(locator.value);
1249
+ return Selector(locator.simplify());
1250
+ };
1248
1251
 
1249
1252
  const elementByXPath = (xpath) => {
1250
- assert(xpath, 'xpath is required')
1253
+ assert(xpath, 'xpath is required');
1251
1254
 
1252
- return Selector(
1253
- () => {
1254
- const iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null)
1255
- const items = []
1255
+ return Selector(() => {
1256
+ const iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
1257
+ const items = [];
1256
1258
 
1257
- let item = iterator.iterateNext()
1259
+ let item = iterator.iterateNext();
1258
1260
 
1259
- while (item) {
1260
- items.push(item)
1261
- item = iterator.iterateNext()
1262
- }
1261
+ while (item) {
1262
+ items.push(item);
1263
+ item = iterator.iterateNext();
1264
+ }
1263
1265
 
1264
- return items
1265
- },
1266
- { dependencies: { xpath } },
1267
- )
1268
- }
1266
+ return items;
1267
+ }, { dependencies: { xpath } });
1268
+ };
1269
1269
 
1270
1270
  const assertElementExists = async (res, locator, prefix, suffix) => {
1271
1271
  if (!res || !(await res.count) || !(await res.nth(0).tagName)) {
1272
- throw new ElementNotFound(locator, prefix, suffix)
1272
+ throw new ElementNotFound(locator, prefix, suffix);
1273
1273
  }
1274
- }
1274
+ };
1275
1275
 
1276
1276
  async function findElements(matcher, locator) {
1277
- if (locator && locator.react) throw new Error('react locators are not yet supported')
1277
+ if (locator && locator.react) throw new Error('react locators are not yet supported');
1278
1278
 
1279
- locator = new Locator(locator, 'css')
1279
+ locator = new Locator(locator, 'css');
1280
1280
 
1281
1281
  if (!locator.isXPath()) {
1282
1282
  return matcher
1283
1283
  ? matcher.find(locator.simplify())
1284
- : Selector(locator.simplify()).with({ timeout: 0, boundTestRun: this.t })
1284
+ : Selector(locator.simplify()).with({ timeout: 0, boundTestRun: this.t });
1285
1285
  }
1286
1286
 
1287
- if (!matcher) return elementByXPath(locator.value).with({ timeout: 0, boundTestRun: this.t })
1287
+ if (!matcher) return elementByXPath(locator.value).with({ timeout: 0, boundTestRun: this.t });
1288
1288
 
1289
- return matcher.find(
1290
- (node, idx, originNode) => {
1291
- const found = document.evaluate(xpath, originNode, null, 5, null)
1292
- let current = null
1293
- while ((current = found.iterateNext())) {
1294
- if (current === node) return true
1295
- }
1296
- return false
1297
- },
1298
- { xpath: locator.value },
1299
- )
1289
+ return matcher.find((node, idx, originNode) => {
1290
+ const found = document.evaluate(xpath, originNode, null, 5, null);
1291
+ let current = null;
1292
+ while (current = found.iterateNext()) {
1293
+ if (current === node) return true;
1294
+ }
1295
+ return false;
1296
+ }, { xpath: locator.value });
1300
1297
  }
1301
1298
 
1302
1299
  async function proceedClick(locator, context = null) {
1303
- let matcher
1300
+ let matcher;
1304
1301
 
1305
1302
  if (context) {
1306
- const els = await this._locate(context)
1307
- await assertElementExists(els, context)
1308
- matcher = await els.nth(0)
1303
+ const els = await this._locate(context);
1304
+ await assertElementExists(els, context);
1305
+ matcher = await els.nth(0);
1309
1306
  }
1310
1307
 
1311
- const els = await findClickable.call(this, matcher, locator)
1308
+ const els = await findClickable.call(this, matcher, locator);
1312
1309
  if (context) {
1313
- await assertElementExists(
1314
- els,
1315
- locator,
1316
- 'Clickable element',
1317
- `was not found inside element ${new Locator(context).toString()}`,
1318
- )
1310
+ await assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
1319
1311
  } else {
1320
- await assertElementExists(els, locator, 'Clickable element')
1312
+ await assertElementExists(els, locator, 'Clickable element');
1321
1313
  }
1322
1314
 
1323
- const firstElement = await els.filterVisible().nth(0)
1315
+ const firstElement = await els.filterVisible().nth(0);
1324
1316
 
1325
- return this.t.click(firstElement).catch(mapError)
1317
+ return this.t
1318
+ .click(firstElement)
1319
+ .catch(mapError);
1326
1320
  }
1327
1321
 
1328
1322
  async function findClickable(matcher, locator) {
1329
- if (locator && locator.react) throw new Error('react locators are not yet supported')
1323
+ if (locator && locator.react) throw new Error('react locators are not yet supported');
1330
1324
 
1331
- locator = new Locator(locator)
1332
- if (!locator.isFuzzy()) return (await findElements.call(this, matcher, locator)).filterVisible()
1325
+ locator = new Locator(locator);
1326
+ if (!locator.isFuzzy()) return (await findElements.call(this, matcher, locator)).filterVisible();
1333
1327
 
1334
- let els
1328
+ let els;
1335
1329
 
1336
1330
  // try to use native TestCafe locator
1337
- els = matcher ? matcher.find('a,button') : createSelector('a,button')
1338
- els = await els.withExactText(locator.value).with({ timeout: 0, boundTestRun: this.t })
1339
- if (await els.count) return els
1331
+ els = matcher ? matcher.find('a,button') : createSelector('a,button');
1332
+ els = await els.withExactText(locator.value).with({ timeout: 0, boundTestRun: this.t });
1333
+ if (await els.count) return els;
1340
1334
 
1341
- const literal = xpathLocator.literal(locator.value)
1335
+ const literal = xpathLocator.literal(locator.value);
1342
1336
 
1343
- els = (await findElements.call(this, matcher, Locator.clickable.narrow(literal))).filterVisible()
1344
- if (await els.count) return els
1337
+ els = (await findElements.call(this, matcher, Locator.clickable.narrow(literal))).filterVisible();
1338
+ if (await els.count) return els;
1345
1339
 
1346
- els = (await findElements.call(this, matcher, Locator.clickable.wide(literal))).filterVisible()
1347
- if (await els.count) return els
1340
+ els = (await findElements.call(this, matcher, Locator.clickable.wide(literal))).filterVisible();
1341
+ if (await els.count) return els;
1348
1342
 
1349
- els = (await findElements.call(this, matcher, Locator.clickable.self(literal))).filterVisible()
1350
- if (await els.count) return els
1343
+ els = (await findElements.call(this, matcher, Locator.clickable.self(literal))).filterVisible();
1344
+ if (await els.count) return els;
1351
1345
 
1352
- return findElements.call(this, matcher, locator.value) // by css or xpath
1346
+ return findElements.call(this, matcher, locator.value); // by css or xpath
1353
1347
  }
1354
1348
 
1355
1349
  async function proceedIsChecked(assertType, option) {
1356
- const els = await findCheckable.call(this, option)
1357
- assertElementExists(els, option, 'Checkable')
1350
+ const els = await findCheckable.call(this, option);
1351
+ assertElementExists(els, option, 'Checkable');
1358
1352
 
1359
- const selected = await els.checked
1353
+ const selected = await els.checked;
1360
1354
 
1361
- return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
1355
+ return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
1362
1356
  }
1363
1357
 
1364
1358
  async function findCheckable(locator, context) {
1365
- assert(locator, 'locator is required')
1366
- assert(this.t, 'this.t is required')
1359
+ assert(locator, 'locator is required');
1360
+ assert(this.t, 'this.t is required');
1367
1361
 
1368
- let contextEl = await this.context
1362
+ let contextEl = await this.context;
1369
1363
  if (typeof context === 'string') {
1370
- contextEl = (await findElements.call(this, contextEl, new Locator(context, 'css').simplify())).filterVisible()
1371
- contextEl = await contextEl.nth(0)
1364
+ contextEl = (await findElements.call(this, contextEl, (new Locator(context, 'css')).simplify())).filterVisible();
1365
+ contextEl = await contextEl.nth(0);
1372
1366
  }
1373
1367
 
1374
- const matchedLocator = new Locator(locator)
1368
+ const matchedLocator = new Locator(locator);
1375
1369
  if (!matchedLocator.isFuzzy()) {
1376
- return (await findElements.call(this, contextEl, matchedLocator.simplify())).filterVisible()
1370
+ return (await findElements.call(this, contextEl, matchedLocator.simplify())).filterVisible();
1377
1371
  }
1378
1372
 
1379
- const literal = xpathLocator.literal(locator)
1380
- let els = (await findElements.call(this, contextEl, Locator.checkable.byText(literal))).filterVisible()
1373
+ const literal = xpathLocator.literal(locator);
1374
+ let els = (await findElements.call(this, contextEl, Locator.checkable.byText(literal))).filterVisible();
1381
1375
  if (await els.count) {
1382
- return els
1376
+ return els;
1383
1377
  }
1384
1378
 
1385
- els = (await findElements.call(this, contextEl, Locator.checkable.byName(literal))).filterVisible()
1379
+ els = (await findElements.call(this, contextEl, Locator.checkable.byName(literal))).filterVisible();
1386
1380
  if (await els.count) {
1387
- return els
1381
+ return els;
1388
1382
  }
1389
1383
 
1390
- return (await findElements.call(this, contextEl, locator)).filterVisible()
1384
+ return (await findElements.call(this, contextEl, locator)).filterVisible();
1391
1385
  }
1392
1386
 
1393
1387
  async function findFields(locator) {
1394
- const matchedLocator = new Locator(locator)
1388
+ const matchedLocator = new Locator(locator);
1395
1389
  if (!matchedLocator.isFuzzy()) {
1396
- return this._locate(matchedLocator)
1390
+ return this._locate(matchedLocator);
1397
1391
  }
1398
- const literal = xpathLocator.literal(locator)
1392
+ const literal = xpathLocator.literal(locator);
1399
1393
 
1400
- let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
1394
+ let els = await this._locate({ xpath: Locator.field.labelEquals(literal) });
1401
1395
  if (await els.count) {
1402
- return els
1396
+ return els;
1403
1397
  }
1404
1398
 
1405
- els = await this._locate({ xpath: Locator.field.labelContains(literal) })
1399
+ els = await this._locate({ xpath: Locator.field.labelContains(literal) });
1406
1400
  if (await els.count) {
1407
- return els
1401
+ return els;
1408
1402
  }
1409
- els = await this._locate({ xpath: Locator.field.byName(literal) })
1403
+ els = await this._locate({ xpath: Locator.field.byName(literal) });
1410
1404
  if (await els.count) {
1411
- return els
1405
+ return els;
1412
1406
  }
1413
- return this._locate({ css: locator })
1407
+ return this._locate({ css: locator });
1414
1408
  }
1415
1409
 
1416
- module.exports = TestCafe
1410
+ export default TestCafe;