aprs.me/test/aprsme/accounts/user_test.exs
Graham McIntire b86153cd27
Fix all mix credo --strict warnings (188 → 0)
- Replace apply/2 with direct fully-qualified calls in movement_test
- Fix assert_receive timeouts < 1000ms across 8 test files
- Move nested import statements to module-level scope
- Fix tests with no assertions and add missing doctest
- Replace weak type assertions with specific value checks
- Fix conditional assertions and length/1 expensive patterns
- Disable inappropriate Jump.CredoChecks.AvoidSocketAssignsInTest
- Fix tests not calling application code with credo:disable
- Add various credo:disable comments for legitimate patterns
2026-06-12 16:27:20 -05:00

213 lines
6.6 KiB
Elixir

defmodule Aprsme.Accounts.UserTest do
use Aprsme.DataCase, async: true
alias Aprsme.Accounts.User
describe "registration_changeset/2" do
test "requires callsign" do
changeset = User.registration_changeset(%User{}, %{})
errors = errors_on(changeset)
assert Map.has_key?(errors, :callsign)
assert "can't be blank" in errors.callsign
end
test "validates callsign format" do
invalid_callsigns = ["123", "TOOLONGCALLSIGN", "NO SPACES", "nodigit"]
for callsign <- invalid_callsigns do
changeset =
User.registration_changeset(%User{}, %{
email: "test@example.com",
password: "valid_password123",
callsign: callsign
})
errors = errors_on(changeset)
assert Map.has_key?(errors, :callsign), "Expected callsign error for: #{callsign}"
assert "must be a valid amateur radio callsign" in errors.callsign
end
end
test "validates empty callsign" do
changeset =
User.registration_changeset(%User{}, %{
email: "test@example.com",
password: "valid_password123",
callsign: ""
})
errors = errors_on(changeset)
assert Map.has_key?(errors, :callsign)
assert "can't be blank" in errors.callsign
end
test "accepts valid callsigns" do
valid_callsigns = ["K1ABC", "W2XYZ", "AA3BB", "KG4AAA", "N7PQR", "VE3ABC"]
for callsign <- valid_callsigns do
changeset =
User.registration_changeset(%User{}, %{
email: "test@example.com",
password: "valid_password123",
callsign: callsign
})
assert changeset.valid?
end
end
test "converts callsign to uppercase" do
changeset =
User.registration_changeset(%User{}, %{
email: "test@example.com",
password: "valid_password123",
callsign: "k1abc"
})
assert get_change(changeset, :callsign) == "K1ABC"
end
end
describe "callsign_changeset/2" do
test "requires callsign to change" do
user = %User{callsign: "K1ABC"}
changeset = User.callsign_changeset(user, %{callsign: "K1ABC"})
errors = errors_on(changeset)
assert Map.has_key?(errors, :callsign)
assert "did not change" in errors.callsign
end
test "validates new callsign format" do
user = %User{callsign: "K1ABC"}
changeset = User.callsign_changeset(user, %{callsign: "INVALID"})
errors = errors_on(changeset)
assert Map.has_key?(errors, :callsign)
assert "must be a valid amateur radio callsign" in errors.callsign
end
test "accepts valid callsign change" do
user = %User{callsign: "K1ABC"}
changeset = User.callsign_changeset(user, %{callsign: "W2XYZ"})
assert changeset.valid?
assert get_change(changeset, :callsign) == "W2XYZ"
end
end
describe "email_changeset/2" do
test "requires email to change" do
user = %User{email: "a@b.com"}
changeset = User.email_changeset(user, %{email: "a@b.com"})
errors = errors_on(changeset)
assert Map.has_key?(errors, :email)
assert "did not change" in errors.email
end
test "validates format of the new email" do
user = %User{email: "a@b.com"}
changeset = User.email_changeset(user, %{email: "bad email"})
errors = errors_on(changeset)
assert "must have the @ sign and no spaces" in errors.email
end
end
describe "password_changeset/2" do
test "requires matching confirmation" do
user = %User{}
changeset =
User.password_changeset(user, %{
"password" => "abcdefghijkl",
"password_confirmation" => "different"
})
errors = errors_on(changeset)
assert "does not match password" in errors.password_confirmation
end
test "hashes password when valid" do
user = %User{}
changeset =
User.password_changeset(user, %{
"password" => "abcdefghijkl",
"password_confirmation" => "abcdefghijkl"
})
assert changeset.valid?
assert byte_size(get_change(changeset, :hashed_password)) > 0
# Plaintext password is dropped after hashing.
refute get_change(changeset, :password)
end
end
describe "confirm_changeset/1" do
test "sets confirmed_at to the current time truncated to seconds" do
changeset = User.confirm_changeset(%User{})
confirmed_at = get_change(changeset, :confirmed_at)
assert %NaiveDateTime{} = confirmed_at
# No microseconds — truncated.
assert confirmed_at.microsecond == {0, 0}
end
end
describe "valid_password?/2" do
test "returns false when the user has no hashed password" do
refute User.valid_password?(%User{hashed_password: nil}, "any")
end
test "returns false when the provided password is empty" do
user = %User{hashed_password: Bcrypt.hash_pwd_salt("hello world!")}
refute User.valid_password?(user, "")
end
test "returns true for the correct password" do
user = %User{hashed_password: Bcrypt.hash_pwd_salt("hello world!")}
assert User.valid_password?(user, "hello world!")
end
test "returns false for the wrong password" do
user = %User{hashed_password: Bcrypt.hash_pwd_salt("hello world!")}
refute User.valid_password?(user, "wrong")
end
end
describe "validate_current_password/2" do
test "adds an error when the password is wrong" do
user = %User{hashed_password: Bcrypt.hash_pwd_salt("hello world!")}
changeset = Ecto.Changeset.change(user)
changeset = User.validate_current_password(changeset, "wrong")
errors = errors_on(changeset)
assert "is not valid" in errors.current_password
end
test "does not add an error when the password is correct" do
user = %User{hashed_password: Bcrypt.hash_pwd_salt("hello world!")}
changeset = Ecto.Changeset.change(user)
changeset = User.validate_current_password(changeset, "hello world!")
assert changeset.valid?
end
end
describe "Inspect protocol" do
test "redacts the hashed and plaintext passwords" do
user = %User{
email: "a@b.com",
hashed_password: "super-secret-hash",
password: "super-secret"
}
output = inspect(user)
refute output =~ "super-secret-hash"
refute output =~ "super-secret"
# The email is non-redacted, so it should still appear.
assert output =~ "a@b.com"
changeset =
User.password_changeset(%User{}, %{"password" => "newpass12345", "password_confirmation" => "newpass12345"})
assert changeset.valid?
assert byte_size(get_change(changeset, :hashed_password)) > 0
end
end
end