I have been stuck with this problem for almost 2 weeks. I'm trying to create a POC with react-query to fetch information from an external source. This specific component should call a Service method and list the result in a result table. I'm mocking this method to return something, but the tests are failing because it seems to be executed before calling the endpoint to fetch the wallets (and at this point, wallets are null, so nothing will be showed).
This is my test:
describe('And there are wallets created', () => {
test('Then it should render a list of wallets', async () => {
const wallets: Wallet[] = [{id: 1, name: 'wallet 1'}, {id: 2, name: 'wallet 2'}];
const listFn = jest.fn(() => {
return Promise.resolve(wallets);
});
WalletService.list = listFn;
renderComponent();
screen.getByText("wallet 1"); //FAILS because no wallets are being rendered
});
});
function renderComponent() {
const queryClient = new QueryClient();
render(
<QueryClientProvider client={queryClient}>
<ListWallet />
</QueryClientProvider>
);
}
This is my component:
const ListWallet: FC = () => {
(...)
const [wallets, setWallets] = useState<Wallet[] | null>(null);
const { isLoading: isLoadingWallets, refetch: getAllWallets } = useQuery<Wallet[], Error>(
"query-wallets",
async () => {
const wallets = await WalletService.list();
return wallets;
},
{
enabled: false,
onSuccess: (res: Wallet[]) => {
console.log('[onSuccess]: response is ' + JSON.stringify(res));
setWallets(res);
},
onError: (err: any) => {
(...)
},
}
);
useEffect(() => {
getAllWallets();
});
return (
<div>
<Card>
<CardHeader title="wallets/list"/>
<CardContent>
<Grid container spacing={1}>
<Table aria-label="simple table" data-testid="dataGrid">
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Wallet Name</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{wallets !== null && wallets.map(wallet => (
<TableRow key={wallet.id}>
<TableCell align="right">{wallet.id}</TableCell>
<TableCell align="right">{wallet.name}</TableCell>
<TableCell align="center">
<Button variant="text"
color="secondary"
aria-label='Edit'
size='small'
data-testid="goToEditWallet">
edit
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Grid>
</CardContent>
</Card>
</div>
);
}
In the console output, wallets are showed as null and then its showed again with the expected information, but nothing is rendered in the view.
Console output:
allWallets is null
allWallets is null
[onSuccess]: response is [{"id":1,"name":"wallet 1"},{"id":2,"name":"wallet 2"}]
[onSuccess]: response is [{"id":1,"name":"wallet 1"},{"id":2,"name":"wallet 2"}]
Am I doing something wrong here? I found references with tests but they seems to extract the useQuery to a customized hook and then they mock it, but I'd like to use it as it was showed. If there is no way to make it pass, I'll use the custom hook approach (well it is what it is).