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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +2 -2
  2. package/bin/codecept.js +84 -81
  3. package/lib/actor.js +13 -13
  4. package/lib/ai.js +10 -13
  5. package/lib/assert/empty.js +20 -21
  6. package/lib/assert/equal.js +37 -39
  7. package/lib/assert/error.js +14 -14
  8. package/lib/assert/include.js +46 -47
  9. package/lib/assert/throws.js +13 -11
  10. package/lib/assert/truth.js +19 -22
  11. package/lib/assert.js +4 -2
  12. package/lib/cli.js +56 -49
  13. package/lib/codecept.js +145 -155
  14. package/lib/colorUtils.js +3 -3
  15. package/lib/command/configMigrate.js +58 -52
  16. package/lib/command/definitions.js +88 -89
  17. package/lib/command/dryRun.js +79 -81
  18. package/lib/command/generate.js +197 -188
  19. package/lib/command/gherkin/init.js +27 -16
  20. package/lib/command/gherkin/snippets.js +21 -21
  21. package/lib/command/gherkin/steps.js +8 -8
  22. package/lib/command/info.js +40 -38
  23. package/lib/command/init.js +290 -288
  24. package/lib/command/interactive.js +32 -32
  25. package/lib/command/list.js +26 -26
  26. package/lib/command/run-multiple/chunk.js +5 -5
  27. package/lib/command/run-multiple/collection.js +3 -3
  28. package/lib/command/run-multiple/run.js +6 -2
  29. package/lib/command/run-multiple.js +113 -93
  30. package/lib/command/run-rerun.js +20 -25
  31. package/lib/command/run-workers.js +64 -66
  32. package/lib/command/run.js +26 -29
  33. package/lib/command/utils.js +80 -65
  34. package/lib/command/workers/runTests.js +11 -12
  35. package/lib/config.js +10 -9
  36. package/lib/container.js +40 -48
  37. package/lib/data/context.js +60 -59
  38. package/lib/data/dataScenarioConfig.js +47 -47
  39. package/lib/data/dataTableArgument.js +29 -29
  40. package/lib/data/table.js +26 -20
  41. package/lib/event.js +163 -167
  42. package/lib/heal.js +14 -18
  43. package/lib/helper/AI.js +130 -41
  44. package/lib/helper/ApiDataFactory.js +74 -70
  45. package/lib/helper/Appium.js +416 -388
  46. package/lib/helper/ExpectHelper.js +40 -48
  47. package/lib/helper/FileSystem.js +80 -79
  48. package/lib/helper/GraphQL.js +44 -43
  49. package/lib/helper/GraphQLDataFactory.js +51 -51
  50. package/lib/helper/JSONResponse.js +65 -62
  51. package/lib/helper/Mochawesome.js +28 -28
  52. package/lib/helper/Nightmare.js +664 -571
  53. package/lib/helper/Playwright.js +1367 -1222
  54. package/lib/helper/Protractor.js +663 -635
  55. package/lib/helper/Puppeteer.js +1232 -1132
  56. package/lib/helper/REST.js +183 -68
  57. package/lib/helper/SoftExpectHelper.js +2 -2
  58. package/lib/helper/TestCafe.js +490 -486
  59. package/lib/helper/WebDriver.js +1246 -1297
  60. package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
  61. package/lib/helper/errors/ConnectionRefused.js +1 -1
  62. package/lib/helper/errors/ElementAssertion.js +2 -2
  63. package/lib/helper/errors/ElementNotFound.js +2 -2
  64. package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
  65. package/lib/helper/extras/Console.js +1 -1
  66. package/lib/helper/extras/PlaywrightPropEngine.js +4 -4
  67. package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
  68. package/lib/helper/extras/PlaywrightRestartOpts.js +21 -18
  69. package/lib/helper/extras/Popup.js +1 -1
  70. package/lib/helper/extras/React.js +3 -3
  71. package/lib/helper/network/actions.js +14 -7
  72. package/lib/helper/network/utils.js +4 -3
  73. package/lib/helper/scripts/blurElement.js +1 -1
  74. package/lib/helper/scripts/focusElement.js +1 -1
  75. package/lib/helper/scripts/highlightElement.js +1 -1
  76. package/lib/helper/scripts/isElementClickable.js +1 -1
  77. package/lib/helper/testcafe/testControllerHolder.js +1 -1
  78. package/lib/helper/testcafe/testcafe-utils.js +7 -8
  79. package/lib/helper.js +1 -3
  80. package/lib/history.js +6 -5
  81. package/lib/hooks.js +6 -6
  82. package/lib/html.js +7 -7
  83. package/lib/index.js +25 -41
  84. package/lib/interfaces/bdd.js +47 -64
  85. package/lib/interfaces/featureConfig.js +19 -19
  86. package/lib/interfaces/gherkin.js +124 -118
  87. package/lib/interfaces/scenarioConfig.js +29 -29
  88. package/lib/listener/artifacts.js +9 -9
  89. package/lib/listener/config.js +24 -24
  90. package/lib/listener/exit.js +12 -12
  91. package/lib/listener/helpers.js +42 -42
  92. package/lib/listener/mocha.js +11 -11
  93. package/lib/listener/retry.js +32 -30
  94. package/lib/listener/steps.js +50 -53
  95. package/lib/listener/timeout.js +54 -54
  96. package/lib/locator.js +7 -11
  97. package/lib/mochaFactory.js +18 -15
  98. package/lib/output.js +19 -15
  99. package/lib/parser.js +15 -12
  100. package/lib/pause.js +45 -38
  101. package/lib/plugin/allure.js +15 -15
  102. package/lib/plugin/autoDelay.js +29 -37
  103. package/lib/plugin/autoLogin.js +70 -65
  104. package/lib/plugin/commentStep.js +18 -18
  105. package/lib/plugin/coverage.js +112 -67
  106. package/lib/plugin/customLocator.js +21 -20
  107. package/lib/plugin/debugErrors.js +24 -24
  108. package/lib/plugin/eachElement.js +38 -38
  109. package/lib/plugin/fakerTransform.js +6 -6
  110. package/lib/plugin/heal.js +67 -108
  111. package/lib/plugin/pauseOnFail.js +11 -11
  112. package/lib/plugin/retryFailedStep.js +32 -39
  113. package/lib/plugin/retryTo.js +46 -40
  114. package/lib/plugin/screenshotOnFail.js +109 -87
  115. package/lib/plugin/selenoid.js +131 -118
  116. package/lib/plugin/standardActingHelpers.js +2 -8
  117. package/lib/plugin/stepByStepReport.js +110 -91
  118. package/lib/plugin/stepTimeout.js +24 -23
  119. package/lib/plugin/subtitles.js +34 -35
  120. package/lib/plugin/tryTo.js +40 -30
  121. package/lib/plugin/wdio.js +78 -75
  122. package/lib/recorder.js +14 -17
  123. package/lib/rerun.js +11 -10
  124. package/lib/scenario.js +25 -23
  125. package/lib/secret.js +4 -3
  126. package/lib/session.js +10 -10
  127. package/lib/step.js +12 -9
  128. package/lib/store.js +2 -3
  129. package/lib/transform.js +1 -1
  130. package/lib/translation.js +7 -8
  131. package/lib/ui.js +12 -14
  132. package/lib/utils.js +70 -72
  133. package/lib/within.js +10 -10
  134. package/lib/workerStorage.js +27 -25
  135. package/lib/workers.js +29 -33
  136. package/package.json +67 -68
  137. package/translations/de-DE.js +2 -1
  138. package/translations/fr-FR.js +2 -2
  139. package/translations/index.js +9 -13
  140. package/translations/it-IT.js +1 -1
  141. package/translations/ja-JP.js +1 -1
  142. package/translations/pl-PL.js +1 -1
  143. package/translations/pt-BR.js +1 -1
  144. package/translations/ru-RU.js +1 -1
  145. package/translations/zh-CN.js +1 -1
  146. package/translations/zh-TW.js +1 -1
  147. package/typings/index.d.ts +423 -65
  148. package/typings/promiseBasedTypes.d.ts +41 -172
  149. package/typings/types.d.ts +43 -178
  150. package/lib/dirname.js +0 -5
  151. package/lib/helper/Expect.js +0 -425
  152. package/lib/helper/MockServer.js +0 -223
