defmodule ExCheck.Reporter.Json do
@moduledoc false
# Strict, single valid JSON object describing the whole run. For tools/scripts;
# pairs naturally with `--output PATH`. Failed checks carry their (escaped) output.
@behaviour ExCheck.Reporter
alias ExCheck.JSON
alias ExCheck.Reporter
@impl true
def report(results, total_duration, opts) do
Reporter.emit(JSON.encode(build(results, total_duration)), opts)
end
@doc false
def build(results, total_duration) do
failed = Enum.count(results, &match?({:error, _, _}, &1))
%{
status: if(failed == 0, do: "ok", else: "error"),
duration_s: total_duration,
passed: Enum.count(results, &match?({:ok, _, _}, &1)),
failed: failed,
skipped: Enum.count(results, &match?({:skipped, _, _}, &1)),
checks: results |> Enum.sort_by(&Reporter.summary_order/1) |> Enum.map(&check/1)
}
end
defp check({:ok, {name, cmd, _}, {code, _, duration}}) do
{name, app} = Reporter.split_name(name)
%{
name: name,
app: app,
status: "ok",
command: command(cmd),
exit_code: code,
duration_s: duration
}
end
defp check({:error, {name, cmd, _}, {code, output, duration}}) do
{name, app} = Reporter.split_name(name)
%{
name: name,
app: app,
status: "error",
command: command(cmd),
exit_code: code,
duration_s: duration,
output: Reporter.strip_ansi(output)
}
end
defp check({:skipped, name, reason}) do
{name, app} = Reporter.split_name(name)
%{name: name, app: app, status: "skipped", reason: Reporter.skip_reason_string(reason)}
end
defp command(cmd), do: cmd |> List.wrap() |> Enum.join(" ")
end