defmodule MicrowavepropWeb.Api.V1.MeControllerTest do use MicrowavepropWeb.ConnCase, async: true alias Microwaveprop.Accounts alias Microwaveprop.AccountsFixtures alias MicrowavepropWeb.Api.RateLimiter setup %{conn: conn} do RateLimiter.reset() user = AccountsFixtures.user_fixture() {:ok, {plaintext, _record}} = Accounts.create_api_token(user, %{name: "test"}) authed = put_req_header(conn, "authorization", "Bearer " <> plaintext) %{user: user, plaintext: plaintext, authed: authed} end describe "GET /api/v1/me" do test "requires auth", %{conn: conn} do conn = get(conn, ~p"/api/v1/me") assert json_response(conn, 401) end test "returns the authenticated user's profile", %{authed: conn, user: user} do conn = get(conn, ~p"/api/v1/me") body = json_response(conn, 200) assert body["data"]["email"] == user.email assert body["data"]["callsign"] == user.callsign assert body["data"]["is_admin"] in [true, false] end end describe "PATCH /api/v1/me" do test "updates the home QTH from a Maidenhead grid", %{authed: conn} do conn = patch(conn, ~p"/api/v1/me", %{"home_grid" => "EM12kx"}) body = json_response(conn, 200) assert body["data"]["home_grid"] == "EM12kx" assert is_float(body["data"]["home_lat"]) end test "returns 422 on bad QTH", %{authed: conn} do conn = patch(conn, ~p"/api/v1/me", %{"home_grid" => "ZZ99zz"}) assert json_response(conn, 422) end end describe "GET /api/v1/me/contacts" do test "returns contacts owned by the user", %{authed: conn, user: user} do {:ok, contact} = Microwaveprop.Radio.create_contact( %{ "station1" => "W5XD", "station2" => "K5XD", "qso_timestamp" => "2026-01-01T00:00:00Z", "band" => "10000", "grid1" => "EM12", "grid2" => "EM13", "mode" => "CW", "submitter_email" => "fixture@example.com" }, user.id ) conn = get(conn, ~p"/api/v1/me/contacts") body = json_response(conn, 200) assert [%{"id" => id, "mine?" => true}] = body["data"] assert id == contact.id end end describe "GET /api/v1/me/beacons" do test "returns beacons submitted by the user", %{authed: conn, user: user} do {:ok, _b} = Microwaveprop.Beacons.create_beacon(user, %{ frequency_mhz: 10_368.1, callsign: "W5HN", lat: 32.897, lon: -97.038, power_mw: 1000.0, height_ft: 100, keying: "on_off" }) conn = get(conn, ~p"/api/v1/me/beacons") assert %{"data" => [_one]} = json_response(conn, 200) end end describe "API token CRUD" do test "lists, then revokes, an API token", %{authed: conn} do list = conn |> get(~p"/api/v1/me/api-tokens") |> json_response(200) assert [%{"id" => id} | _] = list["data"] revoke = conn |> delete(~p"/api/v1/me/api-tokens/#{id}") |> json_response(200) assert revoke["data"]["revoked_at"] end test "404 when revoking unknown id", %{authed: conn} do conn = delete( conn, ~p"/api/v1/me/api-tokens/00000000-0000-0000-0000-000000000000" ) assert json_response(conn, 404) end end describe "beacon monitor CRUD" do test "creates, lists, and deletes a beacon monitor", %{authed: conn} do created = conn |> post(~p"/api/v1/me/beacon-monitors", %{"name" => "Tower"}) |> json_response(201) id = created["data"]["id"] list = conn |> get(~p"/api/v1/me/beacon-monitors") |> json_response(200) assert Enum.any?(list["data"], &(&1["id"] == id)) conn = delete(conn, ~p"/api/v1/me/beacon-monitors/#{id}") assert response(conn, 204) end test "422 when creating with empty name", %{authed: conn} do conn = post(conn, ~p"/api/v1/me/beacon-monitors", %{"name" => ""}) assert json_response(conn, 422) end test "404 when deleting unknown monitor", %{authed: conn} do conn = delete( conn, ~p"/api/v1/me/beacon-monitors/00000000-0000-0000-0000-000000000000" ) assert json_response(conn, 404) end end end