Closed matt-dalton closed 2 years ago
...I should clarify....I don't need to unit test all the functionality of the lib (e.g. offline / online conditions etc) - I just want to test how my components behave when I return data. So I just need useQuery to return some data basically.
Hi @matt-dalton, at the moment to do some offline tests the only way is to copy the logic of the official relay mock https://github.com/facebook/relay/blob/main/packages/relay-test-utils/RelayModernMockEnvironment.js and replace the environment (as I did in this repository).
This is because it is not allowed to pass a custom environment.
OK makes sense. Is there any reason not to just expose createMockEnvironment from your module like the main lib does? Then we could just use your maintained version itself
@matt-dalton, I find the idea interesting, I just changed the PR in wora in order to add these utilities.
Tomorrow I hope to have time to release the first release candidates.
Hi @matt-dalton, i released react-relay-offline 5.0.0-rc.1, do you have the chance to try it? 👍
Hi @morrys ...I just tried upgrading to test. I can't see how to import createMockEnvironment
- is there a different way I should access this?
import {createMockEnvironment} from 'react-relay-offline/test';
Ah OK....missed the /test
I upgrade to react-relay-offline: 5.0.0-rc.1
and react-relay: 12.0.0
and get this error:
It could be I've got the wrong version of one of your sub-dependencies? I did try clearing node_modules and reinstalling though.
add as dependency dev relay-test-utils-internal v12
Hmmm....I think I'm still missing something. I've got this test file:
describe('QueryRenderer', () => {
const setup = () => {
const environment =createMockEnvironment()
// This just uses the logic in my initial post above
const Component = withQueryRenderer({
query: TestQuery
})(TestComponent)
const renderer = render(
<RelayEnvironmentProvider environment={environment}>
<Component />
</RelayEnvironmentProvider>
)
act(() => {
environment.mock.resolveMostRecentOperation(operation =>
MockPayloadGenerator.generate(operation)
)
})
return {
renderer
}
}
it('should render the component correctly', () => {
const { renderer } = setup()
renderer.debug()
})
})
useQuery
still returns null for the data. I've tried:
await environment.hydrate()
before the component render like you've done in some tests. This gives me a netinfo error of Cannot read property 'isInternetReachable' of undefined
isRehydrated
and isOnline
to prevent it going to the offline store, but useQuery
still returns nullAm I missing something here? I don't need to test online/offline nuances, I just want to mock the query responses like you can with the raw Relay lib.
it would be useful to create a sample project in which to check for the error...
Do you have an example of a test that works? Perhaps I can try that first.
You can see the tests of this repository
I've managed to narrow down the problem...
I've used your React web todo-updater
example to recreate the same test I have in my codebase. I got the test to work, and the logic I posted renders 3 times before returning data:
However, in my real codebase (which uses React Native), I just get one render:
If I log inside
useRestore
, I can see that environment.hydrate()
never completes.
Is there anything specific to React Native that would prevent this hydrate function from working in tests? e.g. Do I need to mock anything in particular from async storage (I'm currently using the default mock)? Anything else I can log that might help debug?
For reference the working React test file is:
import TestComponent from '../TestComponent';
import {RelayEnvironmentProvider} from 'react-relay';
import {MockPayloadGenerator} from 'relay-test-utils';
import {act, render, waitFor, screen} from '@testing-library/react';
import environment from '../../relay';
describe('TestComponent', () => {
const setup = () => {
const renderer = render(
<RelayEnvironmentProvider environment={environment}>
<TestComponent />
</RelayEnvironmentProvider>,
);
act(() => {
environment.mock.queueOperationResolver(operation =>
MockPayloadGenerator.generate(operation, {
Query: () => ({
user: {
totalCount: 123,
},
}),
}),
);
});
return {
renderer,
};
};
it('should render the component correctly', async () => {
const {renderer} = setup();
await waitFor(() => renderer.getByTestId('text-read'));
expect(screen.getByText('Total count is: 123')).toBeTruthy();
});
});
You might see what happens here: https://github.com/morrys/wora/blob/master/packages/offline-first/src/index.ts#L97
Also, here you find an example project in react-native, I don't know if you have time to adapt it to the latest version of react-relay-offline and create a test so as to show me the error
Thanks for the pointer @morrys - that file gave me a way of debugging the problem.
Looks like it works now I've mocked netinfo using the latest netinfo version's mock:
// Copied from later version of netinfo: https://github.com/react-native-netinfo/react-native-netinfo/blob/master/jest/netinfo-mock.js
// Can use lib mock once we (react-relay-offline) upgrades to the later version
const defaultState = {
type: 'cellular',
isConnected: true,
isInternetReachable: true,
details: {
isConnectionExpensive: true,
cellularGeneration: '3g'
}
}
const RNCNetInfoMock = {
configure: jest.fn(),
fetch: jest.fn(),
addEventListener: jest.fn(),
useNetInfo: jest.fn()
}
RNCNetInfoMock.fetch.mockResolvedValue(defaultState)
RNCNetInfoMock.useNetInfo.mockReturnValue(defaultState)
RNCNetInfoMock.addEventListener.mockReturnValue(jest.fn())
export default RNCNetInfoMock
I think basically your lib was using an earlier netinfo version (or my project didn't resolve to the latest). Using the now recommended approach above fixed the problem.
Thanks for the help!
Is there a possibility of rolling out your mock as a patch for v4 (Relay v11)? That would allow us to use it ahead of the Relay 12 upgrade - would be much appreciated!
Btw @morrys do you think it would be easier to roll this out via a v4 patch or an official v5 release?
The v5 release candidate looked pretty solid when I was using it, but we could do some more testing with it if that would help.
Version 5 rc is stable I have not released the official version to check compatibility with relay v13 (released yesterday).
I'm back from vacation on Monday and I'll let you know
released with react-relay-offline 5.0.0 https://github.com/morrys/react-relay-offline/releases/tag/v5.0.0
I am now working on relay-hooks version 7 to support relay v13 and later release react-relay-offline version 6
Let me know if you have a problem with the new release 💯
Hi morrys!
I'm trying to unit test using this kind of approach on Relay v11.0.2, relay-offline v4.0.0
I am fetching like this:
Typically I would pass in
environment={createMockEnvironment()}
here, but if I do that it fails because I'm missing offline-specific functions:TypeError: environment.isRehydrated is not a function
If I then try and mock these in a simple way (e.g. returning true for isRehydrated and isOffline) the data returns null.
I saw you had a mock in the codebase here, but this seems to have a lot of complexity I'd rather not replicate.
Is there anything simple I can add as a wrapper around createMockEnvironment that would allow me to fetch data in my tests?