Compare commits

...

57 commits

Author SHA1 Message Date
Jozef Izso
29672c52a8
Merge pull request #772 from dorny/codex/summary-output 2026-04-25 14:21:30 +02:00
Jozef Izso
373689ed6b
chore: rebuild dist folder 2026-04-25 14:20:38 +02:00
Jozef Izso
bd45c7a559
Refactor summary output to use a temporary file 2026-04-25 14:20:21 +02:00
Jozef Izso
49ad12d837
Add changelog for summary output 2026-04-25 14:03:52 +02:00
Jozef Izso
f610967bd1
Add generated summary action output 2026-04-25 14:03:52 +02:00
Jozef Izso
1ab1766274
Merge pull request #773 from dorny/codex/list-files-input 2026-04-25 13:34:59 +02:00
Jozef Izso
528bb1a4e4
Add changelog for list-files input 2026-04-25 13:31:01 +02:00
Jozef Izso
e05b863b43
Suppress empty list-files summary table 2026-04-25 13:17:09 +02:00
Jozef Izso
d7f15447e6
Tighten list-files report tests 2026-04-25 13:04:58 +02:00
Jozef Izso
0af87079d7
Merge pull request #771 from dorny/dependabot/npm_and_yarn/jest-junit-17.0.0 2026-04-25 12:13:48 +02:00
Jozef Izso
45c8d46681
Resolve list-files conflicts on current main 2026-04-25 12:13:19 +02:00
Felix Chapman
ba6f1d11e2
Correct README to indicate list-files is not automatically adjusted 2026-04-25 12:12:06 +02:00
Felix Chapman
a48134be3e
Add new parameter list-files for when there are multiple files in a report 2026-04-25 12:12:06 +02:00
dependabot[bot]
97ba6567fc
Bump jest-junit from 16.0.0 to 17.0.0
Bumps [jest-junit](https://github.com/jest-community/jest-junit) from 16.0.0 to 17.0.0.
- [Release notes](https://github.com/jest-community/jest-junit/releases)
- [Commits](https://github.com/jest-community/jest-junit/compare/v16.0.0...v17.0.0)

---
updated-dependencies:
- dependency-name: jest-junit
  dependency-version: 17.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-24 23:52:36 +00:00
Jozef Izso
093d99bd59
Merge pull request #770 from dorny/feature/update_packages 2026-04-24 14:18:31 +02:00
Jozef Izso
23735d3781
chore: rebuild dist for updated packages 2026-04-24 12:33:58 +02:00
Jozef Izso
67804e5bc2
Update development packages 2026-04-24 12:32:48 +02:00
Jozef Izso
a5b9b5c6e7
Update production packages 2026-04-24 11:58:19 +02:00
Jozef Izso
c36971571b
Merge pull request #763 from dorny/dependabot/npm_and_yarn/actions/github-9.1.0 2026-04-24 11:50:52 +02:00
Jozef Izso
724024e7cf
Merge pull request #769 from mfloryan-marshall/mfloryan-doc-patch-1 2026-04-22 00:34:39 +02:00
Marcin Floryan
0caa66d75c
doc: Updated GitHub actions to latest versions in example
The example of how to include the reporter in the CI/CD workflow used older versions of GitHub actions. This bumps the versions to the latest supported as of April 2026 so that people who copy these into their own pipelines use more up-to-date versions.
2026-04-21 12:14:35 +02:00
github-actions[bot]
fdce2624c0 chore: rebuild dist for Dependabot update 2026-04-08 23:53:15 +00:00
dependabot[bot]
ecf6e5c4c6
Bump @actions/github from 9.0.0 to 9.1.0
Bumps [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github) from 9.0.0 to 9.1.0.
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

---
updated-dependencies:
- dependency-name: "@actions/github"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 23:52:49 +00:00
Jozef Izso
9c68bf6253
Merge pull request #761 from dorny/update_typescript 2026-04-05 20:14:50 +02:00
Jozef Izso
8ebd1f2035
Update Typescript to v6 2026-04-05 20:13:36 +02:00
Jozef Izso
195e976be5
Merge pull request #760 from dorny/update_packages 2026-04-05 20:04:33 +02:00
Jozef Izso
a88cf9b158
Update to latest packages 2026-04-05 18:52:35 +02:00
Jozef Izso
4a3df5aacc
Merge pull request #758 from dorny/dependabot/npm_and_yarn/types/picomatch-4.0.3 2026-04-04 11:31:04 +02:00
dependabot[bot]
db37d6d935
Bump @types/picomatch from 4.0.2 to 4.0.3
Bumps [@types/picomatch](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/picomatch) from 4.0.2 to 4.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/picomatch)

---
updated-dependencies:
- dependency-name: "@types/picomatch"
  dependency-version: 4.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-03 23:52:40 +00:00
Jozef Izso
ab50174d2c
Merge pull request #752 from dorny/dependabot/npm_and_yarn/reports/jest/picomatch-2.3.2 2026-03-27 15:05:05 +01:00
Jozef Izso
ef55eb29a9
Merge pull request #751 from dorny/dependabot/npm_and_yarn/handlebars-4.7.9 2026-03-27 13:14:27 +01:00
dependabot[bot]
2d29da79de
Bump picomatch from 2.2.2 to 2.3.2 in /reports/jest
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.2.2 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.2.2...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-27 12:14:17 +00:00
Jozef Izso
ce1640be7e
Merge pull request #749 from dorny/dependabot/npm_and_yarn/eslint-plugin-jest-29.15.1 2026-03-27 13:14:15 +01:00
Jozef Izso
08ceae2b23
Merge pull request #747 from dorny/dependabot/npm_and_yarn/picomatch-4.0.4 2026-03-27 13:14:06 +01:00
Jozef Izso
fcff37b0cc
Merge pull request #748 from dorny/dependabot/npm_and_yarn/typescript-eslint/parser-8.57.2 2026-03-27 13:13:22 +01:00
dependabot[bot]
63a06a304e
Bump handlebars from 4.7.8 to 4.7.9
Bumps [handlebars](https://github.com/handlebars-lang/handlebars.js) from 4.7.8 to 4.7.9.
- [Release notes](https://github.com/handlebars-lang/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/v4.7.9/release-notes.md)
- [Commits](https://github.com/handlebars-lang/handlebars.js/compare/v4.7.8...v4.7.9)

---
updated-dependencies:
- dependency-name: handlebars
  dependency-version: 4.7.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-27 00:10:45 +00:00
dependabot[bot]
1e586914f0
Bump eslint-plugin-jest from 29.15.0 to 29.15.1
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 29.15.0 to 29.15.1.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v29.15.0...v29.15.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-version: 29.15.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-24 23:52:41 +00:00
github-actions[bot]
7b052bb685 chore: rebuild dist for Dependabot update 2026-03-24 00:09:31 +00:00
dependabot[bot]
18e03ad9cc
Bump @typescript-eslint/parser from 8.57.1 to 8.57.2
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.57.1 to 8.57.2.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.2/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.57.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-24 00:09:22 +00:00
dependabot[bot]
bae76033c4
Bump picomatch from 4.0.3 to 4.0.4
Bumps [picomatch](https://github.com/micromatch/picomatch) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-24 00:09:09 +00:00
Jozef Izso
2dcf091ad5
Merge pull request #746 from dorny/release/v3.0.0
`test-reporter` release v3.0.0
2026-03-21 14:46:12 +01:00
Jozef Izso
a43b3a5f73
test-reporter release v3.0.0 2026-03-21 14:22:41 +01:00
Jozef Izso
79216dc71a
Merge pull request #744 from dorny/dependabot/npm_and_yarn/flatted-3.4.2
Bump flatted from 3.4.1 to 3.4.2
2026-03-21 14:22:31 +01:00
Jozef Izso
62c3873e1e
Merge pull request #745 from dorny/feature/workflow_permissions
Explicitly use lowest permissions required to run workflow
2026-03-21 14:19:52 +01:00
Jozef Izso
bd74ca6c12
Explicitly use lowest permissions required to run workflow 2026-03-21 14:14:22 +01:00
Jozef Izso
0c2b2aa1e0
Merge pull request #738 from dav-tb/feature/node24-runtime
Upgrade action runtime to Node.js 24
2026-03-21 13:22:42 +01:00
Jozef Izso
f7eee307f2
Use the @types/node definitions for NodeJS 24 runtime 2026-03-21 13:09:20 +01:00
David Lemieux
ad0a96f767
Upgrade action runtime to Node.js 24
GitHub Actions is deprecating the Node 20 runtime, with Node 24
becoming the default in June 2026. This updates the action to run
on the node24 runtime.

- action.yml: change `using` from node20 to node24
- .nvmrc: update development version to v24
- package.json: update engines to >=24

Closes #680
2026-03-21 13:09:20 +01:00
Jozef Izso
543415ce39
Merge pull request #741 from dorny/release/v2.7.0
`test-reporter` release v2.7.0
2026-03-21 13:00:09 +01:00
dependabot[bot]
f1284d056a
Bump flatted from 3.4.1 to 3.4.2
Bumps [flatted](https://github.com/WebReflection/flatted) from 3.4.1 to 3.4.2.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.4.1...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-21 12:00:02 +00:00
Jozef Izso
3c1b53fe19
Merge pull request #743 from dorny/dependabot/npm_and_yarn/types/adm-zip-0.5.8
Bump @types/adm-zip from 0.5.7 to 0.5.8
2026-03-21 12:59:30 +01:00
Jozef Izso
dc9521099d
Merge pull request #742 from dorny/dependabot/npm_and_yarn/typescript-eslint/parser-8.57.1
Bump @typescript-eslint/parser from 8.57.0 to 8.57.1
2026-03-21 12:58:59 +01:00
dependabot[bot]
38e11d6bf5
Bump @types/adm-zip from 0.5.7 to 0.5.8
Bumps [@types/adm-zip](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/adm-zip) from 0.5.7 to 0.5.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/adm-zip)

---
updated-dependencies:
- dependency-name: "@types/adm-zip"
  dependency-version: 0.5.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 23:52:58 +00:00
dependabot[bot]
9489e055fc
Bump @typescript-eslint/parser from 8.57.0 to 8.57.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.57.0 to 8.57.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.57.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 23:52:51 +00:00
Jozef Izso
df62474295
test-reporter release v2.7.0 2026-03-16 14:36:58 +01:00
Jozef Izso
24ade537c8
Add the missing collapsed input parameter documentation to README 2026-03-16 14:36:58 +01:00
Jozef Izso
574d6b100c
Merge pull request #739 from dorny/bugfix/update_flatted_package 2026-03-16 14:29:45 +01:00
16 changed files with 2884 additions and 1402 deletions

View file

@ -16,6 +16,9 @@ on:
- '**.md'
workflow_dispatch:
permissions:
contents: read
jobs:
check-dist:
runs-on: ubuntu-latest

View file

@ -8,6 +8,9 @@ on:
- main
workflow_dispatch:
permissions:
contents: read
jobs:
build-test:
name: Build & Test

View file

@ -3,6 +3,9 @@ name: Manual run
on:
workflow_dispatch:
permissions:
contents: read
jobs:
check-dist:
runs-on: ubuntu-latest

View file

@ -6,6 +6,10 @@ on:
types:
- completed
permissions:
contents: read
actions: read
jobs:
report:
name: Workflow test

2
.nvmrc
View file

@ -1 +1 @@
v20
v24

View file

@ -1,5 +1,17 @@
# Changelog
## 3.1.0
* Feature: Add `list-files` input to control test report file listing https://github.com/dorny/test-reporter/pull/773
* Feature: Add `summary_file` output with the path to the generated summary in Markdown format https://github.com/dorny/test-reporter/pull/772
## 3.0.0
* Feature: Use NodeJS 24 LTS as default runtime https://github.com/dorny/test-reporter/pull/738
## 2.7.0
* Feature: Add `slug-prefix` output for link anchors https://github.com/dorny/test-reporter/pull/731
* Feature: Report `jest-junit` testsuite errors as failures https://github.com/dorny/test-reporter/pull/155
* Security: Update dependencies to fix reported security vulnerabilities
## 2.6.0
* Fix: For `workflow_run` events, resolve the commit of the check run from related pull request head commits first (matching `workflow_run.head_branch`, then first PR), and fall back to `workflow_run.head_sha` for non-PR runs https://github.com/dorny/test-reporter/pull/673
* Change: The `test-reporter` action will listed all artifacts associated with the build run https://github.com/dorny/test-reporter/pull/693

View file

@ -47,12 +47,12 @@ jobs:
name: Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # checkout the repo
- uses: actions/checkout@v6 # checkout the repo
- run: npm ci # install packages
- run: npm test # run tests (configured to use jest-junit reporter)
- name: Test Report
uses: dorny/test-reporter@v2
uses: dorny/test-reporter@v3
if: ${{ !cancelled() }} # run this step even if previous step failed
with:
name: JEST Tests # Name of the check run which will be created
@ -78,10 +78,10 @@ jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # checkout the repo
- uses: actions/checkout@v6 # checkout the repo
- run: npm ci # install packages
- run: npm test # run tests (configured to use jest-junit reporter)
- uses: actions/upload-artifact@v4 # upload test results
- uses: actions/upload-artifact@v7 # upload test results
if: ${{ !cancelled() }} # run this step even if previous step failed
with:
name: test-results
@ -103,7 +103,7 @@ jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: dorny/test-reporter@v2
- uses: dorny/test-reporter@v3
with:
artifact: test-results # artifact name
name: JEST Tests # Name of the check run which will be created
@ -114,7 +114,7 @@ jobs:
## Usage
```yaml
- uses: dorny/test-reporter@v2
- uses: dorny/test-reporter@v3
with:
# Name or regex of artifact containing test results
@ -184,6 +184,12 @@ jobs:
# none
list-tests: 'all'
# Limits which test result files are listed:
# all
# failed
# none
list-files: 'all'
# Limits number of created annotations with error message and stack trace captured during test execution.
# Must be less or equal to 50.
max-annotations: '10'
@ -194,6 +200,13 @@ jobs:
# Set this action as failed if no test results were found
fail-on-empty: 'true'
# Controls whether test report details are collapsed or expanded.
# Supported options:
# auto: Collapse only if all tests pass (default behavior)
# always: Always collapse the report details
# never: Always expand the report details
collapsed: 'auto'
# Relative path under $GITHUB_WORKSPACE where the repository was checked out.
working-directory: ''
@ -212,6 +225,7 @@ jobs:
| time | Test execution time [ms] |
| url | Check run URL |
| url_html | Check run URL HTML |
| summary_file | Path to a file containing the generated test report summary in Markdown format |
| slug_prefix| Random anchor links slug prefix generated for the summary headers |
## Supported formats

View file

@ -1,4 +1,5 @@
import {getBadge, DEFAULT_OPTIONS, ReportOptions} from '../../src/report/get-report.js'
import {DEFAULT_OPTIONS, getBadge, getReport, ReportOptions} from '../../src/report/get-report.js'
import {TestCaseResult, TestGroupResult, TestRunResult, TestSuiteResult} from '../../src/test-results.js'
describe('getBadge', () => {
describe('URI encoding with special characters', () => {
@ -131,3 +132,147 @@ describe('getBadge', () => {
})
})
})
describe('getReport', () => {
// Helper function to create test results
function createTestResult(path: string, passed: number, failed: number, skipped: number): TestRunResult {
const tests: TestCaseResult[] = []
for (let i = 0; i < passed; i++) {
tests.push(new TestCaseResult(`passed-test-${i}`, 'success', 100))
}
for (let i = 0; i < failed; i++) {
tests.push(
new TestCaseResult(`failed-test-${i}`, 'failed', 100, {
details: 'Test failed',
message: 'Assertion error'
})
)
}
for (let i = 0; i < skipped; i++) {
tests.push(new TestCaseResult(`skipped-test-${i}`, 'skipped', 0))
}
const group = new TestGroupResult('test-group', tests)
const suite = new TestSuiteResult('test-suite', [group])
return new TestRunResult(path, [suite])
}
describe('list-files parameter', () => {
const results = [
createTestResult('passing-file.spec.ts', 5, 0, 0),
createTestResult('failing-file.spec.ts', 3, 2, 1),
createTestResult('passing-with-skipped-file.spec.ts', 8, 0, 2)
]
it('shows all files when list-files is "all"', () => {
const report = getReport(results, {
...DEFAULT_OPTIONS,
listFiles: 'all',
listSuites: 'none',
listTests: 'none'
})
expect(report).toContain('|Report|Passed|Failed|Skipped|Time|')
expect(report).toContain('passing-file.spec.ts')
expect(report).toContain('failing-file.spec.ts')
expect(report).toContain('passing-with-skipped-file.spec.ts')
})
it('shows only failed files when list-files is "failed"', () => {
const report = getReport(results, {
...DEFAULT_OPTIONS,
listFiles: 'failed',
listSuites: 'none',
listTests: 'none'
})
expect(report).toContain('|Report|Passed|Failed|Skipped|Time|')
expect(report).not.toContain('passing-file.spec.ts')
expect(report).toContain('failing-file.spec.ts')
expect(report).not.toContain('passing-with-skipped-file.spec.ts')
})
it('shows no file details when list-files is "none"', () => {
const report = getReport(results, {
...DEFAULT_OPTIONS,
listFiles: 'none',
listSuites: 'none',
listTests: 'none'
})
expect(report).toContain('![')
expect(report).not.toContain('|Report|Passed|Failed|Skipped|Time|')
expect(report).not.toContain('passing-file.spec.ts')
expect(report).not.toContain('failing-file.spec.ts')
expect(report).not.toContain('passing-with-skipped-file.spec.ts')
})
it('does not show an empty summary table when list-files is "none" and only-summary is enabled', () => {
const report = getReport(results, {
...DEFAULT_OPTIONS,
listFiles: 'none',
listSuites: 'all',
onlySummary: true,
listTests: 'none'
})
expect(report).toContain('![')
expect(report).not.toContain('|Report|Passed|Failed|Skipped|Time|')
expect(report).not.toContain('passing-file.spec.ts')
expect(report).not.toContain('failing-file.spec.ts')
expect(report).not.toContain('passing-with-skipped-file.spec.ts')
})
it('works correctly with list-suites and list-tests when list-files is "failed"', () => {
const report = getReport(results, {
...DEFAULT_OPTIONS,
listFiles: 'failed',
listSuites: 'all',
listTests: 'all'
})
expect(report).toContain('|Report|Passed|Failed|Skipped|Time|')
expect(report).not.toContain('passing-file.spec.ts')
expect(report).toContain('failing-file.spec.ts')
expect(report).not.toContain('passing-with-skipped-file.spec.ts')
// Should show suite details for the failed file
expect(report).toContain('test-suite')
})
it('filters correctly when all files pass and list-files is "failed"', () => {
const allPassingResults = [
createTestResult('passing-file-1.spec.ts', 5, 0, 0),
createTestResult('passing-file-2.spec.ts', 8, 0, 2)
]
const report = getReport(allPassingResults, {
...DEFAULT_OPTIONS,
listFiles: 'failed',
listSuites: 'all',
listTests: 'none'
})
expect(report).not.toContain('passing-file-1.spec.ts')
expect(report).not.toContain('passing-file-2.spec.ts')
expect(report).toContain('![')
expect(report).not.toContain('|Report|Passed|Failed|Skipped|Time|')
})
it('filters correctly when all files fail and list-files is "failed"', () => {
const allFailingResults = [
createTestResult('failing-file-1.spec.ts', 0, 5, 0),
createTestResult('failing-file-2.spec.ts', 1, 2, 1)
]
const report = getReport(allFailingResults, {
...DEFAULT_OPTIONS,
listFiles: 'failed',
listSuites: 'all',
listTests: 'none'
})
expect(report).toContain('failing-file-1.spec.ts')
expect(report).toContain('failing-file-2.spec.ts')
})
})
})

View file

@ -54,6 +54,14 @@ inputs:
- none
required: false
default: 'all'
list-files:
description: |
Limits which test result files are listed. Supported options:
- all
- failed
- none
required: false
default: 'all'
max-annotations:
description: |
Limits number of created annotations with error message and stack trace captured during test execution.
@ -122,10 +130,12 @@ outputs:
description: Check run URL
url_html:
description: Check run URL HTML
summary_file:
description: Path to a file containing the generated test report summary in Markdown format
slug_prefix:
description: Random prefix added to generated report anchor slugs for this action run
runs:
using: 'node20'
using: 'node24'
main: 'dist/index.js'
branding:
color: blue

1860
dist/index.js generated vendored

File diff suppressed because it is too large Load diff

2
dist/licenses.txt generated vendored
View file

@ -889,7 +889,7 @@ reusify
MIT
The MIT License (MIT)
Copyright (c) 2015 Matteo Collina
Copyright (c) 2015-2024 Matteo Collina
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

2014
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "test-reporter",
"version": "2.5.0",
"version": "3.0.0",
"private": true,
"description": "Presents test results from popular testing frameworks as Github check run",
"type": "module",
@ -37,37 +37,37 @@
"author": "Michal Dorner <dorner.michal@gmail.com>",
"license": "MIT",
"dependencies": {
"@actions/core": "^3.0.0",
"@actions/core": "^3.0.1",
"@actions/exec": "^3.0.0",
"@actions/github": "^9.0.0",
"adm-zip": "^0.5.16",
"@actions/github": "^9.1.1",
"adm-zip": "^0.5.17",
"fast-glob": "^3.3.3",
"picomatch": "^4.0.3",
"picomatch": "^4.0.4",
"xml2js": "^0.6.2"
},
"devDependencies": {
"@octokit/webhooks-types": "^7.6.1",
"@types/adm-zip": "^0.5.7",
"@types/adm-zip": "^0.5.8",
"@types/jest": "^30.0.0",
"@types/node": "^20.19.23",
"@types/picomatch": "^4.0.2",
"@types/node": "^24.12.2",
"@types/picomatch": "^4.0.3",
"@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^8.56.1",
"@typescript-eslint/parser": "^8.57.0",
"@typescript-eslint/eslint-plugin": "^8.59.0",
"@typescript-eslint/parser": "^8.59.0",
"@vercel/ncc": "^0.38.4",
"eol-converter-cli": "^1.1.0",
"eslint": "^9.39.4",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^29.15.0",
"eslint-plugin-jest": "^29.15.2",
"eslint-plugin-prettier": "^5.5.5",
"jest": "^30.3.0",
"jest-junit": "^16.0.0",
"jest-junit": "^17.0.0",
"js-yaml": "^4.1.1",
"prettier": "^3.8.1",
"ts-jest": "^29.4.6",
"typescript": "^5.9.3"
"prettier": "^3.8.3",
"ts-jest": "^29.4.9",
"typescript": "^6.0.3"
},
"overrides": {
"sax": "^1.4.3"
@ -83,7 +83,7 @@
"titleTemplate": "{title}"
},
"engines": {
"node": ">=20"
"node": ">=24"
},
"markdownlint-cli2": {
"ignores": [

View file

@ -4548,10 +4548,11 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},

View file

@ -2,6 +2,9 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import {GitHub} from '@actions/github/lib/utils'
import {randomBytes} from 'node:crypto'
import {writeFileSync} from 'node:fs'
import {tmpdir} from 'node:os'
import {join} from 'node:path'
import {ArtifactProvider} from './input-providers/artifact-provider.js'
import {LocalFileProvider} from './input-providers/local-file-provider.js'
@ -44,6 +47,7 @@ class TestReporter {
readonly reporter = core.getInput('reporter', {required: true})
readonly listSuites = core.getInput('list-suites', {required: true}) as 'all' | 'failed' | 'none'
readonly listTests = core.getInput('list-tests', {required: true}) as 'all' | 'failed' | 'none'
readonly listFiles = core.getInput('list-files', {required: true}) as 'all' | 'failed' | 'none'
readonly maxAnnotations = parseInt(core.getInput('max-annotations', {required: true}))
readonly failOnError = core.getInput('fail-on-error', {required: true}) === 'true'
readonly failOnEmpty = core.getInput('fail-on-empty', {required: true}) === 'true'
@ -71,6 +75,11 @@ class TestReporter {
return
}
if (this.listFiles !== 'all' && this.listFiles !== 'failed' && this.listFiles !== 'none') {
core.setFailed(`Input parameter 'list-files' has invalid value`)
return
}
if (this.collapsed !== 'auto' && this.collapsed !== 'always' && this.collapsed !== 'never') {
core.setFailed(`Input parameter 'collapsed' has invalid value`)
return
@ -177,7 +186,17 @@ class TestReporter {
}
}
const {listSuites, listTests, slugPrefix, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed} = this
const {
listSuites,
listTests,
slugPrefix,
listFiles,
onlySummary,
useActionsSummary,
badgeTitle,
reportTitle,
collapsed
} = this
const passed = results.reduce((sum, tr) => sum + tr.passed, 0)
const failed = results.reduce((sum, tr) => sum + tr.failed, 0)
@ -192,6 +211,7 @@ class TestReporter {
listSuites,
listTests,
slugPrefix,
listFiles,
baseUrl,
onlySummary,
useActionsSummary,
@ -204,6 +224,7 @@ class TestReporter {
core.info('Summary content:')
core.info(summary)
this.writeSummaryFile(summary)
await core.summary.addRaw(summary).write()
} else {
core.info(`Creating check run ${name}`)
@ -224,6 +245,7 @@ class TestReporter {
listSuites,
listTests,
slugPrefix,
listFiles,
baseUrl,
onlySummary,
useActionsSummary,
@ -234,6 +256,7 @@ class TestReporter {
core.info('Creating annotations')
const annotations = getAnnotations(results, this.maxAnnotations)
this.writeSummaryFile(summary)
const isFailed = this.failOnError && results.some(tr => tr.result === 'failed')
const conclusion = isFailed ? 'failure' : 'success'
@ -260,6 +283,14 @@ class TestReporter {
return results
}
writeSummaryFile(summary: string): void {
const dir = process.env.RUNNER_TEMP || tmpdir()
const file = join(dir, `test-reporter-summary-${randomBytes(8).toString('hex')}.md`)
writeFileSync(file, summary)
core.info(`Summary written to ${file}`)
core.setOutput('summary_file', file)
}
getParser(reporter: string, options: ParseOptions): TestParser {
switch (reporter) {
case 'dart-json':

View file

@ -12,6 +12,7 @@ export interface ReportOptions {
listSuites: 'all' | 'failed' | 'none'
listTests: 'all' | 'failed' | 'none'
slugPrefix: string
listFiles: 'all' | 'failed' | 'none'
baseUrl: string
onlySummary: boolean
useActionsSummary: boolean
@ -24,6 +25,7 @@ export const DEFAULT_OPTIONS: ReportOptions = {
listSuites: 'all',
listTests: 'all',
slugPrefix: '',
listFiles: 'all',
baseUrl: '',
onlySummary: false,
useActionsSummary: true,
@ -173,21 +175,29 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
sections.push(` `)
}
if (testRuns.length > 0 || options.onlySummary) {
const tableData = testRuns
.map((tr, originalIndex) => ({tr, originalIndex}))
.filter(({tr}) => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
.map(({tr, originalIndex}) => {
const time = formatTime(tr.time)
const name = tr.path
const addr = options.baseUrl + makeRunSlug(originalIndex, options).link
const nameLink = link(name, addr)
const passed = tr.passed > 0 ? `${tr.passed} ${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed} ${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped} ${Icon.skip}` : ''
return [nameLink, passed, failed, skipped, time]
})
// Filter test runs based on list-files option
const filteredTestRuns =
options.listFiles === 'failed'
? testRuns.filter(tr => tr.result === 'failed')
: options.listFiles === 'none'
? []
: testRuns
const tableData = filteredTestRuns
.map((tr, originalIndex) => ({tr, originalIndex}))
.filter(({tr}) => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
.map(({tr, originalIndex}) => {
const time = formatTime(tr.time)
const name = tr.path
const addr = options.baseUrl + makeRunSlug(originalIndex, options).link
const nameLink = link(name, addr)
const passed = tr.passed > 0 ? `${tr.passed} ${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed} ${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped} ${Icon.skip}` : ''
return [nameLink, passed, failed, skipped, time]
})
if (tableData.length > 0) {
const resultsTable = table(
['Report', 'Passed', 'Failed', 'Skipped', 'Time'],
[Align.Left, Align.Right, Align.Right, Align.Right, Align.Right],
@ -197,7 +207,7 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
}
if (options.onlySummary === false) {
const suitesReports = testRuns.map((tr, i) => getSuitesReport(tr, i, options)).flat()
const suitesReports = filteredTestRuns.map((tr, i) => getSuitesReport(tr, i, options)).flat()
sections.push(...suitesReports)
}