codeceptjs 4.0.0-beta.3 → 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.
package/README.md CHANGED
@@ -312,17 +312,17 @@ Thanks all to those who are and will have contributing to this awesome project!
312
312
  <a href="https://github.com/tsuemura"><img src="https://avatars.githubusercontent.com/u/17092259?v=4" title="tsuemura" width="80" height="80"></a>
313
313
  <a href="https://github.com/EgorBodnar"><img src="https://avatars.githubusercontent.com/u/63167966?v=4" title="EgorBodnar" width="80" height="80"></a>
314
314
  <a href="https://github.com/VikalpP"><img src="https://avatars.githubusercontent.com/u/11846339?v=4" title="VikalpP" width="80" height="80"></a>
315
+ <a href="https://github.com/thomashohn"><img src="https://avatars.githubusercontent.com/u/3414869?v=4" title="thomashohn" width="80" height="80"></a>
315
316
  <a href="https://github.com/elaichenkov"><img src="https://avatars.githubusercontent.com/u/29764053?v=4" title="elaichenkov" width="80" height="80"></a>
316
317
  <a href="https://github.com/BorisOsipov"><img src="https://avatars.githubusercontent.com/u/6514276?v=4" title="BorisOsipov" width="80" height="80"></a>
318
+ <a href="https://github.com/ngraf"><img src="https://avatars.githubusercontent.com/u/7094389?v=4" title="ngraf" width="80" height="80"></a>
317
319
  <a href="https://github.com/nitschSB"><img src="https://avatars.githubusercontent.com/u/39341455?v=4" title="nitschSB" width="80" height="80"></a>
318
320
  <a href="https://github.com/hubidu"><img src="https://avatars.githubusercontent.com/u/13134082?v=4" title="hubidu" width="80" height="80"></a>
319
321
  <a href="https://github.com/jploskonka"><img src="https://avatars.githubusercontent.com/u/669483?v=4" title="jploskonka" width="80" height="80"></a>
320
- <a href="https://github.com/ngraf"><img src="https://avatars.githubusercontent.com/u/7094389?v=4" title="ngraf" width="80" height="80"></a>
321
322
  <a href="https://github.com/maojunxyz"><img src="https://avatars.githubusercontent.com/u/28778042?v=4" title="maojunxyz" width="80" height="80"></a>
322
323
  <a href="https://github.com/abhimanyupandian"><img src="https://avatars.githubusercontent.com/u/36107381?v=4" title="abhimanyupandian" width="80" height="80"></a>
323
324
  <a href="https://github.com/martomo"><img src="https://avatars.githubusercontent.com/u/1850135?v=4" title="martomo" width="80" height="80"></a>
324
325
  <a href="https://github.com/hatufacci"><img src="https://avatars.githubusercontent.com/u/4963181?v=4" title="hatufacci" width="80" height="80"></a>
325
- <a href="https://github.com/johnyb"><img src="https://avatars.githubusercontent.com/u/86358?v=4" title="johnyb" width="80" height="80"></a>
326
326
 
