codeceptjs 3.6.4 → 3.6.5-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 +84 -63
- package/lib/assert/empty.js +19 -19
- package/lib/assert/equal.js +32 -30
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +42 -42
- package/lib/assert/throws.js +13 -11
- package/lib/assert/truth.js +17 -18
- package/lib/command/configMigrate.js +57 -52
- package/lib/command/definitions.js +88 -88
- package/lib/command/dryRun.js +65 -63
- package/lib/command/generate.js +191 -181
- package/lib/command/info.js +39 -37
- package/lib/command/init.js +289 -286
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple.js +113 -93
- package/lib/command/run-rerun.js +22 -22
- package/lib/command/run-workers.js +63 -63
- package/lib/command/run.js +24 -26
- package/lib/command/utils.js +64 -63
- package/lib/data/context.js +60 -60
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +26 -20
- package/lib/helper/AI.js +67 -65
- package/lib/helper/ApiDataFactory.js +72 -69
- package/lib/helper/Appium.js +409 -379
- package/lib/helper/ExpectHelper.js +214 -248
- package/lib/helper/FileSystem.js +77 -78
- package/lib/helper/GraphQL.js +44 -43
- package/lib/helper/GraphQLDataFactory.js +49 -50
- package/lib/helper/JSONResponse.js +64 -62
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +12 -12
- package/lib/helper/Nightmare.js +664 -572
- package/lib/helper/Playwright.js +1320 -1211
- package/lib/helper/Protractor.js +663 -629
- package/lib/helper/Puppeteer.js +1232 -1124
- package/lib/helper/REST.js +87 -72
- package/lib/helper/TestCafe.js +490 -491
- package/lib/helper/WebDriver.js +1294 -1156
- package/lib/interfaces/bdd.js +38 -51
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +122 -111
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -23
- package/lib/listener/exit.js +12 -12
- package/lib/listener/helpers.js +42 -42
- package/lib/listener/mocha.js +11 -11
- package/lib/listener/retry.js +32 -30
- package/lib/listener/steps.js +50 -51
- package/lib/listener/timeout.js +53 -53
- package/lib/plugin/allure.js +14 -14
- package/lib/plugin/autoDelay.js +29 -36
- package/lib/plugin/autoLogin.js +70 -66
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +92 -77
- package/lib/plugin/customLocator.js +20 -19
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +37 -37
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +66 -63
- package/lib/plugin/pauseOnFail.js +10 -10
- package/lib/plugin/retryFailedStep.js +31 -38
- package/lib/plugin/retryTo.js +28 -28
- package/lib/plugin/screenshotOnFail.js +107 -86
- package/lib/plugin/selenoid.js +131 -117
- package/lib/plugin/standardActingHelpers.js +2 -8
- package/lib/plugin/stepByStepReport.js +102 -92
- package/lib/plugin/stepTimeout.js +23 -22
- package/lib/plugin/subtitles.js +34 -34
- package/lib/plugin/tryTo.js +39 -29
- package/lib/plugin/wdio.js +77 -72
- package/lib/template/heal.js +11 -14
- package/package.json +4 -2
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +9 -9
- package/translations/it-IT.js +1 -1
- package/translations/ja-JP.js +1 -1
- package/translations/pl-PL.js +1 -1
- package/translations/pt-BR.js +1 -1
- package/translations/ru-RU.js +1 -1
- package/translations/zh-CN.js +1 -1
- package/translations/zh-TW.js +1 -1
- package/typings/promiseBasedTypes.d.ts +238 -0
- package/typings/types.d.ts +32 -0
package/lib/plugin/allure.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
module.exports = () => {
|
|
2
|
-
console.log('Allure plugin was moved to @codeceptjs/allure-legacy. Please install it and update your config')
|
|
3
|
-
console.log()
|
|
4
|
-
console.log('npm install @codeceptjs/allure-legacy --save-dev')
|
|
5
|
-
console.log()
|
|
6
|
-
console.log('Then update your config to use it:')
|
|
7
|
-
console.log()
|
|
8
|
-
console.log('plugins: {')
|
|
9
|
-
console.log(' allure: {')
|
|
10
|
-
console.log(' enabled: true,')
|
|
11
|
-
console.log(
|
|
12
|
-
console.log(' }')
|
|
13
|
-
console.log('}')
|
|
14
|
-
console.log()
|
|
15
|
-
}
|
|
2
|
+
console.log('Allure plugin was moved to @codeceptjs/allure-legacy. Please install it and update your config')
|
|
3
|
+
console.log()
|
|
4
|
+
console.log('npm install @codeceptjs/allure-legacy --save-dev')
|
|
5
|
+
console.log()
|
|
6
|
+
console.log('Then update your config to use it:')
|
|
7
|
+
console.log()
|
|
8
|
+
console.log('plugins: {')
|
|
9
|
+
console.log(' allure: {')
|
|
10
|
+
console.log(' enabled: true,')
|
|
11
|
+
console.log(" require: '@codeceptjs/allure-legacy',")
|
|
12
|
+
console.log(' }')
|
|
13
|
+
console.log('}')
|
|
14
|
+
console.log()
|
|
15
|
+
}
|
package/lib/plugin/autoDelay.js
CHANGED
|
@@ -1,24 +1,17 @@
|
|
|
1
|
-
const Container = require('../container')
|
|
2
|
-
const store = require('../store')
|
|
3
|
-
const recorder = require('../recorder')
|
|
4
|
-
const event = require('../event')
|
|
5
|
-
const log = require('../output').log
|
|
6
|
-
const supportedHelpers = require('./standardActingHelpers').slice()
|
|
1
|
+
const Container = require('../container')
|
|
2
|
+
const store = require('../store')
|
|
3
|
+
const recorder = require('../recorder')
|
|
4
|
+
const event = require('../event')
|
|
5
|
+
const log = require('../output').log
|
|
6
|
+
const supportedHelpers = require('./standardActingHelpers').slice()
|
|
7
7
|
|
|
8
|
-
const methodsToDelay = [
|
|
9
|
-
'click',
|
|
10
|
-
'fillField',
|
|
11
|
-
'checkOption',
|
|
12
|
-
'pressKey',
|
|
13
|
-
'doubleClick',
|
|
14
|
-
'rightClick',
|
|
15
|
-
];
|
|
8
|
+
const methodsToDelay = ['click', 'fillField', 'checkOption', 'pressKey', 'doubleClick', 'rightClick']
|
|
16
9
|
|
|
17
10
|
const defaultConfig = {
|
|
18
11
|
methods: methodsToDelay,
|
|
19
12
|
delayBefore: 100,
|
|
20
13
|
delayAfter: 200,
|
|
21
|
-
}
|
|
14
|
+
}
|
|
22
15
|
|
|
23
16
|
/**
|
|
24
17
|
*
|
|
@@ -59,41 +52,41 @@ const defaultConfig = {
|
|
|
59
52
|
*
|
|
60
53
|
*/
|
|
61
54
|
module.exports = function (config) {
|
|
62
|
-
supportedHelpers.push('REST')
|
|
63
|
-
const helpers = Container.helpers()
|
|
64
|
-
let helper
|
|
55
|
+
supportedHelpers.push('REST')
|
|
56
|
+
const helpers = Container.helpers()
|
|
57
|
+
let helper
|
|
65
58
|
|
|
66
|
-
config = Object.assign(defaultConfig, config)
|
|
59
|
+
config = Object.assign(defaultConfig, config)
|
|
67
60
|
|
|
68
61
|
for (const helperName of supportedHelpers) {
|
|
69
62
|
if (Object.keys(helpers).indexOf(helperName) > -1) {
|
|
70
|
-
helper = helpers[helperName]
|
|
63
|
+
helper = helpers[helperName]
|
|
71
64
|
}
|
|
72
65
|
}
|
|
73
66
|
|
|
74
|
-
if (!helper) return
|
|
67
|
+
if (!helper) return // no helpers for auto-delay
|
|
75
68
|
|
|
76
69
|
event.dispatcher.on(event.step.before, (step) => {
|
|
77
|
-
if (config.methods.indexOf(step.helperMethod) < 0) return
|
|
70
|
+
if (config.methods.indexOf(step.helperMethod) < 0) return // skip non-actions
|
|
78
71
|
|
|
79
72
|
recorder.add('auto-delay', async () => {
|
|
80
|
-
if (store.debugMode) return
|
|
81
|
-
log(`Delaying for ${config.delayBefore}ms`)
|
|
73
|
+
if (store.debugMode) return // no need to delay in debug
|
|
74
|
+
log(`Delaying for ${config.delayBefore}ms`)
|
|
82
75
|
return new Promise((resolve) => {
|
|
83
|
-
setTimeout(resolve, config.delayBefore)
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
})
|
|
76
|
+
setTimeout(resolve, config.delayBefore)
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
})
|
|
87
80
|
|
|
88
81
|
event.dispatcher.on(event.step.after, (step) => {
|
|
89
|
-
if (config.methods.indexOf(step.helperMethod) < 0) return
|
|
82
|
+
if (config.methods.indexOf(step.helperMethod) < 0) return // skip non-actions
|
|
90
83
|
|
|
91
84
|
recorder.add('auto-delay', async () => {
|
|
92
|
-
if (store.debugMode) return
|
|
93
|
-
log(`Delaying for ${config.delayAfter}ms`)
|
|
85
|
+
if (store.debugMode) return // no need to delay in debug
|
|
86
|
+
log(`Delaying for ${config.delayAfter}ms`)
|
|
94
87
|
return new Promise((resolve) => {
|
|
95
|
-
setTimeout(resolve, config.delayAfter)
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
}
|
|
88
|
+
setTimeout(resolve, config.delayAfter)
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
}
|
package/lib/plugin/autoLogin.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const { fileExists } = require('../utils')
|
|
4
|
-
const container = require('../container')
|
|
5
|
-
const store = require('../store')
|
|
6
|
-
const recorder = require('../recorder')
|
|
7
|
-
const { debug } = require('../output')
|
|
8
|
-
const isAsyncFunction = require('../utils').isAsyncFunction
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const { fileExists } = require('../utils')
|
|
4
|
+
const container = require('../container')
|
|
5
|
+
const store = require('../store')
|
|
6
|
+
const recorder = require('../recorder')
|
|
7
|
+
const { debug } = require('../output')
|
|
8
|
+
const isAsyncFunction = require('../utils').isAsyncFunction
|
|
9
9
|
|
|
10
10
|
const defaultUser = {
|
|
11
|
-
fetch: I => I.grabCookie(),
|
|
11
|
+
fetch: (I) => I.grabCookie(),
|
|
12
12
|
check: () => {},
|
|
13
13
|
restore: (I, cookies) => {
|
|
14
|
-
I.amOnPage('/')
|
|
15
|
-
I.setCookie(cookies)
|
|
14
|
+
I.amOnPage('/') // open a page
|
|
15
|
+
I.setCookie(cookies)
|
|
16
16
|
},
|
|
17
|
-
}
|
|
17
|
+
}
|
|
18
18
|
|
|
19
19
|
const defaultConfig = {
|
|
20
20
|
saveToFile: false,
|
|
21
21
|
inject: 'login',
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Logs user in for the first test and reuses session for next tests.
|
|
@@ -249,88 +249,92 @@ const defaultConfig = {
|
|
|
249
249
|
* })
|
|
250
250
|
*
|
|
251
251
|
*
|
|
252
|
-
*/
|
|
252
|
+
*/
|
|
253
253
|
module.exports = function (config) {
|
|
254
|
-
config = Object.assign(defaultConfig, config)
|
|
255
|
-
Object.keys(config.users).map(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
254
|
+
config = Object.assign(defaultConfig, config)
|
|
255
|
+
Object.keys(config.users).map(
|
|
256
|
+
(u) =>
|
|
257
|
+
(config.users[u] = {
|
|
258
|
+
...defaultUser,
|
|
259
|
+
...config.users[u],
|
|
260
|
+
}),
|
|
261
|
+
)
|
|
259
262
|
|
|
260
263
|
if (config.saveToFile) {
|
|
261
264
|
// loading from file
|
|
262
265
|
for (const name in config.users) {
|
|
263
|
-
const fileName = path.join(global.output_dir, `${name}_session.json`)
|
|
264
|
-
if (!fileExists(fileName)) continue
|
|
265
|
-
const data = fs.readFileSync(fileName).toString()
|
|
266
|
+
const fileName = path.join(global.output_dir, `${name}_session.json`)
|
|
267
|
+
if (!fileExists(fileName)) continue
|
|
268
|
+
const data = fs.readFileSync(fileName).toString()
|
|
266
269
|
try {
|
|
267
|
-
store[`${name}_session`] = JSON.parse(data)
|
|
270
|
+
store[`${name}_session`] = JSON.parse(data)
|
|
268
271
|
} catch (err) {
|
|
269
|
-
throw new Error(`Could not load session from ${fileName}\n${err}`)
|
|
272
|
+
throw new Error(`Could not load session from ${fileName}\n${err}`)
|
|
270
273
|
}
|
|
271
|
-
debug(`Loaded user session for ${name}`)
|
|
274
|
+
debug(`Loaded user session for ${name}`)
|
|
272
275
|
}
|
|
273
276
|
}
|
|
274
277
|
|
|
275
278
|
const loginFunction = async (name) => {
|
|
276
|
-
const userSession = config.users[name]
|
|
277
|
-
const I = container.support('I')
|
|
278
|
-
const cookies = store[`${name}_session`]
|
|
279
|
-
const shouldAwait =
|
|
280
|
-
|| isAsyncFunction(userSession.restore)
|
|
281
|
-
|| isAsyncFunction(userSession.check);
|
|
279
|
+
const userSession = config.users[name]
|
|
280
|
+
const I = container.support('I')
|
|
281
|
+
const cookies = store[`${name}_session`]
|
|
282
|
+
const shouldAwait =
|
|
283
|
+
isAsyncFunction(userSession.login) || isAsyncFunction(userSession.restore) || isAsyncFunction(userSession.check)
|
|
282
284
|
|
|
283
285
|
const loginAndSave = async () => {
|
|
284
286
|
if (shouldAwait) {
|
|
285
|
-
await userSession.login(I)
|
|
287
|
+
await userSession.login(I)
|
|
286
288
|
} else {
|
|
287
|
-
userSession.login(I)
|
|
289
|
+
userSession.login(I)
|
|
288
290
|
}
|
|
289
291
|
|
|
290
|
-
const cookies = await userSession.fetch(I)
|
|
292
|
+
const cookies = await userSession.fetch(I)
|
|
291
293
|
if (!cookies) {
|
|
292
|
-
debug(
|
|
293
|
-
return
|
|
294
|
+
debug("Cannot save user session with empty cookies from auto login's fetch method")
|
|
295
|
+
return
|
|
294
296
|
}
|
|
295
297
|
if (config.saveToFile) {
|
|
296
|
-
debug(`Saved user session into file for ${name}`)
|
|
297
|
-
fs.writeFileSync(path.join(global.output_dir, `${name}_session.json`), JSON.stringify(cookies))
|
|
298
|
+
debug(`Saved user session into file for ${name}`)
|
|
299
|
+
fs.writeFileSync(path.join(global.output_dir, `${name}_session.json`), JSON.stringify(cookies))
|
|
298
300
|
}
|
|
299
|
-
store[`${name}_session`] = cookies
|
|
300
|
-
}
|
|
301
|
+
store[`${name}_session`] = cookies
|
|
302
|
+
}
|
|
301
303
|
|
|
302
|
-
if (!cookies) return loginAndSave()
|
|
304
|
+
if (!cookies) return loginAndSave()
|
|
303
305
|
|
|
304
|
-
recorder.session.start('check login')
|
|
306
|
+
recorder.session.start('check login')
|
|
305
307
|
if (shouldAwait) {
|
|
306
|
-
await userSession.restore(I, cookies)
|
|
307
|
-
await userSession.check(I, cookies)
|
|
308
|
+
await userSession.restore(I, cookies)
|
|
309
|
+
await userSession.check(I, cookies)
|
|
308
310
|
} else {
|
|
309
|
-
userSession.restore(I, cookies)
|
|
310
|
-
userSession.check(I, cookies)
|
|
311
|
+
userSession.restore(I, cookies)
|
|
312
|
+
userSession.check(I, cookies)
|
|
311
313
|
}
|
|
312
314
|
recorder.session.catch((err) => {
|
|
313
|
-
debug(`Failed auto login for ${name} due to ${err}`)
|
|
314
|
-
debug('Logging in again')
|
|
315
|
-
recorder.session.start('auto login')
|
|
316
|
-
return loginAndSave()
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
315
|
+
debug(`Failed auto login for ${name} due to ${err}`)
|
|
316
|
+
debug('Logging in again')
|
|
317
|
+
recorder.session.start('auto login')
|
|
318
|
+
return loginAndSave()
|
|
319
|
+
.then(() => {
|
|
320
|
+
recorder.add(() => recorder.session.restore('auto login'))
|
|
321
|
+
recorder.catch(() => debug('continue'))
|
|
322
|
+
})
|
|
323
|
+
.catch((err) => {
|
|
324
|
+
recorder.session.restore('auto login')
|
|
325
|
+
recorder.session.restore('check login')
|
|
326
|
+
recorder.throw(err)
|
|
327
|
+
})
|
|
328
|
+
})
|
|
325
329
|
recorder.add(() => {
|
|
326
|
-
recorder.session.restore('check login')
|
|
327
|
-
})
|
|
330
|
+
recorder.session.restore('check login')
|
|
331
|
+
})
|
|
328
332
|
|
|
329
|
-
return recorder.promise()
|
|
330
|
-
}
|
|
333
|
+
return recorder.promise()
|
|
334
|
+
}
|
|
331
335
|
|
|
332
336
|
// adding this to DI container
|
|
333
|
-
const support = {}
|
|
334
|
-
support[config.inject] = loginFunction
|
|
335
|
-
container.append({ support })
|
|
336
|
-
}
|
|
337
|
+
const support = {}
|
|
338
|
+
support[config.inject] = loginFunction
|
|
339
|
+
container.append({ support })
|
|
340
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const event = require('../event')
|
|
2
|
-
const recorder = require('../recorder')
|
|
3
|
-
const { MetaStep } = require('../step')
|
|
1
|
+
const event = require('../event')
|
|
2
|
+
const recorder = require('../recorder')
|
|
3
|
+
const { MetaStep } = require('../step')
|
|
4
4
|
|
|
5
|
-
let currentCommentStep
|
|
5
|
+
let currentCommentStep
|
|
6
6
|
|
|
7
|
-
const defaultGlobalName = '__'
|
|
7
|
+
const defaultGlobalName = '__'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Add descriptive nested steps for your tests:
|
|
@@ -101,36 +101,36 @@ const defaultGlobalName = '__';
|
|
|
101
101
|
*/
|
|
102
102
|
module.exports = function (config) {
|
|
103
103
|
event.dispatcher.on(event.test.started, () => {
|
|
104
|
-
currentCommentStep = null
|
|
105
|
-
})
|
|
104
|
+
currentCommentStep = null
|
|
105
|
+
})
|
|
106
106
|
|
|
107
107
|
event.dispatcher.on(event.step.started, (step) => {
|
|
108
108
|
if (currentCommentStep) {
|
|
109
|
-
const metaStep = getRootMetaStep(step)
|
|
109
|
+
const metaStep = getRootMetaStep(step)
|
|
110
110
|
|
|
111
111
|
if (metaStep !== currentCommentStep) {
|
|
112
|
-
metaStep.metaStep = currentCommentStep
|
|
112
|
+
metaStep.metaStep = currentCommentStep
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
})
|
|
115
|
+
})
|
|
116
116
|
|
|
117
117
|
if (config.registerGlobal) {
|
|
118
118
|
if (config.registerGlobal === true) {
|
|
119
|
-
config.registerGlobal = defaultGlobalName
|
|
119
|
+
config.registerGlobal = defaultGlobalName
|
|
120
120
|
}
|
|
121
|
-
global[config.registerGlobal] = setCommentString
|
|
121
|
+
global[config.registerGlobal] = setCommentString
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
return setCommentString
|
|
125
|
-
}
|
|
124
|
+
return setCommentString
|
|
125
|
+
}
|
|
126
126
|
|
|
127
127
|
function getRootMetaStep(step) {
|
|
128
|
-
if (step.metaStep) return getRootMetaStep(step.metaStep)
|
|
129
|
-
return step
|
|
128
|
+
if (step.metaStep) return getRootMetaStep(step.metaStep)
|
|
129
|
+
return step
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
function setCommentString(string) {
|
|
133
133
|
recorder.add('set comment metastep', () => {
|
|
134
|
-
currentCommentStep = new MetaStep(String.raw(string), '')
|
|
135
|
-
})
|
|
134
|
+
currentCommentStep = new MetaStep(String.raw(string), '')
|
|
135
|
+
})
|
|
136
136
|
}
|
package/lib/plugin/coverage.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const debugModule = require('debug')
|
|
2
|
-
const { CoverageReport } = require('monocart-coverage-reports')
|
|
3
|
-
const Container = require('../container')
|
|
4
|
-
const recorder = require('../recorder')
|
|
5
|
-
const event = require('../event')
|
|
6
|
-
const output = require('../output')
|
|
7
|
-
const { deepMerge } = require('../utils')
|
|
1
|
+
const debugModule = require('debug')
|
|
2
|
+
const { CoverageReport } = require('monocart-coverage-reports')
|
|
3
|
+
const Container = require('../container')
|
|
4
|
+
const recorder = require('../recorder')
|
|
5
|
+
const event = require('../event')
|
|
6
|
+
const output = require('../output')
|
|
7
|
+
const { deepMerge } = require('../utils')
|
|
8
8
|
|
|
9
9
|
const defaultConfig = {
|
|
10
10
|
name: 'CodeceptJS Coverage Report',
|
|
11
11
|
outputDir: 'output/coverage',
|
|
12
|
-
}
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
const supportedHelpers = ['Puppeteer', 'Playwright', 'WebDriver']
|
|
14
|
+
const supportedHelpers = ['Puppeteer', 'Playwright', 'WebDriver']
|
|
15
15
|
|
|
16
16
|
const v8CoverageHelpers = {
|
|
17
17
|
Playwright: {
|
|
@@ -23,15 +23,15 @@ const v8CoverageHelpers = {
|
|
|
23
23
|
page.coverage.startCSSCoverage({
|
|
24
24
|
resetOnNavigation: false,
|
|
25
25
|
}),
|
|
26
|
-
])
|
|
26
|
+
])
|
|
27
27
|
},
|
|
28
28
|
takeCoverage: async (page, coverageReport) => {
|
|
29
29
|
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
30
30
|
page.coverage.stopJSCoverage(),
|
|
31
31
|
page.coverage.stopCSSCoverage(),
|
|
32
|
-
])
|
|
33
|
-
const coverageList = [...jsCoverage, ...cssCoverage]
|
|
34
|
-
await coverageReport.add(coverageList)
|
|
32
|
+
])
|
|
33
|
+
const coverageList = [...jsCoverage, ...cssCoverage]
|
|
34
|
+
await coverageReport.add(coverageList)
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
37
|
Puppeteer: {
|
|
@@ -44,21 +44,24 @@ const v8CoverageHelpers = {
|
|
|
44
44
|
page.coverage.startCSSCoverage({
|
|
45
45
|
resetOnNavigation: false,
|
|
46
46
|
}),
|
|
47
|
-
])
|
|
47
|
+
])
|
|
48
48
|
},
|
|
49
49
|
takeCoverage: async (page, coverageReport) => {
|
|
50
50
|
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
51
51
|
page.coverage.stopJSCoverage(),
|
|
52
52
|
page.coverage.stopCSSCoverage(),
|
|
53
|
-
])
|
|
53
|
+
])
|
|
54
54
|
// to raw V8 script coverage
|
|
55
|
-
const coverageList = [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
const coverageList = [
|
|
56
|
+
...jsCoverage.map((it) => {
|
|
57
|
+
return {
|
|
58
|
+
source: it.text,
|
|
59
|
+
...it.rawScriptCoverage,
|
|
60
|
+
}
|
|
61
|
+
}),
|
|
62
|
+
...cssCoverage,
|
|
63
|
+
]
|
|
64
|
+
await coverageReport.add(coverageList)
|
|
62
65
|
},
|
|
63
66
|
},
|
|
64
67
|
WebDriver: {
|
|
@@ -71,24 +74,27 @@ const v8CoverageHelpers = {
|
|
|
71
74
|
page.coverage.startCSSCoverage({
|
|
72
75
|
resetOnNavigation: false,
|
|
73
76
|
}),
|
|
74
|
-
])
|
|
77
|
+
])
|
|
75
78
|
},
|
|
76
79
|
takeCoverage: async (page, coverageReport) => {
|
|
77
80
|
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
78
81
|
page.coverage.stopJSCoverage(),
|
|
79
82
|
page.coverage.stopCSSCoverage(),
|
|
80
|
-
])
|
|
83
|
+
])
|
|
81
84
|
// to raw V8 script coverage
|
|
82
|
-
const coverageList = [
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
const coverageList = [
|
|
86
|
+
...jsCoverage.map((it) => {
|
|
87
|
+
return {
|
|
88
|
+
source: it.text,
|
|
89
|
+
...it.rawScriptCoverage,
|
|
90
|
+
}
|
|
91
|
+
}),
|
|
92
|
+
...cssCoverage,
|
|
93
|
+
]
|
|
94
|
+
await coverageReport.add(coverageList)
|
|
89
95
|
},
|
|
90
96
|
},
|
|
91
|
-
}
|
|
97
|
+
}
|
|
92
98
|
|
|
93
99
|
/**
|
|
94
100
|
* Dumps code coverage from Playwright/Puppeteer after every test.
|
|
@@ -117,72 +123,81 @@ const v8CoverageHelpers = {
|
|
|
117
123
|
*
|
|
118
124
|
*/
|
|
119
125
|
module.exports = function (config) {
|
|
120
|
-
config = deepMerge(defaultConfig, config)
|
|
126
|
+
config = deepMerge(defaultConfig, config)
|
|
121
127
|
|
|
122
|
-
if (config.debug) config.logging = 'debug'
|
|
128
|
+
if (config.debug) config.logging = 'debug'
|
|
123
129
|
|
|
124
|
-
const helpers = Container.helpers()
|
|
125
|
-
let coverageRunning = false
|
|
130
|
+
const helpers = Container.helpers()
|
|
131
|
+
let coverageRunning = false
|
|
126
132
|
|
|
127
|
-
const v8Names = Object.keys(v8CoverageHelpers)
|
|
128
|
-
const helperName = Object.keys(helpers).find((it) => v8Names.includes(it))
|
|
133
|
+
const v8Names = Object.keys(v8CoverageHelpers)
|
|
134
|
+
const helperName = Object.keys(helpers).find((it) => v8Names.includes(it))
|
|
129
135
|
if (!helperName) {
|
|
130
|
-
console.error(`Coverage is only supported in ${supportedHelpers.join(' or ')}`)
|
|
136
|
+
console.error(`Coverage is only supported in ${supportedHelpers.join(' or ')}`)
|
|
131
137
|
// no helpers for screenshot
|
|
132
|
-
return
|
|
138
|
+
return
|
|
133
139
|
}
|
|
134
140
|
|
|
135
|
-
config.name = `${config.name} - in ${helperName}
|
|
136
|
-
const debug = debugModule(`codeceptjs:plugin:${helperName.toLowerCase()}Coverage`)
|
|
141
|
+
config.name = `${config.name} - in ${helperName}`
|
|
142
|
+
const debug = debugModule(`codeceptjs:plugin:${helperName.toLowerCase()}Coverage`)
|
|
137
143
|
|
|
138
|
-
const helper = helpers[helperName]
|
|
144
|
+
const helper = helpers[helperName]
|
|
139
145
|
|
|
140
|
-
if (helperName === 'WebDriver' && !helper.config.devtoolsProtocol)
|
|
146
|
+
if (helperName === 'WebDriver' && !helper.config.devtoolsProtocol)
|
|
147
|
+
throw Error('Coverage is currently supporting the WebDriver running with Devtools protocol.')
|
|
141
148
|
|
|
142
|
-
const v8Helper = v8CoverageHelpers[helperName]
|
|
149
|
+
const v8Helper = v8CoverageHelpers[helperName]
|
|
143
150
|
|
|
144
151
|
const coverageOptions = {
|
|
145
152
|
...config,
|
|
146
|
-
}
|
|
153
|
+
}
|
|
147
154
|
|
|
148
|
-
if (helperName === 'WebDriver') coverageOptions.coverageProvider = 'v8'
|
|
155
|
+
if (helperName === 'WebDriver') coverageOptions.coverageProvider = 'v8'
|
|
149
156
|
|
|
150
|
-
const coverageReport = new CoverageReport(coverageOptions)
|
|
151
|
-
coverageReport.cleanCache()
|
|
157
|
+
const coverageReport = new CoverageReport(coverageOptions)
|
|
158
|
+
coverageReport.cleanCache()
|
|
152
159
|
|
|
153
160
|
event.dispatcher.on(event.all.after, async () => {
|
|
154
|
-
output.print(`writing ${coverageOptions.outputDir}`)
|
|
155
|
-
await coverageReport.generate()
|
|
156
|
-
})
|
|
161
|
+
output.print(`writing ${coverageOptions.outputDir}`)
|
|
162
|
+
await coverageReport.generate()
|
|
163
|
+
})
|
|
157
164
|
|
|
158
165
|
// we're going to try to "start" coverage before each step because this is
|
|
159
166
|
// when the browser is already up and is ready to start coverage.
|
|
160
167
|
event.dispatcher.on(event.step.before, () => {
|
|
161
|
-
recorder.add(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
recorder.add(
|
|
169
|
+
'start coverage',
|
|
170
|
+
async () => {
|
|
171
|
+
if (coverageRunning) {
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
if (!helper.page || !helper.page.coverage) {
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
coverageRunning = true
|
|
178
|
+
debug('--> starting coverage <--')
|
|
179
|
+
await v8Helper.startCoverage(helper.page)
|
|
180
|
+
},
|
|
181
|
+
true,
|
|
182
|
+
)
|
|
183
|
+
})
|
|
173
184
|
|
|
174
185
|
// Save coverage data after every test run
|
|
175
186
|
event.dispatcher.on(event.test.after, (test) => {
|
|
176
|
-
recorder.add(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
187
|
+
recorder.add(
|
|
188
|
+
'take coverage',
|
|
189
|
+
async () => {
|
|
190
|
+
if (!coverageRunning) {
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
if (!helper.page || !helper.page.coverage) {
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
coverageRunning = false
|
|
197
|
+
debug('--> stopping coverage <--')
|
|
198
|
+
await v8Helper.takeCoverage(helper.page, coverageReport)
|
|
199
|
+
},
|
|
200
|
+
true,
|
|
201
|
+
)
|
|
202
|
+
})
|
|
203
|
+
}
|