defmodule AprsmeWeb.PageControllerUptimeTest do @moduledoc """ Direct tests for the four `format_uptime_parts/4` branches in PageController. We can't call the private function directly. Instead, register a fake `Aprsme.Is` process that responds to `:get_status` with a chosen `uptime_seconds`, then hit the controller and check the formatted string. """ use AprsmeWeb.ConnCase, async: false defmodule FakeIs do @moduledoc false use GenServer def start_link(uptime_seconds) do GenServer.start_link(__MODULE__, uptime_seconds, name: Aprsme.Is) end @impl true def init(uptime_seconds), do: {:ok, uptime_seconds} @impl true def handle_call(:get_status, _from, uptime_seconds) do now = DateTime.utc_now() connected_at = DateTime.add(now, -uptime_seconds, :second) reply = %{ connected: true, server: "test.local", port: 14_580, connected_at: connected_at, uptime_seconds: uptime_seconds, login_id: "N0CALL", filter: "r/0/0/100", packet_stats: %{total_packets: 0, packets_per_second: 0, last_packet_at: nil}, stored_packet_count: 0, oldest_packet_timestamp: nil } {:reply, reply, uptime_seconds} end end setup do # The real Aprsme.Is doesn't start in :test env, so the name is free. # Defensive: if some prior test registered something under it, unregister. if pid = Process.whereis(Aprsme.Is) do :erlang.unregister(Aprsme.Is) _ = pid end original_cluster = Application.get_env(:aprsme, :cluster_enabled) Application.put_env(:aprsme, :cluster_enabled, false) on_exit(fn -> Application.put_env(:aprsme, :cluster_enabled, original_cluster) end) :ok end defp call_with_uptime(uptime_seconds) do {:ok, fake} = FakeIs.start_link(uptime_seconds) try do conn = Phoenix.ConnTest.build_conn() result = AprsmeWeb.PageController.status_json(conn, %{}) Jason.decode!(result.resp_body) after if Process.alive?(fake), do: GenServer.stop(fake) end end describe "format_uptime branches via status_json" do test "formats multi-day uptime as 'Xd Yh Zm Ss'" do body = call_with_uptime(2 * 86_400 + 3 * 3600 + 15 * 60 + 5) display = body["aprs_is"]["uptime_display"] assert display =~ ~r/^\d+d \d+h \d+m \d+s$/ assert String.starts_with?(display, "2d ") end test "formats sub-day, multi-hour uptime as 'Yh Zm Ss'" do body = call_with_uptime(5 * 3600 + 30 * 60 + 12) display = body["aprs_is"]["uptime_display"] assert display =~ ~r/^\d+h \d+m \d+s$/ refute display =~ "d " end test "formats sub-hour, multi-minute uptime as 'Zm Ss'" do body = call_with_uptime(30 * 60 + 7) display = body["aprs_is"]["uptime_display"] assert display =~ ~r/^\d+m \d+s$/ refute display =~ "h " end test "formats sub-minute uptime as 'Ss'" do body = call_with_uptime(45) display = body["aprs_is"]["uptime_display"] assert display =~ ~r/^\d+s$/ refute display =~ "m " end end end