introspection_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package interpreter
  11. import (
  12. "fmt"
  13. "testing"
  14. "devt.de/krotik/common/lang/graphql/parser"
  15. )
  16. func TestIntrospection(t *testing.T) {
  17. gm, _ := songGraphGroups()
  18. query := map[string]interface{}{
  19. "operationName": nil,
  20. "query": `
  21. query IntrospectionQuery {
  22. __schema {
  23. queryType { name }
  24. mutationType { name }
  25. subscriptionType { name }
  26. types {
  27. ...FullType
  28. }
  29. directives {
  30. name
  31. description
  32. locations
  33. args {
  34. ...InputValue
  35. }
  36. }
  37. }
  38. }
  39. fragment FullType on __Type {
  40. kind
  41. name
  42. description
  43. fields(includeDeprecated: true) {
  44. name
  45. description
  46. args {
  47. ...InputValue
  48. }
  49. type {
  50. ...TypeRef
  51. }
  52. isDeprecated
  53. deprecationReason
  54. }
  55. inputFields {
  56. ...InputValue
  57. }
  58. interfaces {
  59. ...TypeRef
  60. }
  61. enumValues(includeDeprecated: true) {
  62. name
  63. description
  64. isDeprecated
  65. deprecationReason
  66. }
  67. possibleTypes {
  68. ...TypeRef
  69. }
  70. }
  71. fragment InputValue on __InputValue {
  72. name
  73. description
  74. type { ...TypeRef }
  75. defaultValue
  76. }
  77. fragment TypeRef on __Type {
  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. ofType {
  93. kind
  94. name
  95. ofType {
  96. kind
  97. name
  98. ofType {
  99. kind
  100. name
  101. }
  102. }
  103. }
  104. }
  105. }
  106. }
  107. }
  108. }
  109. `}
  110. res, err := runQuery("test", "main", query, gm, nil, false)
  111. data := res["data"].(map[string]interface{})
  112. schema := data["__schema"].(map[string]interface{})
  113. if _, ok := schema["types"]; !ok || err != nil {
  114. t.Error("Unexpected result:", schema, err)
  115. return
  116. }
  117. // Create runtime provider
  118. rtp := NewGraphQLRuntimeProvider("test", "main", gm,
  119. fmt.Sprint(query["operationName"]), make(map[string]interface{}), nil, true)
  120. // Parse the query and annotate the AST with runtime components
  121. ast, err := parser.ParseWithRuntime("test", fmt.Sprint(query["query"]), rtp)
  122. if err != nil {
  123. t.Error("Unexpected result", err)
  124. }
  125. err = ast.Runtime.Validate()
  126. if err != nil {
  127. t.Error("Unexpected result", err)
  128. }
  129. // Evaluate the query
  130. sr := ast.Children[0].Children[0].Children[2].Children[0].Children[1].Runtime.(*selectionSetRuntime)
  131. full := formatData(sr.ProcessFullIntrospection())
  132. filtered := formatData(sr.ProcessIntrospection())
  133. if full != filtered {
  134. // This needs thorough investigation - no point in outputting these
  135. // large datastructures during failure
  136. t.Error("Full and filtered introspection are different")
  137. return
  138. }
  139. // Now try out a reduced version
  140. query = map[string]interface{}{
  141. "operationName": nil,
  142. "query": `
  143. query IntrospectionQuery {
  144. __schema {
  145. queryType { name }
  146. mutationType { name }
  147. subscriptionType { name }
  148. directives {
  149. name
  150. description
  151. locations
  152. args {
  153. ...InputValue
  154. ...InputValue @skip(if: true)
  155. ... {
  156. name
  157. }
  158. }
  159. name1: name1
  160. }
  161. }
  162. }
  163. fragment InputValue on __InputValue {
  164. name
  165. description
  166. type { ...TypeRef }
  167. defaultValue
  168. }
  169. fragment TypeRef on __Type {
  170. kind
  171. name
  172. }
  173. `}
  174. res, err = runQuery("test", "main", query, gm, nil, false)
  175. if formatData(res) != `{
  176. "data": {
  177. "__schema": {
  178. "directives": [
  179. {
  180. "args": [
  181. {
  182. "defaultValue": null,
  183. "description": "Skipped when true.",
  184. "name": "if",
  185. "type": {
  186. "kind": "NON_NULL",
  187. "name": null
  188. }
  189. }
  190. ],
  191. "description": "Directs the executor to skip this field or fragment when the `+"`if`"+` argument is true.",
  192. "locations": [
  193. "FIELD",
  194. "FRAGMENT_SPREAD",
  195. "INLINE_FRAGMENT"
  196. ],
  197. "name": "skip",
  198. "name1": null
  199. },
  200. {
  201. "args": [
  202. {
  203. "defaultValue": null,
  204. "description": "Included when true.",
  205. "name": "if",
  206. "type": {
  207. "kind": "NON_NULL",
  208. "name": null
  209. }
  210. }
  211. ],
  212. "description": "Directs the executor to include this field or fragment only when the `+"`if`"+` argument is true.",
  213. "locations": [
  214. "FIELD",
  215. "FRAGMENT_SPREAD",
  216. "INLINE_FRAGMENT"
  217. ],
  218. "name": "include",
  219. "name1": null
  220. }
  221. ],
  222. "mutationType": {
  223. "name": "Mutation"
  224. },
  225. "queryType": {
  226. "name": "Query"
  227. },
  228. "subscriptionType": {
  229. "name": "Subscription"
  230. }
  231. }
  232. }
  233. }` {
  234. t.Error("Unexpected result:", formatData(res), err)
  235. return
  236. }
  237. }