using System.Net; using System.Text; namespace SatelliteProvider.IntegrationTests; public static class StubAndErrorContractTests { public static async Task RunAll(HttpClient httpClient) { RouteTestHelpers.PrintTestHeader("Test: Stub endpoints + error contracts (AZ-356 / AZ-353)"); await StubMgrs_Returns501(httpClient); await StubUpload_Returns501(httpClient); await CreateRoute_InvalidPayload_Returns400_AZ353_AC3(httpClient); Console.WriteLine("✓ Stub + error-contract tests: PASSED"); } private static async Task StubMgrs_Returns501(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("AZ-356 AC-1: GET /api/satellite/tiles/mgrs returns 501"); var response = await httpClient.GetAsync("/api/satellite/tiles/mgrs?mgrs=33TWN1234567890&squareSideMeters=100"); var status = (int)response.StatusCode; if (status != 501) { throw new Exception($"Expected 501 from /api/satellite/tiles/mgrs, got {status}"); } var body = await response.Content.ReadAsStringAsync(); if (!body.Contains("Not implemented", StringComparison.OrdinalIgnoreCase)) { throw new Exception($"Expected ProblemDetails body containing 'Not implemented', got: {body}"); } Console.WriteLine($" ✓ /api/satellite/tiles/mgrs returns HTTP 501 with ProblemDetails"); } private static async Task StubUpload_Returns501(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("AZ-356 AC-1: POST /api/satellite/upload returns 501"); using var multipart = new MultipartFormDataContent { { new StringContent(DateTime.UtcNow.ToString("o")), "Timestamp" }, { new StringContent("47.461747"), "Lat" }, { new StringContent("37.647063"), "Lon" }, { new StringContent("100"), "Height" }, { new StringContent("35"), "FocalLength" }, { new StringContent("23"), "SensorWidth" }, { new StringContent("15.6"), "SensorHeight" }, }; var fakeImage = new ByteArrayContent(new byte[] { 0xFF, 0xD8, 0xFF, 0xD9 }); fakeImage.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg"); multipart.Add(fakeImage, "Image", "test.jpg"); var response = await httpClient.PostAsync("/api/satellite/upload", multipart); var status = (int)response.StatusCode; if (status != 501) { throw new Exception($"Expected 501 from /api/satellite/upload, got {status}"); } Console.WriteLine($" ✓ /api/satellite/upload returns HTTP 501"); } private static async Task CreateRoute_InvalidPayload_Returns400_AZ353_AC3(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("AZ-353 AC-3: POST /api/satellite/route with <2 points returns 400 (typed ArgumentException path preserved)"); var routeId = Guid.NewGuid(); var body = $"{{\"id\":\"{routeId}\",\"name\":\"too-short\",\"description\":\"\",\"regionSizeMeters\":500,\"zoomLevel\":18,\"requestMaps\":false,\"points\":[{{\"latitude\":47.46,\"longitude\":37.64}}]}}"; var content = new StringContent(body, Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync("/api/satellite/route", content); var status = (int)response.StatusCode; if (status != 400) { throw new Exception($"Expected 400 for 1-point route (typed ArgumentException), got {status}"); } Console.WriteLine($" ✓ 1-point route rejected with HTTP 400 (typed handling preserved)"); } }