package io.leangen.graphql; import graphql.ExecutionResult; import graphql.GraphQL; import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; import io.leangen.graphql.annotations.GraphQLArgument; import io.leangen.graphql.annotations.GraphQLQuery; import io.leangen.graphql.annotations.GraphQLTypeResolver; import io.leangen.graphql.annotations.types.GraphQLInterface; import io.leangen.graphql.domain.Education; import io.leangen.graphql.domain.Street; import io.leangen.graphql.execution.TypeResolutionEnvironment; import io.leangen.graphql.execution.TypeResolver; import org.junit.Test; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Stream; import static io.leangen.graphql.support.QueryResultAssertions.assertNoErrors; import static io.leangen.graphql.support.QueryResultAssertions.assertValueAtPathEquals; /** * @author Bojan Tomic (kaqqao) */ public class TypeResolverTest { @Test public void testTypeResolver() { GraphQLSchema schema = new TestSchemaGenerator() .withOperationsFromSingleton(new RepoService()) .generate(); GraphQL exe = GraphQL.newGraphQL(schema).build(); String queryTemplate = "{repo(id: %d) {" + "identifier, " + "... on SessionRepo_Street {street: item {name}} " + "... on SessionRepo_Education {school: item {schoolName}}}}"; ExecutionResult result = exe.execute(String.format(queryTemplate, 2)); assertNoErrors(result); assertValueAtPathEquals("Baker street", result, "repo.0.0.street.name"); // exe.execute("{repo(id: 3) {key {identifier ... on SessionRepo_Street {street: item {name}} ... on SessionRepo_Education {school: item {schoolName}}}}}}", new HashMap<>()); // result = exe.execute("{repo(id: 3) {identifier ... on SessionRepo_Street {street: item {name}} }}"); result = exe.execute(String.format(queryTemplate, 3)); assertNoErrors(result); assertValueAtPathEquals("Alma Mater", result, "repo.0.0.school.schoolName"); } @Test public void testTypeResolutionWithBaseClass() { GraphQLSchema schema = new TestSchemaGenerator() .withOperationsFromSingleton(new RootQuery()) .generate(); GraphQL exe = GraphQL.newGraphQL(schema).build(); ExecutionResult res = exe.execute("{contents {id title}}"); assertNoErrors(res); } @Test public void testTypeResolutionWithoutBaseClass() { GraphQLSchema schema = new TestSchemaGenerator() .withOperationsFromSingleton(new RootQuery2()) .generate(); GraphQL exe = GraphQL.newGraphQL(schema).build(); ExecutionResult res = exe.execute("{contents {id title}}"); assertNoErrors(res); } public static class RootQuery { @GraphQLQuery public List<Content> contents() { return Arrays.asList(new Trailer("1", "Argo"), new Trailer("2", "Gravity"), new Movie("3", "The Ring", "R"), new Movie("4", "Brazil", "R"), new TVShow("5", "Simpsons", 1, 2)); } } public static class RootQuery2 { @GraphQLQuery public List<Content> contents() { return Arrays.asList(new Trailer2("1", "Argo"), new Trailer2("2", "Gravity"), new Movie2("3", "The Ring", "R"), new Movie2("4", "Brazil", "R"), new TVShow2("5", "Simpsons", 1, 2)); } } @GraphQLInterface(name = "Content", implementationAutoDiscovery = true) public interface Content { @GraphQLQuery String id(); @GraphQLQuery String title(); } public static class ContentBase implements Content { private String id; private String title; ContentBase(String id, String title) { this.title = title; this.id = id; } @Override @GraphQLQuery public String id() {return id;} @Override @GraphQLQuery public String title() {return title;} } public static class Movie extends ContentBase { private String rating; Movie(String id, String title, String rating) { super(id, title); this.rating = rating; } @GraphQLQuery public String rating() {return rating;} } public static class Trailer extends ContentBase { Trailer(String id, String title) { super(id, title); } } public static class TVShow extends ContentBase { private Integer seasonNumber; private Integer episodeNumber; TVShow(String id, String title, Integer seasonNumber, Integer episodeNumber) { super(id, title); this.seasonNumber = seasonNumber; this.episodeNumber = episodeNumber; } @GraphQLQuery public Integer seasonNumber() {return seasonNumber;} @GraphQLQuery public Integer episodeNumber() {return episodeNumber;} } public static class Movie2 implements Content { private String id; private String title; private String rating; Movie2(String id, String title, String rating) { this.id = id; this.title = title; this.rating = rating; } @Override @GraphQLQuery public String id() {return id;} @Override @GraphQLQuery public String title() {return title;} @GraphQLQuery public String rating() {return rating;} } public static class Trailer2 implements Content { private String id; private String title; Trailer2(String id, String title) { this.id = id; this.title = title; } @Override @GraphQLQuery public String id() {return id;} @Override @GraphQLQuery public String title() {return title;} } public static class TVShow2 implements Content { private Integer seasonNumber; private Integer episodeNumber; private String id; private String title; TVShow2(String id, String title, Integer seasonNumber, Integer episodeNumber) { this.id = id; this.title = title; this.seasonNumber = seasonNumber; this.episodeNumber = episodeNumber; } @Override @GraphQLQuery public String id() {return id;} @Override @GraphQLQuery public String title() {return title;} @GraphQLQuery public Integer seasonNumber() {return seasonNumber;} @GraphQLQuery public Integer episodeNumber() {return episodeNumber;} } public static class RepoService { @GraphQLQuery(name = "repo") public List<Stream<GenericRepo>> getRepo(@GraphQLArgument(name = "id") int id) { if (id % 2 == 0) { return Collections.singletonList(Stream.of(new SessionRepo<>(new Street("Baker street", 1)))); } else { return Collections.singletonList(Stream.of(new SessionRepo<>(new Education("Alma Mater", 1600, 1604)))); } } @GraphQLQuery(name = "repo1") public SessionRepo<Street> repo1() { return null; } @GraphQLQuery(name = "repo2") public SessionRepo<Education> repo2() { return null; } } @GraphQLInterface(name = "GenericRepository") private interface GenericRepo { @GraphQLQuery(name = "identifier") String identifier(); } @GraphQLTypeResolver(RepoTypeResolver.class) public static class SessionRepo<T> implements GenericRepo { private T item; SessionRepo(T item) { this.item = item; } @GraphQLQuery(name = "item") @SuppressWarnings("WeakerAccess") //must stay public public T getStoredItem() { return item; } @Override @GraphQLQuery(name = "identifier") public String identifier() { return "SESSION"; } } public static class RepoTypeResolver implements TypeResolver { @Override public GraphQLObjectType resolveType(TypeResolutionEnvironment env) { String typeName = "SessionRepo_" + ((SessionRepo) env.getObject()).getStoredItem().getClass().getSimpleName(); return (GraphQLObjectType) env.getSchema().getType(typeName); } } }