Compare commits

..

57 Commits

Author SHA1 Message Date
Jozef Izso
9c4a54379f Upgrade jest to v30
Update `jest` package to v30.0.4
2025-07-09 14:16:56 +02:00
Jozef Izso
4d84da17a1 Upgrade jest to v30 2025-06-29 16:55:36 +02:00
Jozef Izso
8dd7047bf0 Merge pull request #628 from dorny/chore/update_packages 2025-06-29 12:28:49 +02:00
Jozef Izso
71814ae0cd Update development dependencies 2025-06-28 11:32:23 +02:00
Jozef Izso
18430db883 Merge pull request #615 from dboriichuk/trx-stack-trace-summary
Add stack trace from trx to summary
2025-06-18 13:28:01 +02:00
dboriichuk
ae8bd195f8 Add stack tracke to summary 2025-06-18 14:09:49 +03:00
Jozef Izso
a1ac327414 Merge pull request #606 from dorny/bugfix/142-list_failed_tests_only 2025-06-13 13:07:08 +02:00
Jozef Izso
09bbc2665b Merge pull request #605 from dorny/docs/markdown_linting 2025-06-13 13:06:38 +02:00
Jozef Izso
5456de96b0 Merge pull request #604 from dorny/feature/603_improve_code_quality 2025-06-13 13:06:16 +02:00
Jozef Izso
6adcc0c72a Compile dist code 2025-06-08 16:44:51 +02:00
Siegfried Pammer
2312e637f3 List only failed tests
Fixes issue #142
2025-06-08 16:44:51 +02:00
Jozef Izso
3a1ec876a9 Improve alternative test of images showing test-reporter generated content 2025-06-08 14:18:39 +02:00
Jozef Izso
c4b9a11207 Generate alternative text for images showing test-reporter generated content
Text was generated by Copilot with GPT-4.1 model.
2025-06-08 14:05:26 +02:00
Jozef Izso
981f52cdc2 Configure permissive markdown linting rules 2025-06-08 14:00:55 +02:00
Jozef Izso
016f16f7b8 Do not lint markdown files in the __tests_ folder 2025-06-08 13:56:11 +02:00
Jozef Izso
6126f49c2c Use types arguments in the downloadStream event handlers
Issues #603
2025-06-08 13:21:12 +02:00
Jozef Izso
be2b975095 Use typed WorkflowRunEvent when parsing workflow_run payload
Issue #603
2025-06-08 13:21:12 +02:00
Jozef Izso
a6b3e93884 Merge pull request #588 from OlesGalatsan/features/add-links-to-report 2025-06-08 13:13:59 +02:00
Jozef Izso
223c6cd55b Compile dist code 2025-06-08 13:09:53 +02:00
Oles Galatsan
b522d19cac Return links to summary report 2025-06-08 13:09:27 +02:00
Jozef Izso
d56352b96c Merge pull request #589 from OlesGalatsan/features/add-step-summary-short-summary 2025-06-08 12:59:33 +02:00
Jozef Izso
f078ba5e08 Merge pull request #599 from dorny/chore/update_packages 2025-06-07 13:17:49 +02:00
Jozef Izso
389794c9ad Update packages to latest minor releases 2025-06-07 12:11:17 +02:00
Oles Galatsan
9934a5fbd4 Merge branch 'features/add-step-summary-short-summary' of github.com:OlesGalatsan/test-reporter into features/add-step-summary-short-summary 2025-05-20 14:46:19 +03:00
Oles Galatsan
0f25185fa5 Rebuild 2025-05-20 14:46:05 +03:00
Oles Galatsan
fb07f1b2a5 Merge branch 'dorny:main' into features/add-step-summary-short-summary 2025-05-20 14:25:01 +03:00
Oles Galatsan
364887ed35 Add short summary for step summary 2025-05-20 12:11:51 +03:00
Jozef Izso
0b4ea9b681 Merge pull request #576 from Vampire/use-if-always 2025-05-19 21:55:05 +02:00
Björn Kautler
302102c9a4 Use if: ${{ !cancelled() }} 2025-05-19 20:02:04 +02:00
Jozef Izso
890a17cecf test-reporter release v2.1.0
Merge pull request #584 from dorny/release/v2.1.0
2025-05-17 15:58:49 +02:00
Jozef Izso
53f5051dfe test-reporter release v2.1.0 2025-05-17 15:57:53 +02:00
Jozef Izso
d6ff56a60a Merge pull request #583 from dorny/chore/update_packages
Update npm packages
2025-05-17 15:52:11 +02:00
Jozef Izso
b0baeedf4a Rebuild dist 2025-05-17 14:06:57 +02:00
Jozef Izso
ebe4a9b005 Upgrade npm packages 2025-05-17 14:06:28 +02:00
Jozef Izso
4a3cfcde80 Upgrade typescript to v5.8.3 2025-05-17 14:06:28 +02:00
Jozef Izso
84bcb5d437 Merge pull request #577 from lucasoares/patch-1
docs: make sure list-tests is correctly documented on action.yml
2025-05-17 13:46:23 +02:00
Jozef Izso
a8c55a3654 Merge pull request #571 from Shamus03/feature/golang-json-parser
Add Golang test parser
2025-05-17 13:45:22 +02:00
Shamus Taylor
a0398fb7dd Correct behavior for test cases with slashes 2025-05-17 13:42:38 +02:00
Shamus Taylor
34f1c566ff register parser and update readme 2025-05-17 13:41:22 +02:00
Shamus Taylor
7745ff0ec1 Add Golang test parser 2025-05-17 13:41:22 +02:00
Jozef Izso
d33ca7294f Merge pull request #572 from Vampire/fix-input-descriptions
Fix input description for list options
2025-05-17 13:39:56 +02:00
Jozef Izso
29aefa7a46 Merge pull request #568 from micmarc/feature/summary-title
Feature: Add summary title
2025-05-17 13:39:33 +02:00
Michael Marcus
f1fa471229 Update all tests 2025-05-17 13:37:38 +02:00
Michael Marcus
0f47a5bec1 Update README; use empty string as default 2025-05-17 13:36:24 +02:00
Michael Marcus
2b2d091d3d Do not print a title if none is specified in the config 2025-05-17 13:36:24 +02:00
Michael Marcus
0840d7c281 Add test for java-junit 2025-05-17 13:36:23 +02:00
Michael Marcus
0841c8130e Feature: Add summary title
Add new option `report-title` to add H1 title to the Markdown report

Resolves #540
2025-05-17 13:36:23 +02:00
Jozef Izso
d1bf678c89 Merge pull request #582 from OlesGalatsan/bugfix/empty-trx-test-definitions
Fix for empty TRX TestDefinitions
2025-05-17 13:32:22 +02:00
Oles Galatsan
5b44774702 Add integration test for empty TRX TestDefinitions 2025-05-16 10:25:02 +03:00
Jozef Izso
ef7793576a Merge pull request #581 from OlesGalatsan/features/increase-summary-limit
Increase step summary limit to 1MiB
2025-05-15 15:17:47 +02:00
Oles Galatsan
2acf6c2ccd Fix for empty TRX TestDefinitions 2025-05-15 15:40:14 +03:00
Oles Galatsan
8b055ac247 Increase step summary limit 2025-05-15 15:37:31 +03:00
Lucas Soares
bb9fb75efb docs: make sure list-tests is correctly documented on action.yml 2025-05-08 10:10:26 -03:00
Björn Kautler
596aee5d4e Fix input description for list options 2025-04-28 12:08:48 +02:00
Jozef Izso
d609194929 Merge pull request #567 from micmarc/fix/summary-anchor-links
Fix broken links in report summary
2025-03-25 20:14:59 +01:00
Michael Marcus
8039983cdb Add dist changes 2025-03-25 15:10:26 -04:00
Michael Marcus
314ef1dd49 Fix broken links in report summary
Resolves #566
2025-03-25 14:35:49 -04:00
53 changed files with 13464 additions and 2437 deletions

View File

@@ -24,7 +24,7 @@ jobs:
- run: npm test
- name: Upload test results
if: success() || failure()
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: test-results

View File

