defmodule NLdoc.Test.Logs do @moduledoc """ This module helps with capturing log output in tests. """ @type log() :: {time :: String.t(), metadata :: metadata(), level :: String.t(), message :: String.t()} @type metadata() :: %{String.t() => String.t()} @doc """ For use with &ExUnit.CaptureLog.capture_log/2. ## Examples iex> NLdoc.Test.Logs.opts() [colors: [enabled: false], format: "$time $metadata[$level] $message\\n", metadata: :all] iex> NLdoc.Test.Logs.opts(format: "$message") [colors: [enabled: false], metadata: :all, format: "$message"] iex> NLdoc.Test.Logs.opts(level: :info) [colors: [enabled: false], format: "$time $metadata[$level] $message\\n", metadata: :all, level: :info] """ @spec opts(keyword()) :: keyword() def opts(opts \\ []) when is_list(opts) do [ colors: [enabled: false], format: "$time $metadata[$level] $message\n", metadata: :all ] |> Keyword.merge(opts) end @doc """ For parsing multiple lines of log. ## Examples iex> "23:09:04.123 line=114 file=lib/ex_unit/capture_log.ex [info] hello this is a test\\n" <> ...> "22:08:03.193 line=124 file=lib/ex_unit/capture_log.ex [error] Lorem, ipsum, dolor sit.\\n" ...> |> NLdoc.Test.Logs.parse!() [ { "23:09:04.123", %{"line" => "114", "file" => "lib/ex_unit/capture_log.ex"}, "info", "hello this is a test" }, { "22:08:03.193", %{"line" => "124", "file" => "lib/ex_unit/capture_log.ex"}, "error", "Lorem, ipsum, dolor sit." } ] iex> NLdoc.Test.Logs.parse!("Not following format.") ** (RuntimeError) Log does not follow format: "Not following format." """ def parse!(log) when is_binary(log) do log |> String.split("\n", trim: true) |> Enum.map(&parse_line!/1) end @doc """ Parsing a single line of log. ## Examples iex> "23:09:04.123 line=114 file=lib/ex_unit/capture_log.ex [info] hello this is a test" ...> |> NLdoc.Test.Logs.parse_line!() {"23:09:04.123", %{"line" => "114", "file" => "lib/ex_unit/capture_log.ex"}, "info", "hello this is a test"} iex> NLdoc.Test.Logs.parse_line!("Not following format.") ** (RuntimeError) Log does not follow format: "Not following format." """ @spec parse_line!(log :: String.t()) :: log() def parse_line!(log) when is_binary(log) do regex = ~r/^(?