简体   繁体   中英

React testing library in Typescript

I'm following a tutorial on React.js testing Library and trying to follow along in Typescript. Although after following along with the first test I'm already encountering a few issues and am wondering what should be different in a test written in Typescript.

App.ts

function App() {
    return (
        <div className="container my-5">
            <form>
                <div className="mb-3">
                    <label htmlFor="email" className="form-label">
                        Email Address
                    </label>
                    <input
                        type="email"
                        id="email"
                        name="email"
                        className="form-control"
                    />
                </div>
                <div className="mb-3">
                    <label htmlFor="password" className="form-label">
                        Password
                    </label>
                    <input
                        type="password"
                        id="password"
                        name="password"
                        className="form-control"
                    />
                </div>
            </form>
        </div>
    );
}

export default App;

App.test.tsx

import { render, screen } from "@testing-library/react";
import App from "./App";

test("inputs should be initially empty", () => {
    render(<App />);
    const emailInputElement = screen.getByRole("textbox");
    const passwordInputElement = screen.getByLabelText(/password/);
    expect(emailInputElement.value).toBe("");
    expect(passwordInputElement.value).toBe("");
});

I'm receiving an error "Property 'value' does not exist on type 'HTMLElement" on:

expect(emailInputElement.value).toBe("");
expect(passwordInputElement.value).toBe("");

Do these need to be explained differently on Typescript?

You are getting this error because screen.getByRole and screen.getByLabelText returns HTMLElement object and it doesn´t have value prop.

There are 2 ways to get it working:

  1. explicitly define the return type as HTMLInputElement (it has value prop).
import { render, screen } from "@testing-library/react";
import App from "./App";

test("inputs should be initially empty", () => {
  render(<App />);

   const emailInputElement = screen.getByRole<HTMLInputElement>("textbox");
   const passwordInputElement = screen.getByLabelText<HTMLInputElement>(/password/i);

   expect(emailInputElement.value).toBe("");
   expect(passwordInputElement.value).toBe("");
});
  1. Use @testing-library/jest-dom library -> it provides a set of custom jest matchers that you can use to extend jest. You can check more here .
import "@testing-library/jest-dom/extend-expect";
import { render, screen } from "@testing-library/react";
import App from "./App";

test("inputs should be initially empty", () => {
  render(<App />);

   const emailInputElement = screen.getByRole("textbox");
   const passwordInputElement = screen.getByLabelText(/password/i);  

   expect(emailInputElement).toHaveValue("");
   expect(passwordInputElement).toHaveValue("");
});

You can define type for both text box as HTMLInputElement also where you are targeting password in your actual code it's case sensitive so always use regular expression to avoid tests failing ie (/password/i)

  render(<App/>);
  const emailInputElement: HTMLInputElement = screen.getByRole("textbox");
  const passwordInputElement: HTMLInputElement =
    screen.getByLabelText(/password/i);
  expect(emailInputElement.value).toBe("");
  expect(passwordInputElement.value).toBe("");
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM