Files
satellite-provider/SatelliteProvider.Tests/RouteRegionMatcherTests.cs
T
Oleksandr Bezdieniezhnykh 6f23120c49 [AZ-364] [AZ-360] Refactor C11+C08: decompose RouteProcessingService
Extracts RouteRegionMatcher, RouteCsvWriter, RouteSummaryWriter,
RouteImageRenderer, TilesZipBuilder, RegionFileCleaner from the
~750-LOC RouteProcessingService god-class. Moves TileInfo to its
own file as a sealed record. Replaces IServiceProvider scope-
locator with a direct IRegionService injection (folds AZ-360 / C08).
Updates DI registration and tests.

Tests: 133 / 133 unit + 5 / 5 smoke green; integration suite exit 0.
Pixel-equivalent stitched route image and byte-equivalent CSV /
summary / ZIP outputs verified through the smoke run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 03:12:49 +03:00

100 lines
3.5 KiB
C#

using FluentAssertions;
using SatelliteProvider.DataAccess.Models;
using SatelliteProvider.Services.RouteManagement;
namespace SatelliteProvider.Tests;
// AZ-364 / C11: pure-helper tests for the route-point ↔ region nearest-
// neighbour matcher extracted from RouteProcessingService.
public class RouteRegionMatcherTests
{
[Fact]
public void Match_OrdersRegionsToFollowRoutePointSequence_AZ364_AC1()
{
// Arrange
var sut = new RouteRegionMatcher();
var routePoints = new List<RoutePointEntity>
{
new() { Latitude = 0.0, Longitude = 0.0, SequenceNumber = 0 },
new() { Latitude = 1.0, Longitude = 0.0, SequenceNumber = 1 },
new() { Latitude = 2.0, Longitude = 0.0, SequenceNumber = 2 },
};
var regionFar = new RegionEntity { Id = Guid.NewGuid(), Latitude = 2.0, Longitude = 0.0 };
var regionNear = new RegionEntity { Id = Guid.NewGuid(), Latitude = 0.0, Longitude = 0.0 };
var regionMid = new RegionEntity { Id = Guid.NewGuid(), Latitude = 1.0, Longitude = 0.0 };
var unorderedRegions = new List<RegionEntity> { regionFar, regionNear, regionMid };
// Act
var ordered = sut.Match(routePoints, unorderedRegions);
// Assert
ordered.Should().HaveCount(3);
ordered[0].Id.Should().Be(regionNear.Id);
ordered[1].Id.Should().Be(regionMid.Id);
ordered[2].Id.Should().Be(regionFar.Id);
}
[Fact]
public void Match_ConsumesEachRegionAtMostOnce_AZ364_AC1()
{
// Arrange
var sut = new RouteRegionMatcher();
var sharedRegion = new RegionEntity { Id = Guid.NewGuid(), Latitude = 0.0, Longitude = 0.0 };
var otherRegion = new RegionEntity { Id = Guid.NewGuid(), Latitude = 10.0, Longitude = 0.0 };
var routePoints = new List<RoutePointEntity>
{
new() { Latitude = 0.0, Longitude = 0.0, SequenceNumber = 0 },
new() { Latitude = 0.001, Longitude = 0.0, SequenceNumber = 1 },
};
// Act
var ordered = sut.Match(routePoints, new List<RegionEntity> { sharedRegion, otherRegion });
// Assert
ordered.Should().HaveCount(2);
ordered.Select(r => r.Id).Should().OnlyHaveUniqueItems();
ordered[0].Id.Should().Be(sharedRegion.Id);
ordered[1].Id.Should().Be(otherRegion.Id);
}
[Fact]
public void Match_FewerRegionsThanPoints_ReturnsAvailableSubset_AZ364_AC1()
{
// Arrange
var sut = new RouteRegionMatcher();
var soleRegion = new RegionEntity { Id = Guid.NewGuid(), Latitude = 0.0, Longitude = 0.0 };
var routePoints = new List<RoutePointEntity>
{
new() { Latitude = 0.0, Longitude = 0.0, SequenceNumber = 0 },
new() { Latitude = 1.0, Longitude = 0.0, SequenceNumber = 1 },
};
// Act
var ordered = sut.Match(routePoints, new List<RegionEntity> { soleRegion });
// Assert
ordered.Should().HaveCount(1);
ordered[0].Id.Should().Be(soleRegion.Id);
}
[Fact]
public void Match_NullArguments_Throws_AZ364_AC1()
{
// Arrange
var sut = new RouteRegionMatcher();
// Act
Action actNullPoints = () => sut.Match(null!, new List<RegionEntity>());
Action actNullRegions = () => sut.Match(new List<RoutePointEntity>(), null!);
// Assert
actNullPoints.Should().Throw<ArgumentNullException>();
actNullRegions.Should().Throw<ArgumentNullException>();
}
}