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/add tests for compile time default value evaluation #1026

Merged
merged 5 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
- Feature: Support for the [`repeatable` directive](https://github.com/absinthe-graphql/absinthe/pull/999)
- Feature: Enable [rendering](https://github.com/absinthe-graphql/absinthe/pull/1010) of Type System Directives in SDL based schemas.
- Feature: Correctly match [Introspection type specs](https://github.com/absinthe-graphql/absinthe/pull/1017)
- Bug Fix: Restore dynamic description support [comprehensively fixed](https://github.com/absinthe-graphql/absinthe/pull/1005)
- Bug Fix: Restore dynamic description support [comprehensively fixed](https://github.com/absinthe-graphql/absinthe/pull/1005) (Note: the `description`s are evaluated once --- at compile time)
- Bug Fix: Restore dynamic default_value support [comprehensively fixed](https://github.com/absinthe-graphql/absinthe/pull/1026) (Note: the `default_value`s evaluated once --- at compile time)
- Bug Fix: [Interface nullability](https://github.com/absinthe-graphql/absinthe/pull/1009) corrections
- Bug Fix: Fix [field listing for Inputs](https://github.com/absinthe-graphql/absinthe/pull/1015) that import fields
- Bug Fix: Properly [trim all descriptions](https://github.com/absinthe-graphql/absinthe/pull/1014) no matter the mechanism used to specify them
Expand Down
1 change: 0 additions & 1 deletion lib/absinthe/blueprint/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ defmodule Absinthe.Blueprint.Schema do
end

defp build_types([:close | rest], [%Schema.InputValueDefinition{} = arg, field | stack], buff) do
arg = Map.update!(arg, :default_value, fn val -> {:unquote, [], [val]} end)
Copy link
Contributor Author

@dylan-chong dylan-chong Jan 7, 2021

Choose a reason for hiding this comment

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

Seemed to not work, and i'm guess it was supposed to do the evaluation. Clearly it didn't so just removed and used the wrap_in_unquote function. Tests are passing anyway

build_types(rest, [push(field, :arguments, arg) | stack], buff)
end

Expand Down
2 changes: 2 additions & 0 deletions lib/absinthe/schema/notation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ defmodule Absinthe.Schema.Notation do
|> Keyword.delete(:args)
|> Keyword.delete(:meta)
|> Keyword.update(:description, nil, &wrap_in_unquote/1)
|> Keyword.update(:default_value, nil, &wrap_in_unquote/1)
|> handle_deprecate

{attrs, block}
Expand Down Expand Up @@ -1337,6 +1338,7 @@ defmodule Absinthe.Schema.Notation do
|> Keyword.put_new(:name, to_string(identifier))
|> Keyword.put_new(:type, type)
|> Keyword.update(:description, nil, &wrap_in_unquote/1)
|> Keyword.update(:default_value, nil, &wrap_in_unquote/1)
|> handle_deprecate
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
defmodule Elixir.Absinthe.Integration.Execution.Variables.DefaultValueTest do
use Absinthe.Case, async: true

@query """
@times_query """
query ($mult: Int = 6) {
times(base: 4, multiplier: $mult)
}
"""

test "scenario #1" do
@default_value_query """
query {
microsecond
}
"""

test "query field arg default_value and resolve execution" do
assert {:ok, %{data: %{"times" => 24}}} ==
Absinthe.run(@query, Absinthe.Fixtures.TimesSchema, [])
Absinthe.run(@times_query, Absinthe.Fixtures.TimesSchema, [])
end

test "query field default is evaluated only once" do
{:ok, %{data: %{"microsecond" => first_current_microsecond}}} =
Absinthe.run(@default_value_query, Absinthe.Fixtures.DefaultValueSchema, [])

{:ok, %{data: %{"microsecond" => second_current_microsecond}}} =
Absinthe.run(@default_value_query, Absinthe.Fixtures.DefaultValueSchema, [])

# If the code to grab the default_value was executed twice, this would be different
assert first_current_microsecond == second_current_microsecond
end
end
17 changes: 17 additions & 0 deletions test/absinthe/type/input_object_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ defmodule Absinthe.Type.InputObjectTest do

alias Absinthe.Fixtures.InputObject

# Note: The arg description evaluation tests are in test/absinthe/type/query_test.exs

defmodule Schema do
use Absinthe.Schema

Expand Down Expand Up @@ -120,4 +122,19 @@ defmodule Absinthe.Type.InputObjectTest do
end
end)
end

describe "input object field default_value evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
expected_value: expected_value
} ->
test "for #{test_label} (evaluates default_value to '#{expected_value}')" do
type =
InputObject.TestSchemaFieldsAndArgsDescription.__absinthe_type__(:field_default_value)

assert type.fields[unquote(test_label)].default_value == unquote(expected_value)
end
end)
end
end
23 changes: 19 additions & 4 deletions test/absinthe/type/object_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ defmodule Absinthe.Type.ObjectTest do
end
end

describe "input object keyword description evaluation" do
describe "object keyword description evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
Expand Down Expand Up @@ -83,7 +83,7 @@ defmodule Absinthe.Type.ObjectTest do
end)
end

describe "input object field keyword description evaluation" do
describe "object field keyword description evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
Expand All @@ -100,7 +100,7 @@ defmodule Absinthe.Type.ObjectTest do
end)
end

describe "input object field attribute description evaluation" do
describe "object field attribute description evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Absinthe.Fixtures.FunctionEvaluationHelpers.filter_test_params_for_description_attribute()
|> Enum.each(fn %{
Expand All @@ -115,7 +115,7 @@ defmodule Absinthe.Type.ObjectTest do
end)
end

describe "input object field macro description evaluation" do
describe "object field macro description evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
Expand All @@ -129,4 +129,19 @@ defmodule Absinthe.Type.ObjectTest do
end
end)
end

# TODO default_value is always nil????
describe "object field default_value evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
expected_value: expected_value
} ->
test "for #{test_label} (evaluates default_value to '#{expected_value}')" do
type = Object.TestSchemaFieldsAndArgsDescription.__absinthe_type__(:field_default_value)

assert type.fields[unquote(test_label)].default_value == unquote(expected_value)
end
end)
Copy link
Contributor Author

@dylan-chong dylan-chong Jan 7, 2021

Choose a reason for hiding this comment

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

the input object's field's default_value is always nil here. Not sure if intentional or not. But i have removed this test in ffb7a0c for the time being

end
end
79 changes: 31 additions & 48 deletions test/absinthe/type/query_test.exs
Original file line number Diff line number Diff line change
@@ -1,68 +1,51 @@
defmodule Absinthe.Type.QueryTest do
use Absinthe.Case, async: true

defmodule TestSchema do
Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved to fixtures

use Absinthe.Schema
@module_attribute "goodbye"
alias Absinthe.Fixtures.Query

defmodule NestedModule do
def nested_function(arg1) do
arg1
end
end

def test_function(arg1) do
arg1
end

query do
field :normal_string, :string do
arg :arg_example, :string, description: "string"
end

field :local_function_call, :string do
arg :arg_example, :string, description: test_function("red")
end

field :function_call_using_absolute_path_to_current_module, :string do
arg :arg_example, :string,
description: Absinthe.Type.QueryTest.TestSchema.test_function("red")
end

field :standard_library_function, :string do
arg :arg_example, :string, description: String.replace("red", "e", "a")
end

field :function_in_nested_module, :string do
arg :arg_example, :string, description: NestedModule.nested_function("hello")
end
describe "query field arg keyword description evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
expected_value: expected_value
} ->
test "for #{test_label} (evaluates description to '#{expected_value}')" do
type = Query.TestSchemaFieldArgDescription.__absinthe_type__("RootQueryType")

field :external_module_function_call, :string do
arg :arg_example, :string,
description: Absinthe.Fixtures.FunctionEvaluationHelpers.external_function("hello")
assert type.fields[unquote(test_label)].args.arg_example.description ==
unquote(expected_value)
end
end)
end

field :module_attribute_string_concat, :string do
arg :arg_example, :string, description: "hello " <> @module_attribute
end
describe "query field arg default_value evaluation" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
expected_value: expected_value
} ->
test "for #{test_label} (evaluates default_value to '#{expected_value}')" do
type = Query.TestSchemaFieldArgDefaultValue.__absinthe_type__("RootQueryType")
field = type.fields[unquote(test_label)]

field :interpolation_of_module_attribute, :string do
arg :arg_example, :string, description: "hello #{@module_attribute}"
assert field.args.arg_example.default_value == unquote(expected_value)
end
end
end)
end

describe "query field arg keyword description evaluation" do
describe "query field arg default_value evaluation with import_fields" do
Absinthe.Fixtures.FunctionEvaluationHelpers.function_evaluation_test_params()
|> Enum.each(fn %{
test_label: test_label,
expected_value: expected_value
} ->
test "for #{test_label} (evaluates description to '#{expected_value}')" do
type = TestSchema.__absinthe_type__("RootQueryType")
test "for #{test_label} (evaluates default_value to '#{expected_value}')" do
type =
Query.TestSchemaFieldArgDefaultValueWithImportFields.__absinthe_type__("RootQueryType")

assert type.fields[unquote(test_label)].args.arg_example.description ==
unquote(expected_value)
field = type.fields[unquote(test_label)]

assert field.args.arg_example.default_value == unquote(expected_value)
end
end)
end
Expand Down
10 changes: 10 additions & 0 deletions test/support/fixtures/default_value_schema.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defmodule Absinthe.Fixtures.DefaultValueSchema do
use Absinthe.Schema
use Absinthe.Fixture

# Note: More examples in Absinthe.Fixtures.Query.TestSchemaFieldArgDefaultValueWithImportFields

query do
field :microsecond, :integer, default_value: DateTime.utc_now().microsecond |> elem(0)
end
end
22 changes: 22 additions & 0 deletions test/support/fixtures/input_object.ex
Original file line number Diff line number Diff line change
Expand Up @@ -251,5 +251,27 @@ defmodule Absinthe.Fixtures.InputObject do
description "hello #{@module_attribute}"
end
end

input_object :field_default_value do
field :normal_string, :string, default_value: "string"
field :local_function_call, :string, default_value: test_function("red")

field :function_call_using_absolute_path_to_current_module, :string,
default_value:
Absinthe.Fixtures.InputObject.TestSchemaFieldsAndArgsDescription.test_function("red")

field :standard_library_function, :string, default_value: String.replace("red", "e", "a")

field :function_in_nested_module, :string,
default_value: NestedModule.nested_function("hello")

field :external_module_function_call, :string,
default_value: Absinthe.Fixtures.FunctionEvaluationHelpers.external_function("hello")

field :module_attribute_string_concat, :string, default_value: "hello " <> @module_attribute

field :interpolation_of_module_attribute, :string,
default_value: "hello #{@module_attribute}"
end
end
end
22 changes: 22 additions & 0 deletions test/support/fixtures/object.ex
Original file line number Diff line number Diff line change
Expand Up @@ -251,5 +251,27 @@ defmodule Absinthe.Fixtures.Object do
description "hello #{@module_attribute}"
end
end

object :field_default_value do
field :normal_string, :string, default_value: "string"
field :local_function_call, :string, default_value: test_function("red")

field :function_call_using_absolute_path_to_current_module, :string,
default_value:
Absinthe.Fixtures.Object.TestSchemaFieldsAndArgsDescription.test_function("red")

field :standard_library_function, :string, default_value: String.replace("red", "e", "a")

field :function_in_nested_module, :string,
default_value: NestedModule.nested_function("hello")

field :external_module_function_call, :string,
default_value: Absinthe.Fixtures.FunctionEvaluationHelpers.external_function("hello")

field :module_attribute_string_concat, :string, default_value: "hello " <> @module_attribute

field :interpolation_of_module_attribute, :string,
default_value: "hello #{@module_attribute}"
end
end
end
Loading