credo fixes

This commit is contained in:
Graham McIntire 2026-06-13 18:20:20 -05:00
parent 5bb55180a7
commit 0abe522582
55 changed files with 157 additions and 11 deletions

View file

@ -173,15 +173,15 @@
{Jump.CredoChecks.AvoidFunctionLevelElse}, {Jump.CredoChecks.AvoidFunctionLevelElse},
{Jump.CredoChecks.AvoidLoggerConfigureInTest}, {Jump.CredoChecks.AvoidLoggerConfigureInTest},
{Jump.CredoChecks.AvoidSocketAssignsInTest, [excluded: ["test/support/live_view_test_helpers.ex"]]}, {Jump.CredoChecks.AvoidSocketAssignsInTest, [excluded: ["test/support/live_view_test_helpers.ex"]]},
{Jump.CredoChecks.ConditionalAssertion} {Jump.CredoChecks.ConditionalAssertion},
# {Jump.CredoChecks.DoctestIExExamples, {Jump.CredoChecks.DoctestIExExamples,
# [ [
# derive_test_path: fn filename -> derive_test_path: fn filename ->
# filename filename
# |> String.replace_leading("lib/", "test/") |> String.replace_leading("lib/", "test/")
# |> String.replace_trailing(".ex", "_test.exs") |> String.replace_trailing(".ex", "_test.exs")
# end end
# ]}, ]}
# {Jump.CredoChecks.ForbiddenFunction, # {Jump.CredoChecks.ForbiddenFunction,
# [ # [
# functions: [ # functions: [

View file

