more tests
This commit is contained in:
parent
891fb04f5a
commit
f6509cac08
3 changed files with 569 additions and 0 deletions
163
test/towerops/agents/agent_assignment_test.exs
Normal file
163
test/towerops/agents/agent_assignment_test.exs
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
defmodule Towerops.Agents.AgentAssignmentTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
alias Towerops.Agents.AgentAssignment
|
||||
|
||||
describe "changeset/2" do
|
||||
test "valid changeset with required fields" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id
|
||||
}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.agent_token_id == agent_token_id
|
||||
assert changeset.changes.device_id == device_id
|
||||
end
|
||||
|
||||
test "valid changeset with all fields" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id,
|
||||
enabled: false
|
||||
}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.agent_token_id == agent_token_id
|
||||
assert changeset.changes.device_id == device_id
|
||||
assert changeset.changes.enabled == false
|
||||
end
|
||||
|
||||
test "enabled defaults to true" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id
|
||||
}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert Ecto.Changeset.get_field(changeset, :enabled) == true
|
||||
end
|
||||
|
||||
test "requires agent_token_id" do
|
||||
device_id = Ecto.UUID.generate()
|
||||
attrs = %{device_id: device_id}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{agent_token_id: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "requires device_id" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
attrs = %{agent_token_id: agent_token_id}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{device_id: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "accepts enabled as true" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id,
|
||||
enabled: true
|
||||
}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert Ecto.Changeset.get_field(changeset, :enabled) == true
|
||||
end
|
||||
|
||||
test "accepts enabled as false" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id,
|
||||
enabled: false
|
||||
}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.enabled == false
|
||||
end
|
||||
|
||||
test "allows updating enabled field" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
existing_assignment = %AgentAssignment{
|
||||
id: Ecto.UUID.generate(),
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id,
|
||||
enabled: true
|
||||
}
|
||||
|
||||
attrs = %{enabled: false}
|
||||
changeset = AgentAssignment.changeset(existing_assignment, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.enabled == false
|
||||
end
|
||||
|
||||
test "allows changing agent_token_id" do
|
||||
old_agent_token_id = Ecto.UUID.generate()
|
||||
new_agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
existing_assignment = %AgentAssignment{
|
||||
id: Ecto.UUID.generate(),
|
||||
agent_token_id: old_agent_token_id,
|
||||
device_id: device_id,
|
||||
enabled: true
|
||||
}
|
||||
|
||||
attrs = %{agent_token_id: new_agent_token_id}
|
||||
changeset = AgentAssignment.changeset(existing_assignment, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.agent_token_id == new_agent_token_id
|
||||
end
|
||||
|
||||
test "casts all supported fields" do
|
||||
agent_token_id = Ecto.UUID.generate()
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
agent_token_id: agent_token_id,
|
||||
device_id: device_id,
|
||||
enabled: false
|
||||
}
|
||||
|
||||
changeset = AgentAssignment.changeset(%AgentAssignment{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert Map.has_key?(changeset.changes, :agent_token_id)
|
||||
assert Map.has_key?(changeset.changes, :device_id)
|
||||
assert Map.has_key?(changeset.changes, :enabled)
|
||||
end
|
||||
end
|
||||
end
|
||||
228
test/towerops/agents/agent_token_test.exs
Normal file
228
test/towerops/agents/agent_token_test.exs
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
defmodule Towerops.Agents.AgentTokenTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
alias Towerops.Agents.AgentToken
|
||||
|
||||
describe "build_token/3" do
|
||||
test "generates a token with 48 bytes of entropy" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{token, _changeset} = AgentToken.build_token(org_id, "Test Agent")
|
||||
|
||||
# Decode the base64-encoded token
|
||||
decoded = Base.url_decode64!(token, padding: false)
|
||||
|
||||
# Should be exactly 48 bytes
|
||||
assert byte_size(decoded) == 48
|
||||
end
|
||||
|
||||
test "returns token string and valid changeset for organization agent" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{token, changeset} = AgentToken.build_token(org_id, "My Agent")
|
||||
|
||||
assert is_binary(token)
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.token == token
|
||||
assert changeset.changes.name == "My Agent"
|
||||
assert changeset.changes.organization_id == org_id
|
||||
assert Ecto.Changeset.get_field(changeset, :is_cloud_poller) == false
|
||||
end
|
||||
|
||||
test "sets is_cloud_poller to false by default" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{_token, changeset} = AgentToken.build_token(org_id, "Test Agent")
|
||||
|
||||
assert Ecto.Changeset.get_field(changeset, :is_cloud_poller) == false
|
||||
end
|
||||
|
||||
test "generates unique tokens on each call" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{token1, _} = AgentToken.build_token(org_id, "Agent 1")
|
||||
{token2, _} = AgentToken.build_token(org_id, "Agent 2")
|
||||
{token3, _} = AgentToken.build_token(org_id, "Agent 3")
|
||||
|
||||
# All tokens should be different
|
||||
assert token1 != token2
|
||||
assert token2 != token3
|
||||
assert token1 != token3
|
||||
end
|
||||
|
||||
test "creates cloud poller token when is_cloud_poller is true" do
|
||||
{token, changeset} = AgentToken.build_token(nil, "Cloud Poller", is_cloud_poller: true)
|
||||
|
||||
assert is_binary(token)
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.is_cloud_poller == true
|
||||
refute Map.has_key?(changeset.changes, :organization_id)
|
||||
end
|
||||
|
||||
test "requires name" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{_token, changeset} = AgentToken.build_token(org_id, nil)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{name: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "adds error if cloud poller has organization_id" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{_token, changeset} = AgentToken.build_token(org_id, "Test", is_cloud_poller: true)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{organization_id: ["must be nil for cloud pollers"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "adds error if non-cloud poller has nil organization_id" do
|
||||
{_token, changeset} = AgentToken.build_token(nil, "Test", is_cloud_poller: false)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{organization_id: ["can't be blank for non-cloud pollers"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "token is URL-safe base64 encoded without padding" do
|
||||
org_id = Ecto.UUID.generate()
|
||||
{token, _changeset} = AgentToken.build_token(org_id, "Test Agent")
|
||||
|
||||
# Should not contain padding characters
|
||||
refute String.contains?(token, "=")
|
||||
|
||||
# Should only contain URL-safe base64 characters
|
||||
assert token =~ ~r/^[A-Za-z0-9_-]+$/
|
||||
end
|
||||
end
|
||||
|
||||
describe "update_changeset/2" do
|
||||
test "allows updating name" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "existing-token",
|
||||
name: "Old Name",
|
||||
organization_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
attrs = %{name: "New Name"}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.name == "New Name"
|
||||
end
|
||||
|
||||
test "allows updating allow_remote_debug" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "existing-token",
|
||||
name: "Test Agent",
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
allow_remote_debug: false
|
||||
}
|
||||
|
||||
attrs = %{allow_remote_debug: true}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.allow_remote_debug == true
|
||||
end
|
||||
|
||||
test "allows updating both name and allow_remote_debug" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "existing-token",
|
||||
name: "Old Name",
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
allow_remote_debug: false
|
||||
}
|
||||
|
||||
attrs = %{name: "New Name", allow_remote_debug: true}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.name == "New Name"
|
||||
assert changeset.changes.allow_remote_debug == true
|
||||
end
|
||||
|
||||
test "requires name" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "existing-token",
|
||||
name: "Old Name",
|
||||
organization_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
attrs = %{name: ""}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{name: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "ignores attempts to update token" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "original-token",
|
||||
name: "Test Agent",
|
||||
organization_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
attrs = %{name: "New Name", token: "hacker-token"}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.name == "New Name"
|
||||
refute Map.has_key?(changeset.changes, :token)
|
||||
end
|
||||
|
||||
test "ignores attempts to update organization_id" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "existing-token",
|
||||
name: "Test Agent",
|
||||
organization_id: Ecto.UUID.generate()
|
||||
}
|
||||
|
||||
new_org_id = Ecto.UUID.generate()
|
||||
attrs = %{name: "New Name", organization_id: new_org_id}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.name == "New Name"
|
||||
refute Map.has_key?(changeset.changes, :organization_id)
|
||||
end
|
||||
|
||||
test "ignores attempts to update enabled" do
|
||||
agent_token = %AgentToken{
|
||||
id: Ecto.UUID.generate(),
|
||||
token: "existing-token",
|
||||
name: "Test Agent",
|
||||
organization_id: Ecto.UUID.generate(),
|
||||
enabled: true
|
||||
}
|
||||
|
||||
attrs = %{name: "New Name", enabled: false}
|
||||
changeset = AgentToken.update_changeset(agent_token, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.name == "New Name"
|
||||
refute Map.has_key?(changeset.changes, :enabled)
|
||||
end
|
||||
end
|
||||
|
||||
describe "verify_token/1" do
|
||||
test "returns {:ok, token} for valid binary token" do
|
||||
token = "valid-token-string"
|
||||
assert AgentToken.verify_token(token) == {:ok, token}
|
||||
end
|
||||
|
||||
test "returns {:ok, token} for any binary string" do
|
||||
assert AgentToken.verify_token("abc123") == {:ok, "abc123"}
|
||||
assert AgentToken.verify_token("") == {:ok, ""}
|
||||
assert AgentToken.verify_token("with-dashes") == {:ok, "with-dashes"}
|
||||
end
|
||||
|
||||
test "returns {:error, :invalid_token} for non-binary values" do
|
||||
assert AgentToken.verify_token(nil) == {:error, :invalid_token}
|
||||
assert AgentToken.verify_token(12_345) == {:error, :invalid_token}
|
||||
assert AgentToken.verify_token([]) == {:error, :invalid_token}
|
||||
assert AgentToken.verify_token(%{}) == {:error, :invalid_token}
|
||||
assert AgentToken.verify_token(:atom) == {:error, :invalid_token}
|
||||
end
|
||||
end
|
||||
end
|
||||
178
test/towerops/alerts/alert_test.exs
Normal file
178
test/towerops/alerts/alert_test.exs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
defmodule Towerops.Alerts.AlertTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
alias Towerops.Alerts.Alert
|
||||
|
||||
describe "changeset/2" do
|
||||
test "valid changeset with required fields" do
|
||||
attrs = %{
|
||||
device_id: Ecto.UUID.generate(),
|
||||
alert_type: :device_down,
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z]
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.device_id == attrs.device_id
|
||||
assert changeset.changes.alert_type == :device_down
|
||||
assert changeset.changes.triggered_at == attrs.triggered_at
|
||||
end
|
||||
|
||||
test "valid changeset with all fields" do
|
||||
device_id = Ecto.UUID.generate()
|
||||
user_id = Ecto.UUID.generate()
|
||||
triggered_at = ~U[2026-01-15 10:00:00Z]
|
||||
acknowledged_at = ~U[2026-01-15 10:05:00Z]
|
||||
resolved_at = ~U[2026-01-15 10:10:00Z]
|
||||
email_sent_at = ~U[2026-01-15 10:01:00Z]
|
||||
|
||||
attrs = %{
|
||||
device_id: device_id,
|
||||
alert_type: :device_up,
|
||||
triggered_at: triggered_at,
|
||||
acknowledged_at: acknowledged_at,
|
||||
acknowledged_by_id: user_id,
|
||||
resolved_at: resolved_at,
|
||||
email_sent_at: email_sent_at,
|
||||
message: "Device came back online"
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.device_id == device_id
|
||||
assert changeset.changes.alert_type == :device_up
|
||||
assert changeset.changes.triggered_at == triggered_at
|
||||
assert changeset.changes.acknowledged_at == acknowledged_at
|
||||
assert changeset.changes.acknowledged_by_id == user_id
|
||||
assert changeset.changes.resolved_at == resolved_at
|
||||
assert changeset.changes.email_sent_at == email_sent_at
|
||||
assert changeset.changes.message == "Device came back online"
|
||||
end
|
||||
|
||||
test "requires device_id" do
|
||||
attrs = %{
|
||||
alert_type: :device_down,
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z]
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{device_id: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "requires alert_type" do
|
||||
attrs = %{
|
||||
device_id: Ecto.UUID.generate(),
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z]
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{alert_type: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "requires triggered_at" do
|
||||
attrs = %{
|
||||
device_id: Ecto.UUID.generate(),
|
||||
alert_type: :device_down
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
refute changeset.valid?
|
||||
assert %{triggered_at: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "validates alert_type is one of valid enum values" do
|
||||
attrs = %{
|
||||
device_id: Ecto.UUID.generate(),
|
||||
alert_type: :device_down,
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z]
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
assert changeset.valid?
|
||||
|
||||
attrs2 = %{attrs | alert_type: :device_up}
|
||||
changeset2 = Alert.changeset(%Alert{}, attrs2)
|
||||
assert changeset2.valid?
|
||||
end
|
||||
|
||||
test "accepts nil for optional fields" do
|
||||
attrs = %{
|
||||
device_id: Ecto.UUID.generate(),
|
||||
alert_type: :device_down,
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z],
|
||||
acknowledged_at: nil,
|
||||
acknowledged_by_id: nil,
|
||||
resolved_at: nil,
|
||||
email_sent_at: nil,
|
||||
message: nil
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
end
|
||||
|
||||
test "allows updating an existing alert" do
|
||||
device_id = Ecto.UUID.generate()
|
||||
|
||||
existing_alert = %Alert{
|
||||
id: Ecto.UUID.generate(),
|
||||
device_id: device_id,
|
||||
alert_type: :device_down,
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z]
|
||||
}
|
||||
|
||||
user_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
acknowledged_at: ~U[2026-01-15 10:05:00Z],
|
||||
acknowledged_by_id: user_id,
|
||||
message: "Acknowledged by admin"
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(existing_alert, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
assert changeset.changes.acknowledged_at == attrs.acknowledged_at
|
||||
assert changeset.changes.acknowledged_by_id == user_id
|
||||
assert changeset.changes.message == "Acknowledged by admin"
|
||||
end
|
||||
|
||||
test "casts all supported fields" do
|
||||
device_id = Ecto.UUID.generate()
|
||||
user_id = Ecto.UUID.generate()
|
||||
|
||||
attrs = %{
|
||||
device_id: device_id,
|
||||
alert_type: :device_down,
|
||||
triggered_at: ~U[2026-01-15 10:00:00Z],
|
||||
acknowledged_at: ~U[2026-01-15 10:05:00Z],
|
||||
acknowledged_by_id: user_id,
|
||||
resolved_at: ~U[2026-01-15 10:10:00Z],
|
||||
email_sent_at: ~U[2026-01-15 10:01:00Z],
|
||||
message: "Test message"
|
||||
}
|
||||
|
||||
changeset = Alert.changeset(%Alert{}, attrs)
|
||||
|
||||
assert changeset.valid?
|
||||
|
||||
# All fields should be in changes
|
||||
assert Map.has_key?(changeset.changes, :device_id)
|
||||
assert Map.has_key?(changeset.changes, :alert_type)
|
||||
assert Map.has_key?(changeset.changes, :triggered_at)
|
||||
assert Map.has_key?(changeset.changes, :acknowledged_at)
|
||||
assert Map.has_key?(changeset.changes, :acknowledged_by_id)
|
||||
assert Map.has_key?(changeset.changes, :resolved_at)
|
||||
assert Map.has_key?(changeset.changes, :email_sent_at)
|
||||
assert Map.has_key?(changeset.changes, :message)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue