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:
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("");
});
@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("");
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With