- 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
137 lines
4.4 KiB
Elixir
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
|