using System.Text; namespace Cepis.Tests; /// The batch: order, absences, chunking, and the missing coordinate. public sealed class BatchTests : HttpTestBase { [Fact] public async Task KeepsTheRequestedOrderAndLength() { Server.Handle(_ => Reply.Of(200, Fixtures.CsvBatch)); var result = await Client.LookupManyAsync(["01001000", "99999999", "20040020"]); Assert.Equal(3, result.Count); Assert.Equal("São Paulo", result[0]?.Localidade); Assert.Null(result[1]); Assert.Equal("Rio de Janeiro", result[2]?.Localidade); } [Fact] public async Task CarriesNoCoordinate() { Server.Handle(_ => Reply.Of(200, Fixtures.CsvBatch)); var result = await Client.LookupManyAsync(["01001000"]); Assert.NotNull(result[0]); Assert.Null(result[0]!.Geo); } [Fact] public async Task AMalformedCepIsNullRatherThanAnError() { Server.Handle(call => Reply.Of(200, Csv(call))); var result = await Client.LookupManyAsync(["01001000", "oops", "20040020"]); Assert.Equal(3, result.Count); Assert.NotNull(result[0]); Assert.Null(result[1]); Assert.NotNull(result[2]); } [Fact] public async Task ChunksAboveFiveHundred() { Server.Handle(call => Reply.Of(200, Csv(call))); var ceps = Enumerable.Range(0, 600).Select(i => $"{i:D8}").ToList(); var result = await Client.LookupManyAsync(ceps); Assert.Equal(600, result.Count); Assert.Equal(2, Server.Calls.Count); Assert.Equal(CepisClient.MaxBatch, CountCeps(Server.Calls[0])); Assert.Equal(100, CountCeps(Server.Calls[1])); Assert.All(result, address => Assert.NotNull(address)); } [Fact] public async Task ExactlyFiveHundredIsOneRequest() { Server.Handle(call => Reply.Of(200, Csv(call))); var ceps = Enumerable.Range(0, CepisClient.MaxBatch).Select(i => $"{i:D8}").ToList(); var result = await Client.LookupManyAsync(ceps); Assert.Equal(CepisClient.MaxBatch, result.Count); Assert.Single(Server.Calls); } [Fact] public async Task AShortResponseIsPaddedRatherThanShifted() { Server.Handle(_ => Reply.Of(200, Fixtures.CsvHeader + "\n" + Fixtures.CsvRow("01001000") + "\n")); var result = await Client.LookupManyAsync(["01001000", "20040020", "30140071"]); Assert.Equal(3, result.Count); Assert.Equal("01001000", result[0]?.Cep); Assert.Null(result[1]); Assert.Null(result[2]); } [Fact] public async Task AnEmptyInputMakesNoRequest() { var result = await Client.LookupManyAsync([]); Assert.Empty(result); Assert.Empty(Server.Calls); } [Fact] public async Task ValuesWithCommasSurviveTheParse() { Server.Handle(_ => Reply.Of(200, Fixtures.CsvHeader + "\n" + "\"01001000\",\"Praça da Sé, lado ímpar\",,,Sé,São Paulo,SP,São Paulo,Sudeste,3550308,1004,11,7107\n")); var result = await Client.LookupManyAsync(["01001000"]); Assert.Equal("Praça da Sé, lado ímpar", result[0]?.Logradouro); } private static string Csv(Call call) { var body = new StringBuilder(Fixtures.CsvHeader); foreach (var cep in Requested(call)) { body.Append('\n').Append(cep.Length == 8 ? Fixtures.CsvRow(cep) : cep + ",,,,,,,,,,,,"); } return body.Append('\n').ToString(); } private static string[] Requested(Call call) => (call.Ceps ?? "").Split(',', StringSplitOptions.RemoveEmptyEntries); private static int CountCeps(Call call) => Requested(call).Length; }