codeceptjs 3.7.4 → 3.7.5-beta.2
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 +45 -0
- package/bin/codecept.js +25 -0
- package/bin/test-server.js +53 -0
- package/lib/codecept.js +41 -0
- package/lib/command/init.js +5 -0
- package/lib/command/run-failed-tests.js +216 -0
- package/lib/command/run-workers.js +16 -1
- package/lib/command/workers/runTests.js +220 -14
- package/lib/element/WebElement.js +327 -0
- package/lib/helper/JSONResponse.js +23 -4
- package/lib/helper/Mochawesome.js +24 -2
- package/lib/helper/Playwright.js +396 -57
- package/lib/helper/Puppeteer.js +107 -28
- package/lib/helper/WebDriver.js +18 -4
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +12 -0
- package/lib/mocha/cli.js +1 -1
- package/lib/mocha/test.js +6 -0
- package/lib/mocha/ui.js +13 -0
- package/lib/output.js +8 -10
- package/lib/plugin/failedTestsTracker.js +197 -0
- package/lib/plugin/htmlReporter.js +2955 -0
- package/lib/recorder.js +9 -0
- package/lib/test-server.js +323 -0
- package/lib/utils/mask_data.js +53 -0
- package/lib/utils.js +34 -2
- package/lib/workers.js +135 -9
- package/package.json +8 -6
- package/typings/index.d.ts +17 -4
- package/typings/promiseBasedTypes.d.ts +14 -0
- package/typings/types.d.ts +18 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const event = require('../event')
|
|
4
|
+
const output = require('../output')
|
|
5
|
+
const store = require('../store')
|
|
6
|
+
|
|
7
|
+
const defaultConfig = {
|
|
8
|
+
enabled: true,
|
|
9
|
+
outputFile: './failed-tests.json',
|
|
10
|
+
clearOnSuccess: true,
|
|
11
|
+
includeStackTrace: true,
|
|
12
|
+
includeMetadata: true,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Failed Tests Tracker Plugin for CodeceptJS
|
|
17
|
+
*
|
|
18
|
+
* Tracks failed tests and saves them to a file for later re-execution.
|
|
19
|
+
*
|
|
20
|
+
* ## Configuration
|
|
21
|
+
*
|
|
22
|
+
* ```js
|
|
23
|
+
* "plugins": {
|
|
24
|
+
* "failedTestsTracker": {
|
|
25
|
+
* "enabled": true,
|
|
26
|
+
* "outputFile": "./failed-tests.json",
|
|
27
|
+
* "clearOnSuccess": true,
|
|
28
|
+
* "includeStackTrace": true,
|
|
29
|
+
* "includeMetadata": true
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param {object} config plugin configuration
|
|
35
|
+
*/
|
|
36
|
+
module.exports = function (config) {
|
|
37
|
+
const options = { ...defaultConfig, ...config }
|
|
38
|
+
let failedTests = []
|
|
39
|
+
let allTestsPassed = true
|
|
40
|
+
let workerFailedTests = new Map() // Track failed tests from workers
|
|
41
|
+
|
|
42
|
+
// Track test failures
|
|
43
|
+
event.dispatcher.on(event.test.failed, test => {
|
|
44
|
+
allTestsPassed = false
|
|
45
|
+
|
|
46
|
+
const failedTest = {
|
|
47
|
+
title: test.title,
|
|
48
|
+
fullTitle: test.fullTitle(),
|
|
49
|
+
file: test.file || (test.parent && test.parent.file),
|
|
50
|
+
uid: test.uid,
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Add parent suite information
|
|
55
|
+
if (test.parent) {
|
|
56
|
+
failedTest.suite = test.parent.title
|
|
57
|
+
failedTest.suiteFile = test.parent.file
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Add error information if available
|
|
61
|
+
if (test.err && options.includeStackTrace) {
|
|
62
|
+
failedTest.error = {
|
|
63
|
+
message: test.err.message || 'Test failed',
|
|
64
|
+
stack: test.err.stack || '',
|
|
65
|
+
name: test.err.name || 'Error',
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Add metadata if available
|
|
70
|
+
if (options.includeMetadata) {
|
|
71
|
+
failedTest.metadata = {
|
|
72
|
+
tags: test.tags || [],
|
|
73
|
+
meta: test.meta || {},
|
|
74
|
+
opts: test.opts || {},
|
|
75
|
+
duration: test.duration || 0,
|
|
76
|
+
retries: test.retries || 0,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Add BDD/Gherkin information if available
|
|
81
|
+
if (test.parent && test.parent.feature) {
|
|
82
|
+
failedTest.bdd = {
|
|
83
|
+
feature: test.parent.feature.name || test.parent.title,
|
|
84
|
+
scenario: test.title,
|
|
85
|
+
featureFile: test.parent.file,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
failedTests.push(failedTest)
|
|
90
|
+
output.print(`Failed Tests Tracker: Recorded failed test - ${test.title}`)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
// Save failed tests to file after all tests complete
|
|
94
|
+
event.dispatcher.on(event.all.result, (result) => {
|
|
95
|
+
const outputPath = path.resolve(process.cwd(), options.outputFile)
|
|
96
|
+
let allFailedTests = [...failedTests]
|
|
97
|
+
|
|
98
|
+
// In worker mode, collect failed tests from consolidated result
|
|
99
|
+
if (store.hasWorkers && result && result.tests) {
|
|
100
|
+
const workerFailedTests = result.tests.filter(test => test.state === 'failed' || test.err)
|
|
101
|
+
|
|
102
|
+
workerFailedTests.forEach(test => {
|
|
103
|
+
const failedTest = {
|
|
104
|
+
title: test.title,
|
|
105
|
+
fullTitle: test.fullTitle || test.title,
|
|
106
|
+
file: test.file || (test.parent && test.parent.file),
|
|
107
|
+
uid: test.uid,
|
|
108
|
+
timestamp: new Date().toISOString(),
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Add parent suite information
|
|
112
|
+
if (test.parent) {
|
|
113
|
+
failedTest.suite = test.parent.title
|
|
114
|
+
failedTest.suiteFile = test.parent.file
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Add error information if available
|
|
118
|
+
if (test.err && options.includeStackTrace) {
|
|
119
|
+
failedTest.error = {
|
|
120
|
+
message: test.err.message || 'Test failed',
|
|
121
|
+
stack: test.err.stack || '',
|
|
122
|
+
name: test.err.name || 'Error',
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Add metadata if available
|
|
127
|
+
if (options.includeMetadata) {
|
|
128
|
+
failedTest.metadata = {
|
|
129
|
+
tags: test.tags || [],
|
|
130
|
+
meta: test.meta || {},
|
|
131
|
+
opts: test.opts || {},
|
|
132
|
+
duration: test.duration || 0,
|
|
133
|
+
retries: test.retries || 0,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Add BDD/Gherkin information if available
|
|
138
|
+
if (test.parent && test.parent.feature) {
|
|
139
|
+
failedTest.bdd = {
|
|
140
|
+
feature: test.parent.feature.name || test.parent.title,
|
|
141
|
+
scenario: test.title,
|
|
142
|
+
featureFile: test.parent.file,
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
allFailedTests.push(failedTest)
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (allFailedTests.length === 0) {
|
|
151
|
+
if (options.clearOnSuccess && fs.existsSync(outputPath)) {
|
|
152
|
+
try {
|
|
153
|
+
fs.unlinkSync(outputPath)
|
|
154
|
+
output.print(`Failed Tests Tracker: Cleared previous failed tests file (all tests passed)`)
|
|
155
|
+
} catch (error) {
|
|
156
|
+
output.print(`Failed Tests Tracker: Could not clear failed tests file: ${error.message}`)
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
output.print(`Failed Tests Tracker: No failed tests to save`)
|
|
160
|
+
}
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const failedTestsData = {
|
|
165
|
+
timestamp: new Date().toISOString(),
|
|
166
|
+
totalFailedTests: allFailedTests.length,
|
|
167
|
+
codeceptVersion: require('../codecept').version(),
|
|
168
|
+
tests: allFailedTests,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
// Ensure directory exists
|
|
173
|
+
const dir = path.dirname(outputPath)
|
|
174
|
+
if (!fs.existsSync(dir)) {
|
|
175
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fs.writeFileSync(outputPath, JSON.stringify(failedTestsData, null, 2))
|
|
179
|
+
output.print(`Failed Tests Tracker: Saved ${allFailedTests.length} failed tests to ${outputPath}`)
|
|
180
|
+
} catch (error) {
|
|
181
|
+
output.print(`Failed Tests Tracker: Failed to save failed tests: ${error.message}`)
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// Reset state for new test runs
|
|
186
|
+
event.dispatcher.on(event.all.before, () => {
|
|
187
|
+
failedTests = []
|
|
188
|
+
allTestsPassed = true
|
|
189
|
+
workerFailedTests.clear()
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
// Handle worker mode - listen to workers.result event for consolidated results
|
|
193
|
+
event.dispatcher.on(event.workers.result, (result) => {
|
|
194
|
+
// This event is fired in worker mode with consolidated results
|
|
195
|
+
// The event.all.result handler above will process the consolidated data
|
|
196
|
+
})
|
|
197
|
+
}
|