Tester le crochet useSubscription
Je trouve un peu difficile, car la méthode est omise/non documentée sur le Apollo docs (au moment de l'écriture). Vraisemblablement, il devrait être moqué en utilisant le <MockedProvider />
de @apollo/react-testing
, tout comme les mutations sont dans les exemples donnés dans ce lien.
Test de l'état de chargement d'un abonnement en cours de fonctionnement:
Composant:
const GET_RUNNING_DATA_SUBSCRIPTION = gql`
subscription OnLastPowerUpdate {
onLastPowerUpdate {
result1,
result2,
}
}
`;
const Dashboard: React.FC<RouteComponentProps & Props> = props => {
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>
</>
);
};
Et un test réussi de l'état de chargement de l'abonnement:
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...',
);
});
});
});
Ajouter un autre test pour attendre que les données soient résolues à partir des simulacres transmis, selon les instructions du dernier exemple de la documentation pour tester useMutation, vous devez l'attendre.
Test cassé:
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);
});
Erreur le test interrompu lance:
No more mocked responses for the query: subscription OnLastPowerUpdate {
Dépendances:
"@apollo/react-common": "^3.1.3",
"@apollo/react-hooks": "^3.1.3",
"@apollo/react-testing": "^3.1.3",
Ce que j'ai déjà essayé:
Github repo avec exemple:
https://github.com/harrylincoln/apollo-subs-testing-issue
Quelqu'un là-bas capable de vous aider?
Le problème que je peux voir ici est que vous déclarez le composant SubscriptionData
à l'intérieur du composant Dashboard
donc la prochaine fois que le composant Dashboard
est re-rendu, un autre SubscriptionData
composant sera créé et vous verrez le message d'erreur:
Plus de réponses simulées pour la requête: abonnement OnLastPowerUpdate
Je vous suggère de retirer le composant SubscriptionData
du composant Dashboard
afin qu'il ne soit créé qu'une seule fois
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;
};
const Dashboard: React.FC<RouteComponentProps & Props> = props => {
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]);
if (!userHasProduct) {
return <Redirect to="/enter-serial" />;
}
return (
<>
<Header />
<PageContainer size="midi">
<Panel>
<SubscriptionData />
</Panel>
</PageContainer>
</>
);
};
Et pour les tests, vous pouvez essayer quelque chose comme ceci:
let component;
it('should show a loading state', async () => {
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...',
);
await wait(0);
});
it('should run the data', async () => {
expect(
// another test here
component.root...
).toBe();
});