vscode-apollo 1.20.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/.circleci/config.yml +27 -18
  2. package/.git-blame-ignore-revs +2 -0
  3. package/.nvmrc +1 -1
  4. package/.vscode/launch.json +9 -4
  5. package/.vscode/tasks.json +58 -16
  6. package/.vscodeignore +12 -1
  7. package/CHANGELOG.md +84 -0
  8. package/CODEOWNERS +4 -0
  9. package/README.md +97 -48
  10. package/graphql.configuration.json +5 -1
  11. package/images/marketplace/apollo-wordmark.png +0 -0
  12. package/jest.config.ts +14 -4
  13. package/jest.e2e.config.js +17 -0
  14. package/package.json +67 -68
  15. package/renovate.json +7 -0
  16. package/sampleWorkspace/clientSchema/apollo.config.cjs +10 -0
  17. package/sampleWorkspace/clientSchema/src/clientSchema.js +16 -0
  18. package/sampleWorkspace/clientSchema/src/test.js +18 -0
  19. package/sampleWorkspace/fixtures/starwarsSchema.graphql +299 -0
  20. package/sampleWorkspace/httpSchema/apollo.config.ts +8 -0
  21. package/sampleWorkspace/httpSchema/src/test.js +9 -0
  22. package/sampleWorkspace/localSchema/apollo.config.js +8 -0
  23. package/sampleWorkspace/localSchema/src/test.js +8 -0
  24. package/sampleWorkspace/localSchemaArray/apollo.config.js +12 -0
  25. package/sampleWorkspace/localSchemaArray/planets.graphql +20 -0
  26. package/sampleWorkspace/localSchemaArray/src/test.js +12 -0
  27. package/sampleWorkspace/sampleWorkspace.code-workspace +20 -0
  28. package/sampleWorkspace/spotifyGraph/apollo.config.mjs +5 -0
  29. package/sampleWorkspace/spotifyGraph/src/test.js +11 -0
  30. package/src/__e2e__/mockServer.js +117 -0
  31. package/src/__e2e__/mocks.js +13094 -0
  32. package/src/__e2e__/run.js +23 -0
  33. package/src/__e2e__/runTests.js +44 -0
  34. package/src/__e2e__/setup.js +1 -0
  35. package/src/__e2e__/vscode-environment.js +16 -0
  36. package/src/__e2e__/vscode.js +1 -0
  37. package/src/build.js +57 -0
  38. package/src/env/index.ts +0 -3
  39. package/src/extension.ts +251 -225
  40. package/src/language-server/__e2e__/clientSchema.e2e.ts +147 -0
  41. package/src/language-server/__e2e__/httpSchema.e2e.ts +21 -0
  42. package/src/language-server/__e2e__/localSchema.e2e.ts +25 -0
  43. package/src/language-server/__e2e__/localSchemaArray.e2e.ts +31 -0
  44. package/src/language-server/__e2e__/studioGraph.e2e.ts +65 -0
  45. package/src/language-server/__e2e__/utils.ts +151 -0
  46. package/src/language-server/__tests__/diagnostics.test.ts +8 -8
  47. package/src/language-server/__tests__/fileSet.test.ts +1 -1
  48. package/src/language-server/__tests__/fixtures/starwarsSchema.ts +2 -2
  49. package/src/language-server/config/__tests__/config.ts +22 -96
  50. package/src/language-server/config/__tests__/loadConfig.ts +120 -220
  51. package/src/language-server/config/__tests__/utils.ts +22 -29
  52. package/src/language-server/config/config.ts +221 -156
  53. package/src/language-server/config/loadConfig.ts +32 -153
  54. package/src/language-server/config/loadTsConfig.ts +70 -0
  55. package/src/language-server/config/utils.ts +5 -16
  56. package/src/language-server/diagnostics.ts +17 -8
  57. package/src/language-server/document.ts +16 -16
  58. package/src/language-server/engine/index.ts +57 -39
  59. package/src/language-server/engine/operations/frontendUrlRoot.ts +9 -1
  60. package/src/language-server/engine/operations/schemaTagsAndFieldStats.ts +9 -1
  61. package/src/language-server/errors/__tests__/NoMissingClientDirectives.test.ts +10 -5
  62. package/src/language-server/errors/logger.ts +1 -1
  63. package/src/language-server/errors/validation.ts +20 -23
  64. package/src/language-server/fileSet.ts +10 -12
  65. package/src/language-server/format.ts +1 -1
  66. package/src/language-server/graphqlTypes.ts +13020 -3455
  67. package/src/language-server/index.ts +0 -1
  68. package/src/language-server/languageProvider.ts +29 -32
  69. package/src/language-server/loadingHandler.ts +10 -27
  70. package/src/language-server/project/base.ts +32 -25
  71. package/src/language-server/project/client.ts +80 -114
  72. package/src/language-server/project/defaultClientSchema.ts +29 -4
  73. package/src/language-server/providers/schema/__tests__/file.ts +60 -19
  74. package/src/language-server/providers/schema/base.ts +2 -2
  75. package/src/language-server/providers/schema/endpoint.ts +15 -34
  76. package/src/language-server/providers/schema/engine.ts +25 -18
  77. package/src/language-server/providers/schema/file.ts +41 -32
  78. package/src/language-server/providers/schema/index.ts +5 -21
  79. package/src/language-server/server.ts +72 -50
  80. package/src/language-server/typings/graphql.d.ts +3 -3
  81. package/src/language-server/utilities/__tests__/graphql.test.ts +42 -54
  82. package/src/language-server/utilities/debouncer.ts +1 -1
  83. package/src/language-server/utilities/debug.ts +6 -5
  84. package/src/language-server/utilities/graphql.ts +17 -16
  85. package/src/language-server/utilities/source.ts +16 -16
  86. package/src/language-server/utilities/uri.ts +2 -2
  87. package/src/language-server/workspace.ts +29 -37
  88. package/src/languageServerClient.ts +4 -4
  89. package/src/messages.ts +38 -47
  90. package/src/tools/__tests__/buildServiceDefinition.test.ts +2 -2
  91. package/src/tools/buildServiceDefinition.ts +11 -11
  92. package/src/tools/schema/resolveObject.ts +1 -1
  93. package/src/tools/utilities/predicates.ts +1 -1
  94. package/src/utils.ts +7 -6
  95. package/syntaxes/graphql.dart.json +2 -4
  96. package/syntaxes/graphql.ex.json +1 -4
  97. package/tsconfig.build.json +8 -1
  98. package/tsconfig.json +5 -3
  99. package/src/env/fetch/fetch.ts +0 -32
  100. package/src/env/fetch/global.ts +0 -30
  101. package/src/env/fetch/index.d.ts +0 -2
  102. package/src/env/fetch/index.ts +0 -2
  103. package/src/env/fetch/url.ts +0 -9
  104. package/src/env/polyfills/array.ts +0 -17
  105. package/src/env/polyfills/index.ts +0 -2
  106. package/src/env/polyfills/object.ts +0 -7
  107. package/src/language-server/engine/GraphQLDataSource.ts +0 -124
  108. package/src/language-server/project/service.ts +0 -48
  109. package/src/language-server/typings/codemirror.d.ts +0 -4