@@ -1,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,152 @@ 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
+ const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)')
1053
+ return v ? v[2] : null
1054
+ },
1055
+ { dependencies: { name } },
1056
+ ).with({ boundTestRun: this.t })
1057
+ const value = await getCookie()
1058
+ if (value) return { name, value }
1071
1059
  }
1072
1060
 
1073
1061
  /**
1074
1062
  * {{> clearCookie }}
1075
1063
  */
1076
1064
  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`;
1065
+ const clearCookies = ClientFunction(
1066
+ () => {
1067
+ const cookies = document.cookie.split(';')
1068
+
1069
+ for (let i = 0; i < cookies.length; i++) {
1070
+ const cookie = cookies[i]
1071
+ const eqPos = cookie.indexOf('=')
1072
+ const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie
1073
+ if (cookieName === undefined || name === cookieName) {
1074
+ document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`
1075
+ }
1086
1076
  }
1087
- }
1088
- }, { dependencies: { cookieName } }).with({ boundTestRun: this.t });
1077
+ },
1078
+ { dependencies: { cookieName } },
1079
+ ).with({ boundTestRun: this.t })
1089
1080
 
1090
- return clearCookies();
1081
+ return clearCookies()
1091
1082
  }
1092
1083
 
1093
1084
  /**
1094
1085
  * {{> waitInUrl }}
1095
1086
  */
