Skip to content

Commit cdef3da

Browse files
committed
add a "Modifying a test schema using testSchema.add and testSchema.fork" section
1 parent 3baf29d commit cdef3da

File tree

2 files changed

+80
-6
lines changed

2 files changed

+80
-6
lines changed

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
!/docs/source/development-testing
2525
/docs/source/development-testing/**
2626
!/docs/source/development-testing/reducing-bundle-size.mdx
27+
!/docs/source/development-testing/schema-driven-testing.mdx
2728

2829
!docs/shared
2930
/docs/shared/**

docs/source/development-testing/schema-driven-testing.mdx

+79-6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export function Products() {
7070
);
7171
}
7272
```
73+
7374
</ExpansionPanel>
7475

7576
Now let's write some tests using a test schema created with the `createTestSchema` utility that can then be used to create a mock fetch implementation with `createSchemaFetch`.
@@ -155,7 +156,6 @@ const config: Config = {
155156
};
156157

157158
export default config;
158-
159159
```
160160

161161
In the example `setupTests.ts` file below, `@testing-library/jest-dom` is imported to allow the use of custom `jest-dom` matchers (see the [`@testing-library/jest-dom` documentation](https://github.com/testing-library/jest-dom?tab=readme-ov-file#usage) for more information) and fragment warnings are disabled which can pollute the test output:
@@ -344,10 +344,7 @@ import graphqlSchema from "../../../schema.graphql";
344344
// This should be a function that returns a new ApolloClient instance
345345
// configured just like your production Apollo Client instance - see the FAQ.
346346
import { makeClient } from "../../client";
347-
import {
348-
ApolloProvider,
349-
NormalizedCacheObject,
350-
} from "@apollo/client";
347+
import { ApolloProvider, NormalizedCacheObject } from "@apollo/client";
351348
import { Products } from "../../products";
352349
import { Suspense } from "react";
353350

@@ -437,6 +434,82 @@ describe("Products", () => {
437434
});
438435
```
439436

437+
## Modifying a test schema using `testSchema.add` and `testSchema.fork`
438+
439+
If you need to make changes to the behavior of a schema after it has been created, you can use the `testSchema.add` method to add new resolvers to the schema or overwrite existing ones.
440+
This can be useful for testing scenarios where the behavior of the schema needs to change inside a test.
441+
442+
````tsx title="products.test.tsx"
443+
describe("Products", () => {
444+
it("renders", async () => {
445+
const { restore } = createSchemaFetch(schema).mockGlobal();
446+
447+
render(makeClient());
448+
449+
// make assertions against the rendered DOM output
450+
451+
// Here we want to change the return value of the `products` resolver
452+
// for the next outgoing query.
453+
testSchema.add({
454+
resolvers: {
455+
Query: {
456+
products: () =>
457+
Array.from({ length: 5 }, (_element, id) => ({
458+
// we want to return ids starting from 5 for the second request
459+
id: id + 5,
460+
mediaUrl: `https://example.com/image${id + 5}.jpg`,
461+
})),
462+
},
463+
},
464+
});
465+
466+
// trigger a new query with a user interaction
467+
userEvent.click(screen.getByText("Fetch more"));
468+
469+
// make assertions against the rendered DOM output
470+
471+
restore();
472+
testSchema.reset();
473+
});
474+
});
475+
```
476+
477+
Alternatively, you can use `testSchema.fork` to create a new schema with the same configuration as the original schema,
478+
but with the ability to make changes to the new isolated schema without affecting the original schema.
479+
This can be useful if you just want to mock the global fetch function with a different schema for each test without
480+
having to care about resetting your original testSchema.
481+
You could also write incremental tests where each test builds on the previous one.
482+
483+
If you use MSW, you will probably end up using `testSchema.add`, as MSW needs to be set up with a single schema for all tests.
484+
If you are going the `createSchemaFetch` route, you can use `testSchema.fork` to create a new schema for each test,
485+
and then use `forkedSchema.add` to make changes to the schema for that test.
486+
487+
```tsx
488+
const baseSchema = createTestSchema(staticSchema, {
489+
resolvers: {
490+
// ...
491+
},
492+
scalars: {
493+
// ...
494+
},
495+
});
496+
497+
test("a test", () => {
498+
const forkedSchema = baseSchema.fork();
499+
500+
const { restore } = createSchemaFetch(forkedSchema).mockGlobal();
501+
502+
// make assertions against the rendered DOM output
503+
504+
forkedSchema.add({
505+
// ...
506+
});
507+
508+
restore();
509+
// forkedSchema will just be discarded, and there is no need to reset it
510+
});
511+
````
512+
440513
### FAQ
441514
442515
#### When should I use `createSchemaFetch` vs [MSW](https://mswjs.io/)?
@@ -468,8 +541,8 @@ export const makeClient = () => {
468541
};
469542

470543
export const client = makeClient();
471-
472544
```
545+
473546
</ExpansionPanel>
474547

475548
This way, every test can use `makeClient` to create a new client instance, and you can still use `client` in your production code.

0 commit comments

Comments
 (0)