From 2093668c597ae160d78c8b744f4cdf2da85ed798 Mon Sep 17 00:00:00 2001 From: Paul Rowe Date: Sat, 25 Jul 2020 21:01:09 -0500 Subject: [PATCH 01/13] some tests --- .vscode/settings.json | 3 +- .../mocking/__tests__/MockedProvider.test.tsx | 106 ++++++++++++++++++ src/utilities/testing/mocking/mockLink.ts | 5 +- 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4ab27d98c2e..4f5d484db44 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,6 @@ "typescript.tsdk": "../node_modules/typescript/lib", "cSpell.enableFiletypes": [ "mdx" - ] + ], + "deno.enable": false } diff --git a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx index a89efcb2881..723e79f54ad 100644 --- a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx +++ b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx @@ -94,6 +94,57 @@ describe('General use', () => { return wait().then(resolve, reject); }); + itAsync('should pass the variables to the variableMatcher', async (resolve, reject) => { + function Component({ ...variables }: Variables) { + useQuery(query, { variables }); + return null; + } + + const mock2: MockedResponse = { + request: { + query + }, + variableMatcher: jest.fn().mockReturnValue(true), + result: { data: { user } } + }; + + render( + + + + ); + + return wait(() => { + expect(mock2.variableMatcher as jest.Mock).toHaveBeenCalledWith(variables); + }).then(resolve, reject); + }); + + itAsync('should use a mock if the variableMatcher returns true', async (resolve, reject) => { + function Component({ username }: Variables) { + const { loading, data } = useQuery(query, { variables }); + if (!loading) { + expect(data!.user).toMatchSnapshot(); + } + return null; + } + + const mock2: MockedResponse = { + request: { + query + }, + variableMatcher: (v: Variables) => v.username === variables.username, + result: { data: { user } } + }; + + render( + + + + ); + + return wait().then(resolve, reject); + }); + itAsync('should allow querying with the typename', async (resolve, reject) => { function Component({ username }: Variables) { const { loading, data } = useQuery(query, { variables }); @@ -170,6 +221,33 @@ describe('General use', () => { }).then(resolve, reject); }); + itAsync('should error if the variableMatcher returns false', async (resolve, reject) => { + function Component({ ...variables }: Variables) { + useQuery(query, { variables }); + return null; + } + + const mock2: MockedResponse = { + request: { + query + }, + variableMatcher: () => false, + result: { data: { user } } + }; + + const link = ApolloLink.from([errorLink, new MockLink([mock2])]); + + render( + + + + ); + + return wait(() => { + expect(errorThrown).toBeTruthy(); + }).then(resolve, reject); + }); + itAsync('should error if the variables do not deep equal', async (resolve, reject) => { function Component({ ...variables }: Variables) { useQuery(query, { variables }); @@ -306,6 +384,34 @@ describe('General use', () => { }).then(resolve, reject); }); + itAsync('should error if both variables and a variableMatcher are provided', async (resolve, reject) => { + function Component({ ...variables }: Variables) { + useQuery(query, { variables }); + return null; + } + + const mock2: MockedResponse = { + request: { + query, + variables + }, + variableMatcher: () => true, + result: { data: { user } } + }; + + const link = ApolloLink.from([errorLink, new MockLink([mock2])]); + + render( + + + + ); + + return wait(() => { + expect(errorThrown).toBeTruthy(); + }).then(resolve, reject); + }); + it('should pass down props prop in mock as props for the component', () => { function Component({ ...variables }) { expect(variables.foo).toBe('bar'); diff --git a/src/utilities/testing/mocking/mockLink.ts b/src/utilities/testing/mocking/mockLink.ts index c74b5dba244..f10b3acaa2b 100644 --- a/src/utilities/testing/mocking/mockLink.ts +++ b/src/utilities/testing/mocking/mockLink.ts @@ -19,11 +19,14 @@ import { export type ResultFunction = () => T; -export interface MockedResponse> { +export type VariableMatcher = (variables: V) => boolean; + +export interface MockedResponse, TVariables = Record> { request: GraphQLRequest; result?: FetchResult | ResultFunction>; error?: Error; delay?: number; + variableMatcher?: VariableMatcher, newData?: ResultFunction; } From 2fc758ab6512f7d62ed3f508a5ca7b71ffdcb6d3 Mon Sep 17 00:00:00 2001 From: Paul Rowe Date: Sat, 25 Jul 2020 21:17:52 -0500 Subject: [PATCH 02/13] all green --- .../mocking/__tests__/MockedProvider.test.tsx | 20 +++---------------- .../MockedProvider.test.tsx.snap | 7 +++++++ src/utilities/testing/mocking/mockLink.ts | 20 ++++++++++++++++--- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx index 723e79f54ad..85d66e1fff2 100644 --- a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx +++ b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx @@ -384,12 +384,7 @@ describe('General use', () => { }).then(resolve, reject); }); - itAsync('should error if both variables and a variableMatcher are provided', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - + it('should error if both variables and a variableMatcher are provided', () => { const mock2: MockedResponse = { request: { query, @@ -399,17 +394,8 @@ describe('General use', () => { result: { data: { user } } }; - const link = ApolloLink.from([errorLink, new MockLink([mock2])]); - - render( - - - - ); - - return wait(() => { - expect(errorThrown).toBeTruthy(); - }).then(resolve, reject); + expect(() => new MockLink([mock2])) + .toThrow('Mocked response should contain either variableMatcher or request.variables'); }); it('should pass down props prop in mock as props for the component', () => { diff --git a/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap b/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap index 32de2833292..efc09e46930 100644 --- a/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap +++ b/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap @@ -22,3 +22,10 @@ Object { }, } `; + +exports[`General use should use a mock if the variableMatcher returns true 1`] = ` +Object { + "__typename": "User", + "id": "user_id", +} +`; diff --git a/src/utilities/testing/mocking/mockLink.ts b/src/utilities/testing/mocking/mockLink.ts index f10b3acaa2b..ddf7a4771bc 100644 --- a/src/utilities/testing/mocking/mockLink.ts +++ b/src/utilities/testing/mocking/mockLink.ts @@ -78,9 +78,7 @@ export class MockLink extends ApolloLink { let responseIndex: number = 0; const response = (this.mockedResponsesByKey[key] || []).find( (res, index) => { - const requestVariables = operation.variables || {}; - const mockedResponseVariables = res.request.variables || {}; - if (equal(requestVariables, mockedResponseVariables)) { + if (res.variableMatcher && res.variableMatcher(operation.variables)) { responseIndex = index; return true; } @@ -152,8 +150,24 @@ export class MockLink extends ApolloLink { if (query) { newMockedResponse.request.query = query; } + this.normalizeVariableMatching(newMockedResponse); return newMockedResponse; } + + private normalizeVariableMatching(mockedResponse: MockedResponse) { + const variables = mockedResponse.request.variables; + if (mockedResponse.variableMatcher && variables) { + throw new Error('Mocked response should contain either variableMatcher or request.variables'); + } + + if (!mockedResponse.variableMatcher) { + mockedResponse.variableMatcher = (vars) => { + const requestVariables = vars || {}; + const mockedResponseVariables = variables || {}; + return equal(requestVariables, mockedResponseVariables); + }; + } + } } export interface MockApolloLink extends ApolloLink { From 51d9deb3fb4bff23ed5226325657c3d1f88eae36 Mon Sep 17 00:00:00 2001 From: Paul Rowe Date: Sat, 25 Jul 2020 21:27:44 -0500 Subject: [PATCH 03/13] result function is now taking variables --- .../mocking/__tests__/MockedProvider.test.tsx | 25 +++++++++++++++++++ src/utilities/testing/mocking/mockLink.ts | 8 +++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx index 85d66e1fff2..f4d9b35ebbe 100644 --- a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx +++ b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx @@ -94,6 +94,31 @@ describe('General use', () => { return wait().then(resolve, reject); }); + itAsync('should pass the variables to the result function', async (resolve, reject) => { + function Component({ ...variables }: Variables) { + useQuery(query, { variables }); + return null; + } + + const mock2: MockedResponse = { + request: { + query, + variables + }, + result: jest.fn().mockResolvedValue({ data: { user } }) + }; + + render( + + + + ); + + return wait(() => { + expect(mock2.result as jest.Mock).toHaveBeenCalledWith(variables); + }).then(resolve, reject); + }); + itAsync('should pass the variables to the variableMatcher', async (resolve, reject) => { function Component({ ...variables }: Variables) { useQuery(query, { variables }); diff --git a/src/utilities/testing/mocking/mockLink.ts b/src/utilities/testing/mocking/mockLink.ts index ddf7a4771bc..edce38ded05 100644 --- a/src/utilities/testing/mocking/mockLink.ts +++ b/src/utilities/testing/mocking/mockLink.ts @@ -17,13 +17,13 @@ import { cloneDeep, } from '../../../utilities'; -export type ResultFunction = () => T; +export type ResultFunction> = (variables: V) => T; export type VariableMatcher = (variables: V) => boolean; export interface MockedResponse, TVariables = Record> { request: GraphQLRequest; - result?: FetchResult | ResultFunction>; + result?: FetchResult | ResultFunction, TVariables>; error?: Error; delay?: number; variableMatcher?: VariableMatcher, @@ -100,7 +100,7 @@ export class MockLink extends ApolloLink { const { newData } = response!; if (newData) { - response!.result = newData(); + response!.result = newData(operation.variables); this.mockedResponsesByKey[key].push(response!); } @@ -121,7 +121,7 @@ export class MockLink extends ApolloLink { if (result) { observer.next( typeof result === 'function' - ? (result as ResultFunction)() + ? (result as ResultFunction)(operation.variables) : result ); } From 6528142eb57f8c5d48c9b9e77822dc56e6f7df61 Mon Sep 17 00:00:00 2001 From: Paul Rowe Date: Sat, 25 Jul 2020 21:37:19 -0500 Subject: [PATCH 04/13] adding documentation --- docs/source/development-testing/testing.mdx | 39 ++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/source/development-testing/testing.mdx b/docs/source/development-testing/testing.mdx index 9872572037f..f78b8323229 100644 --- a/docs/source/development-testing/testing.mdx +++ b/docs/source/development-testing/testing.mdx @@ -117,7 +117,7 @@ it('renders without error', () => { }); ``` -The `mocks` array takes objects with specific `request`s and their associated `result`s. When the provider receives a `GET_DOG_QUERY` with matching `variables`, it returns the corresponding object from the `result` key. A `result` may alternatively be a function returning the object: +The `mocks` array takes objects with specific `request`s and their associated `result`s. When the provider receives a `GET_DOG_QUERY` with matching `variables`, it returns the corresponding object from the `result` key. A `result` may alternatively be a function that takes variables and returns the object: ```js const mocks = [ @@ -247,6 +247,43 @@ const dogMock = { }; ``` +## Testing with dynamic variables + +Sometimes, the exact value of the variables being passed are not known. The `MockedResponse` object takes a `variableMatcher` property that is a function that takes the variables and return a bool indication if this mock should match the invocation for the provided query. +You cannot specify this parameter and `request.variables`: + +For example, this mock will match all dog queries: + +```js +const dogMock = { + request: { + query: GET_DOG_QUERY + }, + variableMatcher (variables) => true, + result: { + data: { dog: { id: 1, name: 'Buck', breed: 'poodle' } }, + }, +}; +``` + +This can also be useful for asserting specific variables individually: + +```js +const dogMock = { + request: { + query: GET_DOG_QUERY + }, + variableMatcher: jest.fn().mockReturnValue(true), + result: { + data: { dog: { id: 1, name: 'Buck', breed: 'poodle' } }, + }, +}; + +expect(variableMatcher).toHaveBeenCalledWith(expect.objectContaining({ + name: 'Buck' +})); +``` + ## Testing mutation components `useMutation` based components are tested very similarly to `useQuery` components. The only key difference is how the operation is fired. With `useQuery` the query is fired when the wrapping component _mounts_, whereas with `useMutation` the mutation is fired manually, usually after some user interaction like pressing a button. From e750ed0966630443402f1a50fe756ef8ede58706 Mon Sep 17 00:00:00 2001 From: Paul Rowe Date: Tue, 18 Aug 2020 08:08:51 -0500 Subject: [PATCH 05/13] reverting a settings file --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4f5d484db44..4ab27d98c2e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,5 @@ "typescript.tsdk": "../node_modules/typescript/lib", "cSpell.enableFiletypes": [ "mdx" - ], - "deno.enable": false + ] } From 66fbfb4cca27666683671079d0e471bf82e9ac11 Mon Sep 17 00:00:00 2001 From: prowe Date: Wed, 10 Aug 2022 22:57:16 -0500 Subject: [PATCH 06/13] Update docs/source/development-testing/testing.mdx Co-authored-by: Benjamin Pearson --- docs/source/development-testing/testing.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/development-testing/testing.mdx b/docs/source/development-testing/testing.mdx index f78b8323229..dbf1d2fe83b 100644 --- a/docs/source/development-testing/testing.mdx +++ b/docs/source/development-testing/testing.mdx @@ -259,7 +259,7 @@ const dogMock = { request: { query: GET_DOG_QUERY }, - variableMatcher (variables) => true, + variableMatcher: (variables) => true, result: { data: { dog: { id: 1, name: 'Buck', breed: 'poodle' } }, }, From eed8127ba5d65228e40fe2a9eb056a76a0a2cf71 Mon Sep 17 00:00:00 2001 From: Jeff Auriemma Date: Wed, 16 Aug 2023 23:05:14 -0400 Subject: [PATCH 07/13] Remove unintentionally re-added dead code paths --- .../mocking/__tests__/MockedProvider.test.tsx | 589 ------------------ .../MockedProvider.test.tsx.snap | 31 - 2 files changed, 620 deletions(-) delete mode 100644 src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx delete mode 100644 src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap diff --git a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx b/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx deleted file mode 100644 index f4d9b35ebbe..00000000000 --- a/src/utilities/testing/mocking/__tests__/MockedProvider.test.tsx +++ /dev/null @@ -1,589 +0,0 @@ -import React from 'react'; -import { render, wait } from '@testing-library/react'; -import gql from 'graphql-tag'; - -import { itAsync } from '../../itAsync'; -import { MockedProvider } from '../MockedProvider'; -import { MockedResponse, MockLink } from '../mockLink'; -import { DocumentNode } from 'graphql'; -import { useQuery } from '../../../../react/hooks/useQuery'; -import { InMemoryCache } from '../../../../cache/inmemory/inMemoryCache'; -import { ApolloLink } from '../../../../link/core'; - -const variables = { - username: 'mock_username' -}; - -const userWithoutTypeName = { - id: 'user_id' -}; - -const user = { - __typename: 'User', - ...userWithoutTypeName -}; - -const query: DocumentNode = gql` - query GetUser($username: String!) { - user(username: $username) { - id - } - } -`; - -const queryWithTypename: DocumentNode = gql` - query GetUser($username: String!) { - user(username: $username) { - id - __typename - } - } -`; - -const mocks: ReadonlyArray = [ - { - request: { - query, - variables - }, - result: { data: { user } } - } -]; - -interface Data { - user: { - id: string; - }; -} - -interface Variables { - username: string; -} - -let errorThrown = false; -const errorLink = new ApolloLink((operation, forward) => { - let observer = null; - try { - observer = forward(operation); - } catch (error) { - errorThrown = true; - } - return observer; -}); - -describe('General use', () => { - beforeEach(() => { - errorThrown = false; - }); - - itAsync('should mock the data', async (resolve, reject) => { - function Component({ username }: Variables) { - const { loading, data } = useQuery(query, { variables }); - if (!loading) { - expect(data!.user).toMatchSnapshot(); - } - return null; - } - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should pass the variables to the result function', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - - const mock2: MockedResponse = { - request: { - query, - variables - }, - result: jest.fn().mockResolvedValue({ data: { user } }) - }; - - render( - - - - ); - - return wait(() => { - expect(mock2.result as jest.Mock).toHaveBeenCalledWith(variables); - }).then(resolve, reject); - }); - - itAsync('should pass the variables to the variableMatcher', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - - const mock2: MockedResponse = { - request: { - query - }, - variableMatcher: jest.fn().mockReturnValue(true), - result: { data: { user } } - }; - - render( - - - - ); - - return wait(() => { - expect(mock2.variableMatcher as jest.Mock).toHaveBeenCalledWith(variables); - }).then(resolve, reject); - }); - - itAsync('should use a mock if the variableMatcher returns true', async (resolve, reject) => { - function Component({ username }: Variables) { - const { loading, data } = useQuery(query, { variables }); - if (!loading) { - expect(data!.user).toMatchSnapshot(); - } - return null; - } - - const mock2: MockedResponse = { - request: { - query - }, - variableMatcher: (v: Variables) => v.username === variables.username, - result: { data: { user } } - }; - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should allow querying with the typename', async (resolve, reject) => { - function Component({ username }: Variables) { - const { loading, data } = useQuery(query, { variables }); - if (!loading) { - expect(data!.user).toMatchSnapshot(); - } - return null; - } - - const mocksWithTypename = [ - { - request: { - query: queryWithTypename, - variables - }, - result: { data: { user } } - } - ]; - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should allow using a custom cache', async (resolve, reject) => { - const cache = new InMemoryCache(); - cache.writeQuery({ - query, - variables, - data: { user } - }); - - function Component({ username }: Variables) { - const { loading, data } = useQuery(query, { variables }); - if (!loading) { - expect(data).toMatchObject({ user }); - } - return null; - } - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should error if the variables in the mock and component do not match', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - - const variables2 = { - username: 'other_user' - }; - - const link = ApolloLink.from([errorLink, new MockLink(mocks)]); - - render( - - - - ); - - return wait(() => { - expect(errorThrown).toBeTruthy(); - }).then(resolve, reject); - }); - - itAsync('should error if the variableMatcher returns false', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - - const mock2: MockedResponse = { - request: { - query - }, - variableMatcher: () => false, - result: { data: { user } } - }; - - const link = ApolloLink.from([errorLink, new MockLink([mock2])]); - - render( - - - - ); - - return wait(() => { - expect(errorThrown).toBeTruthy(); - }).then(resolve, reject); - }); - - itAsync('should error if the variables do not deep equal', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - - const mocks2 = [ - { - request: { - query, - variables: { - age: 13, - username: 'some_user' - } - }, - result: { data: { user } } - } - ]; - - const variables2 = { - username: 'some_user', - age: 42 - }; - - const link = ApolloLink.from([errorLink, new MockLink(mocks2)]); - - render( - - - - ); - - return wait(() => { - expect(errorThrown).toBeTruthy(); - }).then(resolve, reject); - }); - - itAsync('should not error if the variables match but have different order', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - const { loading, data } = useQuery(query, { variables }); - if (!loading) { - expect(data).toMatchSnapshot(); - } - return null; - } - - const mocks2 = [ - { - request: { - query, - variables: { - age: 13, - username: 'some_user' - } - }, - result: { data: { user } } - } - ]; - - const variables2 = { - username: 'some_user', - age: 13 - }; - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should support mocking a network error', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - const { loading, error } = useQuery(query, { variables }); - if (!loading) { - expect(error).toEqual(new Error('something went wrong')); - } - return null; - } - - const mocksError = [ - { - request: { - query, - variables - }, - error: new Error('something went wrong') - } - ]; - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should error if the query in the mock and component do not match', async (resolve, reject) => { - function Component({ ...variables }: Variables) { - useQuery(query, { variables }); - return null; - } - - const mocksDifferentQuery = [ - { - request: { - query: gql` - query OtherQuery { - otherQuery { - id - } - } - `, - variables - }, - result: { data: { user } } - } - ]; - - const link = ApolloLink.from([errorLink, new MockLink(mocksDifferentQuery)]); - - render( - - - - ); - - return wait(() => { - expect(errorThrown).toBeTruthy(); - }).then(resolve, reject); - }); - - it('should error if both variables and a variableMatcher are provided', () => { - const mock2: MockedResponse = { - request: { - query, - variables - }, - variableMatcher: () => true, - result: { data: { user } } - }; - - expect(() => new MockLink([mock2])) - .toThrow('Mocked response should contain either variableMatcher or request.variables'); - }); - - it('should pass down props prop in mock as props for the component', () => { - function Component({ ...variables }) { - expect(variables.foo).toBe('bar'); - expect(variables.baz).toBe('qux'); - return null; - } - - render( - - - - ); - }); - - it('should not crash on unmount if there is no query manager', () => { - function Component() { - return null; - } - - const { unmount } = render( - - - - ); - - unmount(); - }); - - itAsync('should support returning mocked results from a function', async (resolve, reject) => { - let resultReturned = false; - - const testUser = { - __typename: 'User', - id: 12345 - }; - - function Component({ ...variables }: Variables) { - const { loading, data } = useQuery(query, { variables }); - if (!loading) { - expect(data!.user).toEqual(testUser); - expect(resultReturned).toBe(true); - } - return null; - } - - const testQuery: DocumentNode = gql` - query GetUser($username: String!) { - user(username: $username) { - id - } - } - `; - - const testVariables = { - username: 'jsmith' - }; - const testMocks = [ - { - request: { - query: testQuery, - variables: testVariables - }, - result() { - resultReturned = true; - return { - data: { - user: { - __typename: 'User', - id: 12345 - } - } - }; - } - } - ]; - - render( - - - - ); - - return wait().then(resolve, reject); - }); -}); - -describe('@client testing', () => { - itAsync('should support @client fields with a custom cache', async (resolve, reject) => { - const cache = new InMemoryCache(); - - cache.writeQuery({ - query: gql`{ - networkStatus { - isOnline - } - }`, - data: { - networkStatus: { - __typename: 'NetworkStatus', - isOnline: true - } - }, - }); - - function Component() { - const { loading, data } = useQuery(gql`{ - networkStatus @client { - isOnline - } - }`); - if (!loading) { - expect(data!.networkStatus.__typename).toEqual('NetworkStatus'); - expect(data!.networkStatus.isOnline).toEqual(true); - } - return null; - } - - render( - - - - ); - - return wait().then(resolve, reject); - }); - - itAsync('should support @client fields with field policies', async (resolve, reject) => { - const cache = new InMemoryCache({ - typePolicies: { - Query: { - fields: { - networkStatus() { - return { - __typename: 'NetworkStatus', - isOnline: true - }; - } - } - } - } - }); - - function Component() { - const { loading, data } = useQuery(gql`{ - networkStatus @client { - isOnline - } - }`); - if (!loading) { - expect(data!.networkStatus.__typename).toEqual('NetworkStatus'); - expect(data!.networkStatus.isOnline).toEqual(true); - } - return null; - } - - render( - - - - ); - - return wait().then(resolve, reject); - }); -}); diff --git a/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap b/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap deleted file mode 100644 index efc09e46930..00000000000 --- a/src/utilities/testing/mocking/__tests__/__snapshots__/MockedProvider.test.tsx.snap +++ /dev/null @@ -1,31 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`General use should allow querying with the typename 1`] = ` -Object { - "__typename": "User", - "id": "user_id", -} -`; - -exports[`General use should mock the data 1`] = ` -Object { - "__typename": "User", - "id": "user_id", -} -`; - -exports[`General use should not error if the variables match but have different order 1`] = ` -Object { - "user": Object { - "__typename": "User", - "id": "user_id", - }, -} -`; - -exports[`General use should use a mock if the variableMatcher returns true 1`] = ` -Object { - "__typename": "User", - "id": "user_id", -} -`; From 2405722d384da47eb11b68e463be3efa8beff38f Mon Sep 17 00:00:00 2001 From: Jeff Auriemma Date: Wed, 16 Aug 2023 23:08:36 -0400 Subject: [PATCH 08/13] Finish resolving test conflicts --- .../react/__tests__/MockedProvider.test.tsx | 82 +++++++++++++------ .../MockedProvider.test.tsx.snap | 21 +++++ 2 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/testing/react/__tests__/MockedProvider.test.tsx b/src/testing/react/__tests__/MockedProvider.test.tsx index 42d9724c4dc..f29268bb4c6 100644 --- a/src/testing/react/__tests__/MockedProvider.test.tsx +++ b/src/testing/react/__tests__/MockedProvider.test.tsx @@ -147,8 +147,9 @@ describe('General use', () => { }).then(resolve, reject); }); - itAsync('should allow querying with the typename', (resolve, reject) => { + itAsync('should use a mock if the variableMatcher returns true', async (resolve, reject) => { let finished = false; + function Component({ username }: Variables) { const { loading, data } = useQuery(query, { variables }); if (!loading) { @@ -158,18 +159,16 @@ describe('General use', () => { return null; } - const mocksWithTypename = [ - { - request: { - query: queryWithTypename, - variables - }, - result: { data: { user } } - } - ]; + const mock2: MockedResponse = { + request: { + query + }, + variableMatcher: (v: Variables) => v.username === variables.username, + result: { data: { user } } + }; render( - + ); @@ -179,36 +178,35 @@ describe('General use', () => { }).then(resolve, reject); }); - itAsync('should use a mock if the variableMatcher returns true', async (resolve, reject) => { - let userData = null; - + itAsync('should allow querying with the typename', (resolve, reject) => { + let finished = false; function Component({ username }: Variables) { const { loading, data } = useQuery(query, { variables }); if (!loading) { - userData = data!.user; + expect(data!.user).toMatchSnapshot(); + finished = true; } return null; } - const mock2: MockedResponse = { - request: { - query - }, - variableMatcher: (v: Variables) => v.username === variables.username, - result: { data: { user } } - }; + const mocksWithTypename = [ + { + request: { + query: queryWithTypename, + variables + }, + result: { data: { user } } + } + ]; render( - + ); waitFor(() => { - expect(userData).toStrictEqual({ - __typename: "User", - id: "user_id", - }); + expect(finished).toBe(true); }).then(resolve, reject); }); @@ -268,6 +266,36 @@ describe('General use', () => { }).then(resolve, reject); }); + itAsync('should error if the variableMatcher returns false', async (resolve, reject) => { + let finished = false; + function Component({ ...variables }: Variables) { + const { loading, error } = useQuery(query, { variables }); + if (!loading) { + expect(error).toMatchSnapshot(); + finished = true; + } + return null; + } + + const mock2: MockedResponse = { + request: { + query + }, + variableMatcher: () => false, + result: { data: { user } } + }; + + render( + + + + ); + + waitFor(() => { + expect(finished).toBe(true); + }, ).then(resolve, reject); + }); + itAsync('should error if the variables do not deep equal', (resolve, reject) => { let finished = false function Component({ ...variables }: Variables) { diff --git a/src/testing/react/__tests__/__snapshots__/MockedProvider.test.tsx.snap b/src/testing/react/__tests__/__snapshots__/MockedProvider.test.tsx.snap index 5fecc4e98d7..727f5edbb85 100644 --- a/src/testing/react/__tests__/__snapshots__/MockedProvider.test.tsx.snap +++ b/src/testing/react/__tests__/__snapshots__/MockedProvider.test.tsx.snap @@ -18,6 +18,20 @@ Expected variables: {"username":"mock_username"} ] `; +exports[`General use should error if the variableMatcher returns false 1`] = ` +[ApolloError: No more mocked responses for the query: query GetUser($username: String!) { + user(username: $username) { + id + __typename + } +} +Expected variables: {"username":"mock_username"} + +Failed to match 1 mock for this query. The mocked response had the following variables: + {} +] +`; + exports[`General use should error if the variables do not deep equal 1`] = ` [ApolloError: No more mocked responses for the query: query GetUser($username: String!) { user(username: $username) { @@ -87,3 +101,10 @@ exports[`General use should support custom error handling using setOnError 1`] = Expected variables: {"username":"mock_username"} ] `; + +exports[`General use should use a mock if the variableMatcher returns true 1`] = ` +Object { + "__typename": "User", + "id": "user_id", +} +`; From 4211375e9f2363e328f0be2d62eccdcaeef186e9 Mon Sep 17 00:00:00 2001 From: Jeff Auriemma Date: Thu, 17 Aug 2023 10:14:24 -0400 Subject: [PATCH 09/13] Changeset for dynamic variable mock matching --- .changeset/sour-sheep-walk.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/sour-sheep-walk.md diff --git a/.changeset/sour-sheep-walk.md b/.changeset/sour-sheep-walk.md new file mode 100644 index 00000000000..b0270d5ee68 --- /dev/null +++ b/.changeset/sour-sheep-walk.md @@ -0,0 +1,7 @@ +--- +"@apollo/client": minor +--- + +Ability to dynamically match mocks + +Adds support for a new property `MockedResponse.variableMatcher`: a predicate function that accepts a `variables` param. If `true`, the `variables` will be passed into the `ResultFunction` to help dynamically build a response. From a60bdd0c1fed069037921141f7448379202a46c6 Mon Sep 17 00:00:00 2001 From: Alessia Bellisario Date: Fri, 15 Sep 2023 14:56:25 -0400 Subject: [PATCH 10/13] chore: fix type errors --- src/testing/core/mocking/mockLink.ts | 12 +++++------- src/testing/react/__tests__/MockedProvider.test.tsx | 5 +++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index a1c0aff8bc8..764a787a5c5 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -19,19 +19,19 @@ import { print, } from "../../../utilities/index.js"; -export type ResultFunction> = (variables: V) => T; +export type ResultFunction = (variables: Record) => T; -export type VariableMatcher = (variables: V) => boolean; +export type VariableMatcher = (variables: Record) => boolean; export interface MockedResponse< TData = Record, TVariables = Record, > { request: GraphQLRequest; - result?: FetchResult | ResultFunction, TVariables>; + result?: FetchResult | ResultFunction>; error?: Error; delay?: number; - variableMatcher?: VariableMatcher; + variableMatcher?: VariableMatcher; newData?: ResultFunction; } @@ -171,9 +171,7 @@ ${unmatchedVars.map((d) => ` ${stringifyForDisplay(d)}`).join("\n")} if (response.result) { observer.next( typeof response.result === "function" - ? (response.result as ResultFunction)( - operation.variables - ) + ? response.result(operation.variables) : response.result ); } diff --git a/src/testing/react/__tests__/MockedProvider.test.tsx b/src/testing/react/__tests__/MockedProvider.test.tsx index 3e314906494..c9b7e8705c2 100644 --- a/src/testing/react/__tests__/MockedProvider.test.tsx +++ b/src/testing/react/__tests__/MockedProvider.test.tsx @@ -7,7 +7,8 @@ import { itAsync, MockedResponse, MockLink } from "../../core"; import { MockedProvider } from "../MockedProvider"; import { useQuery } from "../../../react/hooks"; import { InMemoryCache } from "../../../cache"; -import { ApolloLink } from "../../../link/core"; +import { ApolloLink, FetchResult } from "../../../link/core"; +import { Observable } from "zen-observable-ts"; const variables = { username: "mock_username", @@ -61,7 +62,7 @@ interface Variables { let errorThrown = false; const errorLink = new ApolloLink((operation, forward) => { - let observer = null; + let observer: Observable | null = null; try { observer = forward(operation); } catch (error) { From 4ba85c00c6a83552a54087bbe015b7cb3b4465e7 Mon Sep 17 00:00:00 2001 From: Alessia Bellisario Date: Tue, 19 Sep 2023 05:46:39 -0700 Subject: [PATCH 11/13] chore: update .api-reports/* --- .api-reports/api-report-core.md | 2 +- .api-reports/api-report-react.md | 2 +- .api-reports/api-report-react_components.md | 2 +- .api-reports/api-report-react_context.md | 2 +- .api-reports/api-report-react_hoc.md | 2 +- .api-reports/api-report-react_hooks.md | 2 +- .api-reports/api-report-react_ssr.md | 2 +- .api-reports/api-report-testing.md | 15 +++++++++++---- .api-reports/api-report-testing_core.md | 15 +++++++++++---- .api-reports/api-report-utilities.md | 2 +- .api-reports/api-report.md | 2 +- 11 files changed, 31 insertions(+), 17 deletions(-) diff --git a/.api-reports/api-report-core.md b/.api-reports/api-report-core.md index 0bc6fab994b..e3138c81d29 100644 --- a/.api-reports/api-report-core.md +++ b/.api-reports/api-report-core.md @@ -1642,7 +1642,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-react.md b/.api-reports/api-report-react.md index 504453b9637..1bb039c96dd 100644 --- a/.api-reports/api-report-react.md +++ b/.api-reports/api-report-react.md @@ -1463,7 +1463,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-react_components.md b/.api-reports/api-report-react_components.md index cf07c01004a..71852806729 100644 --- a/.api-reports/api-report-react_components.md +++ b/.api-reports/api-report-react_components.md @@ -1265,7 +1265,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-react_context.md b/.api-reports/api-report-react_context.md index fe5b3e684cb..3bdc1ed79b5 100644 --- a/.api-reports/api-report-react_context.md +++ b/.api-reports/api-report-react_context.md @@ -1175,7 +1175,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-react_hoc.md b/.api-reports/api-report-react_hoc.md index bcfbf8c55c5..6fc66b904e1 100644 --- a/.api-reports/api-report-react_hoc.md +++ b/.api-reports/api-report-react_hoc.md @@ -1243,7 +1243,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-react_hooks.md b/.api-reports/api-report-react_hooks.md index 71597296826..052cfd6c223 100644 --- a/.api-reports/api-report-react_hooks.md +++ b/.api-reports/api-report-react_hooks.md @@ -1393,7 +1393,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-react_ssr.md b/.api-reports/api-report-react_ssr.md index 4e617cff33e..95a9ed6957f 100644 --- a/.api-reports/api-report-react_ssr.md +++ b/.api-reports/api-report-react_ssr.md @@ -1162,7 +1162,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report-testing.md b/.api-reports/api-report-testing.md index 70b9d593258..bf4dae7190b 100644 --- a/.api-reports/api-report-testing.md +++ b/.api-reports/api-report-testing.md @@ -882,7 +882,7 @@ interface MockedProviderState { } // @public (undocumented) -export interface MockedResponse, TVariables = Record> { +export interface MockedResponse, TVariables extends object = Record> { // (undocumented) delay?: number; // (undocumented) @@ -892,7 +892,11 @@ export interface MockedResponse, TVariables = Record // (undocumented) request: GraphQLRequest; // (undocumented) - result?: FetchResult | ResultFunction>; + result?: FetchResult | ResultFunction, TVariables>; + // Warning: (ae-forgotten-export) The symbol "VariableMatcher" needs to be exported by the entry point index.d.ts + // + // (undocumented) + variableMatcher?: VariableMatcher; } // @public (undocumented) @@ -1238,7 +1242,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) @@ -1497,7 +1501,7 @@ interface Resolvers { } // @public (undocumented) -export type ResultFunction = () => T; +export type ResultFunction> = (variables: V) => T; // @public (undocumented) type SafeReadonly = T extends object ? Readonly : T; @@ -1623,6 +1627,9 @@ interface UriFunction { (operation: Operation): string; } +// @public (undocumented) +type VariableMatcher> = (variables: V) => boolean; + // @public (undocumented) export function wait(ms: number): Promise; diff --git a/.api-reports/api-report-testing_core.md b/.api-reports/api-report-testing_core.md index 2dc55496b8d..87943514d93 100644 --- a/.api-reports/api-report-testing_core.md +++ b/.api-reports/api-report-testing_core.md @@ -838,7 +838,7 @@ interface MockApolloLink extends ApolloLink { } // @public (undocumented) -export interface MockedResponse, TVariables = Record> { +export interface MockedResponse, TVariables extends object = Record> { // (undocumented) delay?: number; // (undocumented) @@ -848,7 +848,11 @@ export interface MockedResponse, TVariables = Record // (undocumented) request: GraphQLRequest; // (undocumented) - result?: FetchResult | ResultFunction>; + result?: FetchResult | ResultFunction, TVariables>; + // Warning: (ae-forgotten-export) The symbol "VariableMatcher" needs to be exported by the entry point index.d.ts + // + // (undocumented) + variableMatcher?: VariableMatcher; } // @public (undocumented) @@ -1194,7 +1198,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) @@ -1455,7 +1459,7 @@ interface Resolvers { } // @public (undocumented) -export type ResultFunction = () => T; +export type ResultFunction> = (variables: V) => T; // @public (undocumented) type SafeReadonly = T extends object ? Readonly : T; @@ -1581,6 +1585,9 @@ interface UriFunction { (operation: Operation): string; } +// @public (undocumented) +type VariableMatcher> = (variables: V) => boolean; + // @public (undocumented) export function wait(ms: number): Promise; diff --git a/.api-reports/api-report-utilities.md b/.api-reports/api-report-utilities.md index 410b9ded70b..cc97fb9dbe6 100644 --- a/.api-reports/api-report-utilities.md +++ b/.api-reports/api-report-utilities.md @@ -1905,7 +1905,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) diff --git a/.api-reports/api-report.md b/.api-reports/api-report.md index 01950a8f066..8c933201f08 100644 --- a/.api-reports/api-report.md +++ b/.api-reports/api-report.md @@ -2017,7 +2017,7 @@ class QueryInfo { // Warning: (ae-forgotten-export) The symbol "CacheWriteBehavior" needs to be exported by the entry point index.d.ts // // (undocumented) - markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): void; + markResult(result: FetchResult, document: DocumentNode, options: Pick, cacheWriteBehavior: CacheWriteBehavior): typeof result; // (undocumented) networkError?: Error | null; // (undocumented) From 730042221e419a4a330822cf5eb4e65b9278c2f0 Mon Sep 17 00:00:00 2001 From: Alessia Bellisario Date: Tue, 19 Sep 2023 06:01:26 -0700 Subject: [PATCH 12/13] chore: use TS in docs example --- docs/source/development-testing/testing.mdx | 14 +++++++++----- src/testing/core/mocking/mockLink.ts | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/source/development-testing/testing.mdx b/docs/source/development-testing/testing.mdx index 3f4a74504ee..7fcb53662d3 100644 --- a/docs/source/development-testing/testing.mdx +++ b/docs/source/development-testing/testing.mdx @@ -152,12 +152,14 @@ it("renders without error", async () => { ### Dynamic variables -Sometimes, the exact value of the variables being passed are not known. The `MockedResponse` object takes a `variableMatcher` property that is a function that takes the variables and return a boolean indication if this mock should match the invocation for the provided query. You cannot specify this parameter and `request.variables` at the same time. +Sometimes, the exact value of the variables being passed are not known. The `MockedResponse` object takes a `variableMatcher` property that is a function that takes the variables and returns a boolean indication if this mock should match the invocation for the provided query. You cannot specify this parameter and `request.variables` at the same time. For example, this mock will match all dog queries: -```js -const dogMock = { +```ts +import { MockedResponse } from "@apollo/client/testing"; + +const dogMock: MockedResponse = { request: { query: GET_DOG_QUERY }, @@ -170,8 +172,10 @@ const dogMock = { This can also be useful for asserting specific variables individually: -```js -const dogMock = { +```ts +import { MockedResponse } from "@apollo/client/testing"; + +const dogMock: MockedResponse = { request: { query: GET_DOG_QUERY }, diff --git a/src/testing/core/mocking/mockLink.ts b/src/testing/core/mocking/mockLink.ts index 75bf89571ab..bd798bd6395 100644 --- a/src/testing/core/mocking/mockLink.ts +++ b/src/testing/core/mocking/mockLink.ts @@ -26,8 +26,8 @@ export type VariableMatcher> = ( ) => boolean; export interface MockedResponse< - TData extends object = Record, - TVariables extends object = Record, + TData = Record, + TVariables = Record, > { request: GraphQLRequest; result?: FetchResult | ResultFunction, TVariables>; From 0736062d6a65a4384edd6b4cb1110851b69a0cf3 Mon Sep 17 00:00:00 2001 From: Alessia Bellisario Date: Tue, 19 Sep 2023 06:02:23 -0700 Subject: [PATCH 13/13] chore: update api-report-testing_core.md --- .api-reports/api-report-testing.md | 2 +- .api-reports/api-report-testing_core.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.api-reports/api-report-testing.md b/.api-reports/api-report-testing.md index bf4dae7190b..fdff4903c39 100644 --- a/.api-reports/api-report-testing.md +++ b/.api-reports/api-report-testing.md @@ -882,7 +882,7 @@ interface MockedProviderState { } // @public (undocumented) -export interface MockedResponse, TVariables extends object = Record> { +export interface MockedResponse, TVariables = Record> { // (undocumented) delay?: number; // (undocumented) diff --git a/.api-reports/api-report-testing_core.md b/.api-reports/api-report-testing_core.md index 87943514d93..3cf490dd0d3 100644 --- a/.api-reports/api-report-testing_core.md +++ b/.api-reports/api-report-testing_core.md @@ -838,7 +838,7 @@ interface MockApolloLink extends ApolloLink { } // @public (undocumented) -export interface MockedResponse, TVariables extends object = Record> { +export interface MockedResponse, TVariables = Record> { // (undocumented) delay?: number; // (undocumented)