Intended outcome:
Using Enzyme & Jest in React Native.
Test will render the component, pass in the result of the query, and it will be possible to make assertions about component's content.
Actual outcome:
The query is stuck in loading state (console.log that prints the query is called only once), and the wrapper never re-renders even when calling wrapper.update();. Since component doesn't render at all when the query result isn't yet ready, the wrapper is always empty. If I add await new Promise(resolve => setTimeout(resolve)); (as in the example below), it times out after 5 seconds.
Not sure if the problem is React Native specific, I haven't tried it in plain React yet.
How to reproduce the issue:
const DictQuery = gql`
query {
dictionaries {
test {
id
value
}
}
}
`;
const GraphQLMocks = [
{
request: { query: DictQuery },
result: {
data: {
dictionaries: {
test: [
{
id: '11',
value: 'Value 1'
},
{
id: '12',
value: 'Value 2'
}
]
}
}
}
}
];
it('tests it', async () => {
const wrapper = mount(
<MockedProvider removeTypename mocks={GraphQLMocks}>
<MyScreen />
</MockedProvider>
);
await new Promise(resolve => setTimeout(resolve));
wrapper.update();
expect(wrapper.html()).to.contain('Hello');
});
@graphql(DictQuery, {
name: 'dictionaries',
options: () => ({
notifyOnNetworkStatusChange: true
})
})
class MyScreen extends React.Component<Props, State> {
render() {
const { dictionaries } = this.props;
console.log('dictionaries', dictionaries);
if (!dictionaries || dictionaries.loading) {
return null;
}
return (<p>Hello</p>);
}
}
Version
+1 Same issue with plain React
Facing same issue with react-native
it("should show error UI", () => {
const kycStatus = -1;
const panNumber = "CNIPL3293D";
const mockedData = {
accounts: [
{
__typename: "AccountNode",
name,
kycStatus,
panNumber
}
]
};
const mocks = {
request: {query: PAN_REGISTRATION_ACCOUNTS_QUERY},
result: {data: mockedData}
};
const component = mount(
<MockedProvider addTypename={false} mocks={[mocks]}>
<RegistrationPanContainer />
</MockedProvider>
);
const promise1 = new Promise((resolve) => setTimeout(resolve("Test"), 2));
promise1
.then(() => {
component.update();
console.log("tree", component.debug());
})
.catch((error) => {
console.log("error");
})
// console.log("Component", component);
});
Above gives me following output:-
tree <MockedProvider addTypename={false} mocks={{...}}>
<ApolloProvider client={{...}}>
<Apollo(RegistrationPanContainer)>
<Query displayName="Apollo(RegistrationPanContainer)" skip={false} query={{...}} warnUnhandledError={true}>
<RegistrationPanContainer loadingAccounts={true} errorAccounts={[undefined]} accounts={[undefined]} />
</Query>
</Apollo(RegistrationPanContainer)>
</ApolloProvider>
</MockedProvider>
I'm having the same issue with plain React. Data is clearly coming back but Enzyme isn't re-rendering past the loading state.
Running component.update(); fixed for me.
Thanks @stolinski. Calling update() worked for me too in React Native.
Is this closeable or does someone want to propose a PR with a change?
@rosskevin I have the same issue with React
describe('[Container] ClientTable', () => {
test('should be connected to store', async () => {
const clients = [{ id: '007', name: 'Vincent' }];
const query = loader('./getClients.graphql');
const mocks = [
{
request: { query },
result: {
data: {
clients,
},
},
},
];
const container = mount(
<MockedProvider mocks={mocks} addTypename={false}>
<ClientTableContainer />
</MockedProvider>,
);
await new Promise((resolve: () => void): NodeJS.Timeout => setTimeout(resolve, 0));
container.update();
expect(container.find<ClientTableProps>(ClientTable).props().clients).toEqual(clients);
});
});
My container is like that
export default graphql(loader('./getClients.graphql'), {
props: (props: OptionProps<Props, GetClientsProps>): GetClientsProps => ({
clients: (props.data && props.data.clients) || [],
}),
})(ClientTable);
I discover that, if I change for this
export default graphql(loader('./getClients.graphql'), {
props: (props: OptionProps<Props, GetClientsProps>): GetClientsProps => (console.log(''), {
clients: (props.data && props.data.clients) || [],
}),
})(ClientTable);
It works.
I have no explanation.
I believe this is closable - thanks!
Most helpful comment
Running component.update(); fixed for me.