Skip to content

Commit

Permalink
Merge pull request #4 from mbramson/add-options-validation
Browse files Browse the repository at this point in the history
Add option validation
  • Loading branch information
mbramson authored Nov 15, 2017
2 parents 14eae3b + 2e00d37 commit ab2d3f3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 7 deletions.
16 changes: 11 additions & 5 deletions lib/accomplice.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,28 @@ defmodule Accomplice do
## Examples:
iex> constraints = %{minimum: 2, ideal: 3, maximum: 4}
iex> group(['a', 'b', 'c', 'd', 'e', 'f'], constraints)
[['f', 'e', 'd'], ['c', 'b', 'f']]
[['f', 'e', 'd'], ['c', 'b', 'a']]
"""
@spec group(list(any()), map()) :: list(any()) | :impossible
@spec group(list(any()), map()) :: list(any()) | :impossible | {:error, atom()}
def group([], _options), do: []
def group(elements, %{minimum: _, ideal: _, maximum: _} = options) do
group([], elements, options)
case options |> validate_options do
{:error, message} -> {:error, message}
options -> group([], elements, options)
end
end
def group(elements, options) do
group_simple([], elements, options)
case options |> validate_options do
{:error, message} -> {:error, message}
options -> group_simple([], elements, options)
end
end

@doc """
Same as `group/2`, but it shuffles the elements first so that the elements in
the returned grouping are in random order.
"""
@spec shuffled_group(list(any()), map()) :: list(any()) | :impossible
@spec shuffled_group(list(any()), map()) :: list(any()) | :impossible | {:error, atom()}
def shuffled_group(elements, options) do
elements |> Enum.shuffle |> group(options)
end
Expand Down
21 changes: 20 additions & 1 deletion lib/accomplice_helpers.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
defmodule Accomplice.Helpers do
@moduledoc false

@doc false
@spec validate_options(map()) :: map() | {:error, atom()}
def validate_options(%{minimum: min, ideal: ideal, maximum: max} = options) do
cond do
min < 1 || max < 1 || ideal < 1 -> {:error, :size_constraint_below_one}
min > max -> {:error, :minimum_above_maximum}
ideal < min || ideal > max -> {:error, :ideal_not_between_min_and_max}
true -> options
end
end
def validate_options(%{minimum: min, maximum: max} = options) do
cond do
min < 1 || max < 1 -> {:error, :size_constraint_below_one}
min > max -> {:error, :minimum_above_maximum}
true -> options
end
end
def validate_options(options) when is_map(options), do: {:error, :missing_size_constraint}
def validate_options(_), do: {:error, :options_is_not_map}

@doc false
@spec pop(list(any())) :: {any(), list(any())} | {nil, list(any())}
def pop([]), do: {nil, []}
Expand Down Expand Up @@ -43,5 +63,4 @@ defmodule Accomplice.Helpers do
defp add_actions(ungrouped) do
for _ <- 1..length(ungrouped), do: :add
end

end
35 changes: 34 additions & 1 deletion test/accomplice_helpers_test.exs
Original file line number Diff line number Diff line change
@@ -1,10 +1,43 @@
defmodule AccompliceHelpersTest do
defmodule AccompliceHelpersTest do
use ExUnit.Case
use Quixir

alias Accomplice.Helpers
import OrderInvariantCompare # for <~> operator

describe "validate_options/1" do
test "options must be map" do
assert {:error, :options_is_not_map} == Helpers.validate_options([])
assert {:error, :options_is_not_map} == Helpers.validate_options(nil)
assert {:error, :options_is_not_map} == Helpers.validate_options("")
end

test "missing size constraints is invalid" do
assert {:error, :missing_size_constraint} == Helpers.validate_options(%{})
assert {:error, :missing_size_constraint} == Helpers.validate_options(%{minimum: 1})
assert {:error, :missing_size_constraint} == Helpers.validate_options(%{maximum: 1})
end

test "size constraints must be greater than zero" do
assert {:error, :size_constraint_below_one} == Helpers.validate_options(%{minimum: 0, maximum: 1})
assert {:error, :size_constraint_below_one} == Helpers.validate_options(%{minimum: 1, maximum: 0})
assert {:error, :size_constraint_below_one} == Helpers.validate_options(%{minimum: 1, ideal: 0, maximum: 1})
assert {:error, :size_constraint_below_one} == Helpers.validate_options(%{minimum: 1, ideal: 1, maximum: 0})
assert {:error, :size_constraint_below_one} == Helpers.validate_options(%{minimum: 0, ideal: 1, maximum: 1})
assert %{} = Helpers.validate_options(%{minimum: 1, maximum: 1})
assert %{} = Helpers.validate_options(%{minimum: 1, ideal: 1, maximum: 1})
end

test "min cannot be greater than max" do
assert {:error, :minimum_above_maximum} == Helpers.validate_options(%{minimum: 2, maximum: 1})
end

test "ideal must be between min and max" do
assert {:error, :ideal_not_between_min_and_max} == Helpers.validate_options(%{minimum: 2, ideal: 1, maximum: 3})
assert {:error, :ideal_not_between_min_and_max} == Helpers.validate_options(%{minimum: 2, ideal: 4, maximum: 3})
end
end

describe "pop/1" do
test "returns the head and tail if the list contains elements" do
assert Helpers.pop([1,2,3,4]) == {1, [2,3,4]}
Expand Down

0 comments on commit ab2d3f3

Please sign in to comment.