Skip to content

Commit

Permalink
Merge pull request #1078 from jshmrtn/interface_resolve_type_only_object
Browse files Browse the repository at this point in the history
Prevent key :is_type_of not found error on interfaces
  • Loading branch information
tlvenn authored Dec 9, 2021
2 parents b735555 + e09cd6b commit 1ad9f67
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 10 deletions.
4 changes: 1 addition & 3 deletions lib/absinthe/blueprint/schema/interface_type_definition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ defmodule Absinthe.Blueprint.Schema.InterfaceTypeDefinition do
}
end

@interface_types [Schema.ObjectTypeDefinition, Schema.InterfaceTypeDefinition]

def find_implementors(iface, type_defs) do
for %struct{} = obj when struct in @interface_types <- type_defs,
for %Schema.ObjectTypeDefinition{} = obj <- type_defs,
iface.identifier in obj.interfaces,
do: obj.identifier
end
Expand Down
5 changes: 2 additions & 3 deletions lib/absinthe/type/interface.ex
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ defmodule Absinthe.Type.Interface do
def resolve_type(type, obj, env, opts \\ [lookup: true])

def resolve_type(interface, obj, %{schema: schema} = env, opts) do
implementors = Schema.implementors(schema, interface.identifier)

if resolver = Type.function(interface, :resolve_type) do
case resolver.(obj, env) do
nil ->
Expand All @@ -102,7 +100,8 @@ defmodule Absinthe.Type.Interface do
end
else
type_name =
Enum.find(implementors, fn type ->
Schema.implementors(schema, interface.identifier)
|> Enum.find(fn type ->
Absinthe.Type.function(type, :is_type_of).(obj)
end)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ defmodule Absinthe.Schema.Rule.ObjectMustImplementInterfacesTest do
assert %{
named: [:cat, :dog, :user],
favorite_foods: [:cat, :dog, :user],
parented: [:cat, :dog, :named, :user]
parented: [:cat, :dog, :user]
} ==
Schema.__absinthe_interface_implementors__()
end
Expand All @@ -117,22 +117,29 @@ defmodule Absinthe.Schema.Rule.ObjectMustImplementInterfacesTest do
url: String
}
interface Image implements Resource & Node {
type Image implements Resource & Node {
id: ID!
url: String
thumbnail: String
}
"""

def hydrate(%Absinthe.Blueprint.Schema.InterfaceTypeDefinition{}, _) do
{:resolve_type, &__MODULE__.resolve_type/1}
end

def hydrate(_node, _ancestors), do: []

def resolve_type(_), do: false

query do
end
end

test "interfaces are set from sdl" do
assert %{
image: [],
node: [:image, :resource],
node: [:image],
resource: [:image]
} ==
InterfaceImplementsInterfaces.__absinthe_interface_implementors__()
Expand Down
45 changes: 45 additions & 0 deletions test/absinthe/type/interface_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,49 @@ defmodule Absinthe.Type.InterfaceTest do
test "works even when resolve_type returns nil" do
assert_data(%{"namedThing" => %{}}, run(@graphql, Schema))
end

defmodule NestedInterfacesSchema do
use Absinthe.Schema

interface :root do
field :root, :string
end

interface :intermediate do
field :root, :string
field :intermediate, :string

interface :root
end

# Name starts with Z to order it to the back of the list of types
object :z_child do
field :root, :string
field :intermediate, :string
field :child, :string

interface :root
interface :intermediate

is_type_of fn _entry -> true end
end

query do
field :root, :root do
resolve fn _, _, _ -> {:ok, %{}} end
end
end
end

@graphql """
query GetRoot {
root {
__typename
}
}
"""

test "resolved type of nested interfaces" do
assert_data(%{"root" => %{"__typename" => "ZChild"}}, run(@graphql, NestedInterfacesSchema))
end
end

0 comments on commit 1ad9f67

Please sign in to comment.