refactor(rover-locations): rename status atoms ideal→good, off_limits→bad
Renames the rover-location status enum and every label that referenced it. Existing rows are migrated in place. Also touches the consumers: - Rover.Location enum + default - RoverLocationsLive index, status filter, form, show, badges - Rover.Compute and rover_live (only_ideal_locations → only_good_locations) - RoverPlanning context candidate filter (status == :good) - RoverPlanning.Show / Form copy - All rover-related tests
This commit is contained in:
parent
d1a5442afb
commit
209244f364
15 changed files with 95 additions and 80 deletions
|
|
@ -131,10 +131,10 @@ defmodule Microwaveprop.Rover.Compute do
|
||||||
step.("Loading propagation grid")
|
step.("Loading propagation grid")
|
||||||
raw_cells = time_step("scores_at", fn -> scores_at.(band_mhz, valid_time, bbox) end)
|
raw_cells = time_step("scores_at", fn -> scores_at.(band_mhz, valid_time, bbox) end)
|
||||||
|
|
||||||
ideal_locations = Map.get(args, :ideal_locations, nil)
|
good_locations = Map.get(args, :good_locations, nil)
|
||||||
|
|
||||||
candidate_cells =
|
candidate_cells =
|
||||||
case ideal_locations do
|
case good_locations do
|
||||||
nil -> raw_cells
|
nil -> raw_cells
|
||||||
[] -> raw_cells
|
[] -> raw_cells
|
||||||
locations -> snap_cells_to_locations(locations, raw_cells)
|
locations -> snap_cells_to_locations(locations, raw_cells)
|
||||||
|
|
@ -334,7 +334,7 @@ defmodule Microwaveprop.Rover.Compute do
|
||||||
|> Canopy.lookup_many()
|
|> Canopy.lookup_many()
|
||||||
end
|
end
|
||||||
|
|
||||||
# When the user constrains candidates to known ideal locations, build
|
# When the user constrains candidates to known good locations, build
|
||||||
# synthetic cells at each location's exact lat/lon, inheriting the
|
# synthetic cells at each location's exact lat/lon, inheriting the
|
||||||
# propagation score from the nearest grid cell (so atmospheric forecast
|
# propagation score from the nearest grid cell (so atmospheric forecast
|
||||||
# still factors in even though the spot itself isn't a grid centroid).
|
# still factors in even though the spot itself isn't a grid centroid).
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,21 @@ defmodule Microwaveprop.Rover.Location do
|
||||||
user. Everyone can view the list; only authenticated users can create
|
user. Everyone can view the list; only authenticated users can create
|
||||||
entries (creator tracked via `user_id`).
|
entries (creator tracked via `user_id`).
|
||||||
|
|
||||||
`status` is `:ideal` (recommended spot) or `:off_limits` (avoid —
|
`status` is `:good` (recommended spot) or `:bad` (avoid —
|
||||||
trespass, no-go, etc.).
|
trespass, no-go, etc.).
|
||||||
"""
|
"""
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
@statuses [:ideal, :off_limits]
|
@statuses [:good, :bad]
|
||||||
|
|
||||||
@primary_key {:id, :binary_id, autogenerate: true}
|
@primary_key {:id, :binary_id, autogenerate: true}
|
||||||
@foreign_key_type :binary_id
|
@foreign_key_type :binary_id
|
||||||
schema "rover_locations" do
|
schema "rover_locations" do
|
||||||
field :lat, :float
|
field :lat, :float
|
||||||
field :lon, :float
|
field :lon, :float
|
||||||
field :status, Ecto.Enum, values: @statuses, default: :ideal
|
field :status, Ecto.Enum, values: @statuses, default: :good
|
||||||
field :notes, :string
|
field :notes, :string
|
||||||
|
|
||||||
belongs_to :user, Microwaveprop.Accounts.User
|
belongs_to :user, Microwaveprop.Accounts.User
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ defmodule Microwaveprop.RoverPlanning do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp candidate_rover_locations(%Mission{only_known_good: true}) do
|
defp candidate_rover_locations(%Mission{only_known_good: true}) do
|
||||||
Repo.all(from(l in Location, where: l.status == :ideal))
|
Repo.all(from(l in Location, where: l.status == :good))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp candidate_rover_locations(%Mission{only_known_good: false}) do
|
defp candidate_rover_locations(%Mission{only_known_good: false}) do
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ defmodule Microwaveprop.RoverPlanning.Mission do
|
||||||
paths from each rover-location to each station (`paths`).
|
paths from each rover-location to each station (`paths`).
|
||||||
|
|
||||||
`only_known_good` toggles whether the rover endpoint set is the
|
`only_known_good` toggles whether the rover endpoint set is the
|
||||||
`:ideal` rover-locations (default) or every rover-location.
|
`:good` rover-locations (default) or every rover-location.
|
||||||
"""
|
"""
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ defmodule MicrowavepropWeb.RoverLive do
|
||||||
home_form_error: nil,
|
home_form_error: nil,
|
||||||
scoring_loading: false,
|
scoring_loading: false,
|
||||||
scoring_step: nil,
|
scoring_step: nil,
|
||||||
only_ideal_locations: false,
|
only_good_locations: false,
|
||||||
url_loaded?: false
|
url_loaded?: false
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
|
|
@ -196,8 +196,8 @@ defmodule MicrowavepropWeb.RoverLive do
|
||||||
|> push_event("update_drive_radius", %{km: radius_km})}
|
|> push_event("update_drive_radius", %{km: radius_km})}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("toggle_only_ideal", _params, socket) do
|
def handle_event("toggle_only_good", _params, socket) do
|
||||||
{:noreply, assign(socket, only_ideal_locations: not socket.assigns.only_ideal_locations)}
|
{:noreply, assign(socket, only_good_locations: not socket.assigns.only_good_locations)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("toggle_station", %{"id" => id}, socket) do
|
def handle_event("toggle_station", %{"id" => id}, socket) do
|
||||||
|
|
@ -732,13 +732,13 @@ defmodule MicrowavepropWeb.RoverLive do
|
||||||
min_elev_gain: 0
|
min_elev_gain: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if socket.assigns.only_ideal_locations do
|
if socket.assigns.only_good_locations do
|
||||||
ideals =
|
goods =
|
||||||
Rover.list_locations()
|
Rover.list_locations()
|
||||||
|> Enum.filter(&(&1.status == :ideal))
|
|> Enum.filter(&(&1.status == :good))
|
||||||
|> Enum.map(fn l -> %{lat: l.lat, lon: l.lon} end)
|
|> Enum.map(fn l -> %{lat: l.lat, lon: l.lon} end)
|
||||||
|
|
||||||
Map.put(base, :ideal_locations, ideals)
|
Map.put(base, :good_locations, goods)
|
||||||
else
|
else
|
||||||
base
|
base
|
||||||
end
|
end
|
||||||
|
|
@ -984,7 +984,7 @@ defmodule MicrowavepropWeb.RoverLive do
|
||||||
class="absolute bottom-0 inset-x-0 bg-base-100/90 backdrop-blur border-t border-base-300 z-10"
|
class="absolute bottom-0 inset-x-0 bg-base-100/90 backdrop-blur border-t border-base-300 z-10"
|
||||||
>
|
>
|
||||||
<div class="px-3 pt-1 text-[10px] uppercase tracking-wider text-base-content/60 font-semibold">
|
<div class="px-3 pt-1 text-[10px] uppercase tracking-wider text-base-content/60 font-semibold">
|
||||||
Ideal locations
|
Good locations
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
id="rover-candidates-strip"
|
id="rover-candidates-strip"
|
||||||
|
|
@ -1180,14 +1180,14 @@ defmodule MicrowavepropWeb.RoverLive do
|
||||||
<label class="flex items-start gap-2 cursor-pointer">
|
<label class="flex items-start gap-2 cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={@only_ideal_locations}
|
checked={@only_good_locations}
|
||||||
phx-click="toggle_only_ideal"
|
phx-click="toggle_only_good"
|
||||||
class="checkbox checkbox-sm checkbox-primary mt-0.5"
|
class="checkbox checkbox-sm checkbox-primary mt-0.5"
|
||||||
/>
|
/>
|
||||||
<span class="text-xs leading-tight">
|
<span class="text-xs leading-tight">
|
||||||
Only use known ideal locations
|
Only use known good locations
|
||||||
<span class="block text-[10px] opacity-60 mt-0.5">
|
<span class="block text-[10px] opacity-60 mt-0.5">
|
||||||
Restricts suggestions to spots tagged "ideal" in <a
|
Restricts suggestions to spots tagged "good" in <a
|
||||||
href={~p"/rover-locations"}
|
href={~p"/rover-locations"}
|
||||||
class="link"
|
class="link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule MicrowavepropWeb.RoverLocationsLive do
|
defmodule MicrowavepropWeb.RoverLocationsLive do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Globally-shared list of rover-friendly (or off-limits) parking
|
Globally-shared list of rover-friendly (or bad) parking
|
||||||
locations. Everyone sees the table; only logged-in users can add or
|
locations. Everyone sees the table; only logged-in users can add or
|
||||||
edit entries (and only the creator can edit/delete their own).
|
edit entries (and only the creator can edit/delete their own).
|
||||||
"""
|
"""
|
||||||
|
|
@ -15,7 +15,7 @@ defmodule MicrowavepropWeb.RoverLocationsLive do
|
||||||
alias Microwaveprop.Rover
|
alias Microwaveprop.Rover
|
||||||
alias Microwaveprop.Rover.Location
|
alias Microwaveprop.Rover.Location
|
||||||
|
|
||||||
@valid_status_filters ~w(ideal off_limits)
|
@valid_status_filters ~w(good bad)
|
||||||
|
|
||||||
def table_options do
|
def table_options do
|
||||||
%{sorting: %{default_sort: [inserted_at: :desc]}}
|
%{sorting: %{default_sort: [inserted_at: :desc]}}
|
||||||
|
|
@ -42,8 +42,8 @@ defmodule MicrowavepropWeb.RoverLocationsLive do
|
||||||
base = from(l in Location, as: :resource)
|
base = from(l in Location, as: :resource)
|
||||||
|
|
||||||
case status_filter do
|
case status_filter do
|
||||||
"ideal" -> from(l in base, where: l.status == :ideal)
|
"good" -> from(l in base, where: l.status == :good)
|
||||||
"off_limits" -> from(l in base, where: l.status == :off_limits)
|
"bad" -> from(l in base, where: l.status == :bad)
|
||||||
_ -> base
|
_ -> base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -308,14 +308,14 @@ defmodule MicrowavepropWeb.RoverLocationsLive do
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
defp status_cell(:ideal) do
|
defp status_cell(:good) do
|
||||||
assigns = %{}
|
assigns = %{}
|
||||||
~H|<span class="badge badge-success">Ideal</span>|
|
~H|<span class="badge badge-success">Good</span>|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp status_cell(:off_limits) do
|
defp status_cell(:bad) do
|
||||||
assigns = %{}
|
assigns = %{}
|
||||||
~H|<span class="badge badge-error">Off Limits</span>|
|
~H|<span class="badge badge-error">Bad</span>|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp status_cell(_), do: ""
|
defp status_cell(_), do: ""
|
||||||
|
|
@ -389,7 +389,7 @@ defmodule MicrowavepropWeb.RoverLocationsLive do
|
||||||
field={@form[:status]}
|
field={@form[:status]}
|
||||||
type="select"
|
type="select"
|
||||||
label="Status"
|
label="Status"
|
||||||
options={[{"Ideal", :ideal}, {"Off Limits", :off_limits}]}
|
options={[{"Good", :good}, {"Bad", :bad}]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||||
|
|
@ -434,8 +434,8 @@ defmodule MicrowavepropWeb.RoverLocationsLive do
|
||||||
class="select select-sm select-bordered"
|
class="select select-sm select-bordered"
|
||||||
>
|
>
|
||||||
<option value="all" selected={is_nil(@status_filter)}>All</option>
|
<option value="all" selected={is_nil(@status_filter)}>All</option>
|
||||||
<option value="ideal" selected={@status_filter == "ideal"}>Ideal</option>
|
<option value="good" selected={@status_filter == "good"}>Good</option>
|
||||||
<option value="off_limits" selected={@status_filter == "off_limits"}>Off Limits</option>
|
<option value="bad" selected={@status_filter == "bad"}>Bad</option>
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,12 +69,12 @@ defmodule MicrowavepropWeb.RoverLocationsLive.Show do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp status_label(:ideal), do: "Ideal"
|
defp status_label(:good), do: "Good"
|
||||||
defp status_label(:off_limits), do: "Off Limits"
|
defp status_label(:bad), do: "Bad"
|
||||||
defp status_label(_), do: ""
|
defp status_label(_), do: ""
|
||||||
|
|
||||||
defp status_class(:ideal), do: "badge badge-success"
|
defp status_class(:good), do: "badge badge-success"
|
||||||
defp status_class(:off_limits), do: "badge badge-error"
|
defp status_class(:bad), do: "badge badge-error"
|
||||||
defp status_class(_), do: "badge"
|
defp status_class(_), do: "badge"
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ defmodule MicrowavepropWeb.RoverPlanningLive.Form do
|
||||||
<span>
|
<span>
|
||||||
Only check against known good locations
|
Only check against known good locations
|
||||||
<span class="text-xs opacity-70 block">
|
<span class="text-xs opacity-70 block">
|
||||||
When checked, paths are computed only against rover-locations marked Ideal.
|
When checked, paths are computed only against rover-locations marked Good.
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ defmodule MicrowavepropWeb.RoverPlanningLive.Show do
|
||||||
|
|
||||||
<p class="text-xs text-base-content/60 mt-3">
|
<p class="text-xs text-base-content/60 mt-3">
|
||||||
Scope: {if @mission.only_known_good,
|
Scope: {if @mission.only_known_good,
|
||||||
do: "Known good locations only (status = ideal)",
|
do: "Known good locations only (status = good)",
|
||||||
else: "All rover locations"} · Owner: {(@mission.user && @mission.user.callsign) || "—"}
|
else: "All rover locations"} · Owner: {(@mission.user && @mission.user.callsign) || "—"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule Microwaveprop.Repo.Migrations.RenameRoverLocationStatuses do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("UPDATE rover_locations SET status = 'good' WHERE status = 'ideal'")
|
||||||
|
execute("UPDATE rover_locations SET status = 'bad' WHERE status = 'off_limits'")
|
||||||
|
execute("ALTER TABLE rover_locations ALTER COLUMN status SET DEFAULT 'good'")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
execute("ALTER TABLE rover_locations ALTER COLUMN status SET DEFAULT 'ideal'")
|
||||||
|
execute("UPDATE rover_locations SET status = 'off_limits' WHERE status = 'bad'")
|
||||||
|
execute("UPDATE rover_locations SET status = 'ideal' WHERE status = 'good'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -13,8 +13,8 @@ defmodule Microwaveprop.RoverLocationsTest do
|
||||||
a = user_fixture()
|
a = user_fixture()
|
||||||
b = user_fixture()
|
b = user_fixture()
|
||||||
|
|
||||||
{:ok, _l1} = Rover.create_location(a, %{lat: 32.5, lon: -97.5, status: :ideal})
|
{:ok, _l1} = Rover.create_location(a, %{lat: 32.5, lon: -97.5, status: :good})
|
||||||
{:ok, _l2} = Rover.create_location(b, %{lat: 33.0, lon: -96.5, status: :off_limits})
|
{:ok, _l2} = Rover.create_location(b, %{lat: 33.0, lon: -96.5, status: :bad})
|
||||||
|
|
||||||
result = Rover.list_locations()
|
result = Rover.list_locations()
|
||||||
assert length(result) == 2
|
assert length(result) == 2
|
||||||
|
|
@ -25,33 +25,33 @@ defmodule Microwaveprop.RoverLocationsTest do
|
||||||
describe "create_location/2" do
|
describe "create_location/2" do
|
||||||
test "stores the creator's user_id" do
|
test "stores the creator's user_id" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :ideal})
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
||||||
assert loc.user_id == user.id
|
assert loc.user_id == user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
test "supports notes and the off_limits status" do
|
test "supports notes and the bad status" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
|
|
||||||
{:ok, loc} =
|
{:ok, loc} =
|
||||||
Rover.create_location(user, %{
|
Rover.create_location(user, %{
|
||||||
lat: 32.0,
|
lat: 32.0,
|
||||||
lon: -97.0,
|
lon: -97.0,
|
||||||
status: :off_limits,
|
status: :bad,
|
||||||
notes: "private property"
|
notes: "private property"
|
||||||
})
|
})
|
||||||
|
|
||||||
assert loc.status == :off_limits
|
assert loc.status == :bad
|
||||||
assert loc.notes == "private property"
|
assert loc.notes == "private property"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "rejects out-of-range coordinates" do
|
test "rejects out-of-range coordinates" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
assert {:error, %Ecto.Changeset{}} = Rover.create_location(user, %{lat: 100.0, lon: 0.0, status: :ideal})
|
assert {:error, %Ecto.Changeset{}} = Rover.create_location(user, %{lat: 100.0, lon: 0.0, status: :good})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "requires lat and lon" do
|
test "requires lat and lon" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
assert {:error, cs} = Rover.create_location(user, %{status: :ideal})
|
assert {:error, cs} = Rover.create_location(user, %{status: :good})
|
||||||
assert "can't be blank" in errors_on(cs).lat
|
assert "can't be blank" in errors_on(cs).lat
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -59,7 +59,7 @@ defmodule Microwaveprop.RoverLocationsTest do
|
||||||
describe "update_location/3 and delete_location/2" do
|
describe "update_location/3 and delete_location/2" do
|
||||||
test "creator can update their location" do
|
test "creator can update their location" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
{:ok, loc} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal})
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
|
||||||
|
|
||||||
assert {:ok, updated} = Rover.update_location(user, loc.id, %{notes: "updated"})
|
assert {:ok, updated} = Rover.update_location(user, loc.id, %{notes: "updated"})
|
||||||
assert updated.notes == "updated"
|
assert updated.notes == "updated"
|
||||||
|
|
@ -68,7 +68,7 @@ defmodule Microwaveprop.RoverLocationsTest do
|
||||||
test "non-creator cannot update or delete" do
|
test "non-creator cannot update or delete" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
other = user_fixture()
|
other = user_fixture()
|
||||||
{:ok, loc} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal})
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
|
||||||
|
|
||||||
assert {:error, :not_found} = Rover.update_location(other, loc.id, %{notes: "x"})
|
assert {:error, :not_found} = Rover.update_location(other, loc.id, %{notes: "x"})
|
||||||
assert {:error, :not_found} = Rover.delete_location(other, loc.id)
|
assert {:error, :not_found} = Rover.delete_location(other, loc.id)
|
||||||
|
|
@ -76,7 +76,7 @@ defmodule Microwaveprop.RoverLocationsTest do
|
||||||
|
|
||||||
test "creator can delete their location" do
|
test "creator can delete their location" do
|
||||||
user = user_fixture()
|
user = user_fixture()
|
||||||
{:ok, loc} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal})
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
|
||||||
|
|
||||||
assert {:ok, _} = Rover.delete_location(user, loc.id)
|
assert {:ok, _} = Rover.delete_location(user, loc.id)
|
||||||
refute Enum.any?(Rover.list_locations(), &(&1.id == loc.id))
|
refute Enum.any?(Rover.list_locations(), &(&1.id == loc.id))
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
{:ok, loc} =
|
{:ok, loc} =
|
||||||
Rover.create_location(
|
Rover.create_location(
|
||||||
user,
|
user,
|
||||||
Map.merge(%{lat: 32.5, lon: -97.5, status: :ideal}, attrs)
|
Map.merge(%{lat: 32.5, lon: -97.5, status: :good}, attrs)
|
||||||
)
|
)
|
||||||
|
|
||||||
loc
|
loc
|
||||||
|
|
@ -52,8 +52,8 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
describe "create_mission/2" do
|
describe "create_mission/2" do
|
||||||
test "inserts a mission with stations and enqueues a path per (rover × station) pair" do
|
test "inserts a mission with stations and enqueues a path per (rover × station) pair" do
|
||||||
user = AccountsFixtures.user_fixture()
|
user = AccountsFixtures.user_fixture()
|
||||||
_ideal_loc = create_rover_location(%{lat: 32.0, lon: -97.0, status: :ideal})
|
_ideal_loc = create_rover_location(%{lat: 32.0, lon: -97.0, status: :good})
|
||||||
_off_limits = create_rover_location(%{lat: 33.0, lon: -98.0, status: :off_limits})
|
_off_limits = create_rover_location(%{lat: 33.0, lon: -98.0, status: :bad})
|
||||||
|
|
||||||
assert {:ok, mission} = RoverPlanning.create_mission(user, valid_attrs())
|
assert {:ok, mission} = RoverPlanning.create_mission(user, valid_attrs())
|
||||||
assert mission.user_id == user.id
|
assert mission.user_id == user.id
|
||||||
|
|
@ -63,7 +63,7 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
assert is_float(station.lon)
|
assert is_float(station.lon)
|
||||||
|
|
||||||
paths = RoverPlanning.list_paths(mission)
|
paths = RoverPlanning.list_paths(mission)
|
||||||
# only_known_good=true → only the :ideal location pairs with the station.
|
# only_known_good=true → only the :good location pairs with the station.
|
||||||
# Oban runs inline in test so the worker has already completed.
|
# Oban runs inline in test so the worker has already completed.
|
||||||
assert length(paths) == 1
|
assert length(paths) == 1
|
||||||
assert hd(paths).status in [:complete, :failed]
|
assert hd(paths).status in [:complete, :failed]
|
||||||
|
|
@ -71,8 +71,8 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
|
|
||||||
test "with only_known_good=false, all rover-locations get a path entry" do
|
test "with only_known_good=false, all rover-locations get a path entry" do
|
||||||
user = AccountsFixtures.user_fixture()
|
user = AccountsFixtures.user_fixture()
|
||||||
_ideal = create_rover_location(%{lat: 32.0, lon: -97.0, status: :ideal})
|
_ideal = create_rover_location(%{lat: 32.0, lon: -97.0, status: :good})
|
||||||
_off = create_rover_location(%{lat: 33.0, lon: -98.0, status: :off_limits})
|
_off = create_rover_location(%{lat: 33.0, lon: -98.0, status: :bad})
|
||||||
|
|
||||||
attrs = valid_attrs(%{"only_known_good" => false})
|
attrs = valid_attrs(%{"only_known_good" => false})
|
||||||
assert {:ok, mission} = RoverPlanning.create_mission(user, attrs)
|
assert {:ok, mission} = RoverPlanning.create_mission(user, attrs)
|
||||||
|
|
@ -81,7 +81,7 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
|
|
||||||
test "missing stations returns a changeset error" do
|
test "missing stations returns a changeset error" do
|
||||||
user = AccountsFixtures.user_fixture()
|
user = AccountsFixtures.user_fixture()
|
||||||
attrs = valid_attrs() |> Map.delete("stations")
|
attrs = Map.delete(valid_attrs(), "stations")
|
||||||
|
|
||||||
assert {:error, %Ecto.Changeset{} = cs} = RoverPlanning.create_mission(user, attrs)
|
assert {:error, %Ecto.Changeset{} = cs} = RoverPlanning.create_mission(user, attrs)
|
||||||
refute cs.valid?
|
refute cs.valid?
|
||||||
|
|
@ -92,7 +92,7 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
describe "update_mission/3" do
|
describe "update_mission/3" do
|
||||||
test "owner can update a mission and paths get rebuilt" do
|
test "owner can update a mission and paths get rebuilt" do
|
||||||
user = AccountsFixtures.user_fixture()
|
user = AccountsFixtures.user_fixture()
|
||||||
_ = create_rover_location(%{lat: 32.0, lon: -97.0, status: :ideal})
|
_ = create_rover_location(%{lat: 32.0, lon: -97.0, status: :good})
|
||||||
{:ok, mission} = RoverPlanning.create_mission(user, valid_attrs())
|
{:ok, mission} = RoverPlanning.create_mission(user, valid_attrs())
|
||||||
|
|
||||||
[original] = RoverPlanning.list_paths(mission)
|
[original] = RoverPlanning.list_paths(mission)
|
||||||
|
|
@ -109,7 +109,7 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
test "non-owner update is denied" do
|
test "non-owner update is denied" do
|
||||||
owner = AccountsFixtures.user_fixture()
|
owner = AccountsFixtures.user_fixture()
|
||||||
other = AccountsFixtures.user_fixture()
|
other = AccountsFixtures.user_fixture()
|
||||||
_ = create_rover_location(%{lat: 32.0, lon: -97.0, status: :ideal})
|
_ = create_rover_location(%{lat: 32.0, lon: -97.0, status: :good})
|
||||||
{:ok, mission} = RoverPlanning.create_mission(owner, valid_attrs())
|
{:ok, mission} = RoverPlanning.create_mission(owner, valid_attrs())
|
||||||
|
|
||||||
assert {:error, :not_found} =
|
assert {:error, :not_found} =
|
||||||
|
|
@ -120,7 +120,7 @@ defmodule Microwaveprop.RoverPlanningTest do
|
||||||
owner = AccountsFixtures.user_fixture()
|
owner = AccountsFixtures.user_fixture()
|
||||||
admin = AccountsFixtures.user_fixture()
|
admin = AccountsFixtures.user_fixture()
|
||||||
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
||||||
_ = create_rover_location(%{lat: 32.0, lon: -97.0, status: :ideal})
|
_ = create_rover_location(%{lat: 32.0, lon: -97.0, status: :good})
|
||||||
{:ok, mission} = RoverPlanning.create_mission(owner, valid_attrs())
|
{:ok, mission} = RoverPlanning.create_mission(owner, valid_attrs())
|
||||||
|
|
||||||
assert {:ok, updated} =
|
assert {:ok, updated} =
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ defmodule MicrowavepropWeb.RoverLocationsLive.ShowTest do
|
||||||
Rover.create_location(user, %{
|
Rover.create_location(user, %{
|
||||||
lat: 32.5,
|
lat: 32.5,
|
||||||
lon: -97.5,
|
lon: -97.5,
|
||||||
status: :ideal,
|
status: :good,
|
||||||
notes: "great spot"
|
notes: "great spot"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ defmodule MicrowavepropWeb.RoverLocationsLive.ShowTest do
|
||||||
|
|
||||||
test "owner sees a Delete button; visitors do not", %{conn: conn} do
|
test "owner sees a Delete button; visitors do not", %{conn: conn} do
|
||||||
user = Microwaveprop.AccountsFixtures.user_fixture()
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :ideal})
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
||||||
|
|
||||||
# Anonymous: no Delete
|
# Anonymous: no Delete
|
||||||
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
||||||
|
|
@ -55,7 +55,7 @@ defmodule MicrowavepropWeb.RoverLocationsLive.ShowTest do
|
||||||
owner = Microwaveprop.AccountsFixtures.user_fixture()
|
owner = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
admin = Microwaveprop.AccountsFixtures.user_fixture()
|
admin = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
||||||
{:ok, loc} = Rover.create_location(owner, %{lat: 32.5, lon: -97.5, status: :ideal})
|
{:ok, loc} = Rover.create_location(owner, %{lat: 32.5, lon: -97.5, status: :good})
|
||||||
|
|
||||||
conn = log_in_user(conn, admin)
|
conn = log_in_user(conn, admin)
|
||||||
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
{:ok, _lv, html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
||||||
|
|
@ -64,7 +64,7 @@ defmodule MicrowavepropWeb.RoverLocationsLive.ShowTest do
|
||||||
|
|
||||||
test "owner can delete from the show page and is redirected", %{conn: conn} do
|
test "owner can delete from the show page and is redirected", %{conn: conn} do
|
||||||
user = Microwaveprop.AccountsFixtures.user_fixture()
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :ideal})
|
{:ok, loc} = Rover.create_location(user, %{lat: 32.5, lon: -97.5, status: :good})
|
||||||
conn = log_in_user(conn, user)
|
conn = log_in_user(conn, user)
|
||||||
|
|
||||||
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations/#{loc.id}")
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
Rover.create_location(user, %{
|
Rover.create_location(user, %{
|
||||||
lat: 32.5,
|
lat: 32.5,
|
||||||
lon: -97.5,
|
lon: -97.5,
|
||||||
status: :ideal,
|
status: :good,
|
||||||
notes: "great hill"
|
notes: "great hill"
|
||||||
})
|
})
|
||||||
|
|
||||||
{:ok, _lv, html} = live(conn, ~p"/rover-locations")
|
{:ok, _lv, html} = live(conn, ~p"/rover-locations")
|
||||||
assert html =~ "Ideal"
|
assert html =~ "Good"
|
||||||
assert html =~ "great hill"
|
assert html =~ "great hill"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -37,8 +37,8 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
|
|
||||||
test "status filter narrows the visible rows", %{conn: conn} do
|
test "status filter narrows the visible rows", %{conn: conn} do
|
||||||
user = Microwaveprop.AccountsFixtures.user_fixture()
|
user = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
{:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal, notes: "ideal-spot"})
|
{:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good, notes: "ideal-spot"})
|
||||||
{:ok, _} = Rover.create_location(user, %{lat: 33.0, lon: -98.0, status: :off_limits, notes: "no-go-spot"})
|
{:ok, _} = Rover.create_location(user, %{lat: 33.0, lon: -98.0, status: :bad, notes: "no-go-spot"})
|
||||||
|
|
||||||
{:ok, lv, html} = live(conn, ~p"/rover-locations")
|
{:ok, lv, html} = live(conn, ~p"/rover-locations")
|
||||||
assert html =~ "ideal-spot"
|
assert html =~ "ideal-spot"
|
||||||
|
|
@ -46,7 +46,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
|
|
||||||
html =
|
html =
|
||||||
lv
|
lv
|
||||||
|> form("form[phx-change=filter_status]", %{"value" => "ideal"})
|
|> form("form[phx-change=filter_status]", %{"value" => "good"})
|
||||||
|> render_change()
|
|> render_change()
|
||||||
|
|
||||||
assert html =~ "ideal-spot"
|
assert html =~ "ideal-spot"
|
||||||
|
|
@ -54,7 +54,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
|
|
||||||
html =
|
html =
|
||||||
lv
|
lv
|
||||||
|> form("form[phx-change=filter_status]", %{"value" => "off_limits"})
|
|> form("form[phx-change=filter_status]", %{"value" => "bad"})
|
||||||
|> render_change()
|
|> render_change()
|
||||||
|
|
||||||
refute html =~ "ideal-spot"
|
refute html =~ "ideal-spot"
|
||||||
|
|
@ -72,7 +72,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
|
|
||||||
lv
|
lv
|
||||||
|> form("#location-form",
|
|> form("#location-form",
|
||||||
location: %{lat: "32.5", lon: "-97.5", status: "ideal", notes: "test note"}
|
location: %{lat: "32.5", lon: "-97.5", status: "good", notes: "test note"}
|
||||||
)
|
)
|
||||||
|> render_submit()
|
|> render_submit()
|
||||||
|
|
||||||
|
|
@ -91,7 +91,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
grid: "EM12kp",
|
grid: "EM12kp",
|
||||||
lat: "",
|
lat: "",
|
||||||
lon: "",
|
lon: "",
|
||||||
status: "ideal",
|
status: "good",
|
||||||
notes: ""
|
notes: ""
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -113,7 +113,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
grid: "",
|
grid: "",
|
||||||
lat: "32.5",
|
lat: "32.5",
|
||||||
lon: "-97.5",
|
lon: "-97.5",
|
||||||
status: "ideal",
|
status: "good",
|
||||||
notes: ""
|
notes: ""
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -127,7 +127,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
Rover.create_location(user, %{
|
Rover.create_location(user, %{
|
||||||
lat: 32.5,
|
lat: 32.5,
|
||||||
lon: -97.5,
|
lon: -97.5,
|
||||||
status: :ideal,
|
status: :good,
|
||||||
notes: "rooftop spot"
|
notes: "rooftop spot"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -138,8 +138,8 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
|
|
||||||
test "edit/delete buttons appear only on the owner's row", %{conn: conn, user: user} do
|
test "edit/delete buttons appear only on the owner's row", %{conn: conn, user: user} do
|
||||||
other = Microwaveprop.AccountsFixtures.user_fixture()
|
other = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
{:ok, mine} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal})
|
{:ok, mine} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
|
||||||
{:ok, theirs} = Rover.create_location(other, %{lat: 33.0, lon: -98.0, status: :off_limits})
|
{:ok, theirs} = Rover.create_location(other, %{lat: 33.0, lon: -98.0, status: :bad})
|
||||||
|
|
||||||
{:ok, lv, _html} = live(conn, ~p"/rover-locations")
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations")
|
||||||
|
|
||||||
|
|
@ -156,7 +156,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
{:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
|
||||||
other = Microwaveprop.AccountsFixtures.user_fixture()
|
other = Microwaveprop.AccountsFixtures.user_fixture()
|
||||||
|
|
||||||
{:ok, theirs} = Rover.create_location(other, %{lat: 33.0, lon: -98.0, status: :ideal})
|
{:ok, theirs} = Rover.create_location(other, %{lat: 33.0, lon: -98.0, status: :good})
|
||||||
|
|
||||||
conn = log_in_user(conn, admin)
|
conn = log_in_user(conn, admin)
|
||||||
{:ok, lv, _html} = live(conn, ~p"/rover-locations")
|
{:ok, lv, _html} = live(conn, ~p"/rover-locations")
|
||||||
|
|
@ -180,7 +180,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
Rover.create_location(other, %{
|
Rover.create_location(other, %{
|
||||||
lat: 33.0,
|
lat: 33.0,
|
||||||
lon: -98.0,
|
lon: -98.0,
|
||||||
status: :ideal,
|
status: :good,
|
||||||
notes: "old"
|
notes: "old"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -196,7 +196,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
location: %{
|
location: %{
|
||||||
lat: "33.0",
|
lat: "33.0",
|
||||||
lon: "-98.0",
|
lon: "-98.0",
|
||||||
status: "off_limits",
|
status: "bad",
|
||||||
notes: "admin override"
|
notes: "admin override"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -204,7 +204,7 @@ defmodule MicrowavepropWeb.RoverLocationsLiveTest do
|
||||||
|
|
||||||
updated = Microwaveprop.Repo.get(Location, theirs.id)
|
updated = Microwaveprop.Repo.get(Location, theirs.id)
|
||||||
assert updated.notes == "admin override"
|
assert updated.notes == "admin override"
|
||||||
assert updated.status == :off_limits
|
assert updated.status == :bad
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ defmodule MicrowavepropWeb.RoverPlanningLiveTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp create_mission(user, name) do
|
defp create_mission(user, name) do
|
||||||
{:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal})
|
{:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
|
||||||
|
|
||||||
{:ok, mission} =
|
{:ok, mission} =
|
||||||
RoverPlanning.create_mission(user, %{
|
RoverPlanning.create_mission(user, %{
|
||||||
|
|
@ -86,7 +86,7 @@ defmodule MicrowavepropWeb.RoverPlanningLiveTest do
|
||||||
test "logged-in user can create a mission with a callsign-input station",
|
test "logged-in user can create a mission with a callsign-input station",
|
||||||
%{conn: conn} do
|
%{conn: conn} do
|
||||||
user = AccountsFixtures.user_fixture()
|
user = AccountsFixtures.user_fixture()
|
||||||
{:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :ideal})
|
{:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
|
||||||
conn = log_in_user(conn, user)
|
conn = log_in_user(conn, user)
|
||||||
|
|
||||||
{:ok, lv, html} = live(conn, ~p"/rover-planning/new")
|
{:ok, lv, html} = live(conn, ~p"/rover-planning/new")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue