defmodule DiscUnionTest.Types do
  use ExUnit.Case, async: true
  alias Code.Typespec

  test "autogenerated types for discriminated union" do
    types = types(ExampleDU) |> Enum.sort
    correct_types = [
      "@type t() :: %ExampleDU{case: Asd | {Qwe, any()} | {Rty, integer(), atom()}}",
    ] |> Enum.sort
    assert types == correct_types

    types = types(ExampleDUa) |> Enum.sort
    correct_types = [
      "@type t() :: %ExampleDUa{case: :asd | {:qwe, any()} | {:rty, integer(), atom()}}",
    ] |> Enum.sort
    assert types == correct_types
  end


  # helper functions

  def types(module) when is_atom(module) do
    _ = case Typespec.fetch_types(module) do
          {:ok, types} ->
            Enum.map(types, &print_type/1)
          :error  -> []
        end
  end

  defp print_type({:opaque, type}) do
    {:::, _, [ast, _]} = Typespec.type_to_quoted(type)
    "@opaque #{Macro.to_string(ast)}"
  end

  defp print_type({kind, type}) do
    ast = Typespec.type_to_quoted(type)
    "@#{kind} #{Macro.to_string(ast)}"
  end
end
