diff --git a/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj b/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj index 00706f3..7a40c70 100644 --- a/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj +++ b/SaBusMgrTest_Control/SaBusMgrTest_Control.csproj @@ -11,11 +11,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj b/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj index 0f8a339..9755a0a 100644 --- a/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj +++ b/SaBusMgrTest_Portal/SaBusMgrTest_Portal.csproj @@ -14,11 +14,11 @@ Sarand.BusinessMgr.Test - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/docs/component-reviews.md b/docs/component-reviews.md index 6eaa7e1..2e42c58 100644 --- a/docs/component-reviews.md +++ b/docs/component-reviews.md @@ -7,10 +7,11 @@ table td { } -Last updated: 2026-09-13 +Last updated: 2026-09-14 | Component | Scope | Status | Date reviewed | Next steps | Notes | |---|---|---|---|---|---| | `BusinessMgr.sln` | .NET 10 restore, Debug build, and tests | Migrated; passing with warnings and toolchain requirement | 2026-09-13 | Review remaining framework-specific packages, perform application smoke tests, then release-validate. | All eight projects target `net10.0`. The complete solution builds with Visual Studio 18 MSBuild; the .NET CLI cannot build `SaBusMgrTest_Portal` because its SSDT SQL unit-testing targets are Visual Studio-specific (`MSB4278`). Control tests pass 11 of 11 and Portal tests pass 13 of 13. The Identity-related `NU1903` warnings have been removed. | | `SaBusMgrStandardBase/Base/Helpers/SbmPasswordHelper.cs` and `SaBusinessMgrCoreWebControl/Control/Helpers/SbmcPasswordHelper.cs` | Password hashing | Dependency upgrade complete; legacy hashes compatible | 2026-09-13 | Preserve the compatibility tests when password-hashing defaults or account migration behavior changes. | Both helpers use `PasswordHasher` from `Microsoft.Extensions.Identity.Core` 10.0.12. Current hashes round-trip, wrong passwords fail, and legacy Identity V3 hashes remain valid while being identified for rehash. | | `eng/validate.ps1` | Repository validation | Complete; passing | 2026-09-13 | Use as the standard validation entry point and extend it when repository-wide checks change. | Locates Visual Studio MSBuild for the SSDT project, builds serially, runs 11 Control and 13 Portal tests, audits the Identity-package-owning project, and verifies changed-file line endings and diffs. | +| `SaBusMgrTest_Control` and `SaBusMgrTest_Portal` | Test SDK and coverage tooling | Current; coverage verified | 2026-09-14 | Treat MSTest 4 as a separate major-version review. | Both projects use Microsoft.NET.Test.Sdk 18.10.0 and coverlet collector 10.0.1. Control passes 11 tests and Portal passes 13 tests. The optional validation coverage mode verifies a non-empty Cobertura report from each suite and handles Portal's Visual Studio-only SSDT targets through an MSBuild publish step. | diff --git a/docs/topics.md b/docs/topics.md index e2d5927..d83c347 100644 --- a/docs/topics.md +++ b/docs/topics.md @@ -7,7 +7,7 @@ table td { } -Last updated: 2026-09-13 +Last updated: 2026-09-14 ## Prioritised Topics to Be Actioned @@ -39,3 +39,4 @@ Last updated: 2026-09-13 | Migrate BusinessMgr to .NET 10 against compatible Common targets | 2026-09-10 | 2026-09-10 | 2026-09-10 | All eight BusinessMgr projects now target `net10.0`. Visual Studio 18 MSBuild restored and built the complete solution successfully with no compilation errors. Control tests passed 8 of 8 and Portal tests passed 13 of 13 on .NET 10. Package vulnerability and framework-specific package reviews are tracked separately. | | Automate BusinessMgr validation | 2026-09-12 | 2026-09-12 | 2026-09-12 | Added `eng/validate.ps1` to locate Visual Studio MSBuild, build the SSDT-dependent solution serially, run both test assemblies, and verify diffs and changed-file line endings. The script passes with 8 of 8 Control and 13 of 13 Portal tests. | | Remove vulnerable transitive `System.Security.Cryptography.Xml` 8.0.2 dependency | 2026-09-10 | 2026-09-13 | 2026-09-13 | Replaced the broad legacy `Microsoft.AspNetCore.Identity` 2.3.1 reference with `Microsoft.Extensions.Identity.Core` 10.0.12, matching the only used API, `PasswordHasher`. Three focused tests cover both password helpers, wrong-password rejection, current hash round trips, legacy Identity V3 verification, and rehash detection. Restore and build no longer report `NU1903`; 11 Control and 13 Portal tests pass, and the package audit reports no vulnerable packages for `SaBusMgrStandardBase`. | +| Update BusinessMgr coverage tooling | 2026-09-14 | 2026-09-14 | 2026-09-14 | Updated both test projects to Microsoft.NET.Test.Sdk 18.10.0 and coverlet collector 10.0.1. Full validation passes with 11 Control and 13 Portal tests. The optional `-CollectCoverage` validation mode verifies non-empty Cobertura reports for both suites; the SSDT-based Portal project is published with Visual Studio MSBuild before `dotnet vstest`. MSTest 4 remains a separately scoped major upgrade. | diff --git a/eng/README.md b/eng/README.md index 580fd6f..ae841e9 100644 --- a/eng/README.md +++ b/eng/README.md @@ -6,4 +6,6 @@ Run the complete BusinessMgr validation: .\eng\validate.ps1 ``` -Use `-SkipRestore` when packages are already restored. The script suppresses .NET first-run setup and banners, locates Visual Studio MSBuild because the Portal test project requires Visual Studio SSDT targets, builds serially, derives test output paths from each project's target framework, runs both test assemblies, audits the Identity-package-owning project for vulnerable packages, stores test output under the ignored `TestResults/Validation` folder, checks the Git diff, and verifies working-tree line endings without modifying files. The focused project audit avoids loading the Portal test project's Visual Studio-only SSDT targets through CLI MSBuild. The script's isolated `DOTNET_CLI_HOME` stores only CLI state; NuGet packages reuse `NUGET_PACKAGES` when already configured or the user's standard `.nuget/packages` cache. +Use `-SkipRestore` when packages are already restored. Use `-CollectCoverage` after changing the test platform or coverage collector; it runs additional coverage passes and verifies that both suites produce non-empty Cobertura reports. Portal coverage is published with Visual Studio MSBuild before `dotnet vstest` because the project imports Visual Studio-only SSDT targets. + +The script suppresses .NET first-run setup and banners, locates Visual Studio MSBuild because the Portal test project requires Visual Studio SSDT targets, builds serially, derives test output paths from each project's target framework, runs both test assemblies, audits the Identity-package-owning project for vulnerable packages, stores test and optional coverage output under the ignored `TestResults/Validation` folder, checks the Git diff, and verifies working-tree line endings without modifying files. The focused project audit avoids loading the Portal test project's Visual Studio-only SSDT targets through CLI MSBuild. The script's isolated `DOTNET_CLI_HOME` stores only CLI state; NuGet packages reuse `NUGET_PACKAGES` when already configured or the user's standard `.nuget/packages` cache. diff --git a/eng/validate.ps1 b/eng/validate.ps1 index 6947e1c..bc6d35a 100644 --- a/eng/validate.ps1 +++ b/eng/validate.ps1 @@ -1,6 +1,7 @@ [CmdletBinding()] param( - [switch] $SkipRestore + [switch] $SkipRestore, + [switch] $CollectCoverage ) $ErrorActionPreference = 'Stop' @@ -111,6 +112,23 @@ function Test-LineEndings } } +function Test-CoverageReport +{ + param([Parameter(Mandatory)] [string] $ResultsPath) + + $report = Get-ChildItem -LiteralPath $ResultsPath -Filter 'coverage.cobertura.xml' -Recurse | Select-Object -First 1 + if (($null -eq $report) -or ($report.Length -eq 0)) + { + throw "A non-empty Cobertura coverage report was not found under $ResultsPath" + } + + [xml] $coverage = Get-Content -LiteralPath $report.FullName -Raw + if ($coverage.DocumentElement.Name -ne 'coverage') + { + throw "The coverage report at $($report.FullName) is not valid Cobertura XML." + } +} + Push-Location $repositoryRoot try { @@ -124,6 +142,21 @@ try $portalAssembly = Get-TestAssemblyPath 'SaBusMgrTest_Portal\SaBusMgrTest_Portal.csproj' 'SaBusMgrTest_Portal' Invoke-External dotnet @('vstest', $controlAssembly, "--TestAdapterPath:$(Split-Path -Parent $controlAssembly)", "--ResultsDirectory:$testResultsPath") Invoke-External dotnet @('vstest', $portalAssembly, "--TestAdapterPath:$(Split-Path -Parent $portalAssembly)", "--ResultsDirectory:$testResultsPath") + if ($CollectCoverage) + { + $coverageRunPath = Join-Path $testResultsPath "Coverage\$([guid]::NewGuid())" + $controlCoveragePath = Join-Path $coverageRunPath 'Control' + $portalCoveragePath = Join-Path $coverageRunPath 'Portal' + $portalPublishPath = Join-Path $coverageRunPath 'PortalPublished' + + Invoke-External dotnet @('test', 'SaBusMgrTest_Control\SaBusMgrTest_Control.csproj', '--configuration', 'Debug', '--no-build', '--no-restore', '--collect', 'XPlat Code Coverage', '--results-directory', $controlCoveragePath, '--verbosity', 'minimal') + Test-CoverageReport $controlCoveragePath + + Invoke-External $msBuildPath @('SaBusMgrTest_Portal\SaBusMgrTest_Portal.csproj', '/t:Publish', '/p:Configuration=Debug', "/p:PublishDir=$portalPublishPath", '/m:1', '/v:minimal', '/nologo') + $publishedPortalAssembly = Join-Path $portalPublishPath 'SaBusMgrTest_Portal.dll' + Invoke-External dotnet @('vstest', $publishedPortalAssembly, '--collect:XPlat Code Coverage', "--ResultsDirectory:$portalCoveragePath") + Test-CoverageReport $portalCoveragePath + } Invoke-External dotnet @('list', 'SaBusMgrStandardBase\SaBusMgrStandardBase.csproj', 'package', '--vulnerable', '--include-transitive') Invoke-External git @('diff', '--check') Test-LineEndings