@@ -0,0 +1,147 @@
1
+ import { TextEditor } from "vscode";
2
+ import { closeAllEditors, openEditor, testCompletion, getHover } from "./utils";
3
+
4
+ let editor: TextEditor;
5
+ beforeAll(async () => {
6
+ closeAllEditors();
7
+ editor = await openEditor("clientSchema/src/test.js");
8
+ });
9
+
10
+ test("completion", async () => {
11
+ // dro|id
12
+ await testCompletion(editor, [4, 7], [["droid", "Droid"]]);
13
+ // na|me
14
+ await testCompletion(editor, [5, 8], [["name", "String!"]]);
15
+ // mo|del
16
+ await testCompletion(editor, [6, 8], [["model", "String"]]);
17
+ });
18
+
19
+ test("hover", async () => {
20
+ // featu|reFlagDefer
21
+ expect(await getHover(editor, [3, 10])).toMatchInlineSnapshot(`
22
+ "\`\`\`graphql
23
+ Query.featureFlagDefer: Boolean!
24
+ \`\`\`
25
+
26
+ ---
27
+
28
+ \`Client-Only Field\` \`Resolved locally\`
29
+
30
+ ---
31
+
32
+ Whether to use defer"
33
+ `);
34
+
35
+ // @c|lient(always: false)
36
+ expect(await getHover(editor, [3, 24])).toMatchInlineSnapshot(`
37
+ "\`\`\`graphql
38
+ @client(always: Boolean)
39
+ \`\`\`
40
+
41
+ ---
42
+
43
+ Direct the client to resolve this field locally, either from the cache or local resolvers."
44
+ `);
45
+
46
+ // @client(alwa|ys: false)
47
+ expect(await getHover(editor, [3, 33])).toMatchInlineSnapshot(`
48
+ "\`\`\`graphql
49
+ always: Boolean
50
+ \`\`\`
51
+
52
+ ---
53
+
54
+ When true, the client will never use the cache for this value. See
55
+ https://www.apollographql.com/docs/react/local-state/local-resolvers/#forcing-resolvers-with-clientalways-true"
56
+ `);
57
+
58
+ // @expo|rt(as: "defer")
59
+ expect(await getHover(editor, [3, 49])).toMatchInlineSnapshot(`
60
+ "\`\`\`graphql
61
+ @export(as: String!)
62
+ \`\`\`
63
+
64
+ ---
65
+
66
+ Export this locally resolved field as a variable to be used in the remainder of this query. See
67
+ https://www.apollographql.com/docs/react/local-state/local-resolvers/#using-client-fields-as-variables"
68
+ `);
69
+ expect(await getHover(editor, [3, 53])).toMatchInlineSnapshot(`
70
+ "\`\`\`graphql
71
+ as: String!
72
+ \`\`\`
73
+
74
+ ---
75
+
76
+ The variable name to export this field as."
77
+ `);
78
+
79
+ // @nonre|active
80
+ expect(await getHover(editor, [7, 28])).toMatchInlineSnapshot(`
81
+ "\`\`\`graphql
82
+ @nonreactive
83
+ \`\`\`
84
+
85
+ ---
86
+
87
+ The @nonreactive directive can be used to mark query fields or fragment spreads and is used to indicate that changes to the data contained within the subtrees marked @nonreactive should not trigger rerendering.
88
+ This allows parent components to fetch data to be rendered by their children without rerendering themselves when the data corresponding with fields marked as @nonreactive change.
89
+ https://www.apollographql.com/docs/react/data/directives#nonreactive"
90
+ `);
91
+
92
+ // @def|er(if: $defer, label: "fc")
93
+ expect(await getHover(editor, [8, 14])).toMatchInlineSnapshot(`
94
+ "\`\`\`graphql
95
+ @defer(if: Boolean, label: String)
96
+ \`\`\`
97
+
98
+ ---
99
+
100
+ This directive enables your queries to receive data for specific fields incrementally, instead of receiving all field data at the same time.
101
+ This is helpful whenever some fields in a query take much longer to resolve than others.
102
+ https://www.apollographql.com/docs/react/data/directives#defer"
103
+ `);
104
+ //@defer(i|f: $defer, label: "fc")
105
+ expect(await getHover(editor, [8, 18])).toMatchInlineSnapshot(`
106
+ "\`\`\`graphql
107
+ if: Boolean
108
+ \`\`\`
109
+
110
+ ---
111
+
112
+ When true fragment may be deferred, if omitted defaults to true."
113
+ `);
114
+ //@defer(if: $defer, labe|l: "fc")
115
+ expect(await getHover(editor, [8, 33])).toMatchInlineSnapshot(`
116
+ "\`\`\`graphql
117
+ label: String
118
+ \`\`\`
119
+
120
+ ---
121
+
122
+ A unique label across all @defer and @stream directives in an operation.
123
+ This label should be used by GraphQL clients to identify the data from patch responses and associate it with the correct fragment.
124
+ If provided, the GraphQL Server must add it to the payload."
125
+ `);
126
+ // @connec|tion(key: "feed")
127
+ expect(await getHover(editor, [9, 53])).toMatchInlineSnapshot(`
128
+ "\`\`\`graphql
129
+ @connection(key: String!, filter: [String!])
130
+ \`\`\`
131
+
132
+ ---
133
+
134
+ Specify a custom store key for this result. See
135
+ https://www.apollographql.com/docs/react/caching/advanced-topics/#the-connection-directive"
136
+ `);
137
+ // @connection(ke|y: "feed")
138
+ expect(await getHover(editor, [9, 61])).toMatchInlineSnapshot(`
139
+ "\`\`\`graphql
140
+ key: String!
141
+ \`\`\`
142
+
143
+ ---
144
+
145
+ Specify the store key."
146
+ `);
147
+ });
@@ -0,0 +1,21 @@
1
+ import { TextEditor } from "vscode";
2
+ import { closeAllEditors, openEditor, testCompletion, getHover } from "./utils";
3
+
4
+ let editor: TextEditor;
5
+ beforeAll(async () => {
6
+ closeAllEditors();
7
+ editor = await openEditor("httpSchema/src/test.js");
8
+ });
9
+
10
+ test("completion", async () => {
11
+ await testCompletion(editor, [3, 7], [["books", "[Book]"]]);
12
+ await testCompletion(editor, [5, 9], [["author", "String"]]);
13
+ });
14
+
15
+ test("hover", async () => {
16
+ expect(await getHover(editor, [5, 9])).toMatchInlineSnapshot(`
17
+ "\`\`\`graphql
18
+ Book.author: String
19
+ \`\`\`"
20
+ `);
21
+ });
@@ -0,0 +1,25 @@
1
+ import { TextEditor } from "vscode";
2
+ import { closeAllEditors, openEditor, testCompletion, getHover } from "./utils";
3
+
4
+ let editor: TextEditor;
5
+ beforeAll(async () => {
6
+ closeAllEditors();
7
+ editor = await openEditor("localSchema/src/test.js");
8
+ });
9
+
10
+ test("completion", async () => {
11
+ await testCompletion(editor, [3, 7], [["droid", "Droid"]]);
12
+ await testCompletion(editor, [4, 8], [["name", "String!"]]);
13
+ });
14
+
15
+ test("hover", async () => {
16
+ expect(await getHover(editor, [4, 8])).toMatchInlineSnapshot(`
17
+ "\`\`\`graphql
18
+ Droid.name: String!
19
+ \`\`\`
20
+
21
+ ---
22
+
23
+ What others call this droid"
24
+ `);
25
+ });
@@ -0,0 +1,31 @@
1
+ import { TextEditor } from "vscode";
2
+ import { closeAllEditors, openEditor, testCompletion, getHover } from "./utils";
3
+
4
+ let editor: TextEditor;
5
+ beforeAll(async () => {
6
+ closeAllEditors();
7
+ editor = await openEditor("localSchemaArray/src/test.js");
8
+ });
9
+
10
+ test("completion", async () => {
11
+ await testCompletion(editor, [3, 7], [["droid", "Droid"]]);
12
+ await testCompletion(editor, [4, 8], [["name", "String!"]]);
13
+ await testCompletion(editor, [6, 7], [["planets", "[Planet]"]]);
14
+ });
15
+
16
+ test("hover", async () => {
17
+ expect(await getHover(editor, [4, 8])).toMatchInlineSnapshot(`
18
+ "\`\`\`graphql
19
+ Droid.name: String!
20
+ \`\`\`
21
+
22
+ ---
23
+
24
+ What others call this droid"
25
+ `);
26
+ expect(await getHover(editor, [6, 7])).toMatchInlineSnapshot(`
27
+ "\`\`\`graphql
28
+ Query.planets: [Planet]
29
+ \`\`\`"
30
+ `);
31
+ });
@@ -0,0 +1,65 @@
1
+ import { TextEditor } from "vscode";
2
+ import {
3
+ closeAllEditors,
4
+ openEditor,
5
+ testCompletion,
6
+ getHover,
7
+ getExtension,
8
+ getOutputChannelDocument,
9
+ reloadService,
10
+ } from "./utils";
11
+ import mocks from "../../__e2e__/mocks.js";
12
+ import vscode from "vscode";
13
+ import { scheduler } from "node:timers/promises";
14
+
15
+ const mockPort = Number(process.env.MOCK_SERVER_PORT);
16
+ beforeAll(async () => {
17
+ closeAllEditors();
18
+ });
19
+
20
+ test("completion", async () => {
21
+ const editor = await openEditor("spotifyGraph/src/test.js");
22
+ await testCompletion(editor, [4, 9], [["profile", "CurrentUserProfile!"]]);
23
+ await testCompletion(editor, [6, 15], [["displayName", "String"]]);
24
+ });
25
+
26
+ test("hover", async () => {
27
+ const editor = await openEditor("spotifyGraph/src/test.js");
28
+ expect(await getHover(editor, [4, 9])).toMatchInlineSnapshot(`
29
+ "\`\`\`graphql
30
+ CurrentUser.profile: CurrentUserProfile!
31
+ \`\`\`
32
+
33
+ ---
34
+
35
+ Get detailed profile information about the current user (including the current user's username)."
36
+ `);
37
+ });
38
+
39
+ test("wrong token", async () => {
40
+ try {
41
+ await mocks.sendMock(mockPort, mocks.GetSchemaByTag_WRONG_TOKEN);
42
+ await mocks.sendMock(mockPort, mocks.SchemaTagsAndFieldStats_WRONG_TOKEN);
43
+
44
+ const ext = getExtension();
45
+ ext.outputChannel.clear();
46
+ const outputDoc = await getOutputChannelDocument();
47
+
48
+ await reloadService();
49
+ const output = outputDoc.getText();
50
+
51
+ // currently, this logs twice, along with a full stracktrace, but no indication of where it came from
52
+ // this should be improved on.
53
+ expect(output).toContain(
54
+ `
55
+ [GraphQL error]: HTTP fetch failed from 'kotlin': 406: Not Acceptable
56
+ [GraphQL error]: Invalid credentials provided
57
+ ApolloError: HTTP fetch failed from 'kotlin': 406: Not Acceptable
58
+ Invalid credentials provided
59
+ at new ApolloError`.trim(),
60
+ );
61
+ } finally {
62
+ await mocks.loadDefaultMocks(mockPort);
63
+ await reloadService();
64
+ }
65
+ });
@@ -0,0 +1,151 @@
1
+ import * as vscode from "vscode";
2
+ import { join } from "node:path";
3
+ import { scheduler } from "node:timers/promises";
4
+ import { ProjectStats } from "src/messages";
5
+ import { VSCodeGraphQLExtension } from "src/extension";
6
+
7
+ function resolve(file: string) {
8
+ return join(__dirname, "..", "..", "..", "sampleWorkspace", file);
9
+ }
10
+
11
+ export async function closeAllEditors() {
12
+ while (vscode.window.visibleTextEditors.length > 0) {
13
+ await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
14
+ }
15
+ }
16
+
17
+ async function waitFor<T>(
18
+ fn: () => Promise<T>,
19
+ { retries = 15, delay = 200 } = {},
20
+ ) {
21
+ for (let i = 0; i < retries; i++) {
22
+ try {
23
+ return await fn();
24
+ } catch (error) {
25
+ if (i === retries - 1) {
26
+ throw error;
27
+ }
28
+ await scheduler.wait(delay);
29
+ }
30
+ }
31
+ throw "unreachable";
32
+ }
33
+
34
+ export async function openEditor(file: string) {
35
+ const textDocument = await vscode.workspace.openTextDocument(resolve(file));
36
+ const editor = await vscode.window.showTextDocument(textDocument);
37
+ await waitForLSP(file);
38
+ return editor;
39
+ }
40
+
41
+ export function waitForLSP(file: string) {
42
+ return waitFor(async () => {
43
+ const uri = vscode.Uri.file(resolve(file));
44
+ const stats = await vscode.commands.executeCommand<ProjectStats>(
45
+ "apollographql/fileStats",
46
+ uri.toString(),
47
+ );
48
+ expect(stats.loaded).toBe(true);
49
+ return stats;
50
+ });
51
+ }
52
+
53
+ export async function testCompletion(
54
+ editor: vscode.TextEditor,
55
+ [line, character]: [number, number],
56
+ expected: Array<[label: string, detail: string]>,
57
+ ) {
58
+ await waitFor(async () => {
59
+ editor.selection = new vscode.Selection(line, character, line, character);
60
+ // without this, the completion list is not updated
61
+ await scheduler.wait(300);
62
+ const completions =
63
+ await vscode.commands.executeCommand<vscode.CompletionList>(
64
+ "vscode.executeCompletionItemProvider",
65
+ editor.document.uri,
66
+ new vscode.Position(line, character),
67
+ );
68
+
69
+ const labels = completions.items.slice(0, expected.length).map((item) =>
70
+ typeof item.label === "string"
71
+ ? { label: item.label, detail: "" }
72
+ : {
73
+ label: item.label.label,
74
+ detail: item.detail,
75
+ },
76
+ );
77
+ expect(labels).toStrictEqual(
78
+ expected.map(([label, detail]) => ({ label, detail })),
79
+ );
80
+ });
81
+ }
82
+
83
+ export async function getHover(
84
+ editor: vscode.TextEditor,
85
+ [line, character]: [number, number],
86
+ ) {
87
+ editor.selection = new vscode.Selection(line, character, line, character);
88
+ // without this, the completion list is not updated
89
+ await scheduler.wait(300);
90
+ const hovers = await vscode.commands.executeCommand<vscode.Hover[]>(
91
+ "vscode.executeHoverProvider",
92
+ editor.document.uri,
93
+ new vscode.Position(line, character),
94
+ );
95
+
96
+ const item = hovers[0];
97
+ const content = item.contents[0];
98
+ const label = typeof content === "string" ? content : content.value;
99
+ return label;
100
+ }
101
+
102
+ export function getExtension(): VSCodeGraphQLExtension {
103
+ return vscode.extensions.getExtension("apollographql.vscode-apollo")!.exports;
104
+ }
105
+
106
+ export async function getOutputChannelDocument() {
107
+ const ext = getExtension();
108
+ ext.outputChannel.show();
109
+ await scheduler.wait(300);
110
+ const doc = vscode.workspace.textDocuments.find((d) =>
111
+ d.uri.path.startsWith("extension-output-apollographql.vscode-apollo"),
112
+ );
113
+ if (!doc) {
114
+ throw new Error("Output channel document not found");
115
+ }
116
+ return doc;
117
+ }
118
+
119
+ export function getReloadPromise() {
120
+ const disposables: vscode.Disposable[] = [];
121
+ const ext = getExtension();
122
+ const waitingTokens = new Set<number>();
123
+ disposables.push(
124
+ ext.client.onNotification(
125
+ ext.LanguageServerNotifications.Loading,
126
+ ({ token }) => {
127
+ waitingTokens.add(token);
128
+ },
129
+ ),
130
+ );
131
+ return new Promise<void>((resolve) => {
132
+ disposables.push(
133
+ ext.client.onNotification(
134
+ ext.LanguageServerNotifications.LoadingComplete,
135
+ (token) => {
136
+ waitingTokens.delete(token);
137
+ if (waitingTokens.size === 0) resolve();
138
+ },
139
+ ),
140
+ );
141
+ }).finally(() => disposables.forEach((d) => d.dispose()));
142
+ }
143
+
144
+ export async function reloadService() {
145
+ const reloaded = getReloadPromise();
146
+
147
+ vscode.commands.executeCommand("apollographql/reloadService");
148
+
149
+ await reloaded;
150
+ await scheduler.wait(100);
151
+ }
@@ -14,7 +14,7 @@ const validDocument = new GraphQLDocument(
14
14
  name
15
15
  }
