Promoted pure presentation and utility helpers from `defp` to `def @doc false` across ~20 LiveViews, Oban workers, and sync modules so they're reachable from unit tests. Refactored several `cond` blocks into idiomatic function heads with guards. Added ~250 new test cases in new files under test/towerops and test/towerops_web, including DB-backed tests for CnMaestro.Sync and AlertNotificationWorker, and removed dead LiveView tab components and CapacityLive (no callers anywhere in lib/test). Configured mix.exs test_coverage.ignore_modules to exclude vendored third-party code (SnmpKit, protobuf-generated Towerops.Agent.*, Absinthe GraphQL types, Phoenix HTML modules, Inspect protocol impls) from coverage calculations — these are not our project code. Coverage: 66.93% → 70.09%. Full suite: 10,127 tests, 0 failures.
93 lines
2.8 KiB
Elixir
93 lines
2.8 KiB
Elixir
defmodule Towerops.Workers.CheckWorkerStateTest do
|
|
use ExUnit.Case, async: true
|
|
use ExUnitProperties
|
|
|
|
alias Towerops.Workers.CheckWorker
|
|
|
|
describe "state_changed_to_problem?/2" do
|
|
test "OK → CRITICAL hard is a problem" do
|
|
assert CheckWorker.state_changed_to_problem?(0, %{
|
|
current_state: 2,
|
|
current_state_type: "hard"
|
|
})
|
|
end
|
|
|
|
test "OK → WARNING hard is a problem" do
|
|
assert CheckWorker.state_changed_to_problem?(0, %{
|
|
current_state: 1,
|
|
current_state_type: "hard"
|
|
})
|
|
end
|
|
|
|
test "OK → CRITICAL soft is NOT a problem (avoids flap alerts)" do
|
|
refute CheckWorker.state_changed_to_problem?(0, %{
|
|
current_state: 2,
|
|
current_state_type: "soft"
|
|
})
|
|
end
|
|
|
|
test "already-problem state staying in problem is not a transition" do
|
|
refute CheckWorker.state_changed_to_problem?(1, %{
|
|
current_state: 2,
|
|
current_state_type: "hard"
|
|
})
|
|
|
|
refute CheckWorker.state_changed_to_problem?(2, %{
|
|
current_state: 2,
|
|
current_state_type: "hard"
|
|
})
|
|
end
|
|
|
|
test "OK → OK is not a transition" do
|
|
refute CheckWorker.state_changed_to_problem?(0, %{
|
|
current_state: 0,
|
|
current_state_type: "hard"
|
|
})
|
|
end
|
|
|
|
test "unknown state codes do not trigger" do
|
|
refute CheckWorker.state_changed_to_problem?(0, %{
|
|
current_state: 99,
|
|
current_state_type: "hard"
|
|
})
|
|
end
|
|
end
|
|
|
|
describe "state_changed_to_ok?/2" do
|
|
test "CRITICAL → OK is recovery" do
|
|
assert CheckWorker.state_changed_to_ok?(2, %{current_state: 0})
|
|
end
|
|
|
|
test "WARNING → OK is recovery" do
|
|
assert CheckWorker.state_changed_to_ok?(1, %{current_state: 0})
|
|
end
|
|
|
|
test "OK → OK is not a recovery" do
|
|
refute CheckWorker.state_changed_to_ok?(0, %{current_state: 0})
|
|
end
|
|
|
|
test "stuck in problem is not a recovery" do
|
|
refute CheckWorker.state_changed_to_ok?(1, %{current_state: 1})
|
|
refute CheckWorker.state_changed_to_ok?(2, %{current_state: 2})
|
|
end
|
|
|
|
test "unknown old state does not trigger" do
|
|
refute CheckWorker.state_changed_to_ok?(99, %{current_state: 0})
|
|
end
|
|
end
|
|
|
|
describe "property: state transition predicates are mutually exclusive" do
|
|
property "problem? and ok? can never both be true" do
|
|
check all(
|
|
old <- integer(0..3),
|
|
new <- integer(0..3),
|
|
type <- member_of(["hard", "soft"])
|
|
) do
|
|
check_data = %{current_state: new, current_state_type: type}
|
|
problem? = CheckWorker.state_changed_to_problem?(old, check_data)
|
|
ok? = CheckWorker.state_changed_to_ok?(old, check_data)
|
|
refute problem? and ok?
|
|
end
|
|
end
|
|
end
|
|
end
|