Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make results nullable again if root level errors are enabled #114

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions lib/resource/resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,7 @@ defmodule AshGraphql.Resource do
module: schema,
name: to_string(mutation.name),
description: Ash.Resource.Info.action(resource, mutation.action).description,
type: %Absinthe.Blueprint.TypeReference.NonNull{
of_type: String.to_atom("#{mutation.name}_result")
},
type: mutation_result_type(mutation.name, api),
__reference__: ref(__ENV__)
}
end
Expand Down Expand Up @@ -656,9 +654,7 @@ defmodule AshGraphql.Resource do
module: schema,
name: to_string(mutation.name),
description: Ash.Resource.Info.action(resource, mutation.action).description,
type: %Absinthe.Blueprint.TypeReference.NonNull{
of_type: String.to_atom("#{mutation.name}_result")
},
type: mutation_result_type(mutation.name, api),
__reference__: ref(__ENV__)
}

Expand Down Expand Up @@ -710,13 +706,18 @@ defmodule AshGraphql.Resource do
module: schema,
name: to_string(mutation.name),
description: Ash.Resource.Info.action(resource, mutation.action).description,
type: %Absinthe.Blueprint.TypeReference.NonNull{
of_type: String.to_atom("#{mutation.name}_result")
},
type: mutation_result_type(mutation.name, api),
__reference__: ref(__ENV__)
}
end

defp mutation_result_type(mutation_name, api) do
type = String.to_atom("#{mutation_name}_result")
root_level_errors? = AshGraphql.Api.Info.root_level_errors?(api)

maybe_wrap_non_null(type, not root_level_errors?)
end

defp mutation_args(%{identity: false} = mutation, resource, schema) do
mutation_read_args(mutation, resource, schema)
end
Expand Down
70 changes: 62 additions & 8 deletions test/errors_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ defmodule AshGraphql.ErrorsTest do
end

test "errors can be configured to be shown in the root" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api, graphql: [root_level_errors?: true])

resp =
"""
mutation CreatePost($input: CreatePostInput) {
Expand All @@ -27,7 +25,7 @@ defmodule AshGraphql.ErrorsTest do
}
}
"""
|> Absinthe.run(AshGraphql.Test.Schema,
|> Absinthe.run(AshGraphql.Test.RootLevelErrorsSchema,
variables: %{
"input" => %{
"text" => "foobar",
Expand All @@ -38,7 +36,7 @@ defmodule AshGraphql.ErrorsTest do

assert {:ok, result} = resp

assert %{data: nil, errors: [%{message: message}]} = result
assert %{data: %{"createPost" => nil}, errors: [%{message: message}]} = result
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this change returns the behaviour to the one pre #110, so it's not breaking (there was no release between the two)


assert message =~ "confirmation did not match value"
end
Expand Down Expand Up @@ -111,8 +109,8 @@ defmodule AshGraphql.ErrorsTest do
end

test "showing raised errors alongside root errors shows raised errors in the root" do
Application.put_env(:ash_graphql, AshGraphql.Test.Api,
graphql: [show_raised_errors?: true, root_level_errors?: true]
Application.put_env(:ash_graphql, AshGraphql.Test.RootLevelErrorsApi,
graphql: [show_raised_errors?: true]
)

resp =
Expand All @@ -128,7 +126,7 @@ defmodule AshGraphql.ErrorsTest do
}
}
"""
|> Absinthe.run(AshGraphql.Test.Schema,
|> Absinthe.run(AshGraphql.Test.RootLevelErrorsSchema,
variables: %{
"input" => %{
"text" => "foobar"
Expand All @@ -139,7 +137,7 @@ defmodule AshGraphql.ErrorsTest do
assert {:ok, result} = resp

assert %{
data: nil,
data: %{"createPostWithError" => nil},
errors: [
%{message: message}
]
Expand Down Expand Up @@ -415,4 +413,60 @@ defmodule AshGraphql.ErrorsTest do
assert fields["type"]["ofType"]["kind"] == "NON_NULL"
assert fields["type"]["ofType"]["ofType"]["name"] == "String"
end

test "mutation result is non nullable without root level errors" do
{:ok, %{data: data}} =
"""
query {
__schema {
mutationType {
name
fields {
name
type {
kind
ofType {
name
}
}
}
}
}
}
"""
|> Absinthe.run(AshGraphql.Test.Schema)

create_post_mutation =
data["__schema"]["mutationType"]["fields"]
|> Enum.find(fn field -> field["name"] == "createPost" end)

assert create_post_mutation["type"]["kind"] == "NON_NULL"
assert create_post_mutation["type"]["ofType"]["name"] == "CreatePostResult"
end

test "mutation result is nullable with root level errors" do
{:ok, %{data: data}} =
"""
query {
__schema {
mutationType {
name
fields {
name
type {
name
}
}
}
}
}
"""
|> Absinthe.run(AshGraphql.Test.RootLevelErrorsSchema)

create_post_mutation =
data["__schema"]["mutationType"]["fields"]
|> Enum.find(fn field -> field["name"] == "createPost" end)

assert create_post_mutation["type"]["name"] == "CreatePostResult"
end
end
17 changes: 17 additions & 0 deletions test/support/root_level_errors_api.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule AshGraphql.Test.RootLevelErrorsApi do
@moduledoc false

use Ash.Api,
extensions: [
AshGraphql.Api
],
otp_app: :ash_graphql

graphql do
root_level_errors? true
end

resources do
registry(AshGraphql.Test.Registry)
end
end
30 changes: 30 additions & 0 deletions test/support/root_level_errors_schema.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule AshGraphql.Test.RootLevelErrorsSchema do
@moduledoc false

use Absinthe.Schema

@apis [AshGraphql.Test.RootLevelErrorsApi]

use AshGraphql, apis: @apis

query do
end

mutation do
end

object :foo do
field(:foo, :string)
field(:bar, :string)
end

input_object :foo_input do
field(:foo, non_null(:string))
field(:bar, non_null(:string))
end

enum :status do
value(:open, description: "The post is open")
value(:closed, description: "The post is closed")
end
end
Loading