github.com/dgraph-io/dgraph@v1.2.8/graphql/schema/introspection_test.go (about) 1 package schema 2 3 import ( 4 "io/ioutil" 5 "path/filepath" 6 "testing" 7 8 "github.com/dgraph-io/dgraph/testutil" 9 "github.com/stretchr/testify/require" 10 "github.com/vektah/gqlparser" 11 "github.com/vektah/gqlparser/ast" 12 "github.com/vektah/gqlparser/parser" 13 "github.com/vektah/gqlparser/validator" 14 ) 15 16 const introspectionQuery = ` 17 query { 18 __schema { 19 queryType { name } 20 mutationType { name } 21 subscriptionType { name } 22 types { 23 ...FullType 24 } 25 directives { 26 name 27 locations 28 args { 29 ...InputValue 30 } 31 } 32 } 33 } 34 fragment FullType on __Type { 35 kind 36 name 37 fields(includeDeprecated: true) { 38 name 39 args { 40 ...InputValue 41 } 42 type { 43 ...TypeRef 44 } 45 isDeprecated 46 deprecationReason 47 } 48 inputFields { 49 ...InputValue 50 } 51 interfaces { 52 ...TypeRef 53 } 54 enumValues(includeDeprecated: true) { 55 name 56 isDeprecated 57 deprecationReason 58 } 59 possibleTypes { 60 ...TypeRef 61 } 62 } 63 fragment InputValue on __InputValue { 64 name 65 type { ...TypeRef } 66 defaultValue 67 } 68 fragment TypeRef on __Type { 69 kind 70 name 71 ofType { 72 kind 73 name 74 ofType { 75 kind 76 name 77 ofType { 78 kind 79 name 80 ofType { 81 kind 82 name 83 ofType { 84 kind 85 name 86 ofType { 87 kind 88 name 89 ofType { 90 kind 91 name 92 } 93 } 94 } 95 } 96 } 97 } 98 } 99 } 100 ` 101 102 const complexSchema = `schema { 103 query: TestType 104 } 105 106 input TestInputObject { 107 a: String = test 108 b: [String] 109 c: String = null 110 } 111 112 113 input TestType { 114 complex: TestInputObject 115 } 116 ` 117 118 func TestIntrospectionQuery(t *testing.T) { 119 simpleSchema := `schema { 120 query: QueryRoot 121 } 122 123 type QueryRoot { 124 onlyField: String 125 }` 126 127 iprefix := "testdata/introspection/input" 128 oprefix := "testdata/introspection/output" 129 130 var tests = []struct { 131 name string 132 schema string 133 queryFile string 134 outputFile string 135 }{ 136 { 137 "Filter on __type", 138 simpleSchema, 139 filepath.Join(iprefix, "type_filter.txt"), 140 filepath.Join(oprefix, "type_filter.json"), 141 }, 142 {"Filter __Schema on __type", 143 simpleSchema, 144 filepath.Join(iprefix, "type_schema_filter.txt"), 145 filepath.Join(oprefix, "type_schema_filter.json"), 146 }, 147 {"Filter object type __type", 148 simpleSchema, 149 filepath.Join(iprefix, "type_object_name_filter.txt"), 150 filepath.Join(oprefix, "type_object_name_filter.json"), 151 }, 152 {"Filter complex object type __type", 153 complexSchema, 154 filepath.Join(iprefix, "type_complex_object_name_filter.txt"), 155 filepath.Join(oprefix, "type_complex_object_name_filter.json"), 156 }, 157 } 158 159 for _, tt := range tests { 160 sch := gqlparser.MustLoadSchema( 161 &ast.Source{Name: "schema.graphql", Input: tt.schema}) 162 163 q, err := ioutil.ReadFile(tt.queryFile) 164 require.NoError(t, err) 165 166 doc, gqlErr := parser.ParseQuery(&ast.Source{Input: string(q)}) 167 require.Nil(t, gqlErr) 168 listErr := validator.Validate(sch, doc) 169 require.Equal(t, 0, len(listErr)) 170 171 op := doc.Operations.ForName("") 172 oper := &operation{op: op, 173 vars: map[string]interface{}{}, 174 query: string(q), 175 doc: doc, 176 inSchema: &schema{schema: sch}, 177 } 178 require.NotNil(t, op) 179 180 queries := oper.Queries() 181 resp, err := Introspect(queries[0]) 182 require.NoError(t, err) 183 184 expectedBuf, err := ioutil.ReadFile(tt.outputFile) 185 require.NoError(t, err) 186 testutil.CompareJSON(t, string(expectedBuf), string(resp)) 187 } 188 } 189 190 func TestIntrospectionQueryWithVars(t *testing.T) { 191 sch := gqlparser.MustLoadSchema( 192 &ast.Source{Name: "schema.graphql", Input: complexSchema}) 193 194 q := `query filterNameOnType($name: String!) { 195 __type(name: $name) { 196 kind 197 name 198 inputFields { 199 name 200 type { ...TypeRef } 201 defaultValue 202 } 203 } 204 } 205 206 fragment TypeRef on __Type { 207 kind 208 name 209 ofType { 210 kind 211 name 212 ofType { 213 kind 214 name 215 ofType { 216 kind 217 name 218 } 219 } 220 } 221 }` 222 223 doc, gqlErr := parser.ParseQuery(&ast.Source{Input: q}) 224 require.Nil(t, gqlErr) 225 listErr := validator.Validate(sch, doc) 226 require.Equal(t, 0, len(listErr)) 227 228 op := doc.Operations.ForName("") 229 oper := &operation{op: op, 230 vars: map[string]interface{}{"name": "TestInputObject"}, 231 query: q, 232 doc: doc, 233 inSchema: &schema{schema: sch}, 234 } 235 require.NotNil(t, op) 236 237 queries := oper.Queries() 238 resp, err := Introspect(queries[0]) 239 require.NoError(t, err) 240 241 fname := "testdata/introspection/output/type_complex_object_name_filter.json" 242 expectedBuf, err := ioutil.ReadFile(fname) 243 require.NoError(t, err) 244 testutil.CompareJSON(t, string(expectedBuf), string(resp)) 245 } 246 247 func TestFullIntrospectionQuery(t *testing.T) { 248 // The output doesn't quite match the output in the graphql-js repo. Look into this later. 249 // https://github.com/graphql/graphql-js/blob/master/src/type/__tests__/introspection-test.js#L35 250 sch := gqlparser.MustLoadSchema( 251 &ast.Source{Name: "schema.graphql", Input: ` 252 schema { 253 query: TestType 254 } 255 256 type TestType { 257 testField: String 258 } 259 `}) 260 261 doc, gqlErr := parser.ParseQuery(&ast.Source{Input: introspectionQuery}) 262 require.Nil(t, gqlErr) 263 264 listErr := validator.Validate(sch, doc) 265 require.Equal(t, 0, len(listErr)) 266 267 op := doc.Operations.ForName("") 268 require.NotNil(t, op) 269 oper := &operation{op: op, 270 vars: map[string]interface{}{}, 271 query: string(introspectionQuery), 272 doc: doc, 273 inSchema: &schema{schema: sch}, 274 } 275 276 queries := oper.Queries() 277 resp, err := Introspect(queries[0]) 278 require.NoError(t, err) 279 280 expectedBuf, err := ioutil.ReadFile("testdata/introspection/output/full_query.json") 281 require.NoError(t, err) 282 testutil.CompareJSON(t, string(expectedBuf), string(resp)) 283 }