-
Notifications
You must be signed in to change notification settings - Fork 0
Description
RTL 包中如何进行元素定位?
getxxx、queryxxx、findxxxx 这三种查找方式,这三者都有不同的区别。
getxxx返回已查找到的元素未找到就抛错queryxxx查找元素,没查到的元素返回 Null 不会抛错,一般用于判断元素不存在findxxx异步的查找元素
通过在其后缀 All 之后就会查找多个元素,如果没有使用在后缀All的这种形式,查找元素存在多个的条件下就会抛出错误
1. ByRole
ByRole根据 role 属性来查找元素,该属性一般都是默认值比如 <input type='checkout' role="checkout"> or <button role='button'> 关于更多的默认值请查看w3
使用的方法有: getByRole, queryByRole, getAllByRole, queryAllByRole, findByRole, findAllByRole
If you only query for a single element with getByText('The name') it's oftentimes better to use getByRole(expectedRole, { name: 'The name' }).
这里去介绍了 getByRole 的强大特性,通常可以使用 getByRole 来代替 getByText 使用。
官方文档对于 ByRole 介绍了大量的细节,但是目前阶段在 jsx 结构中添加 aria-*这种的属性来测试组件大致上不太可能 也用不到。所以这里能够明确如何使用 getByRole 的使用方式就行。关于 ARIA 规则详细介绍参考这篇文章
getByRole('switch') would always match
because it's the first role, while getByRole('checkbox') would not. However, getByRole('checkbox', { queryFallbacks: true }) would enable all fallback roles and therefore match the same element.
这里介绍了一个例子 如果使用 getByRole('switch') 来去查找元素能够找到 <div role="switch checkbox" /> 但是如果通过 getByRole('checkbox') 的方式来查找元素 检索不到
原因:By default, it's assumed that the first role of each element is supported, so only the first role can be queried. If you need to query an element by any of its fallback roles instead, you can use queryFallbacks: true.
默认了查找方式是 role 属性中第一个值去查找,如果也想要匹配后值就需要 queryFallbacks: true
简单看一下定义了那些参数
getByRole(
// 查找元素的节点
container: HTMLElement,
// 匹配 role 熟悉的值
role: TextMatch,
// 一些其他选项
options?: {
exact?: boolean = true,
hidden?: boolean = false,
// 较为常用的,提供查找文字
name?: TextMatch,
description?: TextMatch,
normalizer?: NormalizerFn,
selected?: boolean,
checked?: boolean,
pressed?: boolean,
current?: boolean | string,
expanded?: boolean,
queryFallbacks?: boolean,
level?: number,
}): HTMLElement*ByRole的参数属性
- aria-hidden: getAllByRole('button', { hidden: true })
- aria-checked: getByRole('checkbox', { checked: true })
- aria-current=“true”: getByRole('link', { current: true })
- aria-pressed: getByRole('button', { pressed: true })
- aria-expanded: getByRole('link', { expanded: false })
- h1-h6: getByRole('heading', { level: 2 })
- aria-describedby: getByRole('alertdialog', {description: 'Your session is about to expire'})
2. ByLabelText
这里使用的方法有 getByLabelText, queryByLabelText, getAllByLabelText, queryAllByLabelText, findByLabelText, findAllByLabelText
这里看一下参数
getByLabelText(
// 查找元素的节点
container: HTMLElement,
// 匹配的文字
text: TextMatch,
options?: {
// 选择器
selector?: string = '*',
// 严格模式默认 true
exact?: boolean = true,
normalizer?: NormalizerFn,
}): HTMLElementThis will search for the label that matches the given TextMatch, then find the element associated with that label.
这里说了它将会查找与 TextMatch 匹配的文字,然后找到与该标签关联的元素,
// 1. 常见的
<label for="username-input">Username</label>
// 这里与之关联的元素就是 input
<input id="username-input" />
// 使用 aria-labelledby 类型的
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />
// 嵌套 label
<label>Username <input /></label>
// 包裹在子元素的中的文本
<label>
<span>Username</span>
<input />
</label>
// aria-label
<input aria-label="Username" />使用方式
import {render, screen} from '@testing-library/react
render(<Login />)
const inputNode = screen.getByLabelText('Username')如果在查找过程中有一样的属性可以提供 selector options 选择器就行
// 第一种
<label id="username">Username</label>
<input aria-labelledby="username" />
<span aria-labelledby="username">Please enter your username</span>
// 第二种
<label>
Username
<input />
</label>
<label>
Username
<textarea></textarea>
</label>选择 input node 可以这样使用 getByLabelText('Username', {selector: 'input'})
需要注意:getByLabelText will not work in the case where a for attribute on a element matches an id attribute on a non-form element.
如果 label 中的 for 属性和 input 元素的 id 属性不相等或者 for 属性与非表单元素的id 匹配那 getByLabelText 就查找不到元素
类似这种就能查到
<label id="username">Username</label>
<span aria-labelledby="username">Please enter your username</span>这种就会匹配失败, 抛出错误
<section id="photos-section">
<label for="photos-section">Photos</label>
</section>3. ByPlaceholderText
PlaceholderText: 占位符
方法有:getByPlaceholderText, queryByPlaceholderText, getAllByPlaceholderText, queryAllByPlaceholderText, findByPlaceholderText, findAllByPlaceholderText
使用该类型的方法将会检索所有元素上的 placeholderText 属性,并返回匹配的 文本 元素
简单的看一下参数
getByPlaceholderText(
// 还是要搜索的节点
container: HTMLElement,
// 检索的文本
text: TextMatch,
options?: {
exact?: boolean = true,
normalizer?: NormalizerFn,
}): HTMLElement使用方式:
<input placeholder="Username" />
// 查找
import {render, screen} from '@testing-library/react'
render(<MyComponent />)
const inputNode = screen.getByPlaceholderText('Username')ByText
终于到最关键的规则了...
来看一下有那些方法:getByText, queryByText, getAllByText, queryAllByText, findByText, findAllByText
参数:
getByText(
container: HTMLElement,
// 匹配的文字
text: TextMatch,
options?: {
// 选择器
selector?: string = '*',
exact?: boolean = true,
// 排除搜索的节点 默认就 script 和 style 节点
ignore?: string|boolean = 'script, style',
normalizer?: NormalizerFn,
}): HTMLElementThis will search for all elements that have a text node with textContent matching the given TextMatch.
这里说的很详细,查找所有元素的文本节点,并返回匹配文本: TextMatch的元素
ByDisplayValue
使用的方法: getByDisplayValue, queryByDisplayValue, getAllByDisplayValue, queryAllByDisplayValue, findByDisplayValue, findAllByDisplayValue
基本参数:
getByDisplayValue(
container: HTMLElement,
// 匹配 value
value: TextMatch,
options?: {
exact?: boolean = true,
normalizer?: NormalizerFn,
}): HTMLElement功能: Returns the input, textarea, or select element that has the matching display value.
用于返回input,textarea,select元素现实的值
具体使用
<textarea id="messageTextArea" />
// 设置值
document.getElementById('messageTextArea').value = 'Hello World'
// 测试
import {screen} from '@testing-library/dom'
const messageTextArea = screen.getByDisplayValue('Hello World')对于 <select> 元素它会选择与给定值相同的 <option> 节点
<select>
<option value="">State</option>
<option value="AL">Alabama</option>
<option selected value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>这里有疑问,在 react 中直接使用 const { getByDisplayValue } = render(<MyComponent />) 的时候能够获取到 值
const { getByDisplayValue } = render(<MyComponent />)
const value = getByDisplayValue('Alaska')
console.log('value: ', value.textContent) // Alaska但是如果使用 这样的方式 就获取不到对应的值
const value = screen.getByDisplayValue('Alaska')
console.log('value: ', value.textContent) // select 中所有的文本ByAltText
查找具有 Alt 属性的元素通常是 img 返回和 文本 相匹配的元素
ByTitle
Returns the element that has the matching title attribute.
ByTestId
返回具有 data-testid 属性的元素
特别的 API
within: 一般使用 const {getByTestId} = render(<Component/>) 来获取组件可以直接通过 dom 语法获取 dom 元素然后使用 within 包裹起来,就能使用查询函数比如getByText
参考文章
不看参考文章巨亏!!!【网上教程非常多但是良莠不齐,找这方面的教程且挑选出来就要耗费大量的时间和精力】