defmodule Spyanator.Assertions.Calls.Chains do @moduledoc """ functional chains that can be used to inspect how many times a tracked function was called """ alias Spyanator.Assertions.Calls @doc """ Used to make an assertion on the arguments that a tracked function received """ @spec with_arguments(false) :: false def with_arguments(false), do: false @doc """ Used to make an assertion on the arguments that a tracked function received """ @spec with_arguments(%Calls{}, [any]) :: false | %Calls{} def with_arguments(%Calls{call_count: count, module: module, func_name: func_name} = calls, expected_arguments) do actual_arguments = Agent.get(Spyanator.get_pid_for_module(module), fn(state) -> Map.get(state, func_name) |> Map.get(:arguments) end) called_with_args_at_least_once = actual_arguments |> Tuple.to_list |> Enum.member?(expected_arguments) to_return = calls |> Map.put(:expected_arguments, expected_arguments) |> Map.put(:actual_arguments, actual_arguments) count > 0 && called_with_args_at_least_once && to_return end @doc """ Used to start a functional chain that inspects the calls to a tracked function """ @spec received(module, atom) :: boolean | %Calls{call_count: pos_integer} def received(spy_module, func_name) do call_count = Agent.get(Spyanator.get_pid_for_module(spy_module), fn(state) -> Map.get(state, func_name) |> Map.get(:calls) end) call_count > 0 && %Calls{call_count: call_count, module: spy_module, func_name: func_name} end end