Compare commits

..

No commits in common. "main" and "v2.0.0" have entirely different histories.
main ... v2.0.0

84 changed files with 5363 additions and 16801 deletions

View file

@ -21,10 +21,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Set Node.js - name: Set Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
@ -46,7 +46,7 @@ jobs:
id: diff id: diff
# If index.js was different than expected, upload the expected version as an artifact # If index.js was different than expected, upload the expected version as an artifact
- uses: actions/upload-artifact@v5 - uses: actions/upload-artifact@v4
if: ${{ failure() && steps.diff.conclusion == 'failure' }} if: ${{ failure() && steps.diff.conclusion == 'failure' }}
with: with:
name: dist name: dist

View file

@ -13,8 +13,8 @@ jobs:
name: Build & Test name: Build & Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
- run: npm ci - run: npm ci
@ -24,8 +24,8 @@ jobs:
- run: npm test - run: npm test
- name: Upload test results - name: Upload test results
if: ${{ !cancelled() }} if: success() || failure()
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v4
with: with:
name: test-results name: test-results
path: __tests__/__results__/*.xml path: __tests__/__results__/*.xml

View file

@ -8,14 +8,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- run: npm ci - run: npm ci
- run: npm run build - run: npm run build
- run: npm test - run: npm test
- name: Create test report - name: Create test report
uses: ./ uses: ./
if: ${{ !cancelled() }} if: success() || failure()
with: with:
name: JEST Tests name: JEST Tests
path: __tests__/__results__/*.xml path: __tests__/__results__/*.xml

View file

@ -11,7 +11,7 @@ jobs:
name: Workflow test name: Workflow test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- uses: ./ - uses: ./
with: with:
artifact: test-results artifact: test-results

View file

@ -1,13 +0,0 @@
{
"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,38 +1,5 @@
# Changelog # Changelog
## 2.3.0
* Feature: Add Python support with `python-xunit` reporter (pytest) https://github.com/dorny/test-reporter/pull/643
* Feature: Add pytest traceback parsing and `directory-mapping` option https://github.com/dorny/test-reporter/pull/238
* Performance: Update sax.js to fix large XML file parsing https://github.com/dorny/test-reporter/pull/681
* Documentation: Complete documentation for all supported reporters https://github.com/dorny/test-reporter/pull/691
* Security: Bump js-yaml and mocha in /reports/mocha (fixes prototype pollution) https://github.com/dorny/test-reporter/pull/682
## 2.2.0
* Feature: Add collapsed option to control report summary visibility https://github.com/dorny/test-reporter/pull/664
* Fix badge encoding for values including underscore and hyphens https://github.com/dorny/test-reporter/pull/672
* Fix missing `report-title` attribute in action definition https://github.com/dorny/test-reporter/pull/637
* Refactor variable names to fix shadowing issues https://github.com/dorny/test-reporter/pull/630
## 2.1.1
* Fix error when a TestMethod element does not have a className attribute in a trx file https://github.com/dorny/test-reporter/pull/623
* Add stack trace from trx to summary https://github.com/dorny/test-reporter/pull/615
* List only failed tests https://github.com/dorny/test-reporter/pull/606
* Add type definitions to `github-utils.ts` https://github.com/dorny/test-reporter/pull/604
* Avoid split on undefined https://github.com/dorny/test-reporter/pull/258
* Return links to summary report https://github.com/dorny/test-reporter/pull/588
* Add step summary short summary https://github.com/dorny/test-reporter/pull/589
* Fix for empty TRX TestDefinitions https://github.com/dorny/test-reporter/pull/582
* Increase step summary limit to 1MiB https://github.com/dorny/test-reporter/pull/581
* Fix input description for list options https://github.com/dorny/test-reporter/pull/572
## 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 ## 2.0.0
* Parse JUnit report with detailed message in failure https://github.com/dorny/test-reporter/pull/559 * 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 * Support displaying test results in markdown using GitHub Actions Job Summaries https://github.com/dorny/test-reporter/pull/383

View file

@ -9,18 +9,15 @@ This [Github Action](https://github.com/features/actions) displays test results
✔️ Provides final `conclusion` and counts of `passed`, `failed` and `skipped` tests as output parameters ✔️ Provides final `conclusion` and counts of `passed`, `failed` and `skipped` tests as output parameters
**How it looks:** **How it looks:**
|![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)| |![](assets/fluent-validation-report.png)|![](assets/provider-error-summary.png)|![](assets/provider-error-details.png)|![](assets/mocha-groups.png)|
|:--:|:--:|:--:|:--:| |:--:|:--:|:--:|:--:|
**Supported languages / frameworks:** **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) ) - .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) - Dart / [test](https://pub.dev/packages/test)
- Flutter / [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/) - Java / [JUnit](https://junit.org/)
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/) - JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
- Python / [pytest](https://docs.pytest.org/en/stable/) / [unittest](https://docs.python.org/3/library/unittest.html)
- Ruby / [RSpec](https://rspec.info/)
- Swift / xUnit - Swift / xUnit
For more information see [Supported formats](#supported-formats) section. For more information see [Supported formats](#supported-formats) section.
@ -52,7 +49,7 @@ jobs:
- name: Test Report - name: Test Report
uses: dorny/test-reporter@v2 uses: dorny/test-reporter@v2
if: ${{ !cancelled() }} # run this step even if previous step failed if: success() || failure() # run this step even if previous step failed
with: with:
name: JEST Tests # Name of the check run which will be created name: JEST Tests # Name of the check run which will be created
path: reports/jest-*.xml # Path to test results path: reports/jest-*.xml # Path to test results
@ -81,7 +78,7 @@ jobs:
- run: npm ci # install packages - run: npm ci # install packages
- run: npm test # run tests (configured to use jest-junit reporter) - run: npm test # run tests (configured to use jest-junit reporter)
- uses: actions/upload-artifact@v4 # upload test results - uses: actions/upload-artifact@v4 # upload test results
if: ${{ !cancelled() }} # run this step even if previous step failed if: success() || failure() # run this step even if previous step failed
with: with:
name: test-results name: test-results
path: jest-junit.xml path: jest-junit.xml
@ -143,13 +140,10 @@ jobs:
# dotnet-nunit # dotnet-nunit
# dotnet-trx # dotnet-trx
# flutter-json # flutter-json
# golang-json
# java-junit # java-junit
# jest-junit # jest-junit
# mocha-json # mocha-json
# python-xunit
# rspec-json # rspec-json
# swift-xunit
reporter: '' reporter: ''
# Allows you to generate only the summary. # Allows you to generate only the summary.
@ -161,11 +155,6 @@ jobs:
# https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/ # https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/
use-actions-summary: 'true' 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. # Customize the title of badges shown for each Actions Summary.
# Useful when distinguish summaries for tests ran in multiple Actions steps. # Useful when distinguish summaries for tests ran in multiple Actions steps.
badge-title: 'tests' badge-title: 'tests'
@ -257,20 +246,6 @@ Supported testing frameworks:
For more information see [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#examples) For more information see [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#examples)
</details> </details>
<details>
<summary>dotnet-nunit</summary>
Test execution must be configured to generate [NUnit3](https://docs.nunit.org/articles/nunit/technical-notes/usage/Test-Result-XML-Format.html) XML test results.
Install the [NUnit3TestAdapter](https://www.nuget.org/packages/NUnit3TestAdapter) package (required; it registers the `nunit` logger for `dotnet test`), then run tests with:
`dotnet test --logger "nunit;LogFileName=test-results.xml"`
Supported testing frameworks:
- [NUnit](https://nunit.org/)
For more information see [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#examples)
</details>
<details> <details>
<summary>flutter-json</summary> <summary>flutter-json</summary>
@ -298,13 +273,6 @@ For more information see:
</details> </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> <details>
<summary>java-junit (Experimental)</summary> <summary>java-junit (Experimental)</summary>
@ -367,41 +335,6 @@ Before version [v9.1.0](https://github.com/mochajs/mocha/releases/tag/v9.1.0), M
Please update Mocha to version [v9.1.0](https://github.com/mochajs/mocha/releases/tag/v9.1.0) or above if you encounter this issue. Please update Mocha to version [v9.1.0](https://github.com/mochajs/mocha/releases/tag/v9.1.0) or above if you encounter this issue.
</details> </details>
<details>
<summary>python-xunit (Experimental)</summary>
Support for Python test results in xUnit format is experimental - should work but it was not extensively tested.
For **pytest** support, configure [JUnit XML output](https://docs.pytest.org/en/stable/how-to/output.html#creating-junitxml-format-files) and run with the `--junit-xml` option, which also lets you specify the output path for test results.
```shell
pytest --junit-xml=test-report.xml
```
For **unittest** support, use a test runner that outputs the JUnit report format, such as [unittest-xml-reporting](https://pypi.org/project/unittest-xml-reporting/).
</details>
<details>
<summary>rspec-json</summary>
[RSpec](https://rspec.info/) testing framework support requires the usage of JSON formatter.
You can configure RSpec to output JSON format by using the `--format json` option and redirecting to a file:
```shell
rspec --format json --out rspec-results.json
```
Or configure it in `.rspec` file:
```
--format json
--out rspec-results.json
```
For more information see:
- [RSpec documentation](https://rspec.info/)
- [RSpec Formatters](https://relishapp.com/rspec/rspec-core/docs/formatters)
</details>
<details> <details>
<summary>swift-xunit (Experimental)</summary> <summary>swift-xunit (Experimental)</summary>
@ -412,7 +345,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: Unfortunately, there are some known issues and limitations caused by GitHub API:
- Test report (i.e. build summary) is Markdown text. No custom styling or HTML is possible. - Test report (i.e. Check Run summary) is markdown text. No custom styling or HTML is possible.
- Maximum report size is 65535 bytes. Input parameters `list-suites` and `list-tests` will be automatically adjusted if max size is exceeded. - 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. - 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 - 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) ![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%204%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/dart-json.json](#user-content-r0)|1 ✅|4 ❌|1 ⚪|4s| |fixtures/dart-json.json|1 ✅|4 ❌|1 ⚪|4s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dart-json.json</a> ## ❌ <a id="user-content-r0" href="#r0">fixtures/dart-json.json</a>
**6** tests were completed in **4s** with **1** passed, **4** failed and **1** skipped. **6** tests were completed in **4s** with **1** passed, **4** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[test/main_test.dart](#user-content-r0s0)|1 ✅|3 ❌||74ms| |[test/main_test.dart](#r0s0)|1 ✅|3 ❌||74ms|
|[test/second_test.dart](#user-content-r0s1)||1 ❌|1 ⚪|51ms| |[test/second_test.dart](#r0s1)||1 ❌|1 ⚪|51ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">test/main_test.dart</a> ### ❌ <a id="user-content-r0s0" href="#r0s0">test/main_test.dart</a>
``` ```
Test 1 Test 1
✅ Passing test ✅ Passing test
@ -23,7 +23,7 @@ Test 2
❌ Exception in test ❌ Exception in test
Exception: Some error Exception: Some error
``` ```
### ❌ <a id="user-content-r0s1" href="#user-content-r0s1">test/second_test.dart</a> ### ❌ <a id="user-content-r0s1" href="#r0s1">test/second_test.dart</a>
``` ```
❌ Timeout test ❌ Timeout test
TimeoutException after 0:00:00.000001: Test timed out after 0 seconds. 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) ![Tests failed](https://img.shields.io/badge/tests-3%20passed%2C%205%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/dotnet-nunit.xml](#user-content-r0)|3 ✅|5 ❌|1 ⚪|230ms| |fixtures/dotnet-nunit.xml|3 ✅|5 ❌|1 ⚪|230ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dotnet-nunit.xml</a> ## ❌ <a id="user-content-r0" href="#r0">fixtures/dotnet-nunit.xml</a>
**9** tests were completed in **230ms** with **3** passed, **5** failed and **1** skipped. **9** tests were completed in **230ms** with **3** passed, **5** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests](#user-content-r0s0)|3 ✅|5 ❌|1 ⚪|69ms| |[DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests](#r0s0)|3 ✅|5 ❌|1 ⚪|69ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests</a> ### ❌ <a id="user-content-r0s0" href="#r0s0">DotnetTests.NUnitV3Tests.dll.DotnetTests.XUnitTests</a>
``` ```
CalculatorTests CalculatorTests
✅ Is_Even_Number(2) ✅ Is_Even_Number(2)

View file

@ -1,34 +0,0 @@
![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,40 +1,34 @@
![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%205%20failed%2C%201%20skipped-critical) ![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%205%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/dotnet-trx.trx](#user-content-r0)|5 ✅|5 ❌|1 ⚪|1s| |fixtures/dotnet-trx.trx|5 ✅|5 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dotnet-trx.trx</a> ## ❌ <a id="user-content-r0" href="#r0">fixtures/dotnet-trx.trx</a>
**11** tests were completed in **1s** with **5** passed, **5** failed and **1** skipped. **11** tests were completed in **1s** with **5** passed, **5** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[DotnetTests.XUnitTests.CalculatorTests](#user-content-r0s0)|5 ✅|5 ❌|1 ⚪|118ms| |[DotnetTests.XUnitTests.CalculatorTests](#r0s0)|5 ✅|5 ❌|1 ⚪|118ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">DotnetTests.XUnitTests.CalculatorTests</a> ### ❌ <a id="user-content-r0s0" href="#r0s0">DotnetTests.XUnitTests.CalculatorTests</a>
``` ```
✅ Custom Name ✅ Custom Name
❌ Exception_In_TargetTest ❌ Exception_In_TargetTest
System.DivideByZeroException : Attempted to divide by zero. 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 ❌ Exception_In_Test
System.Exception : 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 ❌ Failing_Test
Assert.Equal() Failure Assert.Equal() Failure
Expected: 3 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
✅ Is_Even_Number(i: 2) ✅ Is_Even_Number(i: 2)
❌ Is_Even_Number(i: 3) ❌ Is_Even_Number(i: 3)
Assert.True() Failure Assert.True() Failure
Expected: True 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
✅ Passing_Test ✅ Passing_Test
✅ Should be even number(i: 2) ✅ Should be even number(i: 2)
❌ Should be even number(i: 3) ❌ Should be even number(i: 3)
Assert.True() Failure Assert.True() Failure
Expected: True 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
⚪ Skipped_Test ⚪ Skipped_Test
✅ Timeout_Test ✅ Timeout_Test
``` ```

View file

@ -1,26 +0,0 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%203%20failed-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/dotnet-xunitv3.trx](#user-content-r0)|1 ✅|3 ❌||267ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/dotnet-xunitv3.trx</a>
**4** tests were completed in **267ms** with **1** passed, **3** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[DotnetTests.XUnitV3Tests.FixtureTests](#user-content-r0s0)|1 ✅|1 ❌||18ms|
|[Unclassified](#user-content-r0s1)||2 ❌||0ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">DotnetTests.XUnitV3Tests.FixtureTests</a>
```
❌ Failing_Test
Assert.Null() Failure: Value is not null
Expected: null
Actual: Fixture { }
at DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test() in /_/reports/dotnet/DotnetTests.XUnitV3Tests/FixtureTests.cs:line 25
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
✅ Passing_Test
```
### ❌ <a id="user-content-r0s1" href="#user-content-r0s1">Unclassified</a>
```
❌ [Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test)]
❌ [Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test)]
```

View file

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

View file

@ -1,38 +0,0 @@
![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| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/jest-junit-eslint.xml](#user-content-r0)|1 ✅|||0ms| |fixtures/jest-junit-eslint.xml|1 ✅|||0ms|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/jest-junit-eslint.xml</a> ## ✅ <a id="user-content-r0" href="#r0">fixtures/jest-junit-eslint.xml</a>
**1** tests were completed in **0ms** with **1** passed, **0** failed and **0** skipped. **1** tests were completed in **0ms** with **1** passed, **0** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[test.jsx](#user-content-r0s0)|1 ✅|||0ms| |[test.jsx](#r0s0)|1 ✅|||0ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">test.jsx</a> ### ✅ <a id="user-content-r0s0" href="#r0s0">test.jsx</a>
``` ```
test test
✅ test.jsx ✅ 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) ![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%204%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/jest-junit.xml](#user-content-r0)|1 ✅|4 ❌|1 ⚪|1s| |fixtures/jest-junit.xml|1 ✅|4 ❌|1 ⚪|1s|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/jest-junit.xml</a> ## ❌ <a id="user-content-r0" href="#r0">fixtures/jest-junit.xml</a>
**6** tests were completed in **1s** with **1** passed, **4** failed and **1** skipped. **6** tests were completed in **1s** with **1** passed, **4** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[__tests__\main.test.js](#user-content-r0s0)|1 ✅|3 ❌||486ms| |[__tests__\main.test.js](#r0s0)|1 ✅|3 ❌||486ms|
|[__tests__\second.test.js](#user-content-r0s1)||1 ❌|1 ⚪|82ms| |[__tests__\second.test.js](#r0s1)||1 ❌|1 ⚪|82ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">__tests__\main.test.js</a> ### ❌ <a id="user-content-r0s0" href="#r0s0">__tests__\main.test.js</a>
``` ```
Test 1 Test 1
✅ Passing test ✅ Passing test
@ -21,7 +21,7 @@ Test 2
❌ Exception in test ❌ Exception in test
Error: Some error Error: Some error
``` ```
### ❌ <a id="user-content-r0s1" href="#user-content-r0s1">__tests__\second.test.js</a> ### ❌ <a id="user-content-r0s1" href="#r0s1">__tests__\second.test.js</a>
``` ```
❌ Timeout test ❌ 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: : 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| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/external/jest/jest-react-component-test-results.xml](#user-content-r0)|1 ✅|||1000ms| |fixtures/external/jest/jest-react-component-test-results.xml|1 ✅|||1000ms|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/external/jest/jest-react-component-test-results.xml</a> ## ✅ <a id="user-content-r0" href="#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. **1** tests were completed in **1000ms** with **1** passed, **0** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[\<Component /\>](#user-content-r0s0)|1 ✅|||798ms| |[\<Component /\>](#r0s0)|1 ✅|||798ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">\<Component /\></a> ### ✅ <a id="user-content-r0s0" href="#r0s0">\<Component /\></a>
``` ```
<Component /> should render properly <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) ![Tests failed](https://img.shields.io/badge/tests-1%20failed-critical)
|Report|Passed|Failed|Skipped|Time| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/junit-with-message.xml](#user-content-r0)||1 ❌||1ms| |fixtures/junit-with-message.xml||1 ❌||1ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/junit-with-message.xml</a> ## ❌ <a id="user-content-r0" href="#r0">fixtures/junit-with-message.xml</a>
**1** tests were completed in **1ms** with **0** passed, **1** failed and **0** skipped. **1** tests were completed in **1ms** with **0** passed, **1** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[Test](#user-content-r0s0)||1 ❌||1ms| |[Test](#r0s0)||1 ❌||1ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">Test</a> ### ❌ <a id="user-content-r0s0" href="#r0s0">Test</a>
``` ```
Fails Fails
❌ Test ❌ Test

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -1,26 +0,0 @@
![Tests failed](https://img.shields.io/badge/tests-6%20passed%2C%202%20failed%2C%202%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/python-xunit-pytest.xml](#user-content-r0)|6 ✅|2 ❌|2 ⚪|19ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/python-xunit-pytest.xml</a>
**10** tests were completed in **19ms** with **6** passed, **2** failed and **2** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[pytest](#user-content-r0s0)|6 ✅|2 ❌|2 ⚪|19ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">pytest</a>
```
tests.test_lib
✅ test_always_pass
✅ test_with_subtests
✅ test_parameterized[param1]
✅ test_parameterized[param2]
⚪ test_always_skip
❌ test_always_fail
assert False
⚪ test_expected_failure
❌ test_error
Exception: error
✅ test_with_record_property
custom_classname
✅ test_with_record_xml_attribute
```

View file

@ -1,23 +0,0 @@
![Tests failed](https://img.shields.io/badge/tests-4%20passed%2C%202%20failed%2C%202%20skipped-critical)
|Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[fixtures/python-xunit-unittest.xml](#user-content-r0)|4 ✅|2 ❌|2 ⚪|1ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/python-xunit-unittest.xml</a>
**8** tests were completed in **1ms** with **4** passed, **2** failed and **2** skipped.
|Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:|
|[TestAcme-20251114214921](#user-content-r0s0)|4 ✅|2 ❌|2 ⚪|1ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">TestAcme-20251114214921</a>
```
TestAcme
✅ test_always_pass
✅ test_parameterized_0_param1
✅ test_parameterized_1_param2
✅ test_with_subtests
❌ test_always_fail
AssertionError: failed
❌ test_error
Exception: error
⚪ test_always_skip
⚪ test_expected_failure
```

View file

@ -1,13 +1,13 @@
![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%201%20failed%2C%201%20skipped-critical) ![Tests failed](https://img.shields.io/badge/tests-1%20passed%2C%201%20failed%2C%201%20skipped-critical)
|Report|Passed|Failed|Skipped|Time| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/rspec-json.json](#user-content-r0)|1 ✅|1 ❌|1 ⚪|0ms| |fixtures/rspec-json.json|1 ✅|1 ❌|1 ⚪|0ms|
## ❌ <a id="user-content-r0" href="#user-content-r0">fixtures/rspec-json.json</a> ## ❌ <a id="user-content-r0" href="#r0">fixtures/rspec-json.json</a>
**3** tests were completed in **0ms** with **1** passed, **1** failed and **1** skipped. **3** tests were completed in **0ms** with **1** passed, **1** failed and **1** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[./spec/config/check_env_vars_spec.rb](#user-content-r0s0)|1 ✅|1 ❌|1 ⚪|0ms| |[./spec/config/check_env_vars_spec.rb](#r0s0)|1 ✅|1 ❌|1 ⚪|0ms|
### ❌ <a id="user-content-r0s0" href="#user-content-r0s0">./spec/config/check_env_vars_spec.rb</a> ### ❌ <a id="user-content-r0s0" href="#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
❌ CheckEnvVars#call when all env vars are defined behaves like success load fails in assertion ❌ 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| |Report|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[fixtures/external/SilentNotes.trx](#user-content-r0)|67 ✅||12 ⚪|1s| |fixtures/external/SilentNotes.trx|67 ✅||12 ⚪|1s|
## ✅ <a id="user-content-r0" href="#user-content-r0">fixtures/external/SilentNotes.trx</a> ## ✅ <a id="user-content-r0" href="#r0">fixtures/external/SilentNotes.trx</a>
**79** tests were completed in **1s** with **67** passed, **0** failed and **12** skipped. **79** tests were completed in **1s** with **67** passed, **0** failed and **12** skipped.
|Test suite|Passed|Failed|Skipped|Time| |Test suite|Passed|Failed|Skipped|Time|
|:---|---:|---:|---:|---:| |:---|---:|---:|---:|---:|
|[VanillaCloudStorageClientTest.CloudStorageCredentialsTest](#user-content-r0s0)|6 ✅|||30ms| |[VanillaCloudStorageClientTest.CloudStorageCredentialsTest](#r0s0)|6 ✅|||30ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest](#user-content-r0s1)|2 ✅||3 ⚪|101ms| |[VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest](#r0s1)|2 ✅||3 ⚪|101ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest](#user-content-r0s2)|4 ✅||3 ⚪|166ms| |[VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest](#r0s2)|4 ✅||3 ⚪|166ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest](#user-content-r0s3)|2 ✅|||7ms| |[VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest](#r0s3)|2 ✅|||7ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest](#user-content-r0s4)|1 ✅||3 ⚪|40ms| |[VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest](#r0s4)|1 ✅||3 ⚪|40ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest](#user-content-r0s5)|1 ✅||3 ⚪|15ms| |[VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest](#r0s5)|1 ✅||3 ⚪|15ms|
|[VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest](#user-content-r0s6)|5 ✅|||16ms| |[VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest](#r0s6)|5 ✅|||16ms|
|[VanillaCloudStorageClientTest.CloudStorageTokenTest](#user-content-r0s7)|9 ✅|||0ms| |[VanillaCloudStorageClientTest.CloudStorageTokenTest](#r0s7)|9 ✅|||0ms|
|[VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest](#user-content-r0s8)|3 ✅|||3ms| |[VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest](#r0s8)|3 ✅|||3ms|
|[VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest](#user-content-r0s9)|9 ✅|||12ms| |[VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest](#r0s9)|9 ✅|||12ms|
|[VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest](#user-content-r0s10)|5 ✅|||13ms| |[VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest](#r0s10)|5 ✅|||13ms|
|[VanillaCloudStorageClientTest.SecureStringExtensionsTest](#user-content-r0s11)|7 ✅|||0ms| |[VanillaCloudStorageClientTest.SecureStringExtensionsTest](#r0s11)|7 ✅|||0ms|
|[VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest](#user-content-r0s12)|13 ✅|||43ms| |[VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest](#r0s12)|13 ✅|||43ms|
### ✅ <a id="user-content-r0s0" href="#user-content-r0s0">VanillaCloudStorageClientTest.CloudStorageCredentialsTest</a> ### ✅ <a id="user-content-r0s0" href="#r0s0">VanillaCloudStorageClientTest.CloudStorageCredentialsTest</a>
``` ```
✅ AreEqualWorksWithDifferentPassword ✅ AreEqualWorksWithDifferentPassword
✅ AreEqualWorksWithSameContent ✅ AreEqualWorksWithSameContent
@ -30,7 +30,7 @@
✅ ValidateAcceptsValidCredentials ✅ ValidateAcceptsValidCredentials
✅ ValidateRejectsInvalidCredentials ✅ ValidateRejectsInvalidCredentials
``` ```
### ✅ <a id="user-content-r0s1" href="#user-content-r0s1">VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest</a> ### ✅ <a id="user-content-r0s1" href="#r0s1">VanillaCloudStorageClientTest.CloudStorageProviders.DropboxCloudStorageClientTest</a>
``` ```
✅ FileLifecycleWorks ✅ FileLifecycleWorks
⚪ ReallyDoFetchToken ⚪ ReallyDoFetchToken
@ -38,7 +38,7 @@
⚪ ReallyDoRefreshToken ⚪ ReallyDoRefreshToken
✅ ThrowsAccessDeniedExceptionWithInvalidToken ✅ ThrowsAccessDeniedExceptionWithInvalidToken
``` ```
### ✅ <a id="user-content-r0s2" href="#user-content-r0s2">VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest</a> ### ✅ <a id="user-content-r0s2" href="#r0s2">VanillaCloudStorageClientTest.CloudStorageProviders.FtpCloudStorageClientTest</a>
``` ```
✅ FileLifecycleWorks ✅ FileLifecycleWorks
✅ SanitizeCredentials_ChangesInvalidPrefix ✅ SanitizeCredentials_ChangesInvalidPrefix
@ -48,26 +48,26 @@
⚪ ThrowsWithInvalidUrl ⚪ ThrowsWithInvalidUrl
⚪ ThrowsWithInvalidUsername ⚪ ThrowsWithInvalidUsername
``` ```
### ✅ <a id="user-content-r0s3" href="#user-content-r0s3">VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest</a> ### ✅ <a id="user-content-r0s3" href="#r0s3">VanillaCloudStorageClientTest.CloudStorageProviders.GmxCloudStorageClientTest</a>
``` ```
✅ ChoosesCorrectUrlForGmxComEmail ✅ ChoosesCorrectUrlForGmxComEmail
✅ ChoosesCorrectUrlForGmxNetEmail ✅ ChoosesCorrectUrlForGmxNetEmail
``` ```
### ✅ <a id="user-content-r0s4" href="#user-content-r0s4">VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest</a> ### ✅ <a id="user-content-r0s4" href="#r0s4">VanillaCloudStorageClientTest.CloudStorageProviders.GoogleCloudStorageClientTest</a>
``` ```
✅ FileLifecycleWorks ✅ FileLifecycleWorks
⚪ ReallyDoFetchToken ⚪ ReallyDoFetchToken
⚪ ReallyDoOpenAuthorizationPageInBrowser ⚪ ReallyDoOpenAuthorizationPageInBrowser
⚪ ReallyDoRefreshToken ⚪ ReallyDoRefreshToken
``` ```
### ✅ <a id="user-content-r0s5" href="#user-content-r0s5">VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest</a> ### ✅ <a id="user-content-r0s5" href="#r0s5">VanillaCloudStorageClientTest.CloudStorageProviders.OnedriveCloudStorageClientTest</a>
``` ```
✅ FileLifecycleWorks ✅ FileLifecycleWorks
⚪ ReallyDoFetchToken ⚪ ReallyDoFetchToken
⚪ ReallyDoOpenAuthorizationPageInBrowser ⚪ ReallyDoOpenAuthorizationPageInBrowser
⚪ ReallyDoRefreshToken ⚪ ReallyDoRefreshToken
``` ```
### ✅ <a id="user-content-r0s6" href="#user-content-r0s6">VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest</a> ### ✅ <a id="user-content-r0s6" href="#r0s6">VanillaCloudStorageClientTest.CloudStorageProviders.WebdavCloudStorageClientTest</a>
``` ```
✅ FileLifecycleWorks ✅ FileLifecycleWorks
✅ ParseGmxWebdavResponseCorrectly ✅ ParseGmxWebdavResponseCorrectly
@ -75,7 +75,7 @@
✅ ThrowsWithInvalidPath ✅ ThrowsWithInvalidPath
✅ ThrowsWithInvalidUsername ✅ ThrowsWithInvalidUsername
``` ```
### ✅ <a id="user-content-r0s7" href="#user-content-r0s7">VanillaCloudStorageClientTest.CloudStorageTokenTest</a> ### ✅ <a id="user-content-r0s7" href="#r0s7">VanillaCloudStorageClientTest.CloudStorageTokenTest</a>
``` ```
✅ AreEqualWorksWithNullDate ✅ AreEqualWorksWithNullDate
✅ AreEqualWorksWithSameContent ✅ AreEqualWorksWithSameContent
@ -87,13 +87,13 @@
✅ SetExpiryDateBySecondsWorksWithNull ✅ SetExpiryDateBySecondsWorksWithNull
✅ SetExpiryDateBySecondsWorksWithVeryShortPeriod ✅ SetExpiryDateBySecondsWorksWithVeryShortPeriod
``` ```
### ✅ <a id="user-content-r0s8" href="#user-content-r0s8">VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest</a> ### ✅ <a id="user-content-r0s8" href="#r0s8">VanillaCloudStorageClientTest.OAuth2.AuthorizationResponseErrorTest</a>
``` ```
✅ ParsesAllErrorCodesCorrectly ✅ ParsesAllErrorCodesCorrectly
✅ ParsesNullErrorCodeCorrectly ✅ ParsesNullErrorCodeCorrectly
✅ ParsesUnknownErrorCodeCorrectly ✅ ParsesUnknownErrorCodeCorrectly
``` ```
### ✅ <a id="user-content-r0s9" href="#user-content-r0s9">VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest</a> ### ✅ <a id="user-content-r0s9" href="#r0s9">VanillaCloudStorageClientTest.OAuth2.OAuth2UtilsTest</a>
``` ```
✅ BuildAuthorizationRequestUrlEscapesParameters ✅ BuildAuthorizationRequestUrlEscapesParameters
✅ BuildAuthorizationRequestUrlLeavesOutOptionalParameters ✅ BuildAuthorizationRequestUrlLeavesOutOptionalParameters
@ -105,7 +105,7 @@
✅ ParseRealWorldGoogleRejectResponse ✅ ParseRealWorldGoogleRejectResponse
✅ ParseRealWorldGoogleSuccessResponse ✅ ParseRealWorldGoogleSuccessResponse
``` ```
### ✅ <a id="user-content-r0s10" href="#user-content-r0s10">VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest</a> ### ✅ <a id="user-content-r0s10" href="#r0s10">VanillaCloudStorageClientTest.OAuth2CloudStorageClientTest</a>
``` ```
✅ BuildOAuth2AuthorizationRequestUrlWorks ✅ BuildOAuth2AuthorizationRequestUrlWorks
✅ FetchTokenCanInterpretGoogleResponse ✅ FetchTokenCanInterpretGoogleResponse
@ -113,7 +113,7 @@
✅ FetchTokenThrowsWithWrongState ✅ FetchTokenThrowsWithWrongState
✅ RefreshTokenCanInterpretGoogleResponse ✅ RefreshTokenCanInterpretGoogleResponse
``` ```
### ✅ <a id="user-content-r0s11" href="#user-content-r0s11">VanillaCloudStorageClientTest.SecureStringExtensionsTest</a> ### ✅ <a id="user-content-r0s11" href="#r0s11">VanillaCloudStorageClientTest.SecureStringExtensionsTest</a>
``` ```
✅ AreEqualsWorksCorrectly ✅ AreEqualsWorksCorrectly
✅ CorrectlyConvertsSecureStringToString ✅ CorrectlyConvertsSecureStringToString
@ -123,7 +123,7 @@
✅ CorrectlyConvertsUnicodeBytesToSecureString ✅ CorrectlyConvertsUnicodeBytesToSecureString
✅ CorrectlyConvertsUtf8BytesToSecureString ✅ CorrectlyConvertsUtf8BytesToSecureString
``` ```
### ✅ <a id="user-content-r0s12" href="#user-content-r0s12">VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest</a> ### ✅ <a id="user-content-r0s12" href="#r0s12">VanillaCloudStorageClientTest.SerializeableCloudStorageCredentialsTest</a>
``` ```
✅ DecryptAfterDesrializationCanReadAllPropertiesBack ✅ DecryptAfterDesrializationCanReadAllPropertiesBack
✅ DecryptAfterDesrializationRespectsNullProperties ✅ DecryptAfterDesrializationRespectsNullProperties

View file

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

View file

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`dart-json tests matches report snapshot 1`] = ` exports[`dart-json tests matches report snapshot 1`] = `
TestRunResult { TestRunResult {

View file

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`dotnet-nunit tests report from ./reports/dotnet test results matches snapshot 1`] = ` exports[`dotnet-nunit tests report from ./reports/dotnet test results matches snapshot 1`] = `
TestRunResult { TestRunResult {

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`dotnet-trx tests matches dotnet-trx report snapshot 1`] = ` exports[`dotnet-trx tests matches report snapshot 1`] = `
TestRunResult { TestRunResult {
"path": "fixtures/dotnet-trx.trx", "path": "fixtures/dotnet-trx.trx",
"suites": [ "suites": [
@ -21,9 +21,7 @@ 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.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", 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, "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", "path": "DotnetTests.Unit/Calculator.cs",
}, },
"name": "Exception_In_TargetTest", "name": "Exception_In_TargetTest",
@ -35,8 +33,7 @@ TestRunResult {
"details": "System.Exception : Test "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", 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, "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", "path": "DotnetTests.XUnitTests/CalculatorTests.cs",
}, },
"name": "Exception_In_Test", "name": "Exception_In_Test",
@ -52,8 +49,7 @@ Actual: 2
"line": 27, "line": 27,
"message": "Assert.Equal() Failure "message": "Assert.Equal() Failure
Expected: 3 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", "path": "DotnetTests.XUnitTests/CalculatorTests.cs",
}, },
"name": "Failing_Test", "name": "Failing_Test",
@ -75,8 +71,7 @@ Actual: False
"line": 59, "line": 59,
"message": "Assert.True() Failure "message": "Assert.True() Failure
Expected: True 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", "path": "DotnetTests.XUnitTests/CalculatorTests.cs",
}, },
"name": "Is_Even_Number(i: 3)", "name": "Is_Even_Number(i: 3)",
@ -104,213 +99,7 @@ Actual: False
"line": 67, "line": 67,
"message": "Assert.True() Failure "message": "Assert.True() Failure
Expected: True 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 dotnet-xunitv3 report snapshot 1`] = `
TestRunResult {
"path": "fixtures/dotnet-xunitv3.trx",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": null,
"tests": [
TestCaseResult {
"error": {
"details": "Assert.Null() Failure: Value is not null
Expected: null
Actual: Fixture { }
at DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test() in /_/reports/dotnet/DotnetTests.XUnitV3Tests/FixtureTests.cs:line 25
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)",
"line": 25,
"message": "Assert.Null() Failure: Value is not null
Expected: null
Actual: Fixture { }
at DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test() in /_/reports/dotnet/DotnetTests.XUnitV3Tests/FixtureTests.cs:line 25
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)",
"path": "DotnetTests.XUnitV3Tests/FixtureTests.cs",
},
"name": "Failing_Test",
"result": "failed",
"time": 17.0545,
},
TestCaseResult {
"error": undefined,
"name": "Passing_Test",
"result": "success",
"time": 0.8786,
},
],
},
],
"name": "DotnetTests.XUnitV3Tests.FixtureTests",
"totalTime": undefined,
},
TestSuiteResult {
"groups": [
TestGroupResult {
"name": null,
"tests": [
TestCaseResult {
"error": undefined,
"name": "[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test)]",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test)]",
"result": "failed",
"time": 0,
},
],
},
],
"name": "Unclassified",
"totalTime": undefined,
},
],
"totalTime": 267,
}
`;
exports[`dotnet-trx tests matches report snapshot (only failed tests) 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", "path": "DotnetTests.XUnitTests/CalculatorTests.cs",
}, },
"name": "Should be even number(i: 3)", "name": "Should be even number(i: 3)",

View file

@ -1,131 +0,0 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
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

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`java-junit tests report from apache/pulsar single suite test results matches snapshot 1`] = ` exports[`java-junit tests report from apache/pulsar single suite test results matches snapshot 1`] = `
TestRunResult { TestRunResult {

View file

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`jest-junit tests parsing ESLint report without timing information works - PR #134 1`] = ` exports[`jest-junit tests parsing ESLint report without timing information works - PR #134 1`] = `
TestRunResult { TestRunResult {

View file

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`mocha-json tests report from ./reports/mocha-json test results matches snapshot 1`] = ` exports[`mocha-json tests report from ./reports/mocha-json test results matches snapshot 1`] = `
TestRunResult { TestRunResult {

View file

@ -1,192 +0,0 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`python-xunit pytest report report from python test results matches snapshot 1`] = `
TestRunResult {
"path": "fixtures/python-xunit-pytest.xml",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": "tests.test_lib",
"tests": [
TestCaseResult {
"error": undefined,
"name": "test_always_pass",
"result": "success",
"time": 2,
},
TestCaseResult {
"error": undefined,
"name": "test_with_subtests",
"result": "success",
"time": 5,
},
TestCaseResult {
"error": undefined,
"name": "test_parameterized[param1]",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_parameterized[param2]",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_always_skip",
"result": "skipped",
"time": 0,
},
TestCaseResult {
"error": {
"details": "def test_always_fail():
> assert False
E assert False
tests/test_lib.py:25: AssertionError
",
"line": undefined,
"message": "assert False",
"path": undefined,
},
"name": "test_always_fail",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_expected_failure",
"result": "skipped",
"time": 0,
},
TestCaseResult {
"error": {
"details": "def test_error():
> raise Exception("error")
E Exception: error
tests/test_lib.py:32: Exception
",
"line": undefined,
"message": "Exception: error",
"path": undefined,
},
"name": "test_error",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_with_record_property",
"result": "success",
"time": 0,
},
],
},
TestGroupResult {
"name": "custom_classname",
"tests": [
TestCaseResult {
"error": undefined,
"name": "test_with_record_xml_attribute",
"result": "success",
"time": 0,
},
],
},
],
"name": "pytest",
"totalTime": 19,
},
],
"totalTime": undefined,
}
`;
exports[`python-xunit unittest report report from python test results matches snapshot 1`] = `
TestRunResult {
"path": "fixtures/python-xunit-unittest.xml",
"suites": [
TestSuiteResult {
"groups": [
TestGroupResult {
"name": "TestAcme",
"tests": [
TestCaseResult {
"error": undefined,
"name": "test_always_pass",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_parameterized_0_param1",
"result": "success",
"time": 1,
},
TestCaseResult {
"error": undefined,
"name": "test_parameterized_1_param2",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_with_subtests",
"result": "success",
"time": 0,
},
TestCaseResult {
"error": {
"details": "Traceback (most recent call last):
File "/Users/foo/Projects/python-test/tests/test_lib.py", line 24, in test_always_fail
self.fail("failed")
AssertionError: failed
",
"line": undefined,
"message": "AssertionError: failed",
"path": undefined,
},
"name": "test_always_fail",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": {
"details": "Traceback (most recent call last):
File "/Users/foo/Projects/python-test/tests/test_lib.py", line 31, in test_error
raise Exception("error")
Exception: error
",
"line": undefined,
"message": "Exception: error",
"path": undefined,
},
"name": "test_error",
"result": "failed",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_always_skip",
"result": "skipped",
"time": 0,
},
TestCaseResult {
"error": undefined,
"name": "test_expected_failure",
"result": "skipped",
"time": 0,
},
],
},
],
"name": "TestAcme-20251114214921",
"totalTime": 1,
},
],
"totalTime": 1,
}
`;

View file

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rspec-json tests report from ./reports/rspec-json test results matches snapshot 1`] = ` exports[`rspec-json tests report from ./reports/rspec-json test results matches snapshot 1`] = `
TestRunResult { TestRunResult {

View file

@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`swift-xunit tests report from swift test results matches snapshot 1`] = ` exports[`swift-xunit tests report from swift test results matches snapshot 1`] = `
TestRunResult { TestRunResult {

View file

@ -3,7 +3,7 @@ import * as path from 'path'
import {DartJsonParser} from '../src/parsers/dart-json/dart-json-parser' import {DartJsonParser} from '../src/parsers/dart-json/dart-json-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('dart-json tests', () => { describe('dart-json tests', () => {
@ -66,66 +66,4 @@ describe('dart-json tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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 {DotnetNunitParser} from '../src/parsers/dotnet-nunit/dotnet-nunit-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('dotnet-nunit tests', () => { describe('dotnet-nunit tests', () => {
@ -26,66 +26,4 @@ describe('dotnet-nunit tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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 {DotnetTrxParser} from '../src/parsers/dotnet-trx/dotnet-trx-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport, ReportOptions} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('dotnet-trx tests', () => { describe('dotnet-trx tests', () => {
@ -23,50 +23,9 @@ describe('dotnet-trx tests', () => {
expect(result.result).toBe('success') expect(result.result).toBe('success')
}) })
it('produces empty test run result when TestDefinitions is empty', async () => { it('matches report snapshot', 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.each([['dotnet-trx'], ['dotnet-xunitv3']])('matches %s report snapshot', async reportName => {
const fixturePath = path.join(__dirname, 'fixtures', `${reportName}.trx`)
const outputPath = path.join(__dirname, '__outputs__', `${reportName}.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',
'DotnetTests.XUnitV3Tests/FixtureTests.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 report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('matches report snapshot (only failed tests)', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx') const fixturePath = path.join(__dirname, 'fixtures', 'dotnet-trx.trx')
const outputPath = path.join(__dirname, '__outputs__', 'dotnet-trx-only-failed.md') const outputPath = path.join(__dirname, '__outputs__', 'dotnet-trx.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath)) const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'}) const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
@ -80,12 +39,7 @@ describe('dotnet-trx tests', () => {
const result = await parser.parse(filePath, fileContent) const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot() expect(result).toMatchSnapshot()
const reportOptions: ReportOptions = { const report = getReport([result])
...DEFAULT_OPTIONS,
listSuites: 'all',
listTests: 'failed'
}
const report = getReport([result], reportOptions)
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) fs.writeFileSync(outputPath, report)
}) })
@ -129,66 +83,4 @@ describe('dotnet-trx tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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

@ -1,60 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TestRun id="54e29175-539e-48a3-a634-3a1855a0ed38" name="@Asterix 2025-06-22 14:17:12.022" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Times creation="2025-06-22T14:17:11.756535Z" queuing="2025-06-22T14:17:11.756535Z" start="2025-06-22T14:17:11.756535Z" finish="2025-06-22T14:17:12.023063Z" />
<TestSettings name="default" id="932e6c6f-3e5b-4392-ad65-e04c1ef476b5">
<Deployment runDeploymentRoot="_Asterix_2025-06-22_14_17_12.022" />
</TestSettings>
<Results>
<UnitTestResult executionId="37242a1f-ca3e-44b3-8142-71e510480975" testId="f846a1e6-0b68-2ac6-9a66-f417926e3238" testName="DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test" computerName="Asterix" duration="00:00:00.0170545" startTime="2025-06-22T14:17:11.9339840+00:00" endTime="2025-06-22T14:17:11.9750850+00:00" testType="13CDC9D9-DDB5-4fa4-A97D-D965CCFC6D4B" outcome="Failed" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" relativeResultsDirectory="37242a1f-ca3e-44b3-8142-71e510480975">
<Output>
<ErrorInfo>
<Message>Assert.Null() Failure: Value is not null
Expected: null
Actual: Fixture { }</Message>
<StackTrace> at DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test() in /_/reports/dotnet/DotnetTests.XUnitV3Tests/FixtureTests.cs:line 25
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)</StackTrace>
</ErrorInfo>
</Output>
</UnitTestResult>
<UnitTestResult executionId="592aaafb-4dc0-49dc-b3c7-bcd81218d58a" testId="3ee930dd-8a75-92a0-0d90-373833166db1" testName="DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test" computerName="Asterix" duration="00:00:00.0008786" startTime="2025-06-22T14:17:11.9819890+00:00" endTime="2025-06-22T14:17:11.9833560+00:00" testType="13CDC9D9-DDB5-4fa4-A97D-D965CCFC6D4B" outcome="Passed" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" relativeResultsDirectory="592aaafb-4dc0-49dc-b3c7-bcd81218d58a" />
<UnitTestResult executionId="19c42d36-f4d7-4046-bcc6-dd9b85c9ca2b" testId="372fb60f-1f5b-a52e-032e-41a7556021e8" testName="[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test)]" computerName="Asterix" duration="00:00:00" startTime="2025-06-22T14:17:12.0320280+00:00" endTime="2025-06-22T14:17:12.0320290+00:00" testType="13CDC9D9-DDB5-4fa4-A97D-D965CCFC6D4B" outcome="Failed" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" relativeResultsDirectory="19c42d36-f4d7-4046-bcc6-dd9b85c9ca2b" />
<UnitTestResult executionId="b7f40170-1e2c-45ce-b5e4-5bf49fd4c360" testId="a69083a1-56b4-3da3-2d7c-66fda374fd8e" testName="[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test)]" computerName="Asterix" duration="00:00:00" startTime="2025-06-22T14:17:12.0320420+00:00" endTime="2025-06-22T14:17:12.0320430+00:00" testType="13CDC9D9-DDB5-4fa4-A97D-D965CCFC6D4B" outcome="Failed" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" relativeResultsDirectory="b7f40170-1e2c-45ce-b5e4-5bf49fd4c360" />
</Results>
<TestDefinitions>
<UnitTest name="DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test" storage="~/test-reporter/reports/dotnet/dotnettests.xunitv3tests/bin/debug/net8.0/dotnettests.xunitv3tests.dll" id="f846a1e6-0b68-2ac6-9a66-f417926e3238">
<Execution id="37242a1f-ca3e-44b3-8142-71e510480975" />
<TestMethod codeBase="~/test-reporter/reports/dotnet/DotnetTests.XUnitV3Tests/bin/Debug/net8.0/DotnetTests.XUnitV3Tests.dll" adapterTypeName="executor://30ea7c6e-dd24-4152-a360-1387158cd41d/2.0.3" className="DotnetTests.XUnitV3Tests.FixtureTests" name="DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test" />
</UnitTest>
<UnitTest name="DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test" storage="~/test-reporter/reports/dotnet/dotnettests.xunitv3tests/bin/debug/net8.0/dotnettests.xunitv3tests.dll" id="3ee930dd-8a75-92a0-0d90-373833166db1">
<Execution id="592aaafb-4dc0-49dc-b3c7-bcd81218d58a" />
<TestMethod codeBase="~/test-reporter/reports/dotnet/DotnetTests.XUnitV3Tests/bin/Debug/net8.0/DotnetTests.XUnitV3Tests.dll" adapterTypeName="executor://30ea7c6e-dd24-4152-a360-1387158cd41d/2.0.3" className="DotnetTests.XUnitV3Tests.FixtureTests" name="DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test" />
</UnitTest>
<UnitTest name="[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test)]" storage="~/test-reporter/reports/dotnet/dotnettests.xunitv3tests/bin/debug/net8.0/dotnettests.xunitv3tests.dll" id="372fb60f-1f5b-a52e-032e-41a7556021e8">
<Execution id="19c42d36-f4d7-4046-bcc6-dd9b85c9ca2b" />
<TestMethod codeBase="~/test-reporter/reports/dotnet/DotnetTests.XUnitV3Tests/bin/Debug/net8.0/DotnetTests.XUnitV3Tests.dll" adapterTypeName="executor://30ea7c6e-dd24-4152-a360-1387158cd41d/2.0.3" name="[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Passing_Test)]" />
</UnitTest>
<UnitTest name="[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test)]" storage="~/test-reporter/reports/dotnet/dotnettests.xunitv3tests/bin/debug/net8.0/dotnettests.xunitv3tests.dll" id="a69083a1-56b4-3da3-2d7c-66fda374fd8e">
<Execution id="b7f40170-1e2c-45ce-b5e4-5bf49fd4c360" />
<TestMethod codeBase="~/test-reporter/reports/dotnet/DotnetTests.XUnitV3Tests/bin/Debug/net8.0/DotnetTests.XUnitV3Tests.dll" adapterTypeName="executor://30ea7c6e-dd24-4152-a360-1387158cd41d/2.0.3" name="[Test Class Cleanup Failure (DotnetTests.XUnitV3Tests.FixtureTests.Failing_Test)]" />
</UnitTest>
</TestDefinitions>
<TestEntries>
<TestEntry testId="f846a1e6-0b68-2ac6-9a66-f417926e3238" executionId="37242a1f-ca3e-44b3-8142-71e510480975" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" />
<TestEntry testId="3ee930dd-8a75-92a0-0d90-373833166db1" executionId="592aaafb-4dc0-49dc-b3c7-bcd81218d58a" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" />
<TestEntry testId="372fb60f-1f5b-a52e-032e-41a7556021e8" executionId="19c42d36-f4d7-4046-bcc6-dd9b85c9ca2b" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" />
<TestEntry testId="a69083a1-56b4-3da3-2d7c-66fda374fd8e" executionId="b7f40170-1e2c-45ce-b5e4-5bf49fd4c360" testListId="8C84FA94-04C1-424b-9868-57A2D4851A1D" />
</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="Failed">
<Counters total="4" executed="4" passed="1" failed="3" 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="Asterix" outcome="Error" timestamp="2025-06-22T14:17:12.033401">
<Text>Exit code indicates failure: '2'. Please refer to https://aka.ms/testingplatform/exitcodes for more information.</Text>
</RunInfo>
</RunInfos>
</ResultSummary>
</TestRun>

View file

@ -1,22 +0,0 @@
<?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

@ -1,59 +0,0 @@
{"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

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<testsuites name="pytest tests">
<testsuite name="pytest" errors="0" failures="2" skipped="2" tests="15" time="0.019"
timestamp="2025-11-15T11:51:49.548396-05:00" hostname="Mac.hsd1.va.comcast.net">
<properties>
<property name="custom_prop" value="custom_val"/>
</properties>
<testcase classname="tests.test_lib" name="test_always_pass" time="0.002"/>
<testcase classname="tests.test_lib" name="test_with_subtests" time="0.005"/>
<testcase classname="tests.test_lib" name="test_parameterized[param1]" time="0.000"/>
<testcase classname="tests.test_lib" name="test_parameterized[param2]" time="0.000"/>
<testcase classname="tests.test_lib" name="test_always_skip" time="0.000">
<skipped type="pytest.skip" message="skipped">/Users/mike/Projects/python-test/tests/test_lib.py:20: skipped
</skipped>
</testcase>
<testcase classname="tests.test_lib" name="test_always_fail" time="0.000">
<failure message="assert False">def test_always_fail():
&gt; assert False
E assert False
tests/test_lib.py:25: AssertionError
</failure>
</testcase>
<testcase classname="tests.test_lib" name="test_expected_failure" time="0.000">
<skipped type="pytest.xfail" message=""/>
</testcase>
<testcase classname="tests.test_lib" name="test_error" time="0.000">
<failure message="Exception: error">def test_error():
&gt; raise Exception("error")
E Exception: error
tests/test_lib.py:32: Exception
</failure>
</testcase>
<testcase classname="tests.test_lib" name="test_with_record_property" time="0.000">
<properties>
<property name="example_key" value="1"/>
</properties>
</testcase>
<testcase classname="custom_classname" name="test_with_record_xml_attribute" time="0.000"/>
</testsuite>
</testsuites>

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="TestAcme-20251114214921" tests="8" file=".py" time="0.001" timestamp="2025-11-14T21:49:22" failures="1" errors="1" skipped="2">
<testcase classname="TestAcme" name="test_always_pass" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="8"/>
<testcase classname="TestAcme" name="test_parameterized_0_param1" time="0.001" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="618"/>
<testcase classname="TestAcme" name="test_parameterized_1_param2" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="618"/>
<testcase classname="TestAcme" name="test_with_subtests" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="11"/>
<testcase classname="TestAcme" name="test_always_fail" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="23">
<failure type="AssertionError" message="failed"><![CDATA[Traceback (most recent call last):
File "/Users/foo/Projects/python-test/tests/test_lib.py", line 24, in test_always_fail
self.fail("failed")
AssertionError: failed
]]></failure>
</testcase>
<testcase classname="TestAcme" name="test_error" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="30">
<error type="Exception" message="error"><![CDATA[Traceback (most recent call last):
File "/Users/foo/Projects/python-test/tests/test_lib.py", line 31, in test_error
raise Exception("error")
Exception: error
]]></error>
</testcase>
<testcase classname="TestAcme" name="test_always_skip" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="20">
<skipped type="skip" message="skipped"/>
</testcase>
<testcase classname="TestAcme" name="test_expected_failure" time="0.000" timestamp="2025-11-14T21:49:22" file="tests/test_lib.py" line="26">
<skipped type="XFAIL" message="expected failure: (&lt;class 'AssertionError'&gt;, AssertionError('expected failure'), &lt;traceback object at 0x100c125c0&gt;)"/>
</testcase>
</testsuite>

View file

@ -1,29 +0,0 @@
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 {JavaJunitParser} from '../src/parsers/java-junit/java-junit-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('java-junit tests', () => { describe('java-junit tests', () => {
@ -90,66 +90,4 @@ describe('java-junit tests', () => {
expect(result.result === 'failed') expect(result.result === 'failed')
expect(result.failed === 1) 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 {JestJunitParser} from '../src/parsers/jest-junit/jest-junit-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('jest-junit tests', () => { describe('jest-junit tests', () => {
@ -145,205 +145,4 @@ describe('jest-junit tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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/)
})
it('report can be collapsed when configured', 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,
collapsed: 'always'
})
// Report should include collapsible details
expect(report).toContain('<details><summary>Expand for details</summary>')
expect(report).toContain('</details>')
})
it('report is not collapsed when configured to never', 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,
collapsed: 'never'
})
// Report should not include collapsible details
expect(report).not.toContain('<details><summary>Expand for details</summary>')
expect(report).not.toContain('</details>')
})
it('report auto-collapses when all tests pass', async () => {
// Test with a fixture that has all passing tests (no failures)
const fixturePath = path.join(__dirname, 'fixtures', 'jest-junit-eslint.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)
// Verify this fixture has no failures
expect(result.failed).toBe(0)
const report = getReport([result], {
...DEFAULT_OPTIONS,
collapsed: 'auto'
})
// Should collapse when all tests pass
expect(report).toContain('<details><summary>Expand for details</summary>')
expect(report).toContain('</details>')
})
it('report does not auto-collapse when tests fail', async () => {
// Test with a fixture that has failing tests
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)
// Verify this fixture has failures
expect(result.failed).toBeGreaterThan(0)
const report = getReport([result], {
...DEFAULT_OPTIONS,
collapsed: 'auto'
})
// Should not collapse when there are failures
expect(report).not.toContain('<details><summary>Expand for details</summary>')
expect(report).not.toContain('</details>')
})
it('report includes the short summary', 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 shortSummary = '1 passed, 4 failed and 1 skipped'
const report = getReport([result], DEFAULT_OPTIONS, shortSummary)
// Report should have the title as the first line
expect(report).toMatch(/^## 1 passed, 4 failed and 1 skipped\n/)
})
it('report includes a custom report title and short summary', 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 shortSummary = '1 passed, 4 failed and 1 skipped'
const report = getReport(
[result],
{
...DEFAULT_OPTIONS,
reportTitle: 'My Custom Title'
},
shortSummary
)
// Report should have the title as the first line
expect(report).toMatch(/^# My Custom Title\n## 1 passed, 4 failed and 1 skipped\n/)
})
}) })

View file

@ -3,7 +3,7 @@ import * as path from 'path'
import {MochaJsonParser} from '../src/parsers/mocha-json/mocha-json-parser' import {MochaJsonParser} from '../src/parsers/mocha-json/mocha-json-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('mocha-json tests', () => { describe('mocha-json tests', () => {
@ -64,66 +64,4 @@ describe('mocha-json tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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

@ -1,93 +0,0 @@
import * as fs from 'fs'
import * as path from 'path'
import {PythonXunitParser} from '../src/parsers/python-xunit/python-xunit-parser'
import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils'
const defaultOpts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
describe('python-xunit unittest report', () => {
const fixturePath = path.join(__dirname, 'fixtures', 'python-xunit-unittest.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const outputPath = path.join(__dirname, '__outputs__', 'python-xunit-unittest.md')
it('report from python test results matches snapshot', async () => {
const trackedFiles = ['tests/test_lib.py']
const opts: ParseOptions = {
...defaultOpts,
trackedFiles
}
const parser = new PythonXunitParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
it('report does not include a title by default', async () => {
const parser = new PythonXunitParser(defaultOpts)
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 parser = new PythonXunitParser(defaultOpts)
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 parser = new PythonXunitParser(defaultOpts)
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/)
})
})
describe('python-xunit pytest report', () => {
const fixturePath = path.join(__dirname, 'fixtures', 'python-xunit-pytest.xml')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const outputPath = path.join(__dirname, '__outputs__', 'python-xunit-pytest.md')
it('report from python test results matches snapshot', async () => {
const trackedFiles = ['tests/test_lib.py']
const opts: ParseOptions = {
...defaultOpts,
trackedFiles
}
const parser = new PythonXunitParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
})

View file

@ -1,120 +0,0 @@
import {getBadge, DEFAULT_OPTIONS, ReportOptions} from '../../src/report/get-report'
describe('getBadge', () => {
describe('URI encoding with special characters', () => {
it('generates correct URI with simple badge title', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'tests'
}
const badge = getBadge(5, 0, 1, options)
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-5%20passed%2C%201%20skipped-success)')
})
it('handles badge title with single hyphen', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'unit-tests'
}
const badge = getBadge(3, 0, 0, options)
// The hyphen in the badge title should be encoded as --
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/unit--tests-3%20passed-success)')
})
it('handles badge title with multiple hyphens', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'integration-api-tests'
}
const badge = getBadge(10, 0, 0, options)
// All hyphens in the title should be encoded as --
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/integration--api--tests-10%20passed-success)')
})
it('handles badge title with multiple underscores', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'my_integration_test'
}
const badge = getBadge(10, 0, 0, options)
// All underscores in the title should be encoded as __
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/my__integration__test-10%20passed-success)')
})
it('handles badge title with version format containing hyphen', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'MariaDb 12.0-ubi database tests'
}
const badge = getBadge(1, 0, 0, options)
// The hyphen in "12.0-ubi" should be encoded as --
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/MariaDb%2012.0--ubi%20database%20tests-1%20passed-success)')
})
it('handles badge title with dots and hyphens', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'v1.2.3-beta-test'
}
const badge = getBadge(4, 1, 0, options)
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/v1.2.3--beta--test-4%20passed%2C%201%20failed-critical)')
})
it('preserves structural hyphens between label and message', () => {
const options: ReportOptions = {
...DEFAULT_OPTIONS,
badgeTitle: 'test-suite'
}
const badge = getBadge(2, 3, 1, options)
// The URI should have literal hyphens separating title-message-color
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/test--suite-2%20passed%2C%203%20failed%2C%201%20skipped-critical)')
})
})
describe('generates test outcome as color name for imgshields', () => {
it('uses success color when all tests pass', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(5, 0, 0, options)
expect(badge).toContain('-success)')
})
it('uses critical color when tests fail', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(5, 2, 0, options)
expect(badge).toContain('-critical)')
})
it('uses yellow color when no tests found', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(0, 0, 0, options)
expect(badge).toContain('-yellow)')
})
})
describe('badge message composition', () => {
it('includes only passed count when no failures or skips', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(5, 0, 0, options)
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-5%20passed-success)')
})
it('includes passed and failed counts', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(5, 2, 0, options)
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%202%20failed-critical)')
})
it('includes passed, failed and skipped counts', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(5, 2, 1, options)
expect(badge).toBe('![Tests failed](https://img.shields.io/badge/tests-5%20passed%2C%202%20failed%2C%201%20skipped-critical)')
})
it('uses "none" message when no tests', () => {
const options: ReportOptions = {...DEFAULT_OPTIONS}
const badge = getBadge(0, 0, 0, options)
expect(badge).toBe('![Tests passed successfully](https://img.shields.io/badge/tests-none-yellow)')
})
})
})

View file

@ -3,7 +3,7 @@ import * as path from 'path'
import {RspecJsonParser} from '../src/parsers/rspec-json/rspec-json-parser' import {RspecJsonParser} from '../src/parsers/rspec-json/rspec-json-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('rspec-json tests', () => { describe('rspec-json tests', () => {
@ -42,66 +42,4 @@ describe('rspec-json tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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 {SwiftXunitParser} from '../src/parsers/swift-xunit/swift-xunit-parser'
import {ParseOptions} from '../src/test-parser' import {ParseOptions} from '../src/test-parser'
import {DEFAULT_OPTIONS, getReport} from '../src/report/get-report' import {getReport} from '../src/report/get-report'
import {normalizeFilePath} from '../src/utils/path-utils' import {normalizeFilePath} from '../src/utils/path-utils'
describe('swift-xunit tests', () => { describe('swift-xunit tests', () => {
@ -27,66 +27,4 @@ describe('swift-xunit tests', () => {
fs.mkdirSync(path.dirname(outputPath), {recursive: true}) fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report) 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', () => { it('throws when string has invalid format', () => {
expect(() => parseNetDuration('12:34:56 not a duration')).toThrow(/^Invalid format/) expect(() => parseNetDuration('12:34:56 not a duration')).toThrowError(/^Invalid format/)
}) })
}) })

View file

@ -1,5 +1,6 @@
name: Test Reporter name: Test Reporter
description: Displays test results from popular testing frameworks directly in GitHub description: |
Shows test results in GitHub UI: .NET (xUnit, NUnit, MSTest), Dart, Flutter, Java (JUnit), JavaScript (JEST, Mocha)
author: Michal Dorner <dorner.michal@gmail.com> author: Michal Dorner <dorner.michal@gmail.com>
inputs: inputs:
artifact: artifact:
@ -28,11 +29,9 @@ inputs:
- dotnet-nunit - dotnet-nunit
- dotnet-trx - dotnet-trx
- flutter-json - flutter-json
- golang-json
- java-junit - java-junit
- jest-junit - jest-junit
- mocha-json - mocha-json
- python-xunit
- rspec-json - rspec-json
- swift-xunit - swift-xunit
required: true required: true
@ -40,7 +39,7 @@ inputs:
description: | description: |
Limits which test suites are listed. Supported options: Limits which test suites are listed. Supported options:
- all - all
- failed - only-failed
- none - none
required: false required: false
default: 'all' default: 'all'
@ -48,7 +47,7 @@ inputs:
description: | description: |
Limits which test cases are listed. Supported options: Limits which test cases are listed. Supported options:
- all - all
- failed - only-failed
- none - none
required: false required: false
default: 'all' default: 'all'
@ -69,10 +68,6 @@ inputs:
working-directory: working-directory:
description: Relative path under $GITHUB_WORKSPACE where the repository was checked out description: Relative path under $GITHUB_WORKSPACE where the repository was checked out
required: false required: false
report-title:
description: Title for the test report summary
required: false
default: ''
only-summary: only-summary:
description: | description: |
Allows you to generate only the summary. Allows you to generate only the summary.
@ -90,14 +85,6 @@ inputs:
description: Customize badge title description: Customize badge title
required: false required: false
default: 'tests' default: 'tests'
collapsed:
description: |
Controls whether test report details are collapsed or expanded. Supported options:
- auto: Collapse only if all tests pass (default behavior)
- always: Always collapse the report details
- never: Always expand the report details
required: false
default: 'auto'
token: token:
description: GitHub Access Token description: GitHub Access Token
required: false required: false

1633
dist/index.js generated vendored

File diff suppressed because it is too large Load diff

80
dist/licenses.txt generated vendored
View file

@ -1350,62 +1350,48 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
sax sax
BlueOak-1.0.0 ISC
# Blue Oak Model License The ISC License
Version 1.0.0 Copyright (c) Isaac Z. Schlueter and Contributors
## Purpose Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
This license gives everyone as much permission to work with THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
this software as possible, while protecting contributors WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
from liability. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
## Acceptance ====
In order to receive this license, you must agree to its `String.fromCodePoint` by Mathias Bynens used according to terms of MIT
rules. The rules of this license are both obligations License, as follows:
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright Copyright Mathias Bynens <https://mathiasbynens.be/>
Each contributor licenses you to do everything with this Permission is hereby granted, free of charge, to any person obtaining
software that would otherwise infringe that contributor's a copy of this software and associated documentation files (the
copyright in it. "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
## Notices The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
You must ensure that everyone who gets a copy of THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
any part of this software from you, with or without EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
changes, also gets the text of this license or a link to MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
<https://blueoakcouncil.org/license/1.0.0>. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
## Excuse OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
***As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim.***
to-regex-range to-regex-range

3517
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "test-reporter", "name": "test-reporter",
"version": "2.3.0", "version": "2.0.0",
"private": true, "private": true,
"description": "Presents test results from popular testing frameworks as Github check run", "description": "Presents test results from popular testing frameworks as Github check run",
"main": "lib/main.js", "main": "lib/main.js",
@ -16,10 +16,7 @@
"all": "npm run build && npm run format && npm run lint && npm run package && npm test", "all": "npm run build && npm run format && npm run lint && npm run package && npm test",
"dart-fixture": "cd \"reports/dart\" && dart test --file-reporter=\"json:../../__tests__/fixtures/dart-json.json\"", "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-fixture": "dotnet test reports/dotnet/DotnetTests.XUnitTests --logger \"trx;LogFileName=../../../../__tests__/fixtures/dotnet-trx.trx\"",
"dotnet-xunitv3-fixture": "dotnet run --project reports/dotnet/DotnetTests.XUnitV3Tests/DotnetTests.XUnitV3Tests.csproj --report-trx --report-trx-filename dotnet-xunitv3.trx --results-directory __tests__/fixtures/",
"dotnet-nunit-fixture": "nunit.exe reports/dotnet/DotnetTests.NUnitV3Tests/bin/Debug/netcoreapp3.1/DotnetTests.NUnitV3Tests.dll --result=__tests__/fixtures/dotnet-nunit.xml", "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", "jest-fixture": "cd \"reports/jest\" && npm test",
"mocha-fixture": "cd \"reports/mocha\" && npm test" "mocha-fixture": "cd \"reports/mocha\" && npm test"
}, },
@ -38,39 +35,37 @@
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1", "@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/github": "^6.0.1", "@actions/github": "^6.0.0",
"adm-zip": "^0.5.16", "adm-zip": "^0.5.16",
"fast-glob": "^3.3.3", "fast-glob": "^3.3.3",
"got": "^11.8.6", "got": "^11.8.6",
"picomatch": "^4.0.3", "picomatch": "^4.0.2",
"xml2js": "^0.6.2" "xml2js": "^0.6.2"
}, },
"devDependencies": { "devDependencies": {
"@octokit/webhooks-types": "^7.6.1", "@octokit/webhooks-types": "^7.6.1",
"@types/adm-zip": "^0.5.7", "@types/adm-zip": "^0.5.7",
"@types/jest": "^30.0.0", "@types/jest": "^29.5.14",
"@types/node": "^20.19.23", "@types/node": "^20.17.24",
"@types/picomatch": "^4.0.2", "@types/picomatch": "^2.3.4",
"@types/xml2js": "^0.4.14", "@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0", "@typescript-eslint/parser": "^7.18.0",
"@vercel/ncc": "^0.38.4", "@vercel/ncc": "^0.38.3",
"eol-converter-cli": "^1.1.0", "eol-converter-cli": "^1.1.0",
"eslint": "^8.57.1", "eslint": "^8.57.1",
"eslint-import-resolver-typescript": "^3.10.1", "eslint-import-resolver-typescript": "^3.8.5",
"eslint-plugin-github": "^4.10.2", "eslint-plugin-github": "^4.10.2",
"eslint-plugin-import": "^2.32.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.14.0", "eslint-plugin-jest": "^28.11.0",
"eslint-plugin-prettier": "^5.5.4", "eslint-plugin-prettier": "^5.2.3",
"jest": "^30.2.0", "jest": "^29.7.0",
"jest-circus": "^29.7.0",
"jest-junit": "^16.0.0", "jest-junit": "^16.0.0",
"js-yaml": "^4.1.1", "js-yaml": "^4.1.0",
"prettier": "^3.6.2", "prettier": "^3.5.3",
"ts-jest": "^29.4.5", "ts-jest": "^29.2.6",
"typescript": "^5.9.3" "typescript": "^5.5.4"
},
"overrides": {
"sax": "^1.4.3"
}, },
"jest-junit": { "jest-junit": {
"suiteName": "jest tests", "suiteName": "jest tests",
@ -84,10 +79,5 @@
}, },
"engines": { "engines": {
"node": ">=20" "node": ">=20"
},
"markdownlint-cli2": {
"ignores": [
"__tests__/**/*"
]
} }
} }

