Reputation: 6373
I'm trying to test a component using React Relay and React Testing Library
// @flow
import { Suspense } from 'react';
import {
RelayEnvironmentProvider,
useLazyLoadQuery,
graphql,
} from 'react-relay/hooks';
import { createMockEnvironment, MockPayloadGenerator } from 'relay-test-utils';
import { render, cleanup, screen, act } from '@testing-library/react';
import Banner from './Banner';
jest.mock('react-router-dom', () => ({
useLocation: jest.fn(() => ({
pathname: 'some-path',
})),
}));
describe('<Banner>', () => {
let mockEnvironment;
const defaultMockResolver = {
// We do not want a consistent return in this case since we want the default MockPayloadGenerator behavior for most fields
// See https://relay.dev/docs/en/testing-relay-components#mock-resolver-context
// eslint-disable-next-line consistent-return
String(context) {
if (context.name === 'viewer') {
return {id: 111 };
}
},
};
beforeEach(() => {
mockEnvironment = createMockEnvironment();
});
afterEach(cleanup);
it('renders - snapshot', () => {
mockEnvironment = createMockEnvironment();
const RelayComponent = () => {
const data = useLazyLoadQuery(
graphql`
query BannerTestQuery @relay_test_operation {
viewer {
# Spread the fragment you want to test here
...Banner_viewer
}
}
`,
{},
);
return <Banner viewer={data.myData} />;
};
render(
<RelayEnvironmentProvider environment={mockEnvironment}>
<Suspense fallback="Loading...">
<RelayComponent />
</Suspense>
</RelayEnvironmentProvider>,
);
// expect(container.firstChild).toMatchSnapshot();
act(() => {
mockEnvironment.mock.resolveMostRecentOperation(operation =>
MockPayloadGenerator.generate(operation, defaultMockResolver),
);
});
screen.debug();
});
});
The test however does not load the component with the mocked data but only returns the Suspense fallback
Upvotes: 2
Views: 1112
Reputation: 438
Trying to add more detail here. Agree with Tassilo Singhammer answer. Before rendering, you need to invoke queueOperationResolver
. Inside the queueOperationResolver
you need to generate mock payload via MockPayloadGenerator
. Here is the bear minimum example:
test('Data Render', () => {
const environment = createMockEnvironment();
environment.mock.queueOperationResolver((operation:any) =>
MockPayloadGenerator.generate(operation),
);
const renderer = ReactTestRenderer.create(
<RelayEnvironmentProvider environment={environment}>
<Suspense fallback={<div data-testid="loading">Loading... </div>}>
<HelmetProvider>
<MemoryRouter>
<Home /> // Your component with the useLazyLoadQuery or a QueryRenderer
</MemoryRouter>
</HelmetProvider>
</Suspense>
</RelayEnvironmentProvider>);
// At this point operation will be resolved
// and the data for a query will be available in the store
expect(
renderer.root.find(node => node.props['data-testid'] === 'yourButton'),
).toBeDefined();
});
In my case, I need HelmetProvider
and MemoryRouter
. You may skip, if not needed.
Here is the official documentation: https://relay.dev/docs/guides/testing-relay-components/#example-with-queueoperationresolver
Upvotes: 1
Reputation: 31
This actually works: https://githubmemory.com/repo/facebook/relay/issues/3276
It is important, that you call queueOperationResolver
before rendering the component.
Upvotes: 1