@@ -15,7 +15,7 @@ jobs:
- name: Create test report
uses: ./
if: success() || failure()
if: ${{ !cancelled() }}
with:
name: JEST Tests
path: __tests__/__results__/*.xml

13
.markdownlint.json Normal file
View File

@@ -0,0 +1,13 @@
{
"blanks-around-headings": false,
"blanks-around-lists": false,
"blanks-around-tables": false,
"blanks-around-fences": false,
"no-bare-urls": false,
"line-length": false,
"ul-style": false,
"no-inline-html": false,
"no-multiple-blanks": {
"maximum": 3
}
}

View File

@@ -1,5 +1,13 @@
# Changelog
## 2.1.0
* Feature: Add summary title https://github.com/dorny/test-reporter/pull/568
* Feature: Add Golang test parser https://github.com/dorny/test-reporter/pull/571
* Increase step summary limit to 1MiB https://github.com/dorny/test-reporter/pull/581
* Fix for empty TRX TestDefinitions https://github.com/dorny/test-reporter/pull/582
* Fix input description for list options https://github.com/dorny/test-reporter/pull/572
* Update npm packages https://github.com/dorny/test-reporter/pull/583
## 2.0.0
* Parse JUnit report with detailed message in failure https://github.com/dorny/test-reporter/pull/559
* Support displaying test results in markdown using GitHub Actions Job Summaries https://github.com/dorny/test-reporter/pull/383

View File

@@ -9,13 +9,14 @@ 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/mocha-groups.png)|
|![Summary showing test run with all tests passed, including details such as test file names, number of passed, failed, and skipped tests, and execution times. The interface is dark-themed and displays a green badge indicating 3527 passed and 4 skipped tests.](assets/fluent-validation-report.png)|![Summary showing test run with a failed unit test. The summary uses a dark background and highlights errors in red for quick identification.](assets/provider-error-summary.png)|![GitHub Actions annotation showing details of a failed unit test with a detailed error message, stack trace, and code annotation.](assets/provider-error-details.png)|![Test cases written in Mocha framework with a list of expectations for each test case. The table format and color-coded badges help users quickly assess test suite health.](assets/mocha-groups.png)|
|:--:|:--:|:--:|:--:|
**Supported languages / frameworks:**
- .NET / [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#examples) ( [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)
- Go / [go test](https://pkg.go.dev/testing)
- Java / [JUnit](https://junit.org/)
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
- Swift / xUnit
@@ -49,7 +50,7 @@ jobs:
- name: Test Report
uses: dorny/test-reporter@v2
if: success() || failure() # run this step even if previous step failed
if: ${{ !cancelled() }} # run this step even if previous step failed
with:
name: JEST Tests # Name of the check run which will be created
path: reports/jest-*.xml # Path to test results
@@ -78,7 +79,7 @@ jobs:
- run: npm ci # install packages
- run: npm test # run tests (configured to use jest-junit reporter)
- uses: actions/upload-artifact@v4 # upload test results
if: success() || failure() # run this step even if previous step failed
if: ${{ !cancelled() }} # run this step even if previous step failed
with:
name: test-results
path: jest-junit.xml
@@ -140,6 +141,7 @@ jobs:
# dotnet-nunit
# dotnet-trx
# flutter-json
# golang-json
# java-junit
# jest-junit
# mocha-json
@@ -154,6 +156,11 @@ jobs:
# Allows you to generate reports for Actions Summary
# https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/
use-actions-summary: 'true'
# Optionally specify a title (Heading level 1) for the report. Leading and trailing whitespace are ignored.
# This is useful for separating your test report from other sections in the build summary.
# If omitted or set to whitespace/empty, no title will be printed.
report-title: ''
# Customize the title of badges shown for each Actions Summary.
# Useful when distinguish summaries for tests ran in multiple Actions steps.
@@ -273,6 +280,13 @@ For more information see:
</details>
<details>
<summary>golang-json</summary>
You must use the `-json` flag and output the results to a file (ex: `go test -json > testresults.json`)
</details>
<details>
<summary>java-junit (Experimental)</summary>
@@ -345,7 +359,7 @@ Support for Swift test results in xUnit format is experimental - should work but
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.
- Test report (i.e. build 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@v4` 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

View File

@@ -1,14 +1,14 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%204%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/dart-json.json|1 ✅|4 ❌|1 ⚪|4s|
## ❌ <a id="user-content-r0" href="#r0">fixtures/dart-json.json</a>
|[fixtures/dart-json.json](#user-content-r0)|1 ✅|4 ❌|1 ⚪|4s|
## ❌ <a id="user-content-r0" href="#user-content-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>
|[test/main_test.dart](#user-content-r0s0)|1 ✅|3 ❌||74ms|
|[test/second_test.dart](#user-content-r0s1)||1 ❌|1 ⚪|51ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">test/main_test.dart</a>
```
Test 1
✅ Passing test
@@ -23,7 +23,7 @@ Test 2
❌ Exception in test
Exception: Some error
```
### ❌ <a id="user-content-r0s1" href="#r0s1">test/second_test.dart</a>
### ❌ <a id="user-content-r0s1" href="#user-content-r0s1">test/second_test.dart</a>
```
❌ Timeout test
TimeoutException after 0:00:00.000001: Test timed out after 0 seconds.

View File

@@ -1,13 +1,13 @@
![Tests failed](https://img.shields.io/badge/tests-3%20passed%2C%205%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/dotnet-nunit.xml|3 ✅|5 ❌|1 ⚪|230ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/dotnet-nunit.xml</a>
|[fixtures/dotnet-nunit.xml](#user-content-r0)|3 ✅|5 ❌|1 ⚪|230ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dotnet-nunit.xml</a>
**9** tests were completed in **230ms** with **3** passed, **5** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests](#r0s0)|3 ✅|5 ❌|1 ⚪|69ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests</a>
|[DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests](#user-content-r0s0)|3 ✅|5 ❌|1 ⚪|69ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests</a>
```
CalculatorTests
✅ Is_Even_Number(2)

View File

@@ -0,0 +1,34 @@
![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%205%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/dotnet-trx.trx](#user-content-r0)|5 ✅|5 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dotnet-trx.trx</a>
**11** tests were completed in **1s** with **5** passed, **5** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[DotnetTests.XUnitTests.CalculatorTests](#user-content-r0s0)|5 ✅|5 ❌|1 ⚪|118ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">DotnetTests.XUnitTests.CalculatorTests</a>
```
❌ Exception_In_TargetTest
System.DivideByZeroException : Attempted to divide by zero.
at DotnetTests.Unit.Calculator.Div(Int32 a, Int32 b) in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.Unit\Calculator.cs:line 9
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_TargetTest() in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 33
❌ Exception_In_Test
System.Exception : Test
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_Test() in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 39
❌ Failing_Test
Assert.Equal() Failure
Expected: 3
Actual: 2
at DotnetTests.XUnitTests.CalculatorTests.Failing_Test() in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 27
❌ Is_Even_Number(i: 3)
Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Is_Even_Number(Int32 i) in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 59
❌ Should be even number(i: 3)
Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Theory_With_Custom_Name(Int32 i) in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 67
```

View File

@@ -1,34 +1,40 @@
![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%205%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/dotnet-trx.trx|5 ✅|5 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#r0">fixtures/dotnet-trx.trx</a>
|[fixtures/dotnet-trx.trx](#user-content-r0)|5 ✅|5 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dotnet-trx.trx</a>
**11** tests were completed in **1s** with **5** passed, **5** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[DotnetTests.XUnitTests.CalculatorTests](#r0s0)|5 ✅|5 ❌|1 ⚪|118ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">DotnetTests.XUnitTests.CalculatorTests</a>
|[DotnetTests.XUnitTests.CalculatorTests](#user-content-r0s0)|5 ✅|5 ❌|1 ⚪|118ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">DotnetTests.XUnitTests.CalculatorTests</a>
```
✅ Custom Name
❌ Exception_In_TargetTest
System.DivideByZeroException : Attempted to divide by zero.
at DotnetTests.Unit.Calculator.Div(Int32 a, Int32 b) in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.Unit\Calculator.cs:line 9
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_TargetTest() in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 33
❌ Exception_In_Test
System.Exception : Test
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_Test() in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 39
❌ Failing_Test
Assert.Equal() Failure
Expected: 3
Actual: 2
at DotnetTests.XUnitTests.CalculatorTests.Failing_Test() in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 27
✅ Is_Even_Number(i: 2)
❌ Is_Even_Number(i: 3)
Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Is_Even_Number(Int32 i) in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 59
✅ Passing_Test
✅ Should be even number(i: 2)
❌ Should be even number(i: 3)
Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Theory_With_Custom_Name(Int32 i) in C:\Users\Michal\Workspace\dorny\test-reporter\reports\dotnet\DotnetTests.XUnitTests\CalculatorTests.cs:line 67
⚪ Skipped_Test
✅ Timeout_Test
```

View File

@@ -3,74 +3,74 @@
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/external/FluentValidation.Tests.trx|803 ✅||1 ⚪|4s|
## ✅ <a id="user-content-r0" href="#r0">fixtures/external/FluentValidation.Tests.trx</a>
|[fixtures/external/FluentValidation.Tests.trx](#user-content-r0)|803 ✅||1 ⚪|4s|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/external/FluentValidation.Tests.trx</a>
**804** tests were completed in **4s** with **803** passed, **0** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[FluentValidation.Tests.AbstractValidatorTester](#r0s0)|35 ✅|||12ms|
|[FluentValidation.Tests.AccessorCacheTests](#r0s1)|4 ✅||1 ⚪|4ms|
|[FluentValidation.Tests.AssemblyScannerTester](#r0s2)|2 ✅|||2ms|
|[FluentValidation.Tests.CascadingFailuresTester](#r0s3)|38 ✅|||23ms|
|[FluentValidation.Tests.ChainedValidationTester](#r0s4)|13 ✅|||6ms|
|[FluentValidation.Tests.ChainingValidatorsTester](#r0s5)|3 ✅|||1ms|
|[FluentValidation.Tests.ChildRulesTests](#r0s6)|2 ✅|||7ms|
|[FluentValidation.Tests.CollectionValidatorWithParentTests](#r0s7)|16 ✅|||13ms|
|[FluentValidation.Tests.ComplexValidationTester](#r0s8)|17 ✅|||26ms|
|[FluentValidation.Tests.ConditionTests](#r0s9)|18 ✅|||9ms|
|[FluentValidation.Tests.CreditCardValidatorTests](#r0s10)|2 ✅|||2ms|
|[FluentValidation.Tests.CustomFailureActionTester](#r0s11)|3 ✅|||1ms|
|[FluentValidation.Tests.CustomMessageFormatTester](#r0s12)|6 ✅|||3ms|
|[FluentValidation.Tests.CustomValidatorTester](#r0s13)|10 ✅|||6ms|
|[FluentValidation.Tests.DefaultValidatorExtensionTester](#r0s14)|30 ✅|||38ms|
|[FluentValidation.Tests.EmailValidatorTests](#r0s15)|36 ✅|||18ms|
|[FluentValidation.Tests.EmptyTester](#r0s16)|9 ✅|||5ms|
|[FluentValidation.Tests.EnumValidatorTests](#r0s17)|12 ✅|||24ms|
|[FluentValidation.Tests.EqualValidatorTests](#r0s18)|10 ✅|||3ms|
|[FluentValidation.Tests.ExactLengthValidatorTester](#r0s19)|6 ✅|||2ms|
|[FluentValidation.Tests.ExclusiveBetweenValidatorTests](#r0s20)|19 ✅|||6ms|
|[FluentValidation.Tests.ExtensionTester](#r0s21)|4 ✅|||1ms|
|[FluentValidation.Tests.ForEachRuleTests](#r0s22)|34 ✅|||47ms|
|[FluentValidation.Tests.GreaterThanOrEqualToValidatorTester](#r0s23)|14 ✅|||5ms|
|[FluentValidation.Tests.GreaterThanValidatorTester](#r0s24)|13 ✅|||4ms|
|[FluentValidation.Tests.InclusiveBetweenValidatorTests](#r0s25)|18 ✅|||4ms|
|[FluentValidation.Tests.InheritanceValidatorTest](#r0s26)|11 ✅|||18ms|
|[FluentValidation.Tests.InlineValidatorTester](#r0s27)|1 ✅|||2ms|
|[FluentValidation.Tests.LanguageManagerTests](#r0s28)|21 ✅|||28ms|
|[FluentValidation.Tests.LengthValidatorTests](#r0s29)|16 ✅|||17ms|
|[FluentValidation.Tests.LessThanOrEqualToValidatorTester](#r0s30)|13 ✅|||4ms|
|[FluentValidation.Tests.LessThanValidatorTester](#r0s31)|16 ✅|||6ms|
|[FluentValidation.Tests.LocalisedMessagesTester](#r0s32)|6 ✅|||3ms|
|[FluentValidation.Tests.LocalisedNameTester](#r0s33)|2 ✅|||1ms|
|[FluentValidation.Tests.MemberAccessorTests](#r0s34)|9 ✅|||5ms|
|[FluentValidation.Tests.MessageFormatterTests](#r0s35)|10 ✅|||2ms|
|[FluentValidation.Tests.ModelLevelValidatorTests](#r0s36)|2 ✅|||1ms|
|[FluentValidation.Tests.NameResolutionPluggabilityTester](#r0s37)|3 ✅|||2ms|
|[FluentValidation.Tests.NotEmptyTester](#r0s38)|10 ✅|||7ms|
|[FluentValidation.Tests.NotEqualValidatorTests](#r0s39)|11 ✅|||7ms|
|[FluentValidation.Tests.NotNullTester](#r0s40)|5 ✅|||1ms|
|[FluentValidation.Tests.NullTester](#r0s41)|5 ✅|||2ms|
|[FluentValidation.Tests.OnFailureTests](#r0s42)|10 ✅|||8ms|
|[FluentValidation.Tests.PredicateValidatorTester](#r0s43)|5 ✅|||2ms|
|[FluentValidation.Tests.PropertyChainTests](#r0s44)|7 ✅|||1ms|
|[FluentValidation.Tests.RegularExpressionValidatorTests](#r0s45)|15 ✅|||6ms|
|[FluentValidation.Tests.RuleBuilderTests](#r0s46)|29 ✅|||96ms|
|[FluentValidation.Tests.RuleDependencyTests](#r0s47)|14 ✅|||3s|
|[FluentValidation.Tests.RulesetTests](#r0s48)|21 ✅|||14ms|
|[FluentValidation.Tests.ScalePrecisionValidatorTests](#r0s49)|6 ✅|||4ms|
|[FluentValidation.Tests.SharedConditionTests](#r0s50)|42 ✅|||42ms|
|[FluentValidation.Tests.StandalonePropertyValidationTester](#r0s51)|1 ✅|||0ms|
|[FluentValidation.Tests.StringEnumValidatorTests](#r0s52)|10 ✅|||5ms|
|[FluentValidation.Tests.TrackingCollectionTests](#r0s53)|3 ✅|||2ms|
|[FluentValidation.Tests.TransformTests](#r0s54)|4 ✅|||3ms|
|[FluentValidation.Tests.UserSeverityTester](#r0s55)|7 ✅|||3ms|
|[FluentValidation.Tests.UserStateTester](#r0s56)|4 ✅|||3ms|
|[FluentValidation.Tests.ValidateAndThrowTester](#r0s57)|14 ✅|||25ms|
|[FluentValidation.Tests.ValidationResultTests](#r0s58)|8 ✅|||8ms|
|[FluentValidation.Tests.ValidatorDescriptorTester](#r0s59)|5 ✅|||1ms|
|[FluentValidation.Tests.ValidatorSelectorTests](#r0s60)|10 ✅|||9ms|
|[FluentValidation.Tests.ValidatorTesterTester](#r0s61)|73 ✅|||74ms|
### ✅ <a id="user-content-r0s0" href="#r0s0">FluentValidation.Tests.AbstractValidatorTester</a>
|[FluentValidation.Tests.AbstractValidatorTester](#user-content-r0s0)|35 ✅|||12ms|
|[FluentValidation.Tests.AccessorCacheTests](#user-content-r0s1)|4 ✅||1 ⚪|4ms|
|[FluentValidation.Tests.AssemblyScannerTester](#user-content-r0s2)|2 ✅|||2ms|
|[FluentValidation.Tests.CascadingFailuresTester](#user-content-r0s3)|38 ✅|||23ms|
|[FluentValidation.Tests.ChainedValidationTester](#user-content-r0s4)|13 ✅|||6ms|
|[FluentValidation.Tests.ChainingValidatorsTester](#user-content-r0s5)|3 ✅|||1ms|
|[FluentValidation.Tests.ChildRulesTests](#user-content-r0s6)|2 ✅|||7ms|
|[FluentValidation.Tests.CollectionValidatorWithParentTests](#user-content-r0s7)|16 ✅|||13ms|
|[FluentValidation.Tests.ComplexValidationTester](#user-content-r0s8)|17 ✅|||26ms|
|[FluentValidation.Tests.ConditionTests](#user-content-r0s9)|18 ✅|||9ms|
|[FluentValidation.Tests.CreditCardValidatorTests](#user-content-r0s10)|2 ✅|||2ms|
|[FluentValidation.Tests.CustomFailureActionTester](#user-content-r0s11)|3 ✅|||1ms|
|[FluentValidation.Tests.CustomMessageFormatTester](#user-content-r0s12)|6 ✅|||3ms|
|[FluentValidation.Tests.CustomValidatorTester](#user-content-r0s13)|10 ✅|||6ms|
|[FluentValidation.Tests.DefaultValidatorExtensionTester](#user-content-r0s14)|30 ✅|||38ms|
|[FluentValidation.Tests.EmailValidatorTests](#user-content-r0s15)|36 ✅|||18ms|
|[FluentValidation.Tests.EmptyTester](#user-content-r0s16)|9 ✅|||5ms|
|[FluentValidation.Tests.EnumValidatorTests](#user-content-r0s17)|12 ✅|||24ms|
|[FluentValidation.Tests.EqualValidatorTests](#user-content-r0s18)|10 ✅|||3ms|
|[FluentValidation.Tests.ExactLengthValidatorTester](#user-content-r0s19)|6 ✅|||2ms|
|[FluentValidation.Tests.ExclusiveBetweenValidatorTests](#user-content-r0s20)|19 ✅|||6ms|
|[FluentValidation.Tests.ExtensionTester](#user-content-r0s21)|4 ✅|||1ms|
|[FluentValidation.Tests.ForEachRuleTests](#user-content-r0s22)|34 ✅|||47ms|
|[FluentValidation.Tests.GreaterThanOrEqualToValidatorTester](#user-content-r0s23)|14 ✅|||5ms|
|[FluentValidation.Tests.GreaterThanValidatorTester](#user-content-r0s24)|13 ✅|||4ms|
|[FluentValidation.Tests.InclusiveBetweenValidatorTests](#user-content-r0s25)|18 ✅|||4ms|
|[FluentValidation.Tests.InheritanceValidatorTest](#user-content-r0s26)|11 ✅|||18ms|
|[FluentValidation.Tests.InlineValidatorTester](#user-content-r0s27)|1 ✅|||2ms|
|[FluentValidation.Tests.LanguageManagerTests](#user-content-r0s28)|21 ✅|||28ms|
|[FluentValidation.Tests.LengthValidatorTests](#user-content-r0s29)|16 ✅|||17ms|
|[FluentValidation.Tests.LessThanOrEqualToValidatorTester](#user-content-r0s30)|13 ✅|||4ms|
|[FluentValidation.Tests.LessThanValidatorTester](#user-content-r0s31)|16 ✅|||6ms|
|[FluentValidation.Tests.LocalisedMessagesTester](#user-content-r0s32)|6 ✅|||3ms|
|[FluentValidation.Tests.LocalisedNameTester](#user-content-r0s33)|2 ✅|||1ms|
|[FluentValidation.Tests.MemberAccessorTests](#user-content-r0s34)|9 ✅|||5ms|
|[FluentValidation.Tests.MessageFormatterTests](#user-content-r0s35)|10 ✅|||2ms|
|[FluentValidation.Tests.ModelLevelValidatorTests](#user-content-r0s36)|2 ✅|||1ms|
|[FluentValidation.Tests.NameResolutionPluggabilityTester](#user-content-r0s37)|3 ✅|||2ms|
|[FluentValidation.Tests.NotEmptyTester](#user-content-r0s38)|10 ✅|||7ms|
|[FluentValidation.Tests.NotEqualValidatorTests](#user-content-r0s39)|11 ✅|||7ms|
|[FluentValidation.Tests.NotNullTester](#user-content-r0s40)|5 ✅|||1ms|
|[FluentValidation.Tests.NullTester](#user-content-r0s41)|5 ✅|||2ms|
|[FluentValidation.Tests.OnFailureTests](#user-content-r0s42)|10 ✅|||8ms|
|[FluentValidation.Tests.PredicateValidatorTester](#user-content-r0s43)|5 ✅|||2ms|
|[FluentValidation.Tests.PropertyChainTests](#user-content-r0s44)|7 ✅|||1ms|
|[FluentValidation.Tests.RegularExpressionValidatorTests](#user-content-r0s45)|15 ✅|||6ms|
|[FluentValidation.Tests.RuleBuilderTests](#user-content-r0s46)|29 ✅|||96ms|
|[FluentValidation.Tests.RuleDependencyTests](#user-content-r0s47)|14 ✅|||3s|
|[FluentValidation.Tests.RulesetTests](#user-content-r0s48)|21 ✅|||14ms|
|[FluentValidation.Tests.ScalePrecisionValidatorTests](#user-content-r0s49)|6 ✅|||4ms|
|[FluentValidation.Tests.SharedConditionTests](#user-content-r0s50)|42 ✅|||42ms|
|[FluentValidation.Tests.StandalonePropertyValidationTester](#user-content-r0s51)|1 ✅|||0ms|
|[FluentValidation.Tests.StringEnumValidatorTests](#user-content-r0s52)|10 ✅|||5ms|
|[FluentValidation.Tests.TrackingCollectionTests](#user-content-r0s53)|3 ✅|||2ms|
|[FluentValidation.Tests.TransformTests](#user-content-r0s54)|4 ✅|||3ms|
|[FluentValidation.Tests.UserSeverityTester](#user-content-r0s55)|7 ✅|||3ms|
|[FluentValidation.Tests.UserStateTester](#user-content-r0s56)|4 ✅|||3ms|
|[FluentValidation.Tests.ValidateAndThrowTester](#user-content-r0s57)|14 ✅|||25ms|
|[FluentValidation.Tests.ValidationResultTests](#user-content-r0s58)|8 ✅|||8ms|
|[FluentValidation.Tests.ValidatorDescriptorTester](#user-content-r0s59)|5 ✅|||1ms|
|[FluentValidation.Tests.ValidatorSelectorTests](#user-content-r0s60)|10 ✅|||9ms|
|[FluentValidation.Tests.ValidatorTesterTester](#user-content-r0s61)|73 ✅|||74ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">FluentValidation.Tests.AbstractValidatorTester</a>
```
✅ Can_replace_default_errorcode_resolver
✅ CanValidateInstancesOfType_returns_false_when_comparing_against_some_other_type
@@ -108,7 +108,7 @@
✅ WithName_should_override_field_name
✅ WithName_should_override_field_name_with_value_from_other_property
```
### ✅ <a id="user-content-r0s1" href="#r0s1">FluentValidation.Tests.AccessorCacheTests</a>
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">FluentValidation.Tests.AccessorCacheTests</a>
```
⚪ Benchmark
✅ Equality_comparison_check
@@ -116,12 +116,12 @@
✅ Gets_member_for_nested_property
✅ Identifies_if_memberexp_acts_on_model_instance
```
### ✅ <a id="user-content-r0s2" href="#r0s2">FluentValidation.Tests.AssemblyScannerTester</a>
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">FluentValidation.Tests.AssemblyScannerTester</a>
```
✅ Finds_validators_for_types
✅ ForEach_iterates_over_types
```
### ✅ <a id="user-content-r0s3" href="#r0s3">FluentValidation.Tests.CascadingFailuresTester</a>
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">FluentValidation.Tests.CascadingFailuresTester</a>
```
✅ Cascade_mode_can_be_set_after_validator_instantiated
✅ Cascade_mode_can_be_set_after_validator_instantiated_async
@@ -162,7 +162,7 @@
✅ Validation_stops_on_first_failure_when_set_to_StopOnFirstFailure_at_validator_level_async_legacy
✅ Validation_stops_on_first_failure_when_set_to_StopOnFirstFailure_at_validator_level_legacy
```
### ✅ <a id="user-content-r0s4" href="#r0s4">FluentValidation.Tests.ChainedValidationTester</a>
### ✅ <a id="user-content-r0s4" href="#user-content-r0s4">FluentValidation.Tests.ChainedValidationTester</a>
```
✅ Can_validate_using_validator_for_base_type
✅ Chained_property_should_be_excluded
@@ -178,18 +178,18 @@
✅ Uses_explicit_ruleset
✅ Validates_chained_property
```
### ✅ <a id="user-content-r0s5" href="#r0s5">FluentValidation.Tests.ChainingValidatorsTester</a>
### ✅ <a id="user-content-r0s5" href="#user-content-r0s5">FluentValidation.Tests.ChainingValidatorsTester</a>
```
✅ Options_should_only_apply_to_current_validator
✅ Should_create_multiple_validators
✅ Should_execute_multiple_validators
```
### ✅ <a id="user-content-r0s6" href="#r0s6">FluentValidation.Tests.ChildRulesTests</a>
### ✅ <a id="user-content-r0s6" href="#user-content-r0s6">FluentValidation.Tests.ChildRulesTests</a>
```
✅ Can_define_nested_rules_for_collection
✅ ChildRules_works_with_RuleSet
```
### ✅ <a id="user-content-r0s7" href="#r0s7">FluentValidation.Tests.CollectionValidatorWithParentTests</a>
### ✅ <a id="user-content-r0s7" href="#user-content-r0s7">FluentValidation.Tests.CollectionValidatorWithParentTests</a>
```
✅ Async_condition_should_work_with_child_collection
✅ Can_specify_condition_for_individual_collection_elements
@@ -208,7 +208,7 @@
✅ Validates_collection_several_levels_deep
✅ Validates_collection_several_levels_deep_async
```
### ✅ <a id="user-content-r0s8" href="#r0s8">FluentValidation.Tests.ComplexValidationTester</a>
### ✅ <a id="user-content-r0s8" href="#user-content-r0s8">FluentValidation.Tests.ComplexValidationTester</a>
```
✅ Async_condition_should_work_with_complex_property
✅ Async_condition_should_work_with_complex_property_when_validator_invoked_synchronously
@@ -228,7 +228,7 @@
✅ Validates_child_validator_synchronously
✅ Validates_complex_property
```
### ✅ <a id="user-content-r0s9" href="#r0s9">FluentValidation.Tests.ConditionTests</a>
### ✅ <a id="user-content-r0s9" href="#user-content-r0s9">FluentValidation.Tests.ConditionTests</a>
```
✅ Async_condition_executed_synchronosuly_with_asynchronous_collection_rule
✅ Async_condition_executed_synchronosuly_with_asynchronous_rule
@@ -249,18 +249,18 @@
✅ Validation_should_succeed_when_condition_does_not_match
✅ Validation_should_succeed_when_condition_matches
```
### ✅ <a id="user-content-r0s10" href="#r0s10">FluentValidation.Tests.CreditCardValidatorTests</a>
### ✅ <a id="user-content-r0s10" href="#user-content-r0s10">FluentValidation.Tests.CreditCardValidatorTests</a>
```
✅ IsValidTests
✅ When_validation_fails_the_default_error_should_be_set
```
### ✅ <a id="user-content-r0s11" href="#r0s11">FluentValidation.Tests.CustomFailureActionTester</a>
### ✅ <a id="user-content-r0s11" href="#user-content-r0s11">FluentValidation.Tests.CustomFailureActionTester</a>
```
✅ Does_not_invoke_action_if_validation_success
✅ Invokes_custom_action_on_failure
✅ Passes_object_being_validated_to_action
```
### ✅ <a id="user-content-r0s12" href="#r0s12">FluentValidation.Tests.CustomMessageFormatTester</a>
### ✅ <a id="user-content-r0s12" href="#user-content-r0s12">FluentValidation.Tests.CustomMessageFormatTester</a>
```
✅ Replaces_propertyvalue_placeholder
✅ Replaces_propertyvalue_with_empty_string_when_null
@@ -269,7 +269,7 @@
✅ Uses_custom_delegate_for_building_message_only_for_specific_validator
✅ Uses_property_value_in_message
```
### ✅ <a id="user-content-r0s13" href="#r0s13">FluentValidation.Tests.CustomValidatorTester</a>
### ✅ <a id="user-content-r0s13" href="#user-content-r0s13">FluentValidation.Tests.CustomValidatorTester</a>
```
✅ New_Custom_Returns_single_failure
✅ New_Custom_Returns_single_failure_async
@@ -282,7 +282,7 @@
✅ Runs_async_rule_synchronously_when_validator_invoked_synchronously
✅ Runs_sync_rule_asynchronously_when_validator_invoked_asynchronously
```
### ✅ <a id="user-content-r0s14" href="#r0s14">FluentValidation.Tests.DefaultValidatorExtensionTester</a>
### ✅ <a id="user-content-r0s14" href="#user-content-r0s14">FluentValidation.Tests.DefaultValidatorExtensionTester</a>
```
✅ Empty_should_create_EmptyValidator
✅ Equal_should_create_EqualValidator_with_explicit_value
@@ -315,7 +315,7 @@
✅ ScalePrecision_should_create_ScalePrecisionValidator
✅ ScalePrecision_should_create_ScalePrecisionValidator_with_ignore_trailing_zeros
```
### ✅ <a id="user-content-r0s15" href="#r0s15">FluentValidation.Tests.EmailValidatorTests</a>
### ✅ <a id="user-content-r0s15" href="#user-content-r0s15">FluentValidation.Tests.EmailValidatorTests</a>
```
✅ Fails_email_validation_aspnetcore_compatible(email: " \r \t \n")
✅ Fails_email_validation_aspnetcore_compatible(email: "")
@@ -354,7 +354,7 @@
✅ Valid_email_addresses_regex(email: "testperson+label@gmail.com")
✅ Valid_email_addresses_regex(email: null)
```
### ✅ <a id="user-content-r0s16" href="#r0s16">FluentValidation.Tests.EmptyTester</a>
### ✅ <a id="user-content-r0s16" href="#user-content-r0s16">FluentValidation.Tests.EmptyTester</a>
```
✅ Passes_for_ienumerable_that_doesnt_implement_ICollection
✅ Passes_when_collection_empty
@@ -366,7 +366,7 @@
✅ When_value_is_null_validator_should_pass
✅ When_value_is_whitespace_validation_should_pass
```
### ✅ <a id="user-content-r0s17" href="#r0s17">FluentValidation.Tests.EnumValidatorTests</a>
### ✅ <a id="user-content-r0s17" href="#user-content-r0s17">FluentValidation.Tests.EnumValidatorTests</a>
```
✅ Flags_enum_invalid_when_using_outofrange_negative_value
✅ Flags_enum_invalid_when_using_outofrange_positive_value
@@ -381,7 +381,7 @@
✅ When_the_enum_is_not_initialized_with_valid_value_then_the_validator_should_fail
✅ When_validation_fails_the_default_error_should_be_set
```
### ✅ <a id="user-content-r0s18" href="#r0s18">FluentValidation.Tests.EqualValidatorTests</a>
### ✅ <a id="user-content-r0s18" href="#user-content-r0s18">FluentValidation.Tests.EqualValidatorTests</a>
```
✅ Comparison_property_uses_custom_resolver
✅ Should_store_comparison_type
@@ -394,7 +394,7 @@
✅ When_the_objects_are_not_equal_validation_should_fail
✅ When_validation_fails_the_error_should_be_set
```
### ✅ <a id="user-content-r0s19" href="#r0s19">FluentValidation.Tests.ExactLengthValidatorTester</a>
### ✅ <a id="user-content-r0s19" href="#user-content-r0s19">FluentValidation.Tests.ExactLengthValidatorTester</a>
```
✅ Min_and_max_properties_should_be_set
✅ When_exact_length_rule_failes_error_should_have_exact_length_error_errorcode
@@ -403,7 +403,7 @@
✅ When_the_text_length_is_smaller_the_validator_should_fail
✅ When_the_validator_fails_the_error_message_should_be_set
```
### ✅ <a id="user-content-r0s20" href="#r0s20">FluentValidation.Tests.ExclusiveBetweenValidatorTests</a>
### ✅ <a id="user-content-r0s20" href="#user-content-r0s20">FluentValidation.Tests.ExclusiveBetweenValidatorTests</a>
```
✅ To_and_from_properties_should_be_set
✅ To_and_from_properties_should_be_set_for_dates
@@ -425,14 +425,14 @@
✅ When_the_value_is_smaller_than_the_range_then_the_validator_should_fail
✅ When_the_value_is_smaller_than_the_range_then_the_validator_should_fail_for_strings
```
### ✅ <a id="user-content-r0s21" href="#r0s21">FluentValidation.Tests.ExtensionTester</a>
### ✅ <a id="user-content-r0s21" href="#user-content-r0s21">FluentValidation.Tests.ExtensionTester</a>
```
✅ Should_extract_member_from_member_expression
✅ Should_return_null_for_non_member_expressions
✅ Should_split_pascal_cased_member_name
✅ SplitPascalCase_should_return_null_when_input_is_null
```
### ✅ <a id="user-content-r0s22" href="#r0s22">FluentValidation.Tests.ForEachRuleTests</a>
### ✅ <a id="user-content-r0s22" href="#user-content-r0s22">FluentValidation.Tests.ForEachRuleTests</a>
```
✅ Async_condition_should_work_with_child_collection
✅ Can_access_colletion_index
@@ -469,7 +469,7 @@
✅ When_runs_outside_RuleForEach_loop
✅ When_runs_outside_RuleForEach_loop_async
```
### ✅ <a id="user-content-r0s23" href="#r0s23">FluentValidation.Tests.GreaterThanOrEqualToValidatorTester</a>
### ✅ <a id="user-content-r0s23" href="#user-content-r0s23">FluentValidation.Tests.GreaterThanOrEqualToValidatorTester</a>
```
✅ Comparison_property_uses_custom_resolver
✅ Comparison_type
@@ -486,7 +486,7 @@
✅ Validates_with_nullable_when_property_not_null_cross_property
✅ Validates_with_property
```
### ✅ <a id="user-content-r0s24" href="#r0s24">FluentValidation.Tests.GreaterThanValidatorTester</a>
### ✅ <a id="user-content-r0s24" href="#user-content-r0s24">FluentValidation.Tests.GreaterThanValidatorTester</a>
```
✅ Comparison_property_uses_custom_resolver
✅ Comparison_Type
@@ -502,7 +502,7 @@
✅ Validates_with_nullable_when_property_not_null_cross_property
✅ Validates_with_property
```
### ✅ <a id="user-content-r0s25" href="#r0s25">FluentValidation.Tests.InclusiveBetweenValidatorTests</a>
### ✅ <a id="user-content-r0s25" href="#user-content-r0s25">FluentValidation.Tests.InclusiveBetweenValidatorTests</a>
```
✅ To_and_from_properties_should_be_set
✅ To_and_from_properties_should_be_set_for_strings
@@ -523,7 +523,7 @@
✅ When_the_value_is_smaller_than_the_range_then_the_validator_should_fail
✅ When_the_value_is_smaller_than_the_range_then_the_validator_should_fail_for_strings
```
### ✅ <a id="user-content-r0s26" href="#r0s26">FluentValidation.Tests.InheritanceValidatorTest</a>
### ✅ <a id="user-content-r0s26" href="#user-content-r0s26">FluentValidation.Tests.InheritanceValidatorTest</a>
```
✅ Can_use_custom_subclass_with_nongeneric_overload
✅ Validates_collection
@@ -537,11 +537,11 @@
✅ Validates_with_callback_accepting_derived_async
✅ Validates_with_callback_async
```
### ✅ <a id="user-content-r0s27" href="#r0s27">FluentValidation.Tests.InlineValidatorTester</a>
### ✅ <a id="user-content-r0s27" href="#user-content-r0s27">FluentValidation.Tests.InlineValidatorTester</a>
```
✅ Uses_inline_validator_to_build_rules
```
### ✅ <a id="user-content-r0s28" href="#r0s28">FluentValidation.Tests.LanguageManagerTests</a>
### ✅ <a id="user-content-r0s28" href="#user-content-r0s28">FluentValidation.Tests.LanguageManagerTests</a>
```
✅ All_languages_should_be_loaded
✅ All_localizations_have_same_parameters_as_English
@@ -565,7 +565,7 @@
✅ Gets_translation_for_specific_culture
✅ Uses_error_code_as_localization_key
```
### ✅ <a id="user-content-r0s29" href="#r0s29">FluentValidation.Tests.LengthValidatorTests</a>
### ✅ <a id="user-content-r0s29" href="#user-content-r0s29">FluentValidation.Tests.LengthValidatorTests</a>
```
✅ Min_and_max_properties_should_be_set
✅ When_input_is_null_then_the_validator_should_pass
@@ -584,7 +584,7 @@
✅ When_the_text_is_smaller_than_the_range_then_the_validator_should_fail
✅ When_the_validator_fails_the_error_message_should_be_set
```
### ✅ <a id="user-content-r0s30" href="#r0s30">FluentValidation.Tests.LessThanOrEqualToValidatorTester</a>
### ✅ <a id="user-content-r0s30" href="#user-content-r0s30">FluentValidation.Tests.LessThanOrEqualToValidatorTester</a>
```
✅ Comparison_property_uses_custom_resolver
✅ Comparison_type
@@ -600,7 +600,7 @@
✅ Validates_with_nullable_when_property_not_null_cross_property
✅ Validates_with_property
```
### ✅ <a id="user-content-r0s31" href="#r0s31">FluentValidation.Tests.LessThanValidatorTester</a>
### ✅ <a id="user-content-r0s31" href="#user-content-r0s31">FluentValidation.Tests.LessThanValidatorTester</a>
```
✅ Comparison_property_uses_custom_resolver
✅ Comparison_type
@@ -619,7 +619,7 @@
✅ Validates_with_nullable_when_property_not_null_cross_property
✅ Validates_with_nullable_when_property_null_cross_property
```
### ✅ <a id="user-content-r0s32" href="#r0s32">FluentValidation.Tests.LocalisedMessagesTester</a>
### ✅ <a id="user-content-r0s32" href="#user-content-r0s32">FluentValidation.Tests.LocalisedMessagesTester</a>
```
✅ Correctly_assigns_default_localized_error_message
✅ Does_not_throw_InvalidCastException_when_using_RuleForEach
@@ -628,12 +628,12 @@
✅ Uses_func_to_get_message
✅ Uses_string_format_with_property_value
```
### ✅ <a id="user-content-r0s33" href="#r0s33">FluentValidation.Tests.LocalisedNameTester</a>
### ✅ <a id="user-content-r0s33" href="#user-content-r0s33">FluentValidation.Tests.LocalisedNameTester</a>
```
✅ Uses_localized_name
✅ Uses_localized_name_expression
```
### ✅ <a id="user-content-r0s34" href="#r0s34">FluentValidation.Tests.MemberAccessorTests</a>
### ✅ <a id="user-content-r0s34" href="#user-content-r0s34">FluentValidation.Tests.MemberAccessorTests</a>
```
✅ ComplexPropertyGet
✅ ComplexPropertySet
@@ -645,7 +645,7 @@
✅ SimplePropertyGet
✅ SimplePropertySet
```
### ✅ <a id="user-content-r0s35" href="#r0s35">FluentValidation.Tests.MessageFormatterTests</a>
### ✅ <a id="user-content-r0s35" href="#user-content-r0s35">FluentValidation.Tests.MessageFormatterTests</a>
```
✅ Adds_argument_and_custom_arguments
✅ Adds_formatted_argument_and_custom_arguments
@@ -658,18 +658,18 @@
✅ Understands_date_formats
✅ Understands_numeric_formats
```
### ✅ <a id="user-content-r0s36" href="#r0s36">FluentValidation.Tests.ModelLevelValidatorTests</a>
### ✅ <a id="user-content-r0s36" href="#user-content-r0s36">FluentValidation.Tests.ModelLevelValidatorTests</a>
```
✅ Can_use_child_validator_at_model_level
✅ Validates_at_model_level
```
### ✅ <a id="user-content-r0s37" href="#r0s37">FluentValidation.Tests.NameResolutionPluggabilityTester</a>
### ✅ <a id="user-content-r0s37" href="#user-content-r0s37">FluentValidation.Tests.NameResolutionPluggabilityTester</a>
```
✅ Resolves_nested_properties
✅ ShouldHaveValidationError_Should_support_custom_propertynameresolver
✅ Uses_custom_property_name
```
### ✅ <a id="user-content-r0s38" href="#r0s38">FluentValidation.Tests.NotEmptyTester</a>
### ✅ <a id="user-content-r0s38" href="#user-content-r0s38">FluentValidation.Tests.NotEmptyTester</a>
```
✅ Fails_for_array
✅ Fails_for_ienumerable_that_doesnt_implement_ICollection
@@ -682,7 +682,7 @@
✅ When_value_is_null_validator_should_fail
✅ When_value_is_whitespace_validation_should_fail
```
### ✅ <a id="user-content-r0s39" href="#r0s39">FluentValidation.Tests.NotEqualValidatorTests</a>
### ✅ <a id="user-content-r0s39" href="#user-content-r0s39">FluentValidation.Tests.NotEqualValidatorTests</a>
```
✅ Comparison_property_uses_custom_resolver
✅ Should_handle_custom_value_types_correctly
@@ -696,7 +696,7 @@
✅ When_the_objects_are_not_equal_then_the_validator_should_pass
✅ When_the_validator_fails_the_error_message_should_be_set
```
### ✅ <a id="user-content-r0s40" href="#r0s40">FluentValidation.Tests.NotNullTester</a>
### ✅ <a id="user-content-r0s40" href="#user-content-r0s40">FluentValidation.Tests.NotNullTester</a>
```
✅ Fails_when_nullable_value_type_is_null
✅ Not_null_validator_should_not_crash_with_non_nullable_value_type
@@ -704,7 +704,7 @@
✅ NotNullValidator_should_pass_if_value_has_value
✅ When_the_validator_fails_the_error_message_should_be_set
```
### ✅ <a id="user-content-r0s41" href="#r0s41">FluentValidation.Tests.NullTester</a>
### ✅ <a id="user-content-r0s41" href="#user-content-r0s41">FluentValidation.Tests.NullTester</a>
```
✅ Not_null_validator_should_not_crash_with_non_nullable_value_type
✅ NullValidator_should_fail_if_value_has_value
@@ -712,7 +712,7 @@
✅ Passes_when_nullable_value_type_is_null
✅ When_the_validator_passes_the_error_message_should_be_set
```
### ✅ <a id="user-content-r0s42" href="#r0s42">FluentValidation.Tests.OnFailureTests</a>
### ✅ <a id="user-content-r0s42" href="#user-content-r0s42">FluentValidation.Tests.OnFailureTests</a>
```
✅ OnFailure_called_for_each_failed_rule
✅ OnFailure_called_for_each_failed_rule_asyncAsync
@@ -725,7 +725,7 @@
✅ WhenWithOnFailure_should_invoke_condition_on_async_inner_validator
✅ WhenWithOnFailure_should_invoke_condition_on_inner_validator
```
### ✅ <a id="user-content-r0s43" href="#r0s43">FluentValidation.Tests.PredicateValidatorTester</a>
### ✅ <a id="user-content-r0s43" href="#user-content-r0s43">FluentValidation.Tests.PredicateValidatorTester</a>
```
✅ Should_fail_when_predicate_returns_false
✅ Should_succeed_when_predicate_returns_true
@@ -733,7 +733,7 @@
✅ When_validation_fails_metadata_should_be_set_on_failure
✅ When_validation_fails_the_default_error_should_be_set
```
### ✅ <a id="user-content-r0s44" href="#r0s44">FluentValidation.Tests.PropertyChainTests</a>
### ✅ <a id="user-content-r0s44" href="#user-content-r0s44">FluentValidation.Tests.PropertyChainTests</a>
```
✅ AddIndexer_throws_when_nothing_added
✅ Calling_ToString_should_construct_string_representation_of_chain
@@ -743,7 +743,7 @@
✅ Should_ignore_blanks
✅ Should_not_be_subchain
```
### ✅ <a id="user-content-r0s45" href="#r0s45">FluentValidation.Tests.RegularExpressionValidatorTests</a>
### ✅ <a id="user-content-r0s45" href="#user-content-r0s45">FluentValidation.Tests.RegularExpressionValidatorTests</a>
```
✅ Can_access_expression_in_message
✅ Can_access_expression_in_message_lambda
@@ -761,7 +761,7 @@
✅ When_the_text_matches_the_regular_expression_then_the_validator_should_pass
✅ When_validation_fails_the_default_error_should_be_set
```
### ✅ <a id="user-content-r0s46" href="#r0s46">FluentValidation.Tests.RuleBuilderTests</a>
### ✅ <a id="user-content-r0s46" href="#user-content-r0s46">FluentValidation.Tests.RuleBuilderTests</a>
```
✅ Adding_a_validator_should_return_builder
✅ Adding_a_validator_should_store_validator
@@ -793,7 +793,7 @@
✅ Should_throw_when_inverse_predicate_is_null
✅ Should_throw_when_predicate_is_null
```
### ✅ <a id="user-content-r0s47" href="#r0s47">FluentValidation.Tests.RuleDependencyTests</a>
### ✅ <a id="user-content-r0s47" href="#user-content-r0s47">FluentValidation.Tests.RuleDependencyTests</a>
```
✅ Async_inside_dependent_rules
✅ Async_inside_dependent_rules_when_parent_rule_not_async
@@ -810,7 +810,7 @@
✅ TestAsyncWithDependentRules_SyncEntry
✅ Treats_root_level_RuleFor_call_as_dependent_rule_if_user_forgets_to_use_DependentRulesBuilder
```
### ✅ <a id="user-content-r0s48" href="#r0s48">FluentValidation.Tests.RulesetTests</a>
### ✅ <a id="user-content-r0s48" href="#user-content-r0s48">FluentValidation.Tests.RulesetTests</a>
```
✅ Applies_multiple_rulesets_to_rule
✅ Combines_rulesets_and_explicit_properties
@@ -834,7 +834,7 @@
✅ Trims_spaces
✅ WithMessage_works_inside_rulesets
```
### ✅ <a id="user-content-r0s49" href="#r0s49">FluentValidation.Tests.ScalePrecisionValidatorTests</a>
### ✅ <a id="user-content-r0s49" href="#user-content-r0s49">FluentValidation.Tests.ScalePrecisionValidatorTests</a>
```
✅ Scale_precision_should_be_valid
✅ Scale_precision_should_be_valid_when_ignoring_trailing_zeroes
@@ -843,7 +843,7 @@
✅ Scale_precision_should_not_be_valid_when_ignoring_trailing_zeroes
✅ Scale_precision_should_not_be_valid_when_they_are_equal
```
### ✅ <a id="user-content-r0s50" href="#r0s50">FluentValidation.Tests.SharedConditionTests</a>
### ✅ <a id="user-content-r0s50" href="#user-content-r0s50">FluentValidation.Tests.SharedConditionTests</a>
```
✅ Async_condition_can_be_used_inside_ruleset
✅ Condition_can_be_used_inside_ruleset
@@ -888,11 +888,11 @@
✅ When_condition_only_executed_once
✅ WhenAsync_condition_only_executed_once
```
### ✅ <a id="user-content-r0s51" href="#r0s51">FluentValidation.Tests.StandalonePropertyValidationTester</a>
### ✅ <a id="user-content-r0s51" href="#user-content-r0s51">FluentValidation.Tests.StandalonePropertyValidationTester</a>
```
✅ Should_validate_property_value_without_instance
```
### ✅ <a id="user-content-r0s52" href="#r0s52">FluentValidation.Tests.StringEnumValidatorTests</a>
### ✅ <a id="user-content-r0s52" href="#user-content-r0s52">FluentValidation.Tests.StringEnumValidatorTests</a>
```
✅ IsValidTests_CaseInsensitive_CaseCorrect
✅ IsValidTests_CaseInsensitive_CaseIncorrect
@@ -905,20 +905,20 @@
✅ When_the_property_is_initialized_with_null_then_the_validator_should_be_valid
✅ When_validation_fails_the_default_error_should_be_set
```
### ✅ <a id="user-content-r0s53" href="#r0s53">FluentValidation.Tests.TrackingCollectionTests</a>
### ✅ <a id="user-content-r0s53" href="#user-content-r0s53">FluentValidation.Tests.TrackingCollectionTests</a>
```
✅ Add_AddsItem
✅ Should_not_raise_event_once_handler_detached
✅ When_Item_Added_Raises_ItemAdded
```
### ✅ <a id="user-content-r0s54" href="#r0s54">FluentValidation.Tests.TransformTests</a>
### ✅ <a id="user-content-r0s54" href="#user-content-r0s54">FluentValidation.Tests.TransformTests</a>
```
✅ Transforms_collection_element
✅ Transforms_collection_element_async
✅ Transforms_property_value
✅ Transforms_property_value_to_another_type
```
### ✅ <a id="user-content-r0s55" href="#r0s55">FluentValidation.Tests.UserSeverityTester</a>
### ✅ <a id="user-content-r0s55" href="#user-content-r0s55">FluentValidation.Tests.UserSeverityTester</a>
```
✅ Can_Provide_conditional_severity
✅ Can_Provide_severity_for_item_in_collection
@@ -928,14 +928,14 @@
✅ Stores_user_severity_against_validation_failure
✅ Throws_when_provider_is_null
```
### ✅ <a id="user-content-r0s56" href="#r0s56">FluentValidation.Tests.UserStateTester</a>
### ✅ <a id="user-content-r0s56" href="#user-content-r0s56">FluentValidation.Tests.UserStateTester</a>
```
✅ Can_Provide_state_for_item_in_collection
✅ Correctly_provides_object_being_validated
✅ Stores_user_state_against_validation_failure
✅ Throws_when_provider_is_null
```
### ✅ <a id="user-content-r0s57" href="#r0s57">FluentValidation.Tests.ValidateAndThrowTester</a>
### ✅ <a id="user-content-r0s57" href="#user-content-r0s57">FluentValidation.Tests.ValidateAndThrowTester</a>
```
✅ Does_not_throw_when_valid
✅ Does_not_throw_when_valid_and_a_ruleset
@@ -952,7 +952,7 @@
✅ ValidationException_provides_correct_message_when_appendDefaultMessage_false
✅ ValidationException_provides_correct_message_when_appendDefaultMessage_true
```
### ✅ <a id="user-content-r0s58" href="#r0s58">FluentValidation.Tests.ValidationResultTests</a>
### ✅ <a id="user-content-r0s58" href="#user-content-r0s58">FluentValidation.Tests.ValidationResultTests</a>
```
✅ Can_serialize_failure
✅ Can_serialize_result
@@ -963,7 +963,7 @@
✅ ToString_return_error_messages_with_given_separator
✅ ToString_return_error_messages_with_newline_as_separator
```
### ✅ <a id="user-content-r0s59" href="#r0s59">FluentValidation.Tests.ValidatorDescriptorTester</a>
### ✅ <a id="user-content-r0s59" href="#user-content-r0s59">FluentValidation.Tests.ValidatorDescriptorTester</a>
```
✅ Does_not_throw_when_rule_declared_without_property
✅ Gets_validators_for_property
@@ -971,7 +971,7 @@
✅ Returns_empty_collection_for_property_with_no_validators
✅ Should_retrieve_name_given_to_it_pass_property_as_string
```
### ✅ <a id="user-content-r0s60" href="#r0s60">FluentValidation.Tests.ValidatorSelectorTests</a>
### ✅ <a id="user-content-r0s60" href="#user-content-r0s60">FluentValidation.Tests.ValidatorSelectorTests</a>
```
✅ Can_use_property_with_include
✅ Does_not_validate_other_property
@@ -984,7 +984,7 @@
✅ Validates_nullable_property_with_overriden_name_when_selected
✅ Validates_property_using_expression
```
### ✅ <a id="user-content-r0s61" href="#r0s61">FluentValidation.Tests.ValidatorTesterTester</a>
### ✅ <a id="user-content-r0s61" href="#user-content-r0s61">FluentValidation.Tests.ValidatorTesterTester</a>
```
✅ Allows_only_one_failure_to_match
✅ Can_use_indexer_in_string_message

View File

@@ -0,0 +1,38 @@
![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%206%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/golang-json.json](#user-content-r0)|5 ✅|6 ❌|1 ⚪|6s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/golang-json.json</a>
**12** tests were completed in **6s** with **5** passed, **6** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[_/home/james_t/git/test-reporter/reports/go](#user-content-r0s0)|5 ✅|6 ❌|1 ⚪|6s|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">_/home/james_t/git/test-reporter/reports/go</a>
```
✅ TestPassing
❌ TestFailing
calculator_test.go:19: expected 1+1 = 3, got 2
❌ TestPanicInsideFunction
calculator_test.go:76: caught panic: runtime error: integer divide by zero
❌ TestPanicInsideTest
calculator_test.go:76: caught panic: bad stuff
⚪ TestSkipped
calculator_test.go:45: skipping test
❌ TestCases
TestCases
✅ 1_+_2_=_3
✅ 4_+_7_=_11
❌ 2_+_3_=_4
calculator_test.go:67: expected 2 + 3 = 4, got 5
❌ 1_/_2_=_1
calculator_test.go:67: expected 1 / 2 = 1, got 0
✅ 9_/_3_=_3
✅ 14_/_7_=_2
```

View File

@@ -3,13 +3,13 @@
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/jest-junit-eslint.xml|1 ✅|||0ms|
## ✅ <a id="user-content-r0" href="#r0">fixtures/jest-junit-eslint.xml</a>
|[fixtures/jest-junit-eslint.xml](#user-content-r0)|1 ✅|||0ms|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/jest-junit-eslint.xml</a>
**1** tests were completed in **0ms** with **1** passed, **0** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[test.jsx](#r0s0)|1 ✅|||0ms|
### ✅ <a id="user-content-r0s0" href="#r0s0">test.jsx</a>
|[test.jsx](#user-content-r0s0)|1 ✅|||0ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">test.jsx</a>
```
test
✅ test.jsx

View File

@@ -1,14 +1,14 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%204%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/jest-junit.xml|1 ✅|4 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#r0">fixtures/jest-junit.xml</a>
|[fixtures/jest-junit.xml](#user-content-r0)|1 ✅|4 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#user-content-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>
|[__tests__\main.test.js](#user-content-r0s0)|1 ✅|3 ❌||486ms|
|[__tests__\second.test.js](#user-content-r0s1)||1 ❌|1 ⚪|82ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">__tests__\main.test.js</a>
```
Test 1
✅ Passing test
@@ -21,7 +21,7 @@ Test 2
❌ Exception in test
Error: Some error
```
### ❌ <a id="user-content-r0s1" href="#r0s1">__tests__\second.test.js</a>
### ❌ <a id="user-content-r0s1" href="#user-content-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:

View File

@@ -3,13 +3,13 @@
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/external/jest/jest-react-component-test-results.xml|1 ✅|||1000ms|
## ✅ <a id="user-content-r0" href="#r0">fixtures/external/jest/jest-react-component-test-results.xml</a>
|[fixtures/external/jest/jest-react-component-test-results.xml](#user-content-r0)|1 ✅|||1000ms|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/external/jest/jest-react-component-test-results.xml</a>
**1** tests were completed in **1000ms** with **1** passed, **0** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[\<Component /\>](#r0s0)|1 ✅|||798ms|
### ✅ <a id="user-content-r0s0" href="#r0s0">\<Component /\></a>
|[\<Component /\>](#user-content-r0s0)|1 ✅|||798ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">\<Component /\></a>
```
✅ <Component /> should render properly
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
![Tests failed](https://img.shields.io/badge/tests-1%20failed-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/junit-with-message.xml||1 ❌||1ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/junit-with-message.xml</a>
|[fixtures/junit-with-message.xml](#user-content-r0)||1 ❌||1ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/junit-with-message.xml</a>
**1** tests were completed in **1ms** with **0** passed, **1** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[Test](#r0s0)||1 ❌||1ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">Test</a>
|[Test](#user-content-r0s0)||1 ❌||1ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">Test</a>
```
Fails
❌ Test

View File

@@ -1,14 +1,14 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%204%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/mocha-json.json|1 ✅|4 ❌|1 ⚪|12ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/mocha-json.json</a>
|[fixtures/mocha-json.json](#user-content-r0)|1 ✅|4 ❌|1 ⚪|12ms|
## ❌ <a id="user-content-r0" href="#user-content-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/main.test.js](#user-content-r0s0)|1 ✅|3 ❌||1ms|
|[test/second.test.js](#user-content-r0s1)||1 ❌|1 ⚪|8ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">test/main.test.js</a>
```
Test 1
✅ Passing test
@@ -24,7 +24,7 @@ Test 2
❌ Exception in test
Some error
```
### ❌ <a id="user-content-r0s1" href="#r0s1">test/second.test.js</a>
### ❌ <a id="user-content-r0s1" href="#user-content-r0s1">test/second.test.js</a>
```
⚪ Skipped test
❌ Timeout test

View File

@@ -3,48 +3,48 @@
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/external/mocha/mocha-test-results.json|833 ✅||6 ⚪|6s|
## ✅ <a id="user-content-r0" href="#r0">fixtures/external/mocha/mocha-test-results.json</a>
|[fixtures/external/mocha/mocha-test-results.json](#user-content-r0)|833 ✅||6 ⚪|6s|
## ✅ <a id="user-content-r0" href="#user-content-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](#r0s0)|14 ✅|||8ms|
|[test/node-unit/cli/config.spec.js](#r0s1)|10 ✅|||8ms|
|[test/node-unit/cli/node-flags.spec.js](#r0s2)|105 ✅|||9ms|
|[test/node-unit/cli/options.spec.js](#r0s3)|36 ✅|||250ms|
|[test/node-unit/cli/run-helpers.spec.js](#r0s4)|9 ✅|||8ms|
|[test/node-unit/cli/run.spec.js](#r0s5)|40 ✅|||4ms|
|[test/node-unit/mocha.spec.js](#r0s6)|24 ✅|||33ms|
|[test/node-unit/parallel-buffered-runner.spec.js](#r0s7)|19 ✅|||23ms|
|[test/node-unit/reporters/parallel-buffered.spec.js](#r0s8)|6 ✅|||16ms|
|[test/node-unit/serializer.spec.js](#r0s9)|40 ✅|||31ms|
|[test/node-unit/stack-trace-filter.spec.js](#r0s10)|2 ✅||4 ⚪|1ms|
|[test/node-unit/utils.spec.js](#r0s11)|5 ✅|||1ms|
|[test/node-unit/worker.spec.js](#r0s12)|15 ✅|||92ms|
|[test/unit/context.spec.js](#r0s13)|8 ✅|||5ms|
|[test/unit/duration.spec.js](#r0s14)|3 ✅|||166ms|
|[test/unit/errors.spec.js](#r0s15)|13 ✅|||5ms|
|[test/unit/globals.spec.js](#r0s16)|4 ✅|||0ms|
|[test/unit/grep.spec.js](#r0s17)|8 ✅|||2ms|
|[test/unit/hook-async.spec.js](#r0s18)|3 ✅|||1ms|
|[test/unit/hook-sync-nested.spec.js](#r0s19)|4 ✅|||1ms|
|[test/unit/hook-sync.spec.js](#r0s20)|3 ✅|||0ms|
|[test/unit/hook-timeout.spec.js](#r0s21)|1 ✅|||0ms|
|[test/unit/hook.spec.js](#r0s22)|4 ✅|||0ms|
|[test/unit/mocha.spec.js](#r0s23)|115 ✅||1 ⚪|128ms|
|[test/unit/overspecified-async.spec.js](#r0s24)|1 ✅|||3ms|
|[test/unit/parse-query.spec.js](#r0s25)|2 ✅|||1ms|
|[test/unit/plugin-loader.spec.js](#r0s26)|41 ✅||1 ⚪|16ms|
|[test/unit/required-tokens.spec.js](#r0s27)|1 ✅|||0ms|
|[test/unit/root.spec.js](#r0s28)|1 ✅|||0ms|
|[test/unit/runnable.spec.js](#r0s29)|55 ✅|||122ms|
|[test/unit/runner.spec.js](#r0s30)|77 ✅|||43ms|
|[test/unit/suite.spec.js](#r0s31)|57 ✅|||14ms|
|[test/unit/test.spec.js](#r0s32)|15 ✅|||0ms|
|[test/unit/throw.spec.js](#r0s33)|9 ✅|||9ms|
|[test/unit/timeout.spec.js](#r0s34)|8 ✅|||109ms|
|[test/unit/utils.spec.js](#r0s35)|75 ✅|||24ms|
### ✅ <a id="user-content-r0s0" href="#r0s0">test/node-unit/buffered-worker-pool.spec.js</a>
|[test/node-unit/buffered-worker-pool.spec.js](#user-content-r0s0)|14 ✅|||8ms|
|[test/node-unit/cli/config.spec.js](#user-content-r0s1)|10 ✅|||8ms|
|[test/node-unit/cli/node-flags.spec.js](#user-content-r0s2)|105 ✅|||9ms|
|[test/node-unit/cli/options.spec.js](#user-content-r0s3)|36 ✅|||250ms|
|[test/node-unit/cli/run-helpers.spec.js](#user-content-r0s4)|9 ✅|||8ms|
|[test/node-unit/cli/run.spec.js](#user-content-r0s5)|40 ✅|||4ms|
|[test/node-unit/mocha.spec.js](#user-content-r0s6)|24 ✅|||33ms|
|[test/node-unit/parallel-buffered-runner.spec.js](#user-content-r0s7)|19 ✅|||23ms|
|[test/node-unit/reporters/parallel-buffered.spec.js](#user-content-r0s8)|6 ✅|||16ms|
|[test/node-unit/serializer.spec.js](#user-content-r0s9)|40 ✅|||31ms|
|[test/node-unit/stack-trace-filter.spec.js](#user-content-r0s10)|2 ✅||4 ⚪|1ms|
|[test/node-unit/utils.spec.js](#user-content-r0s11)|5 ✅|||1ms|
|[test/node-unit/worker.spec.js](#user-content-r0s12)|15 ✅|||92ms|
|[test/unit/context.spec.js](#user-content-r0s13)|8 ✅|||5ms|
|[test/unit/duration.spec.js](#user-content-r0s14)|3 ✅|||166ms|
|[test/unit/errors.spec.js](#user-content-r0s15)|13 ✅|||5ms|
|[test/unit/globals.spec.js](#user-content-r0s16)|4 ✅|||0ms|
|[test/unit/grep.spec.js](#user-content-r0s17)|8 ✅|||2ms|
|[test/unit/hook-async.spec.js](#user-content-r0s18)|3 ✅|||1ms|
|[test/unit/hook-sync-nested.spec.js](#user-content-r0s19)|4 ✅|||1ms|
|[test/unit/hook-sync.spec.js](#user-content-r0s20)|3 ✅|||0ms|
|[test/unit/hook-timeout.spec.js](#user-content-r0s21)|1 ✅|||0ms|
|[test/unit/hook.spec.js](#user-content-r0s22)|4 ✅|||0ms|
|[test/unit/mocha.spec.js](#user-content-r0s23)|115 ✅||1 ⚪|128ms|
|[test/unit/overspecified-async.spec.js](#user-content-r0s24)|1 ✅|||3ms|
|[test/unit/parse-query.spec.js](#user-content-r0s25)|2 ✅|||1ms|
|[test/unit/plugin-loader.spec.js](#user-content-r0s26)|41 ✅||1 ⚪|16ms|
|[test/unit/required-tokens.spec.js](#user-content-r0s27)|1 ✅|||0ms|
|[test/unit/root.spec.js](#user-content-r0s28)|1 ✅|||0ms|
|[test/unit/runnable.spec.js](#user-content-r0s29)|55 ✅|||122ms|
|[test/unit/runner.spec.js](#user-content-r0s30)|77 ✅|||43ms|
|[test/unit/suite.spec.js](#user-content-r0s31)|57 ✅|||14ms|
|[test/unit/test.spec.js](#user-content-r0s32)|15 ✅|||0ms|
|[test/unit/throw.spec.js](#user-content-r0s33)|9 ✅|||9ms|
|[test/unit/timeout.spec.js](#user-content-r0s34)|8 ✅|||109ms|
|[test/unit/utils.spec.js](#user-content-r0s35)|75 ✅|||24ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">test/node-unit/buffered-worker-pool.spec.js</a>
```
class BufferedWorkerPool constructor
✅ should apply defaults
@@ -73,7 +73,7 @@ class BufferedWorkerPool static method serializeOptions() when called multiple t
class BufferedWorkerPool static method serializeOptions() when passed no arguments
✅ should not throw
```
### ✅ <a id="user-content-r0s1" href="#r0s1">test/node-unit/cli/config.spec.js</a>
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">test/node-unit/cli/config.spec.js</a>
```
cli/config findConfig()
✅ should look for one of the config files using findup-sync
@@ -95,7 +95,7 @@ cli/config loadConfig() when parsing succeeds when supplied a filepath with ".ym
cli/config loadConfig() when supplied a filepath with unsupported extension
✅ should use the JSON parser
```
### ✅ <a id="user-content-r0s2" href="#r0s2">test/node-unit/cli/node-flags.spec.js</a>
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">test/node-unit/cli/node-flags.spec.js</a>
```
node-flags impliesNoTimeouts()
✅ should return true for inspect flags
@@ -209,7 +209,7 @@ node-flags unparseNodeFlags()
✅ should handle multiple v8 flags
✅ should handle single v8 flags
```
### ✅ <a id="user-content-r0s3" href="#r0s3">test/node-unit/cli/options.spec.js</a>
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">test/node-unit/cli/options.spec.js</a>
```
options loadOptions() "extension" handling when user does not supply "extension" option
✅ should retain the default
@@ -268,7 +268,7 @@ options loadOptions() when parameter provided rc file when path to config (`--co
✅ should not look for a config
✅ should throw to warn the user
```
### ✅ <a id="user-content-r0s4" href="#r0s4">test/node-unit/cli/run-helpers.spec.js</a>
### ✅ <a id="user-content-r0s4" href="#user-content-r0s4">test/node-unit/cli/run-helpers.spec.js</a>
```
helpers list() when given a comma-delimited string
✅ should return a flat array
@@ -287,7 +287,7 @@ helpers validateLegacyPlugin() when used with an "interfaces" key
helpers validateLegacyPlugin() when used with an unknown plugin type
✅ should fail
```
### ✅ <a id="user-content-r0s5" href="#r0s5">test/node-unit/cli/run.spec.js</a>
### ✅ <a id="user-content-r0s5" href="#user-content-r0s5">test/node-unit/cli/run.spec.js</a>
```
command run builder array type
✅ should include option extension
@@ -334,7 +334,7 @@ command run builder string type
✅ should include option timeout
✅ should include option ui
```
### ✅ <a id="user-content-r0s6" href="#r0s6">test/node-unit/mocha.spec.js</a>
### ✅ <a id="user-content-r0s6" href="#user-content-r0s6">test/node-unit/mocha.spec.js</a>
```
Mocha instance method addFile()
✅ should add the given file to the files array
@@ -378,7 +378,7 @@ Mocha instance method unloadFiles()
Mocha static method unloadFile()
✅ should unload a specific file from cache
```
### ✅ <a id="user-content-r0s7" href="#r0s7">test/node-unit/parallel-buffered-runner.spec.js</a>
### ✅ <a id="user-content-r0s7" href="#user-content-r0s7">test/node-unit/parallel-buffered-runner.spec.js</a>
```
parallel-buffered-runner ParallelBufferedRunner constructor
✅ should start in "IDLE" state
@@ -416,7 +416,7 @@ parallel-buffered-runner ParallelBufferedRunner instance method workerReporter()
parallel-buffered-runner ParallelBufferedRunner instance property _state
✅ should disallow an invalid state transition
```
### ✅ <a id="user-content-r0s8" href="#r0s8">test/node-unit/reporters/parallel-buffered.spec.js</a>
### ✅ <a id="user-content-r0s8" href="#user-content-r0s8">test/node-unit/reporters/parallel-buffered.spec.js</a>
```
ParallelBuffered constructor
✅ should listen for Runner events
@@ -429,7 +429,7 @@ ParallelBuffered instance method done
✅ should execute its callback with a SerializableWorkerResult
✅ should reset its `events` prop
```
### ✅ <a id="user-content-r0s9" href="#r0s9">test/node-unit/serializer.spec.js</a>
### ✅ <a id="user-content-r0s9" href="#user-content-r0s9">test/node-unit/serializer.spec.js</a>
```
serializer function deserialize when passed a non-object value
✅ should return the value
@@ -505,7 +505,7 @@ serializer SerializableWorkerResult static method isSerializedWorkerResult when
serializer SerializableWorkerResult static method isSerializedWorkerResult when passed an object without an appropriate `__type` prop
✅ should return `false`
```
### ✅ <a id="user-content-r0s10" href="#r0s10">test/node-unit/stack-trace-filter.spec.js</a>
### ✅ <a id="user-content-r0s10" href="#user-content-r0s10">test/node-unit/stack-trace-filter.spec.js</a>
```
stackTraceFilter() on browser
✅ does not strip out other bower_components
@@ -517,7 +517,7 @@ stackTraceFilter() on node on POSIX OS
stackTraceFilter() on node on Windows
✅ should work on Windows
```
### ✅ <a id="user-content-r0s11" href="#r0s11">test/node-unit/utils.spec.js</a>
### ✅ <a id="user-content-r0s11" href="#user-content-r0s11">test/node-unit/utils.spec.js</a>
```
utils function canonicalType()
✅ should return "asyncfunction" if the parameter is an async function
@@ -528,7 +528,7 @@ utils function type()
✅ should return "error" if the parameter is an Error
✅ should return "function" if the parameter is an async function
```
### ✅ <a id="user-content-r0s12" href="#r0s12">test/node-unit/worker.spec.js</a>
### ✅ <a id="user-content-r0s12" href="#user-content-r0s12">test/node-unit/worker.spec.js</a>
```
worker when run as main process
✅ should throw
@@ -557,7 +557,7 @@ worker when run as worker process function run() when the file at "filepath" is
worker when run as worker process function run() when the file at "filepath" is loadable when serialization succeeds
✅ should resolve with a SerializedWorkerResult
```
### ✅ <a id="user-content-r0s13" href="#r0s13">test/unit/context.spec.js</a>
### ✅ <a id="user-content-r0s13" href="#user-content-r0s13">test/unit/context.spec.js</a>
```
Context nested
✅ should work
@@ -574,7 +574,7 @@ methods slow()
methods timeout()
✅ should return the timeout
```
### ✅ <a id="user-content-r0s14" href="#r0s14">test/unit/duration.spec.js</a>
### ✅ <a id="user-content-r0s14" href="#user-content-r0s14">test/unit/duration.spec.js</a>
```
durations when fast
✅ should not highlight
@@ -583,7 +583,7 @@ durations when reasonable
durations when slow
✅ should highlight in red
```
### ✅ <a id="user-content-r0s15" href="#r0s15">test/unit/errors.spec.js</a>
### ✅ <a id="user-content-r0s15" href="#user-content-r0s15">test/unit/errors.spec.js</a>
```
Errors createForbiddenExclusivityError() when Mocha instance is not running in a worker process
✅ should output a message regarding --forbid-only
@@ -608,7 +608,7 @@ Errors warn()
✅ should ignore falsy messages
✅ should not cache messages
```
### ✅ <a id="user-content-r0s16" href="#r0s16">test/unit/globals.spec.js</a>
### ✅ <a id="user-content-r0s16" href="#user-content-r0s16">test/unit/globals.spec.js</a>
```
global leaks
✅ should cause tests to fail
@@ -616,7 +616,7 @@ global leaks
✅ should pass when prefixed "mocha-"
✅ should pass with wildcard
```
### ✅ <a id="user-content-r0s17" href="#r0s17">test/unit/grep.spec.js</a>
### ✅ <a id="user-content-r0s17" href="#user-content-r0s17">test/unit/grep.spec.js</a>
```
Mocha .grep()
✅ should add a RegExp to the mocha.options object
@@ -631,14 +631,14 @@ Mocha "grep" option
Mocha "invert" option
✅ should add a Boolean to the mocha.options object
```
### ✅ <a id="user-content-r0s18" href="#r0s18">test/unit/hook-async.spec.js</a>
### ✅ <a id="user-content-r0s18" href="#user-content-r0s18">test/unit/hook-async.spec.js</a>
```
async hooks
✅ one
✅ three
✅ two
```
### ✅ <a id="user-content-r0s19" href="#r0s19">test/unit/hook-sync-nested.spec.js</a>
### ✅ <a id="user-content-r0s19" href="#user-content-r0s19">test/unit/hook-sync-nested.spec.js</a>
```
serial nested
✅ bar
@@ -647,19 +647,19 @@ serial nested hooks
✅ one
✅ two
```
### ✅ <a id="user-content-r0s20" href="#r0s20">test/unit/hook-sync.spec.js</a>
### ✅ <a id="user-content-r0s20" href="#user-content-r0s20">test/unit/hook-sync.spec.js</a>
```
serial hooks
✅ one
✅ three
✅ two
```
### ✅ <a id="user-content-r0s21" href="#r0s21">test/unit/hook-timeout.spec.js</a>
### ✅ <a id="user-content-r0s21" href="#user-content-r0s21">test/unit/hook-timeout.spec.js</a>
```
hook timeout
✅ should work
```
### ✅ <a id="user-content-r0s22" href="#r0s22">test/unit/hook.spec.js</a>
### ✅ <a id="user-content-r0s22" href="#user-content-r0s22">test/unit/hook.spec.js</a>
```
Hook error
✅ should get the hook._error when called without arguments
@@ -668,7 +668,7 @@ Hook reset
✅ should call Runnable.reset
✅ should reset the error state
```
### ✅ <a id="user-content-r0s23" href="#r0s23">test/unit/mocha.spec.js</a>
### ✅ <a id="user-content-r0s23" href="#user-content-r0s23">test/unit/mocha.spec.js</a>
```
Mocha constructor
✅ should set _cleanReferencesAfterRun to true
@@ -868,18 +868,18 @@ Mocha instance method runGlobalTeardown() when fixture(s) are present
Mocha instance method unloadFile() when run in a browser
✅ should throw
```
### ✅ <a id="user-content-r0s24" href="#r0s24">test/unit/overspecified-async.spec.js</a>
### ✅ <a id="user-content-r0s24" href="#user-content-r0s24">test/unit/overspecified-async.spec.js</a>
```
overspecified asynchronous resolution method
✅ should fail when multiple methods are used
```
### ✅ <a id="user-content-r0s25" href="#r0s25">test/unit/parse-query.spec.js</a>
### ✅ <a id="user-content-r0s25" href="#user-content-r0s25">test/unit/parse-query.spec.js</a>
```
parseQuery()
✅ should get queryString and return key-value object
✅ should parse "+" as a space
```
### ✅ <a id="user-content-r0s26" href="#r0s26">test/unit/plugin-loader.spec.js</a>
### ✅ <a id="user-content-r0s26" href="#user-content-r0s26">test/unit/plugin-loader.spec.js</a>
```
plugin module class PluginLoader constructor when passed custom plugins
✅ should register the custom plugins
@@ -958,17 +958,17 @@ plugin module root hooks plugin 🎣 when impl is an array
plugin module root hooks plugin 🎣 when impl is an object of functions
⚪ should pass validation
```
### ✅ <a id="user-content-r0s27" href="#r0s27">test/unit/required-tokens.spec.js</a>
### ✅ <a id="user-content-r0s27" href="#user-content-r0s27">test/unit/required-tokens.spec.js</a>
```
using imported describe
✅ using imported it
```
### ✅ <a id="user-content-r0s28" href="#r0s28">test/unit/root.spec.js</a>
### ✅ <a id="user-content-r0s28" href="#user-content-r0s28">test/unit/root.spec.js</a>
```
root
✅ should be a valid suite
```
### ✅ <a id="user-content-r0s29" href="#r0s29">test/unit/runnable.spec.js</a>
### ✅ <a id="user-content-r0s29" href="#user-content-r0s29">test/unit/runnable.spec.js</a>
```
Runnable(title, fn) .run(fn) if async
✅ this.skip() should halt synchronous execution
@@ -1069,7 +1069,7 @@ Runnable(title, fn) when arity >= 1
✅ should be .async
✅ should not be .sync
```
### ✅ <a id="user-content-r0s30" href="#r0s30">test/unit/runner.spec.js</a>
### ✅ <a id="user-content-r0s30" href="#user-content-r0s30">test/unit/runner.spec.js</a>
```
Runner instance method _uncaught() when called with a non-Runner context
✅ should throw
@@ -1185,7 +1185,7 @@ Runner instance method uncaught() when provided an object argument when argument
Runner instance method workerReporter()
✅ should throw
```
### ✅ <a id="user-content-r0s31" href="#r0s31">test/unit/suite.spec.js</a>
### ✅ <a id="user-content-r0s31" href="#user-content-r0s31">test/unit/suite.spec.js</a>
```
Suite instance method addSuite()
✅ adds the suite to the suites collection
@@ -1278,7 +1278,7 @@ Test initialization
✅ should not throw if the title is a string
✅ should throw an error if the title isn't a string
```
### ✅ <a id="user-content-r0s32" href="#r0s32">test/unit/test.spec.js</a>
### ✅ <a id="user-content-r0s32" href="#user-content-r0s32">test/unit/test.spec.js</a>
```
Test .clone()
✅ should add/keep the retriedTest value
@@ -1300,7 +1300,7 @@ Test .reset()
✅ should call Runnable.reset
✅ should reset the run state
```
### ✅ <a id="user-content-r0s33" href="#r0s33">test/unit/throw.spec.js</a>
### ✅ <a id="user-content-r0s33" href="#user-content-r0s33">test/unit/throw.spec.js</a>
```
a test that throws non-extensible
✅ should not pass if throwing async and test is async
@@ -1315,7 +1315,7 @@ a test that throws undefined
✅ should not pass if throwing sync and test is async
✅ should not pass if throwing sync and test is sync
```
### ✅ <a id="user-content-r0s34" href="#r0s34">test/unit/timeout.spec.js</a>
### ✅ <a id="user-content-r0s34" href="#user-content-r0s34">test/unit/timeout.spec.js</a>
```
timeouts
✅ should allow overriding per-test
@@ -1333,7 +1333,7 @@ timeouts disabling using beforeEach
timeouts disabling using timeout(0)
✅ should suppress timeout(4)
```
### ✅ <a id="user-content-r0s35" href="#r0s35">test/unit/utils.spec.js</a>
### ✅ <a id="user-content-r0s35" href="#user-content-r0s35">test/unit/utils.spec.js</a>
```
lib/utils canonicalType()
✅ should recognize various types

View File

@@ -1,28 +1,28 @@
![Tests failed](https://img.shields.io/badge/tests-268%20passed%2C%201%20failed-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/external/flutter/provider-test-results.json|268 ✅|1 ❌||0ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/external/flutter/provider-test-results.json</a>
|[fixtures/external/flutter/provider-test-results.json](#user-content-r0)|268 ✅|1 ❌||0ms|
## ❌ <a id="user-content-r0" href="#user-content-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|
|:---|---:|---:|---:|---:|
|[test/builder_test.dart](#r0s0)|24 ✅|||402ms|
|[test/change_notifier_provider_test.dart](#r0s1)|10 ✅|||306ms|
|[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 ✅|||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|
|[test/provider_test.dart](#r0s9)|11 ✅|||306ms|
|[test/proxy_provider_test.dart](#r0s10)|16 ✅|||438ms|
|[test/reassemble_test.dart](#r0s11)|3 ✅|||221ms|
|[test/selector_test.dart](#r0s12)|17 ✅|||364ms|
|[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>
|[test/builder_test.dart](#user-content-r0s0)|24 ✅|||402ms|
|[test/change_notifier_provider_test.dart](#user-content-r0s1)|10 ✅|||306ms|
|[test/consumer_test.dart](#user-content-r0s2)|18 ✅|||340ms|
|[test/context_test.dart](#user-content-r0s3)|31 ✅|||698ms|
|[test/future_provider_test.dart](#user-content-r0s4)|10 ✅|||305ms|
|[test/inherited_provider_test.dart](#user-content-r0s5)|81 ✅|||1s|
|[test/listenable_provider_test.dart](#user-content-r0s6)|16 ✅|||353ms|
|[test/listenable_proxy_provider_test.dart](#user-content-r0s7)|12 ✅|||373ms|
|[test/multi_provider_test.dart](#user-content-r0s8)|3 ✅|||198ms|
|[test/provider_test.dart](#user-content-r0s9)|11 ✅|||306ms|
|[test/proxy_provider_test.dart](#user-content-r0s10)|16 ✅|||438ms|
|[test/reassemble_test.dart](#user-content-r0s11)|3 ✅|||221ms|
|[test/selector_test.dart](#user-content-r0s12)|17 ✅|||364ms|
|[test/stateful_provider_test.dart](#user-content-r0s13)|4 ✅|||254ms|
|[test/stream_provider_test.dart](#user-content-r0s14)|8 ✅|||282ms|
|[test/value_listenable_provider_test.dart](#user-content-r0s15)|4 ✅|1 ❌||327ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">test/builder_test.dart</a>
```
ChangeNotifierProvider
✅ default
@@ -54,7 +54,7 @@ MultiProvider
✅ with ProxyProvider5
✅ with ProxyProvider6
```
### ✅ <a id="user-content-r0s1" href="#r0s1">test/change_notifier_provider_test.dart</a>
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">test/change_notifier_provider_test.dart</a>
```
✅ Use builder property, not child
ChangeNotifierProvider
@@ -68,7 +68,7 @@ ChangeNotifierProvider
✅ builder6
✅ builder0
```
### ✅ <a id="user-content-r0s2" href="#r0s2">test/consumer_test.dart</a>
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">test/consumer_test.dart</a>
```
consumer
✅ obtains value from Provider<T>
@@ -95,7 +95,7 @@ consumer6
✅ crashed with no builder
✅ can be used inside MultiProvider
```
### ✅ <a id="user-content-r0s3" href="#r0s3">test/context_test.dart</a>
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">test/context_test.dart</a>
```
✅ watch in layoutbuilder
✅ select in layoutbuilder
@@ -130,7 +130,7 @@ BuildContext
✅ context.select deeply compares sets
✅ context.watch listens to value changes
```
### ✅ <a id="user-content-r0s4" href="#r0s4">test/future_provider_test.dart</a>
### ✅ <a id="user-content-r0s4" href="#user-content-r0s4">test/future_provider_test.dart</a>
```
✅ works with MultiProvider
✅ (catchError) previous future completes after transition is no-op
@@ -144,7 +144,7 @@ BuildContext
FutureProvider()
✅ crashes if builder is null
```
### ✅ <a id="user-content-r0s5" href="#r0s5">test/inherited_provider_test.dart</a>
### ✅ <a id="user-content-r0s5" href="#user-content-r0s5">test/inherited_provider_test.dart</a>
```
✅ regression test #377
✅ rebuild on dependency flags update
@@ -233,7 +233,7 @@ DeferredInheritedProvider()
✅ dispose
✅ dispose no-op if never built
```
### ✅ <a id="user-content-r0s6" href="#r0s6">test/listenable_provider_test.dart</a>
### ✅ <a id="user-content-r0s6" href="#user-content-r0s6">test/listenable_provider_test.dart</a>
```
ListenableProvider
✅ works with MultiProvider
@@ -255,7 +255,7 @@ ListenableProvider stateful constructor
✅ pass down key
✅ throws if create is null
```
### ✅ <a id="user-content-r0s7" href="#r0s7">test/listenable_proxy_provider_test.dart</a>
### ✅ <a id="user-content-r0s7" href="#user-content-r0s7">test/listenable_proxy_provider_test.dart</a>
```
ListenableProxyProvider
✅ throws if update is missing
@@ -272,14 +272,14 @@ ListenableProxyProvider variants
✅ ListenableProxyProvider5
✅ ListenableProxyProvider6
```
### ✅ <a id="user-content-r0s8" href="#r0s8">test/multi_provider_test.dart</a>
### ✅ <a id="user-content-r0s8" href="#user-content-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>
### ✅ <a id="user-content-r0s9" href="#user-content-r0s9">test/provider_test.dart</a>
```
✅ works with MultiProvider
Provider.of
@@ -295,7 +295,7 @@ Provider
✅ throws an error if no provider found
✅ update should notify
```
### ✅ <a id="user-content-r0s10" href="#r0s10">test/proxy_provider_test.dart</a>
### ✅ <a id="user-content-r0s10" href="#user-content-r0s10">test/proxy_provider_test.dart</a>
```
ProxyProvider
✅ throws if the provided value is a Listenable/Stream
@@ -316,13 +316,13 @@ ProxyProvider variants
✅ ProxyProvider5
✅ ProxyProvider6
```
### ✅ <a id="user-content-r0s11" href="#r0s11">test/reassemble_test.dart</a>
### ✅ <a id="user-content-r0s11" href="#user-content-r0s11">test/reassemble_test.dart</a>
```
✅ ReassembleHandler
✅ unevaluated create
✅ unevaluated create
```
### ✅ <a id="user-content-r0s12" href="#r0s12">test/selector_test.dart</a>
### ✅ <a id="user-content-r0s12" href="#user-content-r0s12">test/selector_test.dart</a>
```
✅ asserts that builder/selector are not null
✅ Deep compare maps by default
@@ -342,14 +342,14 @@ ProxyProvider variants
✅ Selector5
✅ Selector6
```
### ✅ <a id="user-content-r0s13" href="#r0s13">test/stateful_provider_test.dart</a>
### ✅ <a id="user-content-r0s13" href="#user-content-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>
### ✅ <a id="user-content-r0s14" href="#user-content-r0s14">test/stream_provider_test.dart</a>
```
✅ works with MultiProvider
✅ transition from stream to stream preserve state
@@ -361,7 +361,7 @@ 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>
### ❌ <a id="user-content-r0s15" href="#user-content-r0s15">test/value_listenable_provider_test.dart</a>
```
valueListenableProvider
✅ rebuilds when value change

View File

@@ -1,13 +1,13 @@
![Tests failed](https://img.shields.io/badge/tests-1%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/external/java/TEST-org.apache.pulsar.AddMissingPatchVersionTest.xml||1 ❌|1 ⚪|116ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/external/java/TEST-org.apache.pulsar.AddMissingPatchVersionTest.xml</a>
|[fixtures/external/java/TEST-org.apache.pulsar.AddMissingPatchVersionTest.xml](#user-content-r0)||1 ❌|1 ⚪|116ms|
## ❌ <a id="user-content-r0" href="#user-content-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>
|[org.apache.pulsar.AddMissingPatchVersionTest](#user-content-r0s0)||1 ❌|1 ⚪|116ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">org.apache.pulsar.AddMissingPatchVersionTest</a>
```
⚪ testVersionStrings
❌ testVersionStrings

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%201%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/rspec-json.json|1 ✅|1 ❌|1 ⚪|0ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/rspec-json.json</a>
|[fixtures/rspec-json.json](#user-content-r0)|1 ✅|1 ❌|1 ⚪|0ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/rspec-json.json</a>
**3** tests were completed in **0ms** with **1** passed, **1** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[./spec/config/check_env_vars_spec.rb](#r0s0)|1 ✅|1 ❌|1 ⚪|0ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">./spec/config/check_env_vars_spec.rb</a>
|[./spec/config/check_env_vars_spec.rb](#user-content-r0s0)|1 ✅|1 ❌|1 ⚪|0ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">./spec/config/check_env_vars_spec.rb</a>
```
CheckEnvVars#call when all env vars are defined behaves like success load
❌ CheckEnvVars#call when all env vars are defined behaves like success load fails in assertion

View File

@@ -3,25 +3,25 @@
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/external/SilentNotes.trx|67 ✅||12 ⚪|1s|
## ✅ <a id="user-content-r0" href="#r0">fixtures/external/SilentNotes.trx</a>
|[fixtures/external/SilentNotes.trx](#user-content-r0)|67 ✅||12 ⚪|1s|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/external/SilentNotes.trx</a>
**79** tests were completed in **1s** with **67** passed, **0** failed and **12** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[VanillaCloudStorageClientTest.CloudStorageCredentialsTest](#r0s0)|6 ✅|||30ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest](#r0s1)|2 ✅||3 ⚪|101ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest](#r0s2)|4 ✅||3 ⚪|166ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest](#r0s3)|2 ✅|||7ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest](#r0s4)|1 ✅||3 ⚪|40ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest](#r0s5)|1 ✅||3 ⚪|15ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest](#r0s6)|5 ✅|||16ms|
|[VanillaCloudStorageClientTest.CloudStorageTokenTest](#r0s7)|9 ✅|||0ms|
|[VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest](#r0s8)|3 ✅|||3ms|
|[VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest](#r0s9)|9 ✅|||12ms|
|[VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest](#r0s10)|5 ✅|||13ms|
|[VanillaCloudStorageClientTest.SecureStringExtensionsTest](#r0s11)|7 ✅|||0ms|
|[VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest](#r0s12)|13 ✅|||43ms|
### ✅ <a id="user-content-r0s0" href="#r0s0">VanillaCloudStorageClientTest.CloudStorageCredentialsTest</a>
|[VanillaCloudStorageClientTest.CloudStorageCredentialsTest](#user-content-r0s0)|6 ✅|||30ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest](#user-content-r0s1)|2 ✅||3 ⚪|101ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest](#user-content-r0s2)|4 ✅||3 ⚪|166ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest](#user-content-r0s3)|2 ✅|||7ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest](#user-content-r0s4)|1 ✅||3 ⚪|40ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest](#user-content-r0s5)|1 ✅||3 ⚪|15ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest](#user-content-r0s6)|5 ✅|||16ms|
|[VanillaCloudStorageClientTest.CloudStorageTokenTest](#user-content-r0s7)|9 ✅|||0ms|
|[VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest](#user-content-r0s8)|3 ✅|||3ms|
|[VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest](#user-content-r0s9)|9 ✅|||12ms|
|[VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest](#user-content-r0s10)|5 ✅|||13ms|
|[VanillaCloudStorageClientTest.SecureStringExtensionsTest](#user-content-r0s11)|7 ✅|||0ms|
|[VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest](#user-content-r0s12)|13 ✅|||43ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">VanillaCloudStorageClientTest.CloudStorageCredentialsTest</a>
```
✅ AreEqualWorksWithDifferentPassword
✅ AreEqualWorksWithSameContent
@@ -30,7 +30,7 @@
✅ ValidateAcceptsValidCredentials
✅ ValidateRejectsInvalidCredentials
```
### ✅ <a id="user-content-r0s1" href="#r0s1">VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest</a>
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest</a>
```
✅ FileLifecycleWorks
⚪ ReallyDoFetchToken
@@ -38,7 +38,7 @@
⚪ ReallyDoRefreshToken
✅ ThrowsAccessDeniedExceptionWithInvalidToken
```
### ✅ <a id="user-content-r0s2" href="#r0s2">VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest</a>
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest</a>
```
✅ FileLifecycleWorks
✅ SanitizeCredentials_ChangesInvalidPrefix
@@ -48,26 +48,26 @@
⚪ ThrowsWithInvalidUrl
⚪ ThrowsWithInvalidUsername
```
### ✅ <a id="user-content-r0s3" href="#r0s3">VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest</a>
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest</a>
```
✅ ChoosesCorrectUrlForGmxComEmail
✅ ChoosesCorrectUrlForGmxNetEmail
```
### ✅ <a id="user-content-r0s4" href="#r0s4">VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest</a>
### ✅ <a id="user-content-r0s4" href="#user-content-r0s4">VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest</a>
```
✅ FileLifecycleWorks
⚪ ReallyDoFetchToken
⚪ ReallyDoOpenAuthorizationPageInBrowser
⚪ ReallyDoRefreshToken
```
### ✅ <a id="user-content-r0s5" href="#r0s5">VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest</a>
### ✅ <a id="user-content-r0s5" href="#user-content-r0s5">VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest</a>
```
✅ FileLifecycleWorks
⚪ ReallyDoFetchToken
⚪ ReallyDoOpenAuthorizationPageInBrowser
⚪ ReallyDoRefreshToken
```
### ✅ <a id="user-content-r0s6" href="#r0s6">VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest</a>
### ✅ <a id="user-content-r0s6" href="#user-content-r0s6">VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest</a>
```
✅ FileLifecycleWorks
✅ ParseGmxWebdavResponseCorrectly
@@ -75,7 +75,7 @@
✅ ThrowsWithInvalidPath
✅ ThrowsWithInvalidUsername
```
### ✅ <a id="user-content-r0s7" href="#r0s7">VanillaCloudStorageClientTest.CloudStorageTokenTest</a>
### ✅ <a id="user-content-r0s7" href="#user-content-r0s7">VanillaCloudStorageClientTest.CloudStorageTokenTest</a>
```
✅ AreEqualWorksWithNullDate
✅ AreEqualWorksWithSameContent
@@ -87,13 +87,13 @@
✅ SetExpiryDateBySecondsWorksWithNull
✅ SetExpiryDateBySecondsWorksWithVeryShortPeriod
```
### ✅ <a id="user-content-r0s8" href="#r0s8">VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest</a>
### ✅ <a id="user-content-r0s8" href="#user-content-r0s8">VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest</a>
```
✅ ParsesAllErrorCodesCorrectly
✅ ParsesNullErrorCodeCorrectly
✅ ParsesUnknownErrorCodeCorrectly
```
### ✅ <a id="user-content-r0s9" href="#r0s9">VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest</a>
### ✅ <a id="user-content-r0s9" href="#user-content-r0s9">VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest</a>
```
✅ BuildAuthorizationRequestUrlEscapesParameters
✅ BuildAuthorizationRequestUrlLeavesOutOptionalParameters
@@ -105,7 +105,7 @@
✅ ParseRealWorldGoogleRejectResponse
✅ ParseRealWorldGoogleSuccessResponse
```
### ✅ <a id="user-content-r0s10" href="#r0s10">VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest</a>
### ✅ <a id="user-content-r0s10" href="#user-content-r0s10">VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest</a>
```
✅ BuildOAuth2AuthorizationRequestUrlWorks
✅ FetchTokenCanInterpretGoogleResponse
@@ -113,7 +113,7 @@
✅ FetchTokenThrowsWithWrongState
✅ RefreshTokenCanInterpretGoogleResponse
```
### ✅ <a id="user-content-r0s11" href="#r0s11">VanillaCloudStorageClientTest.SecureStringExtensionsTest</a>
### ✅ <a id="user-content-r0s11" href="#user-content-r0s11">VanillaCloudStorageClientTest.SecureStringExtensionsTest</a>
```
✅ AreEqualsWorksCorrectly
✅ CorrectlyConvertsSecureStringToString
@@ -123,7 +123,7 @@
✅ CorrectlyConvertsUnicodeBytesToSecureString
✅ CorrectlyConvertsUtf8BytesToSecureString
```
### ✅ <a id="user-content-r0s12" href="#r0s12">VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest</a>
### ✅ <a id="user-content-r0s12" href="#user-content-r0s12">VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest</a>
```
✅ DecryptAfterDesrializationCanReadAllPropertiesBack
✅ DecryptAfterDesrializationRespectsNullProperties

View File

@@ -1,13 +1,13 @@
![Tests failed](https://img.shields.io/badge/tests-2%20passed%2C%201%20failed-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|fixtures/swift-xunit.xml|2 ✅|1 ❌||220ms|
## ❌ <a id="user-content-r0" href="#r0">fixtures/swift-xunit.xml</a>
|[fixtures/swift-xunit.xml](#user-content-r0)|2 ✅|1 ❌||220ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/swift-xunit.xml</a>
**3** tests were completed in **220ms** with **2** passed, **1** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[TestResults](#r0s0)|2 ✅|1 ❌||220ms|
### ❌ <a id="user-content-r0s0" href="#r0s0">TestResults</a>
|[TestResults](#user-content-r0s0)|2 ✅|1 ❌||220ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">TestResults</a>
```
AcmeLibTests.AcmeLibTests
✅ test_always_pass

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`dotnet-trx tests matches report snapshot 1`] = `
exports[`dotnet-trx tests matches report snapshot (only failed tests) 1`] = `
TestRunResult {
"path": "fixtures/dotnet-trx.trx",
"suites": [
@@ -21,7 +21,9 @@ TestRunResult {
at DotnetTests.Unit.Calculator.Div(Int32 a, Int32 b) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.Unit\\Calculator.cs:line 9
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_TargetTest() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 33",
"line": 9,
"message": "System.DivideByZeroException : Attempted to divide by zero.",
"message": "System.DivideByZeroException : Attempted to divide by zero.
at DotnetTests.Unit.Calculator.Div(Int32 a, Int32 b) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.Unit\\Calculator.cs:line 9
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_TargetTest() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 33",
"path": "DotnetTests.Unit/Calculator.cs",
},
"name": "Exception_In_TargetTest",
@@ -33,7 +35,8 @@ TestRunResult {
"details": "System.Exception : Test
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 39",
"line": 39,
"message": "System.Exception : Test",
"message": "System.Exception : Test
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 39",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Exception_In_Test",
@@ -49,7 +52,8 @@ Actual: 2
"line": 27,
"message": "Assert.Equal() Failure
Expected: 3
Actual: 2",
Actual: 2
at DotnetTests.XUnitTests.CalculatorTests.Failing_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 27",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Failing_Test",
@@ -71,7 +75,8 @@ Actual: False
"line": 59,
"message": "Assert.True() Failure
Expected: True
Actual: False",
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Is_Even_Number(Int32 i) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 59",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Is_Even_Number(i: 3)",
@@ -99,7 +104,143 @@ Actual: False
"line": 67,
"message": "Assert.True() Failure
Expected: True
Actual: False",
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Theory_With_Custom_Name(Int32 i) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 67",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Should be even number(i: 3)",
"result": "failed",
"time": 0.6537000000000001,
},
TestCaseResult {
"error": undefined,
"name": "Skipped_Test",
"result": "skipped",
"time": 1,
},
TestCaseResult {
"error": undefined,
"name": "Timeout_Test",
"result": "success",
"time": 108.42580000000001,
},
],
},
],
"name": "DotnetTests.XUnitTests.CalculatorTests",
"totalTime": undefined,
},
],
"totalTime": 1116,
}
`;
exports[`dotnet-trx tests matches report snapshot 1`] = `
TestRunResult {
"path": "fixtures/dotnet-trx.trx",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": null,
"tests": [
TestCaseResult {
"error": undefined,
"name": "Custom Name",
"result": "success",
"time": 0.1371,
},
TestCaseResult {
"error": {
"details": "System.DivideByZeroException : Attempted to divide by zero.
at DotnetTests.Unit.Calculator.Div(Int32 a, Int32 b) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.Unit\\Calculator.cs:line 9
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_TargetTest() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 33",
"line": 9,
"message": "System.DivideByZeroException : Attempted to divide by zero.
at DotnetTests.Unit.Calculator.Div(Int32 a, Int32 b) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.Unit\\Calculator.cs:line 9
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_TargetTest() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 33",
"path": "DotnetTests.Unit/Calculator.cs",
},
"name": "Exception_In_TargetTest",
"result": "failed",
"time": 0.8377,
},
TestCaseResult {
"error": {
"details": "System.Exception : Test
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 39",
"line": 39,
"message": "System.Exception : Test
at DotnetTests.XUnitTests.CalculatorTests.Exception_In_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 39",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Exception_In_Test",
"result": "failed",
"time": 2.5175,
},
TestCaseResult {
"error": {
"details": "Assert.Equal() Failure
Expected: 3
Actual: 2
at DotnetTests.XUnitTests.CalculatorTests.Failing_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 27",
"line": 27,
"message": "Assert.Equal() Failure
Expected: 3
Actual: 2
at DotnetTests.XUnitTests.CalculatorTests.Failing_Test() in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 27",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Failing_Test",
"result": "failed",
"time": 3.8697,
},
TestCaseResult {
"error": undefined,
"name": "Is_Even_Number(i: 2)",
"result": "success",
"time": 0.0078,
},
TestCaseResult {
"error": {
"details": "Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Is_Even_Number(Int32 i) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 59",
"line": 59,
"message": "Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Is_Even_Number(Int32 i) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 59",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Is_Even_Number(i: 3)",
"result": "failed",
"time": 0.41409999999999997,
},
TestCaseResult {
"error": undefined,
"name": "Passing_Test",
"result": "success",
"time": 0.1365,
},
TestCaseResult {
"error": undefined,
"name": "Should be even number(i: 2)",
"result": "success",
"time": 0.0097,
},
TestCaseResult {
"error": {
"details": "Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Theory_With_Custom_Name(Int32 i) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 67",
"line": 67,
"message": "Assert.True() Failure
Expected: True
Actual: False
at DotnetTests.XUnitTests.CalculatorTests.Theory_With_Custom_Name(Int32 i) in C:\\Users\\Michal\\Workspace\\dorny\\test-reporter\\reports\\dotnet\\DotnetTests.XUnitTests\\CalculatorTests.cs:line 67",
"path": "DotnetTests.XUnitTests/CalculatorTests.cs",
},
"name": "Should be even number(i: 3)",

View File

@@ -0,0 +1,131 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`golang-json tests report from ./reports/dotnet test results matches snapshot 1`] = `
TestRunResult {
"path": "fixtures/golang-json.json",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": null,
"tests": [
TestCaseResult {
"error": undefined,
"name": "TestPassing",
"result": "success",
"time": 60,
},
TestCaseResult {
"error": {
"details": "calculator_test.go:19: expected 1+1 = 3, got 2
",
"message": "calculator_test.go:19: expected 1+1 = 3, got 2
",
},
"name": "TestFailing",
"result": "failed",
"time": 890,
},
TestCaseResult {
"error": {
"details": "calculator_test.go:76: caught panic: runtime error: integer divide by zero
",
"message": "calculator_test.go:76: caught panic: runtime error: integer divide by zero
",
},
"name": "TestPanicInsideFunction",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": {
"details": "calculator_test.go:76: caught panic: bad stuff
",
"message": "calculator_test.go:76: caught panic: bad stuff
",
},
"name": "TestPanicInsideTest",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": {
"details": "calculator_test.go:45: skipping test
",
"message": "calculator_test.go:45: skipping test
",
},
"name": "TestSkipped",
"result": "skipped",
"time": 940,
},
TestCaseResult {
"error": {
"details": "",
"message": "",
},
"name": "TestCases",
"result": "failed",
"time": 2250,
},
],
},
TestGroupResult {
"name": "TestCases",
"tests": [
TestCaseResult {
"error": undefined,
"name": "1_+_2_=_3",
"result": "success",
"time": 400,
},
TestCaseResult {
"error": undefined,
"name": "4_+_7_=_11",
"result": "success",
"time": 460,
},
TestCaseResult {
"error": {
"details": "calculator_test.go:67: expected 2 + 3 = 4, got 5
",
"message": "calculator_test.go:67: expected 2 + 3 = 4, got 5
",
},
"name": "2_+_3_=_4",
"result": "failed",
"time": 90,
},
TestCaseResult {
"error": {
"details": "calculator_test.go:67: expected 1 / 2 = 1, got 0
",
"message": "calculator_test.go:67: expected 1 / 2 = 1, got 0
",
},
"name": "1_/_2_=_1",
"result": "failed",
"time": 920,
},
TestCaseResult {
"error": undefined,
"name": "9_/_3_=_3",
"result": "success",
"time": 340,
},
TestCaseResult {
"error": undefined,
"name": "14_/_7_=_2",
"result": "success",
"time": 40,
},
],
},
],
"name": "_/home/james_t/git/test-reporter/reports/go",
"totalTime": undefined,
},
],
"totalTime": undefined,
}
`;

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import {DartJsonParser} from '../src/parsers/dart-json/dart-json-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('dart-json tests', () => {
@@ -66,4 +66,66 @@ describe('dart-json tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dart-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 DartJsonParser(opts, 'dart')
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'dart-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 DartJsonParser(opts, 'dart')
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dart-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 DartJsonParser(opts, 'dart')
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import {DotnetNunitParser} from '../src/parsers/dotnet-nunit/dotnet-nunit-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('dotnet-nunit tests', () => {
@@ -26,4 +26,66 @@ describe('dotnet-nunit tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-nunit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetNunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-nunit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetNunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-nunit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetNunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import {DotnetTrxParser} from '../src/parsers/dotnet-trx/dotnet-trx-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport, ReportOptions} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('dotnet-trx tests', () => {
@@ -23,6 +23,22 @@ describe('dotnet-trx tests', () => {
expect(result.result).toBe('success')
})
it('produces empty test run result when TestDefinitions is empty', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'dotnet-trx-empty-test-definitions.trx')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetTrxParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
})
it('matches report snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const outputPath = path.join(__dirname, '__outputs__', 'dotnet-trx.md')
@@ -44,6 +60,32 @@ describe('dotnet-trx tests', () => {
fs.writeFileSync(outputPath, report)
})
it('matches report snapshot (only failed tests)', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const outputPath = path.join(__dirname, '__outputs__', 'dotnet-trx-only-failed.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: ['DotnetTests.Unit/Calculator.cs', 'DotnetTests.XUnitTests/CalculatorTests.cs']
//workDir: 'C:/Users/Michal/Workspace/dorny/test-check/reports/dotnet/'
}
const parser = new DotnetTrxParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const reportOptions: ReportOptions = {
...DEFAULT_OPTIONS,
listSuites: 'all',
listTests: 'failed'
}
const report = getReport([result], reportOptions)
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report from FluentValidation test results matches snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'external', 'FluentValidation.Tests.trx')
const outputPath = path.join(__dirname, '__outputs__', 'fluent-validation-test-results.md')
@@ -83,4 +125,66 @@ describe('dotnet-trx tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetTrxParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetTrxParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new DotnetTrxParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<TestRun id="80e4c095-f726-4ab2-9441-416daa162672" name="..." runUser="..." xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Times creation="2021-02-26T10:36:33.7131022+02:00" queuing="2021-02-26T10:36:33.7131029+02:00" start="2021-02-26T10:36:33.3278956+02:00" finish="2021-02-26T10:36:33.7139830+02:00" />
<TestSettings name="default" id="863a1d8b-ee3b-45f9-86ee-1869bc4e889f">
<Deployment runDeploymentRoot="..." />
</TestSettings>
<Results />
<TestDefinitions />
<TestEntries />
<TestLists>
<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
</TestLists>
<ResultSummary outcome="Completed">
<Counters total="0" executed="0" passed="0" failed="0" error="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />
<RunInfos>
<RunInfo computerName="..." outcome="Warning" timestamp="2021-02-26T10:36:33.6676104+02:00">
<Text>No test is available in (...). Make sure that test discoverer &amp; executors are registered and platform &amp; framework version settings are appropriate and try again.</Text>
</RunInfo>
</RunInfos>
</ResultSummary>
</TestRun>

View File

@@ -0,0 +1,59 @@
{"Time":"2025-04-22T08:59:55.364618802-05:00","Action":"start","Package":"_/home/james_t/git/test-reporter/reports/go"}
{"Time":"2025-04-22T08:59:55.371779289-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing"}
{"Time":"2025-04-22T08:59:55.371805677-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Output":"=== RUN TestPassing\n"}
{"Time":"2025-04-22T08:59:55.428201983-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Output":" calculator_test.go:11: pass!\n"}
{"Time":"2025-04-22T08:59:55.428265529-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Output":"--- PASS: TestPassing (0.06s)\n"}
{"Time":"2025-04-22T08:59:55.428285649-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPassing","Elapsed":0.06}
{"Time":"2025-04-22T08:59:55.428299886-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing"}
{"Time":"2025-04-22T08:59:55.428309029-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Output":"=== RUN TestFailing\n"}
{"Time":"2025-04-22T08:59:56.317425091-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Output":" calculator_test.go:19: expected 1+1 = 3, got 2\n"}
{"Time":"2025-04-22T08:59:56.31748077-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Output":"--- FAIL: TestFailing (0.89s)\n"}
{"Time":"2025-04-22T08:59:56.317493452-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestFailing","Elapsed":0.89}
{"Time":"2025-04-22T08:59:56.317506107-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction"}
{"Time":"2025-04-22T08:59:56.317514487-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Output":"=== RUN TestPanicInsideFunction\n"}
{"Time":"2025-04-22T08:59:56.317530448-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Output":" calculator_test.go:76: caught panic: runtime error: integer divide by zero\n"}
{"Time":"2025-04-22T08:59:56.317541866-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Output":"--- FAIL: TestPanicInsideFunction (0.00s)\n"}
{"Time":"2025-04-22T08:59:56.317552981-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideFunction","Elapsed":0}
{"Time":"2025-04-22T08:59:56.317561057-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest"}
{"Time":"2025-04-22T08:59:56.317568742-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Output":"=== RUN TestPanicInsideTest\n"}
{"Time":"2025-04-22T08:59:56.317584113-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Output":" calculator_test.go:76: caught panic: bad stuff\n"}
{"Time":"2025-04-22T08:59:56.317598524-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Output":"--- FAIL: TestPanicInsideTest (0.00s)\n"}
{"Time":"2025-04-22T08:59:56.317608268-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestPanicInsideTest","Elapsed":0}
{"Time":"2025-04-22T08:59:56.317615472-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped"}
{"Time":"2025-04-22T08:59:56.317623959-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Output":"=== RUN TestSkipped\n"}
{"Time":"2025-04-22T08:59:57.256475698-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Output":" calculator_test.go:45: skipping test\n"}
{"Time":"2025-04-22T08:59:57.256536372-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Output":"--- SKIP: TestSkipped (0.94s)\n"}
{"Time":"2025-04-22T08:59:57.256549142-05:00","Action":"skip","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestSkipped","Elapsed":0.94}
{"Time":"2025-04-22T08:59:57.256562053-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases"}
{"Time":"2025-04-22T08:59:57.256569388-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases","Output":"=== RUN TestCases\n"}
{"Time":"2025-04-22T08:59:57.256580104-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3"}
{"Time":"2025-04-22T08:59:57.256587408-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3","Output":"=== RUN TestCases/1_+_2_=_3\n"}
{"Time":"2025-04-22T08:59:57.653005399-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11"}
{"Time":"2025-04-22T08:59:57.653036336-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11","Output":"=== RUN TestCases/4_+_7_=_11\n"}
{"Time":"2025-04-22T08:59:58.112825221-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4"}
{"Time":"2025-04-22T08:59:58.112858016-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Output":"=== RUN TestCases/2_+_3_=_4\n"}
{"Time":"2025-04-22T08:59:58.201204209-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Output":" calculator_test.go:67: expected 2 + 3 = 4, got 5\n"}
{"Time":"2025-04-22T08:59:58.201245827-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1"}
{"Time":"2025-04-22T08:59:58.201255566-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Output":"=== RUN TestCases/1_/_2_=_1\n"}
{"Time":"2025-04-22T08:59:59.119852965-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Output":" calculator_test.go:67: expected 1 / 2 = 1, got 0\n"}
{"Time":"2025-04-22T08:59:59.119877603-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3"}
{"Time":"2025-04-22T08:59:59.119879955-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3","Output":"=== RUN TestCases/9_/_3_=_3\n"}
{"Time":"2025-04-22T08:59:59.460576385-05:00","Action":"run","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2"}
{"Time":"2025-04-22T08:59:59.460607599-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2","Output":"=== RUN TestCases/14_/_7_=_2\n"}
{"Time":"2025-04-22T08:59:59.504952672-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases","Output":"--- FAIL: TestCases (2.25s)\n"}
{"Time":"2025-04-22T08:59:59.504995938-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3","Output":" --- PASS: TestCases/1_+_2_=_3 (0.40s)\n"}
{"Time":"2025-04-22T08:59:59.505006062-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_+_2_=_3","Elapsed":0.4}
{"Time":"2025-04-22T08:59:59.505017551-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11","Output":" --- PASS: TestCases/4_+_7_=_11 (0.46s)\n"}
{"Time":"2025-04-22T08:59:59.505026099-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/4_+_7_=_11","Elapsed":0.46}
{"Time":"2025-04-22T08:59:59.505033963-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Output":" --- FAIL: TestCases/2_+_3_=_4 (0.09s)\n"}
{"Time":"2025-04-22T08:59:59.505042238-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/2_+_3_=_4","Elapsed":0.09}
{"Time":"2025-04-22T08:59:59.505050917-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Output":" --- FAIL: TestCases/1_/_2_=_1 (0.92s)\n"}
{"Time":"2025-04-22T08:59:59.505059901-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/1_/_2_=_1","Elapsed":0.92}
{"Time":"2025-04-22T08:59:59.505068125-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3","Output":" --- PASS: TestCases/9_/_3_=_3 (0.34s)\n"}
{"Time":"2025-04-22T08:59:59.505076976-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/9_/_3_=_3","Elapsed":0.34}
{"Time":"2025-04-22T08:59:59.5050845-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2","Output":" --- PASS: TestCases/14_/_7_=_2 (0.04s)\n"}
{"Time":"2025-04-22T08:59:59.505091554-05:00","Action":"pass","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases/14_/_7_=_2","Elapsed":0.04}
{"Time":"2025-04-22T08:59:59.505098998-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Test":"TestCases","Elapsed":2.25}
{"Time":"2025-04-22T08:59:59.505107502-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Output":"FAIL\n"}
{"Time":"2025-04-22T08:59:59.505552861-05:00","Action":"output","Package":"_/home/james_t/git/test-reporter/reports/go","Output":"FAIL\t_/home/james_t/git/test-reporter/reports/go\t4.141s\n"}
{"Time":"2025-04-22T08:59:59.505584529-05:00","Action":"fail","Package":"_/home/james_t/git/test-reporter/reports/go","Elapsed":4.141}

View File

@@ -0,0 +1,29 @@
import * as fs from 'fs'
import * as path from 'path'
import {GolangJsonParser} from '../src/parsers/golang-json/golang-json-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('golang-json tests', () => {
it('report from ./reports/dotnet test results matches snapshot', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'golang-json.json')
const outputPath = path.join(__dirname, '__outputs__', 'golang-json.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: ['calculator.go', 'calculator_test.go']
}
const parser = new GolangJsonParser(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

@@ -3,7 +3,7 @@ import * as path from 'path'
import {JavaJunitParser} from '../src/parsers/java-junit/java-junit-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('java-junit tests', () => {
@@ -90,4 +90,66 @@ describe('java-junit tests', () => {
expect(result.result === 'failed')
expect(result.failed === 1)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'junit-with-message.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JavaJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'junit-with-message.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JavaJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'java-junit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JavaJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import {JestJunitParser} from '../src/parsers/jest-junit/jest-junit-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('jest-junit tests', () => {
@@ -145,4 +145,66 @@ describe('jest-junit tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'jest-junit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JestJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'jest-junit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JestJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'jest-junit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new JestJunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -3,7 +3,7 @@ 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 {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('mocha-json tests', () => {
@@ -64,4 +64,66 @@ describe('mocha-json tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', '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)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', '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)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', '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)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import {RspecJsonParser} from '../src/parsers/rspec-json/rspec-json-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('rspec-json tests', () => {
@@ -42,4 +42,66 @@ describe('rspec-json tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'rspec-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 RspecJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'rspec-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 RspecJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'rspec-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 RspecJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -3,7 +3,7 @@ import * as path from 'path'
import {SwiftXunitParser} from '../src/parsers/swift-xunit/swift-xunit-parser'
import {ParseOptions} from '../src/test-parser'
import {getReport} from '../src/report/get-report'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
describe('swift-xunit tests', () => {
@@ -27,4 +27,66 @@ describe('swift-xunit tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'swift-xunit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new SwiftXunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result])
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it.each([
['empty string', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n']
])('report does not include a title when configured value is %s', async (_, reportTitle) => {
const fixturePath = path.join(__dirname, 'fixtures', 'swift-xunit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new SwiftXunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle
})
// Report should have the badge as the first line
expect(report).toMatch(/^!\[Tests failed]/)
})
it('report includes a custom report title', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'swift-xunit.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new SwiftXunitParser(opts)
const result = await parser.parse(filePath, fileContent)
const report = getReport([result], {
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
})
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n/)
})
})

View File

@@ -32,6 +32,6 @@ describe('parseNetDuration', () => {
})
it('throws when string has invalid format', () => {
expect(() => parseNetDuration('12:34:56 not a duration')).toThrowError(/^Invalid format/)
expect(() => parseNetDuration('12:34:56 not a duration')).toThrow(/^Invalid format/)
})
})

View File

@@ -39,7 +39,7 @@ inputs:
description: |
Limits which test suites are listed. Supported options:
- all
- only-failed
- failed
- none
required: false
default: 'all'
@@ -47,7 +47,7 @@ inputs:
description: |
Limits which test cases are listed. Supported options:
- all
- only-failed
- failed
- none
required: false
default: 'all'

700
dist/index.js generated vendored

File diff suppressed because it is too large Load Diff

5577
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "test-reporter",
"version": "2.0.0",
"version": "2.1.0",
"private": true,
"description": "Presents test results from popular testing frameworks as Github check run",
"main": "lib/main.js",
@@ -17,6 +17,8 @@
"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\"",
"dotnet-nunit-fixture": "nunit.exe reports/dotnet/DotnetTests.NUnitV3Tests/bin/Debug/netcoreapp3.1/DotnetTests.NUnitV3Tests.dll --result=__tests__/fixtures/dotnet-nunit.xml",
"dotnet-nunit-legacy-fixture": "nunit-console.exe reports/dotnet-nunit-legacy/NUnitLegacy.sln --result=__tests__/fixtures/dotnet-nunit-legacy.xml",
"golang-json-fixture": "go test -v -json -timeout 5s ./reports/go | tee __tests__/fixtures/golang-json.json",
"jest-fixture": "cd \"reports/jest\" && npm test",
"mocha-fixture": "cd \"reports/mocha\" && npm test"
},
@@ -35,7 +37,7 @@
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/github": "^6.0.0",
"@actions/github": "^6.0.1",
"adm-zip": "^0.5.16",
"fast-glob": "^3.3.3",
"got": "^11.8.6",
@@ -46,7 +48,7 @@
"@octokit/webhooks-types": "^7.6.1",
"@types/adm-zip": "^0.5.7",
"@types/jest": "^29.5.14",
"@types/node": "^20.17.24",
"@types/node": "^20.19.2",
"@types/picomatch": "^2.3.4",
"@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^7.18.0",
@@ -54,18 +56,17 @@
"@vercel/ncc": "^0.38.3",
"eol-converter-cli": "^1.1.0",
"eslint": "^8.57.1",
"eslint-import-resolver-typescript": "^3.8.5",
"eslint-import-resolver-typescript": "^3.10.1",
"eslint-plugin-github": "^4.10.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.11.0",
"eslint-plugin-prettier": "^5.2.3",
"jest": "^29.7.0",
"jest-circus": "^29.7.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^28.14.0",
"eslint-plugin-prettier": "^5.5.1",
"jest": "^30.0.4",
"jest-junit": "^16.0.0",
"js-yaml": "^4.1.0",
"prettier": "^3.5.3",
"ts-jest": "^29.2.6",
"typescript": "^5.5.4"
"prettier": "^3.6.2",
"ts-jest": "^29.4.0",
"typescript": "^5.8.3"
},
"jest-junit": {
"suiteName": "jest tests",
@@ -79,5 +80,10 @@
},
"engines": {
"node": ">=20"
},
"markdownlint-cli2": {
"ignores": [
"__tests__/**/*"
]
}
}