View file

@ -40,7 +40,7 @@ namespace DotnetTests.XUnitTests
} }
[Test] [Test]
[CancelAfter(1)] [Timeout(1)]
public void Timeout_Test() public void Timeout_Test()
{ {
Thread.Sleep(100); Thread.Sleep(100);
@ -58,7 +58,7 @@ namespace DotnetTests.XUnitTests
[TestCase(3)] [TestCase(3)]
public void Is_Even_Number(int i) public void Is_Even_Number(int i)
{ {
Assert.That(i % 2 == 0); Assert.True(i % 2 == 0);
} }
} }
} }

View file

@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<DeterministicSourcePaths>true</DeterministicSourcePaths>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NUnit" Version="4.3.2" /> <PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -2,7 +2,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<DeterministicSourcePaths>true</DeterministicSourcePaths>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -1,14 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<DeterministicSourcePaths>true</DeterministicSourcePaths>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.9.3" /> <PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>exe</OutputType>
<DeterministicSourcePaths>true</DeterministicSourcePaths>
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" Version="1.7.3" />
<PackageReference Include="xunit.v3" Version="2.0.3" />
</ItemGroup>
</Project>

View file

@ -1,27 +0,0 @@
using System;
using Xunit;
namespace DotnetTests.XUnitV3Tests;
public sealed class Fixture : IDisposable
{
public void Dispose()
{
throw new InvalidOperationException("Failure during fixture disposal");
}
}
public class FixtureTests(Fixture fixture) : IClassFixture<Fixture>
{
[Fact]
public void Passing_Test()
{
Assert.NotNull(fixture);
}
[Fact]
public void Failing_Test()
{
Assert.Null(fixture);
}
}

