codeceptjs 3.7.0-rc.1 → 3.7.1-beta.1
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/bin/codecept.js +1 -1
- package/lib/command/check.js +24 -9
- package/lib/effects.js +7 -2
- package/lib/event.js +2 -0
- package/lib/helper/Playwright.js +1 -1
- package/lib/helper/Puppeteer.js +1 -1
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/mocha/test.js +5 -2
- package/lib/plugin/analyze.js +51 -3
- package/lib/plugin/retryFailedStep.js +13 -14
- package/lib/plugin/retryTo.js +1 -1
- package/lib/plugin/screenshotOnFail.js +3 -4
- package/lib/plugin/tryTo.js +1 -1
- package/lib/recorder.js +1 -0
- package/lib/store.js +29 -5
- package/lib/utils.js +5 -5
- package/lib/within.js +2 -0
- package/package.json +2 -2
- package/typings/promiseBasedTypes.d.ts +506 -30
- package/typings/types.d.ts +536 -37
package/bin/codecept.js
CHANGED
|
@@ -62,7 +62,7 @@ program
|
|
|
62
62
|
.command('check')
|
|
63
63
|
.option(commandFlags.config.flag, commandFlags.config.description)
|
|
64
64
|
.description('Checks configuration and environment before running tests')
|
|
65
|
-
.option('-t, --timeout [ms]', 'timeout for checks in ms,
|
|
65
|
+
.option('-t, --timeout [ms]', 'timeout for checks in ms, 50000 by default')
|
|
66
66
|
.action(errorHandler(require('../lib/command/check')))
|
|
67
67
|
|
|
68
68
|
program
|
package/lib/command/check.js
CHANGED
|
@@ -25,6 +25,7 @@ module.exports = async function (options) {
|
|
|
25
25
|
ai: true, // we don't need to check AI
|
|
26
26
|
helpers: false,
|
|
27
27
|
setup: false,
|
|
28
|
+
teardown: false,
|
|
28
29
|
tests: false,
|
|
29
30
|
def: false,
|
|
30
31
|
}
|
|
@@ -87,9 +88,9 @@ module.exports = async function (options) {
|
|
|
87
88
|
|
|
88
89
|
if (config?.ai?.request) {
|
|
89
90
|
checks.ai = true
|
|
90
|
-
printCheck('ai', checks['ai'], '
|
|
91
|
+
printCheck('ai', checks['ai'], 'Configuration is enabled, request function is set')
|
|
91
92
|
} else {
|
|
92
|
-
printCheck('ai', checks['ai'], '
|
|
93
|
+
printCheck('ai', checks['ai'], 'Disabled')
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
printCheck('tests', checks['tests'], `Total: ${numTests} tests`)
|
|
@@ -131,22 +132,36 @@ module.exports = async function (options) {
|
|
|
131
132
|
if (Object.keys(helpers).length) {
|
|
132
133
|
const suite = container.mocha().suite
|
|
133
134
|
const test = createTest('test', () => {})
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
checks.setup = true
|
|
136
|
+
for (const helper of Object.values(helpers)) {
|
|
137
|
+
try {
|
|
136
138
|
if (helper._beforeSuite) await helper._beforeSuite(suite)
|
|
137
139
|
if (helper._before) await helper._before(test)
|
|
140
|
+
} catch (err) {
|
|
141
|
+
err.message = `${helper.constructor.name} helper: ${err.message}`
|
|
142
|
+
if (checks.setup instanceof Error) err.message = `${err.message}\n\n${checks.setup?.message || ''}`.trim()
|
|
143
|
+
checks.setup = err
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
printCheck('Helpers Before', checks['setup'], standardActingHelpers.some(h => Object.keys(helpers).includes(h)) ? 'Initializing browser' : '')
|
|
148
|
+
|
|
149
|
+
checks.teardown = true
|
|
150
|
+
for (const helper of Object.values(helpers).reverse()) {
|
|
151
|
+
try {
|
|
138
152
|
if (helper._passed) await helper._passed(test)
|
|
139
153
|
if (helper._after) await helper._after(test)
|
|
140
154
|
if (helper._finishTest) await helper._finishTest(suite)
|
|
141
155
|
if (helper._afterSuite) await helper._afterSuite(suite)
|
|
156
|
+
} catch (err) {
|
|
157
|
+
err.message = `${helper.constructor.name} helper: ${err.message}`
|
|
158
|
+
if (checks.teardown instanceof Error) err.message = `${err.message}\n\n${checks.teardown?.message || ''}`.trim()
|
|
159
|
+
checks.teardown = err
|
|
142
160
|
}
|
|
143
|
-
checks.setup = true
|
|
144
|
-
} catch (err) {
|
|
145
|
-
checks.setup = err
|
|
146
161
|
}
|
|
147
|
-
}
|
|
148
162
|
|
|
149
|
-
|
|
163
|
+
printCheck('Helpers After', checks['teardown'], standardActingHelpers.some(h => Object.keys(helpers).includes(h)) ? 'Closing browser' : '')
|
|
164
|
+
}
|
|
150
165
|
|
|
151
166
|
try {
|
|
152
167
|
definitions(configFile, { dryRun: true })
|
package/lib/effects.js
CHANGED
|
@@ -2,6 +2,7 @@ const recorder = require('./recorder')
|
|
|
2
2
|
const { debug } = require('./output')
|
|
3
3
|
const store = require('./store')
|
|
4
4
|
const event = require('./event')
|
|
5
|
+
const within = require('./within')
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* A utility function for CodeceptJS tests that acts as a soft assertion.
|
|
@@ -178,11 +179,14 @@ async function tryTo(callback) {
|
|
|
178
179
|
const sessionName = 'tryTo'
|
|
179
180
|
|
|
180
181
|
let result = false
|
|
182
|
+
let isAutoRetriesEnabled = store.autoRetries
|
|
181
183
|
return recorder.add(
|
|
182
184
|
sessionName,
|
|
183
185
|
() => {
|
|
184
186
|
recorder.session.start(sessionName)
|
|
185
|
-
|
|
187
|
+
isAutoRetriesEnabled = store.autoRetries
|
|
188
|
+
if (isAutoRetriesEnabled) debug('Auto retries disabled inside tryTo effect')
|
|
189
|
+
store.autoRetries = false
|
|
186
190
|
callback()
|
|
187
191
|
recorder.add(() => {
|
|
188
192
|
result = true
|
|
@@ -199,7 +203,7 @@ async function tryTo(callback) {
|
|
|
199
203
|
return recorder.add(
|
|
200
204
|
'result',
|
|
201
205
|
() => {
|
|
202
|
-
store.
|
|
206
|
+
store.autoRetries = isAutoRetriesEnabled
|
|
203
207
|
return result
|
|
204
208
|
},
|
|
205
209
|
true,
|
|
@@ -215,4 +219,5 @@ module.exports = {
|
|
|
215
219
|
hopeThat,
|
|
216
220
|
retryTo,
|
|
217
221
|
tryTo,
|
|
222
|
+
within,
|
|
218
223
|
}
|
package/lib/event.js
CHANGED
package/lib/helper/Playwright.js
CHANGED
|
@@ -484,7 +484,7 @@ class Playwright extends Helper {
|
|
|
484
484
|
this.currentRunningTest = test
|
|
485
485
|
|
|
486
486
|
recorder.retry({
|
|
487
|
-
retries:
|
|
487
|
+
retries: test?.opts?.conditionalRetries || 3,
|
|
488
488
|
when: err => {
|
|
489
489
|
if (!err || typeof err.message !== 'string') {
|
|
490
490
|
return false
|
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -312,7 +312,7 @@ class Puppeteer extends Helper {
|
|
|
312
312
|
this.sessionPages = {}
|
|
313
313
|
this.currentRunningTest = test
|
|
314
314
|
recorder.retry({
|
|
315
|
-
retries:
|
|
315
|
+
retries: test?.opts?.conditionalRetries || 3,
|
|
316
316
|
when: err => {
|
|
317
317
|
if (!err || typeof err.message !== 'string') {
|
|
318
318
|
return false
|
|
@@ -2,66 +2,66 @@
|
|
|
2
2
|
* Class to handle the interaction with the Dialog (Popup) Class from Puppeteer
|
|
3
3
|
*/
|
|
4
4
|
class Popup {
|
|
5
|
-
constructor(popup, defaultAction) {
|
|
6
|
-
this._popup = popup
|
|
7
|
-
this._actionType = ''
|
|
8
|
-
this._defaultAction = defaultAction
|
|
5
|
+
constructor(popup = null, defaultAction = '') {
|
|
6
|
+
this._popup = popup
|
|
7
|
+
this._actionType = ''
|
|
8
|
+
this._defaultAction = defaultAction
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
_assertValidActionType(action) {
|
|
12
12
|
if (['accept', 'cancel'].indexOf(action) === -1) {
|
|
13
|
-
throw new Error('Invalid Popup action type. Only "accept" or "cancel" actions are accepted')
|
|
13
|
+
throw new Error('Invalid Popup action type. Only "accept" or "cancel" actions are accepted')
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
set defaultAction(action) {
|
|
18
|
-
this._assertValidActionType(action)
|
|
19
|
-
this._defaultAction = action
|
|
18
|
+
this._assertValidActionType(action)
|
|
19
|
+
this._defaultAction = action
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
get defaultAction() {
|
|
23
|
-
return this._defaultAction
|
|
23
|
+
return this._defaultAction
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
get popup() {
|
|
27
|
-
return this._popup
|
|
27
|
+
return this._popup
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
set popup(popup) {
|
|
31
31
|
if (this._popup) {
|
|
32
|
-
|
|
32
|
+
return
|
|
33
33
|
}
|
|
34
|
-
this._popup = popup
|
|
34
|
+
this._popup = popup
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
get actionType() {
|
|
38
|
-
return this._actionType
|
|
38
|
+
return this._actionType
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
set actionType(action) {
|
|
42
|
-
this._assertValidActionType(action)
|
|
43
|
-
this._actionType = action
|
|
42
|
+
this._assertValidActionType(action)
|
|
43
|
+
this._actionType = action
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
clear() {
|
|
47
|
-
this._popup = null
|
|
48
|
-
this._actionType = ''
|
|
47
|
+
this._popup = null
|
|
48
|
+
this._actionType = ''
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
assertPopupVisible() {
|
|
52
52
|
if (!this._popup) {
|
|
53
|
-
throw new Error('There is no Popup visible')
|
|
53
|
+
throw new Error('There is no Popup visible')
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
assertPopupActionType(type) {
|
|
58
|
-
this.assertPopupVisible()
|
|
59
|
-
const expectedAction = this._actionType || this._defaultAction
|
|
58
|
+
this.assertPopupVisible()
|
|
59
|
+
const expectedAction = this._actionType || this._defaultAction
|
|
60
60
|
if (expectedAction !== type) {
|
|
61
|
-
throw new Error(`Popup action does not fit the expected action type. Expected popup action to be '${expectedAction}' not '${type}`)
|
|
61
|
+
throw new Error(`Popup action does not fit the expected action type. Expected popup action to be '${expectedAction}' not '${type}`)
|
|
62
62
|
}
|
|
63
|
-
this.clear()
|
|
63
|
+
this.clear()
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
module.exports = Popup
|
|
67
|
+
module.exports = Popup
|
package/lib/mocha/test.js
CHANGED
|
@@ -133,8 +133,10 @@ function cloneTest(test) {
|
|
|
133
133
|
return deserializeTest(serializeTest(test))
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
function testToFileName(test) {
|
|
137
|
-
let fileName =
|
|
136
|
+
function testToFileName(test, suffix = '') {
|
|
137
|
+
let fileName = test.title
|
|
138
|
+
|
|
139
|
+
if (suffix) fileName = `${fileName}_${suffix}`
|
|
138
140
|
// remove tags with empty string (disable for now)
|
|
139
141
|
// fileName = fileName.replace(/\@\w+/g, '')
|
|
140
142
|
fileName = fileName.slice(0, 100)
|
|
@@ -146,6 +148,7 @@ function testToFileName(test) {
|
|
|
146
148
|
// if (test.parent && test.parent.title) {
|
|
147
149
|
// fileName = `${clearString(test.parent.title)}_${fileName}`
|
|
148
150
|
// }
|
|
151
|
+
fileName = clearString(fileName).slice(0, 100)
|
|
149
152
|
return fileName
|
|
150
153
|
}
|
|
151
154
|
|
package/lib/plugin/analyze.js
CHANGED
|
@@ -60,7 +60,7 @@ const defaultConfig = {
|
|
|
60
60
|
|
|
61
61
|
If there is no groups of tests, say: "No patterns found"
|
|
62
62
|
Preserve error messages but cut them if they are too long.
|
|
63
|
-
Respond clearly and directly, without introductory words or phrases like
|
|
63
|
+
Respond clearly and directly, without introductory words or phrases like 'Of course,' 'Here is the answer,' etc.
|
|
64
64
|
Do not list more than 3 errors in the group.
|
|
65
65
|
If you identify that all tests in the group have the same tag, add this tag to the group report, otherwise ignore TAG section.
|
|
66
66
|
If you identify that all tests in the group have the same suite, add this suite to the group report, otherwise ignore SUITE section.
|
|
@@ -161,8 +161,56 @@ const defaultConfig = {
|
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
163
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
164
|
+
* Uses AI to analyze test failures and provide insights
|
|
165
|
+
*
|
|
166
|
+
* This plugin analyzes failed tests using AI to provide detailed explanations and group similar failures.
|
|
167
|
+
* When enabled with --ai flag, it generates reports after test execution.
|
|
168
|
+
*
|
|
169
|
+
* #### Usage
|
|
170
|
+
*
|
|
171
|
+
* ```js
|
|
172
|
+
* // in codecept.conf.js
|
|
173
|
+
* exports.config = {
|
|
174
|
+
* plugins: {
|
|
175
|
+
* analyze: {
|
|
176
|
+
* enabled: true,
|
|
177
|
+
* clusterize: 5,
|
|
178
|
+
* analyze: 2,
|
|
179
|
+
* vision: false
|
|
180
|
+
* }
|
|
181
|
+
* }
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* #### Configuration
|
|
186
|
+
*
|
|
187
|
+
* * `clusterize` (number) - minimum number of failures to trigger clustering analysis. Default: 5
|
|
188
|
+
* * `analyze` (number) - maximum number of individual test failures to analyze in detail. Default: 2
|
|
189
|
+
* * `vision` (boolean) - enables visual analysis of test screenshots. Default: false
|
|
190
|
+
* * `categories` (array) - list of failure categories for classification. Defaults to:
|
|
191
|
+
* - Browser connection error / browser crash
|
|
192
|
+
* - Network errors (server error, timeout, etc)
|
|
193
|
+
* - HTML / page elements (not found, not visible, etc)
|
|
194
|
+
* - Navigation errors (404, etc)
|
|
195
|
+
* - Code errors (syntax error, JS errors, etc)
|
|
196
|
+
* - Library & framework errors
|
|
197
|
+
* - Data errors (password incorrect, invalid format, etc)
|
|
198
|
+
* - Assertion failures
|
|
199
|
+
* - Other errors
|
|
200
|
+
* * `prompts` (object) - customize AI prompts for analysis
|
|
201
|
+
* - `clusterize` - prompt for clustering analysis
|
|
202
|
+
* - `analyze` - prompt for individual test analysis
|
|
203
|
+
*
|
|
204
|
+
* #### Features
|
|
205
|
+
*
|
|
206
|
+
* * Groups similar failures when number of failures >= clusterize value
|
|
207
|
+
* * Provides detailed analysis of individual failures
|
|
208
|
+
* * Analyzes screenshots if vision=true and screenshots are available
|
|
209
|
+
* * Classifies failures into predefined categories
|
|
210
|
+
* * Suggests possible causes and solutions
|
|
211
|
+
*
|
|
212
|
+
* @param {Object} config - Plugin configuration
|
|
213
|
+
* @returns {void}
|
|
166
214
|
*/
|
|
167
215
|
module.exports = function (config = {}) {
|
|
168
216
|
config = Object.assign(defaultConfig, config)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
const event = require('../event')
|
|
2
2
|
const recorder = require('../recorder')
|
|
3
|
-
const
|
|
4
|
-
const { log } = require('../output')
|
|
5
|
-
|
|
3
|
+
const store = require('../store')
|
|
6
4
|
const defaultConfig = {
|
|
7
5
|
retries: 3,
|
|
8
6
|
defaultIgnoredSteps: ['amOnPage', 'wait*', 'send*', 'execute*', 'run*', 'have*'],
|
|
@@ -70,9 +68,9 @@ const defaultConfig = {
|
|
|
70
68
|
* Use scenario configuration to disable plugin for a test
|
|
71
69
|
*
|
|
72
70
|
* ```js
|
|
73
|
-
* Scenario('scenario tite', () => {
|
|
71
|
+
* Scenario('scenario tite', { disableRetryFailedStep: true }, () => {
|
|
74
72
|
* // test goes here
|
|
75
|
-
* })
|
|
73
|
+
* })
|
|
76
74
|
* ```
|
|
77
75
|
*
|
|
78
76
|
*/
|
|
@@ -85,19 +83,14 @@ module.exports = config => {
|
|
|
85
83
|
|
|
86
84
|
const when = err => {
|
|
87
85
|
if (!enableRetry) return
|
|
88
|
-
const store = require('../store')
|
|
89
86
|
if (store.debugMode) return false
|
|
87
|
+
if (!store.autoRetries) return false
|
|
90
88
|
if (customWhen) return customWhen(err)
|
|
91
89
|
return true
|
|
92
90
|
}
|
|
93
91
|
config.when = when
|
|
94
92
|
|
|
95
93
|
event.dispatcher.on(event.step.started, step => {
|
|
96
|
-
if (process.env.TRY_TO === 'true') {
|
|
97
|
-
log('Info: RetryFailedStep plugin is disabled inside tryTo block')
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
|
|
101
94
|
// if a step is ignored - return
|
|
102
95
|
for (const ignored of config.ignoredSteps) {
|
|
103
96
|
if (step.name === ignored) return
|
|
@@ -113,9 +106,15 @@ module.exports = config => {
|
|
|
113
106
|
})
|
|
114
107
|
|
|
115
108
|
event.dispatcher.on(event.test.before, test => {
|
|
116
|
-
|
|
117
|
-
//
|
|
118
|
-
|
|
109
|
+
// pass disableRetryFailedStep is a preferred way to disable retries
|
|
110
|
+
// test.disableRetryFailedStep is used for backward compatibility
|
|
111
|
+
if (test.opts.disableRetryFailedStep || test.disableRetryFailedStep) {
|
|
112
|
+
store.autoRetries = false
|
|
113
|
+
return // disable retry when a test is not active
|
|
114
|
+
}
|
|
115
|
+
// this option is used to set the retries inside _before() block of helpers
|
|
116
|
+
store.autoRetries = true
|
|
117
|
+
test.opts.conditionalRetries = config.retries
|
|
119
118
|
recorder.retry(config)
|
|
120
119
|
})
|
|
121
120
|
}
|
package/lib/plugin/retryTo.js
CHANGED
|
@@ -6,7 +6,7 @@ const defaultConfig = {
|
|
|
6
6
|
|
|
7
7
|
module.exports = function (config) {
|
|
8
8
|
config = Object.assign(defaultConfig, config)
|
|
9
|
-
console.log(`Deprecation Warning: 'retryTo' has been moved to the 'codeceptjs/effects' module
|
|
9
|
+
console.log(`Deprecation Warning: 'retryTo' has been moved to the 'codeceptjs/effects' module. Disable retryTo plugin to remove this warning.`)
|
|
10
10
|
|
|
11
11
|
if (config.registerGlobal) {
|
|
12
12
|
global.retryTo = retryTo
|
|
@@ -83,13 +83,12 @@ module.exports = function (config) {
|
|
|
83
83
|
async () => {
|
|
84
84
|
const dataType = 'image/png'
|
|
85
85
|
// This prevents data driven to be included in the failed screenshot file name
|
|
86
|
-
let fileName
|
|
86
|
+
let fileName
|
|
87
87
|
|
|
88
88
|
if (options.uniqueScreenshotNames && test) {
|
|
89
|
-
|
|
90
|
-
fileName = `${fileName.substring(0, 10)}_${uuid}.failed.png`
|
|
89
|
+
fileName = `${testToFileName(test, _getUUID(test))}.failed.png`
|
|
91
90
|
} else {
|
|
92
|
-
fileName
|
|
91
|
+
fileName = `${testToFileName(test)}.failed.png`
|
|
93
92
|
}
|
|
94
93
|
output.plugin('screenshotOnFail', 'Test failed, try to save a screenshot')
|
|
95
94
|
|
package/lib/plugin/tryTo.js
CHANGED
|
@@ -6,7 +6,7 @@ const defaultConfig = {
|
|
|
6
6
|
|
|
7
7
|
module.exports = function (config) {
|
|
8
8
|
config = Object.assign(defaultConfig, config)
|
|
9
|
-
console.log(`Deprecation Warning: 'tryTo' has been moved to the 'codeceptjs/effects' module
|
|
9
|
+
console.log(`Deprecation Warning: 'tryTo' has been moved to the 'codeceptjs/effects' module. Disable tryTo plugin to remove this warning.`)
|
|
10
10
|
|
|
11
11
|
if (config.registerGlobal) {
|
|
12
12
|
global.tryTo = tryTo
|
package/lib/recorder.js
CHANGED
|
@@ -192,6 +192,7 @@ module.exports = {
|
|
|
192
192
|
.pop()
|
|
193
193
|
// no retries or unnamed tasks
|
|
194
194
|
debug(`${currentQueue()} Running | ${taskName} | Timeout: ${timeout || 'None'}`)
|
|
195
|
+
if (retryOpts) debug(`${currentQueue()} Retry opts`, JSON.stringify(retryOpts))
|
|
195
196
|
|
|
196
197
|
if (!retryOpts || !taskName || !retry) {
|
|
197
198
|
const [promise, timer] = getTimeoutPromise(timeout, taskName)
|
package/lib/store.js
CHANGED
|
@@ -3,17 +3,41 @@
|
|
|
3
3
|
* @namespace
|
|
4
4
|
*/
|
|
5
5
|
const store = {
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* If we are in --debug mode
|
|
8
|
+
* @type {boolean}
|
|
9
|
+
*/
|
|
7
10
|
debugMode: false,
|
|
8
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Is timeouts enabled
|
|
14
|
+
* @type {boolean}
|
|
15
|
+
*/
|
|
9
16
|
timeouts: true,
|
|
10
|
-
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* If auto-retries are enabled by retryFailedStep plugin
|
|
20
|
+
* tryTo effect disables them
|
|
21
|
+
* @type {boolean}
|
|
22
|
+
*/
|
|
23
|
+
autoRetries: false,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Tests are executed via dry-run
|
|
27
|
+
* @type {boolean}
|
|
28
|
+
*/
|
|
11
29
|
dryRun: false,
|
|
12
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* If we are in pause mode
|
|
32
|
+
* @type {boolean}
|
|
33
|
+
*/
|
|
13
34
|
onPause: false,
|
|
35
|
+
|
|
36
|
+
// current object states
|
|
37
|
+
|
|
14
38
|
/** @type {CodeceptJS.Test | null} */
|
|
15
39
|
currentTest: null,
|
|
16
|
-
/** @type {
|
|
40
|
+
/** @type {CodeceptJS.Step | null} */
|
|
17
41
|
currentStep: null,
|
|
18
42
|
/** @type {CodeceptJS.Suite | null} */
|
|
19
43
|
currentSuite: null,
|
package/lib/utils.js
CHANGED
|
@@ -13,7 +13,7 @@ function deepMerge(target, source) {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
module.exports.genTestId = test => {
|
|
16
|
-
return require('crypto').createHash('sha256').update(test.fullTitle()).digest('base64').slice(0, -2)
|
|
16
|
+
return this.clearString(require('crypto').createHash('sha256').update(test.fullTitle()).digest('base64').slice(0, -2))
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
module.exports.deepMerge = deepMerge
|
|
@@ -94,19 +94,19 @@ module.exports.template = function (template, data) {
|
|
|
94
94
|
/**
|
|
95
95
|
* Make first char uppercase.
|
|
96
96
|
* @param {string} str
|
|
97
|
-
* @returns {string}
|
|
97
|
+
* @returns {string | undefined}
|
|
98
98
|
*/
|
|
99
99
|
module.exports.ucfirst = function (str) {
|
|
100
|
-
return str.charAt(0).toUpperCase() + str.substr(1)
|
|
100
|
+
if (str) return str.charAt(0).toUpperCase() + str.substr(1)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
104
|
* Make first char lowercase.
|
|
105
105
|
* @param {string} str
|
|
106
|
-
* @returns {string}
|
|
106
|
+
* @returns {string | undefined}
|
|
107
107
|
*/
|
|
108
108
|
module.exports.lcfirst = function (str) {
|
|
109
|
-
return str.charAt(0).toLowerCase() + str.substr(1)
|
|
109
|
+
if (str) return str.charAt(0).toLowerCase() + str.substr(1)
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
module.exports.chunkArray = function (arr, chunk) {
|
package/lib/within.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.1-beta.1",
|
|
4
4
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"acceptance",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"glob": ">=9.0.0 <12",
|
|
99
99
|
"fuse.js": "^7.0.0",
|
|
100
100
|
"html-minifier-terser": "7.2.0",
|
|
101
|
-
"inquirer": "
|
|
101
|
+
"inquirer": "8.2.6",
|
|
102
102
|
"invisi-data": "^1.0.0",
|
|
103
103
|
"joi": "17.13.3",
|
|
104
104
|
"js-beautify": "1.15.1",
|