Merge pull request #99 from dorny/dev

Version 1.4.0
This commit is contained in:
Michal Dorner 2021-04-20 00:09:45 +02:00 committed by GitHub
commit 0c4e1654a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 28124 additions and 1153 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

@ -1,5 +1,11 @@
# Changelog
## v1.4.0
- [Add support for mocha-json](https://github.com/dorny/test-reporter/pull/90)
- [Use full URL to fix navigation from summary to suite details](https://github.com/dorny/test-reporter/pull/89)
- [New report rendering with code blocks instead of tables](https://github.com/dorny/test-reporter/pull/88)
- [Improve test error messages from flutter](https://github.com/dorny/test-reporter/pull/87)
## v1.3.1
- [Fix: parsing of .NET duration string without milliseconds](https://github.com/dorny/test-reporter/pull/84)
- [Fix: dart-json - remove group name from test case names](https://github.com/dorny/test-reporter/pull/85)

View file

@ -9,15 +9,15 @@ This [Github Action](https://github.com/features/actions) displays test results
✔️ Provides final `conclusion` and counts of `passed`, `failed` and `skipped` tests as output parameters
**How it looks:**
|![](assets/fluent-validation-report.png)|![](assets/provider-error-summary.png)|![](assets/provider-error-details.png)|![](assets/provider-groups.png)|
|![](assets/fluent-validation-report.png)|![](assets/provider-error-summary.png)|![](assets/provider-error-details.png)|![](assets/mocha-groups.png)|
|:--:|:--:|:--:|:--:|
**Supported languages / frameworks:**
- .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

@ -1,32 +1,28 @@
![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/dart-json.json</a>
**6** tests were completed in **3.760s** with **1** passed, **4** failed and **1** skipped.
## ❌ <a id="user-content-r0" href="#r0">fixtures/dart-json.json</a>
**6** tests were completed in **4s** with **1** passed, **4** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[test/main_test.dart](#r0s0)|1✔|3❌||74ms|
|[test/second_test.dart](#r0s1)||1❌|1✖|51ms|
### <a id="user-content-r0s0" href="#r0s0">test/main_test.dart</a>
**4** tests were completed in **74ms** with **1** passed, **3** failed and **0** skipped.
**Test 1**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|Passing test|36ms|
**Test 1 Test 1.1**
|Result|Test|Time|
|:---:|:---|---:|
|❌|Failing test|20ms|
|❌|Exception in target unit|6ms|
**Test 2**
|Result|Test|Time|
|:---:|:---|---:|
|❌|Exception in test|12ms|
### <a id="user-content-r0s1" href="#r0s1">test/second_test.dart</a>
**2** tests were completed in **51ms** with **0** passed, **1** failed and **1** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|❌|Timeout test|37ms|
|✖️|Skipped test|14ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">test/main_test.dart</a>
```
Test 1
✔️ Passing test
Test 1 Test 1.1
❌ Failing test
Expected: <2>
Actual: <1>
❌ Exception in target unit
Exception: Some error
Test 2
❌ Exception in test
Exception: Some error
```
### ❌ <a id="user-content-r0s1" href="#r0s1">test/second_test.dart</a>
```
❌ Timeout test
TimeoutException after 0:00:00.000001: Test timed out after 0 seconds.
✖️ Skipped test
```

View file

@ -1,18 +1,21 @@
![Tests failed](https://img.shields.io/badge/tests-3%20passed%2C%203%20failed%2C%201%20skipped-critical)
## <a id="user-content-r0" href="#r0">fixtures/dotnet-trx.trx</a>
**7** tests were completed in **1.061s** with **3** passed, **3** failed and **1** skipped.
## ❌ <a id="user-content-r0" href="#r0">fixtures/dotnet-trx.trx</a>
**7** tests were completed in **1s** with **3** passed, **3** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[DotnetTests.XUnitTests.CalculatorTests](#r0s0)|3✔|3❌|1✖|110ms|
### <a id="user-content-r0s0" href="#r0s0">DotnetTests.XUnitTests.CalculatorTests</a>
**7** tests were completed in **110ms** with **3** passed, **3** failed and **1** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|❌|Exception_In_TargetTest|0ms|
|❌|Exception_In_Test|2ms|
|❌|Failing_Test|3ms|
|✔️|Passing_Test|0ms|
|✔️|Passing_Test_With_Name|0ms|
|✖️|Skipped_Test|1ms|
|✔️|Timeout_Test|102ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">DotnetTests.XUnitTests.CalculatorTests</a>
```
❌ Exception_In_TargetTest
System.DivideByZeroException : Attempted to divide by zero.
❌ Exception_In_Test
System.Exception : Test
❌ Failing_Test
Assert.Equal() Failure
Expected: 3
Actual: 2
✔️ Passing_Test
✔️ Passing_Test_With_Name
✖️ Skipped_Test
✔️ Timeout_Test
```

File diff suppressed because it is too large Load diff

View file

@ -1,32 +1,26 @@
![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/jest-junit.xml</a>
**6** tests were completed in **1.360s** with **1** passed, **4** failed and **1** skipped.
## ❌ <a id="user-content-r0" href="#r0">fixtures/jest-junit.xml</a>
**6** tests were completed in **1s** with **1** passed, **4** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[__tests__\main.test.js](#r0s0)|1✔|3❌||486ms|
|[__tests__\second.test.js](#r0s1)||1❌|1✖|82ms|
### <a id="user-content-r0s0" href="#r0s0">__tests__\main.test.js</a>
**4** tests were completed in **486ms** with **1** passed, **3** failed and **0** skipped.
**Test 1**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|Passing test|1ms|
**Test 1 Test 1.1**
|Result|Test|Time|
|:---:|:---|---:|
|❌|Failing test|2ms|
|❌|Exception in target unit|0ms|
**Test 2**
|Result|Test|Time|
|:---:|:---|---:|
|❌|Exception in test|0ms|
### <a id="user-content-r0s1" href="#r0s1">__tests__\second.test.js</a>
**2** tests were completed in **82ms** with **0** passed, **1** failed and **1** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|❌|Timeout test|4ms|
|✖️|Skipped test|0ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">__tests__\main.test.js</a>
```
Test 1
✔️ Passing test
Test 1 Test 1.1
❌ Failing test
Error: expect(received).toBeTruthy()
❌ Exception in target unit
Error: Some error
Test 2
❌ Exception in test
Error: Some error
```
### ❌ <a id="user-content-r0s1" href="#r0s1">__tests__\second.test.js</a>
```
❌ Timeout test
: Timeout - Async callback was not invoked within the 1 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 1 ms timeout specified by jest.setTimeout.Error:
✖️ Skipped test
```

View file

@ -1,182 +1,182 @@
![Tests failed](https://img.shields.io/badge/tests-4207%20passed%2C%202%20failed%2C%2030%20skipped-critical)
## <a id="user-content-r0" href="#r0">fixtures/external/jest/jest-test-results.xml</a>
**4239** tests were completed in **165.872s** with **4207** passed, **2** failed and **30** skipped.
## ❌ <a id="user-content-r0" href="#r0">fixtures/external/jest/jest-test-results.xml</a>
**4239** tests were completed in **166s** with **4207** passed, **2** failed and **30** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|e2e/__tests__/asyncAndCallback.test.ts|1✔|||746ms|
|e2e/__tests__/asyncRegenerator.test.ts|1✔|||4.127s|
|e2e/__tests__/autoClearMocks.test.ts|2✔|||1.681s|
|e2e/__tests__/autoResetMocks.test.ts|2✔|||1.666s|
|e2e/__tests__/autoRestoreMocks.test.ts|2✔|||1.797s|
|e2e/__tests__/babelPluginJestHoist.test.ts|1✔|||6.249s|
|e2e/__tests__/asyncRegenerator.test.ts|1✔|||4s|
|e2e/__tests__/autoClearMocks.test.ts|2✔|||2s|
|e2e/__tests__/autoResetMocks.test.ts|2✔|||2s|
|e2e/__tests__/autoRestoreMocks.test.ts|2✔|||2s|
|e2e/__tests__/babelPluginJestHoist.test.ts|1✔|||6s|
|e2e/__tests__/badSourceMap.test.ts|1✔|||858ms|
|e2e/__tests__/beforeAllFiltered.ts|1✔|||958ms|
|e2e/__tests__/beforeEachQueue.ts|1✔||1✖|55ms|
|e2e/__tests__/callDoneTwice.test.ts|1✔|||882ms|
|e2e/__tests__/chaiAssertionLibrary.ts|1✔|||1.902s|
|e2e/__tests__/circularInequality.test.ts|1✔|||1.451s|
|e2e/__tests__/circusConcurrentEach.test.ts|2✔|||1.591s|
|e2e/__tests__/chaiAssertionLibrary.ts|1✔|||2s|
|e2e/__tests__/circularInequality.test.ts|1✔|||1s|
|e2e/__tests__/circusConcurrentEach.test.ts|2✔|||2s|
|e2e/__tests__/circusDeclarationErrors.test.ts|1✔|||869ms|
|e2e/__tests__/clearCache.test.ts|2✔|||1.004s|
|e2e/__tests__/cliHandlesExactFilenames.test.ts|2✔|||1.230s|
|e2e/__tests__/compareDomNodes.test.ts|1✔|||1.407s|
|e2e/__tests__/config.test.ts|6✔|||3.945s|
|e2e/__tests__/console.test.ts|7✔|||8.072s|
|e2e/__tests__/consoleAfterTeardown.test.ts|1✔|||1.341s|
|e2e/__tests__/clearCache.test.ts|2✔|||1s|
|e2e/__tests__/cliHandlesExactFilenames.test.ts|2✔|||1s|
|e2e/__tests__/compareDomNodes.test.ts|1✔|||1s|
|e2e/__tests__/config.test.ts|6✔|||4s|
|e2e/__tests__/console.test.ts|7✔|||8s|
|e2e/__tests__/consoleAfterTeardown.test.ts|1✔|||1s|
|e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts|1✔|||793ms|
|e2e/__tests__/coverageHandlebars.test.ts|1✔|||1.873s|
|e2e/__tests__/coverageRemapping.test.ts|1✔|||12.701s|
|e2e/__tests__/coverageReport.test.ts|12✔|||22.264s|
|e2e/__tests__/coverageThreshold.test.ts|5✔|||4.868s|
|e2e/__tests__/coverageTransformInstrumented.test.ts|1✔|||5.029s|
|e2e/__tests__/coverageWithoutTransform.test.ts|1✔|||1.075s|
|e2e/__tests__/coverageHandlebars.test.ts|1✔|||2s|
|e2e/__tests__/coverageRemapping.test.ts|1✔|||13s|
|e2e/__tests__/coverageReport.test.ts|12✔|||22s|
|e2e/__tests__/coverageThreshold.test.ts|5✔|||5s|
|e2e/__tests__/coverageTransformInstrumented.test.ts|1✔|||5s|
|e2e/__tests__/coverageWithoutTransform.test.ts|1✔|||1s|
|e2e/__tests__/createProcessObject.test.ts|1✔|||908ms|
|e2e/__tests__/customInlineSnapshotMatchers.test.ts|1✔|||2.206s|
|e2e/__tests__/customMatcherStackTrace.test.ts|2✔|||1.539s|
|e2e/__tests__/customReporters.test.ts|9✔|||6.553s|
|e2e/__tests__/customInlineSnapshotMatchers.test.ts|1✔|||2s|
|e2e/__tests__/customMatcherStackTrace.test.ts|2✔|||2s|
|e2e/__tests__/customReporters.test.ts|9✔|||7s|
|e2e/__tests__/customResolver.test.ts|1✔|||826ms|
|e2e/__tests__/customTestSequencers.test.ts|3✔|||2.757s|
|e2e/__tests__/customTestSequencers.test.ts|3✔|||3s|
|e2e/__tests__/debug.test.ts|1✔|||899ms|
|e2e/__tests__/declarationErrors.test.ts|3✔|||2.389s|
|e2e/__tests__/declarationErrors.test.ts|3✔|||2s|
|e2e/__tests__/dependencyClash.test.ts|1✔|||833ms|
|e2e/__tests__/detectOpenHandles.ts|8✔|||7.528s|
|e2e/__tests__/domDiffing.test.ts|1✔|||1.361s|
|e2e/__tests__/detectOpenHandles.ts|8✔|||8s|
|e2e/__tests__/domDiffing.test.ts|1✔|||1s|
|e2e/__tests__/doneInHooks.test.ts|1✔|||855ms|
|e2e/__tests__/dynamicRequireDependencies.ts|1✔|||847ms|
|e2e/__tests__/each.test.ts|7✔|||4.721s|
|e2e/__tests__/emptyDescribeWithHooks.test.ts|4✔|||2.886s|
|e2e/__tests__/each.test.ts|7✔|||5s|
|e2e/__tests__/emptyDescribeWithHooks.test.ts|4✔|||3s|
|e2e/__tests__/emptySuiteError.test.ts|1✔|||885ms|
|e2e/__tests__/env.test.ts|6✔|||5.221s|
|e2e/__tests__/env.test.ts|6✔|||5s|
|e2e/__tests__/environmentAfterTeardown.test.ts|1✔|||892ms|
|e2e/__tests__/errorOnDeprecated.test.ts|1✔||24✖|56ms|
|e2e/__tests__/esmConfigFile.test.ts|3✔|||526ms|
|e2e/__tests__/executeTestsOnceInMpr.ts|1✔|||976ms|
|e2e/__tests__/existentRoots.test.ts|4✔|||627ms|
|e2e/__tests__/expectAsyncMatcher.test.ts|2✔|||2.732s|
|e2e/__tests__/expectInVm.test.ts|1✔|||1.527s|
|e2e/__tests__/extraGlobals.test.ts|1✔|||1.011s|
|e2e/__tests__/expectAsyncMatcher.test.ts|2✔|||3s|
|e2e/__tests__/expectInVm.test.ts|1✔|||2s|
|e2e/__tests__/extraGlobals.test.ts|1✔|||1s|
|e2e/__tests__/failureDetailsProperty.test.ts|1✔|||907ms|
|e2e/__tests__/failures.test.ts|7✔|||10.353s|
|e2e/__tests__/fakePromises.test.ts|2✔|||1.716s|
|e2e/__tests__/fatalWorkerError.test.ts|1✔|||3.167s|
|e2e/__tests__/filter.test.ts|7✔|||5.422s|
|e2e/__tests__/findRelatedFiles.test.ts|5✔|||6.230s|
|e2e/__tests__/failures.test.ts|7✔|||10s|
|e2e/__tests__/fakePromises.test.ts|2✔|||2s|
|e2e/__tests__/fatalWorkerError.test.ts|1✔|||3s|
|e2e/__tests__/filter.test.ts|7✔|||5s|
|e2e/__tests__/findRelatedFiles.test.ts|5✔|||6s|
|e2e/__tests__/focusedTests.test.ts|1✔|||888ms|
|e2e/__tests__/forceExit.test.ts|1✔|||2.208s|
|e2e/__tests__/generatorMock.test.ts|1✔|||1.027s|
|e2e/__tests__/forceExit.test.ts|1✔|||2s|
|e2e/__tests__/generatorMock.test.ts|1✔|||1s|
|e2e/__tests__/global-mutation.test.ts|1✔|||40ms|
|e2e/__tests__/global.test.ts|1✔|||31ms|
|e2e/__tests__/globals.test.ts|10✔|||7.505s|
|e2e/__tests__/globalSetup.test.ts|10✔|||13.926s|
|e2e/__tests__/globalTeardown.test.ts|7✔|||11.886s|
|e2e/__tests__/globals.test.ts|10✔|||8s|
|e2e/__tests__/globalSetup.test.ts|10✔|||14s|
|e2e/__tests__/globalTeardown.test.ts|7✔|||12s|
|e2e/__tests__/hasteMapMockChanged.test.ts|1✔|||379ms|
|e2e/__tests__/hasteMapSha1.test.ts|1✔|||298ms|
|e2e/__tests__/hasteMapSize.test.ts|2✔|||397ms|
|e2e/__tests__/importedGlobals.test.ts|1✔|||1.043s|
|e2e/__tests__/injectGlobals.test.ts|2✔|||1.860s|
|e2e/__tests__/jasmineAsync.test.ts|15✔|||28.291s|
|e2e/__tests__/importedGlobals.test.ts|1✔|||1s|
|e2e/__tests__/injectGlobals.test.ts|2✔|||2s|
|e2e/__tests__/jasmineAsync.test.ts|15✔|||28s|
|e2e/__tests__/jasmineAsyncWithPendingDuringTest.ts|1✔||1✖|72ms|
|e2e/__tests__/jest.config.js.test.ts|3✔|||2.134s|
|e2e/__tests__/jest.config.ts.test.ts|5✔|||14.322s|
|[e2e/__tests__/jestChangedFiles.test.ts](#r0s75)|9✔|1❌||9.045s|
|e2e/__tests__/jestEnvironmentJsdom.test.ts|1✔|||1.744s|
|e2e/__tests__/jestRequireActual.test.ts|1✔|||1.665s|
|e2e/__tests__/jestRequireMock.test.ts|1✔|||2.119s|
|e2e/__tests__/jest.config.js.test.ts|3✔|||2s|
|e2e/__tests__/jest.config.ts.test.ts|5✔|||14s|
|[e2e/__tests__/jestChangedFiles.test.ts](#r0s75)|9✔|1❌||9s|
|e2e/__tests__/jestEnvironmentJsdom.test.ts|1✔|||2s|
|e2e/__tests__/jestRequireActual.test.ts|1✔|||2s|
|e2e/__tests__/jestRequireMock.test.ts|1✔|||2s|
|e2e/__tests__/json.test.ts|2✔|||29ms|
|e2e/__tests__/jsonReporter.test.ts|2✔|||1.514s|
|e2e/__tests__/jsonReporter.test.ts|2✔|||2s|
|e2e/__tests__/lifecycles.ts|1✔|||861ms|
|e2e/__tests__/listTests.test.ts|2✔|||945ms|
|e2e/__tests__/locationInResults.test.ts|2✔|||1.764s|
|e2e/__tests__/locationInResults.test.ts|2✔|||2s|
|e2e/__tests__/logHeapUsage.test.ts|1✔|||884ms|
|e2e/__tests__/mockNames.test.ts|8✔|||6.771s|
|e2e/__tests__/modernFakeTimers.test.ts|2✔|||1.680s|
|e2e/__tests__/moduleNameMapper.test.ts|5✔|||5.395s|
|e2e/__tests__/mockNames.test.ts|8✔|||7s|
|e2e/__tests__/modernFakeTimers.test.ts|2✔|||2s|
|e2e/__tests__/moduleNameMapper.test.ts|5✔|||5s|
|e2e/__tests__/moduleParentNullInTest.ts|1✔|||886ms|
|e2e/__tests__/multiProjectRunner.test.ts|14✔|||16.360s|
|e2e/__tests__/multiProjectRunner.test.ts|14✔|||16s|
|e2e/__tests__/nativeAsyncMock.test.ts|1✔|||55ms|
|e2e/__tests__/nativeEsm.test.ts|2✔||1✖|905ms|
|e2e/__tests__/nativeEsmTypescript.test.ts|1✔|||956ms|
|e2e/__tests__/nestedEventLoop.test.ts|1✔|||1.422s|
|e2e/__tests__/nestedTestDefinitions.test.ts|4✔|||4.641s|
|e2e/__tests__/nestedEventLoop.test.ts|1✔|||1s|
|e2e/__tests__/nestedTestDefinitions.test.ts|4✔|||5s|
|e2e/__tests__/nodePath.test.ts|1✔|||866ms|
|e2e/__tests__/noTestFound.test.ts|2✔|||1.063s|
|e2e/__tests__/noTestsFound.test.ts|5✔|||2.739s|
|[e2e/__tests__/onlyChanged.test.ts](#r0s98)|8✔|1❌||22.281s|
|e2e/__tests__/onlyFailuresNonWatch.test.ts|1✔|||2.893s|
|e2e/__tests__/overrideGlobals.test.ts|2✔|||2.046s|
|e2e/__tests__/pnp.test.ts|1✔|||2.715s|
|e2e/__tests__/presets.test.ts|2✔|||1.966s|
|e2e/__tests__/processExit.test.ts|1✔|||1.070s|
|e2e/__tests__/noTestFound.test.ts|2✔|||1s|
|e2e/__tests__/noTestsFound.test.ts|5✔|||3s|
|[e2e/__tests__/onlyChanged.test.ts](#r0s98)|8✔|1❌||22s|
|e2e/__tests__/onlyFailuresNonWatch.test.ts|1✔|||3s|
|e2e/__tests__/overrideGlobals.test.ts|2✔|||2s|
|e2e/__tests__/pnp.test.ts|1✔|||3s|
|e2e/__tests__/presets.test.ts|2✔|||2s|
|e2e/__tests__/processExit.test.ts|1✔|||1s|
|e2e/__tests__/promiseReject.test.ts|1✔|||967ms|
|e2e/__tests__/regexCharInPath.test.ts|1✔|||962ms|
|e2e/__tests__/requireAfterTeardown.test.ts|1✔|||921ms|
|e2e/__tests__/requireMain.test.ts|1✔|||1.137s|
|e2e/__tests__/requireMain.test.ts|1✔|||1s|
|e2e/__tests__/requireMainAfterCreateRequire.test.ts|1✔|||966ms|
|e2e/__tests__/requireMainIsolateModules.test.ts|1✔|||976ms|
|e2e/__tests__/requireMainResetModules.test.ts|2✔|||1.961s|
|e2e/__tests__/requireMainResetModules.test.ts|2✔|||2s|
|e2e/__tests__/requireV8Module.test.ts|1✔|||30ms|
|e2e/__tests__/resetModules.test.ts|1✔|||926ms|
|e2e/__tests__/resolve.test.ts|1✔|||1.863s|
|e2e/__tests__/resolveGetPaths.test.ts|1✔|||1.155s|
|e2e/__tests__/resolve.test.ts|1✔|||2s|
|e2e/__tests__/resolveGetPaths.test.ts|1✔|||1s|
|e2e/__tests__/resolveNodeModule.test.ts|1✔|||943ms|
|e2e/__tests__/resolveNoFileExtensions.test.ts|2✔|||1.263s|
|e2e/__tests__/resolveWithPaths.test.ts|1✔|||1.170s|
|e2e/__tests__/resolveNoFileExtensions.test.ts|2✔|||1s|
|e2e/__tests__/resolveWithPaths.test.ts|1✔|||1s|
|e2e/__tests__/runProgrammatically.test.ts|2✔|||575ms|
|e2e/__tests__/runTestsByPath.test.ts|1✔|||1.999s|
|e2e/__tests__/runtimeInternalModuleRegistry.test.ts|1✔|||1.202s|
|e2e/__tests__/selectProjects.test.ts|18✔|||5.236s|
|e2e/__tests__/runTestsByPath.test.ts|1✔|||2s|
|e2e/__tests__/runtimeInternalModuleRegistry.test.ts|1✔|||1s|
|e2e/__tests__/selectProjects.test.ts|18✔|||5s|
|e2e/__tests__/setImmediate.test.ts|1✔|||904ms|
|e2e/__tests__/setupFilesAfterEnvConfig.test.ts|2✔|||1.967s|
|e2e/__tests__/setupFilesAfterEnvConfig.test.ts|2✔|||2s|
|e2e/__tests__/showConfig.test.ts|1✔|||195ms|
|e2e/__tests__/skipBeforeAfterAll.test.ts|1✔|||1.061s|
|e2e/__tests__/skipBeforeAfterAll.test.ts|1✔|||1s|
|e2e/__tests__/snapshot-unknown.test.ts|1✔|||838ms|
|e2e/__tests__/snapshot.test.ts|9✔|||13.899s|
|e2e/__tests__/snapshot.test.ts|9✔|||14s|
|e2e/__tests__/snapshotMockFs.test.ts|1✔|||883ms|
|e2e/__tests__/snapshotResolver.test.ts|1✔|||823ms|
|e2e/__tests__/snapshotSerializers.test.ts|2✔|||2.065s|
|e2e/__tests__/stackTrace.test.ts|7✔|||4.725s|
|e2e/__tests__/snapshotSerializers.test.ts|2✔|||2s|
|e2e/__tests__/stackTrace.test.ts|7✔|||5s|
|e2e/__tests__/stackTraceNoCaptureStackTrace.test.ts|1✔|||899ms|
|e2e/__tests__/stackTraceSourceMaps.test.ts|1✔|||2.185s|
|e2e/__tests__/stackTraceSourceMapsWithCoverage.test.ts|1✔|||2.444s|
|e2e/__tests__/stackTraceSourceMaps.test.ts|1✔|||2s|
|e2e/__tests__/stackTraceSourceMapsWithCoverage.test.ts|1✔|||2s|
|e2e/__tests__/supportsDashedArgs.ts|2✔|||968ms|
|e2e/__tests__/symbol.test.ts|1✔|||49ms|
|e2e/__tests__/testEnvironment.test.ts|1✔|||1.628s|
|e2e/__tests__/testEnvironmentAsync.test.ts|1✔|||1.493s|
|e2e/__tests__/testEnvironmentCircus.test.ts|1✔|||1.501s|
|e2e/__tests__/testEnvironmentCircusAsync.test.ts|1✔|||1.507s|
|e2e/__tests__/testFailureExitCode.test.ts|2✔|||4.476s|
|e2e/__tests__/testInRoot.test.ts|1✔|||1.009s|
|e2e/__tests__/testEnvironment.test.ts|1✔|||2s|
|e2e/__tests__/testEnvironmentAsync.test.ts|1✔|||1s|
|e2e/__tests__/testEnvironmentCircus.test.ts|1✔|||2s|
|e2e/__tests__/testEnvironmentCircusAsync.test.ts|1✔|||2s|
|e2e/__tests__/testFailureExitCode.test.ts|2✔|||4s|
|e2e/__tests__/testInRoot.test.ts|1✔|||1s|
|e2e/__tests__/testNamePattern.test.ts|1✔|||859ms|
|e2e/__tests__/testNamePatternSkipped.test.ts|1✔|||991ms|
|e2e/__tests__/testPathPatternReporterMessage.test.ts|1✔|||3.076s|
|e2e/__tests__/testPathPatternReporterMessage.test.ts|1✔|||3s|
|e2e/__tests__/testResultsProcessor.test.ts|1✔|||910ms|
|e2e/__tests__/testRetries.test.ts|4✔|||3.277s|
|e2e/__tests__/testTodo.test.ts|5✔|||3.573s|
|e2e/__tests__/timeouts.test.ts|4✔|||4.029s|
|e2e/__tests__/testRetries.test.ts|4✔|||3s|
|e2e/__tests__/testTodo.test.ts|5✔|||4s|
|e2e/__tests__/timeouts.test.ts|4✔|||4s|
|e2e/__tests__/timeoutsLegacy.test.ts|1✔||3✖|71ms|
|e2e/__tests__/timerResetMocks.test.ts|2✔|||1.878s|
|e2e/__tests__/timerUseRealTimers.test.ts|1✔|||1.018s|
|e2e/__tests__/toMatchInlineSnapshot.test.ts|12✔|||23.917s|
|e2e/__tests__/toMatchInlineSnapshotWithRetries.test.ts|3✔|||4.670s|
|e2e/__tests__/toMatchSnapshot.test.ts|9✔|||17.025s|
|e2e/__tests__/toMatchSnapshotWithRetries.test.ts|2✔|||4.435s|
|e2e/__tests__/toMatchSnapshotWithStringSerializer.test.ts|3✔|||3.544s|
|e2e/__tests__/toThrowErrorMatchingInlineSnapshot.test.ts|4✔|||3.562s|
|e2e/__tests__/toThrowErrorMatchingSnapshot.test.ts|5✔|||3.524s|
|e2e/__tests__/transform.test.ts|16✔|||26.740s|
|e2e/__tests__/timerResetMocks.test.ts|2✔|||2s|
|e2e/__tests__/timerUseRealTimers.test.ts|1✔|||1s|
|e2e/__tests__/toMatchInlineSnapshot.test.ts|12✔|||24s|
|e2e/__tests__/toMatchInlineSnapshotWithRetries.test.ts|3✔|||5s|
|e2e/__tests__/toMatchSnapshot.test.ts|9✔|||17s|
|e2e/__tests__/toMatchSnapshotWithRetries.test.ts|2✔|||4s|
|e2e/__tests__/toMatchSnapshotWithStringSerializer.test.ts|3✔|||4s|
|e2e/__tests__/toThrowErrorMatchingInlineSnapshot.test.ts|4✔|||4s|
|e2e/__tests__/toThrowErrorMatchingSnapshot.test.ts|5✔|||4s|
|e2e/__tests__/transform.test.ts|16✔|||27s|
|e2e/__tests__/transformLinkedModules.test.ts|1✔|||783ms|
|e2e/__tests__/typescriptCoverage.test.ts|1✔|||2.893s|
|e2e/__tests__/unexpectedToken.test.ts|3✔|||3.411s|
|e2e/__tests__/useStderr.test.ts|1✔|||1.352s|
|e2e/__tests__/v8Coverage.test.ts|2✔|||2.412s|
|e2e/__tests__/typescriptCoverage.test.ts|1✔|||3s|
|e2e/__tests__/unexpectedToken.test.ts|3✔|||3s|
|e2e/__tests__/useStderr.test.ts|1✔|||1s|
|e2e/__tests__/v8Coverage.test.ts|2✔|||2s|
|e2e/__tests__/verbose.test.ts|1✔|||683ms|
|e2e/__tests__/version.test.ts|1✔|||138ms|
|e2e/__tests__/watchModeNoAccess.test.ts|1✔|||4.370s|
|e2e/__tests__/watchModeOnlyFailed.test.ts|1✔|||1.394s|
|e2e/__tests__/watchModePatterns.test.ts|2✔|||3.503s|
|e2e/__tests__/watchModeUpdateSnapshot.test.ts|1✔|||1.075s|
|e2e/__tests__/workerForceExit.test.ts|2✔|||4.751s|
|e2e/__tests__/wrongEnv.test.ts|5✔|||3.877s|
|e2e/__tests__/watchModeNoAccess.test.ts|1✔|||4s|
|e2e/__tests__/watchModeOnlyFailed.test.ts|1✔|||1s|
|e2e/__tests__/watchModePatterns.test.ts|2✔|||4s|
|e2e/__tests__/watchModeUpdateSnapshot.test.ts|1✔|||1s|
|e2e/__tests__/workerForceExit.test.ts|2✔|||5s|
|e2e/__tests__/wrongEnv.test.ts|5✔|||4s|
|e2e/custom-test-sequencer/a.test.js|1✔|||29ms|
|e2e/custom-test-sequencer/b.test.js|1✔|||21ms|
|e2e/custom-test-sequencer/c.test.js|1✔|||42ms|
@ -206,7 +206,7 @@
|examples/module-mock/__tests__/mock_per_test.js|2✔|||116ms|
|examples/module-mock/__tests__/partial_mock.js|1✔|||215ms|
|examples/mongodb/__test__/db.test.js|1✔|||236ms|
|examples/react-native/__tests__/intro.test.js|4✔|||8.559s|
|examples/react-native/__tests__/intro.test.js|4✔|||9s|
|examples/react-testing-library/__tests__/CheckboxWithLabel-test.js|1✔|||469ms|
|examples/react/__tests__/CheckboxWithLabel-test.js|1✔|||256ms|
|examples/snapshot/__tests__/clock.react.test.js|1✔|||62ms|
@ -228,7 +228,7 @@
|packages/expect/src/__tests__/isError.test.ts|4✔|||43ms|
|packages/expect/src/__tests__/matchers-toContain.property.test.ts|2✔|||236ms|
|packages/expect/src/__tests__/matchers-toContainEqual.property.test.ts|2✔|||287ms|
|packages/expect/src/__tests__/matchers-toEqual.property.test.ts|2✔|||1.062s|
|packages/expect/src/__tests__/matchers-toEqual.property.test.ts|2✔|||1s|
|packages/expect/src/__tests__/matchers-toStrictEqual.property.test.ts|3✔|||394ms|
|packages/expect/src/__tests__/matchers.test.js|592✔|||862ms|
|packages/expect/src/__tests__/spyMatchers.test.ts|248✔|||395ms|
@ -237,11 +237,11 @@
|packages/expect/src/__tests__/toEqual-dom.test.ts|12✔|||99ms|
|packages/expect/src/__tests__/toThrowMatchers.test.ts|98✔|||257ms|
|packages/expect/src/__tests__/utils.test.ts|41✔|||147ms|
|packages/jest-circus/src/__tests__/afterAll.test.ts|6✔|||5.755s|
|packages/jest-circus/src/__tests__/baseTest.test.ts|2✔|||2.902s|
|packages/jest-circus/src/__tests__/afterAll.test.ts|6✔|||6s|
|packages/jest-circus/src/__tests__/baseTest.test.ts|2✔|||3s|
|packages/jest-circus/src/__tests__/circusItTestError.test.ts|8✔|||300ms|
|packages/jest-circus/src/__tests__/circusItTodoTestError.test.ts|3✔|||81ms|
|packages/jest-circus/src/__tests__/hooks.test.ts|3✔|||3.762s|
|packages/jest-circus/src/__tests__/hooks.test.ts|3✔|||4s|
|packages/jest-circus/src/__tests__/hooksError.test.ts|32✔|||127ms|
|packages/jest-cli/src/__tests__/cli/args.test.ts|17✔|||345ms|
|packages/jest-cli/src/init/__tests__/init.test.js|24✔|||119ms|
@ -261,12 +261,12 @@
|packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.js|5✔|||61ms|
|packages/jest-core/src/__tests__/globals.test.ts|1✔|||22ms|
|packages/jest-core/src/__tests__/runJest.test.js|2✔|||261ms|
|packages/jest-core/src/__tests__/SearchSource.test.ts|27✔|||2.596s|
|packages/jest-core/src/__tests__/SearchSource.test.ts|27✔|||3s|
|packages/jest-core/src/__tests__/SnapshotInteractiveMode.test.js|13✔|||89ms|
|packages/jest-core/src/__tests__/TestScheduler.test.js|8✔|||520ms|
|packages/jest-core/src/__tests__/testSchedulerHelper.test.js|12✔|||48ms|
|packages/jest-core/src/__tests__/watch.test.js|80✔|||6.755s|
|packages/jest-core/src/__tests__/watchFileChanges.test.ts|1✔|||1.514s|
|packages/jest-core/src/__tests__/watch.test.js|80✔|||7s|
|packages/jest-core/src/__tests__/watchFileChanges.test.ts|1✔|||2s|
|packages/jest-core/src/__tests__/watchFilenamePatternMode.test.js|2✔|||165ms|
|packages/jest-core/src/__tests__/watchTestNamePatternMode.test.js|1✔|||246ms|
|packages/jest-core/src/lib/__tests__/isValidPath.test.ts|3✔|||166ms|
@ -289,7 +289,7 @@
|packages/jest-globals/src/__tests__/index.ts|1✔|||533ms|
|packages/jest-haste-map/src/__tests__/get_mock_name.test.js|1✔|||22ms|
|packages/jest-haste-map/src/__tests__/includes_dotfiles.test.ts|1✔|||337ms|
|packages/jest-haste-map/src/__tests__/index.test.js|44✔|||1.145s|
|packages/jest-haste-map/src/__tests__/index.test.js|44✔|||1s|
|packages/jest-haste-map/src/__tests__/worker.test.js|7✔|||100ms|
|packages/jest-haste-map/src/crawlers/__tests__/node.test.js|10✔|||170ms|
|packages/jest-haste-map/src/crawlers/__tests__/watchman.test.js|8✔|||153ms|
@ -318,12 +318,12 @@
|packages/jest-message-util/src/__tests__/messages.test.ts|11✔|||205ms|
|packages/jest-mock/src/__tests__/index.test.ts|84✔|||509ms|
|packages/jest-regex-util/src/__tests__/index.test.ts|8✔|||56ms|
|packages/jest-repl/src/__tests__/jest_repl.test.js|1✔|||1.172s|
|packages/jest-repl/src/__tests__/runtime_cli.test.js|4✔|||4.094s|
|packages/jest-repl/src/__tests__/jest_repl.test.js|1✔|||1s|
|packages/jest-repl/src/__tests__/runtime_cli.test.js|4✔|||4s|
|packages/jest-reporters/src/__tests__/CoverageReporter.test.js|12✔|||397ms|
|packages/jest-reporters/src/__tests__/CoverageWorker.test.js|2✔|||199ms|
|packages/jest-reporters/src/__tests__/DefaultReporter.test.js|2✔|||148ms|
|packages/jest-reporters/src/__tests__/generateEmptyCoverage.test.js|3✔|||1.129s|
|packages/jest-reporters/src/__tests__/generateEmptyCoverage.test.js|3✔|||1s|
|packages/jest-reporters/src/__tests__/getResultHeader.test.js|4✔|||30ms|
|packages/jest-reporters/src/__tests__/getSnapshotStatus.test.js|3✔|||28ms|
|packages/jest-reporters/src/__tests__/getSnapshotSummary.test.js|4✔|||49ms|
@ -334,7 +334,7 @@
|packages/jest-reporters/src/__tests__/VerboseReporter.test.js|11✔|||425ms|
|packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts|11✔|||666ms|
|packages/jest-resolve/src/__tests__/isBuiltinModule.test.ts|4✔|||36ms|
|packages/jest-resolve/src/__tests__/resolve.test.ts|16✔|||1.308s|
|packages/jest-resolve/src/__tests__/resolve.test.ts|16✔|||1s|
|packages/jest-runner/src/__tests__/testRunner.test.ts|2✔|||905ms|
|packages/jest-runtime/src/__tests__/instrumentation.test.ts|1✔|||275ms|
|packages/jest-runtime/src/__tests__/runtime_create_mock_from_module.test.js|3✔|||606ms|
@ -344,31 +344,31 @@
|packages/jest-runtime/src/__tests__/runtime_jest_spy_on.test.js|2✔|||521ms|
|packages/jest-runtime/src/__tests__/runtime_mock.test.js|4✔|||743ms|
|packages/jest-runtime/src/__tests__/runtime_module_directories.test.js|4✔|||525ms|
|packages/jest-runtime/src/__tests__/runtime_node_path.test.js|4✔|||1.088s|
|packages/jest-runtime/src/__tests__/runtime_node_path.test.js|4✔|||1s|
|packages/jest-runtime/src/__tests__/runtime_require_actual.test.js|2✔|||478ms|
|packages/jest-runtime/src/__tests__/runtime_require_cache.test.js|2✔|||454ms|
|packages/jest-runtime/src/__tests__/runtime_require_mock.test.js|13✔|||962ms|
|packages/jest-runtime/src/__tests__/runtime_require_module_no_ext.test.js|1✔|||261ms|
|packages/jest-runtime/src/__tests__/runtime_require_module_or_mock_transitive_deps.test.js|6✔|||2.366s|
|packages/jest-runtime/src/__tests__/runtime_require_module_or_mock.test.js|17✔|||1.223s|
|packages/jest-runtime/src/__tests__/runtime_require_module.test.js|27✔|||2.439s|
|packages/jest-runtime/src/__tests__/runtime_require_module_or_mock_transitive_deps.test.js|6✔|||2s|
|packages/jest-runtime/src/__tests__/runtime_require_module_or_mock.test.js|17✔|||1s|
|packages/jest-runtime/src/__tests__/runtime_require_module.test.js|27✔|||2s|
|packages/jest-runtime/src/__tests__/runtime_require_resolve.test.ts|5✔|||707ms|
|packages/jest-runtime/src/__tests__/runtime_wrap.js|2✔|||263ms|
|packages/jest-runtime/src/__tests__/Runtime-sourceMaps.test.js|1✔|||584ms|
|packages/jest-runtime/src/__tests__/Runtime-statics.test.js|2✔|||162ms|
|packages/jest-serializer/src/__tests__/index.test.ts|17✔|||158ms|
|packages/jest-snapshot/src/__tests__/dedentLines.test.ts|17✔|||94ms|
|packages/jest-snapshot/src/__tests__/InlineSnapshots.test.ts|22✔|||1.149s|
|packages/jest-snapshot/src/__tests__/InlineSnapshots.test.ts|22✔|||1s|
|packages/jest-snapshot/src/__tests__/matcher.test.ts|1✔|||131ms|
|packages/jest-snapshot/src/__tests__/mockSerializer.test.ts|10✔|||45ms|
|packages/jest-snapshot/src/__tests__/printSnapshot.test.ts|71✔|||1.188s|
|packages/jest-snapshot/src/__tests__/printSnapshot.test.ts|71✔|||1s|
|packages/jest-snapshot/src/__tests__/SnapshotResolver.test.ts|10✔|||98ms|
|packages/jest-snapshot/src/__tests__/throwMatcher.test.ts|3✔|||481ms|
|packages/jest-snapshot/src/__tests__/utils.test.ts|26✔|||214ms|
|packages/jest-source-map/src/__tests__/getCallsite.test.ts|3✔|||86ms|
|packages/jest-test-result/src/__tests__/formatTestResults.test.ts|1✔|||53ms|
|packages/jest-test-sequencer/src/__tests__/test_sequencer.test.js|8✔|||251ms|
|packages/jest-transform/src/__tests__/ScriptTransformer.test.ts|22✔|||1.660s|
|packages/jest-transform/src/__tests__/ScriptTransformer.test.ts|22✔|||2s|
|packages/jest-transform/src/__tests__/shouldInstrument.test.ts|25✔|||155ms|
|packages/jest-util/src/__tests__/createProcessObject.test.ts|4✔|||81ms|
|packages/jest-util/src/__tests__/deepCyclicCopy.test.ts|12✔|||86ms|
@ -403,32 +403,30 @@
|packages/pretty-format/src/__tests__/prettyFormat.test.ts|86✔|||219ms|
|packages/pretty-format/src/__tests__/react.test.tsx|55✔|||325ms|
|packages/pretty-format/src/__tests__/ReactElement.test.ts|3✔|||64ms|
### <a id="user-content-r0s75" href="#r0s75">e2e/__tests__/jestChangedFiles.test.ts</a>
**10** tests were completed in **9.045s** with **9** passed, **1** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|gets hg SCM roots and dedupes them|559ms|
|✔️|gets git SCM roots and dedupes them|416ms|
|✔️|gets mixed git and hg SCM roots and dedupes them|467ms|
|✔️|gets changed files for git|2.298s|
|✔️|monitors only root paths for git|151ms|
|✔️|does not find changes in files with no diff, for git|628ms|
|✔️|handles a bad revision for "changedSince", for git|878ms|
|❌|gets changed files for hg|2.219s|
|✔️|monitors only root paths for hg|281ms|
|✔️|handles a bad revision for "changedSince", for hg|949ms|
### <a id="user-content-r0s98" href="#r0s98">e2e/__tests__/onlyChanged.test.ts</a>
**9** tests were completed in **22.281s** with **8** passed, **1** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|run for "onlyChanged" and "changedSince"|1.464s|
|✔️|run only changed files|5.196s|
|✔️|report test coverage for only changed files|1.889s|
|✔️|report test coverage of source on test file change under only changed files|822ms|
|✔️|do not pickup non-tested files when reporting coverage on only changed files|861ms|
|✔️|collect test coverage when using onlyChanged|1.058s|
|✔️|onlyChanged in config is overwritten by --all or testPathPattern|7.023s|
|❌|gets changed files for hg|3.765s|
|✔️|path on Windows is case-insensitive|0ms|
### ❌ <a id="user-content-r0s75" href="#r0s75">e2e/__tests__/jestChangedFiles.test.ts</a>
```
✔️ gets hg SCM roots and dedupes them
✔️ gets git SCM roots and dedupes them
✔️ gets mixed git and hg SCM roots and dedupes them
✔️ gets changed files for git
✔️ monitors only root paths for git
✔️ does not find changes in files with no diff, for git
✔️ handles a bad revision for "changedSince", for git
❌ gets changed files for hg
Error: abort: empty revision range
✔️ monitors only root paths for hg
✔️ handles a bad revision for "changedSince", for hg
```
### ❌ <a id="user-content-r0s98" href="#r0s98">e2e/__tests__/onlyChanged.test.ts</a>
```
✔️ run for "onlyChanged" and "changedSince"
✔️ run only changed files
✔️ report test coverage for only changed files
✔️ report test coverage of source on test file change under only changed files
✔️ do not pickup non-tested files when reporting coverage on only changed files
✔️ collect test coverage when using onlyChanged
✔️ onlyChanged in config is overwritten by --all or testPathPattern
❌ gets changed files for hg
Error: expect(received).toMatch(expected)
✔️ path on Windows is case-insensitive
```

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|

View file

@ -1,5 +1,5 @@
![Tests failed](https://img.shields.io/badge/tests-268%20passed%2C%201%20failed-critical)
## <a id="user-content-r0" href="#r0">fixtures/external/flutter/provider-test-results.json</a>
## ❌ <a id="user-content-r0" href="#r0">fixtures/external/flutter/provider-test-results.json</a>
**269** tests were completed in **0ms** with **268** passed, **1** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
@ -8,7 +8,7 @@
|[test/consumer_test.dart](#r0s2)|18✔|||340ms|
|[test/context_test.dart](#r0s3)|31✔|||698ms|
|[test/future_provider_test.dart](#r0s4)|10✔|||305ms|
|[test/inherited_provider_test.dart](#r0s5)|81✔|||1.117s|
|[test/inherited_provider_test.dart](#r0s5)|81✔|||1s|
|[test/listenable_provider_test.dart](#r0s6)|16✔|||353ms|
|[test/listenable_proxy_provider_test.dart](#r0s7)|12✔|||373ms|
|[test/multi_provider_test.dart](#r0s8)|3✔|||198ms|
@ -19,455 +19,356 @@
|[test/stateful_provider_test.dart](#r0s13)|4✔|||254ms|
|[test/stream_provider_test.dart](#r0s14)|8✔|||282ms|
|[test/value_listenable_provider_test.dart](#r0s15)|4✔|1❌||327ms|
### <a id="user-content-r0s0" href="#r0s0">test/builder_test.dart</a> ✔️
**24** tests were completed in **402ms** with **24** passed, **0** failed and **0** skipped.
**ChangeNotifierProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|default|189ms|
|✔️|.value|10ms|
**ListenableProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|default|9ms|
|✔️|.value|16ms|
**Provider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|default|11ms|
|✔️|.value|8ms|
**ProxyProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|0|11ms|
|✔️|1|10ms|
|✔️|2|8ms|
|✔️|3|10ms|
|✔️|4|9ms|
|✔️|5|9ms|
|✔️|6|9ms|
**MultiProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|with 1 ChangeNotifierProvider default|9ms|
|✔️|with 2 ChangeNotifierProvider default|9ms|
|✔️|with ListenableProvider default|12ms|
|✔️|with Provider default|8ms|
|✔️|with ProxyProvider0|7ms|
|✔️|with ProxyProvider1|9ms|
|✔️|with ProxyProvider2|7ms|
|✔️|with ProxyProvider3|9ms|
|✔️|with ProxyProvider4|9ms|
|✔️|with ProxyProvider5|7ms|
|✔️|with ProxyProvider6|7ms|
### <a id="user-content-r0s1" href="#r0s1">test/change_notifier_provider_test.dart</a> ✔️
**10** tests were completed in **306ms** with **10** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|Use builder property, not child|10ms|
**ChangeNotifierProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|value|185ms|
|✔️|builder|18ms|
|✔️|builder1|12ms|
|✔️|builder2|12ms|
|✔️|builder3|19ms|
|✔️|builder4|14ms|
|✔️|builder5|15ms|
|✔️|builder6|11ms|
|✔️|builder0|10ms|
### <a id="user-content-r0s2" href="#r0s2">test/consumer_test.dart</a> ✔️
**18** tests were completed in **340ms** with **18** passed, **0** failed and **0** skipped.
**consumer**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|obtains value from Provider<T>|181ms|
|✔️|crashed with no builder|11ms|
|✔️|can be used inside MultiProvider|16ms|
**consumer2**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|obtains value from Provider<T>|22ms|
|✔️|crashed with no builder|8ms|
|✔️|can be used inside MultiProvider|9ms|
**consumer3**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|obtains value from Provider<T>|9ms|
|✔️|crashed with no builder|7ms|
|✔️|can be used inside MultiProvider|8ms|
**consumer4**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|obtains value from Provider<T>|8ms|
|✔️|crashed with no builder|6ms|
|✔️|can be used inside MultiProvider|8ms|
**consumer5**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|obtains value from Provider<T>|8ms|
|✔️|crashed with no builder|6ms|
|✔️|can be used inside MultiProvider|9ms|
**consumer6**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|obtains value from Provider<T>|8ms|
|✔️|crashed with no builder|8ms|
|✔️|can be used inside MultiProvider|8ms|
### <a id="user-content-r0s3" href="#r0s3">test/context_test.dart</a> ✔️
**31** tests were completed in **698ms** with **31** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|watch in layoutbuilder|179ms|
|✔️|select in layoutbuilder|12ms|
|✔️|cannot select in listView|138ms|
|✔️|watch in listView|33ms|
|✔️|watch in gridView|21ms|
|✔️|clears select dependencies for all dependents|19ms|
**BuildContext**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|internal selected value is updated|32ms|
|✔️|create can use read without being lazy|11ms|
|✔️|watch can be used inside InheritedProvider.update|10ms|
|✔️|select doesn't fail if it loads a provider that depends on other providers|9ms|
|✔️|don't call old selectors if the child rebuilds individually|21ms|
|✔️|selects throws inside click handlers|40ms|
|✔️|select throws if try to read dynamic|9ms|
|✔️|select throws ProviderNotFoundException|9ms|
|✔️|select throws if watch called inside the callback from build|6ms|
|✔️|select throws if read called inside the callback from build|9ms|
|✔️|select throws if select called inside the callback from build|8ms|
|✔️|select throws if read called inside the callback on dependency change|10ms|
|✔️|select throws if watch called inside the callback on dependency change|17ms|
|✔️|select throws if select called inside the callback on dependency change|9ms|
|✔️|can call read inside didChangeDependencies|9ms|
|✔️|select cannot be called inside didChangeDependencies|6ms|
|✔️|select in initState throws|6ms|
|✔️|watch in initState throws|10ms|
|✔️|read in initState works|6ms|
|✔️|consumer can be removed and selector stops to be called|7ms|
|✔️|context.select deeply compares maps|15ms|
|✔️|context.select deeply compares lists|8ms|
|✔️|context.select deeply compares iterables|8ms|
|✔️|context.select deeply compares sets|11ms|
|✔️|context.watch listens to value changes|10ms|
### <a id="user-content-r0s4" href="#r0s4">test/future_provider_test.dart</a> ✔️
**10** tests were completed in **305ms** with **10** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|works with MultiProvider|184ms|
|✔️|(catchError) previous future completes after transition is no-op|16ms|
|✔️|previous future completes after transition is no-op|15ms|
|✔️|transition from future to future preserve state|12ms|
|✔️|throws if future has error and catchError is missing|24ms|
|✔️|calls catchError if present and future has error|21ms|
|✔️|works with null|14ms|
|✔️|create and dispose future with builder|12ms|
|✔️|FutureProvider() crashes if builder is null|4ms|
**FutureProvider()**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|crashes if builder is null|3ms|
### <a id="user-content-r0s5" href="#r0s5">test/inherited_provider_test.dart</a> ✔️
**81** tests were completed in **1.117s** with **81** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|regression test #377|167ms|
|✔️|rebuild on dependency flags update|15ms|
|✔️|properly update debug flags if a create triggers another deferred create|9ms|
|✔️|properly update debug flags if a create triggers another deferred create|8ms|
|✔️|properly update debug flags if an update triggers another create/update|7ms|
|✔️|properly update debug flags if a create triggers another create/update|8ms|
|✔️|Provider.of(listen: false) outside of build works when it loads a provider|22ms|
|✔️|new value is available in didChangeDependencies|26ms|
|✔️|builder receives the current value and updates independently from `update`|16ms|
|✔️|builder can _not_ rebuild when provider updates|8ms|
|✔️|builder rebuilds if provider is recreated|9ms|
|✔️|provider.of throws if listen:true outside of the widget tree|23ms|
|✔️|InheritedProvider throws if no child is provided with default constructor|14ms|
|✔️|InheritedProvider throws if no child is provided with value constructor|8ms|
|✔️|DeferredInheritedProvider throws if no child is provided with default constructor|15ms|
|✔️|DeferredInheritedProvider throws if no child is provided with value constructor|7ms|
|✔️|startListening markNeedsNotifyDependents|7ms|
|✔️|InheritedProvider can be subclassed|8ms|
|✔️|DeferredInheritedProvider can be subclassed|7ms|
|✔️|can be used with MultiProvider|8ms|
|✔️|throw if the widget ctor changes|8ms|
|✔️|InheritedProvider lazy loading can be disabled|6ms|
|✔️|InheritedProvider.value lazy loading can be disabled|9ms|
|✔️|InheritedProvider subclass don't have to specify default lazy value|7ms|
|✔️|DeferredInheritedProvider lazy loading can be disabled|7ms|
|✔️|DeferredInheritedProvider.value lazy loading can be disabled|7ms|
|✔️|selector|14ms|
|✔️|can select multiple types from same provider|9ms|
|✔️|can select same type on two different providers|8ms|
|✔️|can select same type twice on same provider|10ms|
|✔️|Provider.of has a proper error message if context is null|6ms|
**diagnostics**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|InheritedProvider.value|11ms|
|✔️|InheritedProvider doesn't break lazy loading|7ms|
|✔️|InheritedProvider show if listening|7ms|
|✔️|DeferredInheritedProvider.value|6ms|
|✔️|DeferredInheritedProvider|16ms|
**InheritedProvider.value()**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|markNeedsNotifyDependents during startListening is noop|8ms|
|✔️|startListening called again when create returns new value|27ms|
|✔️|startListening|19ms|
|✔️|stopListening not called twice if rebuild doesn't have listeners|16ms|
|✔️|removeListener cannot be null|22ms|
|✔️|pass down current value|17ms|
|✔️|default updateShouldNotify|8ms|
|✔️|custom updateShouldNotify|32ms|
**InheritedProvider()**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|hasValue|16ms|
|✔️|provider calls update if rebuilding only due to didChangeDependencies|9ms|
|✔️|provider notifying dependents doesn't call update|11ms|
|✔️|update can call Provider.of with listen:true|7ms|
|✔️|update lazy loaded can call Provider.of with listen:true|10ms|
|✔️|markNeedsNotifyDependents during startListening is noop|22ms|
|✔️|update can obtain parent of the same type than self|15ms|
|✔️|_debugCheckInvalidValueType|22ms|
|✔️|startListening|18ms|
|✔️|startListening called again when create returns new value|20ms|
|✔️|stopListening not called twice if rebuild doesn't have listeners|18ms|
|✔️|removeListener cannot be null|16ms|
|✔️|fails if initialValueBuilder calls inheritFromElement/inheritFromWiggetOfExactType|17ms|
|✔️|builder is called on every rebuild and after a dependency change|11ms|
|✔️|builder with no updateShouldNotify use ==|8ms|
|✔️|builder calls updateShouldNotify callback|8ms|
|✔️|initialValue is transmitted to valueBuilder|8ms|
|✔️|calls builder again if dependencies change|22ms|
|✔️|exposes initialValue if valueBuilder is null|20ms|
|✔️|call dispose on unmount|22ms|
|✔️|builder unmount, dispose not called if value never read|11ms|
|✔️|call dispose after new value|9ms|
|✔️|valueBuilder works without initialBuilder|11ms|
|✔️|calls initialValueBuilder lazily once|7ms|
|✔️|throws if both builder and initialBuilder are missing|5ms|
**DeferredInheritedProvider.value()**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|hasValue|6ms|
|✔️|startListening|9ms|
|✔️|stopListening cannot be null|9ms|
|✔️|startListening doesn't need setState if already initialized|8ms|
|✔️|setState without updateShouldNotify|8ms|
|✔️|setState with updateShouldNotify|9ms|
|✔️|startListening never leave the widget uninitialized|8ms|
|✔️|startListening called again on controller change|10ms|
**DeferredInheritedProvider()**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|create can't call inherited widgets|7ms|
|✔️|creates the value lazily|7ms|
|✔️|dispose|7ms|
|✔️|dispose no-op if never built|7ms|
### <a id="user-content-r0s6" href="#r0s6">test/listenable_provider_test.dart</a> ✔️
**16** tests were completed in **353ms** with **16** passed, **0** failed and **0** skipped.
**ListenableProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|works with MultiProvider|173ms|
|✔️|asserts that the created notifier can have listeners|12ms|
|✔️|don't listen again if listenable instance doesn't change|12ms|
|✔️|works with null (default)|7ms|
|✔️|works with null (create)|7ms|
|✔️|stateful create called once|11ms|
|✔️|dispose called on unmount|13ms|
|✔️|dispose can be null|8ms|
|✔️|changing listenable rebuilds descendants|12ms|
|✔️|rebuilding with the same provider don't rebuilds descendants|11ms|
|✔️|notifylistener rebuilds descendants|9ms|
**ListenableProvider value constructor**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|pass down key|17ms|
|✔️|changing the Listenable instance rebuilds dependents|29ms|
**ListenableProvider stateful constructor**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|called with context|8ms|
|✔️|pass down key|20ms|
|✔️|throws if create is null|4ms|
### <a id="user-content-r0s7" href="#r0s7">test/listenable_proxy_provider_test.dart</a> ✔️
**12** tests were completed in **373ms** with **12** passed, **0** failed and **0** skipped.
**ListenableProxyProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|throws if update is missing|43ms|
|✔️|asserts that the created notifier has no listener|177ms|
|✔️|asserts that the created notifier has no listener after rebuild|18ms|
|✔️|rebuilds dependendents when listeners are called|20ms|
|✔️|update returning a new Listenable disposes the previously created value and update dependents|25ms|
|✔️|disposes of created value|13ms|
**ListenableProxyProvider variants**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|ListenableProxyProvider|13ms|
|✔️|ListenableProxyProvider2|9ms|
|✔️|ListenableProxyProvider3|9ms|
|✔️|ListenableProxyProvider4|17ms|
|✔️|ListenableProxyProvider5|12ms|
|✔️|ListenableProxyProvider6|17ms|
### <a id="user-content-r0s8" href="#r0s8">test/multi_provider_test.dart</a> ✔️
**3** tests were completed in **198ms** with **3** passed, **0** failed and **0** skipped.
**MultiProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|throw if providers is null|30ms|
|✔️|MultiProvider children can only access parent providers|160ms|
|✔️|MultiProvider.providers with ignored child|8ms|
### <a id="user-content-r0s9" href="#r0s9">test/provider_test.dart</a> ✔️
**11** tests were completed in **306ms** with **11** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|works with MultiProvider|172ms|
**Provider.of**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|throws if T is dynamic|26ms|
|✔️|listen defaults to true when building widgets|13ms|
|✔️|listen defaults to false outside of the widget tree|9ms|
|✔️|listen:false doesn't trigger rebuild|10ms|
|✔️|listen:true outside of the widget tree throws|11ms|
**Provider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|throws if the provided value is a Listenable/Stream|28ms|
|✔️|debugCheckInvalidValueType can be disabled|9ms|
|✔️|simple usage|9ms|
|✔️|throws an error if no provider found|11ms|
|✔️|update should notify|8ms|
### <a id="user-content-r0s10" href="#r0s10">test/proxy_provider_test.dart</a> ✔️
**16** tests were completed in **438ms** with **16** passed, **0** failed and **0** skipped.
**ProxyProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|throws if the provided value is a Listenable/Stream|209ms|
|✔️|debugCheckInvalidValueType can be disabled|13ms|
|✔️|create creates initial value|23ms|
|✔️|consume another providers|18ms|
|✔️|rebuild descendants if value change|13ms|
|✔️|call dispose when unmounted with the latest result|11ms|
|✔️|don't rebuild descendants if value doesn't change|12ms|
|✔️|pass down updateShouldNotify|19ms|
|✔️|works with MultiProvider|16ms|
|✔️|update callback can trigger descendants setState synchronously|24ms|
|✔️|throws if update is null|7ms|
**ProxyProvider variants**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|ProxyProvider2|18ms|
|✔️|ProxyProvider3|16ms|
|✔️|ProxyProvider4|9ms|
|✔️|ProxyProvider5|20ms|
|✔️|ProxyProvider6|10ms|
### <a id="user-content-r0s11" href="#r0s11">test/reassemble_test.dart</a> ✔️
**3** tests were completed in **221ms** with **3** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|ReassembleHandler|194ms|
|✔️|unevaluated create|11ms|
|✔️|unevaluated create|16ms|
### <a id="user-content-r0s12" href="#r0s12">test/selector_test.dart</a> ✔️
**17** tests were completed in **364ms** with **17** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|asserts that builder/selector are not null|32ms|
|✔️|Deep compare maps by default|158ms|
|✔️|Deep compare iterables by default|9ms|
|✔️|Deep compare sets by default|12ms|
|✔️|Deep compare lists by default|14ms|
|✔️|custom shouldRebuid|11ms|
|✔️|passes `child` and `key`|13ms|
|✔️|calls builder if the callback changes|14ms|
|✔️|works with MultiProvider|12ms|
|✔️|don't call builder again if it rebuilds but selector returns the same thing|9ms|
|✔️|call builder again if it rebuilds abd selector returns the a different variable|9ms|
|✔️|Selector|15ms|
|✔️|Selector2|9ms|
|✔️|Selector3|8ms|
|✔️|Selector4|9ms|
|✔️|Selector5|19ms|
|✔️|Selector6|11ms|
### <a id="user-content-r0s13" href="#r0s13">test/stateful_provider_test.dart</a> ✔️
**4** tests were completed in **254ms** with **4** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|asserts|6ms|
|✔️|works with MultiProvider|203ms|
|✔️|calls create only once|27ms|
|✔️|dispose|18ms|
### <a id="user-content-r0s14" href="#r0s14">test/stream_provider_test.dart</a> ✔️
**8** tests were completed in **282ms** with **8** passed, **0** failed and **0** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✔️|works with MultiProvider|191ms|
|✔️|transition from stream to stream preserve state|16ms|
|✔️|throws if stream has error and catchError is missing|22ms|
|✔️|calls catchError if present and stream has error|20ms|
|✔️|works with null|13ms|
|✔️|StreamProvider() crashes if builder is null|5ms|
**StreamProvider()**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|create and dispose stream with builder|11ms|
|✔️|crashes if builder is null|4ms|
### <a id="user-content-r0s15" href="#r0s15">test/value_listenable_provider_test.dart</a>
**5** tests were completed in **327ms** with **4** passed, **1** failed and **0** skipped.
**valueListenableProvider**
|Result|Test|Time|
|:---:|:---|---:|
|✔️|rebuilds when value change|200ms|
|✔️|don't rebuild dependents by default|26ms|
|✔️|pass keys|10ms|
|✔️|don't listen again if stream instance doesn't change|22ms|
|❌|pass updateShouldNotify|69ms|
### ✔️ <a id="user-content-r0s0" href="#r0s0">test/builder_test.dart</a>
```
ChangeNotifierProvider
✔️ default
✔️ .value
ListenableProvider
✔️ default
✔️ .value
Provider
✔️ default
✔️ .value
ProxyProvider
✔️ 0
✔️ 1
✔️ 2
✔️ 3
✔️ 4
✔️ 5
✔️ 6
MultiProvider
✔️ with 1 ChangeNotifierProvider default
✔️ with 2 ChangeNotifierProvider default
✔️ with ListenableProvider default
✔️ with Provider default
✔️ with ProxyProvider0
✔️ with ProxyProvider1
✔️ with ProxyProvider2
✔️ with ProxyProvider3
✔️ with ProxyProvider4
✔️ with ProxyProvider5
✔️ with ProxyProvider6
```
### ✔️ <a id="user-content-r0s1" href="#r0s1">test/change_notifier_provider_test.dart</a>
```
✔️ Use builder property, not child
ChangeNotifierProvider
✔️ value
✔️ builder
✔️ builder1
✔️ builder2
✔️ builder3
✔️ builder4
✔️ builder5
✔️ builder6
✔️ builder0
```
### ✔️ <a id="user-content-r0s2" href="#r0s2">test/consumer_test.dart</a>
```
consumer
✔️ obtains value from Provider<T>
✔️ crashed with no builder
✔️ can be used inside MultiProvider
consumer2
✔️ obtains value from Provider<T>
✔️ crashed with no builder
✔️ can be used inside MultiProvider
consumer3
✔️ obtains value from Provider<T>
✔️ crashed with no builder
✔️ can be used inside MultiProvider
consumer4
✔️ obtains value from Provider<T>
✔️ crashed with no builder
✔️ can be used inside MultiProvider
consumer5
✔️ obtains value from Provider<T>
✔️ crashed with no builder
✔️ can be used inside MultiProvider
consumer6
✔️ obtains value from Provider<T>
✔️ crashed with no builder
✔️ can be used inside MultiProvider
```
### ✔️ <a id="user-content-r0s3" href="#r0s3">test/context_test.dart</a>
```
✔️ watch in layoutbuilder
✔️ select in layoutbuilder
✔️ cannot select in listView
✔️ watch in listView
✔️ watch in gridView
✔️ clears select dependencies for all dependents
BuildContext
✔️ internal selected value is updated
✔️ create can use read without being lazy
✔️ watch can be used inside InheritedProvider.update
✔️ select doesn't fail if it loads a provider that depends on other providers
✔️ don't call old selectors if the child rebuilds individually
✔️ selects throws inside click handlers
✔️ select throws if try to read dynamic
✔️ select throws ProviderNotFoundException
✔️ select throws if watch called inside the callback from build
✔️ select throws if read called inside the callback from build
✔️ select throws if select called inside the callback from build
✔️ select throws if read called inside the callback on dependency change
✔️ select throws if watch called inside the callback on dependency change
✔️ select throws if select called inside the callback on dependency change
✔️ can call read inside didChangeDependencies
✔️ select cannot be called inside didChangeDependencies
✔️ select in initState throws
✔️ watch in initState throws
✔️ read in initState works
✔️ consumer can be removed and selector stops to be called
✔️ context.select deeply compares maps
✔️ context.select deeply compares lists
✔️ context.select deeply compares iterables
✔️ context.select deeply compares sets
✔️ context.watch listens to value changes
```
### ✔️ <a id="user-content-r0s4" href="#r0s4">test/future_provider_test.dart</a>
```
✔️ works with MultiProvider
✔️ (catchError) previous future completes after transition is no-op
✔️ previous future completes after transition is no-op
✔️ transition from future to future preserve state
✔️ throws if future has error and catchError is missing
✔️ calls catchError if present and future has error
✔️ works with null
✔️ create and dispose future with builder
✔️ FutureProvider() crashes if builder is null
FutureProvider()
✔️ crashes if builder is null
```
### ✔️ <a id="user-content-r0s5" href="#r0s5">test/inherited_provider_test.dart</a>
```
✔️ regression test #377
✔️ rebuild on dependency flags update
✔️ properly update debug flags if a create triggers another deferred create
✔️ properly update debug flags if a create triggers another deferred create
✔️ properly update debug flags if an update triggers another create/update
✔️ properly update debug flags if a create triggers another create/update
✔️ Provider.of(listen: false) outside of build works when it loads a provider
✔️ new value is available in didChangeDependencies
✔️ builder receives the current value and updates independently from `update`
✔️ builder can _not_ rebuild when provider updates
✔️ builder rebuilds if provider is recreated
✔️ provider.of throws if listen:true outside of the widget tree
✔️ InheritedProvider throws if no child is provided with default constructor
✔️ InheritedProvider throws if no child is provided with value constructor
✔️ DeferredInheritedProvider throws if no child is provided with default constructor
✔️ DeferredInheritedProvider throws if no child is provided with value constructor
✔️ startListening markNeedsNotifyDependents
✔️ InheritedProvider can be subclassed
✔️ DeferredInheritedProvider can be subclassed
✔️ can be used with MultiProvider
✔️ throw if the widget ctor changes
✔️ InheritedProvider lazy loading can be disabled
✔️ InheritedProvider.value lazy loading can be disabled
✔️ InheritedProvider subclass don't have to specify default lazy value
✔️ DeferredInheritedProvider lazy loading can be disabled
✔️ DeferredInheritedProvider.value lazy loading can be disabled
✔️ selector
✔️ can select multiple types from same provider
✔️ can select same type on two different providers
✔️ can select same type twice on same provider
✔️ Provider.of has a proper error message if context is null
diagnostics
✔️ InheritedProvider.value
✔️ InheritedProvider doesn't break lazy loading
✔️ InheritedProvider show if listening
✔️ DeferredInheritedProvider.value
✔️ DeferredInheritedProvider
InheritedProvider.value()
✔️ markNeedsNotifyDependents during startListening is noop
✔️ startListening called again when create returns new value
✔️ startListening
✔️ stopListening not called twice if rebuild doesn't have listeners
✔️ removeListener cannot be null
✔️ pass down current value
✔️ default updateShouldNotify
✔️ custom updateShouldNotify
InheritedProvider()
✔️ hasValue
✔️ provider calls update if rebuilding only due to didChangeDependencies
✔️ provider notifying dependents doesn't call update
✔️ update can call Provider.of with listen:true
✔️ update lazy loaded can call Provider.of with listen:true
✔️ markNeedsNotifyDependents during startListening is noop
✔️ update can obtain parent of the same type than self
✔️ _debugCheckInvalidValueType
✔️ startListening
✔️ startListening called again when create returns new value
✔️ stopListening not called twice if rebuild doesn't have listeners
✔️ removeListener cannot be null
✔️ fails if initialValueBuilder calls inheritFromElement/inheritFromWiggetOfExactType
✔️ builder is called on every rebuild and after a dependency change
✔️ builder with no updateShouldNotify use ==
✔️ builder calls updateShouldNotify callback
✔️ initialValue is transmitted to valueBuilder
✔️ calls builder again if dependencies change
✔️ exposes initialValue if valueBuilder is null
✔️ call dispose on unmount
✔️ builder unmount, dispose not called if value never read
✔️ call dispose after new value
✔️ valueBuilder works without initialBuilder
✔️ calls initialValueBuilder lazily once
✔️ throws if both builder and initialBuilder are missing
DeferredInheritedProvider.value()
✔️ hasValue
✔️ startListening
✔️ stopListening cannot be null
✔️ startListening doesn't need setState if already initialized
✔️ setState without updateShouldNotify
✔️ setState with updateShouldNotify
✔️ startListening never leave the widget uninitialized
✔️ startListening called again on controller change
DeferredInheritedProvider()
✔️ create can't call inherited widgets
✔️ creates the value lazily
✔️ dispose
✔️ dispose no-op if never built
```
### ✔️ <a id="user-content-r0s6" href="#r0s6">test/listenable_provider_test.dart</a>
```
ListenableProvider
✔️ works with MultiProvider
✔️ asserts that the created notifier can have listeners
✔️ don't listen again if listenable instance doesn't change
✔️ works with null (default)
✔️ works with null (create)
✔️ stateful create called once
✔️ dispose called on unmount
✔️ dispose can be null
✔️ changing listenable rebuilds descendants
✔️ rebuilding with the same provider don't rebuilds descendants
✔️ notifylistener rebuilds descendants
ListenableProvider value constructor
✔️ pass down key
✔️ changing the Listenable instance rebuilds dependents
ListenableProvider stateful constructor
✔️ called with context
✔️ pass down key
✔️ throws if create is null
```
### ✔️ <a id="user-content-r0s7" href="#r0s7">test/listenable_proxy_provider_test.dart</a>
```
ListenableProxyProvider
✔️ throws if update is missing
✔️ asserts that the created notifier has no listener
✔️ asserts that the created notifier has no listener after rebuild
✔️ rebuilds dependendents when listeners are called
✔️ update returning a new Listenable disposes the previously created value and update dependents
✔️ disposes of created value
ListenableProxyProvider variants
✔️ ListenableProxyProvider
✔️ ListenableProxyProvider2
✔️ ListenableProxyProvider3
✔️ ListenableProxyProvider4
✔️ ListenableProxyProvider5
✔️ ListenableProxyProvider6
```
### ✔️ <a id="user-content-r0s8" href="#r0s8">test/multi_provider_test.dart</a>
```
MultiProvider
✔️ throw if providers is null
✔️ MultiProvider children can only access parent providers
✔️ MultiProvider.providers with ignored child
```
### ✔️ <a id="user-content-r0s9" href="#r0s9">test/provider_test.dart</a>
```
✔️ works with MultiProvider
Provider.of
✔️ throws if T is dynamic
✔️ listen defaults to true when building widgets
✔️ listen defaults to false outside of the widget tree
✔️ listen:false doesn't trigger rebuild
✔️ listen:true outside of the widget tree throws
Provider
✔️ throws if the provided value is a Listenable/Stream
✔️ debugCheckInvalidValueType can be disabled
✔️ simple usage
✔️ throws an error if no provider found
✔️ update should notify
```
### ✔️ <a id="user-content-r0s10" href="#r0s10">test/proxy_provider_test.dart</a>
```
ProxyProvider
✔️ throws if the provided value is a Listenable/Stream
✔️ debugCheckInvalidValueType can be disabled
✔️ create creates initial value
✔️ consume another providers
✔️ rebuild descendants if value change
✔️ call dispose when unmounted with the latest result
✔️ don't rebuild descendants if value doesn't change
✔️ pass down updateShouldNotify
✔️ works with MultiProvider
✔️ update callback can trigger descendants setState synchronously
✔️ throws if update is null
ProxyProvider variants
✔️ ProxyProvider2
✔️ ProxyProvider3
✔️ ProxyProvider4
✔️ ProxyProvider5
✔️ ProxyProvider6
```
### ✔️ <a id="user-content-r0s11" href="#r0s11">test/reassemble_test.dart</a>
```
✔️ ReassembleHandler
✔️ unevaluated create
✔️ unevaluated create
```
### ✔️ <a id="user-content-r0s12" href="#r0s12">test/selector_test.dart</a>
```
✔️ asserts that builder/selector are not null
✔️ Deep compare maps by default
✔️ Deep compare iterables by default
✔️ Deep compare sets by default
✔️ Deep compare lists by default
✔️ custom shouldRebuid
✔️ passes `child` and `key`
✔️ calls builder if the callback changes
✔️ works with MultiProvider
✔️ don't call builder again if it rebuilds but selector returns the same thing
✔️ call builder again if it rebuilds abd selector returns the a different variable
✔️ Selector
✔️ Selector2
✔️ Selector3
✔️ Selector4
✔️ Selector5
✔️ Selector6
```
### ✔️ <a id="user-content-r0s13" href="#r0s13">test/stateful_provider_test.dart</a>
```
✔️ asserts
✔️ works with MultiProvider
✔️ calls create only once
✔️ dispose
```
### ✔️ <a id="user-content-r0s14" href="#r0s14">test/stream_provider_test.dart</a>
```
✔️ works with MultiProvider
✔️ transition from stream to stream preserve state
✔️ throws if stream has error and catchError is missing
✔️ calls catchError if present and stream has error
✔️ works with null
✔️ StreamProvider() crashes if builder is null
StreamProvider()
✔️ create and dispose stream with builder
✔️ crashes if builder is null
```
### ❌ <a id="user-content-r0s15" href="#r0s15">test/value_listenable_provider_test.dart</a>
```
valueListenableProvider
✔️ rebuilds when value change
✔️ don't rebuild dependents by default
✔️ pass keys
✔️ don't listen again if stream instance doesn't change
❌ pass updateShouldNotify
The following TestFailure object was thrown running a test:
Expected: <2>
Actual: <1>
Unexpected number of calls
```

View file

@ -1,13 +1,12 @@
![Tests failed](https://img.shields.io/badge/tests-1%20failed%2C%201%20skipped-critical)
## <a id="user-content-r0" href="#r0">fixtures/external/java/TEST-org.apache.pulsar.AddMissingPatchVersionTest.xml</a>
## ❌ <a id="user-content-r0" href="#r0">fixtures/external/java/TEST-org.apache.pulsar.AddMissingPatchVersionTest.xml</a>
**2** tests were completed in **116ms** with **0** passed, **1** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[org.apache.pulsar.AddMissingPatchVersionTest](#r0s0)||1❌|1✖|116ms|
### <a id="user-content-r0s0" href="#r0s0">org.apache.pulsar.AddMissingPatchVersionTest</a>
**2** tests were completed in **116ms** with **0** passed, **1** failed and **1** skipped.
|Result|Test|Time|
|:---:|:---|---:|
|✖️|testVersionStrings|99ms|
|❌|testVersionStrings|17ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">org.apache.pulsar.AddMissingPatchVersionTest</a>
```
✖️ testVersionStrings
❌ testVersionStrings
java.lang.AssertionError: expected [1.2.1] but found [1.2.0]
```

File diff suppressed because it is too large Load diff

View file

@ -160,8 +160,11 @@ The test description was:
pass updateShouldNotify
════════════════════════════════════════════════════════════════════════════════════════════════════",
"line": 112,
"message": "Test failed. See exception logs above.
The test description was: pass updateShouldNotify",
"message": "The following TestFailure object was thrown running a test:
Expected: <2>
Actual: <1>
Unexpected number of calls
",
"path": "test/value_listenable_provider_test.dart",
},
"name": "pass updateShouldNotify",

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: |

BIN
assets/mocha-groups.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

362
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);
@ -324,18 +325,29 @@ class TestReporter {
const tr = await parser.parse(file, content);
results.push(tr);
}
core.info(`Creating check run ${name}`);
const createResp = await this.octokit.checks.create({
head_sha: this.context.sha,
name,
status: 'in_progress',
output: {
title: name,
summary: ''
},
...github.context.repo
});
core.info('Creating report summary');
const { listSuites, listTests } = this;
const summary = get_report_1.getReport(results, { listSuites, listTests });
const baseUrl = createResp.data.html_url;
const summary = get_report_1.getReport(results, { listSuites, listTests, baseUrl });
core.info('Creating annotations');
const annotations = get_annotations_1.getAnnotations(results, this.maxAnnotations);
const isFailed = results.some(tr => tr.result === 'failed');
const conclusion = isFailed ? 'failure' : 'success';
const icon = isFailed ? markdown_utils_1.Icon.fail : markdown_utils_1.Icon.success;
core.info(`Creating check run with conclusion ${conclusion}`);
const resp = await this.octokit.checks.create({
head_sha: this.context.sha,
name,
core.info(`Updating check run conclusion (${conclusion}) and output`);
const resp = await this.octokit.checks.update({
check_run_id: createResp.data.id,
conclusion,
status: 'completed',
output: {
@ -362,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}'`);
}
@ -512,14 +526,14 @@ class DartJsonParser {
return undefined;
}
const { trackedFiles } = this.options;
const message = (_b = (_a = test.error) === null || _a === void 0 ? void 0 : _a.error) !== null && _b !== void 0 ? _b : '';
const stackTrace = (_d = (_c = test.error) === null || _c === void 0 ? void 0 : _c.stackTrace) !== null && _d !== void 0 ? _d : '';
const stackTrace = (_b = (_a = test.error) === null || _a === void 0 ? void 0 : _a.stackTrace) !== null && _b !== void 0 ? _b : '';
const print = test.print
.filter(p => p.messageType === 'print')
.map(p => p.message)
.join('\n');
const details = [print, stackTrace].filter(str => str !== '').join('\n');
const src = this.exceptionThrowSource(details, trackedFiles);
const message = this.getErrorMessage((_d = (_c = test.error) === null || _c === void 0 ? void 0 : _c.error) !== null && _d !== void 0 ? _d : '', print);
let path;
let line;
if (src !== undefined) {
@ -540,6 +554,19 @@ class DartJsonParser {
details
};
}
getErrorMessage(message, print) {
if (this.sdk === 'flutter') {
const uselessMessageRe = /^Test failed\. See exception logs above\.\nThe test description was:/m;
const flutterPrintRe = /^ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK +\s+(.*)\s+When the exception was thrown, this was the stack:/ms;
if (uselessMessageRe.test(message)) {
const match = print.match(flutterPrintRe);
if (match !== null) {
return match[1];
}
}
}
return message || print;
}
exceptionThrowSource(ex, trackedFiles) {
const lines = ex.split(/\r?\n/g);
// regexp to extract file path and line number from stack trace
@ -663,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) {
@ -703,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) {
@ -980,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 {
@ -1045,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;
@ -1056,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;
@ -1088,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:
@ -1098,6 +1209,7 @@ exports.JestJunitParser = JestJunitParser;
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getAnnotations = void 0;
const markdown_utils_1 = __nccwpck_require__(6482);
const parse_utils_1 = __nccwpck_require__(7811);
function getAnnotations(results, maxCount) {
var _a, _b, _c, _d;
if (maxCount === 0) {
@ -1127,9 +1239,9 @@ 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 : getFirstNonEmptyLine(err.details)) !== null && _d !== void 0 ? _d : 'Test failed',
message: (_d = (_c = err.message) !== null && _c !== void 0 ? _c : parse_utils_1.getFirstNonEmptyLine(err.details)) !== null && _d !== void 0 ? _d : 'Test failed',
path,
line
});
@ -1167,10 +1279,6 @@ function enforceCheckRunLimits(err) {
}
return err;
}
function getFirstNonEmptyLine(stackTrace) {
const lines = stackTrace.split(/\r?\n/g);
return lines.find(str => !/^\s*$/.test(str));
}
function ident(text, prefix) {
return text
.split(/\n/g)
@ -1209,50 +1317,62 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getReport = void 0;
const core = __importStar(__nccwpck_require__(2186));
const markdown_utils_1 = __nccwpck_require__(6482);
const parse_utils_1 = __nccwpck_require__(7811);
const slugger_1 = __nccwpck_require__(3328);
const MAX_REPORT_LENGTH = 65535;
const defaultOptions = {
listSuites: 'all',
listTests: 'all'
listTests: 'all',
baseUrl: ''
};
function getReport(results, options = defaultOptions) {
core.info('Generating check run summary');
const maxReportLength = 65535;
applySort(results);
const opts = { ...options };
let report = renderReport(results, opts);
if (getByteLength(report) <= maxReportLength) {
let lines = renderReport(results, opts);
let report = lines.join('\n');
if (getByteLength(report) <= MAX_REPORT_LENGTH) {
return report;
}
if (opts.listTests === 'all') {
core.info("Test report summary is too big - setting 'listTests' to 'failed'");
opts.listTests = 'failed';
report = renderReport(results, opts);
if (getByteLength(report) <= maxReportLength) {
lines = renderReport(results, opts);
report = lines.join('\n');
if (getByteLength(report) <= MAX_REPORT_LENGTH) {
return report;
}
}
if (opts.listSuites === 'all') {
core.info("Test report summary is too big - setting 'listSuites' to 'failed'");
opts.listSuites = 'failed';
report = renderReport(results, opts);
if (getByteLength(report) <= maxReportLength) {
return report;
}
}
if (opts.listTests !== 'none') {
core.info("Test report summary is too big - setting 'listTests' to 'none'");
opts.listTests = 'none';
report = renderReport(results, opts);
if (getByteLength(report) <= maxReportLength) {
return report;
}
}
core.warning(`Test report summary exceeded limit of ${maxReportLength} bytes`);
const badge = getReportBadge(results);
const msg = `**Test report summary exceeded limit of ${maxReportLength} bytes and was removed**`;
return `${badge}\n${msg}`;
core.warning(`Test report summary exceeded limit of ${MAX_REPORT_LENGTH} bytes and will be trimmed`);
return trimReport(lines);
}
exports.getReport = getReport;
function trimReport(lines) {
const closingBlock = '```';
const errorMsg = `**Report exceeded GitHub limit of ${MAX_REPORT_LENGTH} bytes and has been trimmed**`;
const maxErrorMsgLength = closingBlock.length + errorMsg.length + 2;
const maxReportLength = MAX_REPORT_LENGTH - maxErrorMsgLength;
let reportLength = 0;
let codeBlock = false;
let endLineIndex = 0;
for (endLineIndex = 0; endLineIndex < lines.length; endLineIndex++) {
const line = lines[endLineIndex];
const lineLength = getByteLength(line);
reportLength += lineLength + 1;
if (reportLength > maxReportLength) {
break;
}
if (line === '```') {
codeBlock = !codeBlock;
}
}
const reportLines = lines.slice(0, endLineIndex);
if (codeBlock) {
reportLines.push('```');
}
reportLines.push(errorMsg);
return reportLines.join('\n');
}
function applySort(results) {
results.sort((a, b) => a.path.localeCompare(b.path));
for (const res of results) {
@ -1268,7 +1388,7 @@ function renderReport(results, options) {
sections.push(badge);
const runs = getTestRunsReport(results, options);
sections.push(...runs);
return sections.join('\n');
return sections;
}
function getReportBadge(results) {
const passed = results.reduce((sum, tr) => sum + tr.passed, 0);
@ -1305,7 +1425,7 @@ function getTestRunsReport(testRuns, options) {
const tableData = testRuns.map((tr, runIndex) => {
const time = markdown_utils_1.formatTime(tr.time);
const name = tr.path;
const addr = makeRunSlug(runIndex).link;
const addr = options.baseUrl + makeRunSlug(runIndex).link;
const nameLink = markdown_utils_1.link(name, addr);
const passed = tr.passed > 0 ? `${tr.passed}${markdown_utils_1.Icon.success}` : '';
const failed = tr.failed > 0 ? `${tr.failed}${markdown_utils_1.Icon.fail}` : '';
@ -1322,9 +1442,9 @@ function getTestRunsReport(testRuns, options) {
function getSuitesReport(tr, runIndex, options) {
const sections = [];
const trSlug = makeRunSlug(runIndex);
const nameLink = `<a id="${trSlug.id}" href="${trSlug.link}">${tr.path}</a>`;
const nameLink = `<a id="${trSlug.id}" href="${options.baseUrl + trSlug.link}">${tr.path}</a>`;
const icon = getResultIcon(tr.result);
sections.push(`## ${nameLink} ${icon}`);
sections.push(`## ${icon}\xa0${nameLink}`);
const time = markdown_utils_1.formatTime(tr.time);
const headingLine2 = tr.tests > 0
? `**${tr.tests}** tests were completed in **${time}** with **${tr.passed}** passed, **${tr.failed}** failed and **${tr.skipped}** skipped.`
@ -1336,7 +1456,7 @@ function getSuitesReport(tr, runIndex, options) {
const tsTime = markdown_utils_1.formatTime(s.time);
const tsName = s.name;
const skipLink = options.listTests === 'none' || (options.listTests === 'failed' && s.result !== 'failed');
const tsAddr = makeSuiteSlug(runIndex, suiteIndex).link;
const tsAddr = options.baseUrl + makeSuiteSlug(runIndex, suiteIndex).link;
const tsNameLink = skipLink ? tsName : markdown_utils_1.link(tsName, tsAddr);
const passed = s.passed > 0 ? `${s.passed}${markdown_utils_1.Icon.success}` : '';
const failed = s.failed > 0 ? `${s.failed}${markdown_utils_1.Icon.fail}` : '';
@ -1354,33 +1474,38 @@ function getSuitesReport(tr, runIndex, options) {
return sections;
}
function getTestsReport(ts, runIndex, suiteIndex, options) {
const groups = options.listTests === 'failed' ? ts.failedGroups : ts.groups;
var _a, _b, _c;
if (options.listTests === 'failed' && ts.result !== 'failed') {
return [];
}
const groups = ts.groups;
if (groups.length === 0) {
return [];
}
const sections = [];
const tsName = ts.name;
const tsSlug = makeSuiteSlug(runIndex, suiteIndex);
const tsNameLink = `<a id="${tsSlug.id}" href="${tsSlug.link}">${tsName}</a>`;
const tsNameLink = `<a id="${tsSlug.id}" href="${options.baseUrl + tsSlug.link}">${tsName}</a>`;
const icon = getResultIcon(ts.result);
sections.push(`### ${tsNameLink} ${icon}`);
const tsTime = markdown_utils_1.formatTime(ts.time);
const headingLine2 = `**${ts.tests}** tests were completed in **${tsTime}** with **${ts.passed}** passed, **${ts.failed}** failed and **${ts.skipped}** skipped.`;
sections.push(headingLine2);
sections.push(`### ${icon}\xa0${tsNameLink}`);
sections.push('```');
for (const grp of groups) {
const tests = options.listTests === 'failed' ? grp.failedTests : grp.tests;
if (tests.length === 0) {
continue;
if (grp.name) {
sections.push(grp.name);
}
const grpHeader = grp.name ? `\n**${grp.name}**` : '';
const testsTable = markdown_utils_1.table(['Result', 'Test', 'Time'], [markdown_utils_1.Align.Center, markdown_utils_1.Align.Left, markdown_utils_1.Align.Right], ...grp.tests.map(tc => {
const name = tc.name;
const time = markdown_utils_1.formatTime(tc.time);
const space = grp.name ? ' ' : '';
for (const tc of grp.tests) {
const result = getResultIcon(tc.result);
return [result, name, time];
}));
sections.push(grpHeader, testsTable);
sections.push(`${space}${result} ${tc.name}`);
if (tc.error) {
const lines = (_c = ((_a = tc.error.message) !== null && _a !== void 0 ? _a : (_b = parse_utils_1.getFirstNonEmptyLine(tc.error.details)) === null || _b === void 0 ? void 0 : _b.trim())) === null || _c === void 0 ? void 0 : _c.split(/\r?\n/g).map(l => '\t' + l);
if (lines) {
sections.push(...lines);
}
}
}
}
sections.push('```');
return sections;
}
function makeRunSlug(runIndex) {
@ -1442,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 {
@ -1472,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 {
@ -1497,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 {
@ -1786,13 +1930,48 @@ function ellipsis(text, maxLength) {
exports.ellipsis = ellipsis;
function formatTime(ms) {
if (ms > 1000) {
return `${(ms / 1000).toFixed(3)}s`;
return `${Math.round(ms / 1000)}s`;
}
return `${Math.round(ms)}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:
@ -1801,7 +1980,7 @@ exports.formatTime = formatTime;
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.parseIsoDate = exports.parseNetDuration = void 0;
exports.getFirstNonEmptyLine = exports.parseIsoDate = exports.parseNetDuration = void 0;
function parseNetDuration(str) {
const durationRe = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)$/;
const durationMatch = str.match(durationRe);
@ -1820,6 +1999,11 @@ function parseIsoDate(str) {
return new Date(str);
}
exports.parseIsoDate = parseIsoDate;
function getFirstNonEmptyLine(stackTrace) {
const lines = stackTrace.split(/\r?\n/g);
return lines.find(str => !/^\s*$/.test(str));
}
exports.getFirstNonEmptyLine = getFirstNonEmptyLine;
/***/ }),

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'
@ -146,9 +147,22 @@ class TestReporter {
results.push(tr)
}
core.info(`Creating check run ${name}`)
const createResp = await this.octokit.checks.create({
head_sha: this.context.sha,
name,
status: 'in_progress',
output: {
title: name,
summary: ''
},
...github.context.repo
})
core.info('Creating report summary')
const {listSuites, listTests} = this
const summary = getReport(results, {listSuites, listTests})
const baseUrl = createResp.data.html_url
const summary = getReport(results, {listSuites, listTests, baseUrl})
core.info('Creating annotations')
const annotations = getAnnotations(results, this.maxAnnotations)
@ -157,10 +171,9 @@ class TestReporter {
const conclusion = isFailed ? 'failure' : 'success'
const icon = isFailed ? Icon.fail : Icon.success
core.info(`Creating check run with conclusion ${conclusion}`)
const resp = await this.octokit.checks.create({
head_sha: this.context.sha,
name,
core.info(`Updating check run conclusion (${conclusion}) and output`)
const resp = await this.octokit.checks.update({
check_run_id: createResp.data.id,
conclusion,
status: 'completed',
output: {
@ -189,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

@ -161,7 +161,6 @@ export class DartJsonParser implements TestParser {
}
const {trackedFiles} = this.options
const message = test.error?.error ?? ''
const stackTrace = test.error?.stackTrace ?? ''
const print = test.print
.filter(p => p.messageType === 'print')
@ -169,6 +168,7 @@ export class DartJsonParser implements TestParser {
.join('\n')
const details = [print, stackTrace].filter(str => str !== '').join('\n')
const src = this.exceptionThrowSource(details, trackedFiles)
const message = this.getErrorMessage(test.error?.error ?? '', print)
let path
let line
@ -191,6 +191,21 @@ export class DartJsonParser implements TestParser {
}
}
private getErrorMessage(message: string, print: string): string {
if (this.sdk === 'flutter') {
const uselessMessageRe = /^Test failed\. See exception logs above\.\nThe test description was:/m
const flutterPrintRe = /^ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK +\s+(.*)\s+When the exception was thrown, this was the stack:/ms
if (uselessMessageRe.test(message)) {
const match = print.match(flutterPrintRe)
if (match !== null) {
return match[1]
}
}
}
return message || print
}
private exceptionThrowSource(ex: string, trackedFiles: string[]): {path: string; line: number} | undefined {
const lines = ex.split(/\r?\n/g)

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

@ -1,5 +1,6 @@
import {ellipsis, fixEol} from '../utils/markdown-utils'
import {TestRunResult} from '../test-results'
import {getFirstNonEmptyLine} from '../utils/parse-utils'
type Annotation = {
path: string
@ -53,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,
@ -98,11 +99,6 @@ function enforceCheckRunLimits(err: Annotation): Annotation {
return err
}
function getFirstNonEmptyLine(stackTrace: string): string | undefined {
const lines = stackTrace.split(/\r?\n/g)
return lines.find(str => !/^\s*$/.test(str))
}
function ident(text: string, prefix: string): string {
return text
.split(/\n/g)

View file

@ -1,61 +1,79 @@
import * as core from '@actions/core'
import {TestExecutionResult, TestRunResult, TestSuiteResult} from '../test-results'
import {Align, formatTime, Icon, link, table} from '../utils/markdown-utils'
import {getFirstNonEmptyLine} from '../utils/parse-utils'
import {slug} from '../utils/slugger'
const MAX_REPORT_LENGTH = 65535
export interface ReportOptions {
listSuites: 'all' | 'failed'
listTests: 'all' | 'failed' | 'none'
baseUrl: string
}
const defaultOptions: ReportOptions = {
listSuites: 'all',
listTests: 'all'
listTests: 'all',
baseUrl: ''
}
export function getReport(results: TestRunResult[], options: ReportOptions = defaultOptions): string {
core.info('Generating check run summary')
const maxReportLength = 65535
applySort(results)
const opts = {...options}
let report = renderReport(results, opts)
if (getByteLength(report) <= maxReportLength) {
let lines = renderReport(results, opts)
let report = lines.join('\n')
if (getByteLength(report) <= MAX_REPORT_LENGTH) {
return report
}
if (opts.listTests === 'all') {
core.info("Test report summary is too big - setting 'listTests' to 'failed'")
opts.listTests = 'failed'
report = renderReport(results, opts)
if (getByteLength(report) <= maxReportLength) {
lines = renderReport(results, opts)
report = lines.join('\n')
if (getByteLength(report) <= MAX_REPORT_LENGTH) {
return report
}
}
if (opts.listSuites === 'all') {
core.info("Test report summary is too big - setting 'listSuites' to 'failed'")
opts.listSuites = 'failed'
report = renderReport(results, opts)
if (getByteLength(report) <= maxReportLength) {
return report
core.warning(`Test report summary exceeded limit of ${MAX_REPORT_LENGTH} bytes and will be trimmed`)
return trimReport(lines)
}
function trimReport(lines: string[]): string {
const closingBlock = '```'
const errorMsg = `**Report exceeded GitHub limit of ${MAX_REPORT_LENGTH} bytes and has been trimmed**`
const maxErrorMsgLength = closingBlock.length + errorMsg.length + 2
const maxReportLength = MAX_REPORT_LENGTH - maxErrorMsgLength
let reportLength = 0
let codeBlock = false
let endLineIndex = 0
for (endLineIndex = 0; endLineIndex < lines.length; endLineIndex++) {
const line = lines[endLineIndex]
const lineLength = getByteLength(line)
reportLength += lineLength + 1
if (reportLength > maxReportLength) {
break
}
if (line === '```') {
codeBlock = !codeBlock
}
}
if (opts.listTests !== 'none') {
core.info("Test report summary is too big - setting 'listTests' to 'none'")
opts.listTests = 'none'
report = renderReport(results, opts)
if (getByteLength(report) <= maxReportLength) {
return report
}
const reportLines = lines.slice(0, endLineIndex)
if (codeBlock) {
reportLines.push('```')
}
core.warning(`Test report summary exceeded limit of ${maxReportLength} bytes`)
const badge = getReportBadge(results)
const msg = `**Test report summary exceeded limit of ${maxReportLength} bytes and was removed**`
return `${badge}\n${msg}`
reportLines.push(errorMsg)
return reportLines.join('\n')
}
function applySort(results: TestRunResult[]): void {
@ -69,7 +87,7 @@ function getByteLength(text: string): number {
return Buffer.byteLength(text, 'utf8')
}
function renderReport(results: TestRunResult[], options: ReportOptions): string {
function renderReport(results: TestRunResult[], options: ReportOptions): string[] {
const sections: string[] = []
const badge = getReportBadge(results)
sections.push(badge)
@ -77,7 +95,7 @@ function renderReport(results: TestRunResult[], options: ReportOptions): string
const runs = getTestRunsReport(results, options)
sections.push(...runs)
return sections.join('\n')
return sections
}
function getReportBadge(results: TestRunResult[]): string {
@ -118,7 +136,7 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
const tableData = testRuns.map((tr, runIndex) => {
const time = formatTime(tr.time)
const name = tr.path
const addr = makeRunSlug(runIndex).link
const addr = options.baseUrl + makeRunSlug(runIndex).link
const nameLink = link(name, addr)
const passed = tr.passed > 0 ? `${tr.passed}${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed}${Icon.fail}` : ''
@ -143,9 +161,9 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
const sections: string[] = []
const trSlug = makeRunSlug(runIndex)
const nameLink = `<a id="${trSlug.id}" href="${trSlug.link}">${tr.path}</a>`
const nameLink = `<a id="${trSlug.id}" href="${options.baseUrl + trSlug.link}">${tr.path}</a>`
const icon = getResultIcon(tr.result)
sections.push(`## ${nameLink} ${icon}`)
sections.push(`## ${icon}\xa0${nameLink}`)
const time = formatTime(tr.time)
const headingLine2 =
@ -163,7 +181,7 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
const tsTime = formatTime(s.time)
const tsName = s.name
const skipLink = options.listTests === 'none' || (options.listTests === 'failed' && s.result !== 'failed')
const tsAddr = makeSuiteSlug(runIndex, suiteIndex).link
const tsAddr = options.baseUrl + makeSuiteSlug(runIndex, suiteIndex).link
const tsNameLink = skipLink ? tsName : link(tsName, tsAddr)
const passed = s.passed > 0 ? `${s.passed}${Icon.success}` : ''
const failed = s.failed > 0 ? `${s.failed}${Icon.fail}` : ''
@ -186,7 +204,10 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
}
function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: number, options: ReportOptions): string[] {
const groups = options.listTests === 'failed' ? ts.failedGroups : ts.groups
if (options.listTests === 'failed' && ts.result !== 'failed') {
return []
}
const groups = ts.groups
if (groups.length === 0) {
return []
}
@ -195,33 +216,30 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
const tsName = ts.name
const tsSlug = makeSuiteSlug(runIndex, suiteIndex)
const tsNameLink = `<a id="${tsSlug.id}" href="${tsSlug.link}">${tsName}</a>`
const tsNameLink = `<a id="${tsSlug.id}" href="${options.baseUrl + tsSlug.link}">${tsName}</a>`
const icon = getResultIcon(ts.result)
sections.push(`### ${tsNameLink} ${icon}`)
const tsTime = formatTime(ts.time)
const headingLine2 = `**${ts.tests}** tests were completed in **${tsTime}** with **${ts.passed}** passed, **${ts.failed}** failed and **${ts.skipped}** skipped.`
sections.push(headingLine2)
sections.push(`### ${icon}\xa0${tsNameLink}`)
sections.push('```')
for (const grp of groups) {
const tests = options.listTests === 'failed' ? grp.failedTests : grp.tests
if (tests.length === 0) {
continue
if (grp.name) {
sections.push(grp.name)
}
const space = grp.name ? ' ' : ''
for (const tc of grp.tests) {
const result = getResultIcon(tc.result)
sections.push(`${space}${result} ${tc.name}`)
if (tc.error) {
const lines = (tc.error.message ?? getFirstNonEmptyLine(tc.error.details)?.trim())
?.split(/\r?\n/g)
.map(l => '\t' + l)
if (lines) {
sections.push(...lines)
}
}
}
const grpHeader = grp.name ? `\n**${grp.name}**` : ''
const testsTable = table(
['Result', 'Test', 'Time'],
[Align.Center, Align.Left, Align.Right],
...grp.tests.map(tc => {
const name = tc.name
const time = formatTime(tc.time)
const result = getResultIcon(tc.result)
return [result, name, time]
})
)
sections.push(grpHeader, testsTable)
}
sections.push('```')
return sections
}

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 {

View file

@ -41,7 +41,7 @@ export function ellipsis(text: string, maxLength: number): string {
export function formatTime(ms: number): string {
if (ms > 1000) {
return `${(ms / 1000).toFixed(3)}s`
return `${Math.round(ms / 1000)}s`
}
return `${Math.round(ms)}ms`

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}
}
}
}
}

View file

@ -17,3 +17,8 @@ export function parseIsoDate(str: string): Date {
return new Date(str)
}
export function getFirstNonEmptyLine(stackTrace: string): string | undefined {
const lines = stackTrace.split(/\r?\n/g)
return lines.find(str => !/^\s*$/.test(str))
}