using FluentValidation.TestHelper; using SatelliteProvider.Api.Validators; using SatelliteProvider.Common.DTO; namespace SatelliteProvider.Tests.Validators; // AZ-808: unit tests for RegionRequestValidator. Each RuleFor in the validator // has at least one passing case + one failing case. Required-field detection // (id / lat / lon / sizeMeters / zoomLevel / stitchTiles) is not unit-tested // here because it lives at the deserializer layer (JsonRequired), not the // validator — covered by the integration tests (RegionRequestValidationTests). public class RegionRequestValidatorTests { private readonly RegionRequestValidator _validator; public RegionRequestValidatorTests() { GlobalValidatorConfig.ApplyOnce(); _validator = new RegionRequestValidator(); } private static RequestRegionRequest ValidRequest() => new() { Id = Guid.NewGuid(), Lat = 47.461747, Lon = 37.647063, SizeMeters = 200.0, ZoomLevel = 18, StitchTiles = false, }; [Fact] public void Validate_AllValid_Passes() { // Arrange var request = ValidRequest(); // Act var result = _validator.TestValidate(request); // Assert result.ShouldNotHaveAnyValidationErrors(); } [Fact] public void Validate_IdEmpty_FailsNotEmptyRule() { // Arrange var request = ValidRequest() with { Id = Guid.Empty }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldHaveValidationErrorFor("id") .WithErrorMessage("`id` must be a non-zero GUID (the caller's idempotency key)."); } [Theory] [InlineData(-90.001)] [InlineData(90.001)] [InlineData(180.0)] [InlineData(-181.0)] public void Validate_LatOutOfRange_FailsRangeRule(double lat) { // Arrange var request = ValidRequest() with { Lat = lat }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldHaveValidationErrorFor("lat"); } [Theory] [InlineData(-90.0)] [InlineData(0.0)] [InlineData(47.461747)] [InlineData(90.0)] public void Validate_LatAtOrInsideBounds_Passes(double lat) { // Arrange var request = ValidRequest() with { Lat = lat }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldNotHaveValidationErrorFor("lat"); } [Theory] [InlineData(-180.001)] [InlineData(180.001)] [InlineData(360.0)] public void Validate_LonOutOfRange_FailsRangeRule(double lon) { // Arrange var request = ValidRequest() with { Lon = lon }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldHaveValidationErrorFor("lon"); } [Theory] [InlineData(-180.0)] [InlineData(0.0)] [InlineData(37.647063)] [InlineData(180.0)] public void Validate_LonAtOrInsideBounds_Passes(double lon) { // Arrange var request = ValidRequest() with { Lon = lon }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldNotHaveValidationErrorFor("lon"); } [Theory] [InlineData(99.999)] [InlineData(0.0)] [InlineData(10000.001)] [InlineData(100000.0)] [InlineData(-1.0)] public void Validate_SizeMetersOutOfRange_FailsRangeRule(double sizeMeters) { // Arrange var request = ValidRequest() with { SizeMeters = sizeMeters }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldHaveValidationErrorFor("sizeMeters"); } [Theory] [InlineData(100.0)] [InlineData(200.0)] [InlineData(5000.0)] [InlineData(10000.0)] public void Validate_SizeMetersAtOrInsideBounds_Passes(double sizeMeters) { // Arrange var request = ValidRequest() with { SizeMeters = sizeMeters }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldNotHaveValidationErrorFor("sizeMeters"); } [Theory] [InlineData(-1)] [InlineData(23)] [InlineData(100)] public void Validate_ZoomLevelOutOfRange_FailsRangeRule(int zoomLevel) { // Arrange var request = ValidRequest() with { ZoomLevel = zoomLevel }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldHaveValidationErrorFor("zoomLevel"); } [Theory] [InlineData(0)] [InlineData(18)] [InlineData(22)] public void Validate_ZoomLevelAtOrInsideBounds_Passes(int zoomLevel) { // Arrange var request = ValidRequest() with { ZoomLevel = zoomLevel }; // Act var result = _validator.TestValidate(request); // Assert result.ShouldNotHaveValidationErrorFor("zoomLevel"); } }