From c8582cff01761105a06af0c89f26a7116eb1394b Mon Sep 17 00:00:00 2001 From: Quramy Date: Tue, 19 Mar 2024 12:09:25 +0900 Subject: [PATCH] test: Refactor lang service adapter fixture --- .../get-completion-at-position.test.ts | 6 +- .../get-quick-info-at-position.test.ts | 3 +- .../get-semantic-diagnostics.test.ts | 147 ++++++++---------- .../testing/adapter-fixture.ts | 41 +++-- 4 files changed, 99 insertions(+), 98 deletions(-) diff --git a/src/graphql-language-service-adapter/get-completion-at-position.test.ts b/src/graphql-language-service-adapter/get-completion-at-position.test.ts index 52b8e6977..11acdf892 100644 --- a/src/graphql-language-service-adapter/get-completion-at-position.test.ts +++ b/src/graphql-language-service-adapter/get-completion-at-position.test.ts @@ -1,7 +1,7 @@ -import * as ts from 'typescript/lib/tsserverlibrary'; +import ts from 'typescript'; +import { GraphQLSchema } from 'graphql'; import { AdapterFixture } from './testing/adapter-fixture'; import { createSimpleSchema } from './testing/simple-schema'; -import { GraphQLSchema } from 'graphql'; const notFoundCompletionInfo: ts.CompletionInfo = { entries: [], @@ -57,7 +57,7 @@ describe('getCompletionAtPosition', () => { const fixture = createFixture('input.ts', createSimpleSchema()); const completionFn = fixture.adapter.getCompletionAtPosition.bind(fixture.adapter, delegateFn, 'input.ts'); - fixture.addFragment('fragment FRAGMENT on Query { hello }'); + fixture.registerFragment('fragments.ts', 'fragment FRAGMENT on Query { hello }'); fixture.source = 'const a = `query { ...FR'; expect(completionFn(23, undefined)!.entries).toBeTruthy(); expect(completionFn(23, undefined)!.entries.length).not.toBe(0); diff --git a/src/graphql-language-service-adapter/get-quick-info-at-position.test.ts b/src/graphql-language-service-adapter/get-quick-info-at-position.test.ts index f0b2ca1e6..9e5fd4bc7 100644 --- a/src/graphql-language-service-adapter/get-quick-info-at-position.test.ts +++ b/src/graphql-language-service-adapter/get-quick-info-at-position.test.ts @@ -1,8 +1,8 @@ import ts from 'typescript'; +import { GraphQLSchema } from 'graphql'; import { mark, Frets } from 'fretted-strings'; import { createSimpleSchema } from './testing/simple-schema'; import { AdapterFixture } from './testing/adapter-fixture'; -import { GraphQLSchema } from 'graphql'; function delegateFn(): ts.QuickInfo { return { @@ -19,6 +19,7 @@ function delegateFn(): ts.QuickInfo { function createFixture(name: string, schema?: GraphQLSchema) { return new AdapterFixture(name, schema); } + describe('getQuickInfoAtPosition', () => { it('should return GraphQL quick info', () => { const fixture = createFixture('main.ts', createSimpleSchema()); diff --git a/src/graphql-language-service-adapter/get-semantic-diagnostics.test.ts b/src/graphql-language-service-adapter/get-semantic-diagnostics.test.ts index 917e1775d..e9f0ceefa 100644 --- a/src/graphql-language-service-adapter/get-semantic-diagnostics.test.ts +++ b/src/graphql-language-service-adapter/get-semantic-diagnostics.test.ts @@ -1,8 +1,8 @@ -import * as ts from 'typescript/lib/tsserverlibrary'; -import { AdapterFixture } from './testing/adapter-fixture'; -import { createSimpleSchema } from './testing/simple-schema'; +import ts from 'typescript'; import { GraphQLSchema } from 'graphql'; import { mark, Frets } from 'fretted-strings'; +import { AdapterFixture } from './testing/adapter-fixture'; +import { createSimpleSchema } from './testing/simple-schema'; import { ERROR_CODES } from '../errors'; function craeteFixture(name: string, schema?: GraphQLSchema) { @@ -151,12 +151,6 @@ describe('getSemanticDiagnostics', () => { const fixture = craeteFixture('input.ts', createSimpleSchema()); const validateFn = fixture.adapter.getSemanticDiagnostics.bind(fixture.adapter, delegateFn, 'input.ts'); - fixture.addFragment(` - fragment MyFragment on Query { - hello - } - `); - fixture.source = ` const fragment = \` fragment MyFragment on Query { @@ -172,32 +166,30 @@ describe('getSemanticDiagnostics', () => { const fixture = craeteFixture('input.ts', createSimpleSchema()); const validateFn = fixture.adapter.getSemanticDiagnostics.bind(fixture.adapter, delegateFn, 'input.ts'); - fixture.addFragment( - ` - fragment ExternalFragment1 on Query { - __typename - } - `, - 'fragment1.ts', - ); - - fixture.addFragment( - ` - fragment ExternalFragment2 on Query { - __typename - } - `, - 'fragment2.ts', - ); - - fixture.source = ` - const fragment = \` - fragment MyFragment on Query { - hello - ...ExternalFragment1 - } - \`; - `; + fixture + .registerFragment( + 'fragment1.ts', + ` + fragment ExternalFragment1 on Query { + __typename + } + `, + ) + .registerFragment( + 'fragment2.ts', + ` + fragment ExternalFragment2 on Query { + __typename + } + `, + ).source = ` + const fragment = \` + fragment MyFragment on Query { + hello + ...ExternalFragment1 + } + \`; + `; const actual = validateFn(); expect(actual.length).toBe(0); }); @@ -206,33 +198,31 @@ describe('getSemanticDiagnostics', () => { const fixture = craeteFixture('input.ts', createSimpleSchema()); const validateFn = fixture.adapter.getSemanticDiagnostics.bind(fixture.adapter, delegateFn, 'input.ts'); - fixture.addFragment( - ` - fragment DependentFragment on Query { - __typename - } - `, - 'fragment1.ts', - ); - - fixture.addFragment( - ` - fragment NonDependentFragment on Query { - __typename - notExistingFeild - } - `, - 'fragment2.ts', - ); - - fixture.source = ` - const fragment = \` - fragment MyFragment on Query { - hello - ...DependentFragment - } - \`; - `; + fixture + .registerFragment( + 'fragment1.ts', + ` + fragment DependentFragment on Query { + __typename + } + `, + ) + .registerFragment( + 'fragment2.ts', + ` + fragment NonDependentFragment on Query { + __typename + notExistingFeild + } + `, + ).source = ` + const fragment = \` + fragment MyFragment on Query { + hello + ...DependentFragment + } + \`; + `; const actual = validateFn(); expect(actual.length).toBe(0); }); @@ -241,24 +231,22 @@ describe('getSemanticDiagnostics', () => { const fixture = craeteFixture('input.ts', createSimpleSchema()); const validateFn = fixture.adapter.getSemanticDiagnostics.bind(fixture.adapter, delegateFn, 'input.ts'); - fixture.addFragment( + fixture.registerFragment( + 'fragment1.ts', ` fragment DependentFragment on Query { __typename notExistingFeild } `, - 'fragment1.ts', - ); - - fixture.source = ` - const fragment = \` - fragment MyFragment on Query { - hello - ...DependentFragment - } - \`; - `; + ).source = ` + const fragment = \` + fragment MyFragment on Query { + hello + ...DependentFragment + } + \`; + `; const actual = validateFn(); expect(actual.length).toBe(0); }); @@ -319,20 +307,13 @@ describe('getSemanticDiagnostics', () => { const fixture = craeteFixture('input.ts', createSimpleSchema()); const validateFn = fixture.adapter.getSemanticDiagnostics.bind(fixture.adapter, delegateFn, 'input.ts'); - fixture.addFragment( - ` - fragment MyFragment on Query { - __typename - } - `, - ); - fixture.addFragment( + fixture.registerFragment( + 'fragments.ts', ` fragment MyFragment on Query { __typename } `, - 'fragments.ts', ); const frets: Frets = {}; diff --git a/src/graphql-language-service-adapter/testing/adapter-fixture.ts b/src/graphql-language-service-adapter/testing/adapter-fixture.ts index f80e724d8..509906406 100644 --- a/src/graphql-language-service-adapter/testing/adapter-fixture.ts +++ b/src/graphql-language-service-adapter/testing/adapter-fixture.ts @@ -1,6 +1,11 @@ import ts from 'typescript'; import { GraphQLSchema } from 'graphql'; -import { createScriptSourceHelper } from '../../ts-ast-util'; +import { + createScriptSourceHelper, + getTemplateNodeUnder, + getSanitizedTemplateText, + ScriptSourceHelper, +} from '../../ts-ast-util'; import { FragmentRegistry } from '../../gql-ast-util'; import { GraphQLLanguageServiceAdapter } from '../graphql-language-service-adapter'; import { @@ -11,6 +16,7 @@ import { export class AdapterFixture { readonly adapter: GraphQLLanguageServiceAdapter; readonly langService: ts.LanguageService; + readonly scriptSourceHelper: ScriptSourceHelper; private readonly _sourceFileName: string; private readonly _langServiceHost: TestingLanguageServiceHost; private readonly _fragmentRegistry: FragmentRegistry; @@ -23,12 +29,11 @@ export class AdapterFixture { this._langServiceHost = languageServiceHost; this._fragmentRegistry = new FragmentRegistry(); this.langService = languageService; - this.adapter = new GraphQLLanguageServiceAdapter( - createScriptSourceHelper( - { languageService, languageServiceHost, project: { getProjectName: () => 'tsconfig.json' } }, - { exclude: [] }, - ), - { + (this.scriptSourceHelper = createScriptSourceHelper( + { languageService, languageServiceHost, project: { getProjectName: () => 'tsconfig.json' } }, + { exclude: [] }, + )), + (this.adapter = new GraphQLLanguageServiceAdapter(this.scriptSourceHelper, { schema: schema || null, removeDuplicatedFragments: true, fragmentRegistry: this._fragmentRegistry, @@ -38,8 +43,7 @@ export class AdapterFixture { allowTaggedTemplateExpression: true, allowFunctionCallExpression: true, }, - }, - ); + })); } get source() { @@ -48,9 +52,24 @@ export class AdapterFixture { set source(content: string) { this._langServiceHost.updateFile(this._sourceFileName, content); + const documents = this.scriptSourceHelper + .getAllNodes(this._sourceFileName, node => + getTemplateNodeUnder(node, { + names: [], + allowNotTaggedTemplate: true, + allowTaggedTemplateExpression: true, + allowFunctionCallExpression: true, + }), + ) + .map(node => getSanitizedTemplateText(node)); + this._fragmentRegistry.registerDocuments(this._sourceFileName, content, documents); } - addFragment(fragmentDefDoc: string, sourceFileName = this._sourceFileName) { - this._fragmentRegistry.registerDocuments(sourceFileName, 'v1', [{ sourcePosition: 0, text: fragmentDefDoc }]); + registerFragment(sourceFileName: string, fragmentDefDoc: string) { + if (sourceFileName === this._sourceFileName) return this; + this._fragmentRegistry.registerDocuments(sourceFileName, fragmentDefDoc, [ + { sourcePosition: 0, text: fragmentDefDoc }, + ]); + return this; } }