1096
1087
  async waitInUrl(urlPart, sec = null) {
1097
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1088
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1098
1089
 
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 });
1090
+ const clientFn = createClientFunction(
1091
+ (urlPart) => {
1092
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
1093
+ return currUrl.indexOf(urlPart) > -1
1094
+ },
1095
+ [urlPart],
1096
+ ).with({ boundTestRun: this.t })
1103
1097
 
1104
1098
  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
- });
1099
+ const currUrl = await this.grabCurrentUrl()
1100
+ throw new Error(`expected url to include ${urlPart}, but found ${currUrl}`)
1101
+ })
1108
1102
  }
1109
1103
 
1110
1104
  /**
1111
1105
  * {{> waitUrlEquals }}
1112
1106
  */
1113
1107
  async waitUrlEquals(urlPart, sec = null) {
1114
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1108
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1115
1109
 
1116
- const baseUrl = this.options.url;
1110
+ const baseUrl = this.options.url
1117
1111
  if (urlPart.indexOf('http') < 0) {
1118
- urlPart = baseUrl + urlPart;
1112
+ urlPart = baseUrl + urlPart
1119
1113
  }
1120
1114
 
1121
- const clientFn = createClientFunction((urlPart) => {
1122
- const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)));
1123
- return currUrl === urlPart;
1124
- }, [urlPart]).with({ boundTestRun: this.t });
1115
+ const clientFn = createClientFunction(
1116
+ (urlPart) => {
1117
+ const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
1118
+ return currUrl === urlPart
1119
+ },
1120
+ [urlPart],
1121
+ ).with({ boundTestRun: this.t })
1125
1122
 
1126
1123
  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
- });
1124
+ const currUrl = await this.grabCurrentUrl()
1125
+ throw new Error(`expected url to be ${urlPart}, but found ${currUrl}`)
1126
+ })
1130
1127
  }
1131
1128
 
1132
1129
  /**
1133
1130
  * {{> waitForFunction }}
1134
1131
  */
