codeceptjs 3.7.6-beta.4 → 3.7.6

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/lib/codecept.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const { existsSync, readFileSync } = require('fs')
2
2
  const { globSync } = require('glob')
3
- const shuffle = require('lodash.shuffle')
4
3
  const fsPath = require('path')
5
4
  const { resolve } = require('path')
6
5
 
@@ -185,8 +184,10 @@ class Codecept {
185
184
  }
186
185
  }
187
186
 
187
+ this.testFiles.sort()
188
+
188
189
  if (this.opts.shuffle) {
189
- this.testFiles = shuffle(this.testFiles)
190
+ this.testFiles = this.shuffle(this.testFiles)
190
191
  }
191
192
 
192
193
  if (this.opts.shard) {
@@ -194,6 +195,18 @@ class Codecept {
194
195
  }
195
196
  }
196
197
 
198
+ /**
199
+ * Fisher–Yates shuffle (non-mutating)
200
+ */
201
+ shuffle(array) {
202
+ const arr = [...array] // clone to avoid mutating input
203
+ for (let i = arr.length - 1; i > 0; i--) {
204
+ const j = Math.floor(Math.random() * (i + 1))
205
+ ;[arr[i], arr[j]] = [arr[j], arr[i]] // swap
206
+ }
207
+ return arr
208
+ }
209
+
197
210
  /**
198
211
  * Apply sharding to test files based on shard configuration
199
212
  *
@@ -1876,11 +1876,15 @@ class Playwright extends Helper {
1876
1876
  * {{> type }}
1877
1877
  */
1878
1878
  async type(keys, delay = null) {
1879
+ // Always use page.keyboard.type for any string (including single character and national characters).
1879
1880
  if (!Array.isArray(keys)) {
1880
1881
  keys = keys.toString()
1881
- keys = keys.split('')
1882
+ const typeDelay = typeof delay === 'number' ? delay : this.options.pressKeyDelay
1883
+ await this.page.keyboard.type(keys, { delay: typeDelay })
1884
+ return
1882
1885
  }
1883
1886
 
1887
+ // For array input, treat each as a key press to keep working combinations such as ['Control', 'A'] or ['T', 'e', 's', 't'].
1884
1888
  for (const key of keys) {
1885
1889
  await this.page.keyboard.press(key)
1886
1890
  if (delay) await this.wait(delay / 1000)
@@ -20,14 +20,29 @@ module.exports = function () {
20
20
 
21
21
  // disable timeout for BeforeSuite/AfterSuite hooks
22
22
  // add separate configs to them?
23
+ // When a BeforeSuite/AfterSuite hook starts we want to disable the
24
+ // per-test timeout during that hook execution only. Previously the
25
+ // code cleared `suiteTimeout` permanently which caused the suite
26
+ // level timeout to be lost for subsequent tests. Save previous
27
+ // values and restore them when the hook finishes.
28
+ let __prevTimeout = undefined
29
+ let __prevSuiteTimeout = undefined
30
+
23
31
  event.dispatcher.on(event.hook.started, hook => {
24
- if (hook instanceof BeforeSuiteHook) {
32
+ if (hook instanceof BeforeSuiteHook || hook instanceof AfterSuiteHook) {
33
+ __prevTimeout = timeout
34
+ // copy array to preserve original values
35
+ __prevSuiteTimeout = suiteTimeout.slice()
25
36
  timeout = null
26
37
  suiteTimeout = []
27
38
  }
28
- if (hook instanceof AfterSuiteHook) {
29
- timeout = null
30
- suiteTimeout = []
39
+ })
40
+
41
+ event.dispatcher.on(event.hook.finished, hook => {
42
+ if (hook instanceof BeforeSuiteHook || hook instanceof AfterSuiteHook) {
43
+ // restore previously stored values
44
+ timeout = __prevTimeout
45
+ suiteTimeout = __prevSuiteTimeout.slice()
31
46
  }
32
47
  })
33
48
 
package/lib/mocha/test.js CHANGED
@@ -153,14 +153,16 @@ function cloneTest(test) {
153
153
  function testToFileName(test, { suffix = '', unique = false } = {}) {
154
154
  let fileName = test.title
155
155
 
156
- if (unique) fileName = `${fileName}_${test?.uid || Math.floor(new Date().getTime() / 1000)}`
157
- if (suffix) fileName = `${fileName}_${suffix}`
158
156
  // remove tags with empty string (disable for now)
159
157
  // fileName = fileName.replace(/\@\w+/g, '')
160
158
  fileName = fileName.slice(0, 100)
161
159
  if (fileName.indexOf('{') !== -1) {
162
160
  fileName = fileName.substr(0, fileName.indexOf('{') - 3).trim()
163
161
  }
162
+
163
+ // Apply unique suffix AFTER removing data part to ensure uniqueness
164
+ if (unique) fileName = `${fileName}_${test?.uid || Math.floor(new Date().getTime())}`
165
+ if (suffix) fileName = `${fileName}_${suffix}`
164
166
  if (test.ctx && test.ctx.test && test.ctx.test.type === 'hook') fileName = clearString(`${test.title}_${test.ctx.test.title}`)
165
167
  // TODO: add suite title to file name
166
168
  // if (test.parent && test.parent.title) {
package/lib/output.js CHANGED
@@ -222,12 +222,10 @@ module.exports = {
222
222
  /**
223
223
  * @param {Mocha.Test} test
224
224
  */
225
-
226
225
  started(test) {
227
226
  if (outputLevel < 1) return
228
227
  print(` ${colors.dim.bold('Scenario()')}`)
229
228
  },
230
-
231
229
  /**
232
230
  * @param {Mocha.Test} test
233
231
  */
@@ -273,10 +271,12 @@ module.exports = {
273
271
  },
274
272
 
275
273
  /**
274
+ * Prints the stats of a test run to the console.
276
275
  * @param {number} passed
277
276
  * @param {number} failed
278
277
  * @param {number} skipped
279
278
  * @param {number|string} duration
279
+ * @param {number} [failedHooks]
280
280
  */
281
281
  result(passed, failed, skipped, duration, failedHooks = 0) {
282
282
  let style = colors.bgGreen