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

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