namespace SatelliteProvider.IntegrationTests; public static class ExtendedRouteTests { public static async Task RunExtendedRouteEast(HttpClient httpClient) { RouteTestHelpers.PrintTestHeader("Test: Extended Route with 20 Points - 10km East"); var routeId = Guid.NewGuid(); var request = new CreateRouteRequest { Id = routeId, Name = "Extended Route with 20 Points (10km East)", Description = "Test route with 20 action points, located 10km east of the complex route", RegionSizeMeters = 300.0, ZoomLevel = 18, RequestMaps = true, Points = new List { new() { Lat = 48.276067180586544, Lon = 37.51945758819581 }, new() { Lat = 48.27074009522731, Lon = 37.509029159545906 }, new() { Lat = 48.263312668696855, Lon = 37.51207614898682 }, new() { Lat = 48.26539817051818, Lon = 37.50087524414063 }, new() { Lat = 48.25851283439989, Lon = 37.49452377319337 }, new() { Lat = 48.254426906081555, Lon = 37.509801635742195 }, new() { Lat = 48.25914140977405, Lon = 37.52568031311036 }, new() { Lat = 48.25354110233028, Lon = 37.536752471923835 }, new() { Lat = 48.25902712391726, Lon = 37.551257858276374 }, new() { Lat = 48.26828345053738, Lon = 37.537009963989265 }, new() { Lat = 48.27421563182974, Lon = 37.52345758819581 }, new() { Lat = 48.26889854647051, Lon = 37.513029159545906 }, new() { Lat = 48.26147111993905, Lon = 37.51607614898682 }, new() { Lat = 48.26355662176038, Lon = 37.50487524414063 }, new() { Lat = 48.25667128564209, Lon = 37.49852377319337 }, new() { Lat = 48.25258535732375, Lon = 37.513801635742195 }, new() { Lat = 48.25729986101625, Lon = 37.52968031311036 }, new() { Lat = 48.25169955357248, Lon = 37.540752471923835 }, new() { Lat = 48.25718557515946, Lon = 37.555257858276374 }, new() { Lat = 48.26644190177958, Lon = 37.541009963989265 } } }; Console.WriteLine("Step 1: Creating extended route with RequestMaps=true"); RouteTestHelpers.PrintRouteCreationDetails(request); Console.WriteLine($" Location: ~10km east of original complex route"); Console.WriteLine(); RouteTestHelpers.PrintRoutePoints(request.Points, 5); var route = await RouteTestHelpers.CreateRoute(httpClient, request); RouteTestHelpers.PrintRouteResponse(route); RouteTestHelpers.PrintPointTypeDistribution(route); RouteTestHelpers.ValidatePointTypes(route, 1, 1, 18); RouteTestHelpers.ValidateRequestMaps(route, false); Console.WriteLine("Step 2: Waiting for extended route maps to be ready"); Console.WriteLine(" (Processing regions SEQUENTIALLY to avoid API throttling)"); Console.WriteLine(" (This will take several minutes for 20 action points)"); Console.WriteLine(); var finalRoute = await RouteTestHelpers.WaitForRouteReady(httpClient, routeId, 360, 3000); Console.WriteLine(); Console.WriteLine("Step 3: Verifying generated files"); RouteTestHelpers.ValidateFiles(finalRoute); var uniqueTileCount = await RouteTestHelpers.GetUniqueTileCount(finalRoute.CsvFilePath!); var stitchedInfo = new FileInfo(finalRoute.StitchedImagePath!); RouteTestHelpers.PrintGeneratedFiles(finalRoute, uniqueTileCount); RouteTestHelpers.PrintRouteSummary(finalRoute, uniqueTileCount); if (uniqueTileCount < 20) { throw new Exception($"Expected at least 20 unique tiles for extended route, got {uniqueTileCount}"); } if (stitchedInfo.Length < 1024) { throw new Exception($"Stitched image seems too small: {stitchedInfo.Length} bytes"); } Console.WriteLine("✓ Extended Route with 20 Points (10km East) Test: PASSED"); } public static async Task RunRouteWithTilesZipTest(HttpClient httpClient) { RouteTestHelpers.PrintTestHeader("Test: Route with Tiles ZIP File Creation"); var routeId = Guid.NewGuid(); var request = new CreateRouteRequest { Id = routeId, Name = "Route with Tiles ZIP", Description = "Test route with tiles zip file creation", RegionSizeMeters = 500.0, ZoomLevel = 18, RequestMaps = true, CreateTilesZip = true, Points = new List { new() { Lat = 48.276067180586544, Lon = 37.38445758819581 }, new() { Lat = 48.27074009522731, Lon = 37.374029159545906 } } }; Console.WriteLine($"Creating route with 2 points:"); Console.WriteLine($" Start: ({request.Points[0].Lat}, {request.Points[0].Lon})"); Console.WriteLine($" End: ({request.Points[1].Lat}, {request.Points[1].Lon})"); Console.WriteLine($" Region Size: {request.RegionSizeMeters}m"); Console.WriteLine($" Zoom Level: {request.ZoomLevel}"); Console.WriteLine($" Request Maps: {request.RequestMaps}"); Console.WriteLine($" Create Tiles ZIP: {request.CreateTilesZip}"); Console.WriteLine(); var route = await RouteTestHelpers.CreateRoute(httpClient, request); Console.WriteLine("Route Details:"); Console.WriteLine($" ID: {route.Id}"); Console.WriteLine($" Name: {route.Name}"); Console.WriteLine($" Total Points: {route.TotalPoints}"); Console.WriteLine($" Total Distance: {route.TotalDistanceMeters:F2}m"); Console.WriteLine($" Request Maps: {route.RequestMaps}"); Console.WriteLine($" Maps Ready: {route.MapsReady}"); Console.WriteLine(); RouteTestHelpers.ValidateRequestMaps(route, false); Console.WriteLine("Step 2: Waiting for route maps and zip file to be ready"); Console.WriteLine(" (Service is processing regions SEQUENTIALLY to avoid API throttling)"); Console.WriteLine(); var finalRoute = await RouteTestHelpers.WaitForRouteReady(httpClient, routeId, 180, 3000); Console.WriteLine(); Console.WriteLine("Step 3: Verifying generated files including ZIP"); RouteTestHelpers.ValidateFiles(finalRoute, true); var uniqueTileCount = await RouteTestHelpers.GetUniqueTileCount(finalRoute.CsvFilePath!); var zipInfo = new FileInfo(finalRoute.TilesZipPath!); RouteTestHelpers.PrintGeneratedFiles(finalRoute, uniqueTileCount, true); Console.WriteLine("Verifying ZIP file contents:"); using (var zipArchive = System.IO.Compression.ZipFile.OpenRead(finalRoute.TilesZipPath!)) { Console.WriteLine($" ZIP contains {zipArchive.Entries.Count} files"); if (zipArchive.Entries.Count == 0) { throw new Exception("ZIP file is empty"); } if (zipArchive.Entries.Count != uniqueTileCount) { throw new Exception($"ZIP contains {zipArchive.Entries.Count} files but CSV lists {uniqueTileCount} tiles"); } var firstEntry = zipArchive.Entries[0]; Console.WriteLine($" First entry: {firstEntry.FullName} ({firstEntry.Length} bytes)"); if (firstEntry.Length == 0) { throw new Exception("First entry in ZIP is empty"); } var entriesWithDirs = zipArchive.Entries.Where(e => e.FullName.Contains('/')).ToList(); Console.WriteLine($" Entries with directory structure: {entriesWithDirs.Count}/{zipArchive.Entries.Count}"); if (entriesWithDirs.Count == 0) { throw new Exception("ZIP should preserve directory structure but found no entries with paths"); } var samplePaths = entriesWithDirs.Take(3).Select(e => e.FullName).ToList(); Console.WriteLine($" Sample paths:"); foreach (var path in samplePaths) { Console.WriteLine($" - {path}"); } if (!firstEntry.FullName.StartsWith("tiles/")) { throw new Exception($"Expected path to start with 'tiles/' but got '{firstEntry.FullName}'"); } var pathParts = firstEntry.FullName.Split('/'); if (pathParts.Length < 5) { throw new Exception($"Expected directory structure like 'tiles/18/158/91/tile_xxx.jpg' but got '{firstEntry.FullName}'"); } Console.WriteLine($" ✓ Directory structure preserved ({pathParts[0]}/zoom/{pathParts[1]}/x-bucket/{pathParts[2]}/y-bucket/{pathParts[3]}/file)"); } Console.WriteLine(); RouteTestHelpers.PrintRouteSummary(finalRoute, uniqueTileCount, null, true); if (zipInfo.Length < 1024) { throw new Exception($"ZIP file seems too small: {zipInfo.Length} bytes"); } Console.WriteLine("✓ Route with Tiles ZIP File Test: PASSED"); } }