codeceptjs 3.3.1 → 3.3.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 (126) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +4 -25
  3. package/docs/api.md +4 -0
  4. package/docs/basics.md +2 -0
  5. package/docs/build/Appium.js +18 -28
  6. package/docs/build/JSONResponse.js +44 -3
  7. package/docs/build/Nightmare.js +53 -53
  8. package/docs/build/Playwright.js +95 -103
  9. package/docs/build/Protractor.js +66 -66
  10. package/docs/build/Puppeteer.js +74 -74
  11. package/docs/build/REST.js +8 -4
  12. package/docs/build/TestCafe.js +53 -53
  13. package/docs/build/WebDriver.js +84 -86
  14. package/docs/changelog.md +49 -0
  15. package/docs/helpers/Appium.md +212 -268
  16. package/docs/helpers/JSONResponse.md +24 -0
  17. package/docs/helpers/Nightmare.md +92 -141
  18. package/docs/helpers/Playwright.md +302 -413
  19. package/docs/helpers/Puppeteer.md +171 -231
  20. package/docs/helpers/REST.md +2 -0
  21. package/docs/helpers/TestCafe.md +125 -174
  22. package/docs/helpers/WebDriver.md +184 -247
  23. package/docs/plugins.md +41 -1
  24. package/docs/secrets.md +30 -0
  25. package/docs/webapi/amOnPage.mustache +1 -1
  26. package/docs/webapi/appendField.mustache +1 -1
  27. package/docs/webapi/attachFile.mustache +1 -1
  28. package/docs/webapi/checkOption.mustache +1 -1
  29. package/docs/webapi/clearCookie.mustache +1 -1
  30. package/docs/webapi/clearField.mustache +1 -1
  31. package/docs/webapi/click.mustache +1 -1
  32. package/docs/webapi/clickLink.mustache +1 -1
  33. package/docs/webapi/closeCurrentTab.mustache +1 -1
  34. package/docs/webapi/closeOtherTabs.mustache +1 -1
  35. package/docs/webapi/dontSee.mustache +1 -1
  36. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
  37. package/docs/webapi/dontSeeCookie.mustache +1 -1
  38. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +1 -1
  39. package/docs/webapi/dontSeeElement.mustache +1 -1
  40. package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
  41. package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
  42. package/docs/webapi/dontSeeInField.mustache +1 -1
  43. package/docs/webapi/dontSeeInSource.mustache +1 -1
  44. package/docs/webapi/dontSeeInTitle.mustache +1 -1
  45. package/docs/webapi/doubleClick.mustache +1 -1
  46. package/docs/webapi/downloadFile.mustache +1 -1
  47. package/docs/webapi/dragAndDrop.mustache +1 -1
  48. package/docs/webapi/dragSlider.mustache +1 -1
  49. package/docs/webapi/executeAsyncScript.mustache +1 -1
  50. package/docs/webapi/executeScript.mustache +1 -1
  51. package/docs/webapi/fillField.mustache +1 -1
  52. package/docs/webapi/forceClick.mustache +1 -1
  53. package/docs/webapi/forceRightClick.mustache +1 -1
  54. package/docs/webapi/grabDataFromPerformanceTiming.mustache +1 -1
  55. package/docs/webapi/moveCursorTo.mustache +1 -1
  56. package/docs/webapi/openNewTab.mustache +1 -1
  57. package/docs/webapi/pressKey.mustache +1 -1
  58. package/docs/webapi/pressKeyDown.mustache +1 -1
  59. package/docs/webapi/pressKeyUp.mustache +1 -1
  60. package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
  61. package/docs/webapi/refreshPage.mustache +1 -1
  62. package/docs/webapi/resizeWindow.mustache +1 -1
  63. package/docs/webapi/rightClick.mustache +1 -1
  64. package/docs/webapi/saveElementScreenshot.mustache +1 -1
  65. package/docs/webapi/saveScreenshot.mustache +1 -1
  66. package/docs/webapi/say.mustache +1 -1
  67. package/docs/webapi/scrollIntoView.mustache +1 -1
  68. package/docs/webapi/scrollPageToBottom.mustache +1 -1
  69. package/docs/webapi/scrollPageToTop.mustache +1 -1
  70. package/docs/webapi/scrollTo.mustache +1 -1
  71. package/docs/webapi/see.mustache +1 -1
  72. package/docs/webapi/seeAttributesOnElements.mustache +1 -1
  73. package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
  74. package/docs/webapi/seeCookie.mustache +1 -1
  75. package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
  76. package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
  77. package/docs/webapi/seeElement.mustache +1 -1
  78. package/docs/webapi/seeElementInDOM.mustache +1 -1
  79. package/docs/webapi/seeInCurrentUrl.mustache +1 -1
  80. package/docs/webapi/seeInField.mustache +1 -1
  81. package/docs/webapi/seeInPopup.mustache +1 -1
  82. package/docs/webapi/seeInSource.mustache +1 -1
  83. package/docs/webapi/seeInTitle.mustache +1 -1
  84. package/docs/webapi/seeNumberOfElements.mustache +1 -1
  85. package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
  86. package/docs/webapi/seeTextEquals.mustache +1 -1
  87. package/docs/webapi/seeTitleEquals.mustache +1 -1
  88. package/docs/webapi/selectOption.mustache +1 -1
  89. package/docs/webapi/setCookie.mustache +1 -1
  90. package/docs/webapi/setGeoLocation.mustache +1 -1
  91. package/docs/webapi/switchTo.mustache +1 -1
  92. package/docs/webapi/switchToNextTab.mustache +1 -1
  93. package/docs/webapi/switchToPreviousTab.mustache +1 -1
  94. package/docs/webapi/type.mustache +1 -1
  95. package/docs/webapi/uncheckOption.mustache +1 -1
  96. package/docs/webapi/wait.mustache +1 -1
  97. package/docs/webapi/waitForClickable.mustache +1 -1
  98. package/docs/webapi/waitForDetached.mustache +1 -1
  99. package/docs/webapi/waitForElement.mustache +1 -1
  100. package/docs/webapi/waitForEnabled.mustache +1 -1
  101. package/docs/webapi/waitForFunction.mustache +1 -1
  102. package/docs/webapi/waitForInvisible.mustache +1 -1
  103. package/docs/webapi/waitForText.mustache +1 -1
  104. package/docs/webapi/waitForValue.mustache +1 -1
  105. package/docs/webapi/waitForVisible.mustache +1 -1
  106. package/docs/webapi/waitInUrl.mustache +1 -1
  107. package/docs/webapi/waitNumberOfVisibleElements.mustache +1 -1
  108. package/docs/webapi/waitToHide.mustache +1 -1
  109. package/docs/webapi/waitUrlEquals.mustache +1 -1
  110. package/lib/cli.js +1 -1
  111. package/lib/command/interactive.js +1 -1
  112. package/lib/command/run-workers.js +1 -1
  113. package/lib/command/workers/runTests.js +15 -0
  114. package/lib/helper/Appium.js +0 -10
  115. package/lib/helper/JSONResponse.js +44 -3
  116. package/lib/helper/Playwright.js +24 -32
  117. package/lib/helper/REST.js +8 -4
  118. package/lib/helper/WebDriver.js +5 -7
  119. package/lib/output.js +4 -0
  120. package/lib/plugin/customLocator.js +50 -3
  121. package/lib/plugin/retryFailedStep.js +1 -1
  122. package/lib/plugin/retryTo.js +1 -8
  123. package/lib/secret.js +30 -0
  124. package/lib/step.js +1 -1
  125. package/package.json +4 -4
  126. package/typings/types.d.ts +1016 -520
