@@ -267,6 +267,7 @@ describe('Parser', () => {
267267 definitions : [
268268 {
269269 kind : Kind . OPERATION_DEFINITION ,
270+ description : undefined ,
270271 loc : { start : 0 , end : 40 } ,
271272 operation : 'query' ,
272273 name : undefined ,
@@ -357,6 +358,7 @@ describe('Parser', () => {
357358 definitions : [
358359 {
359360 kind : Kind . OPERATION_DEFINITION ,
361+ description : undefined ,
360362 loc : { start : 0 , end : 29 } ,
361363 operation : 'query' ,
362364 name : undefined ,
@@ -404,6 +406,75 @@ describe('Parser', () => {
404406 } ) ;
405407 } ) ;
406408
409+ it ( 'creates ast from nameless query with description' , ( ) => {
410+ const result = parse ( dedent `
411+ "Description"
412+ query {
413+ node {
414+ id
415+ }
416+ }
417+ ` ) ;
418+
419+ expectJSON ( result ) . toDeepEqual ( {
420+ kind : Kind . DOCUMENT ,
421+ loc : { start : 0 , end : 43 } ,
422+ definitions : [
423+ {
424+ kind : Kind . OPERATION_DEFINITION ,
425+ loc : { start : 0 , end : 43 } ,
426+ description : {
427+ kind : Kind . STRING ,
428+ loc : { start : 0 , end : 13 } ,
429+ value : 'Description' ,
430+ block : false ,
431+ } ,
432+ operation : 'query' ,
433+ name : undefined ,
434+ variableDefinitions : undefined ,
435+ directives : undefined ,
436+ selectionSet : {
437+ kind : Kind . SELECTION_SET ,
438+ loc : { start : 20 , end : 43 } ,
439+ selections : [
440+ {
441+ kind : Kind . FIELD ,
442+ loc : { start : 24 , end : 41 } ,
443+ alias : undefined ,
444+ name : {
445+ kind : Kind . NAME ,
446+ loc : { start : 24 , end : 28 } ,
447+ value : 'node' ,
448+ } ,
449+ arguments : undefined ,
450+ directives : undefined ,
451+ selectionSet : {
452+ kind : Kind . SELECTION_SET ,
453+ loc : { start : 29 , end : 41 } ,
454+ selections : [
455+ {
456+ kind : Kind . FIELD ,
457+ loc : { start : 35 , end : 37 } ,
458+ alias : undefined ,
459+ name : {
460+ kind : Kind . NAME ,
461+ loc : { start : 35 , end : 37 } ,
462+ value : 'id' ,
463+ } ,
464+ arguments : undefined ,
465+ directives : undefined ,
466+ selectionSet : undefined ,
467+ } ,
468+ ] ,
469+ } ,
470+ } ,
471+ ] ,
472+ } ,
473+ } ,
474+ ] ,
475+ } ) ;
476+ } ) ;
477+
407478 it ( 'allows parsing without source location information' , ( ) => {
408479 const result = parse ( '{ id }' , { noLocation : true } ) ;
409480 expect ( 'loc' in result ) . to . equal ( false ) ;
@@ -686,6 +757,281 @@ describe('Parser', () => {
686757 } ) ;
687758 } ) ;
688759
760+ describe ( 'operation and variable definition descriptions' , ( ) => {
761+ it ( 'parses operation with description and variable descriptions' , ( ) => {
762+ const result = parse ( dedent `
763+ "Operation description"
764+ query myQuery(
765+ "Variable a description"
766+ $a: Int,
767+ """Variable b\nmultiline description"""
768+ $b: String
769+ ) {
770+ field(a: $a, b: $b)
771+ }
772+ ` ) ;
773+
774+ const opDef = result . definitions . find (
775+ ( d ) => d . kind === Kind . OPERATION_DEFINITION ,
776+ ) ;
777+ if ( ! opDef || opDef . kind !== Kind . OPERATION_DEFINITION ) {
778+ throw new Error ( 'No operation definition found' ) ;
779+ }
780+
781+ expectJSON ( opDef ) . toDeepEqual ( {
782+ kind : Kind . OPERATION_DEFINITION ,
783+ operation : 'query' ,
784+ description : {
785+ kind : Kind . STRING ,
786+ value : 'Operation description' ,
787+ block : false ,
788+ loc : { start : 0 , end : 23 } ,
789+ } ,
790+ name : {
791+ kind : Kind . NAME ,
792+ value : 'myQuery' ,
793+ loc : { start : 30 , end : 37 } ,
794+ } ,
795+ variableDefinitions : [
796+ {
797+ kind : Kind . VARIABLE_DEFINITION ,
798+ description : {
799+ kind : Kind . STRING ,
800+ value : 'Variable a description' ,
801+ block : false ,
802+ loc : { start : 41 , end : 65 } ,
803+ } ,
804+ variable : {
805+ kind : Kind . VARIABLE ,
806+ name : {
807+ kind : Kind . NAME ,
808+ value : 'a' ,
809+ loc : { start : 69 , end : 70 } ,
810+ } ,
811+ loc : { start : 68 , end : 70 } ,
812+ } ,
813+ type : {
814+ kind : Kind . NAMED_TYPE ,
815+ name : {
816+ kind : Kind . NAME ,
817+ value : 'Int' ,
818+ loc : { start : 72 , end : 75 } ,
819+ } ,
820+ loc : { start : 72 , end : 75 } ,
821+ } ,
822+ defaultValue : undefined ,
823+ directives : undefined ,
824+ loc : { start : 41 , end : 75 } ,
825+ } ,
826+ {
827+ kind : Kind . VARIABLE_DEFINITION ,
828+ description : {
829+ kind : Kind . STRING ,
830+ value : 'Variable b\nmultiline description' ,
831+ block : true ,
832+ loc : { start : 79 , end : 117 } ,
833+ } ,
834+ variable : {
835+ kind : Kind . VARIABLE ,
836+ name : {
837+ kind : Kind . NAME ,
838+ value : 'b' ,
839+ loc : { start : 121 , end : 122 } ,
840+ } ,
841+ loc : { start : 120 , end : 122 } ,
842+ } ,
843+ type : {
844+ kind : Kind . NAMED_TYPE ,
845+ name : {
846+ kind : Kind . NAME ,
847+ value : 'String' ,
848+ loc : { start : 124 , end : 130 } ,
849+ } ,
850+ loc : { start : 124 , end : 130 } ,
851+ } ,
852+ defaultValue : undefined ,
853+ directives : undefined ,
854+ loc : { start : 79 , end : 130 } ,
855+ } ,
856+ ] ,
857+ directives : undefined ,
858+ selectionSet : {
859+ kind : Kind . SELECTION_SET ,
860+ selections : [
861+ {
862+ kind : Kind . FIELD ,
863+ alias : undefined ,
864+ name : {
865+ kind : Kind . NAME ,
866+ value : 'field' ,
867+ loc : { start : 137 , end : 142 } ,
868+ } ,
869+ arguments : [
870+ {
871+ kind : Kind . ARGUMENT ,
872+ name : {
873+ kind : Kind . NAME ,
874+ value : 'a' ,
875+ loc : { start : 143 , end : 144 } ,
876+ } ,
877+ value : {
878+ kind : Kind . VARIABLE ,
879+ name : {
880+ kind : Kind . NAME ,
881+ value : 'a' ,
882+ loc : { start : 147 , end : 148 } ,
883+ } ,
884+ loc : { start : 146 , end : 148 } ,
885+ } ,
886+ loc : { start : 143 , end : 148 } ,
887+ } ,
888+ {
889+ kind : Kind . ARGUMENT ,
890+ name : {
891+ kind : Kind . NAME ,
892+ value : 'b' ,
893+ loc : { start : 150 , end : 151 } ,
894+ } ,
895+ value : {
896+ kind : Kind . VARIABLE ,
897+ name : {
898+ kind : Kind . NAME ,
899+ value : 'b' ,
900+ loc : { start : 154 , end : 155 } ,
901+ } ,
902+ loc : { start : 153 , end : 155 } ,
903+ } ,
904+ loc : { start : 150 , end : 155 } ,
905+ } ,
906+ ] ,
907+ directives : undefined ,
908+ selectionSet : undefined ,
909+ loc : { start : 137 , end : 156 } ,
910+ } ,
911+ ] ,
912+ loc : { start : 133 , end : 158 } ,
913+ } ,
914+ loc : { start : 0 , end : 158 } ,
915+ } ) ;
916+ } ) ;
917+
918+ it ( 'descriptions on a short-hand query produce a sensible error' , ( ) => {
919+ const input = `"""Invalid"""
920+ { __typename }` ;
921+ expect ( ( ) => parse ( input ) ) . to . throw (
922+ 'Syntax Error: Unexpected description, descriptions are not supported on shorthand queries.' ,
923+ ) ;
924+ } ) ;
925+
926+ it ( 'parses variable definition with description, default value, and directives' , ( ) => {
927+ const result = parse ( dedent `
928+ query (
929+ "desc"
930+ $foo: Int = 42 @dir
931+ ) {
932+ field(foo: $foo)
933+ }
934+ ` ) ;
935+ const opDef = result . definitions . find (
936+ ( d ) => d . kind === Kind . OPERATION_DEFINITION ,
937+ ) ;
938+ if ( ! opDef || opDef . kind !== Kind . OPERATION_DEFINITION ) {
939+ throw new Error ( 'No operation definition found' ) ;
940+ }
941+ const varDef = opDef . variableDefinitions ?. [ 0 ] ;
942+ expectJSON ( varDef ) . toDeepEqual ( {
943+ kind : Kind . VARIABLE_DEFINITION ,
944+ defaultValue : {
945+ kind : Kind . INT ,
946+ value : '42' ,
947+ loc : { start : 31 , end : 33 } ,
948+ } ,
949+ directives : [
950+ {
951+ arguments : undefined ,
952+ kind : Kind . DIRECTIVE ,
953+ name : {
954+ kind : Kind . NAME ,
955+ value : 'dir' ,
956+ loc : { start : 35 , end : 38 } ,
957+ } ,
958+ loc : { start : 34 , end : 38 } ,
959+ } ,
960+ ] ,
961+ description : {
962+ kind : Kind . STRING ,
963+ value : 'desc' ,
964+ block : false ,
965+ loc : { start : 10 , end : 16 } ,
966+ } ,
967+ variable : {
968+ kind : Kind . VARIABLE ,
969+ name : {
970+ kind : Kind . NAME ,
971+ value : 'foo' ,
972+ loc : { start : 20 , end : 23 } ,
973+ } ,
974+ loc : { start : 19 , end : 23 } ,
975+ } ,
976+ type : {
977+ kind : Kind . NAMED_TYPE ,
978+ name : {
979+ kind : Kind . NAME ,
980+ value : 'Int' ,
981+ loc : { start : 25 , end : 28 } ,
982+ } ,
983+ loc : { start : 25 , end : 28 } ,
984+ } ,
985+ loc : { start : 10 , end : 38 } ,
986+ } ) ;
987+ } ) ;
988+
989+ it ( 'parses fragment with variable description (legacy)' , ( ) => {
990+ const result = parse ( 'fragment Foo("desc" $foo: Int) on Bar { baz }' , {
991+ experimentalFragmentArguments : true ,
992+ } ) ;
993+
994+ const fragDef = result . definitions . find (
995+ ( d ) => d . kind === Kind . FRAGMENT_DEFINITION ,
996+ ) ;
997+ if ( ! fragDef || fragDef . kind !== Kind . FRAGMENT_DEFINITION ) {
998+ throw new Error ( 'No fragment definition found' ) ;
999+ }
1000+ const varDef = fragDef . variableDefinitions ?. [ 0 ] ;
1001+
1002+ expectJSON ( varDef ) . toDeepEqual ( {
1003+ kind : Kind . VARIABLE_DEFINITION ,
1004+ description : {
1005+ kind : Kind . STRING ,
1006+ value : 'desc' ,
1007+ block : false ,
1008+ loc : { start : 13 , end : 19 } ,
1009+ } ,
1010+ variable : {
1011+ kind : Kind . VARIABLE ,
1012+ name : {
1013+ kind : Kind . NAME ,
1014+ value : 'foo' ,
1015+ loc : { start : 21 , end : 24 } ,
1016+ } ,
1017+ loc : { start : 20 , end : 24 } ,
1018+ } ,
1019+ type : {
1020+ kind : Kind . NAMED_TYPE ,
1021+ name : {
1022+ kind : Kind . NAME ,
1023+ value : 'Int' ,
1024+ loc : { start : 26 , end : 29 } ,
1025+ } ,
1026+ loc : { start : 26 , end : 29 } ,
1027+ } ,
1028+ defaultValue : undefined ,
1029+ directives : undefined ,
1030+ loc : { start : 13 , end : 29 } ,
1031+ } ) ;
1032+ } ) ;
1033+ } ) ;
1034+
6891035 describe ( 'parseSchemaCoordinate' , ( ) => {
6901036 it ( 'parses Name' , ( ) => {
6911037 const result = parseSchemaCoordinate ( 'MyType' ) ;
0 commit comments