RTL Queries getBy**
系列 分別會有兩天時間來練習,今天練習:
getByRole
getByLabelText
getByPlaceholderText
getByText
getByRole
<button></button>
相當於 role="button"
<form></form>
相當於 role="form"
<a href=""></a>
相當於 role="link"
<input type="text" />
相當於 role="textbox"
<div role="button"></div>
。我們透過這些特定屬性,作為測試的指定項目。
export default function Applications(){
return(
<form action="">
// Email 輸入框
<div>
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" />
</div>
// 下拉選單
<div>
<label htmlFor="level"></label>
<select name="" id="level">
<option value="High">High</option>
<option value="Medium">Medium</option>
<option value="Low">Low</option>
</select>
</div>
// 送出按鈕
<button type="submit">Submit</button>
</form>
)
}
我要測試上面三個 HTML Element 有沒有顯示在畫面上:
import { render, screen } from "@testing-library/react";
import Applications from "./application";
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const emailEl = screen.getByRole("textbox");
expect(emailEl).toBeInTheDocument();
const selectionEl = screen.getByRole("combobox");
expect(selectionEl).toBeInTheDocument();
const buttonEl = screen.getByRole("button");
expect(buttonEl).toBeInTheDocument();
})
});
測試結果: PASS src/components/application/application.test.tsx
補充說明:select 元素 role="combobox" 代表一組合框,具有可收縮的選項列表的元件,使用者可以選擇其中一個選項。
getByRole
,出現多個 Element 符合的情況我們可能會遇到一個情況是:一個測試 Component 包含多個符合條件的 role 的場景。
export default function Applications(){
return(
<form action="">
<div>
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" />
</div>
<div>
<label htmlFor="name">Name</label>
<input type="text" name="name" id="name" />
</div>
...
</form>
)
}
當我們使用 getByRole("textbox")
驗證 input 測試時,
import { render, screen } from "@testing-library/react";
import Applications from "./application";
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const emailEl = screen.getByRole("textbox");
expect(emailEl).toBeInTheDocument();
const nameEl = screen.getByRole("textbox");
expect(nameEl).toBeInTheDocument();
...
})
});
測試結果為:
FAIL src/components/application/application.test.tsx
● Application › Render correctly
TestingLibraryElementError: Found multiple elements with the role "textbox"Application Component 內有多個符合
role="textbox"
的選項,無法確認我想測試的是哪一個 Element。
這個時候,我們可以使用 getByRole()
的第二個參數選項,帶入明確的指定元素。
import { render, screen } from "@testing-library/react";
import Applications from "./application";
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const emailEl = screen.getByRole("textbox", {
name: "Email" // 指定該 input 的 label value
});
expect(emailEl).toBeInTheDocument();
const nameEl = screen.getByRole("textbox", {
name: "Name" // 指定該 input 的 label value
});
expect(nameEl).toBeInTheDocument();
...
})
});
測試結果:
PASS src/components/application/application.test.tsx
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
export default function Applications(){
return(
<>
<h1>Application</h1>
<h2>User Info</h2>
...
</>
)
}
測試寫法:我們可以用 text value 去指定到我們想測試的那個 Element
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const h1El = screen.getByRole("heading", {
name: "Application"
});
expect(h1El).toBeInTheDocument();
const h2El = screen.getByRole("heading", {
name: "User Info"
});
expect(h2El).toBeInTheDocument();
...
})
});
或者,指定 heading level
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const h1El = screen.getByRole("heading", {
level: 1
});
expect(h1El).toBeInTheDocument();
const h2El = screen.getByRole("heading", {
level: 2
});
expect(h2El).toBeInTheDocument();
...
})
});
測試結果:
PASS src/components/application/application.test.tsx
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
getByLabelText
label
的 text value。export default function Applications(){
return(
<form action="">
// Label 寫法一
<div>
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" />
</div>
// Label 寫法二
<div>
<label htmlFor="name">
Name<input type="text" name="name" id="name" />
</label>
</div>
...
</form>
)
}
撰寫測試:
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const emailEl = screen.getByLabelText("Email");
expect(emailEl).toBeInTheDocument();
const nameEl = screen.getByLabelText("Name");
expect(nameEl).toBeInTheDocument();
})
});
測試結果:
PASS src/components/application/application.test.tsx
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
getByLabelText
,出現多個 Element 符合的情況export default function Applications(){
return(
<form action="">
<div>
<label htmlFor="name">
Name<input type="text" name="name" id="name" />
</label>
</div>
<div>
<label htmlFor="level">Name</label>
<select name="" id="level">
<option value="High">High</option>
<option value="Medium">Medium</option>
<option value="Low">Low</option>
</select>
</div>
...
</form>
)
}
撰寫測試:
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const nameEl = screen.getByLabelText("Name");
expect(nameEl).toBeInTheDocument();
})
});
測試結果:
FAIL src/components/application/application.test.tsx
● Application › Render correctly
TestingLibraryElementError: Found multiple elements with the text of: Name
這時候,我們依樣可以使用 getByLabelText
第二個參數來明確指定要進行測試的 Element
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const nameEl = screen.getByLabelText("Name", {
selector: "input"
});
expect(nameEl).toBeInTheDocument();
const levelNameEl = screen.getByLabelText("Name", {
selector: "select"
});
expect(levelNameEl).toBeInTheDocument();
})
});
測試結果:
PASS src/components/application/application.test.tsx
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
getByPlaceholderText
placeholder
屬性 (2) 符合 指定的 placeholder text valueexport default function Applications(){
return(
<form action="">
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
id="email"
placeholder="Enter Your Email"
/>
</form>
)
}
撰寫測試:
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const emailEl = screen.getByPlaceholderText("Enter Your Email");
expect(emailEl).toBeInTheDocument();
})
});
測試結果:
PASS src/components/application/application.test.tsx
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
getByText
getByText
取的 DOM text value。export default function Applications(){
return(
<>
<h1>Application</h1>
<h2>User Info</h2>
<p>Note: Required Fields</p>
</>
)
}
撰寫測試:
describe("Application", () => {
test("Render correctly", () => {
render(<Applications />);
const paragraphEl = screen.getByText("Note: Required Fields");
expect(paragraphEl).toBeInTheDocument();
})
});
測試結果:
PASS src/components/application/application.test.tsx
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total