@@ -907,7 +907,7 @@ class WebDriver extends Helper {
907
907
  * {{ react }}
908
908
  */
909
909
  async click(locator, context = null) {
910
- const clickMethod = this.browser.isMobile ? 'touchClick' : 'elementClick';
910
+ const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick';
911
911
  const locateFn = prepareLocateFn.call(this, context);
912
912
 
913
913
  const res = await findClickable.call(this, locator, locateFn);
@@ -1117,7 +1117,7 @@ class WebDriver extends Helper {
1117
1117
  * Appium: not tested
1118
1118
  */
1119
1119
  async checkOption(field, context = null) {
1120
- const clickMethod = this.browser.isMobile ? 'touchClick' : 'elementClick';
1120
+ const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick';
1121
1121
  const locateFn = prepareLocateFn.call(this, context);
1122
1122
 
1123
1123
  const res = await findCheckable.call(this, field, locateFn);
@@ -1136,7 +1136,7 @@ class WebDriver extends Helper {
1136
1136
  * Appium: not tested
1137
1137
  */
1138
1138
  async uncheckOption(field, context = null) {
1139
- const clickMethod = this.browser.isMobile ? 'touchClick' : 'elementClick';
1139
+ const clickMethod = this.browser.isMobile && this.browser.capabilities.platformName !== 'android' ? 'touchClick' : 'elementClick';
1140
1140
  const locateFn = prepareLocateFn.call(this, context);
1141
1141
 
1142
1142
  const res = await findCheckable.call(this, field, locateFn);
@@ -1623,7 +1623,7 @@ class WebDriver extends Helper {
1623
1623
  assertElementExists(res);
1624
1624
  const elem = usingFirstElement(res);
1625
1625
  const elementId = getElementId(elem);
1626
- if (this.browser.isMobile) return this.browser.touchScroll(offsetX, offsetY, elementId);
1626
+ if (this.browser.isMobile && this.browser.capabilities.platformName !== 'android') return this.browser.touchScroll(offsetX, offsetY, elementId);
1627
1627
  const location = await elem.getLocation();
1628
1628
  assertElementExists(location, 'Failed to receive', 'location');
1629
1629
  /* eslint-disable prefer-arrow-callback */
@@ -1631,7 +1631,7 @@ class WebDriver extends Helper {
1631
1631
  /* eslint-enable */
1632
1632
  }
1633
1633
 
1634
- if (this.browser.isMobile) return this.browser.touchScroll(locator, offsetX, offsetY);
1634
+ if (this.browser.isMobile && this.browser.capabilities.platformName !== 'android') return this.browser.touchScroll(locator, offsetX, offsetY);
1635
1635
 
1636
1636
  /* eslint-disable prefer-arrow-callback, comma-dangle */
1637
1637
  return this.browser.execute(function (x, y) { return window.scrollTo(x, y); }, offsetX, offsetY);
@@ -2553,7 +2553,6 @@ class WebDriver extends Helper {
2553
2553
  * Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
2554
2554
  * @param {*} caps
2555
2555
  * @param {*} fn
2556
- * @return {Promise<any>}
2557
2556
  */
2558
2557
  /* eslint-disable */
2559
2558
  runOnIOS(caps, fn) {
@@ -2563,7 +2562,6 @@ class WebDriver extends Helper {
2563
2562
  * Placeholder for ~ locator only test case write once run on both Appium and WebDriver.
2564
2563
  * @param {*} caps
2565
2564
  * @param {*} fn
2566
- * @return {Promise<any>}
2567
2565
  */
2568
2566
  runOnAndroid(caps, fn) {
2569
2567
  }
package/lib/output.js CHANGED
@@ -26,6 +26,10 @@ module.exports = {
26
26
  /** @type {number} */
27
27
  stepShift: 0,
28
28
 
29
+ standWithUkraine() {
30
+ return `#${colors.bold.yellow('StandWith')}${colors.bold.cyan('Ukraine')}`;
31
+ },
32
+
29
33
  /**
30
34
  * Set or return current verbosity level
31
35
  * @param {number} [level]
@@ -70,23 +70,70 @@ const defaultConfig = {
70
70
  * I.seeElement('=user'); // matches => [data-qa=user]
71
71
  * I.click('=sign-up'); // matches => [data-qa=sign-up]
72
72
  * ```
73
+ *
74
+ * Using `data-qa` OR `data-test` attribute with `=` prefix:
75
+ *
76
+ * ```js
77
+ * // in codecept.conf.js
78
+ * plugins: {
79
+ * customLocator: {
80
+ * enabled: true,
81
+ * prefix: '=',
82
+ * attribute: ['data-qa', 'data-test'],
83
+ * strategy: 'xpath'
84
+ * }
85
+ * }
86
+ * ```
87
+ *
88
+ * In a test:
89
+ *
90
+ * ```js
91
+ * I.seeElement('=user'); // matches => //*[@data-qa=user or @data-test=user]
92
+ * I.click('=sign-up'); // matches => //*[data-qa=sign-up or @data-test=sign-up]
93
+ * ```
94
+ *
95
+ * ```js
96
+ * // in codecept.conf.js
97
+ * plugins: {
98
+ * customLocator: {
99
+ * enabled: true,
100
+ * prefix: '=',
101
+ * attribute: ['data-qa', 'data-test'],
102
+ * strategy: 'css'
103
+ * }
104
+ * }
105
+ * ```
106
+ *
107
+ * In a test:
108
+ *
109
+ * ```js
110
+ * I.seeElement('=user'); // matches => [data-qa=user],[data-test=user]
111
+ * I.click('=sign-up'); // matches => [data-qa=sign-up],[data-test=sign-up]
112
+ * ```
73
113
  */
74
114
  module.exports = (config) => {
75
- config = Object.assign(defaultConfig, config);
115
+ config = { ...defaultConfig, ...config };
76
116
 
77
117
  Locator.addFilter((value, locatorObj) => {
78
118
  if (typeof value !== 'string') return;
79
119
  if (!value.startsWith(config.prefix)) return;
80
120
 
121
+ if (!['String', 'Array'].includes(config.attribute.constructor.name)) return;
122
+
81
123
  const val = value.substr(config.prefix.length);
82
124
 
83
125
  if (config.strategy.toLowerCase() === 'xpath') {
84
- locatorObj.value = `.//*[@${config.attribute}=${xpathLocator.literal(val)}]`;
126
+ locatorObj.value = `.//*[${
127
+ [].concat(config.attribute)
128
+ .map((attr) => `@${attr}=${xpathLocator.literal(val)}`)
129
+ .join(' or ')}]`;
85
130
  locatorObj.type = 'xpath';
86
131
  }
87
132
 
88
133
  if (config.strategy.toLowerCase() === 'css') {
89
- locatorObj.value = `[${config.attribute}=${val}]`;
134
+ locatorObj.value = [].concat(config.attribute)
135
+ .map((attr) => `[${attr}=${val}]`)
136
+ .join(',');
90
137
  locatorObj.type = 'css';
91
138
  }
92
139
 
@@ -60,7 +60,7 @@ const defaultConfig = {
60
60
  * plugins: {
61
61
  * retryFailedStep: {
62
62
  * enabled: true,
63
- * ignoreSteps: [
63
+ * ignoredSteps: [
64
64
  * 'scroll*', // ignore all scroll steps
65
65
  * /Cookie/, // ignore all steps with a Cookie in it (by regexp)
66
66
  * ]
@@ -101,27 +101,20 @@ module.exports = function (config) {
101
101
  err = e;
102
102
  recorder.session.restore(`retryTo ${tries}`);
103
103
  tries++;
104
- // recorder.session.restore(`retryTo`);
105
104
  if (tries <= maxTries) {
106
105
  debug(`Error ${err}... Retrying`);
107
106
  err = null;
108
107
 
109
- recorder.add(`retryTo ${tries}`, () => {
110
- tryBlock();
111
- // recorder.add(() => new Promise(done => setTimeout(done, pollInterval)));
112
- });
108
+ recorder.add(`retryTo ${tries}`, () => setTimeout(tryBlock, pollInterval));
113
109
  } else {
114
- // recorder.throw(err);
115
110
  done(null);
116
111
  }
117
112
  });
118
- // return recorder.promise();
119
113
  };
120
114
 
121
115
  recorder.add('retryTo', async () => {
122
116
  store.debugMode = true;
123
117
  tryBlock();
124
- // recorder.add(() => recorder.session.restore(`retryTo ${tries-1}`));
125
118
  });
126
119
  }).then(() => {
127
120
  if (err) recorder.throw(err);
package/lib/secret.js CHANGED
@@ -1,3 +1,6 @@
1
+ /* eslint-disable max-classes-per-file */
2
+ const { deepClone } = require('./utils');
3
+
1
4
  /** @param {string} secret */
2
5
  class Secret {
3
6
  constructor(secret) {
@@ -9,13 +12,40 @@ class Secret {
9
12
  return this._secret;
10
13
  }
11
14
 
15
+ getMasked() {
16
+ return '*****';
17
+ }
18
+
12
19
  /**
13
20
  * @param {*} secret
14
21
  * @returns {Secret}
15
22
  */
16
23
  static secret(secret) {
24
+ if (typeof secret === 'object') {
25
+ const fields = Array.from(arguments);
26
+ fields.shift();
27
+ return secretObject(secret, fields);
28
+ }
17
29
  return new Secret(secret);
18
30
  }
19
31
  }
20
32
 
33
+ function secretObject(obj, fieldsToHide = []) {
34
+ const handler = {
35
+ get(obj, prop) {
36
+ if (prop === 'toString') {
37
+ return function () {
38
+ const maskedObject = deepClone(obj);
39
+ fieldsToHide.forEach(f => maskedObject[f] = '****');
40
+ return JSON.stringify(maskedObject);
41
+ };
42
+ }
43
+
44
+ return obj[prop];
45
+ },
46
+ };
47
+
48
+ return new Proxy(obj, handler);
49
+ }
50
+
21
51
  module.exports = Secret;
package/lib/step.js CHANGED
@@ -168,7 +168,7 @@ class Step {
168
168
  } else if (typeof arg === 'undefined') {
169
169
  return `${arg}`;
170
170
  } else if (arg instanceof Secret) {
171
- return '*****';
171
+ return arg.getMasked();
172
172
  } else if (arg.toString && arg.toString() !== '[object Object]') {
173
173
  return arg.toString();
174
174
  } else if (typeof arg === 'object') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeceptjs",
3
- "version": "3.3.1",
3
+ "version": "3.3.4",
4
4
  "description": "Supercharged End 2 End Testing Framework for NodeJS",
5
5
  "keywords": [
6
6
  "acceptance",
@@ -90,7 +90,7 @@
90
90
  "uuid": "^8.3.2"
91
91
  },
92
92
  "devDependencies": {
93
- "@codeceptjs/detox-helper": "^1.0.2",
93
+ "@codeceptjs/detox-helper": "^1.0.2",
94
94
  "@codeceptjs/mock-request": "^0.3.1",
95
95
  "@faker-js/faker": "^5.5.3",
96
96
  "@pollyjs/adapter-puppeteer": "^5.1.0",
@@ -101,7 +101,7 @@
101
101
  "@wdio/selenium-standalone-service": "^5.16.10",
102
102
  "@wdio/utils": "^5.23.0",
103
103
  "apollo-server-express": "^2.25.3",
104
- "chai-as-promised": "^5.2.0",
104
+ "chai-as-promised": "^7.1.1",
105
105
  "chai-subset": "^1.6.0",
106
106
  "contributor-faces": "^1.0.3",
107
107
  "documentation": "^12.3.0",
@@ -122,7 +122,7 @@
122
122
  "mocha-parallel-tests": "^2.3.0",
123
123
  "nightmare": "^3.0.2",
124
124
  "nodemon": "^1.19.4",
125
- "playwright": "^1.18.1",
125
+ "playwright": "^1.23.2",
126
126
  "puppeteer": "^10.4.0",
127
127
  "qrcode-terminal": "^0.12.0",
128
128
  "rosie": "^1.6.0",