lib/matchers/one_of.ex

defmodule Matcher.OneOf do
  defstruct [:expecteds]

  import Matcher.Errors
  alias Matcher.Utils

  defimpl Matcher.Protocol do
    def match(%{expecteds: expecteds}, actual, context) do
      matched? =
        expecteds
        |> Enum.map(fn e ->
          Matcher.match(e, actual, context)
        end)
        |> Enum.find(&Utils.matched?/1)

      if matched? do
        {:ok, nil}
      else
        error(context, message: "one of: #{mismatched(actual)} did not match any alternative")
      end
    end
  end
end