Skip to content

fix: resolve variable references in GraphQLObjectCoercing #127

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

Merged
merged 1 commit into from
Apr 30, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String, Object> variables) {
@Override
public Object parseLiteral(Object value, Map<String, Object> variables) {
if (!(value instanceof Value)) {
throw new IllegalArgumentException(
"Expected AST type 'StringValue' but was '" + value + "'.");
Expand All @@ -539,18 +541,22 @@ private Object parseFieldValue(Object value, Map<String, Object> 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<Value> values = ((ArrayValue) value).getValues();
return values.stream()
.map(v -> parseFieldValue(v, variables))
.map(v -> parseLiteral(v, variables))
.collect(Collectors.toList());
}
if (value instanceof ObjectValue) {
List<ObjectField> values = ((ObjectValue) value).getObjectFields();
Map<String, Object> 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, Object> 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<Value>() {{ add(mkStringValue("s")); add(mkIntValue(BigInteger.valueOf(666))); }}), variables))
.asList()
.containsExactly("s",BigInteger.valueOf(666));

}

@SuppressWarnings({"serial", "rawtypes"})
@Test
public void testASTObjectParsing() {
Map<String, Value> input = new LinkedHashMap<String, Value>();

input.put("fld1", mkStringValue("s"));
input.put("fld2", mkIntValue(BigInteger.valueOf(666)));
input.put("fld3", mkObjectValue(new LinkedHashMap<String, Value>() {{
put("childFld1", mkStringValue("child1"));
put("childFl2", mkVarRef("varRef1"));
}}));


Map<String, Object> expected = new LinkedHashMap<String, Object>();

expected.put("fld1", "s");
expected.put("fld2", BigInteger.valueOf(666));
expected.put("fld3", new LinkedHashMap<String, Object>() {{
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<String, Value> fields) {
List<ObjectField> 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<Value> 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);
}
}