defmodule SmartCity.TestHelper do @moduledoc """ Common utilities for use in test cases """ # no_return() is because eventually() catches ExUnit.AssertionError @type asserting_function :: (() -> no_return() | boolean()) @doc """ Helper function for asynchronous testing - Repeats the given block (zero-arity function) until a timeout occurs or it returns a truthy value. - Catches ExUnit assertions and continues to try the block - Re-runs block one last time if it times out so assertions are run and throw helpful diffs, etc. """ @spec eventually(asserting_function(), integer, integer) :: :ok | none() def eventually(function, dwell \\ 2_000, max_tries \\ 5) do case Patiently.wait_for( wrap_assertions_as_falsey(function), dwell: dwell, max_tries: max_tries ) do :ok -> :ok _ -> function.() end end defp wrap_assertions_as_falsey(function) do fn -> try do function.() rescue ExUnit.AssertionError -> false end end end end