fix(radio): add private clause to current_value/2

The /contacts/:id edit form always submits the `private` checkbox, but
`current_value/2` had no `"private"` clause and fell through to the
catch-all `nil`. The Contact schema defaults `private: false`, so an
unchanged box compared `false != nil` and was always tagged as a
change — for non-owners that meant a spurious pending review queued
on every save, and for owners/admins it triggered a no-op direct
update.

Adds the missing clause so the diff sees boolean-vs-boolean and
correctly returns `:no_changes` when the box is untouched.
This commit is contained in:
Graham McIntire 2026-04-25 10:04:39 -05:00
parent 2365c19321
commit 13996583bd
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 33 additions and 0 deletions

View file

@ -941,6 +941,7 @@ defmodule Microwaveprop.Radio do
defp current_value(contact, "qso_timestamp"), do: contact.qso_timestamp
defp current_value(contact, "height1_ft"), do: contact.height1_ft
defp current_value(contact, "height2_ft"), do: contact.height2_ft
defp current_value(contact, "private"), do: contact.private
defp current_value(_contact, _key), do: nil
defp values_equal?(a, b) when is_binary(a) and is_binary(b) do

View file

@ -449,6 +449,38 @@ defmodule Microwaveprop.Radio.ContactEditTest do
assert {:error, :no_changes} =
Radio.apply_owner_edit(contact, user, %{"qso_timestamp" => "not a real date"})
end
test "unchanged private checkbox is treated as no-op", %{user: user} do
contact = owned_contact(user)
# Schema default is `private: false`; the form always submits the
# current state. Without a current_value/2 clause the diff sees
# `false != nil` and treats it as a real change.
assert contact.private == false
assert {:error, :no_changes} =
Radio.apply_owner_edit(contact, user, %{"private" => false})
end
test "owner can flip private from false to true", %{user: user} do
contact = owned_contact(user)
{:ok, updated} = Radio.apply_owner_edit(contact, user, %{"private" => true})
assert updated.private == true
end
test "checkbox 'true'/'false' strings round-trip correctly", %{user: user} do
contact = owned_contact(user)
# Form delivers booleans as strings; the existing
# normalize_boolean_field coerces them, but the diff still has to
# use the boolean current_value for correctness.
assert {:error, :no_changes} =
Radio.apply_owner_edit(contact, user, %{"private" => "false"})
{:ok, updated} = Radio.apply_owner_edit(contact, user, %{"private" => "true"})
assert updated.private == true
end
end
describe "Radio.owner?/2" do