defmodule MicrowavepropWeb.BeaconLiveTest do use MicrowavepropWeb.ConnCase import Microwaveprop.AccountsFixtures import Microwaveprop.BeaconsFixtures import Phoenix.LiveViewTest alias Microwaveprop.Accounts defp promote_to_admin(user) do {:ok, user} = Accounts.admin_update_user(user, %{is_admin: true}) user end defp admin_user_fixture do promote_to_admin(user_fixture()) end defp approved_beacon_fixture(user, attrs \\ %{}) do beacon = beacon_fixture(user, attrs) {:ok, beacon} = Microwaveprop.Beacons.approve_beacon(beacon) beacon end describe "Index (public)" do test "lists approved beacons without logging in", %{conn: conn} do beacon = approved_beacon_fixture(user_fixture()) {:ok, _view, html} = live(conn, ~p"/beacons") assert html =~ "Beacons" assert html =~ beacon.callsign end test "hides unapproved beacons from the public list", %{conn: conn} do _pending = beacon_fixture(user_fixture(), callsign: "W5PEN") {:ok, _view, html} = live(conn, ~p"/beacons") refute html =~ "W5PEN" end test "anonymous sees the Submit Beacon button", %{conn: conn} do {:ok, _view, html} = live(conn, ~p"/beacons") assert html =~ "Submit Beacon" end test "authenticated user sees the Submit Beacon button", %{conn: conn} do user = user_fixture() conn = log_in_user(conn, user) {:ok, _view, html} = live(conn, ~p"/beacons") assert html =~ "Submit Beacon" end test "admin sees pending beacons section", %{conn: conn} do pending = beacon_fixture(user_fixture(), callsign: "W5PEN") conn = log_in_user(conn, admin_user_fixture()) {:ok, _view, html} = live(conn, ~p"/beacons") assert html =~ "Pending approval" assert html =~ pending.callsign end test "non-admin does not see pending beacons section", %{conn: conn} do _pending = beacon_fixture(user_fixture(), callsign: "W5PEN") conn = log_in_user(conn, user_fixture()) {:ok, _view, html} = live(conn, ~p"/beacons") refute html =~ "Pending approval" refute html =~ "W5PEN" end test "admin can approve a pending beacon", %{conn: conn} do pending = beacon_fixture(user_fixture(), callsign: "W5PEN") conn = log_in_user(conn, admin_user_fixture()) {:ok, view, _html} = live(conn, ~p"/beacons") html = view |> element("a[phx-click][data-confirm='Approve this beacon?']") |> render_click() assert html =~ "Approved #{pending.callsign}" assert Microwaveprop.Beacons.get_beacon!(pending.id).approved == true end end describe "Show (public)" do test "renders beacon details without logging in", %{conn: conn} do beacon = approved_beacon_fixture(user_fixture()) {:ok, _view, html} = live(conn, ~p"/beacons/#{beacon}") assert html =~ beacon.callsign assert html =~ "#{beacon.frequency_mhz}" end test "shows pending badge on unapproved beacons", %{conn: conn} do beacon = beacon_fixture(user_fixture()) {:ok, _view, html} = live(conn, ~p"/beacons/#{beacon}") assert html =~ "Pending approval" end end describe "Form" do test "authenticated non-admin can access /beacons/new", %{conn: conn} do user = user_fixture() conn = log_in_user(conn, user) {:ok, _view, html} = live(conn, ~p"/beacons/new") assert html =~ "New beacon" end test "anonymous user can access /beacons/new", %{conn: conn} do {:ok, _view, html} = live(conn, ~p"/beacons/new") assert html =~ "New beacon" end test "anonymous submission creates an unapproved beacon with no user_id", %{conn: conn} do {:ok, form_live, _html} = live(conn, ~p"/beacons/new") attrs = valid_beacon_attrs(callsign: "W5ANON") assert {:ok, _view, html} = form_live |> form("#beacon-form", beacon: attrs) |> render_submit() |> follow_redirect(conn, ~p"/beacons") assert html =~ "awaiting admin approval" beacon = Enum.find(Microwaveprop.Beacons.list_pending_beacons(), fn b -> b.callsign == "W5ANON" end) assert beacon assert beacon.user_id == nil assert beacon.approved == false end test "non-admin submission creates an unapproved beacon", %{conn: conn} do user = user_fixture() conn = log_in_user(conn, user) {:ok, form_live, _html} = live(conn, ~p"/beacons/new") attrs = valid_beacon_attrs() assert {:ok, _view, _html} = form_live |> form("#beacon-form", beacon: attrs) |> render_submit() |> follow_redirect(conn, ~p"/beacons") beacon = List.first(Microwaveprop.Beacons.list_pending_beacons()) assert beacon.callsign == attrs.callsign assert beacon.approved == false end test "admin edits a beacon", %{conn: conn} do admin = admin_user_fixture() beacon = beacon_fixture(admin) conn = log_in_user(conn, admin) {:ok, form_live, _} = live(conn, ~p"/beacons/#{beacon}/edit") assert {:ok, _view, html} = form_live |> form("#beacon-form", beacon: %{power_mw: 25_000.0}) |> render_submit() |> follow_redirect(conn, ~p"/beacons") assert html =~ "Beacon updated" end test "non-admin cannot access /beacons/:id/edit", %{conn: conn} do beacon = beacon_fixture(user_fixture()) conn = log_in_user(conn, user_fixture()) assert {:error, {:redirect, %{to: "/"}}} = live(conn, ~p"/beacons/#{beacon}/edit") end end end