Repository: keathley/norm
Pull request #10 (2019-09-06 01:08:12)

add bitstring, boolean, refactor, and tests
Hi @keathley.

Thought I'd try and follow up with support for a few more predicates in the generators. This adds bitstring, boolean, some extra tests on existing features, and refactors now that there's a longer list.

Let me know your thoughts!


Patch:
diff --git a/lib/norm/spec.ex b/lib/norm/spec.ex
index 7a8abac..8362211 100644
--- a/lib/norm/spec.ex
+++ b/lib/norm/spec.ex
@@ -76,23 +76,37 @@ defmodule Norm.Spec do
 
   if Code.ensure_loaded?(StreamData) do
     defimpl Norm.Generatable do
+      @supported_primitives [
+        :is_atom,
+        :is_binary,
+        :is_bitstring,
+        :is_boolean,
+        :is_float,
+        :is_integer
+      ]
+
       def gen(%{generator: gen, predicate: pred}) do
-        case gen do
-          :is_integer ->
-            {:ok, StreamData.integer()}
+        predicate =
+          Enum.find(@supported_primitives, {:error, pred}, fn predicate ->
+            gen == predicate
+          end)
+
+        generator_from_predicate(predicate)
+      end
 
-          :is_float ->
-            {:ok, StreamData.float()}
+      defp generator_from_predicate({:error, predicate}), do: {:error, predicate}
 
-          :is_binary ->
-            {:ok, StreamData.binary()}
+      defp generator_from_predicate(:is_atom),
+        do: {:ok, apply(StreamData, :atom, [:alphanumeric])}
 
-          :is_atom ->
-            {:ok, StreamData.atom(:alphanumeric)}
+      defp generator_from_predicate(predicate) do
+        data_type =
+          predicate
+          |> Atom.to_string()
+          |> String.slice(3..-1)
+          |> String.to_atom()
 
-          _ ->
-            {:error, pred}
-        end
+        {:ok, apply(StreamData, data_type, [])}
       end
     end
   end


Test patch:
diff --git a/test/norm/generators/primitives_test.exs b/test/norm/generators/primitives_test.exs
index fd233e2..57d3169 100644
--- a/test/norm/generators/primitives_test.exs
+++ b/test/norm/generators/primitives_test.exs
@@ -2,13 +2,54 @@ defmodule Norm.Generators.GeneratorTest do
   use ExUnit.Case, async: true
   import Norm
 
-  alias Norm.Generator
-
   describe "generates primitive types" do
+    test "generates values from spec(is_atom())" do
+      spec = spec(is_atom())
+      output = generate_value_for_spec(spec)
+
+      assert is_atom(output)
+    end
+
+    test "generates values from spec(is_boolean())" do
+      spec = spec(is_boolean())
+      output = generate_value_for_spec(spec)
+
+      assert is_boolean(output)
+    end
+
+    test "generates values from spec(is_binary())" do
+      spec = spec(is_binary())
+      output = generate_value_for_spec(spec)
+
+      assert is_binary(output)
+    end
+
+    test "generates values from spec(is_bitstring())" do
+      spec = spec(is_bitstring())
+      output = generate_value_for_spec(spec)
+
+      assert is_bitstring(output)
+    end
+
     test "generates values from spec(is_float())" do
-      [output | _] = is_float() |> spec() |> gen() |> Enum.take(1)
+      spec = spec(is_float())
+      output = generate_value_for_spec(spec)
 
       assert is_float(output)
     end
+
+    test "generates values from spec(is_integer())" do
+      spec = spec(is_integer())
+      output = generate_value_for_spec(spec)
+
+      assert is_integer(output)
+    end
+  end
+
+  defp generate_value_for_spec(spec) do
+    spec
+    |> gen()
+    |> Enum.take(1)
+    |> hd()
   end
 end