UNPKG

codemirror-graphql

Version:
1,153 lines (1,102 loc) 32.1 kB
/** * Copyright (c) 2021 GraphQL Contributors * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ import CodeMirror from 'codemirror'; import 'codemirror/addon/hint/show-hint'; import { GraphQLBoolean, GraphQLFloat, GraphQLID, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLString, __Schema, __Type, } from 'graphql'; import '../hint'; import type { GraphQLHintOptions, IHint, IHints } from '../hint'; import '../mode'; import { TestEnum, TestInputObject, TestSchema, TestType, TestUnion, UnionFirst, UnionSecond, } from './testSchema'; import { GraphQLDocumentMode } from 'graphql-language-service'; function createEditorWithHint() { return CodeMirror(document.createElement('div'), { mode: 'graphql', hintOptions: { schema: TestSchema, closeOnUnfocus: false, completeSingle: false, externalFragments: 'fragment Example on Test { id }', }, }); } function getHintSuggestions( queryString: string, cursor: CodeMirror.Position, opts?: GraphQLHintOptions, ) { const editor = createEditorWithHint(); return new Promise<IHints | undefined>(resolve => { const graphqlHint = CodeMirror.hint.graphql; CodeMirror.hint.graphql = ( cm: CodeMirror.Editor, options: GraphQLHintOptions, ) => { const result = graphqlHint(cm, { ...opts, ...options }); resolve(result); CodeMirror.hint.graphql = graphqlHint; return result; }; editor.doc.setValue(queryString); editor.doc.setCursor(cursor); editor.execCommand('autocomplete'); }); } function getExpectedSuggestions(list: IHint[]) { return list.map(item => ({ text: item.text, type: item.type, description: item.description, isDeprecated: item.isDeprecated, deprecationReason: item.deprecationReason, })); } describe('graphql-hint', () => { it('attaches a GraphQL hint function with correct mode/hint options', () => { const editor = createEditorWithHint(); expect(editor.getHelpers(editor.getCursor(), 'hint')).not.toHaveLength(0); }); it('provides correct initial keywords for executable definitions', async () => { const suggestions = await getHintSuggestions( '', { line: 0, ch: 0 }, { autocompleteOptions: { mode: GraphQLDocumentMode.EXECUTABLE } }, ); const list = [ { text: 'query' }, { text: 'mutation' }, { text: 'subscription' }, { text: 'fragment' }, { text: '{' }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct initial keywords for unknown definitions', async () => { const suggestions = await getHintSuggestions('', { line: 0, ch: 0 }); const list = [ { text: 'extend' }, { text: 'query' }, { text: 'mutation' }, { text: 'subscription' }, { text: 'fragment' }, { text: '{' }, { text: 'type' }, { text: 'interface' }, { text: 'union' }, { text: 'input' }, { text: 'scalar' }, { text: 'schema' }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct initial keywords after filtered', async () => { const suggestions = await getHintSuggestions('q', { line: 0, ch: 1 }); const list = [{ text: '{' }, { text: 'query' }]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestions', async () => { const suggestions = await getHintSuggestions('{ ', { line: 0, ch: 2 }); const list = [ { text: 'test', type: TestType, isDeprecated: false, }, { text: 'union', type: TestUnion, isDeprecated: false, }, { text: 'first', type: UnionFirst, isDeprecated: false, }, { text: 'id', type: GraphQLInt, isDeprecated: false, }, { text: 'isTest', type: GraphQLBoolean, isDeprecated: false, }, { text: 'hasArgs', type: GraphQLString, isDeprecated: false, }, { text: '__typename', type: new GraphQLNonNull(GraphQLString), description: 'The name of the current Object type at runtime.', isDeprecated: false, }, { text: '__schema', type: new GraphQLNonNull(__Schema), description: 'Access the current type schema of this server.', isDeprecated: false, }, { text: '__type', type: __Type, description: 'Request the type information of a single type.', isDeprecated: false, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestions after filtered', async () => { const suggestions = await getHintSuggestions('{ i', { line: 0, ch: 3 }); const list = [ { text: 'id', type: GraphQLInt, isDeprecated: false, }, { text: 'isTest', type: GraphQLBoolean, isDeprecated: false, }, { text: 'union', type: TestUnion, isDeprecated: false, }, { text: 'first', type: UnionFirst, isDeprecated: false, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestions when using aliases', async () => { const suggestions = await getHintSuggestions('{ aliasTest: first { ', { line: 0, ch: 21, }); const list = [ { text: 'scalar', type: GraphQLString, isDeprecated: false, }, { text: 'first', type: TestType, isDeprecated: false, }, { text: 'example', type: GraphQLString, isDeprecated: false, }, { text: '__typename', type: new GraphQLNonNull(GraphQLString), description: 'The name of the current Object type at runtime.', isDeprecated: false, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestion indentation', async () => { const suggestions = await getHintSuggestions('{\n ', { line: 1, ch: 2 }); expect(suggestions?.from).toEqual({ line: 1, ch: 2, sticky: null }); expect(suggestions?.to).toEqual({ line: 1, ch: 2, sticky: null }); }); it('provides correct argument suggestions', async () => { const suggestions = await getHintSuggestions('{ hasArgs ( ', { line: 0, ch: 12, }); const list = [ { text: 'string', type: GraphQLString, }, { text: 'int', type: GraphQLInt, }, { text: 'float', type: GraphQLFloat, }, { text: 'boolean', type: GraphQLBoolean, }, { text: 'id', type: GraphQLID, }, { text: 'enum', type: TestEnum, }, { text: 'object', type: TestInputObject, }, { text: 'listString', type: new GraphQLList(GraphQLString), }, { text: 'listInt', type: new GraphQLList(GraphQLInt), }, { text: 'listFloat', type: new GraphQLList(GraphQLFloat), }, { text: 'listBoolean', type: new GraphQLList(GraphQLBoolean), }, { text: 'listID', type: new GraphQLList(GraphQLID), }, { text: 'listEnum', type: new GraphQLList(TestEnum), }, { text: 'listObject', type: new GraphQLList(TestInputObject), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct argument suggestions after filtered', async () => { const suggestions = await getHintSuggestions('{ hasArgs ( f', { line: 0, ch: 13, }); const list = [ { text: 'float', type: GraphQLFloat, }, { text: 'listFloat', type: new GraphQLList(GraphQLFloat), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct argument suggestions when using aliases', async () => { const suggestions = await getHintSuggestions('{ aliasTest: hasArgs ( ', { line: 0, ch: 23, }); const list = [ { text: 'string', type: GraphQLString, }, { text: 'int', type: GraphQLInt, }, { text: 'float', type: GraphQLFloat, }, { text: 'boolean', type: GraphQLBoolean, }, { text: 'id', type: GraphQLID, }, { text: 'enum', type: TestEnum, }, { text: 'object', type: TestInputObject, }, { text: 'listString', type: new GraphQLList(GraphQLString), }, { text: 'listInt', type: new GraphQLList(GraphQLInt), }, { text: 'listFloat', type: new GraphQLList(GraphQLFloat), }, { text: 'listBoolean', type: new GraphQLList(GraphQLBoolean), }, { text: 'listID', type: new GraphQLList(GraphQLID), }, { text: 'listEnum', type: new GraphQLList(TestEnum), }, { text: 'listObject', type: new GraphQLList(TestInputObject), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct directive suggestions', async () => { const suggestions = await getHintSuggestions('{ test (@', { line: 0, ch: 9, }); const list = [ { text: 'include', description: 'Directs the executor to include this field or fragment only when the `if` argument is true.', }, { text: 'skip', description: 'Directs the executor to skip this field or fragment when the `if` argument is true.', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct directive suggestion after filtered', async () => { const suggestions = await getHintSuggestions('{ test (@s', { line: 0, ch: 10, }); const list = [ { text: 'skip', description: 'Directs the executor to skip this field or fragment when the `if` argument is true.', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct directive suggestions when using aliases', async () => { const suggestions = await getHintSuggestions('{ aliasTest: test (@', { line: 0, ch: 20, }); const list = [ { text: 'include', description: 'Directs the executor to include this field or fragment only when the `if` argument is true.', }, { text: 'skip', description: 'Directs the executor to skip this field or fragment when the `if` argument is true.', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct directive suggestions on definitions', async () => { const suggestions = await getHintSuggestions('type Type @', { line: 0, ch: 11, }); const list = [ { text: 'onAllDefs', description: '', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct directive suggestions on args definitions', async () => { const suggestions = await getHintSuggestions( 'type Type { field(arg: String @', { line: 0, ch: 31 }, ); const list = [ { text: 'deprecated', description: 'Marks an element of a GraphQL schema as no longer supported.', }, { text: 'onArg', description: '', }, { text: 'onAllDefs', description: '', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides interface suggestions for type when using implements keyword', async () => { const suggestions = await getHintSuggestions('type Type implements ', { line: 0, ch: 21, }); const list = [ { text: 'TestInterface', type: TestSchema.getType('TestInterface'), }, { text: 'AnotherTestInterface', type: TestSchema.getType('AnotherTestInterface'), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides interface suggestions for interface when using implements keyword', async () => { const suggestions = await getHintSuggestions( 'interface MyInt implements An', { line: 0, ch: 29 }, ); const list = [ { text: 'AnotherTestInterface', type: TestSchema.getType('AnotherTestInterface'), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides interface suggestions for interface when using implements keyword and multiple interfaces', async () => { const suggestions = await getHintSuggestions( 'interface MyInt implements AnotherTestInterface & T', { line: 0, ch: 51 }, ); const list = [ { text: 'TestInterface', type: TestSchema.getType('TestInterface'), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct typeCondition suggestions', async () => { const suggestions = await getHintSuggestions('{ union { ... on ', { line: 0, ch: 17, }); const list = [ { text: 'First', description: '', }, { text: 'Second', description: '', }, { text: 'TestInterface', description: '', }, { text: 'AnotherTestInterface', description: '', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct typeCondition suggestions after filtered', async () => { const suggestions = await getHintSuggestions('{ union { ... on F', { line: 0, ch: 18, }); const list = [ { text: 'First', description: '', }, { text: 'TestInterface', description: '', }, { text: 'AnotherTestInterface', description: '', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct typeCondition suggestions on fragment', async () => { const suggestions = await getHintSuggestions('fragment Foo on ', { line: 0, ch: 16, }); const list = [ { text: 'Test', description: '', }, { text: 'TestUnion', description: '', }, { text: 'First', description: '', }, { text: 'TestInterface', description: '', }, { text: 'AnotherTestInterface', description: '', }, { text: 'Second', description: '', }, { text: 'MutationType', description: 'This is a simple mutation type', }, { text: 'SubscriptionType', description: 'This is a simple subscription type', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct ENUM suggestions', async () => { const suggestions = await getHintSuggestions('{ hasArgs (enum: ', { line: 0, ch: 17, }); const list = [ { text: 'RED', type: TestEnum, isDeprecated: false, }, { text: 'GREEN', type: TestEnum, isDeprecated: false, }, { text: 'BLUE', type: TestEnum, isDeprecated: false, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct testInput suggestions', async () => { const suggestions = await getHintSuggestions('{ hasArgs (object: { ', { line: 0, ch: 21, }); const list = [ { text: 'string', type: GraphQLString, }, { text: 'int', type: GraphQLInt, }, { text: 'float', type: GraphQLFloat, }, { text: 'boolean', type: GraphQLBoolean, }, { text: 'id', type: GraphQLID, }, { text: 'enum', type: TestEnum, }, { text: 'object', type: TestInputObject, }, { text: 'listString', type: new GraphQLList(GraphQLString), }, { text: 'listInt', type: new GraphQLList(GraphQLInt), }, { text: 'listFloat', type: new GraphQLList(GraphQLFloat), }, { text: 'listBoolean', type: new GraphQLList(GraphQLBoolean), }, { text: 'listID', type: new GraphQLList(GraphQLID), }, { text: 'listEnum', type: new GraphQLList(TestEnum), }, { text: 'listObject', type: new GraphQLList(TestInputObject), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct object field suggestions after filtered', async () => { const suggestions = await getHintSuggestions('{ hasArgs (object: { f', { line: 0, ch: 22, }); const list = [ { text: 'float', type: GraphQLFloat, }, { text: 'listFloat', type: new GraphQLList(GraphQLFloat), }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides fragment name suggestion', async () => { const suggestions = await getHintSuggestions( 'fragment Foo on Test { id } query { ...', { line: 0, ch: 40 }, ); const list = [ { text: 'Foo', type: TestType, description: 'fragment Foo on Test', }, { text: 'Example', type: TestType, description: 'fragment Example on Test', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides fragment names for fragments defined lower', async () => { const suggestions = await getHintSuggestions( 'query { ... }\nfragment Foo on Test { id }', { line: 0, ch: 11 }, ); const list = [ { text: 'Foo', type: TestType, description: 'fragment Foo on Test', }, { text: 'Example', type: TestType, description: 'fragment Example on Test', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides only appropriate fragment names', async () => { const suggestions = await getHintSuggestions( 'fragment Foo on TestUnion { ... } ' + 'fragment Bar on First { name } ' + 'fragment Baz on Second { name } ' + 'fragment Qux on TestUnion { name } ' + 'fragment Nrf on Test { id } ' + 'fragment Quux on TestInputObject { string } ' + 'fragment Abc on Xyz { abcdef }', { line: 0, ch: 31 }, ); const list = [ { text: 'Bar', type: UnionFirst, description: 'fragment Bar on First', }, { text: 'Baz', type: UnionSecond, description: 'fragment Baz on Second', }, { text: 'Qux', type: TestUnion, description: 'fragment Qux on TestUnion', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestion inside inline fragment', async () => { const suggestions = await getHintSuggestions( 'fragment Foo on TestUnion { ... on First { ', { line: 0, ch: 43 }, ); const list = [ { text: 'scalar', type: GraphQLString, isDeprecated: false, }, { text: 'first', type: TestType, isDeprecated: false, }, { text: 'example', type: GraphQLString, isDeprecated: false, }, { text: '__typename', type: new GraphQLNonNull(GraphQLString), description: 'The name of the current Object type at runtime.', isDeprecated: false, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestion inside type-less inline fragment', async () => { const suggestions = await getHintSuggestions( 'fragment Foo on First { ... { ', { line: 0, ch: 30 }, ); const list = [ { text: 'scalar', type: GraphQLString, isDeprecated: false, }, { text: 'first', type: TestType, isDeprecated: false, }, { text: 'example', type: GraphQLString, isDeprecated: false, }, { text: '__typename', type: new GraphQLNonNull(GraphQLString), description: 'The name of the current Object type at runtime.', isDeprecated: false, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct boolean suggestions', async () => { const suggestions1 = await getHintSuggestions('{ hasArgs(listBoolean: [ ', { line: 0, ch: 27, }); const list1 = [ { text: 'true', type: GraphQLBoolean, description: 'Not false.', }, { text: 'false', type: GraphQLBoolean, description: 'Not true.', }, ]; const expectedSuggestions1 = getExpectedSuggestions(list1); expect(suggestions1?.list).toEqual(expectedSuggestions1); const suggestions2 = await getHintSuggestions( '{ hasArgs(object: { boolean: t', { line: 0, ch: 30 }, ); const list2 = [ { text: 'true', type: GraphQLBoolean, description: 'Not false.', }, ]; const expectedSuggestions2 = getExpectedSuggestions(list2); expect(suggestions2?.list).toEqual(expectedSuggestions2); const suggestions3 = await getHintSuggestions('{ hasArgs(boolean: f', { line: 0, ch: 20, }); const list3 = [ { text: 'false', type: GraphQLBoolean, description: 'Not true.', }, ]; const expectedSuggestions3 = getExpectedSuggestions(list3); expect(suggestions3?.list).toEqual(expectedSuggestions3); }); it('provides correct variable type suggestions', async () => { const suggestions = await getHintSuggestions('query($foo: ', { line: 0, ch: 12, }); const list = [ { text: 'String', description: 'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.', }, { text: 'Int', description: 'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.', }, { text: 'Boolean', description: 'The `Boolean` scalar type represents `true` or `false`.', }, { text: 'Float', description: 'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).', }, { text: 'ID', description: 'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.', }, { text: 'TestEnum', description: '' }, { text: 'TestInput', description: '' }, { text: '__TypeKind', description: 'An enum describing what kind of type a given `__Type` is.', }, { text: '__DirectiveLocation', description: 'A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides correct variable type suggestions inside list type', async () => { const suggestions = await getHintSuggestions('query($foo: [ ', { line: 0, ch: 14, }); const list = [ { text: 'String', description: 'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.', }, { text: 'Int', description: 'The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.', }, { text: 'Boolean', description: 'The `Boolean` scalar type represents `true` or `false`.', }, { text: 'Float', description: 'The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).', }, { text: 'ID', description: 'The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.', }, { text: 'TestEnum', description: '' }, { text: 'TestInput', description: '' }, { text: '__TypeKind', description: 'An enum describing what kind of type a given `__Type` is.', }, { text: '__DirectiveLocation', description: 'A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.', }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); it('provides no suggestions', async () => { const list: IHint[] = []; const expectedSuggestions = getExpectedSuggestions(list); // kind is FragmentSpread, step is 2 const suggestions1 = await getHintSuggestions( 'fragment Foo on Test { id } query { ...Foo ', { line: 0, ch: 45 }, ); expect(suggestions1?.list).toEqual(expectedSuggestions); // kind is ListType, step is 3 const suggestions2 = await getHintSuggestions('query($foo: [string] ', { line: 0, ch: 21, }); expect(suggestions2?.list).toEqual(expectedSuggestions); // kind is ListValue, step is 1 const suggestions3 = await getHintSuggestions( '{ hasArgs(listString: ["foo" ', { line: 0, ch: 29, }, ); expect(suggestions3?.list).toEqual(expectedSuggestions); // kind is VariableDefinition, step is 1 const suggestions4 = await getHintSuggestions('query($foo ', { line: 0, ch: 11, }); expect(suggestions4?.list).toEqual(expectedSuggestions); // kind is Argument, step is 1 const suggestions5 = await getHintSuggestions('{ hasArgs(string ', { line: 0, ch: 17, }); expect(suggestions5?.list).toEqual(expectedSuggestions); // kind is Argument, step is 2, and input type isn't GraphQLEnumType or GraphQLBoolean const suggestions6 = await getHintSuggestions('{ hasArgs(string: ', { line: 0, ch: 18, }); expect(suggestions6?.list).toEqual(expectedSuggestions); const suggestions7 = await getHintSuggestions( '{ hasArgs(object: { string ', { line: 0, ch: 27 }, ); expect(suggestions7?.list).toEqual(expectedSuggestions); }); it('provides variable completion for arguments', async () => { const expectedSuggestions = getExpectedSuggestions([ { text: 'string', type: GraphQLString }, { text: 'listString', type: new GraphQLList(GraphQLString) }, ]); // kind is Argument, step is 2, and input type isn't GraphQLEnumType or GraphQLBoolean const suggestions9 = await getHintSuggestions( 'query myQuery($arg: String){ hasArgs(string: ', { line: 0, ch: 42, }, ); expect(suggestions9?.list).toEqual(expectedSuggestions); }); it('provides variable completion for arguments with $', async () => { const expectedSuggestions = getExpectedSuggestions([ { text: 'string', type: GraphQLString }, { text: 'listString', type: new GraphQLList(GraphQLString) }, ]); // kind is Argument, step is 2, and input type isn't GraphQLEnumType or GraphQLBoolean const suggestions9 = await getHintSuggestions( 'query myQuery($arg: String){ hasArgs(string: $', { line: 0, ch: 42, }, ); expect(suggestions9?.list).toEqual(expectedSuggestions); }); it('provides correct field name suggestions for an interface type', async () => { const suggestions = await getHintSuggestions( '{ first { ... on TestInterface { ', { line: 0, ch: 33, }, ); const list = [ { text: 'scalar', type: GraphQLString, isDeprecated: false, }, { description: 'The name of the current Object type at runtime.', isDeprecated: false, text: '__typename', type: new GraphQLNonNull(GraphQLString), deprecationReason: undefined, }, ]; const expectedSuggestions = getExpectedSuggestions(list); expect(suggestions?.list).toEqual(expectedSuggestions); }); });