defmodule Cepis.LookupTest do use Cepis.ServerCase test "resolves a CEP", %{server: server, client: client} do FakeServer.respond(server, "/01001000", {200, json(address_fixture()), []}) assert {:ok, address} = Cepis.lookup("01001-000", client) assert address.logradouro == "Praça da Sé" assert address.localidade == "São Paulo" assert address.uf == "SP" assert Cepis.Address.formatted_cep(address) == "01001-000" assert address.geo == nil end test "reads the coordinate when the API sends one", %{server: server, client: client} do body = address_fixture(%{ "geo" => %{"lat" => -23.5, "lon" => -46.6, "raio_m" => 120, "precisao" => "logradouro"} }) FakeServer.respond(server, "/01310100", {200, json(body), []}) assert {:ok, address} = Cepis.lookup("01310100", client) assert address.geo.lat == -23.5 assert address.geo.lon == -46.6 assert address.geo.raio_m == 120 assert Cepis.Geo.precise?(address.geo) end test "a municipality centroid is not precise", %{server: server, client: client} do body = address_fixture(%{ "geo" => %{"lat" => -23.5, "lon" => -46.6, "raio_m" => 22_000, "precisao" => "localidade"} }) FakeServer.respond(server, "/01001000", {200, json(body), []}) assert {:ok, address} = Cepis.lookup("01001000", client) refute Cepis.Geo.precise?(address.geo) end test "a malformed geo block does not lose the address", %{server: server, client: client} do body = address_fixture(%{ "geo" => %{ "lat" => "not a number", "lon" => "-46.6", "raio_m" => "120", "precisao" => "logradouro" } }) FakeServer.respond(server, "/01001000", {200, json(body), []}) assert {:ok, address} = Cepis.lookup("01001000", client) assert address.geo == nil assert address.localidade == "São Paulo" end test "a truncated geo block does not lose the address", %{server: server, client: client} do FakeServer.respond(server, "/01001000", {200, json(address_fixture(%{"geo" => %{}})), []}) assert {:ok, address} = Cepis.lookup("01001000", client) assert address.geo == nil assert address.uf == "SP" end test "a field the API grows is kept in raw", %{server: server, client: client} do body = address_fixture(%{"campo_do_futuro" => "value"}) FakeServer.respond(server, "/01001000", {200, json(body), []}) assert {:ok, address} = Cepis.lookup("01001000", client) assert address.raw["campo_do_futuro"] == "value" assert address.localidade == "São Paulo" end test "a missing CEP is a not-found error", %{server: server, client: client} do FakeServer.respond( server, "/99999999", {404, json(%{"erro" => "cep_nao_encontrado", "mensagem" => "gone"}), []} ) assert {:error, %Cepis.NotFoundError{cep: "99999999"} = error} = Cepis.lookup("99999999", client) assert Exception.message(error) =~ "99999999" end test "a 404 is never retried", %{server: server, client: client} do FakeServer.respond(server, "/99999999", {404, json(%{"erro" => "cep_nao_encontrado"}), []}) assert {:error, %Cepis.NotFoundError{}} = Cepis.lookup("99999999", client) assert FakeServer.count(server, "/99999999") == 1 end test "a malformed CEP never leaves the machine", %{server: server, client: client} do assert {:error, %Cepis.InvalidCEPError{}} = Cepis.lookup("123", client) assert FakeServer.calls(server) == [] end test "a 400 carries the API's own message", %{server: server, client: client} do FakeServer.respond( server, "/00000000", {400, json(%{"erro" => "cep_invalido", "mensagem" => "rejected by the API"}), []} ) assert {:error, %Cepis.InvalidCEPError{} = error} = Cepis.lookup("00000000", client) assert Exception.message(error) =~ "rejected by the API" end test "a 400 is never retried", %{server: server, client: client} do FakeServer.respond(server, "/00000000", {400, json(%{"erro" => "cep_invalido"}), []}) assert {:error, %Cepis.InvalidCEPError{}} = Cepis.lookup("00000000", client) assert FakeServer.count(server, "/00000000") == 1 end test "a captive portal answering instead of the API is diagnosed", %{ server: server, client: client } do FakeServer.respond(server, "/01001000", {200, "captive portal", []}) assert {:error, %Cepis.InvalidResponseError{} = error} = Cepis.lookup("01001000", client) assert Exception.message(error) =~ "captive portal" end test "a JSON body that is not an object is rejected", %{server: server, client: client} do FakeServer.respond(server, "/01001000", {200, "[1,2,3]", []}) assert {:error, %Cepis.InvalidResponseError{}} = Cepis.lookup("01001000", client) end test "the bang variant returns the address and raises on failure", %{ server: server, client: client } do FakeServer.respond(server, "/01001000", {200, json(address_fixture()), []}) assert %Cepis.Address{uf: "SP"} = Cepis.lookup!("01001000", client) assert_raise Cepis.NotFoundError, fn -> Cepis.lookup!("99999999", client) end end test "keyword options work in place of a client struct", %{server: server} do FakeServer.respond(server, "/01001000", {200, json(address_fixture()), []}) assert {:ok, address} = Cepis.lookup("01001000", base_url: server.url, timeout: 5_000) assert address.localidade == "São Paulo" end end