mockClear does not reset the environment properly
- Dominant language
- Rust
- Stars
- 19k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
`createMockEnvironment` returns an instance of `environment` with `mockClear`, but this method does not fully clean the internals.
For example, we would like to create only 1 environment and use `mockClear` between tests to reset the internals in place of running `createMockEnvironment` in each of them, in this way we could move the test setup to `jest.env.js` loaded on `setupFilesAfterEnv`, in some way similar to this example:
```javascript
const environment = createMockEnvironment();
const Provider: React.FC = ({children}) => (
{children}
);
const Dummy: React.VFC<{fetchKey?: string | number}> = ({fetchKey}) => {
const data = useLazyLoadQuery(
graphql`
query dummyQuery {
foo
}
`,
{},
{fetchKey},
);
return (
);
};
describe(() => {
afterEach(() => {
environment.mockClear();
});
it('loading', () => {
render();
// none resolve / reject
expect(...);
});
it('error', () => {
render();
environment.mock.rejectMostRecentOperation(new Error('oops'));
expect(...);
});
it('data', () => {
render();
environment.mock.resolveMostRecentOperation({foo: 123})
expect(...);
});
});
```
At present if we run each of the tests above individually, they work, but if we try them altogether, then they fail. For example with:
```text
Invariant Violation: RelayModernMockEnvironment: There are no pending operations in the list
```
The former error is because the `environment` holds some module state for [`requestCachesByEnvironment`](https://github.com/facebook/relay/blob/30995390857adca421a89f0a58b098bf5ef1c839/packages/relay-runtime/query/fetchQueryInternal.js#L310).
And for more complex scenarios where multiple tests are fired in a row, we can hit 2 other caches that are not cleared in `mockClear`. Also we must clear the store between tests as already [reported and PR](https://github.com/facebook/relay/issues/3686).
To sum up, just adding a few lines in the `mockClear` we could use the same instance all the time.
Here a snippet with some methods that "properly" exposed in the API will make it work:
https://github.com/facebook/relay/blob/741741acc84cc03a3c7cba3014b5c5bf210f78d9/packages/relay-test-utils/RelayModernMockEnvironment.js#L534
```javascript
import {getFragmentResourceForEnvironment} from 'react-relay/lib/relay-hooks/FragmentResource'; // <== not exposed in barrel file
import {getQueryResourceForEnvironment} from 'react-relay/lib/relay-hooks/QueryResource'; // <== not exposed in barrel file
import {getRequestCache} from 'relay-runtime/lib/query/fetchqueryInternal'; // <== not exported by the module
...
function createMockEnvironment(
...
const qr = getQueryResourceForEnvironment(environment);
const fr = getFragmentResourceForEnvironment(environment);
const rc = getRequestCache(environment);
qr._cache.clear();
fr._cache.clear();
rc.clear();
// @see https://github.com/facebook/relay/pull/3687
environment.getStore().getSource().clear();
```
@kassens @alunyov @sibelius Do you foresee something against it? Please advise.
Contributor guide
Assessment
This issue has not been assessed yet.