1135
1132
  async waitForFunction(fn, argsOrSec = null, sec = null) {
1136
- let args = [];
1133
+ let args = []
1137
1134
  if (argsOrSec) {
1138
1135
  if (Array.isArray(argsOrSec)) {
1139
- args = argsOrSec;
1136
+ args = argsOrSec
1140
1137
  } else if (typeof argsOrSec === 'number') {
1141
- sec = argsOrSec;
1138
+ sec = argsOrSec
1142
1139
  }
1143
1140
  }
1144
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1141
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1145
1142
 
1146
- const clientFn = createClientFunction(fn, args).with({ boundTestRun: this.t });
1143
+ const clientFn = createClientFunction(fn, args).with({ boundTestRun: this.t })
1147
1144
 
1148
- return waitForFunction(clientFn, waitTimeout);
1145
+ return waitForFunction(clientFn, waitTimeout)
1149
1146
  }
1150
1147
 
1151
1148
  /**
1152
1149
  * {{> waitNumberOfVisibleElements }}
1153
1150
  */
1154
1151
  async waitNumberOfVisibleElements(locator, num, sec) {
1155
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1152
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1156
1153
 
1157
1154
  return this.t
1158
1155
  .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);
1156
+ .eql(num, `The number of elements (${new Locator(locator)}) is not ${num} after ${sec} sec`, {
1157
+ timeout: waitTimeout,
1158
+ })
1159
+ .catch(mapError)
1161
1160
  }
1162
1161
 
1163
1162
  /**
1164
1163
  * {{> waitForElement }}
1165
1164
  */
1166
1165
  async waitForElement(locator, sec) {
1167
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1166
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1168
1167
 
1169
- return this.t
1170
- .expect(createSelector(locator).with({ boundTestRun: this.t }).exists)
1171
- .ok({ timeout: waitTimeout });
1168
+ return this.t.expect(createSelector(locator).with({ boundTestRun: this.t }).exists).ok({ timeout: waitTimeout })
1172
1169
  }
1173
1170
 
1174
1171
  /**
1175
1172
  * {{> waitToHide }}
1176
1173
  */
1177
1174
  async waitToHide(locator, sec) {
1178
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1175
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1179
1176
 
1180
1177
  return this.t
1181
1178
  .expect(createSelector(locator).filterHidden().with({ boundTestRun: this.t }).exists)
1182
- .notOk({ timeout: waitTimeout });
1179
+ .notOk({ timeout: waitTimeout })
1183
1180
  }
1184
1181
 
1185
1182
  /**
1186
1183
  * {{> waitForInvisible }}
1187
1184
  */
1188
1185
  async waitForInvisible(locator, sec) {
1189
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1186
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1190
1187
 
1191
1188
  return this.t
1192
1189
  .expect(createSelector(locator).filterVisible().with({ boundTestRun: this.t }).exists)
1193
- .ok({ timeout: waitTimeout });
1190
+ .ok({ timeout: waitTimeout })
1194
1191
  }
1195
1192
 
1196
1193
  /**
@@ -1198,213 +1195,220 @@ class TestCafe extends Helper {
1198
1195
  *
1199
1196
  */
1200
1197
  async waitForText(text, sec = null, context = null) {
1201
- const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1198
+ const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
1202
1199
 
1203
- let els;
1200
+ let els
1204
1201
  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 });
1202
+ els = await findElements.call(this, this.context, context)
1203
+ await this.t.expect(els.exists).ok(`Context element ${context} not found`, { timeout: waitTimeout })
1209
1204
  } else {
1210
- els = (await findElements.call(this, this.context, '*'));
1205
+ els = await findElements.call(this, this.context, '*')
1211
1206
  }
1212
1207
 
1213
1208
  return this.t
1214
1209
  .expect(els.withText(text).filterVisible().exists)
1215
1210
  .ok(`No element with text "${text}" found in ${context || 'body'}`, { timeout: waitTimeout })
1216
- .catch(mapError);
1211
+ .catch(mapError)
1217
1212
  }
1218
1213
  }
1219
1214
 
