Maison >interface Web >js tutoriel >Tester window.open() en JavaScript avec Jest

Tester window.open() en JavaScript avec Jest

Patricia Arquette
Patricia Arquetteoriginal
2024-12-10 16:50:12484parcourir

Testing window.open() in JavaScript with Jest

J'ai récemment dû écrire un test pour un composant React qui ouvrait une nouvelle fenêtre de navigateur. Pour ouvrir la nouvelle fenêtre, j'ai utilisé window.open() dans mon code. Cela a rendu le composant facile à écrire, mais j'ai dû penser un peu différemment à la façon d'écrire le test pour cela.

Plus d'informations sur la méthode window.open() sont disponibles sur mdn web docs.

Pour définir un peu ou un arrière-plan, j'avais un composant React qui avait un formulaire simple avec quelques entrées. Lorsque l'utilisateur a terminé les saisies et soumis le formulaire, il a ouvert une nouvelle fenêtre vers une URL spécifiée avec les entrées comme paramètres d'URL.

Le composant à tester

Voici une version très simplifiée du composant à titre de démonstration. Je recommanderais d'utiliser quelque chose comme réagir-hook-form pour ajouter une validation à votre formulaire.

// MyForm.js
import React, { useState } from "react";

const MyForm = ({ baseURL }) => {
  const [name, setName] = useState("");
  const [subject, setSubject] = useState("");

  const onSubmit = () => {
    window.open(
      `${baseURL}?name=${encodeURIComponent(name)}&subject=${encodeURIComponent(
        subject
      )}`,
      "_blank"
    );
  };

  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="name">Name</label>
      <input name="name">



<p>Now we have our component, lets think about the test for it.</p>

<h2>
  
  
  What I’d normally test
</h2>

<p>Normally I would test what has been rendered in my component, using assertions such as expect the component to have text content or assert the url is what is expected (using window.location.href), but I quickly realised that approach won’t work in jest for this example.</p>

<p>Window.open opens a new browser window, so it doesn’t affect the component we are testing. We can’t see what is inside the new window or what its url is as it is outside of the scope of the component we are testing.</p>

<p>So how do we test something that is outside of what we can see? We don’t actually need to test that a new window is opened as that would be testing the window interface’s functionality and not our code. Instead, we just need to test that the window.open method is called.</p>

<h2>
  
  
  Mocking window.open()
</h2>

<p>Therefore we need to mock window.open() and test that it was called inside our code.<br>
</p>

<pre class="brush:php;toolbar:false">// Mock window.open
global.open = jest.fn();

Nous pouvons maintenant définir les valeurs dans les entrées, soumettre notre formulaire puis tester que window.open a été appelé. Nous pouvons utiliser fireEvent pour définir les valeurs des entrées et appuyer sur le bouton de soumission.

fireEvent.input(screen.getByLabelText("Name"), {
  target: {
    value: "Test Name",
  },
});
fireEvent.input(screen.getByLabelText("Subject"), {
  target: {
    value: "An example subject",
  },
});
fireEvent.submit(
  screen.getByRole("button", { name: "Submit (opens in new window)" })
);

Cela vaut la peine de lire la documentation pour connaître les considérations relatives à fireEvent. Vous souhaiterez peut-être utiliser un événement utilisateur à la place en fonction de votre cas d'utilisation.

Nous voulons attendre que la méthode s'exécute. Nous pouvons le faire en utilisant waitFor().

await waitFor(() => {
  expect(global.open).toHaveBeenCalled();
});

Pour nous assurer que nous n'ouvrons pas beaucoup de nouvelles fenêtres, nous pouvons vérifier que nous n'appelons window.open qu'une seule fois.

await waitFor(() => {
  expect(global.open).toHaveBeenCalledTimes(1);
});

Nous pouvons également vérifier avec quels arguments la méthode est appelée, en passant l'URL que nous attendons comme premier argument et la cible comme second.

await waitFor(() => {
  expect(global.open).toHaveBeenCalledWith(
    "http://example.com?name=Test%20Name&subject=An%20example%20subject",
    "_blank"
  );
});

Le dossier de test complet

Voici le fichier de test complet pour votre référence.

// MyForm.test.js
import React from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import MyForm from "./MyForm";

describe("MyForm test", () => {
  beforeEach(() => {
    // Mock window.open
    global.open = jest.fn();
  });

  it("opens a new window with the correct url", async () => {
    render(<MyForm baseURL="http://example.com" />);

    fireEvent.input(screen.getByLabelText("Name"), {
      target: {
        value: "Test Name",
      },
    });
    fireEvent.input(screen.getByLabelText("Subject"), {
      target: {
        value: "An example subject",
      },
    });
    fireEvent.submit(
      screen.getByRole("button", { name: "Submit (opens in new window)" })
    );

    await waitFor(() => {
      expect(global.open).toHaveBeenCalled();
      expect(global.open).toHaveBeenCalledTimes(1);
      expect(global.open).toHaveBeenCalledWith(
        "http://example.com?name=Test%20Name&subject=An%20example%20subject",
        "_blank"
      );
    });
  });
});

Photo par energepic.com sur StockSnap

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn