towerops/test/towerops/organizations/organization_property_test.exs
Graham McIntire 146f5745cf
fix: resolve compilation errors, test failures, and credo issues
- Escape HEEx template braces in GraphQL/API docs with raw(~S[...])
- Fix test assertions for updated marketing copy and UI text
- Extract helper functions in GraphQL resolvers to reduce nesting depth
- Create shared ErrorHelpers module for API controllers
- Fix ETS race condition in brute force whitelist cache for async tests
- Fix property test generators to use ASCII instead of printable unicode
- Add alert_severity helper to site_live/show
- Update accounts fixtures for explicit user confirmation
2026-02-14 12:23:10 -06:00

137 lines
4.4 KiB
Elixir

defmodule Towerops.Organizations.OrganizationPropertyTest do
@moduledoc "Property-based tests for Organization changeset validation."
use Towerops.DataCase
use ExUnitProperties
alias Towerops.Organizations.Organization
describe "name validation" do
property "accepts valid names (2-100 printable chars)" do
check all(name <- string(:ascii, min_length: 2, max_length: 100), max_runs: 50) do
changeset = Organization.changeset(%Organization{}, %{name: name})
# Name field itself should be valid (other fields may cause errors)
refute Keyword.has_key?(changeset.errors, :name)
end
end
property "rejects names shorter than 2 characters" do
check all(name <- string(:printable, min_length: 0, max_length: 1), max_runs: 25) do
changeset =
%Organization{}
|> Organization.changeset(%{name: name})
|> Map.put(:action, :insert)
assert Keyword.has_key?(changeset.errors, :name)
end
end
property "rejects names longer than 100 characters" do
check all(name <- string(:ascii, min_length: 101, max_length: 300), max_runs: 25) do
changeset =
%Organization{}
|> Organization.changeset(%{name: name})
|> Map.put(:action, :insert)
assert {:name, _} = List.keyfind(changeset.errors, :name, 0)
end
end
end
describe "SNMP port validation" do
property "accepts valid ports (1-65535)" do
check all(port <- integer(1..65_535), max_runs: 50) do
changeset = Organization.changeset(%Organization{}, %{name: "Test Org", snmp_port: port})
refute Keyword.has_key?(changeset.errors, :snmp_port)
end
end
property "rejects ports outside valid range" do
check all(port <- one_of([integer(-1000..0), integer(65_536..100_000)]), max_runs: 50) do
changeset =
%Organization{}
|> Organization.changeset(%{name: "Test Org", snmp_port: port})
|> Map.put(:action, :insert)
assert Keyword.has_key?(changeset.errors, :snmp_port)
end
end
end
describe "SNMP version validation" do
property "rejects arbitrary strings as SNMP version" do
valid = MapSet.new(["1", "2c", "3"])
check all(
version <- string(:alphanumeric, min_length: 1, max_length: 10),
not MapSet.member?(valid, version),
max_runs: 50
) do
changeset =
%Organization{}
|> Organization.changeset(%{name: "Test Org", snmp_version: version})
|> Map.put(:action, :insert)
assert Keyword.has_key?(changeset.errors, :snmp_version)
end
end
test "accepts valid SNMP versions" do
for version <- ["1", "2c", "3"] do
changeset = Organization.changeset(%Organization{}, %{name: "Test Org", snmp_version: version})
refute Keyword.has_key?(changeset.errors, :snmp_version)
end
end
end
describe "SNMPv3 fields" do
property "v3 requires username regardless of input" do
check all(
username <- one_of([constant(nil), constant("")]),
max_runs: 10
) do
changeset =
%Organization{}
|> Organization.changeset(%{
name: "Test Org",
snmp_version: "3",
snmpv3_username: username
})
|> Map.put(:action, :insert)
assert Keyword.has_key?(changeset.errors, :snmpv3_username)
end
end
property "v3 auth password must be at least 8 chars when auth protocol set" do
check all(password <- string(:ascii, min_length: 1, max_length: 7), max_runs: 30) do
changeset =
%Organization{}
|> Organization.changeset(%{
name: "Test Org",
snmp_version: "3",
snmpv3_username: "testuser",
snmpv3_auth_protocol: "SHA-256",
snmpv3_auth_password: password
})
|> Map.put(:action, :insert)
assert Keyword.has_key?(changeset.errors, :snmpv3_auth_password)
end
end
end
describe "MikroTik port validation" do
property "accepts valid MikroTik ports" do
check all(port <- integer(1..65_535), max_runs: 50) do
changeset =
Organization.changeset(%Organization{}, %{
name: "Test Org",
mikrotik_enabled: true,
mikrotik_port: port
})
refute Keyword.has_key?(changeset.errors, :mikrotik_port)
end
end
end
end