defmodule Microwaveprop.RadioTest do use Microwaveprop.DataCase, async: true alias Microwaveprop.Radio alias Microwaveprop.Radio.Qso defp create_qso(attrs \\ %{}) do default = %{ station1: "W5XD", station2: "K5TR", qso_timestamp: ~U[2026-03-28 18:00:00Z], mode: "CW", band: Decimal.new("1296"), grid1: "EM12", grid2: "EM00", pos1: %{"lat" => 32.9, "lon" => -97.0}, pos2: %{"lat" => 30.3, "lon" => -97.7}, distance_km: Decimal.new("295") } {:ok, qso} = %Qso{} |> Qso.changeset(Map.merge(default, attrs)) |> Repo.insert() qso end describe "list_qsos/1" do test "returns empty page when no QSOs exist" do result = Radio.list_qsos() assert result.entries == [] assert result.page == 1 assert result.total_pages == 1 assert result.total_entries == 0 end test "paginates 20 per page, ordered by qso_timestamp desc" do for i <- 1..25 do ts = DateTime.add(~U[2026-01-01 00:00:00Z], i * 3600, :second) create_qso(%{qso_timestamp: ts}) end result = Radio.list_qsos() assert length(result.entries) == 20 assert result.page == 1 assert result.total_pages == 2 assert result.total_entries == 25 # Most recent first first = hd(result.entries) assert first.qso_timestamp == DateTime.add(~U[2026-01-01 00:00:00Z], 25 * 3600, :second) end test "returns second page" do for i <- 1..25 do ts = DateTime.add(~U[2026-01-01 00:00:00Z], i * 3600, :second) create_qso(%{qso_timestamp: ts}) end result = Radio.list_qsos(page: 2) assert length(result.entries) == 5 assert result.page == 2 assert result.total_pages == 2 end end describe "list_qsos/1 sorting" do test "sorts by station1 ascending" do create_qso(%{station1: "ZZ9ZZ"}) create_qso(%{station1: "AA1AA"}) result = Radio.list_qsos(sort_by: :station1, sort_order: :asc) stations = Enum.map(result.entries, & &1.station1) assert stations == ["AA1AA", "ZZ9ZZ"] end test "sorts by distance_km descending" do create_qso(%{distance_km: Decimal.new("100"), station1: "A1A"}) create_qso(%{distance_km: Decimal.new("500"), station1: "B2B"}) result = Radio.list_qsos(sort_by: :distance_km, sort_order: :desc) distances = Enum.map(result.entries, & &1.distance_km) assert distances == [Decimal.new("500"), Decimal.new("100")] end test "invalid sort_by falls back to qso_timestamp desc" do early = create_qso(%{qso_timestamp: ~U[2026-01-01 00:00:00Z]}) late = create_qso(%{qso_timestamp: ~U[2026-03-01 00:00:00Z]}) result = Radio.list_qsos(sort_by: :bogus) ids = Enum.map(result.entries, & &1.id) assert ids == [late.id, early.id] end end describe "get_qso!/1" do test "returns a QSO by ID" do qso = create_qso() found = Radio.get_qso!(qso.id) assert found.id == qso.id assert found.station1 == "W5XD" end test "raises Ecto.NoResultsError on bad ID" do assert_raise Ecto.NoResultsError, fn -> Radio.get_qso!(Ecto.UUID.generate()) end end end end