Home > Blockchain >  React testing library in Typescript
React testing library in Typescript

Time:06-20

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?

CodePudding user response:

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("");
});

CodePudding user response:

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("");
});
  • Related