211 lines
5.6 KiB
Elixir
211 lines
5.6 KiB
Elixir
defmodule Towerops.Monitoring.CheckTest do
|
|
# async: false to prevent deadlocks when testing foreign key constraints
|
|
use Towerops.DataCase, async: false
|
|
|
|
import Towerops.AccountsFixtures
|
|
|
|
alias Towerops.Monitoring.Check
|
|
|
|
describe "changeset/2" do
|
|
setup do
|
|
user = user_fixture()
|
|
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
|
|
|
{:ok, site} =
|
|
Towerops.Sites.create_site(%{
|
|
name: "Test Site",
|
|
organization_id: organization.id
|
|
})
|
|
|
|
{:ok, device} =
|
|
Towerops.Devices.create_device(%{
|
|
name: "Test Device",
|
|
ip_address: "192.168.1.1",
|
|
site_id: site.id,
|
|
organization_id: site.organization_id
|
|
})
|
|
|
|
{:ok, device: device}
|
|
end
|
|
|
|
test "valid changeset with all fields", %{device: device} do
|
|
attrs = %{
|
|
device_id: device.id,
|
|
status: :success,
|
|
response_time_ms: 12.5,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
|
|
assert changeset.valid?
|
|
assert get_change(changeset, :device_id) == device.id
|
|
assert get_change(changeset, :status) == :success
|
|
assert get_change(changeset, :response_time_ms) == 12.5
|
|
assert get_change(changeset, :checked_at)
|
|
end
|
|
|
|
test "valid changeset with failure status", %{device: device} do
|
|
attrs = %{
|
|
device_id: device.id,
|
|
status: :failure,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
|
|
assert changeset.valid?
|
|
assert get_change(changeset, :status) == :failure
|
|
# response_time_ms is optional and can be nil for failures
|
|
refute Map.has_key?(changeset.changes, :response_time_ms)
|
|
end
|
|
|
|
test "requires device_id" do
|
|
attrs = %{
|
|
status: :success,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
|
|
refute changeset.valid?
|
|
assert "can't be blank" in errors_on(changeset).device_id
|
|
end
|
|
|
|
test "requires status" do
|
|
attrs = %{
|
|
device_id: Ecto.UUID.generate(),
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
|
|
refute changeset.valid?
|
|
assert "can't be blank" in errors_on(changeset).status
|
|
end
|
|
|
|
test "requires checked_at" do
|
|
attrs = %{
|
|
device_id: Ecto.UUID.generate(),
|
|
status: :success
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
|
|
refute changeset.valid?
|
|
assert "can't be blank" in errors_on(changeset).checked_at
|
|
end
|
|
|
|
test "accepts only valid status values", %{device: device} do
|
|
# Invalid status value
|
|
attrs = %{
|
|
device_id: device.id,
|
|
status: :invalid_status,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
|
|
refute changeset.valid?
|
|
assert "is invalid" in errors_on(changeset).status
|
|
end
|
|
|
|
test "validates foreign key constraint on insert", %{device: device} do
|
|
# This test requires actual database insert
|
|
valid_attrs = %{
|
|
device_id: device.id,
|
|
status: :success,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, valid_attrs)
|
|
assert {:ok, _check} = Repo.insert(changeset)
|
|
|
|
# Now try with invalid device_id
|
|
invalid_attrs = %{
|
|
device_id: Ecto.UUID.generate(),
|
|
status: :success,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, invalid_attrs)
|
|
assert {:error, changeset} = Repo.insert(changeset)
|
|
assert "does not exist" in errors_on(changeset).device_id
|
|
end
|
|
|
|
test "response_time_ms can be nil", %{device: device} do
|
|
attrs = %{
|
|
device_id: device.id,
|
|
status: :failure,
|
|
response_time_ms: nil,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
assert changeset.valid?
|
|
end
|
|
|
|
test "response_time_ms accepts float values", %{device: device} do
|
|
attrs = %{
|
|
device_id: device.id,
|
|
status: :success,
|
|
response_time_ms: 123.456,
|
|
checked_at: DateTime.utc_now()
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
assert changeset.valid?
|
|
assert get_change(changeset, :response_time_ms) == 123.456
|
|
end
|
|
|
|
test "checked_at accepts DateTime", %{device: device} do
|
|
now = DateTime.utc_now()
|
|
|
|
attrs = %{
|
|
device_id: device.id,
|
|
status: :success,
|
|
checked_at: now
|
|
}
|
|
|
|
changeset = Check.changeset(%Check{}, attrs)
|
|
assert changeset.valid?
|
|
end
|
|
end
|
|
|
|
describe "schema" do
|
|
test "has correct fields" do
|
|
fields = Check.__schema__(:fields)
|
|
assert :id in fields
|
|
assert :device_id in fields
|
|
assert :status in fields
|
|
assert :response_time_ms in fields
|
|
assert :checked_at in fields
|
|
assert :inserted_at in fields
|
|
end
|
|
|
|
test "belongs to device" do
|
|
assocs = Check.__schema__(:associations)
|
|
assert :device in assocs
|
|
|
|
assoc = Check.__schema__(:association, :device)
|
|
assert assoc.queryable == Towerops.Devices.Device
|
|
end
|
|
|
|
test "uses binary_id for primary key" do
|
|
assert Check.__schema__(:type, :id) == :binary_id
|
|
end
|
|
|
|
test "uses binary_id for foreign keys" do
|
|
assert Check.__schema__(:type, :device_id) == :binary_id
|
|
end
|
|
|
|
test "status is an enum" do
|
|
assert {:parameterized, {Ecto.Enum, _}} = Check.__schema__(:type, :status)
|
|
end
|
|
|
|
test "does not have updated_at timestamp" do
|
|
fields = Check.__schema__(:fields)
|
|
refute :updated_at in fields
|
|
end
|
|
end
|
|
end
|