From 8bb8774ae7ea4fe579a84c06ea632c0deba7d5b0 Mon Sep 17 00:00:00 2001 From: Nano Taboada <87288+nanotaboada@users.noreply.github.com> Date: Sat, 4 Apr 2026 05:00:37 -0300 Subject: [PATCH] test(validators): fix naming and add missing coverage (#427) Co-authored-by: Claude Sonnet 4.6 --- .claude/commands/pre-commit.md | 3 +- CHANGELOG.md | 4 ++ .../Unit/PlayerValidatorTests.cs | 46 ++++++++++++++++++- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/.claude/commands/pre-commit.md b/.claude/commands/pre-commit.md index 9a9f686..94f1407 100644 --- a/.claude/commands/pre-commit.md +++ b/.claude/commands/pre-commit.md @@ -5,7 +5,8 @@ Run the pre-commit checklist for this project: 1. Update `CHANGELOG.md` `[Unreleased]` section — add an entry under the appropriate subsection (Added / Changed / Fixed / Removed) describing the changes made, referencing the issue number. 2. Run `dotnet build --configuration Release` — must succeed. 3. Run `dotnet test --settings .runsettings` — all tests must pass. -4. Run `dotnet csharpier --check .` — must pass (run `dotnet csharpier .` to auto-fix). +4. If `dotnet csharpier` is available, run `dotnet csharpier --check .` — must pass + (run `dotnet csharpier .` to auto-fix). Skip this step with a note if not installed. 5. If `coderabbit` CLI is installed, run `coderabbit review --type uncommitted --prompt-only`: - If actionable/serious findings are reported, stop and address them before proposing the commit. - If only nitpick-level findings, report them and continue to the commit proposal. diff --git a/CHANGELOG.md b/CHANGELOG.md index f5aa253..339d14b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ This project uses famous football stadiums (A-Z) that hosted FIFA World Cup matc ### Added +- Add `ValidateAsync_SquadNumberNegative_ReturnsValidationError` test to exercise the `GreaterThan(0)` rule with a negative value, which passes `NotEmpty()` but fails the greater-than rule (#427) +- Add `ValidateAsync_FirstNameEmptyInUpdateRuleSet_ReturnsValidationError` test to verify the `"Update"` rule set enforces structural field validation (#427) - Add `adr/` directory with 12 Architecture Decision Records documenting architectural choices, technology decisions, and design trade-offs (#372) - Add ADR index and template at `adr/README.md` (#372) - Add Architecture Decisions section to `README.md` referencing the ADR index (#372) @@ -52,6 +54,8 @@ This project uses famous football stadiums (A-Z) that hosted FIFA World Cup matc ### Changed +- Rename `ValidateAsync_SquadNumber_BelongsToPlayerBeingUpdated_ReturnsNoErrors` to `ValidateAsync_SquadNumberBelongsToPlayerBeingUpdated_ReturnsNoErrors` to align with the 3-segment naming convention for service/validator tests (#427) +- Make CSharpier step in `/pre-commit` conditional (skip with a note if not installed), consistent with the Docker and CodeRabbit steps (#427) - Add "Verify tag commit is reachable from master" step to CD workflow using `git merge-base --is-ancestor` before any build or publish steps (#439) ### Fixed diff --git a/test/Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/PlayerValidatorTests.cs b/test/Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/PlayerValidatorTests.cs index a9337ec..4be8017 100644 --- a/test/Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/PlayerValidatorTests.cs +++ b/test/Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/PlayerValidatorTests.cs @@ -123,6 +123,30 @@ public async Task ValidateAsync_SquadNumberNotGreaterThanZero_ReturnsValidationE result.Errors.Should().Contain(error => error.PropertyName == "SquadNumber"); } + [Fact] + [Trait("Category", "Unit")] + public async Task ValidateAsync_SquadNumberNegative_ReturnsValidationError() + { + // Arrange + var request = PlayerFakes.MakeRequestModelForCreate(); + request.SquadNumber = -5; + var validator = CreateValidator(); + + // Act + var result = await validator.ValidateAsync( + request, + options => options.IncludeRuleSets("Create") + ); + + // Assert + result.IsValid.Should().BeFalse(); + result + .Errors.Should() + .Contain(error => + error.PropertyName == "SquadNumber" && error.ErrorMessage.Contains("greater than 0") + ); + } + [Fact] [Trait("Category", "Unit")] public async Task ValidateAsync_SquadNumberNotUnique_ReturnsValidationError() @@ -153,7 +177,7 @@ public async Task ValidateAsync_SquadNumberNotUnique_ReturnsValidationError() [Fact] [Trait("Category", "Unit")] - public async Task ValidateAsync_SquadNumber_BelongsToPlayerBeingUpdated_ReturnsNoErrors() + public async Task ValidateAsync_SquadNumberBelongsToPlayerBeingUpdated_ReturnsNoErrors() { // Arrange // Simulate a PUT request for an existing player: the squad number in the @@ -178,6 +202,26 @@ public async Task ValidateAsync_SquadNumber_BelongsToPlayerBeingUpdated_ReturnsN result.Errors.Should().BeEmpty(); } + [Fact] + [Trait("Category", "Unit")] + public async Task ValidateAsync_FirstNameEmptyInUpdateRuleSet_ReturnsValidationError() + { + // Arrange + var request = PlayerFakes.MakeRequestModelForUpdate(10); + request.FirstName = string.Empty; + var validator = CreateValidator(); + + // Act + var result = await validator.ValidateAsync( + request, + options => options.IncludeRuleSets("Update") + ); + + // Assert + result.IsValid.Should().BeFalse(); + result.Errors.Should().Contain(error => error.PropertyName == "FirstName"); + } + /* ------------------------------------------------------------------------- * AbbrPosition * ---------------------------------------------------------------------- */