A partir de React Testing Library v13 ya no es necesario instalar la liberia @testing-library/react-hooks. Ahora es tan simple como:
import { renderHook, waitFor } from "@testing-library/react";
Como podran notar tambien importe el waitFor pues el mismo comportamiento de waitForNextUpdate (no disponible) se puede simular con esta funcionalidad. El ejercicio de la clase quedaria de la siguiente manera:
¡Excelente aporte técnico Luis! 👏
Efectivamente, la migración a renderHook y waitFor desde @testing-library/react representa una mejora significativa en la API. Esta consolidación no solo reduce dependencias sino que también alinea mejor con los principios de Testing Library.
Gracias por mantener al día a la comunidad con las mejores prácticas actuales. 🚀
Otra alternativa por si les resulta un error con el waitForNextUpdate():
TypeError: waitForNextUpdate is not a function ❯ src/hooks/useOrders.test.ts:57:15 55| 56| // Wait for the hook to update after fetching orders 57| await waitForNextUpdate(); | ^ 58| 59| // Ensure the loading state is false and orders are loaded
De hecho no debería mostrar ese error, y realmente lo que pasa (y es algo que me pasó), es importar "renderHook" de "@testing-library/react-hooks" y no de "@testing-library/react"
¡Excelentes observaciones!
Para clarificar: desde RTL v13+, el enfoque recomendado es:
import{ renderHook, waitFor }from'@testing-library/react';// Nuevo approachconst{ result }=renderHook(()=>useOrders());awaitwaitFor(()=>{expect(result.current.orders).toBeDefined();});```El error `waitForNextUpdate is not a function` típicamente ocurre por mezclar APIs antiguas con nuevas. La migración completa a `@testing-library/react` es la solución más limpia y alineada con las mejores prácticas actuales.Gracias a ambos por contribuir a la claridad técnica de este tema.🚀
💻👨💻 ¡Listo el reto! Valide que en el primer caso de uso el error fuera "null" porque así funciona en la lógica de nuestro custom hook:
it("Deberia obtener las ordenes",async()=>{const mockOrders =[{id:"f47ac10b-58cc-4372-a567-0e02b2c3d479",customer:{id:"60d07f61-99bf-4b90-955b-5d3a7c9bb3d4",name:"John Doe",email:"john.doe@example.com",},products:[{id:"7567ec4b-b10c-48c5-9345-fc73c48a80a2",name:"Laptop",price:999.99,quantity:1,},{id:"7567ec4b-b10c-48c5-9345-fc73c48a80a3",name:"Mouse",price:29.99,quantity:1,},],total:1029.98,status:"delivered",orderDate:"2023-10-01T10:00:00Z",shippingAddress:{street:"123 Main St",city:"Anytown",state:"CA",zipCode:"12345",country:"USA",},paymentMethod:"credit_card",},]; mockGetOrders.mockResolvedValue(mockOrders); mockUseSession.mockReturnValue({user:{id:1}})const{ result }=renderHook(()=>useOrders());expect(result.current.loading).toBe(true);awaitwaitFor(()=>{expect(result.current.loading).toBe(false);expect(result.current.orders).toEqual(mockOrders);expect(result.current.error).toBe(null);});});
Y acá validé el caso de error, que lo que hace es settear un texto de error en este estado:
it("Deberia mostrar el mensaje de error",async()=>{ mockGetOrders.mockRejectedValue("Failed to fetch orders. Please try again later.");const{ result }=renderHook(()=>useOrders());awaitwaitFor(()=>{expect(result.current.error).toBe("Failed to fetch orders. Please try again later.");});});
desde react 18 no se usa el waitfor Next ni se instala la libreria de react-hook, evitar este paso y solo usar con las importaciones de import { renderHook, waitFor } from "@testing-library/react"; usando sus correspondientes:
it("Deberia retornar error",async()=>{ mockGetOrders.mockRejectedValue("Hubo un error"); mockUseSession.mockReturnValue({ user:{ id:"1"}});const{ result }=renderHook(()=>useOrders());expect(result.current.loading).toBe(true);awaitwaitFor(()=>{expect(result.current.error).toBe("Failed to fetch orders. Please try again later.");expect(result.current.loading).toBe(false);expect(result.current.orders).toEqual([]);});});```it("Deberia retornar error",async()=>{ mockGetOrders.mockRejectedValue("Hubo un error"); mockUseSession.mockReturnValue({ user:{ id:"1"}});const{ result }=renderHook(()=>useOrders());expect(result.current.loading).toBe(true);awaitwaitFor(()=>{expect(result.current.error).toBe("Failed to fetch orders. Please try again later.");expect(result.current.loading).toBe(false);expect(result.current.orders).toEqual(\[]);});});