@ -26,6 +26,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> org_id = Ecto.UUID.generate()
iex> get_organization_agent_health(org_id) iex> get_organization_agent_health(org_id)
[ [
%{ %{
@ -85,6 +86,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> org_id = Ecto.UUID.generate()
iex> get_device_assignment_breakdown(org_id) iex> get_device_assignment_breakdown(org_id)
%{ %{
direct: 50, direct: 50,
@ -152,6 +154,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> agent_id = Ecto.UUID.generate()
iex> get_agent_metric_stats(agent_id) iex> get_agent_metric_stats(agent_id)
%{ %{
total_metrics: 1440, total_metrics: 1440,
@ -225,6 +228,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> org_id = Ecto.UUID.generate()
iex> get_offline_agents(org_id) iex> get_offline_agents(org_id)
[ [
%{id: "uuid", name: "DC2 Agent", last_seen_at: ~U[2026-01-14 10:00:00Z]} %{id: "uuid", name: "DC2 Agent", last_seen_at: ~U[2026-01-14 10:00:00Z]}
@ -252,6 +256,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> org_id = Ecto.UUID.generate()
iex> get_high_load_agents(org_id) iex> get_high_load_agents(org_id)
[ [
%{id: "uuid", name: "DC1 Agent", device_count: 75} %{id: "uuid", name: "DC1 Agent", device_count: 75}
@ -284,6 +289,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> org_id = Ecto.UUID.generate()
iex> get_unmonitored_devices(org_id) iex> get_unmonitored_devices(org_id)
[ [
%{id: "uuid", name: "Switch-01", site_name: "DC1"} %{id: "uuid", name: "Switch-01", site_name: "DC1"}
@ -325,6 +331,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> device_id = Ecto.UUID.generate()
iex> get_device_latency_by_agent(device_id, min_checks: 10) iex> get_device_latency_by_agent(device_id, min_checks: 10)
[ [
%{agent_token_id: "uuid-1", avg_latency_ms: 12.5, check_count: 120}, %{agent_token_id: "uuid-1", avg_latency_ms: 12.5, check_count: 120},
@ -363,6 +370,7 @@ defmodule Towerops.Agents.Stats do
## Examples ## Examples
iex> device_id = Ecto.UUID.generate()
iex> get_device_assignment_with_latency(device_id) iex> get_device_assignment_with_latency(device_id)
%{ %{
device_id: "uuid", device_id: "uuid",

View file

@ -113,7 +113,7 @@ defmodule Towerops.EctoTypes.IpAddress do
## Examples ## Examples
iex> IpAddress.new("192.168.1.1") iex> IpAddress.new("192.168.1.1")
{:ok, %IpAddress{address: "192.168.1.1", version: :ipv4}} {:ok, %IpAddress{address: "192.168.1.1", version: :ipv4, tuple: {192, 168, 1, 1}}}
iex> IpAddress.new("invalid") iex> IpAddress.new("invalid")
:error :error
@ -129,7 +129,7 @@ defmodule Towerops.EctoTypes.IpAddress do
## Examples ## Examples
iex> IpAddress.new!("192.168.1.1") iex> IpAddress.new!("192.168.1.1")
%IpAddress{address: "192.168.1.1", version: :ipv4} %IpAddress{address: "192.168.1.1", version: :ipv4, tuple: {192, 168, 1, 1}}
iex> IpAddress.new!("invalid") iex> IpAddress.new!("invalid")
** (ArgumentError) invalid IP address: "invalid" ** (ArgumentError) invalid IP address: "invalid"

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.ASN1Test do
alias SnmpKit.SnmpLib.ASN1 alias SnmpKit.SnmpLib.ASN1
doctest ASN1
@moduletag :unit @moduletag :unit
@moduletag :protocol @moduletag :protocol
@moduletag :phase_2 @moduletag :phase_2

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.HostParserTest do
alias SnmpKit.SnmpLib.HostParser alias SnmpKit.SnmpLib.HostParser
doctest HostParser
@moduletag :unit @moduletag :unit
@moduletag :host_parser @moduletag :host_parser

View file

@ -11,6 +11,8 @@ defmodule SnmpKit.SnmpLib.MIB.CompilerTest do
alias SnmpKit.SnmpLib.MIB.Compiler alias SnmpKit.SnmpLib.MIB.Compiler
alias SnmpKit.SnmpLib.MIB.Parser alias SnmpKit.SnmpLib.MIB.Parser
doctest Compiler, except: [compile: 1, compile_string: 1, compile_string: 2, load_compiled: 1, compile_all: 1]
# Skip these tests if yecc is not available (requires :parsetools) # Skip these tests if yecc is not available (requires :parsetools)
@moduletag :yecc_required @moduletag :yecc_required

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.MIB.ErrorTest do
alias SnmpKit.SnmpLib.MIB.Error alias SnmpKit.SnmpLib.MIB.Error
doctest Error
describe "new/2" do describe "new/2" do
test "creates error with type and message" do test "creates error with type and message" do
error = Error.new(:syntax_error) error = Error.new(:syntax_error)

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.MIB.RegistryTest do
alias SnmpKit.SnmpLib.MIB.Registry alias SnmpKit.SnmpLib.MIB.Registry
doctest Registry, except: [walk_tree: 1]
describe "resolve_name/1" do describe "resolve_name/1" do
test "resolves standard MIB names" do test "resolves standard MIB names" do
assert {:ok, [1, 3, 6, 1, 2, 1, 1, 1]} = Registry.resolve_name("sysDescr") assert {:ok, [1, 3, 6, 1, 2, 1, 1, 1]} = Registry.resolve_name("sysDescr")

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.OIDTest do
alias SnmpKit.SnmpLib.OID alias SnmpKit.SnmpLib.OID
doctest OID
@moduletag :unit @moduletag :unit
@moduletag :protocol @moduletag :protocol
@moduletag :phase_2 @moduletag :phase_2

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.PDUTest do
alias SnmpKit.SnmpLib.PDU alias SnmpKit.SnmpLib.PDU
doctest PDU
@moduletag :unit @moduletag :unit
@moduletag :protocol @moduletag :protocol
@moduletag :phase_1 @moduletag :phase_1

View file

@ -4,6 +4,8 @@ defmodule SnmpKit.SnmpLib.TransportTest do
alias SnmpKit.SnmpLib.Transport alias SnmpKit.SnmpLib.Transport
doctest Transport
@moduletag :unit @moduletag :unit
@moduletag :protocol @moduletag :protocol
@moduletag :phase_2 @moduletag :phase_2

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpLib.TypesTest do
alias SnmpKit.SnmpLib.Types alias SnmpKit.SnmpLib.Types
doctest Types
@moduletag :unit @moduletag :unit
@moduletag :protocol @moduletag :protocol
@moduletag :phase_2 @moduletag :phase_2

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpMgr.BulkTest do
alias SnmpKit.SnmpMgr.Bulk alias SnmpKit.SnmpMgr.Bulk
doctest Bulk
describe "get_bulk/3 version validation" do describe "get_bulk/3 version validation" do
test "rejects SNMPv1 with error" do test "rejects SNMPv1 with error" do
result = Bulk.get_bulk("192.168.1.1", [1, 3, 6, 1, 2, 1, 1], version: :v1) result = Bulk.get_bulk("192.168.1.1", [1, 3, 6, 1, 2, 1, 1], version: :v1)

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpMgr.ErrorsTest do
alias SnmpKit.SnmpMgr.Errors alias SnmpKit.SnmpMgr.Errors
doctest Errors
describe "code_to_atom/1" do describe "code_to_atom/1" do
test "converts standard SNMP error codes to atoms" do test "converts standard SNMP error codes to atoms" do
assert Errors.code_to_atom(0) == :no_error assert Errors.code_to_atom(0) == :no_error

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpMgr.FormatTest do
alias SnmpKit.SnmpMgr.Format alias SnmpKit.SnmpMgr.Format
doctest Format
describe "pretty_print/1 - new functionality" do describe "pretty_print/1 - new functionality" do
test "formats 3-tuple results with type-aware formatting" do test "formats 3-tuple results with type-aware formatting" do
# Test timeticks formatting (delegates to SnmpKit.SnmpLib.Types) # Test timeticks formatting (delegates to SnmpKit.SnmpLib.Types)

View file

@ -4,6 +4,8 @@ defmodule SnmpKit.SnmpMgr.MIBTest do
alias SnmpKit.SnmpLib.MIB.Parser alias SnmpKit.SnmpLib.MIB.Parser
alias SnmpKit.SnmpMgr.MIB alias SnmpKit.SnmpMgr.MIB
doctest MIB
setup do setup do
# Start the MIB GenServer if not already running # Start the MIB GenServer if not already running
case GenServer.whereis(MIB) do case GenServer.whereis(MIB) do

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpMgr.TypesTest do
alias SnmpKit.SnmpMgr.Types alias SnmpKit.SnmpMgr.Types
doctest Types
describe "encode_value/2 with automatic type inference" do describe "encode_value/2 with automatic type inference" do
test "infers string type for printable binary" do test "infers string type for printable binary" do
assert {:ok, {:string, "Hello World"}} = Types.encode_value("Hello World") assert {:ok, {:string, "Hello World"}} = Types.encode_value("Hello World")

View file

@ -3,6 +3,8 @@ defmodule SnmpKit.SnmpMgr.WalkTest do
alias SnmpKit.SnmpMgr.Walk alias SnmpKit.SnmpMgr.Walk
doctest Walk
# Test helpers to mock Core module behavior # Test helpers to mock Core module behavior
defmodule CoreMock do defmodule CoreMock do
@moduledoc false @moduledoc false

View file

@ -3,6 +3,8 @@ defmodule Towerops.Accounts.HIBPTest do
alias Towerops.Accounts.HIBP alias Towerops.Accounts.HIBP
doctest HIBP, except: [check_password: 1]
describe "check_password/1 with non-binary input" do describe "check_password/1 with non-binary input" do
test "returns {:ok, :unknown} for nil" do test "returns {:ok, :unknown} for nil" do
assert {:ok, :unknown} = HIBP.check_password(nil) assert {:ok, :unknown} = HIBP.check_password(nil)

View file

@ -0,0 +1,36 @@
defmodule Towerops.Accounts.PasswordsTest do
use ExUnit.Case, async: true
alias Towerops.Accounts.Passwords
# The module's @doc examples reference undefined variables (`user`, `url`) and
# use `...` placeholder syntax, which are not valid standalone doctests.
# Manual tests cover each function instead.
# doctest Towerops.Accounts.Passwords
alias Towerops.Accounts.User
describe "change_user_password/3" do
test "returns an Ecto.Changeset with default empty attrs" do
user = %User{}
assert %Ecto.Changeset{data: %User{}} =
Passwords.change_user_password(user)
end
test "returns an Ecto.Changeset with provided attrs" do
user = %User{email: "test@example.com"}
attrs = %{password: "new-valid-password-123!", password_confirmation: "new-valid-password-123!"}
assert %Ecto.Changeset{data: %User{}} =
Passwords.change_user_password(user, attrs)
end
test "returns an Ecto.Changeset with opts" do
user = %User{email: "test@example.com"}
attrs = %{password: "new-valid-password-123!", password_confirmation: "new-valid-password-123!"}
assert %Ecto.Changeset{} = Passwords.change_user_password(user, attrs, [])
end
end
end

View file

@ -10,6 +10,8 @@ defmodule Towerops.AccountsTest do
alias Towerops.GeoIP.Block alias Towerops.GeoIP.Block
alias Towerops.GeoIP.Location alias Towerops.GeoIP.Location
doctest Accounts
describe "get_user_by_email/1" do describe "get_user_by_email/1" do
test "does not return the user if the email does not exist" do test "does not return the user if the email does not exist" do
refute Accounts.get_user_by_email("unknown@example.com") refute Accounts.get_user_by_email("unknown@example.com")

View file

@ -6,6 +6,8 @@ defmodule Towerops.Admin.AuditLoggerTest do
alias Towerops.Admin.AuditLog alias Towerops.Admin.AuditLog
alias Towerops.Admin.AuditLogger alias Towerops.Admin.AuditLogger
doctest AuditLogger
setup do setup do
actor = user_fixture() actor = user_fixture()
target = user_fixture() target = user_fixture()

View file

@ -7,6 +7,8 @@ defmodule Towerops.AdminTest do
alias Towerops.Admin alias Towerops.Admin
alias Towerops.Organizations.Organization alias Towerops.Organizations.Organization
doctest Admin, except: [delete_user: 3, delete_organization: 3, create_audit_log: 1]
describe "create_audit_log/1" do describe "create_audit_log/1" do
test "creates audit log with valid attributes" do test "creates audit log with valid attributes" do
superuser = user_fixture(%{superuser: true}) superuser = user_fixture(%{superuser: true})

View file

@ -3,6 +3,8 @@ defmodule Towerops.Agents.AgentTokenTest do
alias Towerops.Agents.AgentToken alias Towerops.Agents.AgentToken
doctest AgentToken
describe "build_token/3" do describe "build_token/3" do
test "generates a token with 48 bytes of entropy" do test "generates a token with 48 bytes of entropy" do
org_id = Ecto.UUID.generate() org_id = Ecto.UUID.generate()

View file

@ -17,6 +17,8 @@ defmodule Towerops.Agents.StatsTest do
alias Towerops.Snmp.Sensor alias Towerops.Snmp.Sensor
alias Towerops.Snmp.SensorReading alias Towerops.Snmp.SensorReading
doctest Stats
describe "get_organization_agent_health/1" do describe "get_organization_agent_health/1" do
test "returns empty list for organization with no agents" do test "returns empty list for organization with no agents" do
user = user_fixture() user = user_fixture()

View file

@ -9,6 +9,8 @@ defmodule Towerops.AgentsTest do
alias Towerops.Agents.AgentCache alias Towerops.Agents.AgentCache
alias Towerops.Agents.AgentToken alias Towerops.Agents.AgentToken
doctest Agents
setup do setup do
user = user_fixture() user = user_fixture()

View file

@ -8,6 +8,8 @@ defmodule Towerops.ApiTokensTest do
alias Towerops.ApiTokens alias Towerops.ApiTokens
alias Towerops.ApiTokens.ApiToken alias Towerops.ApiTokens.ApiToken
doctest ApiTokens
describe "create_api_token/1" do describe "create_api_token/1" do
setup do setup do
user = user_fixture() user = user_fixture()

View file

@ -12,6 +12,8 @@ defmodule Towerops.BillingTest do
alias Towerops.Organizations.Organization alias Towerops.Organizations.Organization
alias Towerops.Settings.ApplicationSetting alias Towerops.Settings.ApplicationSetting
doctest Billing
setup do setup do
user = user_fixture() user = user_fixture()
organization = organization_fixture(user.id) organization = organization_fixture(user.id)

View file

@ -7,6 +7,8 @@ defmodule Towerops.Devices.FirmwareTest do
alias Towerops.Devices.Firmware alias Towerops.Devices.Firmware
alias Towerops.Snmp.Device, as: SnmpDevice alias Towerops.Snmp.Device, as: SnmpDevice
doctest Firmware
describe "upsert_firmware_release/1" do describe "upsert_firmware_release/1" do
test "creates a new firmware release" do test "creates a new firmware release" do
attrs = %{ attrs = %{

View file

@ -3,6 +3,8 @@ defmodule Towerops.Devices.MikrotikBackups.DifferTest do
alias Towerops.Devices.MikrotikBackups.Differ alias Towerops.Devices.MikrotikBackups.Differ
doctest Differ
describe "mask_sensitive_data/1" do describe "mask_sensitive_data/1" do
test "masks passwords in user set commands" do test "masks passwords in user set commands" do
config = "/user set admin password=SuperSecret123" config = "/user set admin password=SuperSecret123"

View file

@ -3,6 +3,8 @@ defmodule Towerops.Devices.VersionComparatorTest do
alias Towerops.Devices.VersionComparator alias Towerops.Devices.VersionComparator
doctest VersionComparator
describe "compare/2" do describe "compare/2" do
test "returns :eq for equal versions" do test "returns :eq for equal versions" do
assert VersionComparator.compare("7.14.1", "7.14.1") == :eq assert VersionComparator.compare("7.14.1", "7.14.1") == :eq

View file

@ -6,6 +6,8 @@ defmodule Towerops.EquipmentTest do
alias Towerops.Devices alias Towerops.Devices
alias Towerops.Devices.Device alias Towerops.Devices.Device
doctest Devices
describe "device" do describe "device" do
import Towerops.AccountsFixtures import Towerops.AccountsFixtures

View file

@ -3,6 +3,8 @@ defmodule Towerops.EctoTypes.IpAddressTest do
alias Towerops.EctoTypes.IpAddress alias Towerops.EctoTypes.IpAddress
doctest IpAddress
describe "type/0" do describe "type/0" do
test "returns :string" do test "returns :string" do
assert IpAddress.type() == :string assert IpAddress.type() == :string

View file

@ -3,6 +3,8 @@ defmodule Towerops.EctoTypes.MacAddressTest do
alias Towerops.EctoTypes.MacAddress alias Towerops.EctoTypes.MacAddress
doctest MacAddress
describe "type/0" do describe "type/0" do
test "returns :string" do test "returns :string" do
assert MacAddress.type() == :string assert MacAddress.type() == :string

View file

@ -3,6 +3,8 @@ defmodule Towerops.EctoTypes.SnmpOidTest do
alias Towerops.EctoTypes.SnmpOid alias Towerops.EctoTypes.SnmpOid
doctest SnmpOid
describe "type/0" do describe "type/0" do
test "returns :string" do test "returns :string" do
assert SnmpOid.type() == :string assert SnmpOid.type() == :string

View file

@ -11,6 +11,8 @@ defmodule Towerops.Gaiia.SubscriberMatchingTest do
alias Towerops.Gaiia.SubscriberMatching alias Towerops.Gaiia.SubscriberMatching
alias Towerops.Repo alias Towerops.Repo
doctest SubscriberMatching, except: [normalize_mac: 1]
setup do setup do
user = user_fixture() user = user_fixture()
org = organization_fixture(user.id) org = organization_fixture(user.id)

View file

@ -8,6 +8,8 @@ defmodule Towerops.GaiiaTest do
alias Towerops.Gaiia alias Towerops.Gaiia
alias Towerops.Snmp.Device alias Towerops.Snmp.Device
doctest Gaiia
setup do setup do
user = user_fixture() user = user_fixture()
org = organization_fixture(user.id) org = organization_fixture(user.id)

View file

@ -7,6 +7,8 @@ defmodule Towerops.MobileSessionsTest do
alias Towerops.MobileSessions.MobileSession alias Towerops.MobileSessions.MobileSession
alias Towerops.MobileSessions.QRLoginToken alias Towerops.MobileSessions.QRLoginToken
doctest MobileSessions
defp valid_session_attrs(user) do defp valid_session_attrs(user) do
%{ %{
user_id: user.id, user_id: user.id,

View file

@ -3,6 +3,8 @@ defmodule Towerops.NumericTest do
alias Towerops.Numeric alias Towerops.Numeric
doctest Numeric
describe "parse_integer/1" do describe "parse_integer/1" do
test "returns {:ok, int} for integer" do test "returns {:ok, int} for integer" do
assert {:ok, 42} = Numeric.parse_integer(42) assert {:ok, 42} = Numeric.parse_integer(42)

View file

@ -4,6 +4,8 @@ defmodule Towerops.Organizations.PolicyTest do
alias Towerops.Organizations.Membership alias Towerops.Organizations.Membership
alias Towerops.Organizations.Policy alias Towerops.Organizations.Policy
doctest Policy
describe "can?/3" do describe "can?/3" do
test "owner can do everything" do test "owner can do everything" do
membership = %Membership{role: :owner} membership = %Membership{role: :owner}

View file

@ -9,6 +9,8 @@ defmodule Towerops.Organizations.SubscriptionLimitsTest do
alias Towerops.Organizations.SubscriptionLimits alias Towerops.Organizations.SubscriptionLimits
alias Towerops.Sites alias Towerops.Sites
doctest SubscriptionLimits
describe "device_limit/1" do describe "device_limit/1" do
test "returns 10 for free plan" do test "returns 10 for free plan" do
assert SubscriptionLimits.device_limit("free") == 10 assert SubscriptionLimits.device_limit("free") == 10

View file

@ -7,6 +7,8 @@ defmodule Towerops.OrganizationsTest do
alias Towerops.Organizations alias Towerops.Organizations
alias Towerops.Organizations.Organization alias Towerops.Organizations.Organization
doctest Organizations
describe "organizations" do describe "organizations" do
setup do setup do
user = user_fixture() user = user_fixture()

View file

@ -3,6 +3,8 @@ defmodule Towerops.Settings.ApplicationSettingTest do
alias Towerops.Settings.ApplicationSetting alias Towerops.Settings.ApplicationSetting
doctest ApplicationSetting
describe "parse_value/1" do describe "parse_value/1" do
test "returns nil for nil value" do test "returns nil for nil value" do
setting = %ApplicationSetting{value: nil, value_type: "string"} setting = %ApplicationSetting{value: nil, value_type: "string"}

View file

@ -4,6 +4,8 @@ defmodule Towerops.SettingsTest do
alias Towerops.Settings alias Towerops.Settings
alias Towerops.Settings.ApplicationSetting alias Towerops.Settings.ApplicationSetting
doctest Settings
# Ensure the migration-seeded setting exists (CI may have stale test DB) # Ensure the migration-seeded setting exists (CI may have stale test DB)
setup do setup do
if !Settings.get_setting_record("global_default_cloud_poller_id") do if !Settings.get_setting_record("global_default_cloud_poller_id") do

View file

@ -17,6 +17,8 @@ defmodule Towerops.Snmp.AgentDiscoveryTest do
alias Towerops.Snmp.AgentDiscovery alias Towerops.Snmp.AgentDiscovery
alias Towerops.Snmp.Device, as: DiscoveredDevice alias Towerops.Snmp.Device, as: DiscoveredDevice
doctest AgentDiscovery, except: [process_agent_discovery: 2]
describe "process_agent_discovery/2 — failure paths" do describe "process_agent_discovery/2 — failure paths" do
test "empty oid_values returns :agent_collected_no_data" do test "empty oid_values returns :agent_collected_no_data" do
device = DevicesFixtures.device_fixture() device = DevicesFixtures.device_fixture()

View file

@ -7,6 +7,8 @@ defmodule Towerops.Snmp.ClientTest do
alias Towerops.Snmp.Client alias Towerops.Snmp.Client
alias Towerops.Snmp.SnmpMock alias Towerops.Snmp.SnmpMock
doctest Client
# Set up mocks # Set up mocks
setup :verify_on_exit! setup :verify_on_exit!

View file

@ -13,6 +13,8 @@ defmodule Towerops.Snmp.DiscoveryTest do
alias Towerops.Snmp.Sensor alias Towerops.Snmp.Sensor
alias Towerops.Snmp.SnmpMock alias Towerops.Snmp.SnmpMock
doctest Discovery
setup :verify_on_exit! setup :verify_on_exit!
# Stub get_multiple and get to provide generic fallbacks # Stub get_multiple and get to provide generic fallbacks

View file

@ -3,6 +3,8 @@ defmodule Towerops.Snmp.SensorScaleTest do
alias Towerops.Snmp.SensorScale alias Towerops.Snmp.SensorScale
doctest SensorScale
describe "normalize/2 — temperature" do describe "normalize/2 — temperature" do
test "passes plausible whole-degree readings through unchanged" do test "passes plausible whole-degree readings through unchanged" do
assert SensorScale.normalize("temperature", 36.0) == 36.0 assert SensorScale.normalize("temperature", 36.0) == 36.0

View file

@ -19,6 +19,8 @@ defmodule Towerops.SnmpTest do
alias Towerops.Snmp.WirelessClient alias Towerops.Snmp.WirelessClient
alias Towerops.Snmp.WirelessClientReading alias Towerops.Snmp.WirelessClientReading
doctest Snmp
setup do setup do
user = user_fixture() user = user_fixture()
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id) {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)

View file

@ -7,6 +7,8 @@ defmodule Towerops.Topology.LldpTest do
alias Towerops.Topology.Lldp alias Towerops.Topology.Lldp
alias Towerops.Topology.Lldp.Parser alias Towerops.Topology.Lldp.Parser
doctest Lldp
setup :verify_on_exit! setup :verify_on_exit!
setup do setup do

View file

@ -3,6 +3,8 @@ defmodule Towerops.URLValidatorTest do
alias Towerops.URLValidator alias Towerops.URLValidator
doctest URLValidator
describe "validate/1" do describe "validate/1" do
test "accepts valid https URL" do test "accepts valid https URL" do
assert :ok = URLValidator.validate("https://example.com") assert :ok = URLValidator.validate("https://example.com")

View file

@ -4,6 +4,8 @@ defmodule Towerops.Workers.FirmwareVersionFetcherWorkerTest do
alias Towerops.Devices.Firmware alias Towerops.Devices.Firmware
alias Towerops.Workers.FirmwareVersionFetcherWorker alias Towerops.Workers.FirmwareVersionFetcherWorker
doctest FirmwareVersionFetcherWorker
describe "perform/1" do describe "perform/1" do
test "returns :ok and inserts a release on a valid RSS response" do test "returns :ok and inserts a release on a valid RSS response" do
Req.Test.stub(FirmwareVersionFetcherWorker, fn conn -> Req.Test.stub(FirmwareVersionFetcherWorker, fn conn ->

View file

@ -9,6 +9,8 @@ defmodule ToweropsWeb.Helpers.StatusHelpersTest do
alias Towerops.Sites alias Towerops.Sites
alias ToweropsWeb.Helpers.StatusHelpers alias ToweropsWeb.Helpers.StatusHelpers
doctest StatusHelpers
describe "status_emoji/1" do describe "status_emoji/1" do
test "returns green for nil organization" do test "returns green for nil organization" do
assert StatusHelpers.status_emoji(nil) == "🟢" assert StatusHelpers.status_emoji(nil) == "🟢"

View file

@ -3,6 +3,8 @@ defmodule ToweropsWeb.TimeHelpersTest do
alias ToweropsWeb.TimeHelpers alias ToweropsWeb.TimeHelpers
doctest TimeHelpers
describe "to_user_timezone/2" do describe "to_user_timezone/2" do
test "returns shifted datetime and abbreviation for known timezone" do test "returns shifted datetime and abbreviation for known timezone" do
datetime = ~U[2026-01-15 14:34:00Z] datetime = ~U[2026-01-15 14:34:00Z]

View file

@ -9,6 +9,8 @@ defmodule ToweropsWeb.PermissionsTest do
alias Towerops.Repo alias Towerops.Repo
alias ToweropsWeb.Permissions alias ToweropsWeb.Permissions
doctest Permissions, except: [can?: 3, owner?: 1, admin?: 1]
describe "can?/3 with superuser" do describe "can?/3 with superuser" do
setup do setup do
user = user_fixture(%{is_superuser: true}) user = user_fixture(%{is_superuser: true})