271 lines
9.4 KiB
Elixir
271 lines
9.4 KiB
Elixir
defmodule MicrowavepropWeb.RoverLocationsLive.ShowTest do
|
|
use MicrowavepropWeb.ConnCase, async: true
|
|
|
|
import Phoenix.LiveViewTest
|
|
|
|
alias Microwaveprop.Radio.Maidenhead
|
|
alias Microwaveprop.Repo
|
|
alias Microwaveprop.Rover
|
|
|
|
describe "show" do
|
|
test "renders the location and a map container", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
|
|
{:ok, loc} =
|
|
Rover.create_location(user, %{
|
|
lat: 32.5,
|
|
lon: -97.5,
|
|
status: :good,
|
|
notes: "great spot"
|
|
})
|
|
|
|
{:ok, lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
|
|
assert html =~ "Rover Location"
|
|
assert html =~ "great spot"
|
|
assert html =~ "EM12gm"
|
|
assert has_element?(lv, "#location-map-#{loc.id}[phx-hook=LocationMap]")
|
|
end
|
|
|
|
test "redirects when the location does not exist", %{conn: conn} do
|
|
missing_id = Ecto.UUID.generate()
|
|
|
|
assert {:error, {:live_redirect, %{to: "/rover-locations"}}} =
|
|
live(conn, ~p"/rover-locations/#{missing_id}")
|
|
end
|
|
|
|
test "redirects when the id is not a valid UUID", %{conn: conn} do
|
|
assert {:error, {:live_redirect, %{to: "/rover-locations"}}} =
|
|
live(conn, ~p"/rover-locations/not-a-uuid")
|
|
end
|
|
|
|
test "owner sees a Delete button; visitors do not", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
|
|
# Anonymous: no Delete
|
|
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
refute html =~ "Delete"
|
|
|
|
# Owner: Delete present
|
|
conn = log_in_user(conn, user)
|
|
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
assert html =~ "Delete"
|
|
end
|
|
|
|
test "admin sees Delete on someone else's location", %{conn: conn} do
|
|
owner = Microwaveprop.AccountsFixtures.user_fixture()
|
|
admin = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
|
{:ok, loc} = Rover.create_location(owner, %{lat: 32.5, lon: -97.5, status: :good})
|
|
|
|
conn = log_in_user(conn, admin)
|
|
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
assert html =~ "Delete"
|
|
end
|
|
|
|
test "owner can enter edit mode and the marker is told to become draggable",
|
|
%{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
|
|
html = lv |> element("button", "Edit") |> render_click()
|
|
|
|
assert html =~ "Editing — drag the marker"
|
|
# Save + Cancel show up; Edit button hides.
|
|
assert has_element?(lv, "button[phx-click='save_edit']")
|
|
assert has_element?(lv, "button[phx-click='cancel_edit']")
|
|
refute has_element?(lv, "button[phx-click='toggle_edit']")
|
|
end
|
|
|
|
test "drag updates the working coords + grid (without persisting)", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
_ = lv |> element("button", "Edit") |> render_click()
|
|
|
|
# Simulate the JS hook firing the dragend event.
|
|
html = render_hook(lv, "location_dragged", %{"lat" => 33.25, "lon" => -97.75})
|
|
|
|
assert html =~ "33.25"
|
|
assert html =~ "-97.75"
|
|
# Grid recomputed for the new coords.
|
|
assert html =~ Maidenhead.from_latlon(33.25, -97.75, 10)
|
|
|
|
# DB still has the original coords until Save is clicked.
|
|
assert %{lat: 32.5, lon: -97.5} = Repo.reload(loc)
|
|
end
|
|
|
|
test "save persists the dragged coords to the DB", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
_ = lv |> element("button", "Edit") |> render_click()
|
|
_ = render_hook(lv, "location_dragged", %{"lat" => 33.25, "lon" => -97.75})
|
|
|
|
html = lv |> element("button[phx-click='save_edit']") |> render_click()
|
|
assert html =~ "Location updated"
|
|
|
|
reloaded = Repo.reload(loc)
|
|
assert_in_delta reloaded.lat, 33.25, 1.0e-6
|
|
assert_in_delta reloaded.lon, -97.75, 1.0e-6
|
|
end
|
|
|
|
test "cancel reverts the working coords without writing to the DB",
|
|
%{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
_ = lv |> element("button", "Edit") |> render_click()
|
|
_ = render_hook(lv, "location_dragged", %{"lat" => 99.0, "lon" => 99.0})
|
|
|
|
html = lv |> element("button[phx-click='cancel_edit']") |> render_click()
|
|
|
|
# Working coords reset to the stored values.
|
|
assert html =~ "32.5"
|
|
refute html =~ "99.0, 99.0"
|
|
|
|
reloaded = Repo.reload(loc)
|
|
assert reloaded.lat == 32.5
|
|
assert reloaded.lon == -97.5
|
|
end
|
|
|
|
test "save_edit fails closed when the user is signed out mid-session", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
|
|
# Anonymous conn — driving the event directly through render_hook
|
|
# exercises the unauthenticated branch of save_edit.
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
|
|
html = render_hook(lv, "save_edit", %{})
|
|
assert html =~ "Sign in required"
|
|
assert Repo.reload(loc).lat == 32.5
|
|
end
|
|
|
|
test "edit mode exposes status + notes inputs populated with current values",
|
|
%{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
|
|
{:ok, loc} =
|
|
Rover.create_location(user, %{
|
|
lat: 32.5,
|
|
lon: -97.5,
|
|
status: :good,
|
|
notes: "first pass"
|
|
})
|
|
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
# Inputs are not visible until edit mode is entered.
|
|
refute has_element?(lv, "select[name='location[status]']")
|
|
refute has_element?(lv, "textarea[name='location[notes]']")
|
|
assert html =~ "first pass"
|
|
|
|
_ = lv |> element("button", "Edit") |> render_click()
|
|
|
|
assert has_element?(lv, "select[name='location[status]']")
|
|
|
|
assert has_element?(
|
|
lv,
|
|
"textarea[name='location[notes]']",
|
|
"first pass"
|
|
)
|
|
end
|
|
|
|
test "save persists status + notes edits", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
|
|
{:ok, loc} =
|
|
Rover.create_location(user, %{
|
|
lat: 32.5,
|
|
lon: -97.5,
|
|
status: :good,
|
|
notes: "old"
|
|
})
|
|
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
_ = lv |> element("button", "Edit") |> render_click()
|
|
|
|
_ =
|
|
lv
|
|
|> form("#location-edit-form",
|
|
location: %{status: "bad", notes: "private property"}
|
|
)
|
|
|> render_change()
|
|
|
|
html = lv |> element("button[phx-click='save_edit']") |> render_click()
|
|
assert html =~ "Location updated"
|
|
|
|
reloaded = Repo.reload(loc)
|
|
assert reloaded.status == :bad
|
|
assert reloaded.notes == "private property"
|
|
end
|
|
|
|
test "cancel reverts pending status + notes changes", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
|
|
{:ok, loc} =
|
|
Rover.create_location(user, %{
|
|
lat: 32.5,
|
|
lon: -97.5,
|
|
status: :good,
|
|
notes: "keeper"
|
|
})
|
|
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
_ = lv |> element("button", "Edit") |> render_click()
|
|
|
|
_ =
|
|
lv
|
|
|> form("#location-edit-form",
|
|
location: %{status: "bad", notes: "scratch this"}
|
|
)
|
|
|> render_change()
|
|
|
|
_ = lv |> element("button[phx-click='cancel_edit']") |> render_click()
|
|
|
|
reloaded = Repo.reload(loc)
|
|
assert reloaded.status == :good
|
|
assert reloaded.notes == "keeper"
|
|
end
|
|
|
|
test "non-owner does not see the Edit button", %{conn: conn} do
|
|
owner = Microwaveprop.AccountsFixtures.user_fixture()
|
|
visitor = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(owner, %{lat: 32.5, lon: -97.5, status: :good})
|
|
conn = log_in_user(conn, visitor)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
refute has_element?(lv, "button[phx-click='toggle_edit']")
|
|
end
|
|
|
|
test "owner can delete from the show page and is redirected", %{conn: conn} do
|
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
|
conn = log_in_user(conn, user)
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
|
|
|
assert {:ok, _index_lv, _html} =
|
|
lv
|
|
|> element("button", "Delete")
|
|
|> render_click()
|
|
|> follow_redirect(conn, ~p"/rover-locations")
|
|
end
|
|
end
|
|
end
|