Skip to content

Commit

Permalink
Feature request 241: reuse mocks in MockLink / MockedProvider (#11178)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebakerckhof committed Sep 21, 2023
1 parent a4c38d6 commit 4d64a6f
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .api-reports/api-report-testing.md
Expand Up @@ -888,6 +888,8 @@ export interface MockedResponse<TData = Record<string, any>, TVariables = Record
// (undocumented)
error?: Error;
// (undocumented)
maxUsageCount?: number;
// (undocumented)
newData?: ResultFunction<FetchResult>;
// (undocumented)
request: GraphQLRequest<TVariables>;
Expand Down
2 changes: 2 additions & 0 deletions .api-reports/api-report-testing_core.md
Expand Up @@ -844,6 +844,8 @@ export interface MockedResponse<TData = Record<string, any>, TVariables = Record
// (undocumented)
error?: Error;
// (undocumented)
maxUsageCount?: number;
// (undocumented)
newData?: ResultFunction<FetchResult>;
// (undocumented)
request: GraphQLRequest<TVariables>;
Expand Down
5 changes: 5 additions & 0 deletions .changeset/yellow-flies-repeat.md
@@ -0,0 +1,5 @@
---
"@apollo/client": minor
---

Support re-using of mocks in the MockedProvider
4 changes: 1 addition & 3 deletions .github/workflows/api-extractor.yml
Expand Up @@ -19,8 +19,6 @@ jobs:
- name: Install dependencies (with cache)
uses: bahmutov/npm-install@v1

- name: Run build
run: npm run build

# Builds the library and runs the api extractor
- name: Run Api-Extractor
run: npm run extract-api
2 changes: 1 addition & 1 deletion .size-limit.cjs
@@ -1,7 +1,7 @@
const checks = [
{
path: "dist/apollo-client.min.cjs",
limit: "37986",
limit: "38000",
},
{
path: "dist/main.cjs",
Expand Down
31 changes: 31 additions & 0 deletions docs/source/development-testing/testing.mdx
Expand Up @@ -150,6 +150,37 @@ it("renders without error", async () => {

</ExpansionPanel>

#### Reusing mocks

By default, a mock is only used once. If you want to reuse a mock for multiple operations, you can set the `maxUsageCount` field to a number indicating how many times the mock should be used:

<ExpansionPanel title="Click to expand 🐶">

```jsx title="dog.test.js"
import { GET_DOG_QUERY } from "./dog";

const mocks = [
{
request: {
query: GET_DOG_QUERY,
variables: {
name: "Buck"
}
},
result: {
data: {
dog: { id: "1", name: "Buck", breed: "bulldog" }
}
},
maxUsageCount: 2, // The mock can be used twice before it's removed, default is 1
}
];
```

</ExpansionPanel>

Passing `Number.POSITIVE_INFINITY` will cause the mock to be reused indefinitely.

### 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 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.
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -42,7 +42,7 @@
"prepdist": "node ./config/prepareDist.js",
"prepdist:changesets": "ts-node-script config/prepareChangesetsRelease.ts",
"postprocess-dist": "ts-node-script config/postprocessDist.ts",
"extract-api": "ts-node-script config/apiExtractor.ts",
"extract-api": "npm run build && ts-node-script config/apiExtractor.ts",
"clean": "rimraf dist coverage lib temp",
"check:format": "prettier --check .",
"ci:precheck": "node config/precheck.js",
Expand Down
16 changes: 14 additions & 2 deletions src/testing/core/mocking/mockLink.ts
Expand Up @@ -30,6 +30,7 @@ export interface MockedResponse<
TVariables = Record<string, any>,
> {
request: GraphQLRequest<TVariables>;
maxUsageCount?: number;
result?: FetchResult<TData> | ResultFunction<FetchResult<TData>, TVariables>;
error?: Error;
delay?: number;
Expand Down Expand Up @@ -135,8 +136,11 @@ ${unmatchedVars.map((d) => ` ${stringifyForDisplay(d)}`).join("\n")}
);
}
} else {
mockedResponses.splice(responseIndex, 1);

if (response.maxUsageCount! > 1) {
response.maxUsageCount!--;
} else {
mockedResponses.splice(responseIndex, 1);
}
const { newData } = response;
if (newData) {
response.result = newData(operation.variables);
Expand Down Expand Up @@ -203,6 +207,14 @@ ${unmatchedVars.map((d) => ` ${stringifyForDisplay(d)}`).join("\n")}
if (query) {
newMockedResponse.request.query = query;
}

mockedResponse.maxUsageCount = mockedResponse.maxUsageCount ?? 1;
invariant(
mockedResponse.maxUsageCount > 0,
`Mock response maxUsageCount must be greater than 0, %s given`,
mockedResponse.maxUsageCount
);

this.normalizeVariableMatching(newMockedResponse);
return newMockedResponse;
}
Expand Down

0 comments on commit 4d64a6f

Please sign in to comment.