1220
1215
  async function waitForFunction(browserFn, waitTimeout) {
1221
- const pause = () => new Promise((done => {
1222
- setTimeout(done, 50);
1223
- }));
1216
+ const pause = () =>
1217
+ new Promise((done) => {
1218
+ setTimeout(done, 50)
1219
+ })
1220
+
1221
+ const start = Date.now()
1224
1222
 
1225
- const start = Date.now();
1226
- // eslint-disable-next-line no-constant-condition
1227
1223
  while (true) {
1228
- let result;
1224
+ let result
1229
1225
  try {
1230
- result = await browserFn();
1231
- // eslint-disable-next-line no-empty
1226
+ result = await browserFn()
1232
1227
  } catch (err) {
1233
- throw new Error(`Error running function ${err.toString()}`);
1228
+ throw new Error(`Error running function ${err.toString()}`)
1234
1229
  }
1235
1230
 
1236
- if (result) return result;
1231
+ if (result) return result
1237
1232
 
1238
- const duration = (Date.now() - start);
1233
+ const duration = Date.now() - start
1239
1234
  if (duration > waitTimeout) {
1240
- throw new Error('waitForFunction timed out');
1235
+ throw new Error('waitForFunction timed out')
1241
1236
  }
1242
- await pause(); // make polling
1237
+ await pause() // make polling
1243
1238
  }
1244
1239
  }
1245
1240
 
1246
1241
  const createSelector = (locator) => {
1247
- locator = new Locator(locator, 'css');
1248
- if (locator.isXPath()) return elementByXPath(locator.value);
1249
- return Selector(locator.simplify());
1250
- };
1242
+ locator = new Locator(locator, 'css')
1243
+ if (locator.isXPath()) return elementByXPath(locator.value)
1244
+ return Selector(locator.simplify())
1245
+ }
1251
1246
 
1252
1247
  const elementByXPath = (xpath) => {
1253
- assert(xpath, 'xpath is required');
1248
+ assert(xpath, 'xpath is required')
1254
1249
 
1255
- return Selector(() => {
1256
- const iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
1257
- const items = [];
1250
+ return Selector(
1251
+ () => {
1252
+ const iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null)
1253
+ const items = []
1258
1254
 
1259
- let item = iterator.iterateNext();
1255
+ let item = iterator.iterateNext()
1260
1256
 
1261
- while (item) {
1262
- items.push(item);
1263
- item = iterator.iterateNext();
1264
- }
1257
+ while (item) {
1258
+ items.push(item)
1259
+ item = iterator.iterateNext()
1260
+ }
1265
1261
 
1266
- return items;
1267
- }, { dependencies: { xpath } });
1268
- };
1262
+ return items
1263
+ },
1264
+ { dependencies: { xpath } },
1265
+ )
1266
+ }
1269
1267
 
1270
1268
  const assertElementExists = async (res, locator, prefix, suffix) => {
1271
1269
  if (!res || !(await res.count) || !(await res.nth(0).tagName)) {
1272
- throw new ElementNotFound(locator, prefix, suffix);
1270
+ throw new ElementNotFound(locator, prefix, suffix)
1273
1271
  }
1274
- };
1272
+ }
1275
1273
 
1276
1274
  async function findElements(matcher, locator) {
1277
- if (locator && locator.react) throw new Error('react locators are not yet supported');
1275
+ if (locator && locator.react) throw new Error('react locators are not yet supported')
1278
1276
 
1279
- locator = new Locator(locator, 'css');
1277
+ locator = new Locator(locator, 'css')
1280
1278
 
1281
1279
  if (!locator.isXPath()) {
1282
1280
  return matcher
1283
1281
  ? matcher.find(locator.simplify())
1284
- : Selector(locator.simplify()).with({ timeout: 0, boundTestRun: this.t });
1282
+ : Selector(locator.simplify()).with({ timeout: 0, boundTestRun: this.t })
1285
1283
  }
1286
1284
 
1287
- if (!matcher) return elementByXPath(locator.value).with({ timeout: 0, boundTestRun: this.t });
1285
+ if (!matcher) return elementByXPath(locator.value).with({ timeout: 0, boundTestRun: this.t })
1288
1286
 
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 });
1287
+ return matcher.find(
1288
+ (node, idx, originNode) => {
1289
+ const found = document.evaluate(xpath, originNode, null, 5, null)
1290
+ let current = null
1291
+ while ((current = found.iterateNext())) {
1292
+ if (current === node) return true
1293
+ }
1294
+ return false
1295
+ },
1296
+ { xpath: locator.value },
1297
+ )
1297
1298
  }
