towerops/test/towerops/profiles/profile_watcher_test.exs

122 lines
3.8 KiB
Elixir

defmodule FakeReloader do
@moduledoc false
def reload, do: {:ok, 0}
end
defmodule Towerops.Profiles.ProfileWatcherTest do
use ExUnit.Case, async: true
alias Towerops.Profiles.ProfileWatcher
describe "yaml_file?/1" do
test "returns true for .yaml files" do
assert ProfileWatcher.yaml_file?("path/to/profile.yaml")
end
test "returns true for .yml files" do
assert ProfileWatcher.yaml_file?("path/to/profile.yml")
end
test "returns false for other extensions" do
refute ProfileWatcher.yaml_file?("profile.json")
refute ProfileWatcher.yaml_file?("profile.txt")
refute ProfileWatcher.yaml_file?("profile")
end
test "raises on nil" do
assert_raise FunctionClauseError, fn ->
apply(ProfileWatcher, :yaml_file?, [nil])
end
end
end
describe "should_reload?/1" do
test "returns true for :created event" do
assert ProfileWatcher.should_reload?([:created])
end
test "returns true for :modified event" do
assert ProfileWatcher.should_reload?([:modified])
end
test "returns true for :removed event" do
assert ProfileWatcher.should_reload?([:removed])
end
test "returns true for :renamed event" do
assert ProfileWatcher.should_reload?([:renamed])
end
test "returns true when any event triggers reload" do
assert ProfileWatcher.should_reload?([:accessed, :modified])
end
test "returns false for non-reload events" do
refute ProfileWatcher.should_reload?([:accessed])
refute ProfileWatcher.should_reload?([:attrs_changed])
end
test "returns false for empty list" do
refute ProfileWatcher.should_reload?([])
end
test "returns false for non-list input" do
refute ProfileWatcher.should_reload?(nil)
refute ProfileWatcher.should_reload?(:created)
refute ProfileWatcher.should_reload?(%{})
end
end
describe "start_link/1" do
test "starts the GenServer under its registered name" do
# Stop the dev-only auto-started instance if any so we get a clean start
_ = if pid = Process.whereis(ProfileWatcher), do: GenServer.stop(pid, :normal)
assert {:ok, pid} = ProfileWatcher.start_link([])
assert Process.alive?(pid)
GenServer.stop(pid, :normal)
end
end
describe "GenServer init/handle_info" do
test "init/1 returns :ok with a state map" do
assert {:ok, _state} = ProfileWatcher.init([])
end
test "handles :stop file_event without crashing" do
assert {:noreply, %{}} =
ProfileWatcher.handle_info({:file_event, self(), :stop}, %{})
end
test "ignores file events for non-yaml files" do
msg = {:file_event, self(), {"foo.txt", [:modified]}}
assert {:noreply, %{}} = ProfileWatcher.handle_info(msg, %{})
end
test "ignores file events when no reload-relevant event is present" do
msg = {:file_event, self(), {"profile.yaml", [:accessed]}}
assert {:noreply, %{}} = ProfileWatcher.handle_info(msg, %{})
end
test "yaml file event with reload trigger doesn't crash and preserves state" do
# Stub out the reloader so we don't pay the full YamlProfiles.reload
# cost (loads ~hundreds of YAML files from disk) just to verify the
# handle_info branch.
previous = Application.get_env(:towerops, :profile_reloader)
Application.put_env(:towerops, :profile_reloader, FakeReloader)
on_exit(fn ->
if previous,
do: Application.put_env(:towerops, :profile_reloader, previous),
else: Application.delete_env(:towerops, :profile_reloader)
end)
msg = {:file_event, self(), {"priv/profiles/test.yaml", [:modified]}}
ExUnit.CaptureLog.capture_log(fn ->
assert {:noreply, %{watcher_pid: nil}} =
ProfileWatcher.handle_info(msg, %{watcher_pid: nil})
end)
end
end
end