From 0b69d18ac52ac9f4d64bf0a2ec8f15049cd51fe8 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 14:52:32 -0600 Subject: [PATCH 01/12] Remove client-only directives in MockLink --- .../core/mocking/__tests__/mockLink.ts | 160 ++++++++++++++++++ src/testing/core/mocking/mockLink.ts | 18 +- 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/src/testing/core/mocking/__tests__/mockLink.ts b/src/testing/core/mocking/__tests__/mockLink.ts index dc68b654505..3b3e9e26446 100644 --- a/src/testing/core/mocking/__tests__/mockLink.ts +++ b/src/testing/core/mocking/__tests__/mockLink.ts @@ -1,6 +1,7 @@ import gql from "graphql-tag"; import { MockLink, MockedResponse } from "../mockLink"; import { execute } from "../../../../link/core/execute"; +import { ObservableStream, spyOnConsole } from "../../../internal"; describe("MockedResponse.newData", () => { const setup = () => { @@ -126,3 +127,162 @@ describe("mockLink", () => { jest.advanceTimersByTime(MAXIMUM_DELAY); }); }); + +test("removes @nonreactive directives from fields", async () => { + const query = gql` + query A { + a + b + c @nonreactive + } + `; + + const link = new MockLink([ + { request: { query }, result: { data: { a: 1, b: 2, c: 3 } } }, + ]); + + { + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + b + c + } + `, + }) + ); + + await expect(stream.takeNext()).resolves.toEqual({ + data: { a: 1, b: 2, c: 3 }, + }); + } + + { + using spy = spyOnConsole("warn"); + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + b + c @nonreactive + } + `, + }) + ); + + expect(spy.warn).toHaveBeenCalledTimes(1); + expect(spy.warn).toHaveBeenCalledWith( + expect.stringMatching(/^No more mocked responses for the query/) + ); + + await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + } +}); + +test("removes @connection directives", async () => { + const query = gql` + query A { + a + b + c @connection(key: "test") + } + `; + + const link = new MockLink([ + { request: { query }, result: { data: { a: 1, b: 2, c: 3 } } }, + ]); + + { + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + b + c + } + `, + }) + ); + + await expect(stream.takeNext()).resolves.toEqual({ + data: { a: 1, b: 2, c: 3 }, + }); + } + + { + using spy = spyOnConsole("warn"); + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + b + c @connection(key: "test") + } + `, + }) + ); + + expect(spy.warn).toHaveBeenCalledTimes(1); + expect(spy.warn).toHaveBeenCalledWith( + expect.stringMatching(/^No more mocked responses for the query/) + ); + + await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + } +}); + +test("removes fields with @client directives", async () => { + const query = gql` + query A { + a + b + c @client + } + `; + + const link = new MockLink([ + { request: { query }, result: { data: { a: 1, b: 2 } } }, + ]); + + { + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + b + } + `, + }) + ); + + await expect(stream.takeNext()).resolves.toEqual({ data: { a: 1, b: 2 } }); + } + + { + using spy = spyOnConsole("warn"); + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + b + c @client + } + `, + }) + ); + + expect(spy.warn).toHaveBeenCalledTimes(1); + expect(spy.warn).toHaveBeenCalledWith( + expect.stringMatching(/^No more mocked responses for the query/) + ); + + await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + } +}); diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index 46b43cca6ad..c16acfc4851 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -6,6 +6,7 @@ import type { Operation, GraphQLRequest, FetchResult, + DocumentNode, } from "../../../link/core/index.js"; import { ApolloLink } from "../../../link/core/index.js"; @@ -17,6 +18,7 @@ import { cloneDeep, stringifyForDisplay, print, + removeDirectivesFromDocument, } from "../../../utilities/index.js"; export type ResultFunction> = (variables: V) => T; @@ -42,10 +44,22 @@ export interface MockLinkOptions { showWarnings?: boolean; } +function getServerQuery(document: DocumentNode) { + return removeDirectivesFromDocument( + [ + { name: "client", remove: true }, + { name: "connection" }, + { name: "nonreactive" }, + ], + document + ); +} + function requestToKey(request: GraphQLRequest, addTypename: Boolean): string { + const serverQuery = request.query ? getServerQuery(request.query) : null; const queryString = - request.query && - print(addTypename ? addTypenameToDocument(request.query) : request.query); + serverQuery && + print(addTypename ? addTypenameToDocument(serverQuery) : serverQuery); const requestKey = { query: queryString }; return JSON.stringify(requestKey); } From 2baa33d41572cd6e116ed3458871f91d70b38e2b Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:14:06 -0600 Subject: [PATCH 02/12] Add ability to not remove client only directives in MockLink --- .../core/mocking/__tests__/mockLink.ts | 53 +++++++++++++++++++ src/testing/core/mocking/mockLink.ts | 41 ++++++++++---- 2 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/testing/core/mocking/__tests__/mockLink.ts b/src/testing/core/mocking/__tests__/mockLink.ts index 3b3e9e26446..374e663d8df 100644 --- a/src/testing/core/mocking/__tests__/mockLink.ts +++ b/src/testing/core/mocking/__tests__/mockLink.ts @@ -286,3 +286,56 @@ test("removes fields with @client directives", async () => { await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); } }); + +test("leaves query as-is when removeClientOnlyDirectives is false", async () => { + const query = gql` + query A { + a + b @client + c @nonreactive + d @connection(key: "test") + } + `; + + const link = new MockLink( + [{ request: { query }, result: { data: { a: 1, c: 3, d: 4 } } }], + true, + { removeClientOnlyDirectives: false } + ); + + { + using spy = spyOnConsole("warn"); + const stream = new ObservableStream( + execute(link, { + query: gql` + query A { + a + c + d + } + `, + }) + ); + + expect(spy.warn).toHaveBeenCalledTimes(1); + expect(spy.warn).toHaveBeenCalledWith( + expect.stringMatching(/^No more mocked responses for the query/) + ); + + await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + } + + { + const link = new MockLink( + [{ request: { query }, result: { data: { a: 1, b: 2, c: 3, d: 4 } } }], + true, + { removeClientOnlyDirectives: false } + ); + + const stream = new ObservableStream(execute(link, { query })); + + await expect(stream.takeNext()).resolves.toEqual({ + data: { a: 1, b: 2, c: 3, d: 4 }, + }); + } +}); diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index c16acfc4851..84107a84855 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -42,6 +42,17 @@ export interface MockedResponse< export interface MockLinkOptions { showWarnings?: boolean; + + /** + * Determines whether to remove client-only directives from the query such as + * `@client`, `@nonreactive`, and `@connection`. This matches the behavior in + * the core client and ensures `MockLink` behaves more similarly to a + * GraphQL server which would not receive these directives in the request. + * + * @default true + * @since 3.10.4 + */ + removeClientOnlyDirectives?: boolean; } function getServerQuery(document: DocumentNode) { @@ -55,29 +66,44 @@ function getServerQuery(document: DocumentNode) { ); } -function requestToKey(request: GraphQLRequest, addTypename: Boolean): string { - const serverQuery = request.query ? getServerQuery(request.query) : null; +function requestToKey( + request: GraphQLRequest, + { + addTypename, + removeClientOnlyDirectives, + }: { addTypename: boolean; removeClientOnlyDirectives: boolean } +): string { + let serverQuery: DocumentNode | null = request.query; + + if (request.query && removeClientOnlyDirectives) { + serverQuery = getServerQuery(request.query); + } + const queryString = serverQuery && print(addTypename ? addTypenameToDocument(serverQuery) : serverQuery); const requestKey = { query: queryString }; + console.log(requestKey); return JSON.stringify(requestKey); } export class MockLink extends ApolloLink { public operation!: Operation; - public addTypename: Boolean = true; + public addTypename: boolean = true; public showWarnings: boolean = true; + public removeClientOnlyDirectives: boolean = true; private mockedResponsesByKey: { [key: string]: MockedResponse[] } = {}; constructor( mockedResponses: ReadonlyArray>, - addTypename: Boolean = true, + addTypename: boolean = true, options: MockLinkOptions = Object.create(null) ) { super(); this.addTypename = addTypename; this.showWarnings = options.showWarnings ?? true; + this.removeClientOnlyDirectives = + options.removeClientOnlyDirectives ?? true; if (mockedResponses) { mockedResponses.forEach((mockedResponse) => { @@ -89,10 +115,7 @@ export class MockLink extends ApolloLink { public addMockedResponse(mockedResponse: MockedResponse) { const normalizedMockedResponse = this.normalizeMockedResponse(mockedResponse); - const key = requestToKey( - normalizedMockedResponse.request, - this.addTypename - ); + const key = requestToKey(normalizedMockedResponse.request, this); let mockedResponses = this.mockedResponsesByKey[key]; if (!mockedResponses) { mockedResponses = []; @@ -103,7 +126,7 @@ export class MockLink extends ApolloLink { public request(operation: Operation): Observable | null { this.operation = operation; - const key = requestToKey(operation, this.addTypename); + const key = requestToKey(operation, this); const unmatchedVars: Array> = []; const requestVariables = operation.variables || {}; const mockedResponses = this.mockedResponsesByKey[key]; From cffe53bef656a4292fc529979fd4c2bfbe96fd71 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:14:54 -0600 Subject: [PATCH 03/12] Minor refactor to existing tests --- .../core/mocking/__tests__/mockLink.ts | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/testing/core/mocking/__tests__/mockLink.ts b/src/testing/core/mocking/__tests__/mockLink.ts index 374e663d8df..b16d5b45440 100644 --- a/src/testing/core/mocking/__tests__/mockLink.ts +++ b/src/testing/core/mocking/__tests__/mockLink.ts @@ -161,17 +161,7 @@ test("removes @nonreactive directives from fields", async () => { { using spy = spyOnConsole("warn"); - const stream = new ObservableStream( - execute(link, { - query: gql` - query A { - a - b - c @nonreactive - } - `, - }) - ); + const stream = new ObservableStream(execute(link, { query })); expect(spy.warn).toHaveBeenCalledTimes(1); expect(spy.warn).toHaveBeenCalledWith( @@ -215,17 +205,7 @@ test("removes @connection directives", async () => { { using spy = spyOnConsole("warn"); - const stream = new ObservableStream( - execute(link, { - query: gql` - query A { - a - b - c @connection(key: "test") - } - `, - }) - ); + const stream = new ObservableStream(execute(link, { query })); expect(spy.warn).toHaveBeenCalledTimes(1); expect(spy.warn).toHaveBeenCalledWith( From 9e5d738ceb0a3b408bbb031ddf66f4ab6eebd243 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:16:15 -0600 Subject: [PATCH 04/12] Add maxUsageCount to all tests --- .../core/mocking/__tests__/mockLink.ts | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/testing/core/mocking/__tests__/mockLink.ts b/src/testing/core/mocking/__tests__/mockLink.ts index b16d5b45440..34a96ee51d8 100644 --- a/src/testing/core/mocking/__tests__/mockLink.ts +++ b/src/testing/core/mocking/__tests__/mockLink.ts @@ -138,7 +138,11 @@ test("removes @nonreactive directives from fields", async () => { `; const link = new MockLink([ - { request: { query }, result: { data: { a: 1, b: 2, c: 3 } } }, + { + request: { query }, + result: { data: { a: 1, b: 2, c: 3 } }, + maxUsageCount: Number.POSITIVE_INFINITY, + }, ]); { @@ -182,7 +186,11 @@ test("removes @connection directives", async () => { `; const link = new MockLink([ - { request: { query }, result: { data: { a: 1, b: 2, c: 3 } } }, + { + request: { query }, + result: { data: { a: 1, b: 2, c: 3 } }, + maxUsageCount: Number.POSITIVE_INFINITY, + }, ]); { @@ -226,7 +234,11 @@ test("removes fields with @client directives", async () => { `; const link = new MockLink([ - { request: { query }, result: { data: { a: 1, b: 2 } } }, + { + request: { query }, + result: { data: { a: 1, b: 2 } }, + maxUsageCount: Number.POSITIVE_INFINITY, + }, ]); { @@ -278,7 +290,13 @@ test("leaves query as-is when removeClientOnlyDirectives is false", async () => `; const link = new MockLink( - [{ request: { query }, result: { data: { a: 1, c: 3, d: 4 } } }], + [ + { + request: { query }, + result: { data: { a: 1, c: 3, d: 4 } }, + maxUsageCount: Number.POSITIVE_INFINITY, + }, + ], true, { removeClientOnlyDirectives: false } ); @@ -306,12 +324,6 @@ test("leaves query as-is when removeClientOnlyDirectives is false", async () => } { - const link = new MockLink( - [{ request: { query }, result: { data: { a: 1, b: 2, c: 3, d: 4 } } }], - true, - { removeClientOnlyDirectives: false } - ); - const stream = new ObservableStream(execute(link, { query })); await expect(stream.takeNext()).resolves.toEqual({ From b08d5ad9f47da8dc1f942f09b93e398eadcfd8e2 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:17:54 -0600 Subject: [PATCH 05/12] Revert type signature closer to original function --- src/testing/core/mocking/mockLink.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index 84107a84855..db3e85b73a5 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -68,10 +68,8 @@ function getServerQuery(document: DocumentNode) { function requestToKey( request: GraphQLRequest, - { - addTypename, - removeClientOnlyDirectives, - }: { addTypename: boolean; removeClientOnlyDirectives: boolean } + addTypename: boolean, + removeClientOnlyDirectives?: boolean ): string { let serverQuery: DocumentNode | null = request.query; @@ -115,7 +113,11 @@ export class MockLink extends ApolloLink { public addMockedResponse(mockedResponse: MockedResponse) { const normalizedMockedResponse = this.normalizeMockedResponse(mockedResponse); - const key = requestToKey(normalizedMockedResponse.request, this); + const key = requestToKey( + normalizedMockedResponse.request, + this.addTypename, + this.removeClientOnlyDirectives + ); let mockedResponses = this.mockedResponsesByKey[key]; if (!mockedResponses) { mockedResponses = []; @@ -126,7 +128,11 @@ export class MockLink extends ApolloLink { public request(operation: Operation): Observable | null { this.operation = operation; - const key = requestToKey(operation, this); + const key = requestToKey( + operation, + this.addTypename, + this.removeClientOnlyDirectives + ); const unmatchedVars: Array> = []; const requestVariables = operation.variables || {}; const mockedResponses = this.mockedResponsesByKey[key]; From 14f77f9da4f0f9e727ea55d2e570762a0af7eb71 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:22:21 -0600 Subject: [PATCH 06/12] Remove stray console.log --- src/testing/core/mocking/mockLink.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index db3e85b73a5..02ea636a503 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -81,7 +81,6 @@ function requestToKey( serverQuery && print(addTypename ? addTypenameToDocument(serverQuery) : serverQuery); const requestKey = { query: queryString }; - console.log(requestKey); return JSON.stringify(requestKey); } From 3be86e29b5dd8218fdaf2650c3088986555e9c27 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:34:44 -0600 Subject: [PATCH 07/12] Remove nonreactive directive in normalizeMockedResponse --- src/testing/core/mocking/mockLink.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index 02ea636a503..34e2bd5fb56 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -6,7 +6,6 @@ import type { Operation, GraphQLRequest, FetchResult, - DocumentNode, } from "../../../link/core/index.js"; import { ApolloLink } from "../../../link/core/index.js"; @@ -14,11 +13,11 @@ import { Observable, addTypenameToDocument, removeClientSetsFromDocument, - removeConnectionDirectiveFromDocument, cloneDeep, stringifyForDisplay, print, removeDirectivesFromDocument, + checkDocument, } from "../../../utilities/index.js"; export type ResultFunction> = (variables: V) => T; @@ -244,11 +243,12 @@ ${unmatchedVars.map((d) => ` ${stringifyForDisplay(d)}`).join("\n")} mockedResponse: MockedResponse ): MockedResponse { const newMockedResponse = cloneDeep(mockedResponse); - const queryWithoutConnection = removeConnectionDirectiveFromDocument( - newMockedResponse.request.query + const queryWithoutClientOnlyDirectives = removeDirectivesFromDocument( + [{ name: "connection" }, { name: "nonreactive" }], + checkDocument(newMockedResponse.request.query) ); - invariant(queryWithoutConnection, "query is required"); - newMockedResponse.request.query = queryWithoutConnection!; + invariant(queryWithoutClientOnlyDirectives, "query is required"); + newMockedResponse.request.query = queryWithoutClientOnlyDirectives!; const query = removeClientSetsFromDocument(newMockedResponse.request.query); if (query) { newMockedResponse.request.query = query; From d38606063e3ad555c376b97bbec48bf913b08de4 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:35:09 -0600 Subject: [PATCH 08/12] Remove removeClientOnlyDirectives option --- .../core/mocking/__tests__/mockLink.ts | 53 ------------------- src/testing/core/mocking/mockLink.ts | 50 ++--------------- 2 files changed, 5 insertions(+), 98 deletions(-) diff --git a/src/testing/core/mocking/__tests__/mockLink.ts b/src/testing/core/mocking/__tests__/mockLink.ts index 34a96ee51d8..ed0dc24de2b 100644 --- a/src/testing/core/mocking/__tests__/mockLink.ts +++ b/src/testing/core/mocking/__tests__/mockLink.ts @@ -278,56 +278,3 @@ test("removes fields with @client directives", async () => { await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); } }); - -test("leaves query as-is when removeClientOnlyDirectives is false", async () => { - const query = gql` - query A { - a - b @client - c @nonreactive - d @connection(key: "test") - } - `; - - const link = new MockLink( - [ - { - request: { query }, - result: { data: { a: 1, c: 3, d: 4 } }, - maxUsageCount: Number.POSITIVE_INFINITY, - }, - ], - true, - { removeClientOnlyDirectives: false } - ); - - { - using spy = spyOnConsole("warn"); - const stream = new ObservableStream( - execute(link, { - query: gql` - query A { - a - c - d - } - `, - }) - ); - - expect(spy.warn).toHaveBeenCalledTimes(1); - expect(spy.warn).toHaveBeenCalledWith( - expect.stringMatching(/^No more mocked responses for the query/) - ); - - await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); - } - - { - const stream = new ObservableStream(execute(link, { query })); - - await expect(stream.takeNext()).resolves.toEqual({ - data: { a: 1, b: 2, c: 3, d: 4 }, - }); - } -}); diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index 34e2bd5fb56..76114da59c2 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -41,44 +41,12 @@ export interface MockedResponse< export interface MockLinkOptions { showWarnings?: boolean; - - /** - * Determines whether to remove client-only directives from the query such as - * `@client`, `@nonreactive`, and `@connection`. This matches the behavior in - * the core client and ensures `MockLink` behaves more similarly to a - * GraphQL server which would not receive these directives in the request. - * - * @default true - * @since 3.10.4 - */ - removeClientOnlyDirectives?: boolean; -} - -function getServerQuery(document: DocumentNode) { - return removeDirectivesFromDocument( - [ - { name: "client", remove: true }, - { name: "connection" }, - { name: "nonreactive" }, - ], - document - ); } -function requestToKey( - request: GraphQLRequest, - addTypename: boolean, - removeClientOnlyDirectives?: boolean -): string { - let serverQuery: DocumentNode | null = request.query; - - if (request.query && removeClientOnlyDirectives) { - serverQuery = getServerQuery(request.query); - } - +function requestToKey(request: GraphQLRequest, addTypename: boolean): string { const queryString = - serverQuery && - print(addTypename ? addTypenameToDocument(serverQuery) : serverQuery); + request.query && + print(addTypename ? addTypenameToDocument(request.query) : request.query); const requestKey = { query: queryString }; return JSON.stringify(requestKey); } @@ -87,7 +55,6 @@ export class MockLink extends ApolloLink { public operation!: Operation; public addTypename: boolean = true; public showWarnings: boolean = true; - public removeClientOnlyDirectives: boolean = true; private mockedResponsesByKey: { [key: string]: MockedResponse[] } = {}; constructor( @@ -98,8 +65,6 @@ export class MockLink extends ApolloLink { super(); this.addTypename = addTypename; this.showWarnings = options.showWarnings ?? true; - this.removeClientOnlyDirectives = - options.removeClientOnlyDirectives ?? true; if (mockedResponses) { mockedResponses.forEach((mockedResponse) => { @@ -113,8 +78,7 @@ export class MockLink extends ApolloLink { this.normalizeMockedResponse(mockedResponse); const key = requestToKey( normalizedMockedResponse.request, - this.addTypename, - this.removeClientOnlyDirectives + this.addTypename ); let mockedResponses = this.mockedResponsesByKey[key]; if (!mockedResponses) { @@ -126,11 +90,7 @@ export class MockLink extends ApolloLink { public request(operation: Operation): Observable | null { this.operation = operation; - const key = requestToKey( - operation, - this.addTypename, - this.removeClientOnlyDirectives - ); + const key = requestToKey(operation, this.addTypename); const unmatchedVars: Array> = []; const requestVariables = operation.variables || {}; const mockedResponses = this.mockedResponsesByKey[key]; From afb216738ee4c7de5b549637206a5ea68ed492b5 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:37:38 -0600 Subject: [PATCH 09/12] Revert type change for addTypename --- src/testing/core/mocking/mockLink.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index 76114da59c2..09bdf0a6a4a 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -43,7 +43,7 @@ export interface MockLinkOptions { showWarnings?: boolean; } -function requestToKey(request: GraphQLRequest, addTypename: boolean): string { +function requestToKey(request: GraphQLRequest, addTypename: Boolean): string { const queryString = request.query && print(addTypename ? addTypenameToDocument(request.query) : request.query); @@ -53,13 +53,13 @@ function requestToKey(request: GraphQLRequest, addTypename: boolean): string { export class MockLink extends ApolloLink { public operation!: Operation; - public addTypename: boolean = true; + public addTypename: Boolean = true; public showWarnings: boolean = true; private mockedResponsesByKey: { [key: string]: MockedResponse[] } = {}; constructor( mockedResponses: ReadonlyArray>, - addTypename: boolean = true, + addTypename: Boolean = true, options: MockLinkOptions = Object.create(null) ) { super(); From f03b6fed7c94abe2621b34470f7df1e9ec1e6eba Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 13 May 2024 15:47:33 -0600 Subject: [PATCH 10/12] Add changeset --- .changeset/serious-candles-arrive.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/serious-candles-arrive.md diff --git a/.changeset/serious-candles-arrive.md b/.changeset/serious-candles-arrive.md new file mode 100644 index 00000000000..4f9a8d4536d --- /dev/null +++ b/.changeset/serious-candles-arrive.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +Remove `@nonreactive` directives from queries passed to `MockLink` to ensure they are properly matched. From 1f0e897306b631ac1c5221a870971302c7f9f750 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Tue, 14 May 2024 10:37:56 -0600 Subject: [PATCH 11/12] Reorganize tests to better mimic actual usage --- .../core/mocking/__tests__/mockLink.ts | 138 +++++++++--------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/src/testing/core/mocking/__tests__/mockLink.ts b/src/testing/core/mocking/__tests__/mockLink.ts index ed0dc24de2b..3813f291b47 100644 --- a/src/testing/core/mocking/__tests__/mockLink.ts +++ b/src/testing/core/mocking/__tests__/mockLink.ts @@ -1,7 +1,7 @@ import gql from "graphql-tag"; import { MockLink, MockedResponse } from "../mockLink"; import { execute } from "../../../../link/core/execute"; -import { ObservableStream, spyOnConsole } from "../../../internal"; +import { ObservableStream } from "../../../internal"; describe("MockedResponse.newData", () => { const setup = () => { @@ -129,25 +129,29 @@ describe("mockLink", () => { }); test("removes @nonreactive directives from fields", async () => { - const query = gql` + const serverQuery = gql` query A { a b - c @nonreactive + c } `; const link = new MockLink([ { - request: { query }, + request: { + query: gql` + query A { + a + b + c @nonreactive + } + `, + }, result: { data: { a: 1, b: 2, c: 3 } }, - maxUsageCount: Number.POSITIVE_INFINITY, }, - ]); - - { - const stream = new ObservableStream( - execute(link, { + { + request: { query: gql` query A { a @@ -155,8 +159,13 @@ test("removes @nonreactive directives from fields", async () => { c } `, - }) - ); + }, + result: { data: { a: 4, b: 5, c: 6 } }, + }, + ]); + + { + const stream = new ObservableStream(execute(link, { query: serverQuery })); await expect(stream.takeNext()).resolves.toEqual({ data: { a: 1, b: 2, c: 3 }, @@ -164,38 +173,38 @@ test("removes @nonreactive directives from fields", async () => { } { - using spy = spyOnConsole("warn"); - const stream = new ObservableStream(execute(link, { query })); + const stream = new ObservableStream(execute(link, { query: serverQuery })); - expect(spy.warn).toHaveBeenCalledTimes(1); - expect(spy.warn).toHaveBeenCalledWith( - expect.stringMatching(/^No more mocked responses for the query/) - ); - - await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + await expect(stream.takeNext()).resolves.toEqual({ + data: { a: 4, b: 5, c: 6 }, + }); } }); test("removes @connection directives", async () => { - const query = gql` + const serverQuery = gql` query A { a b - c @connection(key: "test") + c } `; const link = new MockLink([ { - request: { query }, + request: { + query: gql` + query A { + a + b + c @connection(key: "test") + } + `, + }, result: { data: { a: 1, b: 2, c: 3 } }, - maxUsageCount: Number.POSITIVE_INFINITY, }, - ]); - - { - const stream = new ObservableStream( - execute(link, { + { + request: { query: gql` query A { a @@ -203,8 +212,13 @@ test("removes @connection directives", async () => { c } `, - }) - ); + }, + result: { data: { a: 4, b: 5, c: 6 } }, + }, + ]); + + { + const stream = new ObservableStream(execute(link, { query: serverQuery })); await expect(stream.takeNext()).resolves.toEqual({ data: { a: 1, b: 2, c: 3 }, @@ -212,69 +226,57 @@ test("removes @connection directives", async () => { } { - using spy = spyOnConsole("warn"); - const stream = new ObservableStream(execute(link, { query })); - - expect(spy.warn).toHaveBeenCalledTimes(1); - expect(spy.warn).toHaveBeenCalledWith( - expect.stringMatching(/^No more mocked responses for the query/) - ); + const stream = new ObservableStream(execute(link, { query: serverQuery })); - await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + await expect(stream.takeNext()).resolves.toEqual({ + data: { a: 4, b: 5, c: 6 }, + }); } }); test("removes fields with @client directives", async () => { - const query = gql` + const serverQuery = gql` query A { a b - c @client } `; const link = new MockLink([ { - request: { query }, - result: { data: { a: 1, b: 2 } }, - maxUsageCount: Number.POSITIVE_INFINITY, - }, - ]); - - { - const stream = new ObservableStream( - execute(link, { + request: { query: gql` query A { a b + c @client } `, - }) - ); - - await expect(stream.takeNext()).resolves.toEqual({ data: { a: 1, b: 2 } }); - } - - { - using spy = spyOnConsole("warn"); - const stream = new ObservableStream( - execute(link, { + }, + result: { data: { a: 1, b: 2 } }, + }, + { + request: { query: gql` query A { a b - c @client } `, - }) - ); + }, + result: { data: { a: 3, b: 4 } }, + }, + ]); - expect(spy.warn).toHaveBeenCalledTimes(1); - expect(spy.warn).toHaveBeenCalledWith( - expect.stringMatching(/^No more mocked responses for the query/) - ); + { + const stream = new ObservableStream(execute(link, { query: serverQuery })); + + await expect(stream.takeNext()).resolves.toEqual({ data: { a: 1, b: 2 } }); + } + + { + const stream = new ObservableStream(execute(link, { query: serverQuery })); - await expect(stream.takeError()).resolves.toEqual(expect.any(Error)); + await expect(stream.takeNext()).resolves.toEqual({ data: { a: 3, b: 4 } }); } }); From 1e48c5611169eaa9ad51de112364f387cfb5f96c Mon Sep 17 00:00:00 2001 From: jerelmiller Date: Tue, 14 May 2024 16:46:57 +0000 Subject: [PATCH 12/12] Clean up Prettier, Size-limit, and Api-Extractor --- .size-limits.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.size-limits.json b/.size-limits.json index 05c84cd4f6a..e90e42c4eea 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 39581, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32832 + "dist/apollo-client.min.cjs": 39579, + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32825 }