Skip to content

Commit

Permalink
bump relay to 18 and mention client extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
Stanislaw Wilczynski authored and Stanislaw Wilczynski committed Oct 18, 2024
1 parent 4b4cfca commit 504d057
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 66 deletions.
9 changes: 5 additions & 4 deletions packages/examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"graphql": "^15.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-relay": "^17.0.0",
"relay-runtime": "^17.0.0"
"react-relay": "^18.0.0",
"relay-runtime": "^18.0.0"
},
"devDependencies": {
"@babel/core": "^7.20.2",
Expand Down Expand Up @@ -54,11 +54,12 @@
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"@types/react-relay": "^16.0.0",
"@types/relay-runtime": "^17.0.0",
"@types/relay-runtime": "^18.0.0",
"esbuild-loader": "^3.0.1",
"monorepo-scripts": "*",
"prop-types": "15.8.1",
"relay-compiler": "^17.0.0",
"relay-compiler": "^18.0.0",
"relay-test-utils": "^18.0.0",
"storybook": "^7.6.19",
"typescript": "^5.6.0"
},
Expand Down

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

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

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

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

24 changes: 18 additions & 6 deletions packages/examples/src/relay/pure-relay/Feedback.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { graphql } from "react-relay";
import {
getNovaDecorator,
getNovaEnvironmentForStory,
MockPayloadGenerator as PayloadGenerator,
type WithNovaEnvironment,
EventingProvider,
getOperationName,
getOperationType,
type StoryObjWithoutFragmentRefs,
} from "@nova/react-test-utils/relay";
import { MockPayloadGenerator } from "relay-test-utils";
import type { Meta } from "@storybook/react";
import { userEvent, waitFor, within, expect } from "@storybook/test";
import type { TypeMap } from "../../__generated__/schema.all.interface";
Expand All @@ -21,12 +21,24 @@ import { RecordSource, Store } from "relay-runtime";

const schema = getSchema();

const MockPayloadGenerator = new PayloadGenerator(schema);

const novaDecorator = getNovaDecorator(schema, {
getEnvironmentOptions: () => ({
store: new Store(new RecordSource()),
}),
// We add this to verify scenario of using relay's MockPayloadGenerator
generateFunction: (operation, mockResolvers) => {
const result = MockPayloadGenerator.generateWithDefer(
operation,
mockResolvers ?? null,
{
mockClientData: true,
generateDeferredPayload: true,
},
);

return result;
},
});

const meta = {
Expand Down Expand Up @@ -106,7 +118,7 @@ export const Like: Story = {
const operation = mock.getMostRecentOperation();
await expect(operation).toBeDefined();
});
await mock.resolveMostRecentOperation((operation) => {
mock.resolveMostRecentOperation((operation) => {
return MockPayloadGenerator.generate(operation, likeResolvers);
});
},
Expand All @@ -127,7 +139,7 @@ export const ArtificialFailureToShowcaseDecoratorBehaviorInCaseOfADevCausedError
const operation = mock.getMostRecentOperation();
await expect(operation).toBeDefined();
});
await mock.rejectMostRecentOperation(new Error("Query failed"));
mock.rejectMostRecentOperation(new Error("Query failed"));
},
};