1298
1299
 
1299
1300
  async function proceedClick(locator, context = null) {
1300
- let matcher;
1301
+ let matcher
1301
1302
 
1302
1303
  if (context) {
1303
- const els = await this._locate(context);
1304
- await assertElementExists(els, context);
1305
- matcher = await els.nth(0);
1304
+ const els = await this._locate(context)
1305
+ await assertElementExists(els, context)
1306
+ matcher = await els.nth(0)
1306
1307
  }
1307
1308
 
1308
- const els = await findClickable.call(this, matcher, locator);
1309
+ const els = await findClickable.call(this, matcher, locator)
1309
1310
  if (context) {
1310
- await assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`);
1311
+ await assertElementExists(
1312
+ els,
1313
+ locator,
1314
+ 'Clickable element',
1315
+ `was not found inside element ${new Locator(context).toString()}`,
1316
+ )
1311
1317
  } else {
1312
- await assertElementExists(els, locator, 'Clickable element');
1318
+ await assertElementExists(els, locator, 'Clickable element')
1313
1319
  }
1314
1320
 
1315
- const firstElement = await els.filterVisible().nth(0);
1321
+ const firstElement = await els.filterVisible().nth(0)
1316
1322
 
1317
- return this.t
1318
- .click(firstElement)
1319
- .catch(mapError);
1323
+ return this.t.click(firstElement).catch(mapError)
1320
1324
  }
1321
1325
 
1322
1326
  async function findClickable(matcher, locator) {
1323
- if (locator && locator.react) throw new Error('react locators are not yet supported');
1327
+ if (locator && locator.react) throw new Error('react locators are not yet supported')
1324
1328
 
1325
- locator = new Locator(locator);
1326
- if (!locator.isFuzzy()) return (await findElements.call(this, matcher, locator)).filterVisible();
1329
+ locator = new Locator(locator)
1330
+ if (!locator.isFuzzy()) return (await findElements.call(this, matcher, locator)).filterVisible()
1327
1331
 
1328
- let els;
1332
+ let els
1329
1333
 
1330
1334
  // 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;
1335
+ els = matcher ? matcher.find('a,button') : createSelector('a,button')
1336
+ els = await els.withExactText(locator.value).with({ timeout: 0, boundTestRun: this.t })
1337
+ if (await els.count) return els
1334
1338
 
1335
- const literal = xpathLocator.literal(locator.value);
1339
+ const literal = xpathLocator.literal(locator.value)
1336
1340
 
1337
- els = (await findElements.call(this, matcher, Locator.clickable.narrow(literal))).filterVisible();
1338
- if (await els.count) return els;
1341
+ els = (await findElements.call(this, matcher, Locator.clickable.narrow(literal))).filterVisible()
1342
+ if (await els.count) return els
1339
1343
 
1340
- els = (await findElements.call(this, matcher, Locator.clickable.wide(literal))).filterVisible();
1341
- if (await els.count) return els;
1344
+ els = (await findElements.call(this, matcher, Locator.clickable.wide(literal))).filterVisible()
1345
+ if (await els.count) return els
1342
1346
 
1343
- els = (await findElements.call(this, matcher, Locator.clickable.self(literal))).filterVisible();
1344
- if (await els.count) return els;
1347
+ els = (await findElements.call(this, matcher, Locator.clickable.self(literal))).filterVisible()
1348
+ if (await els.count) return els
1345
1349
 
1346
- return findElements.call(this, matcher, locator.value); // by css or xpath
1350
+ return findElements.call(this, matcher, locator.value) // by css or xpath
1347
1351
  }
1348
1352
 
1349
1353
  async function proceedIsChecked(assertType, option) {
1350
- const els = await findCheckable.call(this, option);
1351
- assertElementExists(els, option, 'Checkable');
1354
+ const els = await findCheckable.call(this, option)
1355
+ assertElementExists(els, option, 'Checkable')
1352
1356
 
1353
- const selected = await els.checked;
1357
+ const selected = await els.checked
1354
1358
 
1355
- return truth(`checkable ${option}`, 'to be checked')[assertType](selected);
1359
+ return truth(`checkable ${option}`, 'to be checked')[assertType](selected)
1356
1360
  }
1357
1361
 
1358
1362
  async function findCheckable(locator, context) {
1359
- assert(locator, 'locator is required');
1360
- assert(this.t, 'this.t is required');
1363
+ assert(locator, 'locator is required')
1364
+ assert(this.t, 'this.t is required')
1361
1365
 
1362
- let contextEl = await this.context;
1366
+ let contextEl = await this.context
1363
1367
  if (typeof context === 'string') {
1364
- contextEl = (await findElements.call(this, contextEl, (new Locator(context, 'css')).simplify())).filterVisible();
1365
- contextEl = await contextEl.nth(0);
1368
+ contextEl = (await findElements.call(this, contextEl, new Locator(context, 'css').simplify())).filterVisible()
1369
+ contextEl = await contextEl.nth(0)
1366
1370
  }
1367
1371
 
1368
- const matchedLocator = new Locator(locator);
1372
+ const matchedLocator = new Locator(locator)
1369
1373
  if (!matchedLocator.isFuzzy()) {
1370
- return (await findElements.call(this, contextEl, matchedLocator.simplify())).filterVisible();
1374
+ return (await findElements.call(this, contextEl, matchedLocator.simplify())).filterVisible()
1371
1375
  }
1372
1376
 
1373
- const literal = xpathLocator.literal(locator);
1374
- let els = (await findElements.call(this, contextEl, Locator.checkable.byText(literal))).filterVisible();
1377
+ const literal = xpathLocator.literal(locator)
1378
+ let els = (await findElements.call(this, contextEl, Locator.checkable.byText(literal))).filterVisible()
1375
1379
  if (await els.count) {
1376
- return els;
1380
+ return els
1377
1381
  }
1378
1382
 
1379
- els = (await findElements.call(this, contextEl, Locator.checkable.byName(literal))).filterVisible();
1383
+ els = (await findElements.call(this, contextEl, Locator.checkable.byName(literal))).filterVisible()
1380
1384
  if (await els.count) {
1381
- return els;
1385
+ return els
1382
1386
  }
1383
1387
 
1384
- return (await findElements.call(this, contextEl, locator)).filterVisible();
1388
+ return (await findElements.call(this, contextEl, locator)).filterVisible()
1385
1389
  }
1386
1390
 
1387
1391
  async function findFields(locator) {
1388
- const matchedLocator = new Locator(locator);
1392
+ const matchedLocator = new Locator(locator)
1389
1393
  if (!matchedLocator.isFuzzy()) {
1390
- return this._locate(matchedLocator);
1394
+ return this._locate(matchedLocator)
1391
1395
  }
1392
- const literal = xpathLocator.literal(locator);
1396
+ const literal = xpathLocator.literal(locator)
1393
1397
 
1394
- let els = await this._locate({ xpath: Locator.field.labelEquals(literal) });
1398
+ let els = await this._locate({ xpath: Locator.field.labelEquals(literal) })
1395
1399
  if (await els.count) {
1396
- return els;
1400
+ return els
1397
1401
  }
1398
1402
 
1399
- els = await this._locate({ xpath: Locator.field.labelContains(literal) });
1403
+ els = await this._locate({ xpath: Locator.field.labelContains(literal) })
1400
1404
  if (await els.count) {
1401
- return els;
1405
+ return els
1402
1406
  }
1403
- els = await this._locate({ xpath: Locator.field.byName(literal) });
1407
+ els = await this._locate({ xpath: Locator.field.byName(literal) })
1404
1408
  if (await els.count) {
1405
- return els;
1409
+ return els
1406
1410
  }
1407
- return this._locate({ css: locator });
1411
+ return this._locate({ css: locator })
1408
1412
  }
1409
1413
 
1410
- export default TestCafe;
1414
+ module.exports = TestCafe