20
reports/go/calculator.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import "errors"
func CalculatorSum(a, b int) int {
return a + b
}
func CalculatorDivide(a, b int) int {
return a / b
}
var ErrDivideByZero = errors.New("divide by zero")
func CalculatorSafeDivide(a, b int) (int, error) {
if b == 0 {
return 0, ErrDivideByZero
}
return a / b, nil
}

View File

@@ -0,0 +1,82 @@
package main
import (
"math/rand"
"testing"
"time"
)
func TestPassing(t *testing.T) {
randomSleep()
t.Log("pass!")
}
func TestFailing(t *testing.T) {
randomSleep()
expected := 3
actual := CalculatorSum(1, 1)
if actual != expected {
t.Fatalf("expected 1+1 = %d, got %d", expected, actual)
}
}
func TestPanicInsideFunction(t *testing.T) {
defer catchPanics(t)
expected := 0
actual := CalculatorDivide(1, 0)
if actual != expected {
t.Fatalf("expected 1/1 = %d, got %d", expected, actual)
}
}
func TestPanicInsideTest(t *testing.T) {
defer catchPanics(t)
panic("bad stuff")
}
// Timeouts cause the entire test process to end - so we can't get good output for these
// func TestTimeout(t *testing.T) {
// time.Sleep(time.Second * 5)
// }
func TestSkipped(t *testing.T) {
randomSleep()
t.Skipf("skipping test")
}
func TestCases(t *testing.T) {
for _, tc := range []struct {
name string
fn func(int, int) int
a, b, c int
}{
{"1 + 2 = 3", CalculatorSum, 1, 2, 3},
{"4 + 7 = 11", CalculatorSum, 4, 7, 11},
{"2 + 3 = 4", CalculatorSum, 2, 3, 4},
{"1 / 2 = 1", CalculatorDivide, 1, 2, 1},
{"9 / 3 = 3", CalculatorDivide, 9, 3, 3},
{"14 / 7 = 2", CalculatorDivide, 14, 7, 2},
} {
t.Run(tc.name, func(t *testing.T) {
randomSleep()
c := tc.fn(tc.a, tc.b)
if c != tc.c {
t.Fatalf("expected %s, got %d", tc.name, c)
}
})
}
}
func catchPanics(t *testing.T) {
err := recover()
if err != nil {
t.Fatalf("caught panic: %v", err)
}
}
func randomSleep() {
time.Sleep(time.Duration(rand.Int63n(int64(time.Second))))
}

