1 module graphql.starwars.validation; 2 3 import std.typecons : Nullable, nullable; 4 import std.format : format; 5 import std.experimental.logger; 6 import std.exception; 7 import std.stdio; 8 9 import vibe.data.json; 10 11 import graphql.validation.exception; 12 import graphql.constants; 13 import graphql.parser; 14 import graphql.builder; 15 import graphql.lexer; 16 import graphql.ast; 17 import graphql.graphql; 18 import graphql.helper; 19 import graphql.starwars.data; 20 import graphql.starwars.schema; 21 import graphql.starwars.types; 22 import graphql.validation.querybased; 23 import graphql.validation.schemabased; 24 25 @safe: 26 27 void test(string s) { 28 auto graphqld = new GraphQLD!(StarWarsSchema); 29 auto l = Lexer(s); 30 auto p = Parser(l); 31 32 Document d = p.parseDocument(); 33 const(Document) cd = d; 34 QueryValidator fv = new QueryValidator(d); 35 fv.accept(cd); 36 noCylces(fv.fragmentChildren); 37 allFragmentsReached(fv); 38 SchemaValidator!StarWarsSchema sv = new SchemaValidator!StarWarsSchema(d, 39 graphqld.schema 40 ); 41 sv.accept(cd); 42 DefaultContext con; 43 Json gqld = graphqld.execute(d, Json.emptyObject(), con); 44 } 45 46 @safe unittest { 47 assertNotThrown(test(` 48 query NestedQueryWithFragment { 49 hero { 50 ...NameAndAppearances 51 friends { 52 ...NameAndAppearances 53 friends { 54 ...NameAndAppearances 55 } 56 } 57 } 58 } 59 60 fragment NameAndAppearances on Character { 61 name 62 appearsIn 63 }`)); 64 } 65 66 @safe unittest { 67 assertThrown!FieldDoesNotExist(test(` 68 query HeroSpaceshipQuery { 69 hero { 70 favoriteSpaceship 71 } 72 } 73 `)); 74 } 75 76 @safe unittest { 77 assertThrown!FieldDoesNotExist(test(` 78 query HeroFieldsOnScalarQuery { 79 hero { 80 name { 81 firstCharacterOfName 82 } 83 } 84 } 85 `)); 86 } 87 88 @safe unittest { 89 assertNotThrown(test(` 90 query DroidFieldInFragment { 91 hero { 92 name 93 ...DroidFields 94 } 95 } 96 97 fragment DroidFields on Droid { 98 primaryFunction 99 } 100 `)); 101 } 102 103 @safe unittest { 104 assertNotThrown(test(` 105 query DroidFieldInFragment { 106 hero { 107 name 108 ... on Droid { 109 primaryFunction 110 } 111 } 112 } 113 `)); 114 }