Skip to content

Commit

Permalink
Add expected/received variables to 'No more mocked responses' error m…
Browse files Browse the repository at this point in the history
…essage (#8340)

Co-authored-by: Ben Newman <ben@apollographql.com>
  • Loading branch information
markneub and benjamn authored Jun 7, 2021
1 parent 2d0ebe7 commit 9b522cf
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 28 deletions.
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
})
```
[@benjamn](https://github.com/benjamn) in [#7810](https://github.com/apollographql/apollo-client/pull/7810)
- Make sure the `MockedResponse` `ResultFunction` type is re-exported. <br/>

- Make sure the `MockedResponse` `ResultFunction` type is re-exported. <br/>
[@hwillson](https://github.com/hwillson) in [#8315](https://github.com/apollographql/apollo-client/pull/8315)
- Fix polling when used with skip <br />

- Fix polling when used with `skip`. <br/>
[@brainkim](https://github.com/brainkim) in [#8346](https://github.com/apollographql/apollo-client/pull/8346)

### Potentially breaking changes
Expand Down Expand Up @@ -74,7 +76,11 @@
- Fully remove result cache entries from LRU dependency system when the corresponding entities are removed from `InMemoryCache` by eviction, or by any other means. <br/>
[@sofianhn](https://github.com/sofianhn) and [@benjamn](https://github.com/benjamn) in [#8147](https://github.com/apollographql/apollo-client/pull/8147)

- Expose missing field errors in results. <br/> [@brainkim](github.com/brainkim) in [#8262](https://github.com/apollographql/apollo-client/pull/8262)
- Expose missing field errors in results. <br/>
[@brainkim](github.com/brainkim) in [#8262](https://github.com/apollographql/apollo-client/pull/8262)

- Add expected/received `variables` to `No more mocked responses...` error messages generated by `MockLink`. <br/>
[@markneub](github.com/markneub) in [#8340](https://github.com/apollographql/apollo-client/pull/8340)

### Documentation
TBD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ describe('General use', () => {
}

const variables2 = {
username: 'other_user'
username: 'other_user',
age: undefined
};

render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ exports[`General use should error if the query in the mock and component do not
__typename
}
}
, variables: {"username":"mock_username"}]
Expected variables: {"username":"mock_username"}
]
`;

exports[`General use should error if the variables do not deep equal 1`] = `
Expand All @@ -24,7 +26,12 @@ exports[`General use should error if the variables do not deep equal 1`] = `
__typename
}
}
, variables: {"username":"some_user","age":42}]
Expected variables: {"username":"some_user","age":42}
Failed to match 1 mock for this query, which had the following variables:
{"age":13,"username":"some_user"}
]
`;

exports[`General use should error if the variables in the mock and component do not match 1`] = `
Expand All @@ -34,7 +41,12 @@ exports[`General use should error if the variables in the mock and component do
__typename
}
}
, variables: {"username":"other_user"}]
Expected variables: {"username":"other_user","age":<undefined>}
Failed to match 1 mock for this query, which had the following variables:
{"username":"mock_username"}
]
`;
exports[`General use should mock the data 1`] = `
Expand Down Expand Up @@ -64,7 +76,9 @@ exports[`General use should return "No more mocked responses" errors in response
__typename
}
}
, variables: {}]
Expected variables: {}
]
`;
exports[`General use should support custom error handling using setOnError 1`] = `
Expand All @@ -74,5 +88,7 @@ exports[`General use should support custom error handling using setOnError 1`] =
__typename
}
}
, variables: {"username":"mock_username"}]
Expected variables: {"username":"mock_username"}
]
`;
53 changes: 34 additions & 19 deletions src/utilities/testing/mocking/mockLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@ import {
removeClientSetsFromDocument,
removeConnectionDirectiveFromDocument,
cloneDeep,
makeUniqueId,
} from '../../../utilities';

export type ResultFunction<T> = () => T;

function stringifyForDisplay(value: any): string {
const undefId = makeUniqueId("stringifyForDisplay");
return JSON.stringify(value, (key, value) => {
return value === void 0 ? undefId : value;
}).split(JSON.stringify(undefId)).join("<undefined>");
}

export interface MockedResponse<TData = Record<string, any>> {
request: GraphQLRequest;
result?: FetchResult<TData> | ResultFunction<FetchResult<TData>>;
Expand Down Expand Up @@ -72,34 +80,41 @@ export class MockLink extends ApolloLink {
public request(operation: Operation): Observable<FetchResult> | null {
this.operation = operation;
const key = requestToKey(operation, this.addTypename);
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)) {
responseIndex = index;
return true;
}
return false;
const unmatchedVars: Array<Record<string, any>> = [];
const requestVariables = operation.variables || {};
const mockedResponses = this.mockedResponsesByKey[key];
const responseIndex = mockedResponses ? mockedResponses.findIndex((res, index) => {
const mockedResponseVars = res.request.variables || {};
if (equal(requestVariables, mockedResponseVars)) {
return true;
}
);
unmatchedVars.push(mockedResponseVars);
return false;
}) : -1;

const response = responseIndex >= 0
? mockedResponses[responseIndex]
: void 0;

let configError: Error;

if (!response || typeof responseIndex === 'undefined') {
if (!response) {
configError = new Error(
`No more mocked responses for the query: ${print(
operation.query
)}, variables: ${JSON.stringify(operation.variables)}`
);
`No more mocked responses for the query: ${print(operation.query)}
Expected variables: ${stringifyForDisplay(operation.variables)}
${unmatchedVars.length > 0 ? `
Failed to match ${unmatchedVars.length} mock${
unmatchedVars.length === 1 ? "" : "s"
} for this query, which had the following variables:
${unmatchedVars.map(d => ` ${stringifyForDisplay(d)}`).join('\n')}
` : ""}`);
} else {
this.mockedResponsesByKey[key].splice(responseIndex, 1);
mockedResponses.splice(responseIndex, 1);

const { newData } = response;
if (newData) {
response.result = newData();
this.mockedResponsesByKey[key].push(response);
mockedResponses.push(response);
}

if (!response.result && !response.error) {
Expand Down Expand Up @@ -151,7 +166,7 @@ export class MockLink extends ApolloLink {
): MockedResponse {
const newMockedResponse = cloneDeep(mockedResponse);
const queryWithoutConnection = removeConnectionDirectiveFromDocument(
newMockedResponse.request.query
newMockedResponse.request.query
);
invariant(queryWithoutConnection, "query is required");
newMockedResponse.request.query = queryWithoutConnection!;
Expand Down

0 comments on commit 9b522cf

Please sign in to comment.