diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 42a433b..7684856 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -19,10 +19,6 @@ jobs: - name: Build and test run: | - # TODO: Add your dotnet build/test commands here - # Go: go test ./... - # Python: pip install -r requirements.txt && pytest - # .NET: dotnet test - # Java (Maven): mvn test - # Java (Gradle): ./gradlew test - echo "No build commands configured — update squad-ci.yml" + dotnet restore + dotnet build --no-restore --configuration Release + dotnet test --no-build --configuration Release diff --git a/src/Api/Data/IssueRepository.cs b/src/Api/Data/IssueRepository.cs index 69740dc..45c16bd 100644 --- a/src/Api/Data/IssueRepository.cs +++ b/src/Api/Data/IssueRepository.cs @@ -138,6 +138,8 @@ internal class IssueEntity [BsonElement("updatedAt")] public DateTime UpdatedAt { get; set; } public bool IsArchived { get; set; } + public string? ArchivedBy { get; set; } + public DateTime? ArchivedAt { get; set; } public List? Labels { get; set; } public static IssueEntity FromDomain(Issue issue) diff --git a/src/Api/Program.cs b/src/Api/Program.cs index f326659..266e4d0 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -34,6 +34,24 @@ var app = builder.Build(); +app.UseExceptionHandler(errorApp => errorApp.Run(async context => +{ + var ex = context.Features.Get()?.Error; + if (ex is FluentValidation.ValidationException validationEx) + { + context.Response.StatusCode = StatusCodes.Status400BadRequest; + context.Response.ContentType = "application/problem+json"; + var errors = validationEx.Errors + .GroupBy(e => e.PropertyName) + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); + await context.Response.WriteAsJsonAsync(new { title = "Validation failed", errors }); + } + else + { + context.Response.StatusCode = StatusCodes.Status500InternalServerError; + } +})); + app.UseHttpsRedirection(); app.MapOpenApi(); diff --git a/src/Shared/Domain/Issue.cs b/src/Shared/Domain/Issue.cs index 6ab2001..2c1e70f 100644 --- a/src/Shared/Domain/Issue.cs +++ b/src/Shared/Domain/Issue.cs @@ -102,17 +102,17 @@ public Issue Update(string title, string? description) } /// - /// Gets or sets a value indicating whether the issue is archived (soft-deleted). + /// Gets a value indicating whether the issue is archived (soft-deleted). /// - public bool IsArchived { get; set; } = false; + public bool IsArchived { get; init; } = false; /// - /// Gets or sets the user who archived the issue. + /// Gets the user who archived the issue. /// - public string? ArchivedBy { get; set; } + public string? ArchivedBy { get; init; } /// - /// Gets or sets the timestamp when the issue was archived. + /// Gets the timestamp when the issue was archived. /// - public DateTime? ArchivedAt { get; set; } + public DateTime? ArchivedAt { get; init; } } diff --git a/tests/Unit/Validators/ListIssuesQueryValidatorTests.cs b/tests/Unit/Validators/ListIssuesQueryValidatorTests.cs index 8e32400..92512fa 100644 --- a/tests/Unit/Validators/ListIssuesQueryValidatorTests.cs +++ b/tests/Unit/Validators/ListIssuesQueryValidatorTests.cs @@ -62,7 +62,7 @@ public void ListIssuesQueryValidator_PageZero_ReturnsValidationError() result.IsValid.Should().BeFalse(); result.Errors.Should().HaveCount(1); result.Errors[0].PropertyName.Should().Be("Page"); - result.Errors[0].ErrorMessage.Should().Contain("greater than 0"); + result.Errors[0].ErrorMessage.Should().Contain("greater than or equal to 1"); } [Fact] @@ -100,7 +100,7 @@ public void ListIssuesQueryValidator_PageSizeZero_ReturnsValidationError() result.IsValid.Should().BeFalse(); result.Errors.Should().HaveCount(1); result.Errors[0].PropertyName.Should().Be("PageSize"); - result.Errors[0].ErrorMessage.Should().Contain("greater than 0"); + result.Errors[0].ErrorMessage.Should().Contain("between 1 and 100"); } [Fact]