View file

@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotnetTests.XUnitTests", "D
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetTests.NUnitV3Tests", "DotnetTests.NUnitV3Tests\DotnetTests.NUnitV3Tests.csproj", "{81023ED7-56CB-47E9-86C5-9125A0873C55}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetTests.NUnitV3Tests", "DotnetTests.NUnitV3Tests\DotnetTests.NUnitV3Tests.csproj", "{81023ED7-56CB-47E9-86C5-9125A0873C55}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetTests.XUnitV3Tests", "DotnetTests.XUnitV3Tests\DotnetTests.XUnitV3Tests.csproj", "{D35E65DC-62EF-4612-9FF3-66F5600BFB74}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -31,10 +29,6 @@ Global
{81023ED7-56CB-47E9-86C5-9125A0873C55}.Debug|Any CPU.Build.0 = Debug|Any CPU {81023ED7-56CB-47E9-86C5-9125A0873C55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81023ED7-56CB-47E9-86C5-9125A0873C55}.Release|Any CPU.ActiveCfg = Release|Any CPU {81023ED7-56CB-47E9-86C5-9125A0873C55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81023ED7-56CB-47E9-86C5-9125A0873C55}.Release|Any CPU.Build.0 = Release|Any CPU {81023ED7-56CB-47E9-86C5-9125A0873C55}.Release|Any CPU.Build.0 = Release|Any CPU
{D35E65DC-62EF-4612-9FF3-66F5600BFB74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D35E65DC-62EF-4612-9FF3-66F5600BFB74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D35E65DC-62EF-4612-9FF3-66F5600BFB74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D35E65DC-62EF-4612-9FF3-66F5600BFB74}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -42,7 +36,6 @@ Global
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{F8607EDB-D25D-47AA-8132-38ACA242E845} = {BCAC3B31-ADB1-4221-9D5B-182EE868648C} {F8607EDB-D25D-47AA-8132-38ACA242E845} = {BCAC3B31-ADB1-4221-9D5B-182EE868648C}
{81023ED7-56CB-47E9-86C5-9125A0873C55} = {BCAC3B31-ADB1-4221-9D5B-182EE868648C} {81023ED7-56CB-47E9-86C5-9125A0873C55} = {BCAC3B31-ADB1-4221-9D5B-182EE868648C}
{D35E65DC-62EF-4612-9FF3-66F5600BFB74} = {BCAC3B31-ADB1-4221-9D5B-182EE868648C}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6ED5543C-74AA-4B21-8050-943550F3F66E} SolutionGuid = {6ED5543C-74AA-4B21-8050-943550F3F66E}

