I need MockedProvider to return mocked results when a query is re-executed with data.fetchMore
With the following mock:
Feed.mocks.js
import feed from 'feedQuery'; // this is the same query used by the component
[{
request: { // this mock works correctly, on mount
query: feed,
variables: {
limit: 10,
offset: 0,
orderBy: 'id_DESC',
},
},
response:{
// accurate response data, matched query exactly
}},
{ // this is the fetchMore mock
request: {
query: feed,
variables: {
offset: 0,
limit: 10,
orderBy: 'id_ASC',
},
},
result: {
// exact same results as above, but in reverse
// This mock does not work
}
}];
And the following test:
Feed.test.js
import { render, waitForElement, fireEvent } from 'react-testing-library';
import { MockedProvider } from 'react-apollo/test-utils';
import FeedTable from 'FeedTable';
import FEED_MOCk from 'Feed.mocks'
let container;
let getId;
beforeAll(() => {
({ container } = render(
<MockedProvider mocks={FEED_MOCK} addTypename={false}>
<FeedTable />
</MockedProvider>
));
getId = id => container.querySelectorAll('tr')[id].childNodes[1].innerHTML;
});
// Passes ✓ - loading state
it('should render skeleton while loading', () => {
expect(container.querySelectorAll('.skeleton__heading').length).toBe(14);
expect(container.querySelectorAll('.skeleton__text')).toMatchSnapshot();
});
// Passes ✓ - this moves the table passed its initial loading state,
// proof that the initial query mock works
it('should render 10 rows by default', async () => {
await waitForElement(() => container.querySelector('.table-loaded'));
const numberOfRows = (await waitForElement(() => container.querySelectorAll('tr'))).length;
expect(numberOfRows).toBe(11); // 1 Header Row + 10 Data Rows = 11;
});
// Passes ✓ - actually pulling out the Mock ID's
it('rows should be in descending order by ID by default ', async () => {
expect(getId(1)).toBe('10');
expect(getId(2)).toBe('9');
});
// Fails ✖ - Throw error indicated below at : Error Message
it('clicking id header should change order to ID Ascending', async () => {
expect(getId(1)).toBe('10');
expect(getId(2)).toBe('9');
const idHeader = container.querySelector('button--table-sort');
fireEvent.click(idHeader);
await waitForElement(() =>
container.querySelctor(
'selector-indicating-table-loaded)'
)
);
expect(getId(1)).toBe('1');
expect(getId(1)).toBe('2');
});
What should happen?
The test that fails, should pass. I should receive my mocked results, which are identical to the first mock, but in reverse ie. Ascending order.
I get the no more mocked responses error
Error Message
Network error: No more mocked responses for the query: query myQuery($limit: Int!, $offset: Int!, $orderBy: OrderBy!, $filter: String) {
feed(limit: $limit, offset: $offset, orderBy: $orderBy, filter: $filter) {
myFeed {
id
}
count
}
}
, variables: {"offset":0,"limit":10,"orderBy":"id_ASC"}
I have a table component that implements pagination by executing a GraphQL query with updated limit offset and orderBy variables.
When this table component first mounts, the initial query which populates the table is as follows:
feed(limit: $limit, offset: $offset, orderBy: $orderBy, filter: $filter) {
myFeed {
id
description
... other fields
}
count
}
}
, variables: {"offset":0,"limit":10,"orderBy":"id_DESC"}
Note: the orderBy is 'is_DESC'
What I'm trying to test:
1) When I click a table header Apollo Client sends an updated GraphQL query to fetch the paginated data.
2) When I click next page, Apollo Client sends an updated GraphQL query to fetch the paginated data.
I am using react-testing-library to simulate clicks, and when a header is clicked the following code is executed:
data.fetchMore({
fetchPolicy: 'cache-and-network',
variables: {
offset,
limit,
orderBy: `${key}_${newDirection}`, // the only thing that changes
filter,
},
updateQuery: (previous, { fetchMoreResult }) => {
setLoading(false);
return fetchMoreResult || previous;
},
});
As you can see we are updating the query and changing only a single variable, the orderBy. Apollo client handles this okay as the error message indicates it is looking for a mock response with orderBy : 'id_ASC' _however it is unable to find one_
I have not got time to create a reproduction repo at the minute, but I will hopefully be able to soon.
Version
My issue sounds quite similar to https://github.com/apollographql/react-apollo/issues/993
Which was seemingly closed after no responses... worrying
So I figured out the issue after 3 days of banging my head, going to do a small write up here.
I've read several other threads where people mentioned that the variables declared in the mocks must match exactly the variables being passed to ApolloClient.
But I did not realise an _undefined_ variable would be passed through.
Take the following Query
<Query
query={myQuery}
variables={{
limit: 10,
offset: 0,
filter, // this value is undefined
}}
>
</Query>
Would you expect the following mock to match this query?
request: {
query: myQuery,
variables: {
limit: 10,
offset: 0
},
},
I did, but I was mistaken. So just for future reference - undefined values are still included and must be mocked up as well
Most helpful comment
So I figured out the issue after 3 days of banging my head, going to do a small write up here.
I've read several other threads where people mentioned that the variables declared in the mocks must match exactly the variables being passed to ApolloClient.
But I did not realise an _undefined_ variable would be passed through.
Take the following Query
Would you expect the following mock to match this query?
I did, but I was mistaken. So just for future reference -
undefinedvalues are still included and must be mocked up as well