Búsqueda de sitios web

reactjs - Necesito renderizar un hook personalizado y probar el mensaje de error cuando alguien intenta usar el hook sin el proveedor


Usando React, Jest y la biblioteca de pruebas de React

Mi hook personalizado

import { useContext } from "react";

import { SelectThemeContext } from "../contexts/SelectThemeContext/SelectThemeContextProvider";

import { isEmpty } from "../utils/functions/isEmpty";

const useSelectThemeContext = () => {
  const context = useContext(SelectThemeContext);

  if (isEmpty(context)) {
    throw Error(
      "You have to use useSelectThemeContext inside <SelectThemeContextProvider />",
    );
  }

  const { theme, toggleTheme } = context;
  return { theme, toggleTheme };
};

export default useSelectThemeContext;

Mi prueba

it("[ACAMP-03] - should return error message when trying to use custom hook without provider", async () => {
    let message: string;
    try {
      await renderHook(() => useSelectThemeContext());
      message = "";
    } catch (e: any) {
      message = e.message;
    }

    expect(message).toEqual(
      "You have to use useSelectThemeContext inside <SelectThemeContextProvider />",
    );
  });

Puedo recibir el mensaje pero también obtengo un error en la consola.

en VirtualConsole. (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45) en reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
en innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9) en invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
en HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9) en HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17) en HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)

console.error
  The above error occurred in the <TestComponent> component:
  
      at TestComponent (C:\Users\rafael.almeida\Documents\Projects\Estudo\acamp\base-reactv18-eslint-prettier-config\node_modules\@testing-library\react\dist\pure.js:281:5)
  
  Consider adding an error boundary to your tree to customize error handling behavior.
  Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

  at logCapturedError (node_modules/react-dom/cjs/react-dom.development.js:18687:23)
  at update.callback (node_modules/react-dom/cjs/react-dom.development.js:18720:5)
  at callCallback (node_modules/react-dom/cjs/react-dom.development.js:13923:12)
  at commitUpdateQueue (node_modules/react-dom/cjs/react-dom.development.js:13944:9)
  at commitLayoutEffectOnFiber (node_modules/react-dom/cjs/react-dom.development.js:23391:13)
  at commitLayoutMountEffects_complete (node_modules/react-dom/cjs/react-dom.development.js:24688:9)  
  at commitLayoutEffects_begin (node_modules/react-dom/cjs/react-dom.development.js:24674:7)
  at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:24612:3)

Ejecutar prueba CodeSandBox Probar CodeSandBox

Respuesta #1

Puedes/deberías usar @testing-library/react-hooks. Proporciona un método renderHook diferente que puede aceptar un parámetro wrapper y puede devolver errores.

Tu prueba se vería entonces algo así. No creo que tenga que ser async. Si tus requisitos específicos requieren una función async, entonces consulta la documentación de jest. Recuerdo que esto era un poco diferente de lo que esperaba para probar async.

import { renderHook } from "@testing-library/react-hooks";

it("[ACAMP-03] - should return error message when trying to use custom hook without provider", () => {
    const { result } = renderHook(() => useSelectedThemeContext());

    expect(result.error?.message).toEqual(
      "You have to use useSelectThemeContext inside <SelectThemeContextProvider />",
    );
  });

Si quieres probar la funcionalidad con el proveedor, puedes hacer algo como esto.

it("does what the hook is supposed to do", () => {
    const wrapper = ({ children }) => (
        <SelectedThemeContextProvider>
            {children}
        </SelectedThemeContextProvider>
    );

    const { result } = renderHook(() => useSelectedThemeContext(), {wrapper});

    expect(result.error).toBeUndefined();

    // using color as an example
    expect(result.color).toEqual("#ffffff");
})

Respuesta #2

Estoy usando un método para suprimir el console.error específicamente para pruebas, si el algoritmo está diseñado de una manera que no necesite usar esto, por favor...

const spyConsole = jest
  .spyOn(console, "error")
  .mockImplementation(() => {});