codeceptjs 3.3.8-beta.1 → 3.4.0

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 (72) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +31 -32
  3. package/docs/advanced.md +48 -24
  4. package/docs/basics.md +115 -40
  5. package/docs/best.md +2 -2
  6. package/docs/build/ApiDataFactory.js +14 -9
  7. package/docs/build/Appium.js +2 -19
  8. package/docs/build/FileSystem.js +3 -3
  9. package/docs/build/GraphQL.js +1 -1
  10. package/docs/build/GraphQLDataFactory.js +3 -3
  11. package/docs/build/JSONResponse.js +1 -1
  12. package/docs/build/Mochawesome.js +1 -1
  13. package/docs/build/Nightmare.js +1 -1
  14. package/docs/build/Playwright.js +4 -3
  15. package/docs/build/Protractor.js +1 -1
  16. package/docs/build/Puppeteer.js +1 -1
  17. package/docs/build/REST.js +1 -1
  18. package/docs/build/TestCafe.js +5 -5
  19. package/docs/build/WebDriver.js +30 -165
  20. package/docs/changelog.md +49 -2
  21. package/docs/helpers/ApiDataFactory.md +6 -6
  22. package/docs/helpers/FileSystem.md +2 -2
  23. package/docs/helpers/GraphQLDataFactory.md +2 -2
  24. package/docs/helpers/Playwright.md +2 -1
  25. package/docs/index.md +1 -1
  26. package/docs/plugins.md +42 -125
  27. package/docs/reports.md +0 -56
  28. package/docs/tutorial.md +271 -0
  29. package/docs/typescript.md +2 -8
  30. package/lib/actor.js +2 -1
  31. package/lib/cli.js +3 -3
  32. package/lib/codecept.js +2 -1
  33. package/lib/command/generate.js +3 -1
  34. package/lib/command/gherkin/snippets.js +8 -4
  35. package/lib/command/init.js +0 -8
  36. package/lib/command/run-workers.js +3 -6
  37. package/lib/command/utils.js +0 -10
  38. package/lib/command/workers/runTests.js +2 -2
  39. package/lib/config.js +5 -1
  40. package/lib/helper/ApiDataFactory.js +14 -9
  41. package/lib/helper/Appium.js +2 -19
  42. package/lib/helper/FileSystem.js +3 -3
  43. package/lib/helper/GraphQL.js +1 -1
  44. package/lib/helper/GraphQLDataFactory.js +3 -3
  45. package/lib/helper/JSONResponse.js +1 -1
  46. package/lib/helper/Mochawesome.js +1 -1
  47. package/lib/helper/Nightmare.js +1 -1
  48. package/lib/helper/Playwright.js +4 -3
  49. package/lib/helper/Protractor.js +1 -1
  50. package/lib/helper/Puppeteer.js +1 -1
  51. package/lib/helper/REST.js +1 -1
  52. package/lib/helper/TestCafe.js +5 -5
  53. package/lib/helper/WebDriver.js +30 -165
  54. package/lib/helper.js +0 -2
  55. package/lib/interfaces/bdd.js +1 -1
  56. package/lib/interfaces/featureConfig.js +1 -0
  57. package/lib/interfaces/gherkin.js +38 -25
  58. package/lib/listener/exit.js +2 -2
  59. package/lib/listener/retry.js +67 -0
  60. package/lib/listener/steps.js +1 -1
  61. package/lib/listener/timeout.js +47 -10
  62. package/lib/mochaFactory.js +3 -3
  63. package/lib/plugin/allure.js +14 -323
  64. package/lib/plugin/fakerTransform.js +2 -2
  65. package/lib/recorder.js +1 -1
  66. package/lib/scenario.js +25 -18
  67. package/lib/utils.js +6 -0
  68. package/lib/workers.js +4 -7
  69. package/package.json +14 -18
  70. package/typings/index.d.ts +76 -1
  71. package/typings/promiseBasedTypes.d.ts +12 -12
  72. package/typings/types.d.ts +95 -262
