defmodule Microwaveprop.Workers.TerrainProfileWorkerTest do use Microwaveprop.DataCase, async: true alias Microwaveprop.Radio.Contact alias Microwaveprop.Terrain alias Microwaveprop.Terrain.ElevationClient alias Microwaveprop.Workers.TerrainProfileWorker @qso_attrs %{ station1: "W5XD", station2: "K5TR", qso_timestamp: ~U[2026-03-28 18:00:00Z], mode: "CW", band: Decimal.new("1296"), pos1: %{"lat" => 32.9, "lon" => -97.0}, pos2: %{"lat" => 30.3, "lon" => -97.7}, distance_km: Decimal.new("295") } defp create_contact(attrs \\ %{}) do {:ok, contact} = %Contact{} |> Contact.changeset(Map.merge(@qso_attrs, attrs)) |> Repo.insert() contact end defp stub_elevation_api do Req.Test.stub(ElevationClient, fn conn -> params = Plug.Conn.fetch_query_params(conn).query_params lat_count = params["latitude"] |> String.split(",") |> length() elevations = List.duplicate(200.0, lat_count) Req.Test.json(conn, %{"elevation" => elevations}) end) end describe "perform/1" do test "fetches elevation and stores terrain profile" do stub_elevation_api() contact = create_contact() refute Terrain.has_terrain_profile?(contact.id) job = TerrainProfileWorker.new(%{"contact_id" => contact.id}) assert :ok = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args}) assert Terrain.has_terrain_profile?(contact.id) profile = Terrain.get_terrain_profile(contact.id) assert profile.sample_count == 65 assert profile.verdict in ["CLEAR", "FRESNEL_MINOR", "FRESNEL_PARTIAL", "BLOCKED"] assert is_list(profile.path_points) end test "skips if terrain profile already exists" do stub_elevation_api() contact = create_contact() {:ok, _} = Terrain.upsert_terrain_profile(%{ contact_id: contact.id, sample_count: 65, path_points: [], verdict: "CLEAR" }) job = TerrainProfileWorker.new(%{"contact_id" => contact.id}) assert :ok = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args}) end test "returns error when elevation API fails" do Req.Test.stub(ElevationClient, fn conn -> Plug.Conn.send_resp(conn, 500, "error") end) contact = create_contact() job = TerrainProfileWorker.new(%{"contact_id" => contact.id}) assert {:error, _} = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args}) refute Terrain.has_terrain_profile?(contact.id) end test "uses correct frequency from band" do stub_elevation_api() contact = create_contact(%{band: Decimal.new("10368")}) job = TerrainProfileWorker.new(%{"contact_id" => contact.id}) assert :ok = TerrainProfileWorker.perform(%Oban.Job{args: job.changes.args}) profile = Terrain.get_terrain_profile(contact.id) assert profile.verdict end end end