Promoted pure presentation and utility helpers from `defp` to `def @doc false` across ~20 LiveViews, Oban workers, and sync modules so they're reachable from unit tests. Refactored several `cond` blocks into idiomatic function heads with guards. Added ~250 new test cases in new files under test/towerops and test/towerops_web, including DB-backed tests for CnMaestro.Sync and AlertNotificationWorker, and removed dead LiveView tab components and CapacityLive (no callers anywhere in lib/test). Configured mix.exs test_coverage.ignore_modules to exclude vendored third-party code (SnmpKit, protobuf-generated Towerops.Agent.*, Absinthe GraphQL types, Phoenix HTML modules, Inspect protocol impls) from coverage calculations — these are not our project code. Coverage: 66.93% → 70.09%. Full suite: 10,127 tests, 0 failures.
140 lines
4.1 KiB
Elixir
140 lines
4.1 KiB
Elixir
defmodule Towerops.GeocodingTest do
|
|
use ExUnit.Case, async: false
|
|
|
|
alias Towerops.Geocoding
|
|
|
|
setup do
|
|
original = Application.get_env(:towerops, :google_maps_api_key)
|
|
Application.put_env(:towerops, :google_maps_api_key, "test-key")
|
|
|
|
on_exit(fn ->
|
|
if is_nil(original) do
|
|
Application.delete_env(:towerops, :google_maps_api_key)
|
|
else
|
|
Application.put_env(:towerops, :google_maps_api_key, original)
|
|
end
|
|
end)
|
|
|
|
:ok
|
|
end
|
|
|
|
describe "geocode/1" do
|
|
test "returns lat/lng/formatted_address on OK response" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
assert conn.query_string =~ "address="
|
|
assert conn.query_string =~ "key=test-key"
|
|
|
|
Req.Test.json(conn, %{
|
|
"status" => "OK",
|
|
"results" => [
|
|
%{
|
|
"geometry" => %{"location" => %{"lat" => 40.7128, "lng" => -74.006}},
|
|
"formatted_address" => "New York, NY, USA"
|
|
}
|
|
]
|
|
})
|
|
end)
|
|
|
|
assert {:ok, result} = Geocoding.geocode("New York")
|
|
assert result.latitude == 40.7128
|
|
assert result.longitude == -74.006
|
|
assert result.formatted_address == "New York, NY, USA"
|
|
end
|
|
|
|
test "returns error on ZERO_RESULTS" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{"status" => "ZERO_RESULTS", "results" => []})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("nonexistent address")
|
|
assert message =~ "No results"
|
|
end
|
|
|
|
test "returns error on OVER_QUERY_LIMIT" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{"status" => "OVER_QUERY_LIMIT"})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("anywhere")
|
|
assert message =~ "quota"
|
|
end
|
|
|
|
test "returns error on REQUEST_DENIED with message" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{
|
|
"status" => "REQUEST_DENIED",
|
|
"error_message" => "API key invalid"
|
|
})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("anywhere")
|
|
assert message =~ "denied"
|
|
assert message =~ "API key invalid"
|
|
end
|
|
|
|
test "returns error on INVALID_REQUEST" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{"status" => "INVALID_REQUEST"})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("")
|
|
assert message =~ "Invalid request"
|
|
end
|
|
|
|
test "returns error on unknown status" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{"status" => "UNKNOWN_ERROR"})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("anywhere")
|
|
assert message =~ "UNKNOWN_ERROR"
|
|
end
|
|
|
|
test "returns error when OK but missing geometry" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{
|
|
"status" => "OK",
|
|
"results" => [%{"formatted_address" => "Somewhere"}]
|
|
})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("anywhere")
|
|
assert message =~ "Invalid response format"
|
|
end
|
|
|
|
test "returns error for unexpected response body" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
Req.Test.json(conn, %{"unexpected" => "shape"})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("anywhere")
|
|
assert message =~ "Unexpected response format"
|
|
end
|
|
|
|
test "returns error on non-200 status" do
|
|
Req.Test.stub(Geocoding, fn conn ->
|
|
conn
|
|
|> Plug.Conn.put_status(500)
|
|
|> Req.Test.json(%{"error" => "server error"})
|
|
end)
|
|
|
|
assert {:error, message} = Geocoding.geocode("anywhere")
|
|
assert message =~ "Geocoding API error"
|
|
assert message =~ "500"
|
|
end
|
|
|
|
test "returns :no_api_key error when key is missing" do
|
|
Application.delete_env(:towerops, :google_maps_api_key)
|
|
System.delete_env("GOOGLE_MAPS_API_KEY")
|
|
|
|
assert {:error, :no_api_key} = Geocoding.geocode("anywhere")
|
|
end
|
|
|
|
test "returns :no_api_key error when key is whitespace-only" do
|
|
Application.put_env(:towerops, :google_maps_api_key, " ")
|
|
System.delete_env("GOOGLE_MAPS_API_KEY")
|
|
|
|
assert {:error, :no_api_key} = Geocoding.geocode("anywhere")
|
|
end
|
|
end
|
|
end
|