Adds ~800 new tests (incl. 27 StreamData properties) across 22 modules that previously had little or no coverage. Highlights: - Pure utility modules (LogSanitizer, PacketFieldWhitelist, PacketSanitizer, DeviceParser, CoordinateUtils, BoundsUtils, ParamUtils, Convert, WeatherUnits) get thorough unit + property coverage including UTF-8 truncation boundaries, antimeridian longitude wrap, Haversine symmetry, and unit-conversion inverses. - JSON view modules (CallsignJSON, ErrorJSON, ChangesetJSON) verified for envelope shape and error templating. - Plugs (HealthCheck, RateLimiter, ApiCSRF) exercised for happy-path and halt paths. - GenServer modules (RegexCache, CleanupScheduler, DeploymentNotifier) tested without touching the supervised singleton where possible. - Drops the orphaned map_live/map_helpers_test.exs whose module name collided with the new live/shared/coordinate_utils_test.exs.
78 lines
2.8 KiB
Elixir
78 lines
2.8 KiB
Elixir
defmodule AprsmeWeb.Api.V1.FallbackControllerTest do
|
|
use AprsmeWeb.ConnCase, async: true
|
|
|
|
import Phoenix.Controller, only: [put_format: 2]
|
|
|
|
alias AprsmeWeb.Api.V1.FallbackController
|
|
|
|
defp invalid_changeset do
|
|
%Aprsme.Devices{} |> Aprsme.Devices.changeset(%{}) |> Map.put(:action, :insert)
|
|
end
|
|
|
|
# Phoenix's render/3 looks up `_format` in conn.params. The bare build_conn
|
|
# hasn't fetched params — put_format/2 short-circuits that lookup so the
|
|
# fallback controller can be exercised in isolation.
|
|
defp prep(conn), do: put_format(conn, "json")
|
|
|
|
defp json(conn), do: Jason.decode!(conn.resp_body)
|
|
|
|
describe "call/2" do
|
|
test "handles {:error, changeset}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, invalid_changeset()})
|
|
assert conn.status == 422
|
|
body = json(conn)
|
|
assert body["error"]["code"] == "validation_error"
|
|
assert is_map(body["error"]["details"])
|
|
end
|
|
|
|
test "handles {:error, :not_found}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, :not_found})
|
|
assert conn.status == 404
|
|
assert json(conn)["error"]["code"] == "not_found"
|
|
end
|
|
|
|
test "handles {:error, :unauthorized}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, :unauthorized})
|
|
assert conn.status == 401
|
|
assert json(conn)["error"]["code"] == "generic_error"
|
|
end
|
|
|
|
test "handles {:error, :forbidden}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, :forbidden})
|
|
assert conn.status == 403
|
|
end
|
|
|
|
test "handles {:error, :bad_request}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, :bad_request})
|
|
assert conn.status == 400
|
|
end
|
|
|
|
test "unknown atom reasons produce 500", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, :totally_unknown})
|
|
assert conn.status == 500
|
|
end
|
|
|
|
test "handles {:error, atom, message}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, :bad_request, "specific message"})
|
|
assert conn.status == 400
|
|
assert json(conn)["error"]["message"] == "specific message"
|
|
end
|
|
|
|
test "handles {:error, binary}", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), {:error, "custom error"})
|
|
assert conn.status == 400
|
|
assert json(conn)["error"]["message"] == "custom error"
|
|
end
|
|
|
|
test "handles :timeout", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), :timeout)
|
|
assert conn.status == 408
|
|
end
|
|
|
|
test "handles unknown errors with 500", %{conn: conn} do
|
|
conn = FallbackController.call(prep(conn), :some_weird_thing)
|
|
assert conn.status == 500
|
|
assert json(conn)["error"]["code"] == "internal_server_error"
|
|
end
|
|
end
|
|
end
|