De acuerdo, tengo este montón de código que se lanza en useEffect(() => {...}, []) también conocido como componentDidMount .
// utils/apiCalls.ts export const loadData = async <T>( url: string, errorMsg = "Couldn't retrieve data.", ): Promise<T> => { const res = await fetch(url, { mode: 'cors', credentials: 'include' }); if (res.ok) return await res.json(); throw new Error(errorMsg); }; export const loadChat = (id: number): Promise<IChat> => { return loadData<IChat>( `${CHAT_API}/${id}/nested/`, "We couldn't get the chat.", ); }; // components/MessageContainer.tsx const MessageContainer = (/* props */) => { /* * Some coding... */ useEffect(() => { if (session === null) return; if (chat === null) { loadChat(session.chat).then(setChat).catch(alert); return; } // More coding... }, [session, chat]); }; El problema surge cuando trato de probarlo con @testing-library/react ya que me da esta advertencia Warning: An update to MessagesContainer inside a test was not wrapped in act(...) .
¿Cómo puedo hacer una prueba correcta para esto? Aquí está la prueba que tengo ahora mismo.
// tests/MessagesContainer.spec.tsx describe('MessagesContainer suite', () => { it('loads messages on mount', () => { fetchMock.mockResponseOnce(JSON.stringify(ChatMock)); render( <SessionContext.Provider value={SessionMock}> <MessagesContainer {...MessagesContainerMockedProps} /> </SessionContext.Provider>, ); expect(fetchMock.mock.calls.length).toEqual(1); }); }); NOTA : El renderizado envolvente en act no funcionó.
Entonces, al final, utilicé waitFor para verificar si el elemento se ha montado.
// tests/ChatMessagesContainer.spec.tsx describe('ChatMessagesContainer suite', () => { it('renders multiple messages', async () => { const messageMock = Object.assign({}, MessageMock); messageMock.message = faker.lorem.words(); const chatMock = Object.assign({}, ChatMock); chatMock.chat_message_set = [MessageMock, messageMock]; fetchMock.mockResponseOnce(JSON.stringify(chatMock)); const { getAllByText } = render( <AuthContext.Provider value={UserMock}> <SessionContext.Provider value={SessionMock}> <MessagesContainer {...MessagesContainerMockedProps} /> </SessionContext.Provider> </AuthContext.Provider>, ); // THIS IS THE IMPORTANT PART expect(await screen.findByText(MessageMock.message)).toBeInTheDocument(); expect(getAllByText(MessageMock.author.username).length).toEqual(2); }); }); Este artículo fue realmente útil Tal vez no necesite act .
fetch es una función asíncrona que finaliza solo todos los extremos regulares de ejecución de secuencias de comandos. Realmente debe esperar a que finalice la fetch antes de llamar a expect . Además, no se recomienda usar testing-library como lo hizo. Desea verificar cómo se representa el elemento después de fetch , escriba su prueba de acuerdo con el resultado de excepción en la interfaz de usuario. Por ejemplo, si después de buscar espera algo como esto:
<span>message</span>esperas un espacio con el mensaje, y la prueba será:
expect(screen.findByText('message'));