towerops/test/mix/tasks/unused_test.exs
2026-06-15 11:15:46 -05:00

77 lines
2.6 KiB
Elixir

defmodule Mix.Tasks.UnusedTest do
# Mutates `Mix.shell/1` globally; cannot run concurrently with other tests
# that capture Mix shell output.
use ExUnit.Case, async: false
alias Mix.Tasks.Unused
setup do
previous_shell = Mix.shell()
Mix.shell(Mix.Shell.Process)
on_exit(fn -> Mix.shell(previous_shell) end)
:ok
end
describe "run/1" do
test "emits human-readable text output by default and returns :ok" do
assert :ok = Unused.run([])
# The task either reports "no unused" or a header — both go through
# `Mix.shell().info/1` which the Process shell captures as messages.
assert_received_info_matching(fn msg ->
msg =~ "unused public functions" or msg =~ "No unused public functions"
end)
end
test "honours --format json by emitting valid JSON" do
assert :ok = Unused.run(["--format", "json"])
json = collect_info_messages()
# The task always emits exactly one JSON document via Mix.shell().info/1.
decoded = Jason.decode!(json)
refute decoded == []
for entry <- decoded do
assert byte_size(entry["module"]) > 0
assert byte_size(entry["function"]) > 0
assert is_integer(entry["arity"])
assert byte_size(entry["file"]) > 0
assert is_integer(entry["line"])
end
end
test "honours --only by filtering output to a module prefix" do
# No assertion on contents — just exercise the apply_only/2 branch.
assert :ok = Unused.run(["--only", "Towerops.NoSuchPrefix"])
assert_received_info_matching(fn msg ->
msg =~ "No unused public functions"
end)
end
test "honours --skip by removing modules under a prefix" do
# Just exercise the apply_skip branch — output depends on the build env.
assert :ok = Unused.run(["--skip", "Towerops"])
msg = collect_info_messages()
# Either we get the "found N" header or the "no unused" message.
assert msg =~ ~r/unused public functions|No unused public functions/
end
end
# ──────────────────────────────────────────────────────────────────────
# Helpers
defp collect_info_messages(acc \\ "") do
receive do
{:mix_shell, :info, [msg]} -> collect_info_messages(acc <> msg <> "\n")
after
0 -> String.trim(acc)
end
end
defp assert_received_info_matching(predicate) do
msg = collect_info_messages()
assert predicate.(msg), "no Mix shell info message matched the predicate. Got: #{inspect(msg)}"
end
end