En nuestra aplicación de una sola página, el cambio entre páginas se realiza con window.location.hash . Y encontré un problema en las pruebas unitarias de React Testing Library: al hacer clic en la etiqueta <a/> borra window.location.hash . Por ejemplo, cuando estoy en la página "Información", mi hash es igual a '#info' . Y cuando hago clic en el elemento <a /> , el hash no cambia. Pero en las pruebas, el hash se convierte en una cadena vacía '' después de hacer lo mismo.
Aquí hay una prueba corta que no funciona :
import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; test('Test', async () => { window.location.hash = 'hash'; render(<a className="some-class">Some text</a>); await userEvent.click(screen.getByText('Some text')); await new Promise(resolve => setTimeout(resolve, 30)); expect(window.location.hash).toEqual('#hash'); });Y aquí está el mensaje de error :
Error: expect(received).toEqual(expected) // deep equality Expected: "#hash" Received: "" El problema es con la etiqueta de anclaje. La prueba con la etiqueta span funciona bien:
import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; test('Test', async () => { window.location.hash = 'hash'; render(<span className="some-class">Some text</span>); // <span /> instead of <a /> await userEvent.click(screen.getByText('Some text')); await new Promise(resolve => setTimeout(resolve, 30)); expect(window.location.hash).toEqual('#hash'); }); Pregunta ¿Cómo puedo evitar este comportamiento? No puedo simplemente deshacerme a las etiquetas en el código, porque la mayoría de los componentes básicos están declarados en otra biblioteca npm.
EDITAR 1 Realmente no quiero verificar location.hash . Quiero verificar el contenido de la página, que depende del valor de location.hash . Y el verdadero problema es: cuando location.hash se convierte en una cadena vacía, parte del contenido desaparece.
Basado en este SO , este comportamiento es más como un problema de jsdom . Y para lograr el valor esperado, debe hacer algo como esto:
const oldLocation = window.location; describe("matching cities to foods", () => { afterEach(() => { // AFTER EACH TEST, set it to the original object. window.location = oldLocation; }); test("Test", async () => { // delete only for this test delete window.location; // Change only the hash option and keep the rest same as the original. window.location = { ...oldLocation, hash: "hash" }; render(<a className="some-class">Some text</a>); await userEvent.click(screen.getByText("Some text")); await new Promise((resolve) => setTimeout(resolve, 30)); expect(window.location.hash).toEqual("hash"); }); });