16
16
  }
17
- }`)
17
+ }`),
18
18
  );
19
19
  const invalidDocument = new GraphQLDocument(
20
20
  new Source(`
@@ -25,7 +25,7 @@ const invalidDocument = new GraphQLDocument(
25
25
  name
26
26
  }
27
27
  }
28
- }`)
28
+ }`),
29
29
  );
30
30
  const documentWithTypes = new GraphQLDocument(
31
31
  new Source(`
@@ -43,41 +43,41 @@ const documentWithTypes = new GraphQLDocument(
43
43
  name
44
44
  }
45
45
  }
46
- }`)
46
+ }`),
47
47
  );
48
48
  const documentWithOffset = new GraphQLDocument(
49
49
  new Source(`query QueryWithOffset { hero { nam } }`, "testDocument", {
50
50
  line: 5,
51
51
  column: 10,
52
- })
52
+ }),
53
53
  );
54
54
  describe("Language server diagnostics", () => {
55
55
  describe("#collectExecutableDefinitionDiagnositics", () => {
56
56
  it("returns no diagnostics for a correct document", () => {
57
57
  const diagnostics = collectExecutableDefinitionDiagnositics(
58
58
  schema,
59
- validDocument
59
+ validDocument,
60
60
  );
61
61
  expect(diagnostics.length).toEqual(0);
62
62
  });
63
63
  it("returns two diagnostics for a document with two errors", () => {
64
64
  const diagnostics = collectExecutableDefinitionDiagnositics(
65
65
  schema,
66
- invalidDocument
66
+ invalidDocument,
67
67
  );
68
68
  expect(diagnostics.length).toEqual(2);
69
69
  });
70
70
  it("returns no diagnostics for a document that includes type definitions", () => {
71
71
  const diagnostics = collectExecutableDefinitionDiagnositics(
72
72
  schema,
73
- documentWithTypes
73
+ documentWithTypes,
74
74
  );
75
75
  expect(diagnostics.length).toEqual(0);
76
76
  });
77
77
  it("correctly offsets locations", () => {
78
78
  const diagnostics = collectExecutableDefinitionDiagnositics(
79
79
  schema,
80
- documentWithOffset
80
+ documentWithOffset,
81
81
  );
82
82
  expect(diagnostics.length).toEqual(1);
83
83
  expect(diagnostics[0].range.start.character).toEqual(40);
@@ -1,5 +1,5 @@
1
1
  import { FileSet } from "../fileSet";
2
- import URI from "vscode-uri";
2
+ import { URI } from "vscode-uri";
3
3
 
4
4
  describe("fileSet", () => {
5
5
  describe("includesFile", () => {
@@ -1,6 +1,6 @@
1
1
  import { IntrospectionQuery } from "graphql";
2
2
 
3
- export const starwarsSchema: IntrospectionQuery = {
3
+ export const starwarsSchema = {
4
4
  __schema: {
5
5
  queryType: {
6
6
  name: "Query",
@@ -1914,4 +1914,4 @@ export const starwarsSchema: IntrospectionQuery = {
1914
1914
  },
1915
1915
  ],
1916
1916
  },
1917
- };
1917
+ } as IntrospectionQuery;
@@ -1,128 +1,54 @@
1
- import { ApolloConfig, ApolloConfigFormat, DefaultConfigBase } from "../";
2
- import URI from "vscode-uri";
1
+ import { ClientConfig, parseApolloConfig } from "../";
2
+ import { URI } from "vscode-uri";
3
3
 
4
4
  describe("ApolloConfig", () => {
5
5
  describe("confifDirURI", () => {
6
6
  it("properly parses dir paths for configDirURI", () => {
7
7
  const uri = URI.parse("/test/dir/name");
8
- const config = new ApolloConfig(
9
- { service: { name: "hai", ...DefaultConfigBase } },
10
- uri
11
- );
8
+ const config = parseApolloConfig({ client: { service: "hai" } }, uri);
12
9
  // can be either /test/dir/name or \\test\\dir\\name depending on platform
13
10
  // this difference is fine :)
14
- expect(config.configDirURI?.fsPath).toMatch(
15
- /\/test\/dir\/name|\\test\\dir\\name/
11
+ expect(config?.configDirURI?.fsPath).toMatch(
12
+ /\/test\/dir\/name|\\test\\dir\\name/,
16
13
  );
17
14
  });
18
15
  it("properly parses filepaths for configDirURI", () => {
19
16
  const uri = URI.parse("/test/dir/name/apollo.config.js");
20
- const config = new ApolloConfig(
21
- { service: { name: "hai", ...DefaultConfigBase } },
22
- uri
17
+ const config = parseApolloConfig(
18
+ {
19
+ client: { service: "hai" },
20
+ },
21
+ uri,
23
22
  );
24
23
  // can be either /test/dir/name or \\test\\dir\\name depending on platform
25
24
  // this difference is fine :)
26
- expect(config.configDirURI?.fsPath).toMatch(
27
- /\/test\/dir\/name|\\test\\dir\\name/
25
+ expect(config?.configDirURI?.fsPath).toMatch(
26
+ /\/test\/dir\/name|\\test\\dir\\name/,
28
27
  );
29
28
  });
30
29
  });
31
30
 
32
- describe("projects", () => {
33
- it("creates a ClientConfig when client is present", () => {
34
- const rawConfig: ApolloConfigFormat = {
35
- client: { service: "my-service", ...DefaultConfigBase },
36
- };
37
- const config = new ApolloConfig(rawConfig);
38
- const projects = config.projects;
39
- expect(projects).toHaveLength(1);
40
- expect(projects[0].isClient).toBeTruthy();
41
- });
42
- it("creates a ServiceConfig when service is present", () => {
43
- const rawConfig: ApolloConfigFormat = {
44
- service: { name: "my-service", ...DefaultConfigBase },
45
- };
46
- const config = new ApolloConfig(rawConfig);
47
- const projects = config.projects;
48
-
49
- expect(projects).toHaveLength(1);
50
- expect(projects[0].isService).toBeTruthy();
51
- });
52
- it("creates multiple configs when both client and service are present", () => {
53
- const rawConfig: ApolloConfigFormat = {
54
- client: { service: "my-service", ...DefaultConfigBase },
55
- service: { name: "my-service", ...DefaultConfigBase },
56
- };
57
- const config = new ApolloConfig(rawConfig);
58
- const projects = config.projects;
59
-
60
- expect(projects).toHaveLength(2);
61
- expect(projects.find((c) => c.isClient)).toBeTruthy();
62
- expect(projects.find((c) => c.isService)).toBeTruthy();
63
- });
64
- });
65
-
66
31
  describe("variant", () => {
67
32
  it("gets default variant when none is set", () => {
68
- const config = new ApolloConfig({
69
- client: { service: "hai", ...DefaultConfigBase },
33
+ const config = parseApolloConfig({
34
+ client: { service: "hai" },
70
35
  });
71
- expect(config.variant).toEqual("current");
36
+ expect(config?.variant).toEqual("current");
72
37
  });
73
38
 
74
39
  it("gets variant from service specifier", () => {
75
- const config = new ApolloConfig({
76
- client: { service: "hai@master", ...DefaultConfigBase },
40
+ const config = parseApolloConfig({
41
+ client: { service: "hai@master" },
77
42
  });
78
- expect(config.variant).toEqual("master");
43
+ expect(config?.variant).toEqual("master");
79
44
  });
80
45
 
81
46
  it("can set and override variants", () => {
82
- const config = new ApolloConfig({
83
- client: { service: "hai@master", ...DefaultConfigBase },
47
+ const config = parseApolloConfig({
48
+ client: { service: "hai@master" },
84
49
  });
85
- config.variant = "new";
86
- expect(config.variant).toEqual("new");
87
- });
88
- });
89
-
90
- describe("setDefaults", () => {
91
- it("can override engine defaults", () => {
92
- const config = new ApolloConfig({ client: { ...DefaultConfigBase } });
93
- const overrides = {
94
- engine: {
95
- endpoint: "https://test.apollographql.com/api/graphql",
96
- },
97
- };
98
- config.setDefaults(overrides);
99
- expect(config.engine).toEqual(overrides.engine);
100
- });
101
-
102
- it("can override client defaults", () => {
103
- const config = new ApolloConfig({ client: { ...DefaultConfigBase } });
104
- const overrides = {
105
- client: {
106
- name: "my-client",
107
- service: "my-service@master",
108
- ...DefaultConfigBase,
109
- },
110
- };
111
- config.setDefaults(overrides);
112
- expect(config.client).toEqual(overrides.client);
113
- });
114
-
115
- it("can override service defaults", () => {
116
- const config = new ApolloConfig({ client: { ...DefaultConfigBase } });
117
- const overrides = {
118
- service: {
119
- name: "my-service",
120
- url: "localhost:9090",
121
- ...DefaultConfigBase,
122
- },
123
- };
124
- config.setDefaults(overrides);
125
- expect(config.service).toEqual(config.service);
50
+ config!.variant = "new";
51
+ expect(config?.variant).toEqual("new");
126
52
  });
127
53
  });
128
54
  });