Add comprehensive tests for Organizations.Invitation
Improved coverage from 60.00% to 100% by adding 13 tests covering: - Required field validations (email, role, organization_id, invited_by_id) - Email format validation - Automatic token generation using crypto - Token preservation when provided - Automatic expires_at generation (7 days from now) - Expires_at preservation when provided - All valid role values (admin, member, viewer) - Accepted_at field handling Overall coverage: 66.34%
This commit is contained in:
parent
160007cab1
commit
f5bef9b997
1 changed files with 210 additions and 0 deletions
210
test/towerops/organizations/invitation_test.exs
Normal file
210
test/towerops/organizations/invitation_test.exs
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
defmodule Towerops.Organizations.InvitationTest do
|
||||
use Towerops.DataCase
|
||||
|
||||
alias Towerops.Organizations.Invitation
|
||||
|
||||
describe "changeset/2" do
|
||||
test "valid changeset with required fields" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert get_field(changeset, :email) == "test@example.com"
|
||||
assert get_field(changeset, :role) == :member
|
||||
# Token and expires_at should be auto-generated
|
||||
assert get_field(changeset, :token)
|
||||
assert get_field(changeset, :expires_at)
|
||||
end
|
||||
|
||||
test "requires email" do
|
||||
attrs = %{
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{email: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "requires role" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{role: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "requires organization_id" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{organization_id: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "requires invited_by_id" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{invited_by_id: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "validates email format" do
|
||||
attrs = %{
|
||||
email: "invalid-email",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{email: ["has invalid format"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "accepts valid email formats" do
|
||||
valid_emails = [
|
||||
"test@example.com",
|
||||
"user.name@domain.co.uk",
|
||||
"user+tag@example.org"
|
||||
]
|
||||
|
||||
for email <- valid_emails do
|
||||
attrs = %{
|
||||
email: email,
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
assert changeset.valid?, "Expected #{email} to be valid"
|
||||
end
|
||||
end
|
||||
|
||||
test "generates token automatically" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
token = get_field(changeset, :token)
|
||||
|
||||
assert token
|
||||
assert is_binary(token)
|
||||
assert String.length(token) > 0
|
||||
end
|
||||
|
||||
test "does not override provided token" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate(),
|
||||
token: "custom-token"
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
assert get_field(changeset, :token) == "custom-token"
|
||||
end
|
||||
|
||||
test "generates expires_at automatically (7 days from now)" do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
now = DateTime.utc_now()
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
expires_at = get_field(changeset, :expires_at)
|
||||
|
||||
assert expires_at
|
||||
|
||||
# Should be approximately 7 days from now (within 1 minute tolerance)
|
||||
diff_seconds = DateTime.diff(expires_at, now, :second)
|
||||
expected_seconds = 7 * 24 * 60 * 60
|
||||
assert_in_delta diff_seconds, expected_seconds, 60
|
||||
end
|
||||
|
||||
test "does not override provided expires_at" do
|
||||
custom_expires_at = DateTime.utc_now() |> DateTime.add(1, :day) |> DateTime.truncate(:second)
|
||||
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate(),
|
||||
expires_at: custom_expires_at
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
assert DateTime.compare(get_field(changeset, :expires_at), custom_expires_at) == :eq
|
||||
end
|
||||
|
||||
test "accepts all valid role values" do
|
||||
roles = [:admin, :member, :viewer]
|
||||
|
||||
for role <- roles do
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: role,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
assert changeset.valid?, "Expected role #{role} to be valid"
|
||||
end
|
||||
end
|
||||
|
||||
test "allows accepted_at to be set" do
|
||||
accepted_at = DateTime.truncate(DateTime.utc_now(), :second)
|
||||
|
||||
attrs = %{
|
||||
email: "test@example.com",
|
||||
role: :member,
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
invited_by_id: Ecto.UUID.generate(),
|
||||
accepted_at: accepted_at
|
||||
}
|
||||
|
||||
changeset = Invitation.changeset(%Invitation{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert DateTime.compare(get_field(changeset, :accepted_at), accepted_at) == :eq
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue