absinthe-graphql / absinthe

The GraphQL toolkit for Elixir
http://absinthe-graphql.org
Other
4.29k stars 525 forks source link

can't seem to support a nullable union type #1046

Open atomkirk opened 3 years ago

atomkirk commented 3 years ago

Environment

Expected behavior

Given this schema:

  object :form_field do
    field :value, :value_union do
      resolve(fn field, _, _ ->
        case field[:value] do
          bool when is_boolean(bool) -> {:ok, %{boolean: bool}}
          str -> {:ok, %{string: str}}
          _ -> {:ok, nil}
        end
      end)
    end
  end

  union :value_union do
    types([:string_value, :boolean_value])

    resolve_type(fn
      bool, _ when is_boolean(bool) -> :boolean_value
      str, _  -> :string_value
    end)
  end

  object :string_value do
    field(:string, non_null(:string))
  end

  object :boolean_value do
    field(:boolean, non_null(:boolean))
  end

I would expect the union resolve_type to not get called if {:ok, nil} is returned, but it is called…

Actual behavior

It returns an error that string_value.string returns nil from a non-nullable type. (it shouldn't get that far, all of value should be null

And, if I return nil from resolve_type, it returns value: {} in the response. Basically, a nullable union field doesn't seem to work…

benwilson512 commented 3 years ago

I need to double check with the spec, but this does seem like a bug. I would expect that returning nil from a resolver would simply prevent the union resolve_type from running at all and go ahead with a nil value. Will investigate.

maartenvanvliet commented 2 years ago

Was not able to reproduce this.

In the example the resolve_type function won't match since the first argument is the returned value of the resolver, so %{boolean: bool}, %{string: str} or nil and not a scalar boolean or string. The behaviour seen likely stems from that.

When nil is returned by the resolver, the final result has nil in the response so this is correct.