还有哪些其他方法可以测试功能组件内的功能?

问题描述 投票:0回答:1

我有一个呈现表单组件的标头组件:

import { useWeatherContext } from "../lib/Context/WeatherContext";
import HeaderForm from "./HeaderForm";

const Header = () => {
  const { setWeather } = useWeatherContext();

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const target = e.target as typeof e.target & {
      cityZip: { value: string };
    };
    setWeather({ location: target.cityZip.value });
    target.cityZip.value = "";
  };

  return (
    <header>
      <h2>Weathur</h2>
      <HeaderForm handleSubmit={handleSubmit} />
    </header>
  );
};

export default Header;
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons";

const HeaderForm = ({
  handleSubmit,
}: {
  handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
}) => {
  return (
    <form
      data-testid="city-form"
      autoComplete="off"
      id="search-form"
      onSubmit={(e) => {
        handleSubmit(e);
      }}
    >
      <input
        data-testid="city-input"
        type="text"
        name="cityZip"
        placeholder="City or Zip..."
        aria-label="City or Zip Code Input"
        required
        onInvalid={(e) => {
          const target = e.target as HTMLInputElement;
          target.setCustomValidity("Please enter a valid city or zip code.");
        }}
        onInput={(e) => {
          const target = e.target as HTMLInputElement;
          target.setCustomValidity("");
        }}
      />
      <button
        data-testid="city-form-button"
        type="submit"
        aria-label="Submit Button for Search"
      >
        <FontAwesomeIcon icon={faMagnifyingGlass} />
      </button>
    </form>
  );
};

export default HeaderForm;

以前,我在标头中有此表单,但后来将其提取,因为我无法弄清楚如何测试handleSubmit() 函数。因此,在提取表单并传递handleSubmit作为道具后,我的测试如下所示(并通过):

import { screen, fireEvent, waitFor, render } from "@testing-library/react";
import { WeatherContextProvider } from "../src/lib/Context/WeatherContext";
import { ErrorContextProvider } from "../src/lib/Context/ErrorContext";
import { LoadingContextProvider } from "../src/lib/Context/LoadingContext";
import HeaderForm from "../src/components/HeaderForm";

const handleSubmitMock = vi.fn();

const renderElements = () => {
  render(
    <WeatherContextProvider>
      <ErrorContextProvider>
        <LoadingContextProvider>
          <HeaderForm handleSubmit={handleSubmitMock} />
        </LoadingContextProvider>
      </ErrorContextProvider>
    </WeatherContextProvider>
  );
};

describe("Header", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("should trigger handleSubmit when form is submitted", async () => {
    renderElements();

    const input = screen.getByTestId("city-input");
    const button = screen.getByTestId("city-form-button");

    fireEvent.change(input, { target: { value: "11102" } });
    fireEvent.click(button);

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

  it("should not allow a blank input to be submitted", async () => {
    renderElements();

    const input = screen.getByTestId("city-input");
    const button = screen.getByTestId("city-form-button");

    fireEvent.change(input, { target: { value: "" } });
    fireEvent.click(button);

    await waitFor(() => {
      expect(handleSubmitMock).not.toHaveBeenCalledTimes(1);
    });
  });
});

我很困惑为什么我首先需要提取我的表格。有没有办法在 Header() 中访问handleSubmit?我为此使用 Vitest 和 React 测试库,以及 React、Vite 和 Typescript。

我感谢任何帮助,如果需要更多代码,这里是 github 存储库

reactjs typescript unit-testing jestjs vitest
1个回答
0
投票

有没有办法访问handleSubmit

不,这是一个内部函数,不向您公开。为了能够测试它,您需要能够将其作为道具传递。这是一个非常强大的概念,称为依赖注入(在函数式编程中)。每当您需要能够测试函数“内部”的东西时,请将其作为参数传递。

© www.soinside.com 2019 - 2024. All rights reserved.