327
327
  [//]: contributor-faces
328
328
 
package/lib/cli.js CHANGED
@@ -219,7 +219,6 @@ class Cli extends Base {
219
219
 
220
220
  this.failures.forEach((failure) => {
221
221
  if (failure.constructor.name === 'Hook') {
222
- stats.failures -= stats.failures
223
222
  stats.failedHooks += 1
224
223
  }
225
224
  })
package/lib/codecept.js CHANGED
@@ -92,6 +92,9 @@ class Codecept {
92
92
 
93
93
  // debug mode
94
94
  global.debugMode = false;
95
+
96
+ // mask sensitive data
97
+ global.maskSensitiveData = this.config.maskSensitiveData || false;
95
98
  }
96
99
  }
97
100
 
@@ -7,7 +7,7 @@ const store = require('../store')
7
7
  const Container = require('../container')
8
8
 
9
9
  module.exports = async function (test, options) {
10
- if (options.grep) process.env.grep = options.grep.toLowerCase()
10
+ if (options.grep) process.env.grep = options.grep
11
11
  const configFile = options.config
12
12
  let codecept
13
13
 
@@ -60,35 +60,40 @@ function printTests(files) {
60
60
  let numOfTests = 0
61
61
  let numOfSuites = 0
62
62
  let outputString = ''
63
- const filterBy = process.env.grep ? process.env.grep.toLowerCase() : undefined
63
+ const filterBy = process.env.grep
64
64
 
65
+ let filterRegex
65
66
  if (filterBy) {
66
- for (const suite of mocha.suite.suites) {
67
- const currentSuite = suite.title
68
- if (suite.title.toLowerCase().includes(filterBy)) {
69
- outputString += `${colors.white.bold(suite.title)} -- ${output.styles.log(suite.file || '')} -- ${mocha.suite.suites.length} tests\n`
70
- numOfSuites++
71
- }
72
-
73
- for (test of suite.tests) {
74
- if (test.title.toLowerCase().includes(filterBy)) {
75
- numOfTests++
76
- outputString += `${colors.white.bold(test.parent.title)} -- ${output.styles.log(test.parent.file || '')} -- ${mocha.suite.suites.length} tests\n`
77
- outputString += ` ${output.styles.scenario(figures.checkboxOff)} ${test.title}\n`
78
- }
79
- }
67
+ try {
68
+ filterRegex = new RegExp(filterBy, 'i') // Case-insensitive matching
69
+ } catch (err) {
70
+ console.error(`Invalid grep pattern: ${filterBy}`)
71
+ process.exit(1)
80
72
  }
81
- numOfSuites = countSuites(outputString)
82
- } else {
83
- for (const suite of mocha.suite.suites) {
84
- output.print(
85
- `${colors.white.bold(suite.title)} -- ${output.styles.log(suite.file || '')} -- ${mocha.suite.suites.length} tests`,
86
- )
73
+ }
74
+
75
+ for (const suite of mocha.suite.suites) {
76
+ const suiteMatches = filterRegex ? filterRegex.test(suite.title) : true
77
+ let suiteHasMatchingTests = false
78
+
79
+ if (suiteMatches) {
80
+ outputString += `${colors.white.bold(suite.title)} -- ${output.styles.log(suite.file || '')}\n`
81
+ suiteHasMatchingTests = true
87
82
  numOfSuites++
83
+ }
84
+
85
+ for (const test of suite.tests) {
86
+ const testMatches = filterRegex ? filterRegex.test(test.title) : true
87
+
88
+ if (testMatches) {
89
+ if (!suiteMatches && !suiteHasMatchingTests) {
90
+ outputString += `${colors.white.bold(suite.title)} -- ${output.styles.log(suite.file || '')}\n`
91
+ suiteHasMatchingTests = true
92
+ numOfSuites++
93
+ }
88
94
 
89
- for (test of suite.tests) {
90
95
  numOfTests++
91
- output.print(` ${output.styles.scenario(figures.checkboxOff)} ${test.title}`)
96
+ outputString += ` ${output.styles.scenario(figures.checkboxOff)} ${test.title}\n`
92
97
  }
93
98
  }
94
99
  }
@@ -108,15 +113,5 @@ function printFooter() {
108
113
  function removeDuplicates(inputString) {
109
114
  const array = inputString.split('\n')
110
115
  const uniqueLines = [...new Set(array)]
111
- const resultString = uniqueLines.join('\n')
112
-
113
- return resultString
114
- }
115
-
116
- function countSuites(inputString) {
117
- const array = inputString.split('\n')
118
-
119
- const uniqueLines = [...new Set(array)]
120
- const res = uniqueLines.filter((item) => item.includes('-- '))
121
- return res.length
116
+ return uniqueLines.join('\n')
122
117
  }
@@ -127,6 +127,6 @@ ${step.type}(${step.regexp ? '/^' : "'"}${step}${step.regexp ? '$/' : "'"}, () =
127
127
 
128
128
  if (!options.dryRun) {
129
129
  output.success(`Snippets added to ${output.colors.bold(stepFile)}`);
130
- fs.writeFileSync(stepFile, fs.readFileSync(stepFile).toString() + snippets.join('\n') + '\n'); // eslint-disable-line
130
+ fs.writeFileSync(stepFile, fs.readFileSync(stepFile).toString() + snippets.join('\n') + '\n');
131
131
  }
132
132
  };
@@ -13,9 +13,8 @@ const container = require('../../container');
13
13
  const { getConfig } = require('../utils');
14
14
  const { tryOrDefault, deepMerge } = require('../../utils');
15
15
 
16
- // eslint-disable-next-line no-unused-vars
17
16
  let stdout = '';
18
- /* eslint-enable no-unused-vars */
17
+
19
18
  const stderr = '';
20
19
 
21
20
  // Requiring of Codecept need to be after tty.getWindowSize is available.
package/lib/heal.js CHANGED
@@ -113,7 +113,7 @@ class Heal {
113
113
  });
114
114
 
115
115
  if (typeof codeSnippet === 'string') {
116
- const I = Container.support('I'); // eslint-disable-line
116
+ const I = Container.support('I');
117
117
  await eval(codeSnippet); // eslint-disable-line
118
118
  } else if (typeof codeSnippet === 'function') {
119
119
  await codeSnippet(Container.support());
@@ -51,7 +51,7 @@ const REST = require('./REST')
51
51
  *
52
52
  * module.exports = new Factory()
53
53
  * // no need to set id, it will be set by REST API
54
- * .attr('author', () => faker.name.findName())
54
+ * .attr('author', () => faker.person.findName())
55
55
  * .attr('title', () => faker.lorem.sentence())
56
56
  * .attr('body', () => faker.lorem.paragraph());
57
57
  * ```
@@ -491,17 +491,15 @@ class Appium extends Webdriver {
491
491
  * });
492
492
  * ```
493
493
  *
494
- * @param {*} fn
495
494
  */
496
- /* eslint-disable */
497
- async runInWeb(fn) {
495
+
496
+ async runInWeb() {
498
497
  if (!this.isWeb) return
499
498
  recorder.session.start('Web-only actions')
500
499
 
501
500
  recorder.add('restore from Web session', () => recorder.session.restore(), true)
502
501
  return recorder.promise()
503
502
  }
504
- /* eslint-enable */
505
503
 
506
504
  _runWithCaps(caps, fn) {
507
505
  if (typeof caps === 'object') {
@@ -1077,7 +1075,7 @@ class Appium extends Webdriver {
1077
1075
  *
1078
1076
  * Appium: support Android and iOS
1079
1077
  */
1080
- /* eslint-disable */
1078
+
1081
1079
  async swipe(locator, xoffset, yoffset, speed = 1000) {
1082
1080
  onlyForApps.call(this)
1083
1081
  const res = await this.browser.$(parseLocator.call(this, locator))
@@ -1087,7 +1085,6 @@ class Appium extends Webdriver {
1087
1085
  y: (await res.getLocation()).y + yoffset,
1088
1086
  })
1089
1087
  }
1090
- /* eslint-enable */
1091
1088
 
1092
1089
  /**
1093
1090
  * Perform a swipe on the screen.
@@ -55,7 +55,7 @@ const GraphQL = require('./GraphQL')
55
55
  * input: { ...buildObj },
56
56
  * }))
57
57
  * // 'attr'-id can be left out depending on the GraphQl resolvers
58
- * .attr('name', () => faker.name.findName())
58
+ * .attr('name', () => faker.person.findName())
59
59
  * .attr('email', () => faker.interact.email())
60
60
  * ```
61
61
  * For more options see [rosie documentation](https://github.com/rosiejs/rosie).
@@ -1324,7 +1324,7 @@ class Nightmare extends Helper {
1324
1324
  offsetY,
1325
1325
  )
1326
1326
  }
1327
- // eslint-disable-next-line prefer-arrow-callback
1327
+
1328
1328
  return this.executeScript(
1329
1329
  function (x, y) {
1330
1330
  return window.scrollTo(x, y)
@@ -1345,7 +1345,6 @@ class Nightmare extends Helper {
1345
1345
  * {{> scrollPageToBottom }}
1346
1346
  */
1347
1347
  async scrollPageToBottom() {
1348
- /* eslint-disable prefer-arrow-callback, comma-dangle */
1349
1348
  return this.executeScript(function () {
1350
1349
  const body = document.body
1351
1350
  const html = document.documentElement
@@ -1354,21 +1353,19 @@ class Nightmare extends Helper {
1354
1353
  Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
1355
1354
  )
1356
1355
  })
1357
- /* eslint-enable */
1358
1356
  }
1359
1357
 
1360
1358
  /**
1361
1359
  * {{> grabPageScrollPosition }}
1362
1360
  */
1363
1361
  async grabPageScrollPosition() {
1364
- /* eslint-disable comma-dangle */
1365
1362
  function getScrollPosition() {
1366
1363
  return {
1367
1364
  x: window.pageXOffset,
1368
1365
  y: window.pageYOffset,
1369
1366
  }
1370
1367
  }
1371
- /* eslint-enable comma-dangle */
1368
+
1372
1369
  return this.executeScript(getScrollPosition)
1373
1370
  }
1374
1371
  }
@@ -1241,14 +1241,13 @@ class Playwright extends Helper {
1241
1241
  * {{> grabPageScrollPosition }}
1242
1242
  */
1243
1243
  async grabPageScrollPosition() {
1244
- /* eslint-disable comma-dangle */
1245
1244
  function getScrollPosition() {
1246
1245
  return {
1247
1246
  x: window.pageXOffset,
1248
1247
  y: window.pageYOffset,
1249
1248
  }
1250
1249
  }
1251
- /* eslint-enable comma-dangle */
1250
+
1252
1251
  return this.executeScript(getScrollPosition)
1253
1252
  }
1254
1253
 
@@ -1284,7 +1283,7 @@ class Playwright extends Helper {
1284
1283
  * ```
1285
1284
  */
1286
1285
  async _locate(locator) {
1287
- const context = (await this.context) || (await this._getContext())
1286
+ const context = await this._getContext()
1288
1287
 
1289
1288
  if (this.frame) return findElements(this.frame, locator)
1290
1289
 
@@ -1300,7 +1299,7 @@ class Playwright extends Helper {
1300
1299
  * ```
1301
1300
  */
1302
1301
  async _locateElement(locator) {
1303
- const context = (await this.context) || (await this._getContext())
1302
+ const context = await this._getContext()
1304
1303
  return findElement(context, locator)
1305
1304
  }
1306
1305
 
@@ -2737,7 +2736,7 @@ class Playwright extends Helper {
2737
2736
  }
2738
2737
 
2739
2738
  async _getContext() {
2740
- if (this.context && this.context.constructor.name === 'FrameLocator') {
2739
+ if ((this.context && this.context.constructor.name === 'FrameLocator') || this.context) {
2741
2740
  return this.context
2742
2741
  }
2743
2742
  return this.page
@@ -2839,11 +2838,14 @@ class Playwright extends Helper {
2839
2838
  }
2840
2839
  } else {
2841
2840
  // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2842
- // eslint-disable-next-line no-lonely-if
2841
+
2843
2842
  const _contextObject = this.frame ? this.frame : contextObject
2844
2843
  let count = 0
2845
2844
  do {
2846
- waiter = await _contextObject.locator(`:has-text("${text}")`).first().isVisible()
2845
+ waiter = await _contextObject
2846
+ .locator(`:has-text(${JSON.stringify(text)})`)
2847
+ .first()
2848
+ .isVisible()
2847
2849
  if (waiter) break
2848
2850
  await this.wait(1)
2849
2851
  count += 1000
@@ -3813,7 +3815,6 @@ function parseWindowSize(windowSize) {
3813
3815
  // List of key values to key definitions
3814
3816
  // https://github.com/puppeteer/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
3815
3817
  const keyDefinitionMap = {
3816
- /* eslint-disable quote-props */
3817
3818
  0: 'Digit0',
3818
3819
  1: 'Digit1',
3819
3820
  2: 'Digit2',
@@ -3861,7 +3862,6 @@ const keyDefinitionMap = {
3861
3862
  '\\': 'Backslash',
3862
3863
  ']': 'BracketRight',
3863
3864
  "'": 'Quote',
3864
- /* eslint-enable quote-props */
3865
3865
  }
3866
3866
 
3867
3867
  function getNormalizedKey(key) {
@@ -595,7 +595,6 @@ class Protractor extends Helper {
595
595
  async pressKey(key) {
596
596
  let modifier
597
597
  if (Array.isArray(key) && ~['Control', 'Command', 'Shift', 'Alt'].indexOf(key[0])) {
598
- // eslint-disable-line no-bitwise
599
598
  modifier = Key[key[0].toUpperCase()]
600
599
  key = key[1]
601
600
  }
@@ -1106,7 +1105,6 @@ class Protractor extends Helper {
1106
1105
  }
1107
1106
 
1108
1107
  let { width, height } = await this.browser.executeScript(() => ({
1109
- // eslint-disable-line
1110
1108
  height: document.body.scrollHeight,
1111
1109
  width: document.body.scrollWidth,
1112
1110
  }))
@@ -1614,7 +1612,7 @@ class Protractor extends Helper {
1614
1612
  }
1615
1613
  const elem = res[0]
1616
1614
  const location = await elem.getLocation()
1617
- /* eslint-disable prefer-arrow-callback */
1615
+
1618
1616
  return this.executeScript(
1619
1617
  function (x, y) {
1620
1618
  return window.scrollTo(x, y)
@@ -1622,10 +1620,8 @@ class Protractor extends Helper {
1622
1620
  location.x + offsetX,
1623
1621
  location.y + offsetY,
1624
1622
  )
1625
- /* eslint-enable */
1626
1623
  }
1627
1624
 
1628
- /* eslint-disable prefer-arrow-callback, comma-dangle */
1629
1625
  return this.executeScript(
1630
1626
  function (x, y) {
1631
1627
  return window.scrollTo(x, y)
@@ -1633,7 +1629,6 @@ class Protractor extends Helper {
1633
1629
  offsetX,
1634
1630
  offsetY,
1635
1631
  )
1636
- /* eslint-enable */
1637
1632
  }
1638
1633
 
1639
1634
  /**
@@ -1647,7 +1642,6 @@ class Protractor extends Helper {
1647
1642
  * {{> scrollPageToBottom }}
1648
1643
  */
1649
1644
  async scrollPageToBottom() {
1650
- /* eslint-disable prefer-arrow-callback, comma-dangle */
1651
1645
  return this.executeScript(function () {
1652
1646
  const body = document.body
1653
1647
  const html = document.documentElement
@@ -1656,21 +1650,19 @@ class Protractor extends Helper {
1656
1650
  Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
1657
1651
  )
1658
1652
  })
1659
- /* eslint-enable */
1660
1653
  }
1661
1654
 
1662
1655
  /**
1663
1656
  * {{> grabPageScrollPosition }}
1664
1657
  */
1665
1658
  async grabPageScrollPosition() {
1666
- /* eslint-disable comma-dangle */
1667
1659
  function getScrollPosition() {
1668
1660
  return {
1669
1661
  x: window.pageXOffset,
1670
1662
  y: window.pageYOffset,
1671
1663
  }
1672
1664
  }
1673
- /* eslint-enable comma-dangle */
1665
+
1674
1666
  return this.executeScript(getScrollPosition)
1675
1667
  }
1676
1668
 
@@ -861,14 +861,13 @@ class Puppeteer extends Helper {
861
861
  * {{> grabPageScrollPosition }}
862
862
  */
863
863
  async grabPageScrollPosition() {
864
- /* eslint-disable comma-dangle */
865
864
  function getScrollPosition() {
866
865
  return {
867
866
  x: window.pageXOffset,
868
867
  y: window.pageYOffset,
869
868
  }
870
869
  }
871
- /* eslint-enable comma-dangle */
870
+
872
871
  return this.executeScript(getScrollPosition)
873
872
  }
874
873
 
@@ -3106,7 +3105,6 @@ async function getClickablePoint(el) {
3106
3105
  // List of key values to key definitions
3107
3106
  // https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/lib/USKeyboardLayout.js
3108
3107
  const keyDefinitionMap = {
3109
- /* eslint-disable quote-props */
3110
3108
  0: 'Digit0',
3111
3109
  1: 'Digit1',
3112
3110
  2: 'Digit2',
@@ -3154,7 +3152,6 @@ const keyDefinitionMap = {
3154
3152
  '\\': 'Backslash',
3155
3153
  ']': 'BracketRight',
3156
3154
  "'": 'Quote',
3157
- /* eslint-enable quote-props */
3158
3155
  }
3159
3156
 
3160
3157
  function getNormalizedKey(key) {
@@ -408,6 +408,30 @@ class REST extends Helper {
408
408
 
409
409
  return this._executeRequest(request)
410
410
  }
411
+
412
+ /**
413
+ * Sends DELETE request to API with payload.
414
+ *
415
+ * ```js
416
+ * I.sendDeleteRequestWithPayload('/api/users/1', { author: 'john' });
417
+ * ```
418
+ *
419
+ * @param {*} url
420
+ * @param {*} [payload={}] - the payload to be sent. By default it is sent as an empty object
421
+ * @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
422
+ *
423
+ * @returns {Promise<*>} response
424
+ */
425
+ async sendDeleteRequestWithPayload(url, payload = {}, headers = {}) {
426
+ const request = {
427
+ baseURL: this._url(url),
428
+ method: 'DELETE',
429
+ data: payload,
430
+ headers,
431
+ }
432
+
433
+ return this._executeRequest(request)
434
+ }
411
435
  }
412
436
 
413
437
  module.exports = REST
@@ -1049,7 +1049,6 @@ class TestCafe extends Helper {
1049
1049
  }
1050
1050
  const getCookie = ClientFunction(
1051
1051
  () => {
1052
- // eslint-disable-next-line prefer-template
1053
1052
  const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)')
1054
1053
  return v ? v[2] : null
1055
1054
  },
@@ -1220,12 +1219,11 @@ async function waitForFunction(browserFn, waitTimeout) {
1220
1219
  })
1221
1220
 
1222
1221
  const start = Date.now()
1223
- // eslint-disable-next-line no-constant-condition
1222
+
1224
1223
  while (true) {
1225
1224
  let result
1226
1225
  try {
1227
1226
  result = await browserFn()
1228
- // eslint-disable-next-line no-empty
1229
1227
  } catch (err) {
1230
1228
  throw new Error(`Error running function ${err.toString()}`)
1231
1229
  }