Skip to content

Commit 7c3a83c

Browse files
author
DavertMik
committed
Merge branch '4.x' of github.com:codeceptjs/CodeceptJS into 4.x
2 parents 04c92d7 + 55c5ce7 commit 7c3a83c

23 files changed

Lines changed: 621 additions & 76 deletions

docs/plugins.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,49 @@ More config options are available:
569569
570570
* `config` (optional, default `{}`)
571571
572+
## junitReporter
573+
574+
Generates a JUnit-compatible XML report after a test run.
575+
576+
Unlike Mocha's `mocha-junit-reporter`, this plugin understands CodeceptJS steps and substeps.
577+
For every `<testcase>` it includes:
578+
579+
* `<properties>` — the test's meta information: every `meta` key from `Scenario('...', { meta })`, plus its `tags` and `retries`
580+
* `<system-out>` — an indented step/substep log (substeps are nested under their meta step); only failed steps are marked
581+
* `<failure>` — for failed tests: the error message, type, stack trace and (optionally) the step trace
582+
583+
The produced file is consumable by Jenkins, GitLab CI, CircleCI, GitHub Actions test reporters, etc.
584+
585+
#### Configuration
586+
587+
```js
588+
"plugins": {
589+
"junitReporter": {
590+
"enabled": true
591+
}
592+
}
593+
```
594+
595+
Possible config options:
596+
597+
* `outputName`: file name for the report. Default: `report.xml`.
598+
* `output`: directory where the report is stored, relative to the project root. Default: the `output` directory.
599+
* `testGroupName`: value of the `name` attribute on the root `<testsuites>` element. Default: `CodeceptJS`.
600+
* `attachMeta`: add the test's meta information (`meta` keys, `tags`, `retries`) as `<properties>`. Default: true.
601+
* `attachSteps`: add the step/substep log as `<system-out>`. Default: true.
602+
* `stepsInFailure`: append the step trace to the `<failure>` body. Default: true.
603+
604+
CLI examples:
605+
606+
npx codeceptjs run -p junitReporter
607+
npx codeceptjs run -p junitReporter:outputName=junit.xml
608+
609+
> ℹ When running with `run-workers`, steps are serialized between processes and substep nesting is flattened.
610+
611+
### Parameters
612+
613+
* `config` **any** (optional, default `{}`)
614+
572615
## pageInfo
573616
574617
Collects information from web page after each failed test and adds it to the test as an artifact.

lib/actor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export default function (obj = {}, container) {
9494
actor[action] = actor[actionAlias] = function () {
9595
const step = new Step(helper, action)
9696
if (translation.loaded) {
97-
step.name = actionAlias
97+
step.title = actionAlias
9898
step.actor = translation.I
9999
}
100100
// add methods to promise chain

lib/command/workers/runTests.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ process.on('unhandledRejection', (reason, promise) => {
5454
process.stderr.write(`${reason.stack}\n`)
5555
}
5656

57-
// Don't exit on test-related rejections
58-
if (msg.includes('expected') || msg.includes('AssertionError')) {
59-
return
60-
}
61-
process.exit(1)
57+
// Do not exit — killing the worker silently drops every remaining test from the report.
6258
})
6359

6460
// hide worker output

lib/heal.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ class Heal {
4949
}
5050

5151
hasCorrespondingRecipes(step) {
52-
return matchRecipes(this.recipes, this.contextName).filter(r => !r.steps || r.steps.includes(step.name)).length > 0
52+
return matchRecipes(this.recipes, this.contextName).filter(r => !r.steps || r.steps.includes(step.title)).length > 0
5353
}
5454

5555
async getCodeSuggestions(context) {
5656
const suggestions = []
57-
const stepName = context.step?.name
57+
const stepName = context.step?.title
5858
const recipes = matchRecipes(this.recipes, this.contextName)
5959
.filter(r => !r.steps || !stepName || r.steps.includes(stepName))
6060

lib/plugin/aiTrace.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export default function (config = {}) {
195195
} else {
196196
if (stepNum === -1) return
197197
if (isStepIgnored(step)) return
198-
if (step.metaStep && step.metaStep.name === 'BeforeSuite') return
198+
if (step.metaStep && step.metaStep.title === 'BeforeSuite') return
199199

200200
const stepPrefix = generateStepPrefix(step, stepNum)
201201
stepNum++
@@ -247,7 +247,7 @@ export default function (config = {}) {
247247
async function persistStep(step) {
248248
if (stepNum === -1) return
249249
if (isStepIgnored(step)) return
250-
if (step.metaStep && step.metaStep.name === 'BeforeSuite') return
250+
if (step.metaStep && step.metaStep.title === 'BeforeSuite') return
251251

252252
const stepKey = step.toString()
253253

@@ -437,8 +437,9 @@ export default function (config = {}) {
437437

438438
function isStepIgnored(step) {
439439
if (!config.ignoreSteps) return false
440+
if (!step.title) return false
440441
for (const pattern of config.ignoreSteps || []) {
441-
if (step.name.match(pattern)) return true
442+
if (step.title.match(pattern)) return true
442443
}
443444
return false
444445
}

lib/plugin/analyze.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,9 @@ const defaultConfig = {
155155
if (config.vision && test.artifacts.screenshot) {
156156
debug('Adding screenshot to prompt')
157157
messages[0].content.push({
158-
type: 'image_url',
159-
image_url: {
160-
url: 'data:image/png;base64,' + base64EncodeFile(test.artifacts.screenshot),
161-
},
158+
type: 'image',
159+
image: base64EncodeFile(test.artifacts.screenshot),
160+
mediaType: 'image/png',
162161
})
163162
}
164163

0 commit comments

Comments
 (0)