Je reçois toujours un Warning: An update to App inside a test was not wrapped in act(...).
dans ma suite de tests chaque fois que je fais une requête API et que je mets à jour l'état.
J'utilise la bibliothèque react-testing. J'ai également essayé d'utiliser les utils de test ReactDOM, j'ai obtenu le même résultat. Une autre chose que j'ai essayée a été de mettre le conteneur en act
, j'ai toujours obtenu le même résultat.
Veuillez noter que: Mon application fonctionne et mon test réussit. J'ai juste besoin de savoir ce que je faisais de mal ou si c'est un bogue dans le paquet react-dom qui fait apparaître cette erreur. Et il est mauvais de se moquer de l'erreur de la console et de la désactiver.
const [data, setData] = useState([]); const [error, setError] = useState(''); const fetchInitData = async () => { try { const res = await fetch(API_URL); const data = await res.json(); if (data.fault) { setError('Rate limit Exceeded'); } else { setData(data.results); } } catch(e) { setError(e.message); } }; useEffect(() => { fetchInitData(); }, [isEqual(data)]);
Voici l'implémentation du hook:
global.fetch = require('jest-fetch-mock'); it('should clear select content item', async () => { fetch.mockResponseOnce(JSON.stringify({ results: data })); const { container } = render(<App />); const content = container.querySelector('.content'); await wait(); expect(content.querySelectorAll('.content--item').length).toBe(2); });
4 Réponses :
C'est un problème connu, vérifiez ce problème dans Github https://github.com/kentcdodds/react-testing-library/issues/281
Pour vous débarrasser de l'avertissement act()
vous devez vous assurer que vos promesses se résolvent de manière synchrone. Vous pouvez lire ici comment procéder.
Sommaire:
La solution à cela est un peu compliquée:
- nous polyfill Promise globalement avec une mise en œuvre qui peut résoudre les promesses `` immédiatement '', comme la promesse
- transpilez votre javascript avec une configuration babel personnalisée comme celle de ce dépôt
- utilisez jest.runAllTimers (); cela va également vider la file d'attente des tâches de promesse
J'ai eu ce problème et j'ai renoncé à utiliser wait and async à la place, j'ai utilisé des faketimers de plaisanterie et ainsi de suite, donc votre code devrait être quelque chose comme ça.
global.fetch = require('jest-fetch-mock'); it('should clear select content item', /*async */ () => { jest.useFakeTimers(); fetch.mockResponseOnce(JSON.stringify({ results: data })); const { container } = render(<App />); const content = container.querySelector('.content'); // await wait(); act(() => { jest.runAllTimers(); }); expect(content.querySelectorAll('.content--item').length).toBe(2); });
Pour tous ceux qui tombent dessus plus d'un an plus tard comme je l'ai fait, le problème mentionné par Giorgio a depuis été résolu, et wait
a depuis été remplacé par waitFor
, comme documenté ici:
https://testing-library.com/docs/dom-testing-library/api-async/
Cela étant le cas, je pense que la solution à l'avertissement devrait maintenant être quelque chose comme ceci:
beforeEach(async () => { await waitFor(() => render(<App />)); });
Dans mon cas, j'avais un composant App
chargeant des données de manière asynchrone dans un hook useEffect
, et je useEffect
donc cet avertissement à chaque test, en utilisant beforeEach
pour rendre App
. C'était la solution spécifique pour mon cas:
import { render, waitFor } from '@testing-library/react'; // ... it('should clear select content item', async () => { fetch.mockResponseOnce(JSON.stringify({ results: data })); const { container } = render(<App />); const content = container.querySelector('.content'); await waitFor(() => expect(content.querySelectorAll('.content--item').length).toBe(2); ); });
Tout cela fait-il partie d'une fonction?
Ouais c'est ça. Laisse-moi ajouter que ça marche et que mon test réussit. Le seul problème, ce sont les erreurs ennuyeuses