Expand All @@ -152,7 +164,7 @@ export const LikeFailure: Story = {
const operationType = getOperationType(operation);
expect(operationName).toEqual("FeedbackStoryRelayQuery");
expect(operationType).toEqual("query");
await mock.resolveMostRecentOperation((operation) => {
mock.resolveMostRecentOperation((operation) => {
return MockPayloadGenerator.generate(operation, {
Feedback: () => sampleFeedback,
});
Expand All @@ -168,7 +180,7 @@ export const LikeFailure: Story = {
const nextOperationType = getOperationType(nextOperation);
expect(nextOperationName).toEqual("FeedbackComponent_RelayLikeMutation");
expect(nextOperationType).toEqual("mutation");
await mock.rejectMostRecentOperation(new Error("Like failed"));
mock.rejectMostRecentOperation(new Error("Like failed"));
await container.findByText("Something went wrong");
},
};
Expand Down

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

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

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

52 changes: 51 additions & 1 deletion packages/nova-react-test-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,56 @@ const meta = {

The second parameter of `getNovaDecorator` is an `options` object of type `Partial<EnvironmentConfig>` from `relay-test-utils`.

### (Pure relay or Nova with Relay) How can I make sure the mock data is generated for client extensions?

The current default generator doesn't support client extensions. However, you can use the `generateFunction` option to provide your own generator. Here is an example of how you can use the `MockPayloadGenerator` from `relay-test-utils` to generate data for client extensions:

```tsx
import { MockPayloadGenerator } from "relay-test-utils";
import { getNovaDecorator } from "@nova/react-test-utils/relay";

const novaDecorator = getNovaDecorator(schema, {
generateFunction: (operation, mockResolvers) => {
const result = MockPayloadGenerator.generate(
operation,
mockResolvers ?? null,
{
mockClientData: true, // this makes sure data for client extensions is generated
},
);

return result;
},
});
```

### (Pure relay or Nova with Relay) How can I make sure the mock data is generated with deferred payloads?

The current default generator doesn't return deferred payloads. However, similarly as in example above you can use the `generateFunction` option to provide your own generator which does.

```tsx
import { MockPayloadGenerator } from "relay-test-utils";
import { getNovaDecorator } from "@nova/react-test-utils/relay";

const novaDecorator = getNovaDecorator(schema, {
getEnvironmentOptions: () => ({
store: new Store(new RecordSource()),
}),
generateFunction: (operation, mockResolvers) => {
const result = MockPayloadGenerator.generateWithDefer(
operation,
mockResolvers ?? null,
{
mockClientData: true,
generateDeferredPayload: true, // this makes sure mock data is array of deferred payloads, not a single response
},
);

return result;
},
});
```

#### How can I mock query/mutation/subscription?

- [Query example](../examples/src/relay/Feedback/FeedbackContainer.stories.ts#L30)
Expand Down Expand Up @@ -306,7 +356,7 @@ graphql.mock.queueOperationResolver((operation) => {
return MockPayloadGenerator.generate(operation);
}
});
```
````

#### Can I reuse the setup I made for stories somehow in unit tests?

Expand Down
11 changes: 6 additions & 5 deletions packages/nova-react-test-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"react-relay": ">16",
"relay-runtime": ">16",
"relay-test-utils": ">16",
"@types/react-relay": ">16"
"@types/react-relay": ">16",
"@types/relay-test-utils": ">16"
},
"peerDependenciesMeta": {
"@apollo/client": {
Expand Down Expand Up @@ -82,13 +83,13 @@
"@testing-library/react": "^15.0.0",
"@types/jest": "^29.2.0",
"@types/react-relay": "^16.0.0",
"@types/relay-test-utils": "^17.0.0",
"@types/relay-test-utils": "^18.0.0",
"@types/react-test-renderer": "^18.3.0",
"monorepo-scripts": "*",
"react": "^18.3.1",
"react-relay": "^17.0.0",
"relay-runtime": "^17.0.0",
"relay-test-utils": "^17.0.0",
"react-relay": "^18.0.0",
"relay-runtime": "^18.0.0",
"relay-test-utils": "^18.0.0",
"react-test-renderer": "^18.3.1"
},
"repository": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,34 @@ import { novaGraphql } from "./nova-relay-graphql";
import { RelayMockPayloadGenerator } from "./test-utils";
import * as React from "react";
import { RelayEnvironmentProvider } from "react-relay";
import { createMockEnvironment } from "relay-test-utils";
import {
createMockEnvironment,
type MockPayloadGenerator,
} from "relay-test-utils";
import type { GraphQLSchema } from "graphql";
import type { ReactRenderer } from "@storybook/react";
import type { PlayFunctionContext } from "@storybook/types";
import type { NovaMockEnvironment } from "./nova-mock-environment";
import type { EnvironmentConfig } from "relay-runtime";

// We need this as `generateWithDefer` is overloaded and we want to get most relaxed return type
type OverloadedReturnType<T> =
T extends { (...args: any[]) : infer R; (...args: any[]) : infer R } ? R :
T extends (...args: any[]) => infer R ? R : any

type GraphitationGenerateArgs = Parameters<
RelayMockPayloadGenerator["generate"]
>;

// We put very relaxed constraints on the return type here, because we want users to be able to use
// Relay's payload generator for example for having returned deferred payloads or mocking client extensions,
// which doesn't work with graphitation's payload generator.
type RelayGenerateReturn =
| ReturnType<(typeof MockPayloadGenerator)["generate"]>
| OverloadedReturnType<(typeof MockPayloadGenerator)["generateWithDefer"]>;

type Options = { getEnvironmentOptions?: () => Partial<EnvironmentConfig> } & {
generateFunction?: typeof RelayMockPayloadGenerator.prototype.generate;
generateFunction?: (...args: GraphitationGenerateArgs) => RelayGenerateReturn;
};

export const getNovaRelayDecorator: (
Expand Down
2 changes: 1 addition & 1 deletion packages/nova-react-test-utils/src/relay/test-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class RelayMockPayloadGenerator {

public generate(
operation: RelayOperationDescriptor,
mockResolvers?: MockResolvers,
mockResolvers?: MockResolvers | null,
generateId?: () => number,
): ReturnType<typeof payloadGenerator> {
if (!operation.request.node.params.text) {
Expand Down
Loading

0 comments on commit 504d057

Please sign in to comment.