Current section
Files
Jump to
Current section
Files
lib/enum_a.ex
defmodule FlowAssertions.EnumA do
use FlowAssertions.Define
alias FlowAssertions.Messages
@moduledoc """
Assertions that apply to Enums.
"""
@doc """
Assert that an Enum has only a single element.
```
[1] |> assert_singleton # passes
[ ] |> assert_singleton # fails
%{a: 1} |> assert_singleton # passes
%{a: 1, b: 2} |> assert_singleton # fails
```
"""
defchain assert_singleton(enum),
do: singleton_or_flunk(enum)
@doc """
Returns the content element of what must be a single-element Enum.
'''
[1] |> singleton_content # 1
[ ] |> singleton_content # fails
%{a: 1} |> singleton_content # the tuple {:a, 1}
5 |> singleton_content # faila
"""
def singleton_content(enum),
do: singleton_or_flunk(enum)
@doc """
Assert that an Enum has no elements."
```
[] |> assert_empty # true
%{} |> assert_empty # true
```
"""
defchain assert_empty(value_to_check) do
assert_enumerable(value_to_check)
elaborate_assert(Enum.empty?(value_to_check),
Messages.expected_no_element,
left: value_to_check)
end
@doc """
If the value doesn't implement `Enumerable` produces an assertion exception.
The output is more friendly than a `Protocol.UndefinedError`. So, for example,
the other assertions in this module start with this assertion.
defchain assert_empty(value_to_check) do
assert_enumerable(value_to_check)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
elaborate_assert(Enum.empty?(value_to_check),
Messages.expected_no_element,
left: value_to_check)
end
"""
defchain assert_enumerable(value_to_check) do
elaborate_assert(Enumerable.impl_for(value_to_check),
Messages.not_enumerable, left: value_to_check)
end
# ----------------------------------------------------------------------------
defp singleton_or_flunk(enum) do
assert_enumerable(enum)
case Enum.into(enum, []) do
[x] -> x
left -> elaborate_flunk(Messages.expected_1_element, left: left)
end
end
end