package/lib/cli.js CHANGED
@@ -40,7 +40,7 @@ class Cli extends Base {
40
40
 
41
41
  runner.on('fail', (test) => {
42
42
  if (test.ctx.currentTest) {
43
- this.loadedTests.push(test.ctx.currentTest.id);
43
+ this.loadedTests.push(test.ctx.currentTest.uid);
44
44
  }
45
45
  if (showSteps && test.steps) {
46
46
  return output.scenario.failed(test);
@@ -57,7 +57,7 @@ class Cli extends Base {
57
57
  } else {
58
58
  skipTestConfig(test, null);
59
59
  }
60
- this.loadedTests.push(test.id);
60
+ this.loadedTests.push(test.uid);
61
61
  cursor.CR();
62
62
  output.test.skipped(test);
63
63
  });
@@ -111,7 +111,7 @@ class Cli extends Base {
111
111
  let skippedCount = 0;
112
112
  const grep = runner._grep;
113
113
  for (const test of suite.tests) {
114
- if (!test.state && !this.loadedTests.includes(test.id)) {
114
+ if (!test.state && !this.loadedTests.includes(test.uid)) {
115
115
  if (matchTest(grep, test.title)) {
116
116
  if (!test.opts) {
117
117
  test.opts = {};
package/lib/codecept.js CHANGED
@@ -67,8 +67,8 @@ class Codecept {
67
67
  global.output_dir = fsPath.resolve(dir, this.config.output);
68
68
 
69
69
  if (!this.config.noGlobals) {
70
+ global.Helper = global.codecept_helper = require('@codeceptjs/helper');
70
71
  global.actor = global.codecept_actor = require('./actor');
71
- global.Helper = global.codecept_helper = require('./helper');
72
72
  global.pause = require('./pause');
73
73
  global.within = require('./within');
74
74
  global.session = require('./session');
@@ -98,6 +98,7 @@ class Codecept {
98
98
  runHook(require('./listener/artifacts'));
99
99
  runHook(require('./listener/config'));
100
100
  runHook(require('./listener/helpers'));
101
+ runHook(require('./listener/retry'));
101
102
  runHook(require('./listener/timeout'));
102
103
  runHook(require('./listener/exit'));
103
104
 
@@ -128,7 +128,9 @@ module.exports.pageObject = function (genPath, opts) {
128
128
  const name = lcfirst(result.name) + ucfirst(kind);
129
129
  let data = readConfig(configFile);
130
130
  config.include[name] = result.filename;
131
- data = data.replace(/include[\s\S][^\}]*/i, `include: ${JSON.stringify(config.include).slice(0, -1)}`);
131
+ const currentInclude = `${data.match(/include:[\s\S][^\}]*/i)[0]}\n ${name}:${JSON.stringify(config.include[name])}`;
132
+
133
+ data = data.replace(/include:[\s\S][^\}]*/i, `${currentInclude}`);
132
134
 
133
135
  fs.writeFileSync(configFile, beautify(data), 'utf-8');
134
136
 
@@ -1,6 +1,7 @@
1
1
  const escapeStringRegexp = require('escape-string-regexp');
2
2
  const fs = require('fs');
3
- const { Parser } = require('gherkin');
3
+ const Gherkin = require('@cucumber/gherkin');
4
+ const Messages = require('@cucumber/messages');
4
5
  const glob = require('glob');
5
6
  const fsPath = require('path');
6
7
 
@@ -9,7 +10,10 @@ const Codecept = require('../../codecept');
9
10
  const output = require('../../output');
10
11
  const { matchStep } = require('../../interfaces/bdd');
11
12
 
12
- const parser = new Parser();
13
+ const uuidFn = Messages.IdGenerator.uuid();
14
+ const builder = new Gherkin.AstBuilder(uuidFn);
15
+ const matcher = new Gherkin.GherkinClassicTokenMatcher();
16
+ const parser = new Gherkin.Parser(builder, matcher);
13
17
  parser.stopAtFirstError = false;
14
18
 
15
19
  module.exports = function (genPath, options) {
@@ -85,8 +89,8 @@ module.exports = function (genPath, options) {
85
89
  const parseFile = (file) => {
86
90
  const ast = parser.parse(fs.readFileSync(file).toString());
87
91
  for (const child of ast.feature.children) {
88
- if (child.type === 'ScenarioOutline') continue; // skip scenario outline
89
- parseSteps(child.steps).map((step) => {
92
+ if (child.scenario.keyword === 'Scenario Outline') continue; // skip scenario outline
93
+ parseSteps(child.scenario.steps).map((step) => {
90
94
  return Object.assign(step, { file: file.replace(global.codecept_dir, '').slice(1) });
91
95
  }).map((step) => newSteps.set(`${step.type}(${step})`, step));
92
96
  }
@@ -126,13 +126,6 @@ module.exports = function (initPath) {
126
126
  default: './output',
127
127
  message: 'Where should logs, screenshots, and reports to be stored?',
128
128
  },
129
- {
130
- name: 'promise',
131
- type: 'confirm',
132
- default: false,
133
- message: 'Would you prefer to use promise-based typings for all I.* commands? http://bit.ly/3XIMq6n',
134
- when: (answers) => answers.typescript,
135
- },
136
129
  {
137
130
  name: 'translation',
138
131
  type: 'list',
@@ -155,7 +148,6 @@ module.exports = function (initPath) {
155
148
  config.tests = result.tests;
156
149
  if (isTypeScript) {
157
150
  config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`;
158
- config.fullPromiseBased = result.promise;
159
151
  }
160
152
 
161
153
  // create a directory tests if it is included in tests path
@@ -1,16 +1,10 @@
1
1
  // For Node version >=10.5.0, have to use experimental flag
2
- const { satisfyNodeVersion } = require('./utils');
3
2
  const { tryOrDefault } = require('../utils');
4
3
  const output = require('../output');
5
4
  const event = require('../event');
6
5
  const Workers = require('../workers');
7
6
 
8
7
  module.exports = async function (workerCount, options) {
9
- satisfyNodeVersion(
10
- '>=11.7.0',
11
- 'Required minimum Node version of 11.7.0 to work with "run-workers"',
12
- );
13
-
14
8
  process.env.profile = options.profile;
15
9
 
16
10
  const { config: testConfig, override = '' } = options;
@@ -46,6 +40,9 @@ module.exports = async function (workerCount, options) {
46
40
  try {
47
41
  await workers.bootstrapAll();
48
42
  await workers.run();
43
+ } catch (err) {
44
+ output.error(err);
45
+ process.exit(1);
49
46
  } finally {
50
47
  await workers.teardownAll();
51
48
  }
@@ -1,6 +1,5 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const semver = require('semver');
4
3
  const util = require('util');
5
4
  const mkdirp = require('mkdirp');
6
5
 
@@ -71,15 +70,6 @@ function safeFileWrite(file, contents) {
71
70
 
72
71
  module.exports.safeFileWrite = safeFileWrite;
73
72
 
74
- module.exports.satisfyNodeVersion = (
75
- version,
76
- failureMessage = `Required Node version: ${version}`,
77
- ) => {
78
- if (!semver.satisfies(process.version, version)) {
79
- fail(failureMessage);
80
- }
81
- };
82
-
83
73
  module.exports.captureStream = (stream) => {
84
74
  let oldStream;
85
75
  let buffer = '';
@@ -68,7 +68,7 @@ function filterTests() {
68
68
  mocha.loadFiles();
69
69
 
70
70
  for (const suite of mocha.suite.suites) {
71
- suite.tests = suite.tests.filter(test => tests.indexOf(test.id) >= 0);
71
+ suite.tests = suite.tests.filter(test => tests.indexOf(test.uid) >= 0);
72
72
  }
73
73
  }
74
74
 
@@ -124,7 +124,7 @@ function initializeListeners() {
124
124
  return {
125
125
  opts: test.opts || {},
126
126
  tags: test.tags || [],
127
- id: test.id,
127
+ uid: test.uid,
128
128
  workerIndex,
129
129
  retries: test._retries,
130
130
  title: test.title,
package/lib/config.js CHANGED
@@ -79,7 +79,11 @@ class Config {
79
79
  configFile = path.resolve(configFile || '.');
80
80
 
81
81
  if (!fileExists(configFile)) {
82
- throw new Error(`Config file ${configFile} does not exist. Execute 'codeceptjs init' to create config`);
82
+ configFile = configFile.replace('.js', '.ts');
83
+
84
+ if (!fileExists(configFile)) {
85
+ throw new Error(`Config file ${configFile} does not exist. Execute 'codeceptjs init' to create config`);
86
+ }
83
87
  }
84
88
 
85
89
  // is config file
@@ -1,6 +1,6 @@
1
1
  const path = require('path');
2
2
 
3
- const Helper = require('../helper');
3
+ const Helper = require('@codeceptjs/helper');
4
4
  const REST = require('./REST');
5
5
 
6
6
  /**
@@ -46,8 +46,8 @@ const REST = require('./REST');
46
46
  * ```js
47
47
  * // tests/factories/posts.js
48
48
  *
49
- * const Factory = require('rosie').Factory;
50
- * const faker = require('@faker-js/faker');
49
+ * const { Factory } = require('rosie');
50
+ * const { faker } = require('@faker-js/faker');
51
51
  *
52
52
  * module.exports = new Factory()
53
53
  * // no need to set id, it will be set by REST API
@@ -230,7 +230,7 @@ class ApiDataFactory extends Helper {
230
230
  }
231
231
 
232
232
  _after() {
233
- if (!this.config.cleanup) {
233
+ if (!this.config.cleanup || this.config.cleanup === false) {
234
234
  return Promise.resolve();
235
235
  }
236
236
  const promises = [];
@@ -244,7 +244,6 @@ class ApiDataFactory extends Helper {
244
244
  promises.push(this._requestDelete(factoryName, createdItems[id]));
245
245
  }
246
246
  }
247
-
248
247
  return Promise.all(promises);
249
248
  }
250
249
 
@@ -262,8 +261,8 @@ class ApiDataFactory extends Helper {
262
261
  * ```
263
262
  *
264
263
  * @param {*} factory factory to use
265
- * @param {*} params predefined parameters
266
- * @param {*} options options for programmatically generate the attributes
264
+ * @param {*} [params] predefined parameters
265
+ * @param {*} [options] options for programmatically generate the attributes
267
266
  * @returns {Promise<*>}
268
267
  */
269
268
  have(factory, params, options) {
@@ -288,8 +287,8 @@ class ApiDataFactory extends Helper {
288
287
  *
289
288
  * @param {*} factory
290
289
  * @param {*} times
291
- * @param {*} params
292
- * @param {*} options
290
+ * @param {*} [params]
291
+ * @param {*} [options]
293
292
  */
294
293
  haveMultiple(factory, times, params, options) {
295
294
  const promises = [];
@@ -379,7 +378,9 @@ Current file error: ${err.message}`);
379
378
 
380
379
  if (!request) {
381
380
  const method = Object.keys(this.factories[factory].delete)[0];
381
+
382
382
  const url = this.factories[factory].delete[method].replace('{id}', id);
383
+
383
384
  request = {
384
385
  method,
385
386
  url,
@@ -388,6 +389,10 @@ Current file error: ${err.message}`);
388
389
 
389
390
  request.baseURL = this.config.endpoint;
390
391
 
392
+ if (request.url.match(/^undefined/)) {
393
+ return this.debugSection('Please configure the delete request in your ApiDataFactory helper', 'delete: () => ({ method: \'DELETE\', url: \'/api/users\' })');
394
+ }
395
+
391
396
  return this.restHelper._executeRequest(request).then(() => {
392
397
  const idx = this.created[factory].indexOf(id);
393
398
  this.debugSection('Deleted Id', `Id: ${id}`);
@@ -1,5 +1,4 @@
1
1
  let webdriverio;
2
- let wdioV4;
3
2
 
4
3
  const fs = require('fs');
5
4
  const axios = require('axios').default;
@@ -131,6 +130,7 @@ class Appium extends Webdriver {
131
130
  * @augments WebDriver
132
131
  */
133
132
 
133
+ // @ts-ignore
134
134
  constructor(config) {
135
135
  super(config);
136
136
 
@@ -138,7 +138,6 @@ class Appium extends Webdriver {
138
138
  this.axios = axios.create();
139
139
 
140
140
  webdriverio = require('webdriverio');
141
- (!webdriverio.VERSION || webdriverio.VERSION.indexOf('4') !== 0) ? wdioV4 = false : wdioV4 = true;
142
141
  }
143
142
 
144
143
  _validateConfig(config) {
@@ -516,10 +515,6 @@ class Appium extends Webdriver {
516
515
  async removeApp(appId, bundleId) {
517
516
  onlyForApps.call(this, supportedPlatform.android);
518
517
 
519
- if (wdioV4) {
520
- return this.browser.removeApp(bundleId);
521
- }
522
-
523
518
  return this.axios({
524
519
  method: 'post',
525
520
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/appium/device/remove_app`,
@@ -610,19 +605,13 @@ class Appium extends Webdriver {
610
605
  */
611
606
  async seeOrientationIs(orientation) {
612
607
  onlyForApps.call(this);
613
- let currentOrientation;
614
-
615
- if (wdioV4) {
616
- const res = await this.browser.orientation();
617
- currentOrientation = res;
618
- }
619
608
 
620
609
  const res = await this.axios({
621
610
  method: 'get',
622
611
  url: `${this._buildAppiumEndpoint()}/session/${this.browser.sessionId}/orientation`,
623
612
  });
624
613
 
625
- currentOrientation = res.data.value;
614
+ const currentOrientation = res.data.value;
626
615
  return truth('orientation', `to be ${orientation}`).assert(currentOrientation === orientation);
627
616
  }
628
617
 
@@ -640,9 +629,6 @@ class Appium extends Webdriver {
640
629
  */
641
630
  async setOrientation(orientation) {
642
631
  onlyForApps.call(this);
643
- if (wdioV4) {
644
- return this.browser.setOrientation(orientation);
645
- }
646
632
 
647
633
  return this.axios({
648
634
  method: 'post',
@@ -916,9 +902,6 @@ class Appium extends Webdriver {
916
902
  */
917
903
  async sendDeviceKeyEvent(keyValue) {
918
904
  onlyForApps.call(this, supportedPlatform.android);
919
- if (wdioV4) {
920
- return this.browser.sendKeyEvent(keyValue);
921
- }
922
905
  return this.browser.pressKeyCode(keyValue);
923
906
  }
924
907
 
@@ -2,7 +2,7 @@ const assert = require('assert');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
4
 
5
- const Helper = require('../helper');
5
+ const Helper = require('@codeceptjs/helper');
6
6
  const { fileExists } = require('../utils');
7
7
  const { fileIncludes } = require('../assert/include');
8
8
  const { fileEquals } = require('../assert/equal');
@@ -71,10 +71,10 @@ class FileSystem extends Helper {
71
71
  }
72
72
 
73
73
  /**
74
- * Waits for file to be present in current directory.
74
+ * Waits for the file to be present in the current directory.
75
75
  *
76
76
  * ```js
77
- * I.handleDownloads();
77
+ * I.handleDownloads('downloads/largeFilesName.txt');
78
78
  * I.click('Download large File');
79
79
  * I.amInPath('output/downloads');
80
80
  * I.waitForFile('largeFilesName.txt', 10); // wait 10 seconds for file
@@ -1,5 +1,5 @@
1
1
  const axios = require('axios').default;
2
- const Helper = require('../helper');
2
+ const Helper = require('@codeceptjs/helper');
3
3
 
4
4
  /**
5
5
  * GraphQL helper allows to send additional requests to a GraphQl endpoint during acceptance tests.
@@ -1,6 +1,6 @@
1
1
  const path = require('path');
2
2
 
3
- const Helper = require('../helper');
3
+ const Helper = require('@codeceptjs/helper');
4
4
  const GraphQL = require('./GraphQL');
5
5
 
6
6
  /**
@@ -46,8 +46,8 @@ const GraphQL = require('./GraphQL');
46
46
  * ```js
47
47
  * // tests/factories/users.js
48
48
  *
49
- * const Factory = require('rosie').Factory;
50
- * const faker = require('@faker-js/faker');
49
+ * const { Factory } = require('rosie').Factory;
50
+ * const { faker } = require('@faker-js/faker');
51
51
  *
52
52
  * // Used with a constructor function passed to Factory, so that the final build
53
53
  * // object matches the necessary pattern to be sent as the variables object.
@@ -2,7 +2,7 @@ const assert = require('assert');
2
2
  const chai = require('chai');
3
3
  const joi = require('joi');
4
4
  const chaiDeepMatch = require('chai-deep-match');
5
- const Helper = require('../helper');
5
+ const Helper = require('@codeceptjs/helper');
6
6
 
7
7
  chai.use(chaiDeepMatch);
8
8
 
@@ -2,7 +2,7 @@ let addMochawesomeContext;
2
2
  let currentTest;
3
3
  let currentSuite;
4
4
 
5
- const Helper = require('../helper');
5
+ const Helper = require('@codeceptjs/helper');
6
6
  const { clearString } = require('../utils');
7
7
 
8
8
  class Mochawesome extends Helper {
@@ -2,7 +2,7 @@ const path = require('path');
2
2
 
3
3
  const urlResolve = require('url').resolve;
4
4
 
5
- const Helper = require('../helper');
5
+ const Helper = require('@codeceptjs/helper');
6
6
  const { includes: stringIncludes } = require('../assert/include');
7
7
  const { urlEquals } = require('../assert/equal');
8
8
  const { equals } = require('../assert/equal');
@@ -1,7 +1,7 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
3
 
4
- const Helper = require('../helper');
4
+ const Helper = require('@codeceptjs/helper');
5
5
  const Locator = require('../locator');
6
6
  const recorder = require('../recorder');
7
7
  const stringIncludes = require('../assert/include').includes;
@@ -66,6 +66,7 @@ const pathSeparator = path.sep;
66
66
  * @prop {boolean} [video=false] - enables video recording for failed tests; videos are saved into `output/videos` folder
67
67
  * @prop {boolean} [keepVideoForPassedTests=false] - save videos for passed tests; videos are saved into `output/videos` folder
68
68
  * @prop {boolean} [trace=false] - record [tracing information](https://playwright.dev/docs/trace-viewer) with screenshots and snapshots.
69
+ * @prop {boolean} [keepTraceForPassedTests=false] - save trace for passed tests.
69
70
  * @prop {boolean} [fullPageScreenshots=false] - make full page screenshots on failure.
70
71
  * @prop {boolean} [uniqueScreenshotNames=false] - option to prevent screenshot override if you have scenarios with the same name in different suites.
71
72
  * @prop {boolean} [keepBrowserState=false] - keep browser state between tests when `restart` is set to 'session'.
@@ -1259,7 +1260,7 @@ class Playwright extends Helper {
1259
1260
  *
1260
1261
  * ```
1261
1262
  *
1262
- * @param {string} [fileName] set filename for downloaded file
1263
+ * @param {string} fileName set filename for downloaded file
1263
1264
  * @return {Promise<void>}
1264
1265
  */
1265
1266
  async handleDownloads(fileName) {
@@ -2981,7 +2982,7 @@ async function refreshContextSession() {
2981
2982
 
2982
2983
  async function saveVideoForPage(page, name) {
2983
2984
  if (!page.video()) return null;
2984
- const fileName = `${global.output_dir}${pathSeparator}videos${pathSeparator}${Date.now()}_${clearString(name).slice(0, 245)}.webm`;
2985
+ const fileName = `${`${global.output_dir}${pathSeparator}videos${pathSeparator}${Date.now()}_${clearString(name)}`.slice(0, 245)}.webm`;
2985
2986
  page.video().saveAs(fileName).then(() => {
2986
2987
  if (!page) return;
2987
2988
  page.video().delete().catch(e => {});
@@ -6,7 +6,7 @@ let ProtractorExpectedConditions;
6
6
 
7
7
  const path = require('path');
8
8
 
9
- const Helper = require('../helper');
9
+ const Helper = require('@codeceptjs/helper');
10
10
  const stringIncludes = require('../assert/include').includes;
11
11
  const { urlEquals, equals } = require('../assert/equal');
12
12
  const { empty } = require('../assert/empty');
@@ -3,7 +3,7 @@ const fs = require('fs');
3
3
  const fsExtra = require('fs-extra');
4
4
  const path = require('path');
5
5
 
6
- const Helper = require('../helper');
6
+ const Helper = require('@codeceptjs/helper');
7
7
  const Locator = require('../locator');
8
8
  const recorder = require('../recorder');
9
9
  const stringIncludes = require('../assert/include').includes;
@@ -1,7 +1,7 @@
1
1
  const axios = require('axios').default;
2
+ const Helper = require('@codeceptjs/helper');
2
3
  const Secret = require('../secret');
3
4
 
4
- const Helper = require('../helper');
5
5
  const { beautify } = require('../utils');
6
6
 
7
7
  /**
@@ -6,6 +6,7 @@ const qrcode = require('qrcode-terminal');
6
6
  const createTestCafe = require('testcafe');
7
7
  const { Selector, ClientFunction } = require('testcafe');
8
8
 
9
+ const Helper = require('@codeceptjs/helper');
9
10
  const ElementNotFound = require('./errors/ElementNotFound');
10
11
  const testControllerHolder = require('./testcafe/testControllerHolder');
11
12
  const {
@@ -22,7 +23,6 @@ const {
22
23
  xpathLocator,
23
24
  } = require('../utils');
24
25
  const Locator = require('../locator');
25
- const Helper = require('../helper');
26
26
 
27
27
  /**
28
28
  * Client Functions
@@ -545,8 +545,8 @@ class TestCafe extends Helper {
545
545
 
546
546
  // TODO As far as I understand the testcafe docs this should do a multi-select
547
547
  // but it does not work
548
- const clickOpts = { ctrl: option.length > 1 };
549
- await this.t.click(el, clickOpts).catch(mapError);
548
+ // const clickOpts = { ctrl: option.length > 1 };
549
+ await this.t.click(el).catch(mapError);
550
550
 
551
551
  for (const key of option) {
552
552
  const opt = key;
@@ -555,7 +555,7 @@ class TestCafe extends Helper {
555
555
  try {
556
556
  optEl = el.child('option').withText(opt);
557
557
  if (await optEl.count) {
558
- await this.t.click(optEl, clickOpts).catch(mapError);
558
+ await this.t.click(optEl).catch(mapError);
559
559
  continue;
560
560
  }
561
561
  // eslint-disable-next-line no-empty
@@ -566,7 +566,7 @@ class TestCafe extends Helper {
566
566
  const sel = `[value="${opt}"]`;
567
567
  optEl = el.find(sel);
568
568
  if (await optEl.count) {
569
- await this.t.click(optEl, clickOpts).catch(mapError);
569
+ await this.t.click(optEl).catch(mapError);
570
570
  }
571
571
  // eslint-disable-next-line no-empty
572
572
  } catch (err) {