test: add coverage for ExpiredBanCleanupWorker

7 tests exercising perform/1: expired/active/permanent ban handling,
mixed scenarios, empty database, and PubSub broadcast behavior.
This commit is contained in:
Graham McIntire 2026-02-11 16:25:33 -06:00
parent dd0b29aefb
commit 030ed43708
No known key found for this signature in database
2 changed files with 114 additions and 0 deletions

View file

@ -1,6 +1,12 @@
CHANGELOG - towerops-web
========================
2026-02-11 - test: add 100% coverage for ExpiredBanCleanupWorker
- File: test/towerops/workers/expired_ban_cleanup_worker_test.exs (new)
Added 7 tests covering perform/1: expired ban deletion, active ban preservation,
permanent ban preservation, mixed scenarios, empty database, PubSub broadcast
on deletion, and no broadcast when nothing deleted.
2026-02-11 - fix: handle "null" string values in SNMP parsing
- File: lib/towerops/snmp/profiles/base.ex (parse_integer/1, parse_float/1)
Added explicit handling for "null" string values before attempting integer/float

View file

@ -0,0 +1,108 @@
defmodule Towerops.Workers.ExpiredBanCleanupWorkerTest do
use Towerops.DataCase, async: false
alias Towerops.Security.IpBlock
alias Towerops.Workers.ExpiredBanCleanupWorker
describe "perform/1" do
test "deletes expired temporary bans" do
insert_ip_block(%{
ip_address: "10.0.0.1",
banned_until: DateTime.add(DateTime.utc_now(), -60, :second)
})
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
assert [] = Repo.all(IpBlock)
end
test "keeps active temporary bans" do
block =
insert_ip_block(%{
ip_address: "10.0.0.2",
banned_until: DateTime.add(DateTime.utc_now(), 300, :second)
})
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
assert Repo.get(IpBlock, block.id)
end
test "keeps permanent bans" do
block =
insert_ip_block(%{
ip_address: "10.0.0.3",
offense_count: 3,
banned_until: nil
})
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
assert Repo.get(IpBlock, block.id)
end
test "deletes only expired bans among mixed records" do
expired =
insert_ip_block(%{
ip_address: "10.0.0.10",
banned_until: DateTime.add(DateTime.utc_now(), -120, :second)
})
active =
insert_ip_block(%{
ip_address: "10.0.0.11",
banned_until: DateTime.add(DateTime.utc_now(), 600, :second)
})
permanent =
insert_ip_block(%{
ip_address: "10.0.0.12",
offense_count: 3,
banned_until: nil
})
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
refute Repo.get(IpBlock, expired.id)
assert Repo.get(IpBlock, active.id)
assert Repo.get(IpBlock, permanent.id)
end
test "returns :ok when no records exist" do
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
end
test "broadcasts to PubSub when bans are deleted" do
Phoenix.PubSub.subscribe(Towerops.PubSub, "security:blocks")
insert_ip_block(%{
ip_address: "10.0.0.20",
banned_until: DateTime.add(DateTime.utc_now(), -60, :second)
})
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
assert_receive :blocks_updated
end
test "does not broadcast to PubSub when nothing is deleted" do
Phoenix.PubSub.subscribe(Towerops.PubSub, "security:blocks")
assert :ok = ExpiredBanCleanupWorker.perform(%Oban.Job{args: %{}})
refute_receive :blocks_updated
end
end
defp insert_ip_block(attrs) do
defaults = %{
offense_count: 1,
last_violation_at: DateTime.utc_now(),
reason: "test ban"
}
%IpBlock{}
|> IpBlock.changeset(Map.merge(defaults, attrs))
|> Repo.insert!()
end
end