Merge pull request #90 from dorny/mocha-json

Add support for mocha-json
This commit is contained in:
Michal Dorner 2021-04-19 23:22:04 +02:00 committed by GitHub
commit e81e3750bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 24743 additions and 81 deletions

View file

@ -21,6 +21,7 @@ jobs:
- run: npm test
- name: Upload test results
if: success() || failure()
uses: actions/upload-artifact@v2
with:
name: test-results

View file

@ -16,8 +16,8 @@ This [Github Action](https://github.com/features/actions) displays test results
- .NET / [xUnit](https://xunit.net/) / [NUnit](https://nunit.org/) / [MSTest](https://github.com/Microsoft/testfx-docs)
- Dart / [test](https://pub.dev/packages/test)
- Flutter / [test](https://pub.dev/packages/test)
- JavaScript / [JEST](https://jestjs.io/)
- Java / [JUnit](https://junit.org/)
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
For more information see [Supported formats](#supported-formats) section.
@ -54,9 +54,9 @@ jobs:
## Recommended setup for public repositories
Workflows triggered by pull requests from forked repositories are executed with read-only token and therefore can't create check runs.
To workaround this security restriction it's required to use two separate workflows:
1. `CI` runs in the context of PR head branch with read-only token. It executes the tests and uploads test results as build artifact
2. `Test Report` runs in the context of repository main branch with read/write token. It will download test results and create reports
To workaround this security restriction, it's required to use two separate workflows:
1. `CI` runs in the context of the PR head branch with the read-only token. It executes the tests and uploads test results as a build artifact
2. `Test Report` runs in the context of the repository main branch with read/write token. It will download test results and create reports
**PR head branch:** *.github/workflows/ci.yml*
```yaml
@ -116,7 +116,7 @@ jobs:
# Coma separated list of paths to test results
# Supports wildcards via [fast-glob](https://github.com/mrmlnc/fast-glob)
# All matched result files must be of same format
# All matched result files must be of the same format
path: ''
# Format of test results. Supported options:
@ -125,6 +125,7 @@ jobs:
# flutter-json
# java-junit
# jest-junit
# mocha-json
reporter: ''
# Limits which test suites are listed:
@ -142,7 +143,7 @@ jobs:
# Must be less or equal to 50.
max-annotations: '10'
# Set action as failed if test report contain any failed test
# Set action as failed if test report contains any failed test
fail-on-error: 'true'
# Relative path under $GITHUB_WORKSPACE where the repository was checked out.
@ -224,8 +225,8 @@ Or with (undocumented) CLI argument:
According to documentation `dart_test.yaml` should be at the root of the package, next to the package's pubspec.
On current `stable` and `beta` channels it doesn't work and you have to put `dart_test.yaml` inside your `test` folder.
On `dev` channel it's already fixed.
On current `stable` and `beta` channels it doesn't work, and you have to put `dart_test.yaml` inside your `test` folder.
On `dev` channel, it's already fixed.
For more information see:
- [test package](https://pub.dev/packages/test)
@ -239,17 +240,17 @@ For more information see:
<summary>java-junit (Experimental)</summary>
Support for [JUnit](https://Junit.org/) XML is experimental - should work but it was not extensively tested.
To have code annotations working properly it's required your directory structure matches package name.
This is due to the fact Java stacktraces doesn't contains full path to the source file.
Some heuristic was necessary to figure out mapping between line in stack trace and actual source file.
To have code annotations working properly, it's required your directory structure matches the package name.
This is due to the fact Java stack traces don't contain a full path to the source file.
Some heuristic was necessary to figure out the mapping between the line in the stack trace and an actual source file.
</details>
<details>
<summary>jest-Junit</summary>
[JEST](https://jestjs.io/) testing framework support requires usage of [jest-Junit](https://github.com/jest-community/jest-Junit) reporter.
[JEST](https://jestjs.io/) testing framework support requires the usage of [jest-Junit](https://github.com/jest-community/jest-Junit) reporter.
It will create test results in Junit XML format which can be then processed by this action.
You can use following example configuration in `package.json`:
You can use the following example configuration in `package.json`:
```json
"scripts": {
"test": "jest --ci --reporters=default --reporters=jest-Junit"
@ -272,19 +273,38 @@ You can use following example configuration in `package.json`:
Configuration of `uniqueOutputName`, `suiteNameTemplate`, `classNameTemplate`, `titleTemplate` is important for proper visualization of test results.
</details>
<details>
<summary>mocha-json</summary>
[Mocha](https://mochajs.org/) testing framework support requires:
- Mocha version [v7.2.0](https://github.com/mochajs/mocha/releases/tag/v7.2.0) or higher
- Usage of [json](https://mochajs.org/#json) reporter.
You can use the following example configuration in `package.json`:
```json
"scripts": {
"test": "mocha --reporter json > test-results.json"
}
```
Test processing might fail if any of your tests write anything on standard output.
Mocha, unfortunately, doesn't have the option to store `json` output directly to the file, and we have to rely on redirecting its standard output.
There is a work in progress to fix it: [mocha#4607](https://github.com/mochajs/mocha/pull/4607)
</details>
## GitHub limitations
Unfortunately there are some known issues and limitations caused by GitHub API:
Unfortunately, there are some known issues and limitations caused by GitHub API:
- Test report (i.e. Check Run summary) is markdown text. No custom styling or HTML is possible.
- Maximum report size is 65535 bytes. Input parameters `list-suites` and `list-tests` will be automatically adjusted if max size is exceeded.
- Test report can't reference any additional files (e.g. screenshots). You can use `actions/upload-artifact@v2` to upload them and inspect manually.
- Check Runs are created for specific commit SHA. it's not possible to specify under which workflow test report should belong if there are more
workflows running for same SHA. Thanks to this GitHub "feature" it's possible your test report will appear in unexpected place in GitHub UI.
For more information see [#67](https://github.com/dorny/test-reporter/issues/67).
- Test report can't reference any additional files (e.g. screenshots). You can use `actions/upload-artifact@v2` to upload them and inspect them manually.
- Check Runs are created for specific commit SHA. It's not possible to specify under which workflow test report should belong if more
workflows are running for the same SHA. Thanks to this GitHub "feature" it's possible your test report will appear in an unexpected place in GitHub UI.
For more information, see [#67](https://github.com/dorny/test-reporter/issues/67).
## See also
- [paths-filter](https://github.com/dorny/paths-filter) - Conditionally run actions based on files modified by PR, feature branch or pushed commits
- [paths-filter](https://github.com/dorny/paths-filter) - Conditionally run actions based on files modified by PR, feature branch, or pushed commits
## License

View file

@ -0,0 +1,29 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%204%20failed%2C%201%20skipped-critical)
## ❌ <a id="user-content-r0" href="#r0">fixtures/mocha-json.json</a>
**6** tests were completed in **12ms** with **1** passed, **4** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[test/main.test.js](#r0s0)|1✔|3❌||1ms|
|[test/second.test.js](#r0s1)||1❌|1✖|8ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">test/main.test.js</a>
```
Test 1
✔️ Passing test
Test 1 Test 1.1
❌ Exception in target unit
Some error
❌ Failing test
Expected values to be strictly equal:
false !== true
Test 2
❌ Exception in test
Some error
```
### ❌ <a id="user-content-r0s1" href="#r0s1">test/second.test.js</a>
```
✖️ Skipped test
❌ Timeout test
Timeout of 1ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (C:\Users\Michal\Workspace\dorny\test-reporter\reports\mocha\test\second.test.js)
```

View file

@ -0,0 +1,41 @@
![Tests passed successfully](https://img.shields.io/badge/tests-833%20passed%2C%206%20skipped-success)
## ✔️ <a id="user-content-r0" href="#r0">fixtures/external/mocha/mocha-test-results.json</a>
**839** tests were completed in **6s** with **833** passed, **0** failed and **6** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|test/node-unit/buffered-worker-pool.spec.js|14✔|||8ms|
|test/node-unit/cli/config.spec.js|10✔|||8ms|
|test/node-unit/cli/node-flags.spec.js|105✔|||9ms|
|test/node-unit/cli/options.spec.js|36✔|||250ms|
|test/node-unit/cli/run-helpers.spec.js|9✔|||8ms|
|test/node-unit/cli/run.spec.js|40✔|||4ms|
|test/node-unit/mocha.spec.js|24✔|||33ms|
|test/node-unit/parallel-buffered-runner.spec.js|19✔|||23ms|
|test/node-unit/reporters/parallel-buffered.spec.js|6✔|||16ms|
|test/node-unit/serializer.spec.js|40✔|||31ms|
|test/node-unit/stack-trace-filter.spec.js|2✔||4✖|1ms|
|test/node-unit/utils.spec.js|5✔|||1ms|
|test/node-unit/worker.spec.js|15✔|||92ms|
|test/unit/context.spec.js|8✔|||5ms|
|test/unit/duration.spec.js|3✔|||166ms|
|test/unit/errors.spec.js|13✔|||5ms|
|test/unit/globals.spec.js|4✔|||0ms|
|test/unit/grep.spec.js|8✔|||2ms|
|test/unit/hook-async.spec.js|3✔|||1ms|
|test/unit/hook-sync-nested.spec.js|4✔|||1ms|
|test/unit/hook-sync.spec.js|3✔|||0ms|
|test/unit/hook-timeout.spec.js|1✔|||0ms|
|test/unit/hook.spec.js|4✔|||0ms|
|test/unit/mocha.spec.js|115✔||1✖|128ms|
|test/unit/overspecified-async.spec.js|1✔|||3ms|
|test/unit/parse-query.spec.js|2✔|||1ms|
|test/unit/plugin-loader.spec.js|41✔||1✖|16ms|
|test/unit/required-tokens.spec.js|1✔|||0ms|
|test/unit/root.spec.js|1✔|||0ms|
|test/unit/runnable.spec.js|55✔|||122ms|
|test/unit/runner.spec.js|77✔|||43ms|
|test/unit/suite.spec.js|57✔|||14ms|
|test/unit/test.spec.js|15✔|||0ms|
|test/unit/throw.spec.js|9✔|||9ms|
|test/unit/timeout.spec.js|8✔|||109ms|
|test/unit/utils.spec.js|75✔|||24ms|

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
{
"stats": {
"suites": 0,
"tests": 0,
"passes": 0,
"pending": 0,
"failures": 0,
"start": "2021-03-08T20:01:44.391Z",
"end": "2021-03-08T20:01:44.391Z",
"duration": 0
},
"tests": [],
"pending": [],
"failures": [],
"passes": []
}

View file

@ -0,0 +1,516 @@
.browserslistrc
.editorconfig
.eleventy.js
.eslintignore
.eslintrc.yml
.fossaignore
.gitattributes
.github/CODE_OF_CONDUCT.md
.github/CONTRIBUTING.md
.github/FUNDING.yml
.github/ISSUE_TEMPLATE/bug_report.md
.github/ISSUE_TEMPLATE/feature_request.md
.github/ISSUE_TEMPLATE/support-question.md
.github/PULL_REQUEST_TEMPLATE.md
.github/stale.yml
.github/workflows/mocha.yml
.github/workflows/nightly-site-deploy.yml
.github/workflows/purge-expired-artifacts.yml
.gitignore
.lintstagedrc.json
.mailmap
.markdownlint.json
.mocharc.yml
.npmrc
.nycrc
.wallaby.js
AUTHORS
CHANGELOG.md
LICENSE
MAINTAINERS.md
PROJECT_CHARTER.md
README.md
assets/growl/error.png
assets/growl/ok.png
assets/mocha-banner-192.png
assets/mocha-banner.svg
assets/mocha-fixture-wizard.sketch
assets/mocha-logo-128.png
assets/mocha-logo-192.png
assets/mocha-logo-64.png
assets/mocha-logo-96.png
assets/mocha-logo.svg
assets/opencollective-header.png
bin/_mocha
bin/mocha
browser-entry.js
docs/.browserslistrc
docs/.eleventyignore
docs/API.md
docs/CNAME
docs/LICENSE-CC-BY-4.0
docs/README.md
docs/_data/blocklist.json
docs/_data/files.js
docs/_data/supporters.js
docs/_data/toc.js
docs/_data/usage.js
docs/_headers
docs/_includes/default.liquid
docs/_includes/fixture-wizard.html
docs/_includes/supporters.md
docs/api-tutorials/custom-reporter.md
docs/api-tutorials/jsdoc.tutorials.json
docs/changelogs/CHANGELOG_V3_older.md
docs/changelogs/CHANGELOG_V4.md
docs/changelogs/README.md
docs/css/normalize.css
docs/css/prism.css
docs/css/style.css
docs/css/supporters.css
docs/example/Array.js
docs/example/async-dump.js
docs/example/debug-hanging-mocha.js
docs/example/tests.html
docs/favicon.ico
docs/images/emacs.png
docs/images/jetbrains-plugin.png
docs/images/join-chat.svg
docs/images/link-icon.svg
docs/images/matomo-logo.png
docs/images/mocha-logo.svg
docs/images/mocha_side_bar.png
docs/images/openjsf-logo.svg
docs/images/reporter-doc.png
docs/images/reporter-dot.png
docs/images/reporter-html.png
docs/images/reporter-json-stream.png
docs/images/reporter-json.png
docs/images/reporter-landing-fail.png
docs/images/reporter-landing.png
docs/images/reporter-list.png
docs/images/reporter-min.png
docs/images/reporter-nyan.png
docs/images/reporter-progress.png
docs/images/reporter-spec-duration.png
docs/images/reporter-spec-fail.png
docs/images/reporter-spec.png
docs/images/reporter-string-diffs.png
docs/images/reporter-tap.png
docs/images/test-duration-range.png
docs/images/wallaby-logo.png
docs/images/wallaby.png
docs/index.md
docs/js/html5shiv.min.js
example/config/.mocharc.js
example/config/.mocharc.json
example/config/.mocharc.jsonc
example/config/.mocharc.yml
example/config/README.md
index.js
jsdoc.conf.json
karma.conf.js
lib/browser/growl.js
lib/browser/highlight-tags.js
lib/browser/parse-query.js
lib/browser/progress.js
lib/browser/template.html
lib/cli/cli.js
lib/cli/collect-files.js
lib/cli/commands.js
lib/cli/config.js
lib/cli/index.js
lib/cli/init.js
lib/cli/lookup-files.js
lib/cli/node-flags.js
lib/cli/one-and-dones.js
lib/cli/options.js
lib/cli/run-helpers.js
lib/cli/run-option-metadata.js
lib/cli/run.js
lib/cli/watch-run.js
lib/context.js
lib/errors.js
lib/esm-utils.js
lib/hook.js
lib/interfaces/bdd.js
lib/interfaces/common.js
lib/interfaces/exports.js
lib/interfaces/index.js
lib/interfaces/qunit.js
lib/interfaces/tdd.js
lib/mocha.js
lib/mocharc.json
lib/nodejs/buffered-worker-pool.js
lib/nodejs/file-unloader.js
lib/nodejs/growl.js
lib/nodejs/parallel-buffered-runner.js
lib/nodejs/reporters/parallel-buffered.js
lib/nodejs/serializer.js
lib/nodejs/worker.js
lib/pending.js
lib/plugin-loader.js
lib/reporters/base.js
lib/reporters/doc.js
lib/reporters/dot.js
lib/reporters/html.js
lib/reporters/index.js
lib/reporters/json-stream.js
lib/reporters/json.js
lib/reporters/landing.js
lib/reporters/list.js
lib/reporters/markdown.js
lib/reporters/min.js
lib/reporters/nyan.js
lib/reporters/progress.js
lib/reporters/spec.js
lib/reporters/tap.js
lib/reporters/xunit.js
lib/runnable.js
lib/runner.js
lib/stats-collector.js
lib/suite.js
lib/test.js
lib/utils.js
mocha.css
netlify.toml
package-lock.json
package-scripts.js
package.json
rollup.config.js
scripts/karma-rollup-plugin.js
scripts/linkify-changelog.js
scripts/netlify-headers.js
scripts/pick-from-package-json.js
scripts/update-authors.js
test/README.md
test/assertions.js
test/browser-specific/esm.spec.mjs
test/browser-specific/fixtures/esm.fixture.mjs
test/browser-specific/fixtures/requirejs/lib.fixture.js
test/browser-specific/fixtures/requirejs/main.fixture.js
test/browser-specific/fixtures/webpack/webpack.config.js
test/browser-specific/fixtures/webpack/webpack.fixture.mjs
test/browser-specific/requirejs-setup.js
test/browser-specific/setup.js
test/compiler-fixtures/foo.fixture.js
test/compiler/test.coffee
test/compiler/test.foo
test/integration/README.md
test/integration/color.spec.js
test/integration/common-js-require.spec.js
test/integration/compiler-globbing.spec.js
test/integration/config.spec.js
test/integration/deprecate.spec.js
test/integration/diffs.spec.js
test/integration/duplicate-arguments.spec.js
test/integration/esm.spec.js
test/integration/events.spec.js
test/integration/file-utils.spec.js
test/integration/fixtures/__default__.fixture.js
test/integration/fixtures/cascade.fixture.js
test/integration/fixtures/common-js-require.fixture.js
test/integration/fixtures/config/mocha-config/index.js
test/integration/fixtures/config/mocha-config/package.json
test/integration/fixtures/config/mocharc.cjs
test/integration/fixtures/config/mocharc.js
test/integration/fixtures/config/mocharc.json
test/integration/fixtures/config/mocharc.yaml
test/integration/fixtures/current-test-title.fixture.js
test/integration/fixtures/deprecate.fixture.js
test/integration/fixtures/diffs/diffs.css.in
test/integration/fixtures/diffs/diffs.css.out
test/integration/fixtures/diffs/diffs.fixture.js
test/integration/fixtures/diffs/output
test/integration/fixtures/esm/add.mjs
test/integration/fixtures/esm/esm-failure.fixture.mjs
test/integration/fixtures/esm/esm-success.fixture.mjs
test/integration/fixtures/esm/js-folder/add.js
test/integration/fixtures/esm/js-folder/esm-in-js.fixture.js
test/integration/fixtures/esm/js-folder/package.json
test/integration/fixtures/esm/syntax-error/esm-syntax-error.fixture.mjs
test/integration/fixtures/exit.fixture.js
test/integration/fixtures/glob/glob.spec.js
test/integration/fixtures/glob/nested/glob.spec.js
test/integration/fixtures/hooks/after-each-hook-async-error.fixture.js
test/integration/fixtures/hooks/after-each-hook-error.fixture.js
test/integration/fixtures/hooks/after-each-this-test-error.fixture.js
test/integration/fixtures/hooks/after-hook-async-error.fixture.js
test/integration/fixtures/hooks/after-hook-deepnested-error.fixture.js
test/integration/fixtures/hooks/after-hook-error.fixture.js
test/integration/fixtures/hooks/after-hook-nested-error.fixture.js
test/integration/fixtures/hooks/before-each-hook-async-error.fixture.js
test/integration/fixtures/hooks/before-each-hook-error.fixture.js
test/integration/fixtures/hooks/before-hook-async-error-tip.fixture.js
test/integration/fixtures/hooks/before-hook-async-error.fixture.js
test/integration/fixtures/hooks/before-hook-deepnested-error.fixture.js
test/integration/fixtures/hooks/before-hook-error-tip.fixture.js
test/integration/fixtures/hooks/before-hook-error.fixture.js
test/integration/fixtures/hooks/before-hook-nested-error.fixture.js
test/integration/fixtures/hooks/before-hook-root-error.fixture.js
test/integration/fixtures/hooks/multiple-hook-async-error.fixture.js
test/integration/fixtures/hooks/multiple-hook-error.fixture.js
test/integration/fixtures/multiple-done-async.fixture.js
test/integration/fixtures/multiple-done-before-each.fixture.js
test/integration/fixtures/multiple-done-before.fixture.js
test/integration/fixtures/multiple-done-specs.fixture.js
test/integration/fixtures/multiple-done-with-error.fixture.js
test/integration/fixtures/multiple-done.fixture.js
test/integration/fixtures/multiple-runs/clean-references.fixture.js
test/integration/fixtures/multiple-runs/dispose.fixture.js
test/integration/fixtures/multiple-runs/multiple-runs-with-different-output-suite.fixture.js
test/integration/fixtures/multiple-runs/multiple-runs-with-flaky-before-each-suite.fixture.js
test/integration/fixtures/multiple-runs/multiple-runs-with-flaky-before-each.fixture.js
test/integration/fixtures/multiple-runs/run-thrice-helper.js
test/integration/fixtures/multiple-runs/run-thrice.fixture.js
test/integration/fixtures/multiple-runs/start-second-run-if-previous-is-still-running-suite.fixture.js
test/integration/fixtures/multiple-runs/start-second-run-if-previous-is-still-running.fixture.js
test/integration/fixtures/no-diff.fixture.js
test/integration/fixtures/options/allow-uncaught/propagate.fixture.js
test/integration/fixtures/options/allow-uncaught/this-skip-it.fixture.js
test/integration/fixtures/options/async-only-async.fixture.js
test/integration/fixtures/options/async-only-sync.fixture.js
test/integration/fixtures/options/bail-async.fixture.js
test/integration/fixtures/options/bail-with-after.fixture.js
test/integration/fixtures/options/bail-with-afterEach.fixture.js
test/integration/fixtures/options/bail-with-before.fixture.js
test/integration/fixtures/options/bail-with-beforeEach.fixture.js
test/integration/fixtures/options/bail-with-test.fixture.js
test/integration/fixtures/options/bail.fixture.js
test/integration/fixtures/options/delay-fail.fixture.js
test/integration/fixtures/options/delay-only.fixture.js
test/integration/fixtures/options/delay.fixture.js
test/integration/fixtures/options/extension/test1.fixture.js
test/integration/fixtures/options/extension/test2.fixture.coffee
test/integration/fixtures/options/file-alpha.fixture.js
test/integration/fixtures/options/file-beta.fixture.js
test/integration/fixtures/options/file-theta.fixture.js
test/integration/fixtures/options/forbid-only/only-before-each.fixture.js
test/integration/fixtures/options/forbid-only/only-before.fixture.js
test/integration/fixtures/options/forbid-only/only-empty-suite.fixture.js
test/integration/fixtures/options/forbid-only/only-suite.fixture.js
test/integration/fixtures/options/forbid-only/only.fixture.js
test/integration/fixtures/options/forbid-only/passed.fixture.js
test/integration/fixtures/options/forbid-pending/before-this-skip.fixture.js
test/integration/fixtures/options/forbid-pending/beforeEach-this-skip.fixture.js
test/integration/fixtures/options/forbid-pending/passed.fixture.js
test/integration/fixtures/options/forbid-pending/pending.fixture.js
test/integration/fixtures/options/forbid-pending/skip-empty-suite.fixture.js
test/integration/fixtures/options/forbid-pending/skip-suite.fixture.js
test/integration/fixtures/options/forbid-pending/skip.fixture.js
test/integration/fixtures/options/forbid-pending/this-skip.fixture.js
test/integration/fixtures/options/grep.fixture.js
test/integration/fixtures/options/ignore/fail.fixture.js
test/integration/fixtures/options/ignore/nested/fail.fixture.js
test/integration/fixtures/options/ignore/nested/pass.fixture.js
test/integration/fixtures/options/ignore/pass.fixture.js
test/integration/fixtures/options/jobs/fail-in-parallel.fixture.js
test/integration/fixtures/options/only/bdd.fixture.js
test/integration/fixtures/options/only/qunit.fixture.js
test/integration/fixtures/options/only/tdd.fixture.js
test/integration/fixtures/options/parallel/bail.fixture.js
test/integration/fixtures/options/parallel/exclusive-test-a.fixture.js
test/integration/fixtures/options/parallel/exclusive-test-b.fixture.js
test/integration/fixtures/options/parallel/retries-a.fixture.js
test/integration/fixtures/options/parallel/retries-b.fixture.js
test/integration/fixtures/options/parallel/syntax-err.fixture.js
test/integration/fixtures/options/parallel/test-a.fixture.js
test/integration/fixtures/options/parallel/test-b.fixture.js
test/integration/fixtures/options/parallel/test-c.fixture.js
test/integration/fixtures/options/parallel/test-d.fixture.js
test/integration/fixtures/options/parallel/uncaught.fixture.js
test/integration/fixtures/options/reporter-with-options.fixture.js
test/integration/fixtures/options/retries.fixture.js
test/integration/fixtures/options/slow-test.fixture.js
test/integration/fixtures/options/sort-alpha.fixture.js
test/integration/fixtures/options/sort-beta.fixture.js
test/integration/fixtures/options/watch/dependency.fixture.js
test/integration/fixtures/options/watch/hook.fixture.js
test/integration/fixtures/options/watch/test-file-change.fixture.js
test/integration/fixtures/options/watch/test-with-dependency.fixture.js
test/integration/fixtures/parallel/test1.mjs
test/integration/fixtures/parallel/test2.mjs
test/integration/fixtures/parallel/test3.mjs
test/integration/fixtures/passing-async.fixture.js
test/integration/fixtures/passing-sync.fixture.js
test/integration/fixtures/passing.fixture.js
test/integration/fixtures/pending/programmatic.fixture.js
test/integration/fixtures/pending/skip-async-before-hooks.fixture.js
test/integration/fixtures/pending/skip-async-before-nested.fixture.js
test/integration/fixtures/pending/skip-async-before.fixture.js
test/integration/fixtures/pending/skip-async-beforeEach.fixture.js
test/integration/fixtures/pending/skip-async-spec.fixture.js
test/integration/fixtures/pending/skip-hierarchy.fixture.js
test/integration/fixtures/pending/skip-shorthand.fixture.js
test/integration/fixtures/pending/skip-sync-after.fixture.js
test/integration/fixtures/pending/skip-sync-before-hooks.fixture.js
test/integration/fixtures/pending/skip-sync-before-inner.fixture.js
test/integration/fixtures/pending/skip-sync-before-nested.fixture.js
test/integration/fixtures/pending/skip-sync-before.fixture.js
test/integration/fixtures/pending/skip-sync-beforeEach-cond.fixture.js
test/integration/fixtures/pending/skip-sync-beforeEach.fixture.js
test/integration/fixtures/pending/skip-sync-spec.fixture.js
test/integration/fixtures/pending/spec.fixture.js
test/integration/fixtures/plugins/global-fixtures/global-setup-teardown-multiple.fixture.js
test/integration/fixtures/plugins/global-fixtures/global-setup-teardown.fixture.js
test/integration/fixtures/plugins/global-fixtures/global-setup.fixture.js
test/integration/fixtures/plugins/global-fixtures/global-teardown.fixture.js
test/integration/fixtures/plugins/root-hooks/esm/package.json
test/integration/fixtures/plugins/root-hooks/esm/root-hook-defs-esm.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-defs-a.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-defs-b.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-defs-c.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-defs-d.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-defs-esm-broken.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-defs-esm.fixture.mjs
test/integration/fixtures/plugins/root-hooks/root-hook-test-2.fixture.js
test/integration/fixtures/plugins/root-hooks/root-hook-test.fixture.js
test/integration/fixtures/regression/issue-1991.fixture.js
test/integration/fixtures/regression/issue-2315.fixture.js
test/integration/fixtures/regression/issue-2406.fixture.js
test/integration/fixtures/regression/issue-2417.fixture.js
test/integration/fixtures/reporters.fixture.js
test/integration/fixtures/retries/async.fixture.js
test/integration/fixtures/retries/early-pass.fixture.js
test/integration/fixtures/retries/hooks.fixture.js
test/integration/fixtures/retries/nested.fixture.js
test/integration/fixtures/runner/events-bail-retries.fixture.js
test/integration/fixtures/runner/events-bail.fixture.js
test/integration/fixtures/runner/events-basic.fixture.js
test/integration/fixtures/runner/events-delay.fixture.js
test/integration/fixtures/runner/events-retries.fixture.js
test/integration/fixtures/simple-reporter.js
test/integration/fixtures/simple-ui.fixture.js
test/integration/fixtures/suite/suite-no-callback.fixture.js
test/integration/fixtures/suite/suite-returning-value.fixture.js
test/integration/fixtures/suite/suite-skipped-callback.fixture.js
test/integration/fixtures/suite/suite-skipped-no-callback.fixture.js
test/integration/fixtures/test-for-simple-ui.fixture.js
test/integration/fixtures/timeout-override.fixture.js
test/integration/fixtures/timeout.fixture.js
test/integration/fixtures/uncaught/after-runner.fixture.js
test/integration/fixtures/uncaught/double.fixture.js
test/integration/fixtures/uncaught/fatal.fixture.js
test/integration/fixtures/uncaught/hook.fixture.js
test/integration/fixtures/uncaught/issue-1327.fixture.js
test/integration/fixtures/uncaught/issue-1417.fixture.js
test/integration/fixtures/uncaught/listeners.fixture.js
test/integration/fixtures/uncaught/pending.fixture.js
test/integration/fixtures/uncaught/recover.fixture.js
test/integration/fixtures/uncaught/unhandled.fixture.js
test/integration/glob.spec.js
test/integration/helpers.js
test/integration/hook-err.spec.js
test/integration/hooks.spec.js
test/integration/init.spec.js
test/integration/invalid-arguments.spec.js
test/integration/multiple-done.spec.js
test/integration/multiple-runs.spec.js
test/integration/no-diff.spec.js
test/integration/only.spec.js
test/integration/options/allowUncaught.spec.js
test/integration/options/asyncOnly.spec.js
test/integration/options/bail.spec.js
test/integration/options/compilers.spec.js
test/integration/options/delay.spec.js
test/integration/options/exit.spec.js
test/integration/options/extension.spec.js
test/integration/options/file.spec.js
test/integration/options/forbidOnly.spec.js
test/integration/options/forbidPending.spec.js
test/integration/options/grep.spec.js
test/integration/options/ignore.spec.js
test/integration/options/invert.spec.js
test/integration/options/jobs.spec.js
test/integration/options/listInterfaces.spec.js
test/integration/options/listReporters.spec.js
test/integration/options/node-flags.spec.js
test/integration/options/opts.spec.js
test/integration/options/parallel.spec.js
test/integration/options/reporter-option.spec.js
test/integration/options/retries.spec.js
test/integration/options/sort.spec.js
test/integration/options/timeout.spec.js
test/integration/options/ui.spec.js
test/integration/options/watch.spec.js
test/integration/parallel.spec.js
test/integration/pending.spec.js
test/integration/plugins/global-fixtures.spec.js
test/integration/plugins/root-hooks.spec.js
test/integration/regression.spec.js
test/integration/reporters.spec.js
test/integration/retries.spec.js
test/integration/suite.spec.js
test/integration/timeout.spec.js
test/integration/uncaught.spec.js
test/interfaces/bdd.spec.js
test/interfaces/exports.spec.js
test/interfaces/qunit.spec.js
test/interfaces/tdd.spec.js
test/jsapi/index.js
test/node-unit/buffered-worker-pool.spec.js
test/node-unit/cli/config.spec.js
test/node-unit/cli/fixtures/bad-module.fixture.js
test/node-unit/cli/node-flags.spec.js
test/node-unit/cli/options.spec.js
test/node-unit/cli/run-helpers.spec.js
test/node-unit/cli/run.spec.js
test/node-unit/fixtures/dumb-module.fixture.js
test/node-unit/fixtures/dumber-module.fixture.js
test/node-unit/fixtures/wonky-reporter.fixture.js
test/node-unit/mocha.spec.js
test/node-unit/parallel-buffered-runner.spec.js
test/node-unit/reporters/parallel-buffered.spec.js
test/node-unit/serializer.spec.js
test/node-unit/stack-trace-filter.spec.js
test/node-unit/utils.spec.js
test/node-unit/worker.spec.js
test/only/bdd-require.spec.js
test/only/global/bdd.spec.js
test/only/global/qunit.spec.js
test/only/global/tdd.spec.js
test/reporters/base.spec.js
test/reporters/doc.spec.js
test/reporters/dot.spec.js
test/reporters/helpers.js
test/reporters/json-stream.spec.js
test/reporters/json.spec.js
test/reporters/landing.spec.js
test/reporters/list.spec.js
test/reporters/markdown.spec.js
test/reporters/min.spec.js
test/reporters/nyan.spec.js
test/reporters/progress.spec.js
test/reporters/spec.spec.js
test/reporters/tap.spec.js
test/reporters/xunit.spec.js
test/require/a.js
test/require/b.coffee
test/require/c.js
test/require/d.coffee
test/require/require.spec.js
test/setup.js
test/smoke/smoke.spec.js
test/unit/context.spec.js
test/unit/duration.spec.js
test/unit/errors.spec.js
test/unit/globals.spec.js
test/unit/grep.spec.js
test/unit/hook-async.spec.js
test/unit/hook-sync-nested.spec.js
test/unit/hook-sync.spec.js
test/unit/hook-timeout.spec.js
test/unit/hook.spec.js
test/unit/mocha.spec.js
test/unit/overspecified-async.spec.js
test/unit/parse-query.spec.js
test/unit/plugin-loader.spec.js
test/unit/required-tokens.spec.js
test/unit/root.spec.js
test/unit/runnable.spec.js
test/unit/runner.spec.js
test/unit/suite.spec.js
test/unit/test.spec.js
test/unit/throw.spec.js
test/unit/timeout.spec.js
test/unit/utils.spec.js

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,158 @@
{
"stats": {
"suites": 3,
"tests": 6,
"passes": 1,
"pending": 1,
"failures": 4,
"start": "2021-02-24T20:26:09.297Z",
"end": "2021-02-24T20:26:09.309Z",
"duration": 12
},
"tests": [
{
"title": "Timeout test",
"fullTitle": "Timeout test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js",
"duration": 8,
"currentRetry": 0,
"err": {
"stack": "Error: Timeout of 1ms exceeded. For async tests and hooks, ensure \"done()\" is called; if returning a Promise, ensure it resolves. (C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js)\n at listOnTimeout (internal/timers.js:554:17)\n at processTimers (internal/timers.js:497:7)",
"message": "Timeout of 1ms exceeded. For async tests and hooks, ensure \"done()\" is called; if returning a Promise, ensure it resolves. (C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js)",
"code": "ERR_MOCHA_TIMEOUT",
"timeout": 1,
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js"
}
},
{
"title": "Skipped test",
"fullTitle": "Skipped test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js",
"currentRetry": 0,
"err": {}
},
{
"title": "Passing test",
"fullTitle": "Test 1 Passing test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 0,
"currentRetry": 0,
"speed": "fast",
"err": {}
},
{
"title": "Failing test",
"fullTitle": "Test 1 Test 1.1 Failing test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 1,
"currentRetry": 0,
"err": {
"stack": "AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:\n\nfalse !== true\n\n at Context.<anonymous> (test\\main.test.js:11:14)\n at processImmediate (internal/timers.js:461:21)",
"message": "Expected values to be strictly equal:\n\nfalse !== true\n",
"generatedMessage": true,
"name": "AssertionError",
"code": "ERR_ASSERTION",
"actual": "false",
"expected": "true",
"operator": "strictEqual"
}
},
{
"title": "Exception in target unit",
"fullTitle": "Test 1 Test 1.1 Exception in target unit",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 0,
"currentRetry": 0,
"err": {
"stack": "Error: Some error\n at Object.throwError (lib\\main.js:2:9)\n at Context.<anonymous> (test\\main.test.js:15:11)\n at processImmediate (internal/timers.js:461:21)",
"message": "Some error"
}
},
{
"title": "Exception in test",
"fullTitle": "Test 2 Exception in test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 0,
"currentRetry": 0,
"err": {
"stack": "Error: Some error\n at Context.<anonymous> (test\\main.test.js:22:11)\n at processImmediate (internal/timers.js:461:21)",
"message": "Some error"
}
}
],
"pending": [
{
"title": "Skipped test",
"fullTitle": "Skipped test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js",
"currentRetry": 0,
"err": {}
}
],
"failures": [
{
"title": "Timeout test",
"fullTitle": "Timeout test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js",
"duration": 8,
"currentRetry": 0,
"err": {
"stack": "Error: Timeout of 1ms exceeded. For async tests and hooks, ensure \"done()\" is called; if returning a Promise, ensure it resolves. (C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js)\n at listOnTimeout (internal/timers.js:554:17)\n at processTimers (internal/timers.js:497:7)",
"message": "Timeout of 1ms exceeded. For async tests and hooks, ensure \"done()\" is called; if returning a Promise, ensure it resolves. (C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js)",
"code": "ERR_MOCHA_TIMEOUT",
"timeout": 1,
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\second.test.js"
}
},
{
"title": "Failing test",
"fullTitle": "Test 1 Test 1.1 Failing test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 1,
"currentRetry": 0,
"err": {
"stack": "AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:\n\nfalse !== true\n\n at Context.<anonymous> (test\\main.test.js:11:14)\n at processImmediate (internal/timers.js:461:21)",
"message": "Expected values to be strictly equal:\n\nfalse !== true\n",
"generatedMessage": true,
"name": "AssertionError",
"code": "ERR_ASSERTION",
"actual": "false",
"expected": "true",
"operator": "strictEqual"
}
},
{
"title": "Exception in target unit",
"fullTitle": "Test 1 Test 1.1 Exception in target unit",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 0,
"currentRetry": 0,
"err": {
"stack": "Error: Some error\n at Object.throwError (lib\\main.js:2:9)\n at Context.<anonymous> (test\\main.test.js:15:11)\n at processImmediate (internal/timers.js:461:21)",
"message": "Some error"
}
},
{
"title": "Exception in test",
"fullTitle": "Test 2 Exception in test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 0,
"currentRetry": 0,
"err": {
"stack": "Error: Some error\n at Context.<anonymous> (test\\main.test.js:22:11)\n at processImmediate (internal/timers.js:461:21)",
"message": "Some error"
}
}
],
"passes": [
{
"title": "Passing test",
"fullTitle": "Test 1 Passing test",
"file": "C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\mocha\\test\\main.test.js",
"duration": 0,
"currentRetry": 0,
"speed": "fast",
"err": {}
}
]
}

View file

@ -0,0 +1,67 @@
import * as fs from 'fs'
import * as path from 'path'
import {MochaJsonParser} from '../src/parsers/mocha-json/mocha-json-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('mocha-json tests', () => {
it('produces empty test run result when there are no test cases', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'mocha-json.json')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new MochaJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
})
it('report from ./reports/mocha-json test results matches snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'mocha-json.json')
const outputPath = path.join(__dirname, '__outputs__', 'mocha-json.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: ['test/main.test.js', 'test/second.test.js', 'lib/main.js']
}
const parser = new MochaJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report from mochajs/mocha test results matches snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'mocha', 'mocha-test-results.json')
const trackedFilesPath = path.join(__dirname, 'fixtures', 'external', 'mocha', 'files.txt')
const outputPath = path.join(__dirname, '__outputs__', 'mocha-test-results.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const trackedFiles = fs.readFileSync(trackedFilesPath, {encoding: 'utf8'}).split(/\n\r?/g)
const opts: ParseOptions = {
parseErrors: true,
trackedFiles
}
const parser = new MochaJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
})

View file

@ -1,6 +1,6 @@
name: Test Reporter
description: |
Displays test results directly in GitHub. Supports .NET (xUnit, NUnit, MSTest), Dart, Flutter and JavaScript (JEST).
Shows test results in GitHub UI: .NET (xUnit, NUnit, MSTest), Dart, Flutter, Java (JUnit), JavaScript (JEST, Mocha)
author: Michal Dorner <dorner.michal@gmail.com>
inputs:
artifact:
@ -23,6 +23,7 @@ inputs:
- flutter-json
- java-junit
- jest-junit
- mocha-json
required: true
list-suites:
description: |

197
dist/index.js generated vendored
View file

@ -221,6 +221,7 @@ const dart_json_parser_1 = __nccwpck_require__(4528);
const dotnet_trx_parser_1 = __nccwpck_require__(2664);
const java_junit_parser_1 = __nccwpck_require__(676);
const jest_junit_parser_1 = __nccwpck_require__(1113);
const mocha_json_parser_1 = __nccwpck_require__(6043);
const path_utils_1 = __nccwpck_require__(4070);
const github_utils_1 = __nccwpck_require__(3522);
const markdown_utils_1 = __nccwpck_require__(6482);
@ -373,6 +374,8 @@ class TestReporter {
return new java_junit_parser_1.JavaJunitParser(options);
case 'jest-junit':
return new jest_junit_parser_1.JestJunitParser(options);
case 'mocha-json':
return new mocha_json_parser_1.MochaJsonParser(options);
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`);
}
@ -687,6 +690,7 @@ class DotnetTrxParser {
const trx = await this.getTrxReport(path, content);
const tc = this.getTestClasses(trx);
const tr = this.getTestRunResult(path, trx, tc);
tr.sort(true);
return tr;
}
async getTrxReport(path, content) {
@ -727,10 +731,6 @@ class DotnetTrxParser {
tc.tests.push(test);
}
const result = Object.values(testClasses);
result.sort((a, b) => a.name.localeCompare(b.name));
for (const tc of result) {
tc.tests.sort((a, b) => a.name.localeCompare(b.name));
}
return result;
}
getTestRunResult(path, trx, testClasses) {
@ -1004,6 +1004,7 @@ exports.JavaJunitParser = JavaJunitParser;
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.JestJunitParser = void 0;
const xml2js_1 = __nccwpck_require__(6189);
const node_utils_1 = __nccwpck_require__(5824);
const path_utils_1 = __nccwpck_require__(4070);
const test_results_1 = __nccwpck_require__(2768);
class JestJunitParser {
@ -1069,7 +1070,7 @@ class JestJunitParser {
const details = tc.failure[0];
let path;
let line;
const src = this.exceptionThrowSource(details);
const src = node_utils_1.getExceptionSource(details, this.options.trackedFiles, file => this.getRelativePath(file));
if (src) {
path = src.path;
line = src.line;
@ -1080,29 +1081,13 @@ class JestJunitParser {
details
};
}
exceptionThrowSource(stackTrace) {
const lines = stackTrace.split(/\r?\n/);
const re = /\((.*):(\d+):\d+\)$/;
const { trackedFiles } = this.options;
for (const str of lines) {
const match = str.match(re);
if (match !== null) {
const [_, fileStr, lineStr] = match;
const filePath = path_utils_1.normalizeFilePath(fileStr);
if (filePath.startsWith('internal/') || filePath.includes('/node_modules/')) {
continue;
}
const workDir = this.getWorkDir(filePath);
if (!workDir) {
continue;
}
const path = filePath.substr(workDir.length);
if (trackedFiles.includes(path)) {
const line = parseInt(lineStr);
return { path, line };
}
}
getRelativePath(path) {
path = path_utils_1.normalizeFilePath(path);
const workDir = this.getWorkDir(path);
if (workDir !== undefined && path.startsWith(workDir)) {
path = path.substr(workDir.length);
}
return path;
}
getWorkDir(path) {
var _a, _b;
@ -1112,6 +1097,108 @@ class JestJunitParser {
exports.JestJunitParser = JestJunitParser;
/***/ }),
/***/ 6043:
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.MochaJsonParser = void 0;
const test_results_1 = __nccwpck_require__(2768);
const node_utils_1 = __nccwpck_require__(5824);
const path_utils_1 = __nccwpck_require__(4070);
class MochaJsonParser {
constructor(options) {
this.options = options;
}
async parse(path, content) {
const mocha = this.getMochaJson(path, content);
const result = this.getTestRunResult(path, mocha);
result.sort(true);
return Promise.resolve(result);
}
getMochaJson(path, content) {
try {
return JSON.parse(content);
}
catch (e) {
throw new Error(`Invalid JSON at ${path}\n\n${e}`);
}
}
getTestRunResult(resultsPath, mocha) {
const suitesMap = {};
const getSuite = (test) => {
var _a;
const path = this.getRelativePath(test.file);
return (_a = suitesMap[path]) !== null && _a !== void 0 ? _a : (suitesMap[path] = new test_results_1.TestSuiteResult(path, []));
};
for (const test of mocha.passes) {
const suite = getSuite(test);
this.processTest(suite, test, 'success');
}
for (const test of mocha.failures) {
const suite = getSuite(test);
this.processTest(suite, test, 'failed');
}
for (const test of mocha.pending) {
const suite = getSuite(test);
this.processTest(suite, test, 'skipped');
}
const suites = Object.values(suitesMap);
return new test_results_1.TestRunResult(resultsPath, suites, mocha.stats.duration);
}
processTest(suite, test, result) {
var _a;
const groupName = test.fullTitle !== test.title
? test.fullTitle.substr(0, test.fullTitle.length - test.title.length).trimEnd()
: null;
let group = suite.groups.find(grp => grp.name === groupName);
if (group === undefined) {
group = new test_results_1.TestGroupResult(groupName, []);
suite.groups.push(group);
}
const error = this.getTestCaseError(test);
const testCase = new test_results_1.TestCaseResult(test.title, result, (_a = test.duration) !== null && _a !== void 0 ? _a : 0, error);
group.tests.push(testCase);
}
getTestCaseError(test) {
const details = test.err.stack;
const message = test.err.message;
if (details === undefined) {
return undefined;
}
let path;
let line;
const src = node_utils_1.getExceptionSource(details, this.options.trackedFiles, file => this.getRelativePath(file));
if (src) {
path = src.path;
line = src.line;
}
return {
path,
line,
message,
details
};
}
getRelativePath(path) {
path = path_utils_1.normalizeFilePath(path);
const workDir = this.getWorkDir(path);
if (workDir !== undefined && path.startsWith(workDir)) {
path = path.substr(workDir.length);
}
return path;
}
getWorkDir(path) {
var _a, _b;
return ((_b = (_a = this.options.workDir) !== null && _a !== void 0 ? _a : this.assumedWorkDir) !== null && _b !== void 0 ? _b : (this.assumedWorkDir = path_utils_1.getBasePath(path, this.options.trackedFiles)));
}
}
exports.MochaJsonParser = MochaJsonParser;
/***/ }),
/***/ 5867:
@ -1152,7 +1239,7 @@ function getAnnotations(results, maxCount) {
errors.push({
testRunPaths: [tr.path],
suiteName: ts.name,
testName: tc.name,
testName: tg.name ? `${tg.name}${tc.name}` : tc.name,
details: err.details,
message: (_d = (_c = err.message) !== null && _c !== void 0 ? _c : parse_utils_1.getFirstNonEmptyLine(err.details)) !== null && _d !== void 0 ? _d : 'Test failed',
path,
@ -1480,6 +1567,14 @@ class TestRunResult {
get failedSuites() {
return this.suites.filter(s => s.result === 'failed');
}
sort(deep) {
this.suites.sort((a, b) => a.name.localeCompare(b.name));
if (deep) {
for (const suite of this.suites) {
suite.sort(deep);
}
}
}
}
exports.TestRunResult = TestRunResult;
class TestSuiteResult {
@ -1510,6 +1605,14 @@ class TestSuiteResult {
get failedGroups() {
return this.groups.filter(grp => grp.result === 'failed');
}
sort(deep) {
this.groups.sort((a, b) => { var _a, _b; return ((_a = a.name) !== null && _a !== void 0 ? _a : '').localeCompare((_b = b.name) !== null && _b !== void 0 ? _b : ''); });
if (deep) {
for (const grp of this.groups) {
grp.sort();
}
}
}
}
exports.TestSuiteResult = TestSuiteResult;
class TestGroupResult {
@ -1535,6 +1638,9 @@ class TestGroupResult {
get failedTests() {
return this.tests.filter(tc => tc.result === 'failed');
}
sort() {
this.tests.sort((a, b) => a.name.localeCompare(b.name));
}
}
exports.TestGroupResult = TestGroupResult;
class TestCaseResult {
@ -1831,6 +1937,41 @@ function formatTime(ms) {
exports.formatTime = formatTime;
/***/ }),
/***/ 5824:
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getExceptionSource = void 0;
const path_utils_1 = __nccwpck_require__(4070);
function getExceptionSource(stackTrace, trackedFiles, getRelativePath) {
const lines = stackTrace.split(/\r?\n/);
const re = /\((.*):(\d+):\d+\)$/;
for (const str of lines) {
const match = str.match(re);
if (match !== null) {
const [_, fileStr, lineStr] = match;
const filePath = path_utils_1.normalizeFilePath(fileStr);
if (filePath.startsWith('internal/') || filePath.includes('/node_modules/')) {
continue;
}
const path = getRelativePath(filePath);
if (!path) {
continue;
}
if (trackedFiles.includes(path)) {
const line = parseInt(lineStr);
return { path, line };
}
}
}
}
exports.getExceptionSource = getExceptionSource;
/***/ }),
/***/ 7811:

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View file

@ -14,7 +14,8 @@
"all": "npm run build && npm run format && npm run lint && npm run package && npm test",
"dart-fixture": "cd \"reports/dart\" && dart test --file-reporter=\"json:../../__tests__/fixtures/dart-json.json\"",
"dotnet-fixture": "dotnet test reports/dotnet/DotnetTests.XUnitTests --logger \"trx;LogFileName=../../../../__tests__/fixtures/dotnet-trx.trx\"",
"jest-fixture": "cd \"reports/jest\" && npm test"
"jest-fixture": "cd \"reports/jest\" && npm test",
"mocha-fixture": "cd \"reports/mocha\" && npm test"
},
"repository": {
"type": "git",

View file

@ -0,0 +1,5 @@
function throwError() {
throw new Error('Some error')
}
exports.throwError = throwError

761
reports/mocha/package-lock.json generated Normal file
View file

@ -0,0 +1,761 @@
{
"name": "mocha-fixture",
"version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@ungap/promise-all-settled": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
"dev": true
},
"ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
"dev": true
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true
},
"camelcase": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz",
"integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==",
"dev": true
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"chokidar": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
}
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"ms": "2.1.2"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"decamelize": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true
},
"diff": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
"dev": true
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"requires": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
}
},
"flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"js-yaml": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
"integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
"dev": true,
"requires": {
"argparse": "^2.0.1"
}
},
"locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"requires": {
"p-locate": "^5.0.0"
}
},
"log-symbols": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"dev": true,
"requires": {
"chalk": "^4.0.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"mocha": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz",
"integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==",
"dev": true,
"requires": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.1",
"debug": "4.3.1",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"glob": "7.1.6",
"growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "4.0.0",
"log-symbols": "4.0.0",
"minimatch": "3.0.4",
"ms": "2.1.3",
"nanoid": "3.1.20",
"serialize-javascript": "5.0.1",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
"which": "2.0.2",
"wide-align": "1.1.3",
"workerpool": "6.1.0",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"nanoid": {
"version": "3.1.20",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==",
"dev": true
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"requires": {
"yocto-queue": "^0.1.0"
}
},
"p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"requires": {
"p-limit": "^3.0.2"
}
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
},
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true
},
"serialize-javascript": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
"integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "^3.0.0"
}
},
"strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"dev": true,
"requires": {
"string-width": "^1.0.2 || 2"
}
},
"workerpool": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
"integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==",
"dev": true
},
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
}
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"y18n": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
"dev": true
},
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
}
}
},
"yargs-parser": {
"version": "20.2.4",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
"dev": true
},
"yargs-unparser": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
"requires": {
"camelcase": "^6.0.0",
"decamelize": "^4.0.0",
"flat": "^5.0.2",
"is-plain-obj": "^2.1.0"
}
},
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true
}
}
}

View file

@ -0,0 +1,14 @@
{
"name": "mocha-fixture",
"version": "0.0.0",
"private": true,
"description": "Generates test fixtures for test-reporter action",
"scripts": {
"test": "mocha --reporter json > ../../__tests__/fixtures/mocha-json.json"
},
"author": "Michal Dorner <dorner.michal@gmail.com>",
"license": "MIT",
"devDependencies": {
"mocha": "^8.3.0"
}
}

View file

@ -0,0 +1,24 @@
const assert = require('assert').strict;
const lib = require('../lib/main')
describe('Test 1', () => {
it('Passing test', () => {
assert.equal(true, true)
});
describe('Test 1.1', () => {
it('Failing test', () => {
assert.equal(false, true)
});
it('Exception in target unit', () => {
lib.throwError();
});
});
});
describe('Test 2', () => {
it('Exception in test', () => {
throw new Error('Some error');
});
});

View file

@ -0,0 +1,8 @@
it('Timeout test', async function(done) {
this.timeout(1);
setTimeout(done, 1000);
});
it.skip('Skipped test', () => {
// do nothing
});

View file

@ -14,6 +14,7 @@ import {DartJsonParser} from './parsers/dart-json/dart-json-parser'
import {DotnetTrxParser} from './parsers/dotnet-trx/dotnet-trx-parser'
import {JavaJunitParser} from './parsers/java-junit/java-junit-parser'
import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser'
import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser'
import {normalizeDirPath} from './utils/path-utils'
import {getCheckRunContext} from './utils/github-utils'
@ -201,6 +202,8 @@ class TestReporter {
return new JavaJunitParser(options)
case 'jest-junit':
return new JestJunitParser(options)
case 'mocha-json':
return new MochaJsonParser(options)
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
}

View file

@ -49,6 +49,7 @@ export class DotnetTrxParser implements TestParser {
const trx = await this.getTrxReport(path, content)
const tc = this.getTestClasses(trx)
const tr = this.getTestRunResult(path, trx, tc)
tr.sort(true)
return tr
}
@ -94,11 +95,6 @@ export class DotnetTrxParser implements TestParser {
}
const result = Object.values(testClasses)
result.sort((a, b) => a.name.localeCompare(b.name))
for (const tc of result) {
tc.tests.sort((a, b) => a.name.localeCompare(b.name))
}
return result
}

View file

@ -2,6 +2,7 @@ import {ParseOptions, TestParser} from '../../test-parser'
import {parseStringPromise} from 'xml2js'
import {JunitReport, TestCase, TestSuite} from './jest-junit-types'
import {getExceptionSource} from '../../utils/node-utils'
import {getBasePath, normalizeFilePath} from '../../utils/path-utils'
import {
@ -84,7 +85,7 @@ export class JestJunitParser implements TestParser {
let path
let line
const src = this.exceptionThrowSource(details)
const src = getExceptionSource(details, this.options.trackedFiles, file => this.getRelativePath(file))
if (src) {
path = src.path
line = src.line
@ -97,31 +98,13 @@ export class JestJunitParser implements TestParser {
}
}
private exceptionThrowSource(stackTrace: string): {path: string; line: number} | undefined {
const lines = stackTrace.split(/\r?\n/)
const re = /\((.*):(\d+):\d+\)$/
const {trackedFiles} = this.options
for (const str of lines) {
const match = str.match(re)
if (match !== null) {
const [_, fileStr, lineStr] = match
const filePath = normalizeFilePath(fileStr)
if (filePath.startsWith('internal/') || filePath.includes('/node_modules/')) {
continue
}
const workDir = this.getWorkDir(filePath)
if (!workDir) {
continue
}
const path = filePath.substr(workDir.length)
if (trackedFiles.includes(path)) {
const line = parseInt(lineStr)
return {path, line}
}
}
private getRelativePath(path: string): string {
path = normalizeFilePath(path)
const workDir = this.getWorkDir(path)
if (workDir !== undefined && path.startsWith(workDir)) {
path = path.substr(workDir.length)
}
return path
}
private getWorkDir(path: string): string | undefined {

View file

@ -0,0 +1,118 @@
import {ParseOptions, TestParser} from '../../test-parser'
import {
TestCaseError,
TestCaseResult,
TestExecutionResult,
TestGroupResult,
TestRunResult,
TestSuiteResult
} from '../../test-results'
import {getExceptionSource} from '../../utils/node-utils'
import {getBasePath, normalizeFilePath} from '../../utils/path-utils'
import {MochaJson, MochaJsonTest} from './mocha-json-types'
export class MochaJsonParser implements TestParser {
assumedWorkDir: string | undefined
constructor(readonly options: ParseOptions) {}
async parse(path: string, content: string): Promise<TestRunResult> {
const mocha = this.getMochaJson(path, content)
const result = this.getTestRunResult(path, mocha)
result.sort(true)
return Promise.resolve(result)
}
private getMochaJson(path: string, content: string): MochaJson {
try {
return JSON.parse(content)
} catch (e) {
throw new Error(`Invalid JSON at ${path}\n\n${e}`)
}
}
private getTestRunResult(resultsPath: string, mocha: MochaJson): TestRunResult {
const suitesMap: {[path: string]: TestSuiteResult} = {}
const getSuite = (test: MochaJsonTest): TestSuiteResult => {
const path = this.getRelativePath(test.file)
return suitesMap[path] ?? (suitesMap[path] = new TestSuiteResult(path, []))
}
for (const test of mocha.passes) {
const suite = getSuite(test)
this.processTest(suite, test, 'success')
}
for (const test of mocha.failures) {
const suite = getSuite(test)
this.processTest(suite, test, 'failed')
}
for (const test of mocha.pending) {
const suite = getSuite(test)
this.processTest(suite, test, 'skipped')
}
const suites = Object.values(suitesMap)
return new TestRunResult(resultsPath, suites, mocha.stats.duration)
}
private processTest(suite: TestSuiteResult, test: MochaJsonTest, result: TestExecutionResult): void {
const groupName =
test.fullTitle !== test.title
? test.fullTitle.substr(0, test.fullTitle.length - test.title.length).trimEnd()
: null
let group = suite.groups.find(grp => grp.name === groupName)
if (group === undefined) {
group = new TestGroupResult(groupName, [])
suite.groups.push(group)
}
const error = this.getTestCaseError(test)
const testCase = new TestCaseResult(test.title, result, test.duration ?? 0, error)
group.tests.push(testCase)
}
private getTestCaseError(test: MochaJsonTest): TestCaseError | undefined {
const details = test.err.stack
const message = test.err.message
if (details === undefined) {
return undefined
}
let path
let line
const src = getExceptionSource(details, this.options.trackedFiles, file => this.getRelativePath(file))
if (src) {
path = src.path
line = src.line
}
return {
path,
line,
message,
details
}
}
private getRelativePath(path: string): string {
path = normalizeFilePath(path)
const workDir = this.getWorkDir(path)
if (workDir !== undefined && path.startsWith(workDir)) {
path = path.substr(workDir.length)
}
return path
}
private getWorkDir(path: string): string | undefined {
return (
this.options.workDir ??
this.assumedWorkDir ??
(this.assumedWorkDir = getBasePath(path, this.options.trackedFiles))
)
}
}

View file

@ -0,0 +1,23 @@
export interface MochaJson {
stats: MochaJsonStats
passes: MochaJsonTest[]
pending: MochaJsonTest[]
failures: MochaJsonTest[]
}
export interface MochaJsonStats {
duration: number
}
export interface MochaJsonTest {
title: string
fullTitle: string
file: string
duration?: number
err: MochaJsonTestError
}
export interface MochaJsonTestError {
stack?: string
message?: string
}

View file

@ -54,7 +54,7 @@ export function getAnnotations(results: TestRunResult[], maxCount: number): Anno
errors.push({
testRunPaths: [tr.path],
suiteName: ts.name,
testName: tc.name,
testName: tg.name ? `${tg.name}${tc.name}` : tc.name,
details: err.details,
message: err.message ?? getFirstNonEmptyLine(err.details) ?? 'Test failed',
path,

View file

@ -26,6 +26,15 @@ export class TestRunResult {
get failedSuites(): TestSuiteResult[] {
return this.suites.filter(s => s.result === 'failed')
}
sort(deep: boolean): void {
this.suites.sort((a, b) => a.name.localeCompare(b.name))
if (deep) {
for (const suite of this.suites) {
suite.sort(deep)
}
}
}
}
export class TestSuiteResult {
@ -55,6 +64,15 @@ export class TestSuiteResult {
get failedGroups(): TestGroupResult[] {
return this.groups.filter(grp => grp.result === 'failed')
}
sort(deep: boolean): void {
this.groups.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''))
if (deep) {
for (const grp of this.groups) {
grp.sort()
}
}
}
}
export class TestGroupResult {
@ -80,6 +98,10 @@ export class TestGroupResult {
get failedTests(): TestCaseResult[] {
return this.tests.filter(tc => tc.result === 'failed')
}
sort(): void {
this.tests.sort((a, b) => a.name.localeCompare(b.name))
}
}
export class TestCaseResult {

30
src/utils/node-utils.ts Normal file
View file

@ -0,0 +1,30 @@
import {normalizeFilePath} from './path-utils'
export function getExceptionSource(
stackTrace: string,
trackedFiles: string[],
getRelativePath: (str: string) => string
): {path: string; line: number} | undefined {
const lines = stackTrace.split(/\r?\n/)
const re = /\((.*):(\d+):\d+\)$/
for (const str of lines) {
const match = str.match(re)
if (match !== null) {
const [_, fileStr, lineStr] = match
const filePath = normalizeFilePath(fileStr)
if (filePath.startsWith('internal/') || filePath.includes('/node_modules/')) {
continue
}
const path = getRelativePath(filePath)
if (!path) {
continue
}
if (trackedFiles.includes(path)) {
const line = parseInt(lineStr)
return {path, line}
}
}
}
}