From 4e23753cb473b5555b361f32d17dd2936c799af2 Mon Sep 17 00:00:00 2001 From: Maarten van Vliet Date: Wed, 5 Jan 2022 16:34:00 +0100 Subject: [PATCH 1/4] Add failing test cases for wrapped unknown types --- test/absinthe/phase/validation/known_type_names_test.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/absinthe/phase/validation/known_type_names_test.exs b/test/absinthe/phase/validation/known_type_names_test.exs index 3a16f915eb..5c29fec619 100644 --- a/test/absinthe/phase/validation/known_type_names_test.exs +++ b/test/absinthe/phase/validation/known_type_names_test.exs @@ -61,7 +61,7 @@ defmodule Absinthe.Phase.Validation.KnownTypeNamesTest do test "unknown type names are invalid" do assert_fails_validation( """ - query Foo($var: JumbledUpLetters) { + query Foo($var: JumbledUpLetters, $foo: Foo!, $bar: [Bar!]) { user(id: 4) { name pets { ... on Badger { name }, ...PetFields } @@ -74,6 +74,8 @@ defmodule Absinthe.Phase.Validation.KnownTypeNamesTest do [], [ unknown_type(:variable_definition, "JumbledUpLetters", 1), + unknown_type(:variable_definition, "Foo", 1), + unknown_type(:variable_definition, "Bar", 1), unknown_type(:inline_type_condition, "Badger", 4), unknown_type(:named_type_condition, "Peettt", 7) ] From 0ce82ea70754760904356db462c110c280248927 Mon Sep 17 00:00:00 2001 From: Maarten van Vliet Date: Wed, 5 Jan 2022 19:55:09 +0100 Subject: [PATCH 2/4] Fix check unknown wrapped types --- lib/absinthe/phase/validation/known_type_names.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/absinthe/phase/validation/known_type_names.ex b/lib/absinthe/phase/validation/known_type_names.ex index 46d623f131..c609f2e6a2 100644 --- a/lib/absinthe/phase/validation/known_type_names.ex +++ b/lib/absinthe/phase/validation/known_type_names.ex @@ -33,7 +33,7 @@ defmodule Absinthe.Phase.Validation.KnownTypeNames do |> put_error(error(node, name)) end - defp handle_node(%Blueprint.Document.VariableDefinition{schema_node: nil} = node, schema) do + defp handle_node(%Blueprint.Document.VariableDefinition{} = node, schema) do name = Blueprint.TypeReference.unwrap(node.type).name inner_schema_type = schema.__absinthe_lookup__(name) From 65b9cff643027adf417ce5640dd2fa9016892c15 Mon Sep 17 00:00:00 2001 From: Maarten van Vliet Date: Wed, 5 Jan 2022 19:55:32 +0100 Subject: [PATCH 3/4] Add Did you mean? suggestions for unknown types --- .../phase/validation/known_type_names.ex | 24 ++++++++++++++++--- .../validation/known_type_names_test.exs | 21 ++++++++++------ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/absinthe/phase/validation/known_type_names.ex b/lib/absinthe/phase/validation/known_type_names.ex index c609f2e6a2..7e6efd9b6b 100644 --- a/lib/absinthe/phase/validation/known_type_names.ex +++ b/lib/absinthe/phase/validation/known_type_names.ex @@ -12,6 +12,7 @@ defmodule Absinthe.Phase.Validation.KnownTypeNames do # ``` alias Absinthe.{Blueprint, Phase} + alias Absinthe.Phase.Document.Validation.Utils use Absinthe.Phase use Absinthe.Phase.Validation @@ -40,9 +41,11 @@ defmodule Absinthe.Phase.Validation.KnownTypeNames do if inner_schema_type do node else + suggestions = suggested_type_names(schema, name) + node |> flag_invalid(:bad_type_name) - |> put_error(error(node, name)) + |> put_error(error(node, name, suggestions)) end end @@ -50,12 +53,27 @@ defmodule Absinthe.Phase.Validation.KnownTypeNames do node end + defp suggested_type_names(schema, name) do + schema + |> Absinthe.Schema.referenced_types() + |> Enum.map(& &1.name) + |> Absinthe.Utils.Suggestion.sort_list(name) + end + @spec error(Blueprint.node_t(), String.t()) :: Phase.Error.t() - defp error(node, name) do + defp error(node, name, suggestions \\ []) do %Phase.Error{ phase: __MODULE__, - message: ~s(Unknown type "#{name}".), + message: message(name, suggestions), locations: [node.source_location] } end + + defp message(name, []) do + ~s(Unknown type "#{name}".) + end + + defp message(name, suggestions) do + ~s(Unknown type "#{name}".) <> Utils.MessageSuggestions.suggest_message(suggestions) + end end diff --git a/test/absinthe/phase/validation/known_type_names_test.exs b/test/absinthe/phase/validation/known_type_names_test.exs index 5c29fec619..9d6f5db94f 100644 --- a/test/absinthe/phase/validation/known_type_names_test.exs +++ b/test/absinthe/phase/validation/known_type_names_test.exs @@ -7,24 +7,26 @@ defmodule Absinthe.Phase.Validation.KnownTypeNamesTest do alias Absinthe.Blueprint - def unknown_type(:variable_definition, name, line) do + def unknown_type(type, name, line, custom_error_message \\ nil) + + def unknown_type(:variable_definition, name, line, custom_error_message) do bad_value( Blueprint.Document.VariableDefinition, - error_message(name), + custom_error_message || error_message(name), line, &(Blueprint.TypeReference.unwrap(&1.type).name == name) ) end - def unknown_type(:named_type_condition, name, line) do + def unknown_type(:named_type_condition, name, line, _) do unknown_type_condition(Blueprint.Document.Fragment.Named, name, line) end - def unknown_type(:spread_type_condition, name, line) do + def unknown_type(:spread_type_condition, name, line, _) do unknown_type_condition(Blueprint.Document.Fragment.Spread, name, line) end - def unknown_type(:inline_type_condition, name, line) do + def unknown_type(:inline_type_condition, name, line, _) do unknown_type_condition(Blueprint.Document.Fragment.Inline, name, line) end @@ -61,7 +63,7 @@ defmodule Absinthe.Phase.Validation.KnownTypeNamesTest do test "unknown type names are invalid" do assert_fails_validation( """ - query Foo($var: JumbledUpLetters, $foo: Foo!, $bar: [Bar!]) { + query Foo($var: JumbledUpLetters, $foo: Boolen!, $bar: [Bar!]) { user(id: 4) { name pets { ... on Badger { name }, ...PetFields } @@ -74,7 +76,12 @@ defmodule Absinthe.Phase.Validation.KnownTypeNamesTest do [], [ unknown_type(:variable_definition, "JumbledUpLetters", 1), - unknown_type(:variable_definition, "Foo", 1), + unknown_type( + :variable_definition, + "Boolen", + 1, + ~s(Unknown type "Boolen". Did you mean "Alien" or "Boolean"?) + ), unknown_type(:variable_definition, "Bar", 1), unknown_type(:inline_type_condition, "Badger", 4), unknown_type(:named_type_condition, "Peettt", 7) From 483d6e529094cabcb82bdbed30eb013b65265955 Mon Sep 17 00:00:00 2001 From: Maarten van Vliet Date: Wed, 5 Jan 2022 19:59:55 +0100 Subject: [PATCH 4/4] Add changelog entry for #1138 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96d6041451..844fb6402a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ## Unreleased -- Bug Fix: [Validate field names are unique to an object/interface/input object](https://github.com/absinthe-graphql/absinthe/pull/1135) +- Bug Fix: [Fix check unknown types to also cover wrapped types](https://github.com/absinthe-graphql/absinthe/pull/1138) +- Bug Fix: [Validate field names are unique to an object, interface or an input object](https://github.com/absinthe-graphql/absinthe/pull/1135) ## 1.6.6