@@ -258,6 +258,7 @@ describe('Parser', () => {
258258 definitions : [
259259 {
260260 kind : Kind . OPERATION_DEFINITION ,
261+ description : undefined ,
261262 loc : { start : 0 , end : 40 } ,
262263 operation : 'query' ,
263264 name : undefined ,
@@ -349,6 +350,7 @@ describe('Parser', () => {
349350 {
350351 kind : Kind . OPERATION_DEFINITION ,
351352 loc : { start : 0 , end : 29 } ,
353+ description : undefined ,
352354 operation : 'query' ,
353355 name : undefined ,
354356 variableDefinitions : [ ] ,
@@ -395,6 +397,75 @@ describe('Parser', () => {
395397 } ) ;
396398 } ) ;
397399
400+ it ( 'creates ast from nameless query with description' , ( ) => {
401+ const result = parse ( dedent `
402+ "Description"
403+ query {
404+ node {
405+ id
406+ }
407+ }
408+ ` ) ;
409+
410+ expectJSON ( result ) . toDeepEqual ( {
411+ kind : Kind . DOCUMENT ,
412+ loc : { start : 0 , end : 43 } ,
413+ definitions : [
414+ {
415+ kind : Kind . OPERATION_DEFINITION ,
416+ loc : { start : 0 , end : 43 } ,
417+ description : {
418+ kind : Kind . STRING ,
419+ loc : { start : 0 , end : 13 } ,
420+ value : 'Description' ,
421+ block : false ,
422+ } ,
423+ operation : 'query' ,
424+ name : undefined ,
425+ variableDefinitions : [ ] ,
426+ directives : [ ] ,
427+ selectionSet : {
428+ kind : Kind . SELECTION_SET ,
429+ loc : { start : 20 , end : 43 } ,
430+ selections : [
431+ {
432+ kind : Kind . FIELD ,
433+ loc : { start : 24 , end : 41 } ,
434+ alias : undefined ,
435+ name : {
436+ kind : Kind . NAME ,
437+ loc : { start : 24 , end : 28 } ,
438+ value : 'node' ,
439+ } ,
440+ arguments : [ ] ,
441+ directives : [ ] ,
442+ selectionSet : {
443+ kind : Kind . SELECTION_SET ,
444+ loc : { start : 29 , end : 41 } ,
445+ selections : [
446+ {
447+ kind : Kind . FIELD ,
448+ loc : { start : 35 , end : 37 } ,
449+ alias : undefined ,
450+ name : {
451+ kind : Kind . NAME ,
452+ loc : { start : 35 , end : 37 } ,
453+ value : 'id' ,
454+ } ,
455+ arguments : [ ] ,
456+ directives : [ ] ,
457+ selectionSet : undefined ,
458+ } ,
459+ ] ,
460+ } ,
461+ } ,
462+ ] ,
463+ } ,
464+ } ,
465+ ] ,
466+ } ) ;
467+ } ) ;
468+
398469 it ( 'allows parsing without source location information' , ( ) => {
399470 const result = parse ( '{ id }' , { noLocation : true } ) ;
400471 expect ( 'loc' in result ) . to . equal ( false ) ;
@@ -657,4 +728,280 @@ describe('Parser', () => {
657728 } ) ;
658729 } ) ;
659730 } ) ;
731+
732+ describe ( 'operation and variable definition descriptions' , ( ) => {
733+ it ( 'parses operation with description and variable descriptions' , ( ) => {
734+ const result = parse ( dedent `
735+ "Operation description"
736+ query myQuery(
737+ "Variable a description"
738+ $a: Int,
739+ """Variable b\nmultiline description"""
740+ $b: String
741+ ) {
742+ field(a: $a, b: $b)
743+ }
744+ ` ) ;
745+
746+ // Find the operation definition
747+ const opDef = result . definitions . find (
748+ ( d ) => d . kind === Kind . OPERATION_DEFINITION ,
749+ ) ;
750+ if ( ! opDef || opDef . kind !== Kind . OPERATION_DEFINITION ) {
751+ throw new Error ( 'No operation definition found' ) ;
752+ }
753+
754+ expectJSON ( opDef ) . toDeepEqual ( {
755+ kind : Kind . OPERATION_DEFINITION ,
756+ operation : 'query' ,
757+ description : {
758+ kind : Kind . STRING ,
759+ value : 'Operation description' ,
760+ block : false ,
761+ loc : { start : 0 , end : 23 } ,
762+ } ,
763+ name : {
764+ kind : Kind . NAME ,
765+ value : 'myQuery' ,
766+ loc : { start : 30 , end : 37 } ,
767+ } ,
768+ variableDefinitions : [
769+ {
770+ kind : Kind . VARIABLE_DEFINITION ,
771+ description : {
772+ kind : Kind . STRING ,
773+ value : 'Variable a description' ,
774+ block : false ,
775+ loc : { start : 41 , end : 65 } ,
776+ } ,
777+ variable : {
778+ kind : Kind . VARIABLE ,
779+ name : {
780+ kind : Kind . NAME ,
781+ value : 'a' ,
782+ loc : { start : 69 , end : 70 } ,
783+ } ,
784+ loc : { start : 68 , end : 70 } ,
785+ } ,
786+ type : {
787+ kind : Kind . NAMED_TYPE ,
788+ name : {
789+ kind : Kind . NAME ,
790+ value : 'Int' ,
791+ loc : { start : 72 , end : 75 } ,
792+ } ,
793+ loc : { start : 72 , end : 75 } ,
794+ } ,
795+ defaultValue : undefined ,
796+ directives : [ ] ,
797+ loc : { start : 41 , end : 75 } ,
798+ } ,
799+ {
800+ kind : Kind . VARIABLE_DEFINITION ,
801+ description : {
802+ kind : Kind . STRING ,
803+ value : 'Variable b\nmultiline description' ,
804+ block : true ,
805+ loc : { start : 79 , end : 117 } ,
806+ } ,
807+ variable : {
808+ kind : Kind . VARIABLE ,
809+ name : {
810+ kind : Kind . NAME ,
811+ value : 'b' ,
812+ loc : { start : 121 , end : 122 } ,
813+ } ,
814+ loc : { start : 120 , end : 122 } ,
815+ } ,
816+ type : {
817+ kind : Kind . NAMED_TYPE ,
818+ name : {
819+ kind : Kind . NAME ,
820+ value : 'String' ,
821+ loc : { start : 124 , end : 130 } ,
822+ } ,
823+ loc : { start : 124 , end : 130 } ,
824+ } ,
825+ defaultValue : undefined ,
826+ directives : [ ] ,
827+ loc : { start : 79 , end : 130 } ,
828+ } ,
829+ ] ,
830+ directives : [ ] ,
831+ selectionSet : {
832+ kind : Kind . SELECTION_SET ,
833+ selections : [
834+ {
835+ kind : Kind . FIELD ,
836+ alias : undefined ,
837+ name : {
838+ kind : Kind . NAME ,
839+ value : 'field' ,
840+ loc : { start : 137 , end : 142 } ,
841+ } ,
842+ arguments : [
843+ {
844+ kind : Kind . ARGUMENT ,
845+ name : {
846+ kind : Kind . NAME ,
847+ value : 'a' ,
848+ loc : { start : 143 , end : 144 } ,
849+ } ,
850+ value : {
851+ kind : Kind . VARIABLE ,
852+ name : {
853+ kind : Kind . NAME ,
854+ value : 'a' ,
855+ loc : { start : 147 , end : 148 } ,
856+ } ,
857+ loc : { start : 146 , end : 148 } ,
858+ } ,
859+ loc : { start : 143 , end : 148 } ,
860+ } ,
861+ {
862+ kind : Kind . ARGUMENT ,
863+ name : {
864+ kind : Kind . NAME ,
865+ value : 'b' ,
866+ loc : { start : 150 , end : 151 } ,
867+ } ,
868+ value : {
869+ kind : Kind . VARIABLE ,
870+ name : {
871+ kind : Kind . NAME ,
872+ value : 'b' ,
873+ loc : { start : 154 , end : 155 } ,
874+ } ,
875+ loc : { start : 153 , end : 155 } ,
876+ } ,
877+ loc : { start : 150 , end : 155 } ,
878+ } ,
879+ ] ,
880+ directives : [ ] ,
881+ selectionSet : undefined ,
882+ loc : { start : 137 , end : 156 } ,
883+ } ,
884+ ] ,
885+ loc : { start : 133 , end : 158 } ,
886+ } ,
887+ loc : { start : 0 , end : 158 } ,
888+ } ) ;
889+ } ) ;
890+
891+ it ( 'descriptions on a short-hand query produce a sensible error' , ( ) => {
892+ const input = `"""Invalid"""
893+ { __typename }` ;
894+ expect ( ( ) => parse ( input ) ) . to . throw (
895+ 'Syntax Error: Unexpected description, descriptions are not supported on shorthand queries.' ,
896+ ) ;
897+ } ) ;
898+
899+ it ( 'parses variable definition with description, default value, and directives' , ( ) => {
900+ const result = parse ( dedent `
901+ query (
902+ "desc"
903+ $foo: Int = 42 @dir
904+ ) {
905+ field(foo: $foo)
906+ }
907+ ` ) ;
908+ const opDef = result . definitions . find (
909+ ( d ) => d . kind === Kind . OPERATION_DEFINITION ,
910+ ) ;
911+ if ( ! opDef || opDef . kind !== Kind . OPERATION_DEFINITION ) {
912+ throw new Error ( 'No operation definition found' ) ;
913+ }
914+ const varDef = opDef . variableDefinitions ?. [ 0 ] ;
915+ expectJSON ( varDef ) . toDeepEqual ( {
916+ kind : Kind . VARIABLE_DEFINITION ,
917+ defaultValue : {
918+ kind : Kind . INT ,
919+ value : '42' ,
920+ loc : { start : 31 , end : 33 } ,
921+ } ,
922+ directives : [
923+ {
924+ arguments : [ ] ,
925+ kind : Kind . DIRECTIVE ,
926+ name : {
927+ kind : Kind . NAME ,
928+ value : 'dir' ,
929+ loc : { start : 35 , end : 38 } ,
930+ } ,
931+ loc : { start : 34 , end : 38 } ,
932+ } ,
933+ ] ,
934+ description : {
935+ kind : Kind . STRING ,
936+ value : 'desc' ,
937+ block : false ,
938+ loc : { start : 10 , end : 16 } ,
939+ } ,
940+ variable : {
941+ kind : Kind . VARIABLE ,
942+ name : {
943+ kind : Kind . NAME ,
944+ value : 'foo' ,
945+ loc : { start : 20 , end : 23 } ,
946+ } ,
947+ loc : { start : 19 , end : 23 } ,
948+ } ,
949+ type : {
950+ kind : Kind . NAMED_TYPE ,
951+ name : {
952+ kind : Kind . NAME ,
953+ value : 'Int' ,
954+ loc : { start : 25 , end : 28 } ,
955+ } ,
956+ loc : { start : 25 , end : 28 } ,
957+ } ,
958+ loc : { start : 10 , end : 38 } ,
959+ } ) ;
960+ } ) ;
961+
962+ it ( 'parses fragment with variable description (legacy)' , ( ) => {
963+ const result = parse ( 'fragment Foo("desc" $foo: Int) on Bar { baz }' , {
964+ allowLegacyFragmentVariables : true ,
965+ } ) ;
966+
967+ const fragDef = result . definitions . find (
968+ ( d ) => d . kind === Kind . FRAGMENT_DEFINITION ,
969+ ) ;
970+ if ( ! fragDef || fragDef . kind !== Kind . FRAGMENT_DEFINITION ) {
971+ throw new Error ( 'No fragment definition found' ) ;
972+ }
973+ const varDef = fragDef . variableDefinitions ?. [ 0 ] ;
974+
975+ expectJSON ( varDef ) . toDeepEqual ( {
976+ kind : Kind . VARIABLE_DEFINITION ,
977+ description : {
978+ kind : Kind . STRING ,
979+ value : 'desc' ,
980+ block : false ,
981+ loc : { start : 13 , end : 19 } ,
982+ } ,
983+ variable : {
984+ kind : Kind . VARIABLE ,
985+ name : {
986+ kind : Kind . NAME ,
987+ value : 'foo' ,
988+ loc : { start : 21 , end : 24 } ,
989+ } ,
990+ loc : { start : 20 , end : 24 } ,
991+ } ,
992+ type : {
993+ kind : Kind . NAMED_TYPE ,
994+ name : {
995+ kind : Kind . NAME ,
996+ value : 'Int' ,
997+ loc : { start : 26 , end : 29 } ,
998+ } ,
999+ loc : { start : 26 , end : 29 } ,
1000+ } ,
1001+ defaultValue : undefined ,
1002+ directives : [ ] ,
1003+ loc : { start : 13 , end : 29 } ,
1004+ } ) ;
1005+ } ) ;
1006+ } ) ;
6601007} ) ;
0 commit comments