Description
Testing the useSubscription hook I'm finding a bit difficult, since the method is omitted/not documented on the Apollo docs (at time of writing). Presumably, it should be mocked using the <MockedProvider />
from @apollo/react-testing
, much like the mutations are in the examples given in that link.
Testing the loading state for a subscription I have working:
Component:
const userHasProduct = !!props.user.serialNumber;
const [startGetRunningData] = useMutation(START_GET_RUNNING_DATA);
const [stopGetRunningData] = useMutation(STOP_GET_RUNNING_DATA);
useEffect(() => {
startGetRunningData({
variables: { serialNumber: props.user.serialNumber },
});
return () => {
stopGetRunningData();
};
}, [startGetRunningData, stopGetRunningData, props]);
const SubscriptionData = (): any => {
const { data, loading } = useSubscription(GET_RUNNING_DATA_SUBSCRIPTION);
if (loading) {
return <Heading>Data loading...</Heading>;
}
const metrics = [];
if (data) {
console.log('DATA NEVER CALLED IN TEST!');
}
return metrics;
};
if (!userHasProduct) {
return <Redirect to="/enter-serial" />;
}
return (
<>
<Header />
<PageContainer size="midi">
<Panel>
<SubscriptionData />
</Panel>
</PageContainer>
</>
);
};
And a successful test of the loading state for the subscription:
import React from 'react';
import thunk from 'redux-thunk';
import { createMemoryHistory } from 'history';
import { create } from 'react-test-renderer';
import { Router } from 'react-router-dom';
import wait from 'waait';
import { MockedProvider } from '@apollo/react-testing';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import Dashboard from './Dashboard';
import {
START_GET_RUNNING_DATA,
STOP_GET_RUNNING_DATA,
GET_RUNNING_DATA_SUBSCRIPTION,
} from './queries';
const mockStore = configureMockStore([thunk]);
const serialNumber = 'AL3286wefnnsf';
describe('Dashboard page', () => {
let store: any;
const fakeHistory = createMemoryHistory();
const mocks = [
{
request: {
query: START_GET_RUNNING_DATA,
variables: {
serialNumber,
},
},
result: {
data: {
startFetchingRunningData: {
startedFetch: true,
},
},
},
},
{
request: {
query: GET_RUNNING_DATA_SUBSCRIPTION,
},
result: {
data: {
onLastPowerUpdate: {
result1: 'string',
result2: 'string'
},
},
},
},
{
request: {
query: STOP_GET_RUNNING_DATA,
},
result: {
data: {
startFetchingRunningData: {
startedFetch: false,
},
},
},
},
];
afterEach(() => {
jest.resetAllMocks();
});
describe('when initialising', () => {
beforeEach(() => {
store = mockStore({
user: {
serialNumber,
token: 'some.token.yeah',
hydrated: true,
},
});
store.dispatch = jest.fn();
});
it('should show a loading state', async () => {
const component = create(
<Provider store={store}>
<MockedProvider mocks={mocks} addTypename={false}>
<Router history={fakeHistory}>
<Dashboard />
</Router>
</MockedProvider>
</Provider>,
);
expect(component.root.findAllByType(Heading)[0].props.children).toBe(
'Data loading...',
);
});
});
});
Adding another test to wait until the data has been resolved from the mocks passed in, as per the instructions on the last example from the docs for testing useMutation, you have to wait for it...
it('should run the data', async () => {
const component = create(
<Provider store={store}>
<MockedProvider mocks={mocks} addTypename={false}>
<Router history={fakeHistory}>
<Dashboard />
</Router>
</MockedProvider>
</Provider>,
);
await wait(0);
});
The error I get is:
No more mocked responses for the query: subscription OnLastPowerUpdate {
This doesn't make any sense to me since the working test and this test's mocks are identical.
Deps:
"@apollo/react-common": "^3.1.3",
"@apollo/react-hooks": "^3.1.3",
"@apollo/react-testing": "^3.1.3",
Things I've tried already:
- react-test-renderer / enzyme / @testing-library/react
- awaiting next tick
- initialising the client in the test differently
- playing with the
fetchPolicy
option via the methoduseSubscription
Anyone out there able to help?