View file

@ -1,20 +0,0 @@
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

@ -1,82 +0,0 @@
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))))
}

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,6 @@
"author": "Michal Dorner <dorner.michal@gmail.com>", "author": "Michal Dorner <dorner.michal@gmail.com>",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"mocha": "^11.7.5" "mocha": "^8.3.0"
} }
} }

View file

@ -13,13 +13,12 @@ import {getReport} from './report/get-report'
import {DartJsonParser} from './parsers/dart-json/dart-json-parser' import {DartJsonParser} from './parsers/dart-json/dart-json-parser'
import {DotnetNunitParser} from './parsers/dotnet-nunit/dotnet-nunit-parser' import {DotnetNunitParser} from './parsers/dotnet-nunit/dotnet-nunit-parser'
import {DotnetTrxParser} from './parsers/dotnet-trx/dotnet-trx-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 {JavaJunitParser} from './parsers/java-junit/java-junit-parser'
import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser' import {JestJunitParser} from './parsers/jest-junit/jest-junit-parser'
import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser' import {MochaJsonParser} from './parsers/mocha-json/mocha-json-parser'
import {PythonXunitParser} from './parsers/python-xunit/python-xunit-parser'
import {RspecJsonParser} from './parsers/rspec-json/rspec-json-parser' import {RspecJsonParser} from './parsers/rspec-json/rspec-json-parser'
import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser' import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils' import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
import {getCheckRunContext} from './utils/github-utils' import {getCheckRunContext} from './utils/github-utils'
@ -48,8 +47,6 @@ class TestReporter {
readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true' readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true'
readonly useActionsSummary = core.getInput('use-actions-summary', {required: false}) === 'true' readonly useActionsSummary = core.getInput('use-actions-summary', {required: false}) === 'true'
readonly badgeTitle = core.getInput('badge-title', {required: false}) readonly badgeTitle = core.getInput('badge-title', {required: false})
readonly reportTitle = core.getInput('report-title', {required: false})
readonly collapsed = core.getInput('collapsed', {required: false}) as 'auto' | 'always' | 'never'
readonly token = core.getInput('token', {required: true}) readonly token = core.getInput('token', {required: true})
readonly octokit: InstanceType<typeof GitHub> readonly octokit: InstanceType<typeof GitHub>
readonly context = getCheckRunContext() readonly context = getCheckRunContext()
@ -67,11 +64,6 @@ class TestReporter {
return return
} }
if (this.collapsed !== 'auto' && this.collapsed !== 'always' && this.collapsed !== 'never') {
core.setFailed(`Input parameter 'collapsed' has invalid value`)
return
}
if (isNaN(this.maxAnnotations) || this.maxAnnotations < 0 || this.maxAnnotations > 50) { if (isNaN(this.maxAnnotations) || this.maxAnnotations < 0 || this.maxAnnotations > 50) {
core.setFailed(`Input parameter 'max-annotations' has invalid value`) core.setFailed(`Input parameter 'max-annotations' has invalid value`)
return return
@ -172,29 +164,11 @@ class TestReporter {
} }
} }
const {listSuites, listTests, onlySummary, useActionsSummary, badgeTitle, reportTitle, collapsed} = this const {listSuites, listTests, onlySummary, useActionsSummary, badgeTitle} = 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 = '' let baseUrl = ''
if (this.useActionsSummary) { if (this.useActionsSummary) {
const summary = getReport( const summary = getReport(results, {listSuites, listTests, baseUrl, onlySummary, useActionsSummary, badgeTitle})
results,
{
listSuites,
listTests,
baseUrl,
onlySummary,
useActionsSummary,
badgeTitle,
reportTitle,
collapsed
},
shortSummary
)
core.info('Summary content:') core.info('Summary content:')
core.info(summary) core.info(summary)
@ -214,16 +188,7 @@ class TestReporter {
core.info('Creating report summary') core.info('Creating report summary')
baseUrl = createResp.data.html_url as string baseUrl = createResp.data.html_url as string
const summary = getReport(results, { const summary = getReport(results, {listSuites, listTests, baseUrl, onlySummary, useActionsSummary, badgeTitle})
listSuites,
listTests,
baseUrl,
onlySummary,
useActionsSummary,
badgeTitle,
reportTitle,
collapsed
})
core.info('Creating annotations') core.info('Creating annotations')
const annotations = getAnnotations(results, this.maxAnnotations) const annotations = getAnnotations(results, this.maxAnnotations)
@ -231,6 +196,11 @@ class TestReporter {
const isFailed = this.failOnError && results.some(tr => tr.result === 'failed') const isFailed = this.failOnError && results.some(tr => tr.result === 'failed')
const conclusion = isFailed ? 'failure' : 'success' 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`) core.info(`Updating check run conclusion (${conclusion}) and output`)
const resp = await this.octokit.rest.checks.update({ const resp = await this.octokit.rest.checks.update({
check_run_id: createResp.data.id, check_run_id: createResp.data.id,
@ -261,8 +231,6 @@ class TestReporter {
return new DotnetNunitParser(options) return new DotnetNunitParser(options)
case 'dotnet-trx': case 'dotnet-trx':
return new DotnetTrxParser(options) return new DotnetTrxParser(options)
case 'golang-json':
return new GolangJsonParser(options)
case 'flutter-json': case 'flutter-json':
return new DartJsonParser(options, 'flutter') return new DartJsonParser(options, 'flutter')
case 'java-junit': case 'java-junit':
@ -271,8 +239,6 @@ class TestReporter {
return new JestJunitParser(options) return new JestJunitParser(options)
case 'mocha-json': case 'mocha-json':
return new MochaJsonParser(options) return new MochaJsonParser(options)
case 'python-xunit':
return new PythonXunitParser(options)
case 'rspec-json': case 'rspec-json':
return new RspecJsonParser(options) return new RspecJsonParser(options)
case 'swift-xunit': case 'swift-xunit':

View file

@ -77,13 +77,13 @@ export class DotnetNunitParser implements TestParser {
.join('.') .join('.')
const groupName = suitesWithoutTheories[suitesWithoutTheories.length - 1].$.name const groupName = suitesWithoutTheories[suitesWithoutTheories.length - 1].$.name
let existingSuite = result.find(suite => suite.name === suiteName) let existingSuite = result.find(existingSuite => existingSuite.name === suiteName)
if (existingSuite === undefined) { if (existingSuite === undefined) {
existingSuite = new TestSuiteResult(suiteName, []) existingSuite = new TestSuiteResult(suiteName, [])
result.push(existingSuite) result.push(existingSuite)
} }
let existingGroup = existingSuite.groups.find(group => group.name === groupName) let existingGroup = existingSuite.groups.find(existingGroup => existingGroup.name === groupName)
if (existingGroup === undefined) { if (existingGroup === undefined) {
existingGroup = new TestGroupResult(groupName, []) existingGroup = new TestGroupResult(groupName, [])
existingSuite.groups.push(existingGroup) existingSuite.groups.push(existingGroup)

View file

@ -62,8 +62,7 @@ export class DotnetTrxParser implements TestParser {
} }
private getTestClasses(trx: TrxReport): TestClass[] { 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 [] return []
} }
@ -81,7 +80,7 @@ export class DotnetTrxParser implements TestParser {
const testClasses: {[name: string]: TestClass} = {} const testClasses: {[name: string]: TestClass} = {}
for (const r of unitTestsResults) { for (const r of unitTestsResults) {
const className = r.test.TestMethod[0].$.className ?? "Unclassified" const className = r.test.TestMethod[0].$.className
let tc = testClasses[className] let tc = testClasses[className]
if (tc === undefined) { if (tc === undefined) {
tc = new TestClass(className) tc = new TestClass(className)
@ -146,8 +145,8 @@ export class DotnetTrxParser implements TestParser {
return undefined return undefined
} }
const message = test.error.Message[0]
const stackTrace = test.error.StackTrace[0] const stackTrace = test.error.StackTrace[0]
const message = `${test.error.Message[0]}\n${stackTrace}`
let path let path
let line let line
@ -161,7 +160,7 @@ export class DotnetTrxParser implements TestParser {
path, path,
line, line,
message, message,
details: `${message}` details: `${message}\n${stackTrace}`
} }
} }

View file

@ -1,115 +0,0 @@
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

@ -1,19 +0,0 @@
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

@ -1,8 +0,0 @@
import {ParseOptions} from '../../test-parser'
import {JavaJunitParser} from '../java-junit/java-junit-parser'
export class PythonXunitParser extends JavaJunitParser {
constructor(readonly options: ParseOptions) {
super(options)
}
}

View file

@ -6,7 +6,7 @@ import {getFirstNonEmptyLine} from '../utils/parse-utils'
import {slug} from '../utils/slugger' import {slug} from '../utils/slugger'
const MAX_REPORT_LENGTH = 65535 const MAX_REPORT_LENGTH = 65535
const MAX_ACTIONS_SUMMARY_LENGTH = 1048576 const MAX_ACTIONS_SUMMARY_LENGTH = 131072 // 1048576 soon
export interface ReportOptions { export interface ReportOptions {
listSuites: 'all' | 'failed' | 'none' listSuites: 'all' | 'failed' | 'none'
@ -15,30 +15,24 @@ export interface ReportOptions {
onlySummary: boolean onlySummary: boolean
useActionsSummary: boolean useActionsSummary: boolean
badgeTitle: string badgeTitle: string
reportTitle: string
collapsed: 'auto' | 'always' | 'never'
} }
export const DEFAULT_OPTIONS: ReportOptions = { const defaultOptions: ReportOptions = {
listSuites: 'all', listSuites: 'all',
listTests: 'all', listTests: 'all',
baseUrl: '', baseUrl: '',
onlySummary: false, onlySummary: false,
useActionsSummary: true, useActionsSummary: true,
badgeTitle: 'tests', badgeTitle: 'tests'
reportTitle: '',
collapsed: 'auto'
} }
export function getReport( export function getReport(results: TestRunResult[], options: ReportOptions = defaultOptions): string {
results: TestRunResult[], core.info('Generating check run summary')
options: ReportOptions = DEFAULT_OPTIONS,
shortSummary = ''
): string {
applySort(results) applySort(results)
const opts = {...options} const opts = {...options}
let lines = renderReport(results, opts, shortSummary) let lines = renderReport(results, opts)
let report = lines.join('\n') let report = lines.join('\n')
if (getByteLength(report) <= getMaxReportLength(options)) { if (getByteLength(report) <= getMaxReportLength(options)) {
@ -48,7 +42,7 @@ export function getReport(
if (opts.listTests === 'all') { if (opts.listTests === 'all') {
core.info("Test report summary is too big - setting 'listTests' to 'failed'") core.info("Test report summary is too big - setting 'listTests' to 'failed'")
opts.listTests = 'failed' opts.listTests = 'failed'
lines = renderReport(results, opts, shortSummary) lines = renderReport(results, opts)
report = lines.join('\n') report = lines.join('\n')
if (getByteLength(report) <= getMaxReportLength(options)) { if (getByteLength(report) <= getMaxReportLength(options)) {
return report return report
@ -59,7 +53,7 @@ export function getReport(
return trimReport(lines, options) return trimReport(lines, options)
} }
function getMaxReportLength(options: ReportOptions = DEFAULT_OPTIONS): number { function getMaxReportLength(options: ReportOptions = defaultOptions): number {
return options.useActionsSummary ? MAX_ACTIONS_SUMMARY_LENGTH : MAX_REPORT_LENGTH return options.useActionsSummary ? MAX_ACTIONS_SUMMARY_LENGTH : MAX_REPORT_LENGTH
} }
@ -105,18 +99,8 @@ function getByteLength(text: string): number {
return Buffer.byteLength(text, 'utf8') return Buffer.byteLength(text, 'utf8')
} }
function renderReport(results: TestRunResult[], options: ReportOptions, shortSummary: string): string[] { function renderReport(results: TestRunResult[], options: ReportOptions): string[] {
const sections: string[] = [] const sections: string[] = []
const reportTitle: string = options.reportTitle.trim()
if (reportTitle) {
sections.push(`# ${reportTitle}`)
}
if (shortSummary) {
sections.push(`## ${shortSummary}`)
}
const badge = getReportBadge(results, options) const badge = getReportBadge(results, options)
sections.push(badge) sections.push(badge)
@ -133,7 +117,7 @@ function getReportBadge(results: TestRunResult[], options: ReportOptions): strin
return getBadge(passed, failed, skipped, options) return getBadge(passed, failed, skipped, options)
} }
export function getBadge(passed: number, failed: number, skipped: number, options: ReportOptions): string { function getBadge(passed: number, failed: number, skipped: number, options: ReportOptions): string {
const text = [] const text = []
if (passed > 0) { if (passed > 0) {
text.push(`${passed} passed`) text.push(`${passed} passed`)
@ -153,37 +137,28 @@ export function getBadge(passed: number, failed: number, skipped: number, option
color = 'yellow' color = 'yellow'
} }
const hint = failed > 0 ? 'Tests failed' : 'Tests passed successfully' const hint = failed > 0 ? 'Tests failed' : 'Tests passed successfully'
const encodedBadgeTitle = encodeImgShieldsURIComponent(options.badgeTitle) const uri = encodeURIComponent(`${options.badgeTitle}-${message}-${color}`)
const encodedMessage = encodeImgShieldsURIComponent(message) return `![${hint}](https://img.shields.io/badge/${uri})`
const encodedColor = encodeImgShieldsURIComponent(color)
return `![${hint}](https://img.shields.io/badge/${encodedBadgeTitle}-${encodedMessage}-${encodedColor})`
} }
function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): string[] { function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): string[] {
const sections: string[] = [] const sections: string[] = []
const totalFailed = testRuns.reduce((sum, tr) => sum + tr.failed, 0) const totalFailed = testRuns.reduce((sum, tr) => sum + tr.failed, 0)
if (totalFailed === 0) {
// Determine if report should be collapsed based on collapsed option
const shouldCollapse = options.collapsed === 'always' || (options.collapsed === 'auto' && totalFailed === 0)
if (shouldCollapse) {
sections.push(`<details><summary>Expand for details</summary>`) sections.push(`<details><summary>Expand for details</summary>`)
sections.push(` `) sections.push(` `)
} }
if (testRuns.length > 0 || options.onlySummary) { if (testRuns.length > 0 || options.onlySummary) {
const tableData = testRuns const tableData = testRuns
.map((tr, originalIndex) => ({tr, originalIndex})) .filter(tr => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
.filter(({tr}) => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0) .map(tr => {
.map(({tr, originalIndex}) => {
const time = formatTime(tr.time) const time = formatTime(tr.time)
const name = tr.path 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 passed = tr.passed > 0 ? `${tr.passed} ${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed} ${Icon.fail}` : '' const failed = tr.failed > 0 ? `${tr.failed} ${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped} ${Icon.skip}` : '' const skipped = tr.skipped > 0 ? `${tr.skipped} ${Icon.skip}` : ''
return [nameLink, passed, failed, skipped, time] return [name, passed, failed, skipped, time]
}) })
const resultsTable = table( const resultsTable = table(
@ -199,7 +174,7 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
sections.push(...suitesReports) sections.push(...suitesReports)
} }
if (shouldCollapse) { if (totalFailed === 0) {
sections.push(`</details>`) sections.push(`</details>`)
} }
return sections return sections
@ -210,7 +185,7 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites const suites = options.listSuites === 'failed' ? tr.failedSuites : tr.suites
if (options.listSuites !== 'none') { if (options.listSuites !== 'none') {
const trSlug = makeRunSlug(runIndex, options) const trSlug = makeRunSlug(runIndex)
const nameLink = `<a id="${trSlug.id}" href="${options.baseUrl + trSlug.link}">${tr.path}</a>` const nameLink = `<a id="${trSlug.id}" href="${options.baseUrl + trSlug.link}">${tr.path}</a>`
const icon = getResultIcon(tr.result) const icon = getResultIcon(tr.result)
sections.push(`## ${icon}\xa0${nameLink}`) sections.push(`## ${icon}\xa0${nameLink}`)
@ -230,7 +205,7 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
const tsTime = formatTime(s.time) const tsTime = formatTime(s.time)
const tsName = s.name const tsName = s.name
const skipLink = options.listTests === 'none' || (options.listTests === 'failed' && s.result !== 'failed') const skipLink = options.listTests === 'none' || (options.listTests === 'failed' && s.result !== 'failed')
const tsAddr = options.baseUrl + makeSuiteSlug(runIndex, suiteIndex, options).link const tsAddr = options.baseUrl + makeSuiteSlug(runIndex, suiteIndex).link
const tsNameLink = skipLink ? tsName : link(tsName, tsAddr) const tsNameLink = skipLink ? tsName : link(tsName, tsAddr)
const passed = s.passed > 0 ? `${s.passed} ${Icon.success}` : '' const passed = s.passed > 0 ? `${s.passed} ${Icon.success}` : ''
const failed = s.failed > 0 ? `${s.failed} ${Icon.fail}` : '' const failed = s.failed > 0 ? `${s.failed} ${Icon.fail}` : ''
@ -265,7 +240,7 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
const sections: string[] = [] const sections: string[] = []
const tsName = ts.name const tsName = ts.name
const tsSlug = makeSuiteSlug(runIndex, suiteIndex, options) const tsSlug = makeSuiteSlug(runIndex, suiteIndex)
const tsNameLink = `<a id="${tsSlug.id}" href="${options.baseUrl + tsSlug.link}">${tsName}</a>` const tsNameLink = `<a id="${tsSlug.id}" href="${options.baseUrl + tsSlug.link}">${tsName}</a>`
const icon = getResultIcon(ts.result) const icon = getResultIcon(ts.result)
sections.push(`### ${icon}\xa0${tsNameLink}`) sections.push(`### ${icon}\xa0${tsNameLink}`)
@ -277,9 +252,6 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
} }
const space = grp.name ? ' ' : '' const space = grp.name ? ' ' : ''
for (const tc of grp.tests) { for (const tc of grp.tests) {
if (options.listTests === 'failed' && tc.result !== 'failed') {
continue
}
const result = getResultIcon(tc.result) const result = getResultIcon(tc.result)
sections.push(`${space}${result} ${tc.name}`) sections.push(`${space}${result} ${tc.name}`)
if (tc.error) { if (tc.error) {
@ -297,14 +269,14 @@ function getTestsReport(ts: TestSuiteResult, runIndex: number, suiteIndex: numbe
return sections return sections
} }
function makeRunSlug(runIndex: number, options: ReportOptions): {id: string; link: string} { function makeRunSlug(runIndex: number): {id: string; link: string} {
// use prefix to avoid slug conflicts after escaping the paths // use prefix to avoid slug conflicts after escaping the paths
return slug(`r${runIndex}`, options) return slug(`r${runIndex}`)
} }
function makeSuiteSlug(runIndex: number, suiteIndex: number, options: ReportOptions): {id: string; link: string} { function makeSuiteSlug(runIndex: number, suiteIndex: number): {id: string; link: string} {
// use prefix to avoid slug conflicts after escaping the paths // use prefix to avoid slug conflicts after escaping the paths
return slug(`r${runIndex}s${suiteIndex}`, options) return slug(`r${runIndex}s${suiteIndex}`)
} }
function getResultIcon(result: TestExecutionResult): string { function getResultIcon(result: TestExecutionResult): string {
@ -319,7 +291,3 @@ function getResultIcon(result: TestExecutionResult): string {
return '' return ''
} }
} }
function encodeImgShieldsURIComponent(component: string): string {
return encodeURIComponent(component).replace(/-/g, '--').replace(/_/g, '__')
}

View file

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

View file

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

View file

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