From a0e7d7c01e115ad3f5c1b4fe90b27765f2ec3585 Mon Sep 17 00:00:00 2001 From: Igor Dianov Date: Mon, 29 Apr 2019 19:33:15 -0700 Subject: [PATCH] fix: resolve variable references in GraphQLObjectCoercing --- .../graphql/jpa/query/schema/JavaScalars.java | 14 +- .../jpa/query/schema/ObjectCoercingTests.java | 127 ++++++++++++++++++ 2 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/ObjectCoercingTests.java diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalars.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalars.java index b74172e63..aba4e4a0a 100644 --- a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalars.java +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalars.java @@ -50,6 +50,7 @@ import graphql.language.ObjectValue; import graphql.language.StringValue; import graphql.language.Value; +import graphql.language.VariableReference; import graphql.schema.Coercing; import graphql.schema.CoercingParseValueException; import graphql.schema.CoercingSerializeException; @@ -511,11 +512,12 @@ public Object parseValue(Object input) { @Override public Object parseLiteral(Object input) { - return parseFieldValue((Value) input, Collections.emptyMap()); + return parseLiteral((Value) input, Collections.emptyMap()); } //recursively parse the input into a Map - private Object parseFieldValue(Object value, Map variables) { + @Override + public Object parseLiteral(Object value, Map variables) { if (!(value instanceof Value)) { throw new IllegalArgumentException( "Expected AST type 'StringValue' but was '" + value + "'."); @@ -539,10 +541,14 @@ private Object parseFieldValue(Object value, Map variables) { if (value instanceof NullValue) { return null; } + if (value instanceof VariableReference) { + String varName = ((VariableReference) value).getName(); + return variables.get(varName); + } if (value instanceof ArrayValue) { List values = ((ArrayValue) value).getValues(); return values.stream() - .map(v -> parseFieldValue(v, variables)) + .map(v -> parseLiteral(v, variables)) .collect(Collectors.toList()); } if (value instanceof ObjectValue) { @@ -550,7 +556,7 @@ private Object parseFieldValue(Object value, Map variables) { Map parsedValues = new LinkedHashMap<>(); values.forEach(field -> { - Object parsedValue = parseFieldValue(field.getValue(), variables); + Object parsedValue = parseLiteral(field.getValue(), variables); parsedValues.put(field.getName(), parsedValue); }); return parsedValues; diff --git a/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/ObjectCoercingTests.java b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/ObjectCoercingTests.java new file mode 100644 index 000000000..58ca8ee54 --- /dev/null +++ b/graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/ObjectCoercingTests.java @@ -0,0 +1,127 @@ +package com.introproventures.graphql.jpa.query.schema; + + +import static org.assertj.core.api.Assertions.assertThat; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import graphql.language.ArrayValue; +import graphql.language.BooleanValue; +import graphql.language.EnumValue; +import graphql.language.FloatValue; +import graphql.language.IntValue; +import graphql.language.NullValue; +import graphql.language.ObjectField; +import graphql.language.ObjectValue; +import graphql.language.StringValue; +import graphql.language.Value; +import graphql.language.VariableReference; +import graphql.schema.Coercing; +import org.junit.Test; + +public class ObjectCoercingTests { + + private Map variables = Collections.singletonMap( "varRef1", "value1"); + + private Coercing coercing = new JavaScalars.GraphQLObjectCoercing(); + + @SuppressWarnings("serial") + @Test + public void testASTParsing() { + // when + assertThat(coercing.parseLiteral(mkStringValue("s"), variables)).isEqualTo("s"); + assertThat(coercing.parseLiteral(mkFloatValue("99.9"), variables)).isEqualTo(new BigDecimal("99.9")); + assertThat(coercing.parseLiteral(mkIntValue(BigInteger.valueOf(666)), variables)).isEqualTo(BigInteger.valueOf(666)); + assertThat(coercing.parseLiteral(mkBooleanValue(true), variables)).isEqualTo(true); + assertThat(coercing.parseLiteral(mkNullValue(), variables)).isEqualTo(null); + assertThat(coercing.parseLiteral(mkVarRef("varRef1"), variables)).isEqualTo("value1"); + assertThat(coercing.parseLiteral(mkArrayValue(new ArrayList() {{ add(mkStringValue("s")); add(mkIntValue(BigInteger.valueOf(666))); }}), variables)) + .asList() + .containsExactly("s",BigInteger.valueOf(666)); + + } + + @SuppressWarnings({"serial", "rawtypes"}) + @Test + public void testASTObjectParsing() { + Map input = new LinkedHashMap(); + + input.put("fld1", mkStringValue("s")); + input.put("fld2", mkIntValue(BigInteger.valueOf(666))); + input.put("fld3", mkObjectValue(new LinkedHashMap() {{ + put("childFld1", mkStringValue("child1")); + put("childFl2", mkVarRef("varRef1")); + }})); + + + Map expected = new LinkedHashMap(); + + expected.put("fld1", "s"); + expected.put("fld2", BigInteger.valueOf(666)); + expected.put("fld3", new LinkedHashMap() {{ + put("childFld1", "child1"); + put("childFl2", "value1"); + }}); + + assertThat(coercing.parseLiteral(mkObjectValue(input), variables)).isEqualTo(expected); + } + + @Test + public void testSerializeIsAlwaysInAndOut() { + assertThat(coercing.serialize(666)).isEqualTo(666); + assertThat(coercing.serialize("same")).isEqualTo("same"); + } + + @Test + public void testParseValueIsAlwaysInAndOut() { + assertThat(coercing.parseValue(666)).isEqualTo(666); + assertThat(coercing.parseValue("same")).isEqualTo("same"); + } + + ObjectValue mkObjectValue(Map fields) { + List list = new ArrayList<>(); + + for (String key : fields.keySet()) { + list.add(new ObjectField(key, fields.get(key))); + } + return new ObjectValue(list); + } + + VariableReference mkVarRef(String name) { + return new VariableReference(name); + } + + ArrayValue mkArrayValue(List values) { + return new ArrayValue(values); + } + + NullValue mkNullValue() { + return NullValue.newNullValue().build(); + } + + EnumValue mkEnumValue(String val) { + return new EnumValue(val); + } + + BooleanValue mkBooleanValue(boolean val) { + return new BooleanValue(val); + } + + IntValue mkIntValue(BigInteger val) { + return new IntValue(val); + } + + FloatValue mkFloatValue(String val) { + return new FloatValue(new BigDecimal(val)); + } + + StringValue mkStringValue(String val) { + return new StringValue(val); + } +} \ No newline at end of file