3
reports/go/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module test_reporter_example
go 1.24.2

View File

@@ -13,6 +13,7 @@ import {getReport} from './report/get-report'
import {DartJsonParser} from './parsers/dart-json/dart-json-parser'
import {DotnetNunitParser} from './parsers/dotnet-nunit/dotnet-nunit-parser'
import {DotnetTrxParser} from './parsers/dotnet-trx/dotnet-trx-parser'
import {GolangJsonParser} from './parsers/golang-json/golang-json-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'
@@ -47,6 +48,7 @@ class TestReporter {
readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true'
readonly useActionsSummary = core.getInput('use-actions-summary', {required: false}) === 'true'
readonly badgeTitle = core.getInput('badge-title', {required: false})
readonly reportTitle = core.getInput('report-title', {required: false})
readonly token = core.getInput('token', {required: true})
readonly octokit: InstanceType<typeof GitHub>
readonly context = getCheckRunContext()
@@ -164,14 +166,28 @@ class TestReporter {
}
}
const {listSuites, listTests, onlySummary, useActionsSummary, badgeTitle} = this
const {listSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle} = this
const passed = results.reduce((sum, tr) => sum + tr.passed, 0)
const failed = results.reduce((sum, tr) => sum + tr.failed, 0)
const skipped = results.reduce((sum, tr) => sum + tr.skipped, 0)
const shortSummary = `${passed} passed, ${failed} failed and ${skipped} skipped `
let baseUrl = ''
if (this.useActionsSummary) {
const summary = getReport(results, {listSuites, listTests, baseUrl, onlySummary, useActionsSummary, badgeTitle})
const summary = getReport(results, {
listSuites,
listTests,
baseUrl,
onlySummary,
useActionsSummary,
badgeTitle,
reportTitle
})
core.info('Summary content:')
core.info(summary)
core.summary.addRaw(`# ${shortSummary}`)
await core.summary.addRaw(summary).write()
} else {
core.info(`Creating check run ${name}`)
@@ -188,7 +204,15 @@ class TestReporter {
core.info('Creating report summary')
baseUrl = createResp.data.html_url as string
const summary = getReport(results, {listSuites, listTests, baseUrl, onlySummary, useActionsSummary, badgeTitle})
const summary = getReport(results, {
listSuites,
listTests,
baseUrl,
onlySummary,
useActionsSummary,
badgeTitle,
reportTitle
})
core.info('Creating annotations')
const annotations = getAnnotations(results, this.maxAnnotations)
@@ -196,11 +220,6 @@ class TestReporter {
const isFailed = this.failOnError && results.some(tr => tr.result === 'failed')
const conclusion = isFailed ? 'failure' : 'success'
const passed = results.reduce((sum, tr) => sum + tr.passed, 0)
const failed = results.reduce((sum, tr) => sum + tr.failed, 0)
const skipped = results.reduce((sum, tr) => sum + tr.skipped, 0)
const shortSummary = `${passed} passed, ${failed} failed and ${skipped} skipped `
core.info(`Updating check run conclusion (${conclusion}) and output`)
const resp = await this.octokit.rest.checks.update({
check_run_id: createResp.data.id,
@@ -231,6 +250,8 @@ class TestReporter {
return new DotnetNunitParser(options)
case 'dotnet-trx':
return new DotnetTrxParser(options)
case 'golang-json':
return new GolangJsonParser(options)
case 'flutter-json':
return new DartJsonParser(options, 'flutter')
case 'java-junit':

View File

@@ -62,7 +62,8 @@ export class DotnetTrxParser implements TestParser {
}
private getTestClasses(trx: TrxReport): TestClass[] {
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined) {
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined ||
!trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))) {
return []
}
@@ -145,8 +146,8 @@ export class DotnetTrxParser implements TestParser {
return undefined
}
const message = test.error.Message[0]
const stackTrace = test.error.StackTrace[0]
const message = `${test.error.Message[0]}\n${stackTrace}`
let path
let line
@@ -160,7 +161,7 @@ export class DotnetTrxParser implements TestParser {
path,
line,
message,
details: `${message}\n${stackTrace}`
details: `${message}`
}
}

View File

@@ -0,0 +1,115 @@
import { ParseOptions, TestParser } from '../../test-parser'
import { GoTestEvent } from './golang-json-types'
import { getExceptionSource } from '../../utils/node-utils'
import { getBasePath, normalizeFilePath } from '../../utils/path-utils'
import {
TestExecutionResult,
TestRunResult,
TestSuiteResult,
TestGroupResult,
TestCaseResult,
TestCaseError
} from '../../test-results'
export class GolangJsonParser implements TestParser {
assumedWorkDir: string | undefined
constructor(readonly options: ParseOptions) { }
async parse(path: string, content: string): Promise<TestRunResult> {
const events = await this.getGolangTestEvents(path, content)
return this.getTestRunResult(path, events)
}
private async getGolangTestEvents(path: string, content: string): Promise<GoTestEvent[]> {
return content.trim().split('\n').map((line, index) => {
try {
return JSON.parse(line) as GoTestEvent
} catch (e) {
throw new Error(`Invalid JSON at ${path} line ${index + 1}\n\n${e}`)
}
})
}
private getTestRunResult(path: string, events: GoTestEvent[]): TestRunResult {
const eventGroups = new Map<string, GoTestEvent[]>()
for (const event of events) {
if (!event.Test) {
continue
}
const k = `${event.Package}/${event.Test}`
let g = eventGroups.get(k)
if (!g) {
g = []
eventGroups.set(k, g)
}
g.push(event)
}
const suites: TestSuiteResult[] = []
for (const eventGroup of eventGroups.values()) {
const event = eventGroup[0]
let suite = suites.find(s => s.name === event.Package)
if (!suite) {
suite = new TestSuiteResult(event.Package, [])
suites.push(suite)
}
if (!event.Test) {
continue
}
let groupName: string | null
let rest: string[]
[groupName, ...rest] = event.Test.split('/')
let testName = rest.join('/')
if (!testName) {
testName = groupName
groupName = null
}
let group = suite.groups.find(g => g.name === groupName)
if (!group) {
group = new TestGroupResult(groupName, [])
suite.groups.push(group)
}
const lastEvent = eventGroup.at(-1)!
const result: TestExecutionResult = lastEvent.Action === 'pass' ? 'success'
: lastEvent.Action === 'skip' ? 'skipped'
: 'failed'
if (lastEvent.Elapsed === undefined) {
throw new Error('missing elapsed on final test event')
}
const time: number = lastEvent.Elapsed * 1000
let error: TestCaseError | undefined = undefined
if (result !== 'success') {
const outputEvents = eventGroup
.filter(e => e.Action === 'output')
.map(e => e.Output ?? '')
// Go output prepends indentation to help group tests - remove it
.map(o => o.replace(/^ /, ''))
// First and last lines will be generic "test started" and "test finished" lines - remove them
outputEvents.splice(0, 1)
outputEvents.splice(-1, 1)
const details = outputEvents.join('')
error = {
message: details,
details: details
}
}
group.tests.push(new TestCaseResult(testName, result, time, error))
}
return new TestRunResult(path, suites)
}
}

View File

@@ -0,0 +1,19 @@
export type GoTestAction = 'start'
| 'run'
| 'pause'
| 'cont'
| 'pass'
| 'bench'
| 'fail'
| 'output'
| 'skip'
export type GoTestEvent = {
Time: string
Action: GoTestAction
Package: string
Test?: string
Elapsed?: number
Output?: string
FailedBuild?: string
}

View File

@@ -6,7 +6,7 @@ import {getFirstNonEmptyLine} from '../utils/parse-utils'
import {slug} from '../utils/slugger'
const MAX_REPORT_LENGTH = 65535
const MAX_ACTIONS_SUMMARY_LENGTH = 131072 // 1048576 soon
const MAX_ACTIONS_SUMMARY_LENGTH = 1048576
export interface ReportOptions {
listSuites: 'all' | 'failed' | 'none'
@@ -15,18 +15,20 @@ export interface ReportOptions {
onlySummary: boolean
useActionsSummary: boolean
badgeTitle: string
reportTitle: string
}
const defaultOptions: ReportOptions = {
export const DEFAULT_OPTIONS: ReportOptions = {
listSuites: 'all',
listTests: 'all',
baseUrl: '',
onlySummary: false,
useActionsSummary: true,
badgeTitle: 'tests'
badgeTitle: 'tests',
reportTitle: ''
}
export function getReport(results: TestRunResult[], options: ReportOptions = defaultOptions): string {
export function getReport(results: TestRunResult[], options: ReportOptions = DEFAULT_OPTIONS): string {
core.info('Generating check run summary')
applySort(results)
@@ -53,7 +55,7 @@ export function getReport(results: TestRunResult[], options: ReportOptions = def
return trimReport(lines, options)
}
function getMaxReportLength(options: ReportOptions = defaultOptions): number {
function getMaxReportLength(options: ReportOptions = DEFAULT_OPTIONS): number {
return options.useActionsSummary ? MAX_ACTIONS_SUMMARY_LENGTH : MAX_REPORT_LENGTH
}
@@ -101,6 +103,12 @@ function getByteLength(text: string): number {
function renderReport(results: TestRunResult[], options: ReportOptions): string[] {
const sections: string[] = []
const reportTitle: string = options.reportTitle.trim()
if (reportTitle) {
sections.push(`# ${reportTitle}`)
}
const badge = getReportBadge(results, options)
sections.push(badge)
@@ -151,14 +159,17 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
if (testRuns.length > 0 || options.onlySummary) {
const tableData = testRuns
.filter(tr => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
.map(tr => {
.map((tr, originalIndex) => ({tr, originalIndex}))
.filter(({tr}) => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
.map(({tr, originalIndex}) => {
const time = formatTime(tr.time)
const name = tr.path
const addr = options.baseUrl + makeRunSlug(originalIndex, options).link
const nameLink = link(name, addr)
const passed = tr.passed > 0 ? `${tr.passed} ${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed} ${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped} ${Icon.skip}` : ''
return [name, passed, failed, skipped, time]
return [nameLink, passed, failed, skipped, time]
})
const resultsTable = table(
@@ -185,7 +196,7 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites
if (options.listSuites !== 'none') {
const trSlug = makeRunSlug(runIndex)
const trSlug = makeRunSlug(runIndex, options)
const nameLink = `<a id="${trSlug.id}" href="${options.baseUrl + trSlug.link}">${tr.path}</a>`
const icon = getResultIcon(tr.result)
sections.push(`## ${icon}\xa0${nameLink}`)
@@ -205,7 +216,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 = options.baseUrl + makeSuiteSlug(runIndex, suiteIndex).link
const tsAddr = options.baseUrl + makeSuiteSlug(runIndex, suiteIndex, options).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}` : ''
@@ -240,7 +251,7 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
const sections: string[] = []
const tsName = ts.name
const tsSlug = makeSuiteSlug(runIndex, suiteIndex)
const tsSlug = makeSuiteSlug(runIndex, suiteIndex, options)
const tsNameLink = `<a id="${tsSlug.id}" href="${options.baseUrl + tsSlug.link}">${tsName}</a>`
const icon = getResultIcon(ts.result)
sections.push(`### ${icon}\xa0${tsNameLink}`)
@@ -252,6 +263,9 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
}
const space = grp.name ? ' ' : ''
for (const tc of grp.tests) {
if (options.listTests === 'failed' && tc.result !== 'failed') {
continue
}
const result = getResultIcon(tc.result)
sections.push(`${space}${result} ${tc.name}`)
if (tc.error) {
@@ -269,14 +283,14 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
return sections
}
function makeRunSlug(runIndex: number): {id: string; link: string} {
function makeRunSlug(runIndex: number, options: ReportOptions): {id: string; link: string} {
// use prefix to avoid slug conflicts after escaping the paths
return slug(`r${runIndex}`)
return slug(`r${runIndex}`, options)
}
function makeSuiteSlug(runIndex: number, suiteIndex: number): {id: string; link: string} {
function makeSuiteSlug(runIndex: number, suiteIndex: number, options: ReportOptions): {id: string; link: string} {
// use prefix to avoid slug conflicts after escaping the paths
return slug(`r${runIndex}s${suiteIndex}`)
return slug(`r${runIndex}s${suiteIndex}`, options)
}
function getResultIcon(result: TestExecutionResult): string {

View File

@@ -2,16 +2,17 @@ import {createWriteStream} from 'fs'
import * as core from '@actions/core'
import * as github from '@actions/github'
import {GitHub} from '@actions/github/lib/utils'
import type {PullRequest} from '@octokit/webhooks-types'
import type {PullRequest, WorkflowRunEvent} from '@octokit/webhooks-types'
import {IncomingMessage} from 'http'
import * as stream from 'stream'
import {promisify} from 'util'
import got from 'got'
import got, {Progress} from 'got'
const asyncStream = promisify(stream.pipeline)
export function getCheckRunContext(): {sha: string; runId: number} {
if (github.context.eventName === 'workflow_run') {
core.info('Action was triggered by workflow_run: using SHA and RUN_ID from triggering workflow')
const event = github.context.payload
const event = github.context.payload as WorkflowRunEvent
if (!event.workflow_run) {
throw new Error("Event of type 'workflow_run' is missing 'workflow_run' field")
}
@@ -54,11 +55,11 @@ export async function downloadArtifact(
const downloadStream = got.stream(req.url, {headers})
const fileWriterStream = createWriteStream(fileName)
downloadStream.on('redirect', response => {
downloadStream.on('redirect', (response: IncomingMessage) => {
core.info(`Downloading ${response.headers.location}`)
})
downloadStream.on('downloadProgress', ({transferred}) => {
core.info(`Progress: ${transferred} B`)
downloadStream.on('downloadProgress', (progress: Progress) => {
core.info(`Progress: ${progress.transferred} B`)
})
await asyncStream(downloadStream, fileWriterStream)

View File

@@ -1,7 +1,9 @@
// Returns HTML element id and href link usable as manual anchor links
// This is needed because Github in check run summary doesn't automatically
// create links out of headings as it normally does for other markdown content
export function slug(name: string): {id: string; link: string} {
import {ReportOptions} from '../report/get-report'
export function slug(name: string, options: ReportOptions): {id: string; link: string} {
const slugId = name
.trim()
.replace(/_/g, '')
@@ -9,6 +11,7 @@ export function slug(name: string): {id: string; link: string} {
.replace(/[^\w-]/g, '')
const id = `user-content-${slugId}`
const link = `#${slugId}`
// When using the Action Summary for display, links must include the "user-content-" prefix.
const link = options.useActionsSummary ? `#${id}` : `#${slugId}`
return {id, link}
}

View File

@@ -8,6 +8,7 @@
"esModuleInterop": true,
"skipLibCheck": true,
"moduleResolution": "node16",
"isolatedModules": true,
"outDir": "./lib",
"rootDir": "./src",