Ariakit 测试
重要内容: 这个软件包是实验性的,并不遵循语义化的版本,意思是断裂变化可能发生在补丁和小版本中.
Ariakit的单位和端到端测试中模拟用户交互功能.
目录
安装
npm i @ariakit/test
使用量
从软件包根导入助手以模拟用户互动 :
import { click, press, type } from "@ariakit/test";
这个 @ariakit/test/react 切入点使反应组件用于测试 @ariakit/test/playwright 入口为 Playwright 测试提供查询帮助.
测试环境
帮手们希望有一个DOM执行 PointerEvent,意思是快乐度,jsdom v27 或后期,或真正的浏览器.
他们仍然运行在jsdom26 jest-environment-jsdom 三十取决. 每一次帮助者射击的事件 都带着同样的鼠标 修饰器和指向器成员 随处随地 clientX, (中文(简体) ), button, (中文(简体) ), pointerId,修改器则在浏览器中表示. click, (中文(简体) ), auxclick,以及 contextmenu 是从 MouseEvent 而不是说 PointerEvent,也使成员保持浏览器计算.
这个 pointer* 事件是环境无法从自己的界面建立起来的,所以它们来自 Event 却不是 instanceof MouseEvent。调度层仍然产生 pageX, (中文(简体) ), pageY,以及 which,但不要依赖布局 offsetX 财务报告和审定财务报表 offsetY 未定义 。 这个 PointerEvent 完全没有全球,所以 new PointerEvent() 财务报告和审定财务报表 event instanceof PointerEvent 丢出一个 ReferenceError。 。 。 .
API 参考
blurclickdispatchfocushovermouseDownmouseUppressqueryqrightClickselectsleeptaptypewaitFor
blur
function blur(element?: DirtiableElement | null): Promise<void>;
从元素中去除焦点,模拟一个真正的用户移动焦点远离它. 当没有元素被传递时,当前聚焦的元素(document.activeElement)为被使用. 如果打入自元素被聚焦后改变其值, a change 事件会在模糊之前发出.
示例
await type("hello", q.textbox());
// Dispatches the pending `change` event, then blurs the textbox.
await blur();
click
function click(
element: Element | null,
options?: PointerEventInit,
tap = false,
): Promise<void>;
点击一个元素,模拟一个真正的鼠标点击所产生的事件的顺序——在目标上徘徊,然后 pointerdown, (中文(简体) ), mousedown, (中文(简体) ), focus, (中文(简体) ), pointerup, (中文(简体) ), mouseup,以及 click。 。 。 .
隐藏和被禁用元素的处理方式与浏览器一样,并点击标签, option 元素,和形式控件的行为类似本地交互. 过 options 以设置修改键等事件属性(例如). { shiftKey: true }) (中文(简体) ).
过 button 键。 激活行为持续 click所以非主按钮起火 auxclick 而不是激活标签或 option 元素,次要按钮也起火 contextmenu 当它被压住的时候 每个步骤都会产生 buttons 从按钮,所以明确 buttons 此处被忽略; mouseDown 财务报告和审定财务报表 mouseUp 接受一个描述 和弦的手势.
示例
await click(q.button("Submit"));
// With a modifier key held down:
await click(q.option("Item"), { shiftKey: true });
// With the middle mouse button, firing `auxclick`:
await click(q.link("Ariakit"), { button: 1 });
dispatch
type Target = Document | Window | Node | Element | null;
type EventFunction = (element: Target, options?: object) => Promise<boolean>;
type DispatchEventType = Exclude<EventType, "doubleClick"> | "auxClick";
type EventsObject = {
[K in DispatchEventType]: EventFunction;
};
const dispatch: typeof baseDispatch & EventsObject;
在元素上创建并点出 DOM 事件, 然后等待产生的微任务冲出 。 打电话 dispatch.<eventName>(element, options) 用于构建和点燃特定事件(例如:. dispatch.keyDown, (中文(简体) ), dispatch.click, (中文(简体) ), dispatch.input),或打电话 dispatch(element, event) 直接带 Event 举个例子.
不同于高级助手,如 click 财务报告和审定财务报表 type,这个点出单个事件而不模拟周围的交互序列. 向元素发射指向和鼠标事件 pointer-events: none 被重新发送到已启用指针事件的最近的祖先上, 匹配浏览器如何引导这些事件 .
由名称构建的指针事件报告一个设备的接触大小和转录器角度浏览器报告,所以 width 财务报告和审定财务报表 height 为: 1 财务报告和审定财务报表 altitudeAngle 是一个正确的角度。 只提供倾斜或球面角度的对从另一对得到. 成员描述一种姿态,例如: pressure 财务报告和审定财务报表 isPrimary中,保留其默认值;上级帮助者填写。 你构造自己的一个事件 无论建筑师给它什么.
按名称创建的鼠标和指针事件 pageX 财务报告和审定财务报表 pageY 从客户端坐标和目标窗口滚动中取出 which 从 button。基于布局的 offsetX 财务报告和审定财务报表 offsetY 保持环境价值.
click, (中文(简体) ), auxclick,以及 contextmenu 建为 PointerEvent,浏览器发送它们的方式,所以它们接受和报告指针属性,例如 pointerType。无环境 PointerEvent 建为 MouseEvent 相反,他们报告 相同的属性在那里.
回归:决心 false 当事件默认动作被阻止时 event.preventDefault(),以及 true 否则.
示例
await dispatch.keyDown(q.textbox(), { key: "Enter" });
await dispatch.click(q.button());
await dispatch.auxClick(q.link("Ariakit"), { button: 1 });
// Fire a custom event instance directly:
await dispatch(q.textbox(), new Event("selectstart", { bubbles: true }));
focus
function focus(element: Element | null): Promise<void>;
将焦点移动到元素上,模拟一个真正的用户聚焦它. 不聚焦的元素会被忽略,而聚焦已经聚焦的元素则是一个不聚焦. 如果打入自获得焦点以来更改了另一个元素的值,则待处理 change 在焦点移动前发送事件.
示例
await focus(q.textbox());
expect(q.textbox()).toHaveFocus();
hover
function hover(
element: Element | null,
options?: PointerEventInit,
): Promise<void>;
将指针移到元素上方,模拟在元素上徘徊的真正用户。 发射相关 pointer编号 :mouse 输入、 过并移动事件, 并发送先前悬浮元素上的相匹配的休假事件.
隐藏元素和元素 pointer-events: none 以浏览器的方式处理。 过 options 以设置修改键等事件属性。 指针事件报告 pressure: 0,或 0.5 当你通过 buttons 以描述按住按钮的动作, 如拖动时.
示例
await hover(q.button("More options"));
expect(q.menu()).toBeVisible();
mouseDown
function mouseDown(
element: Element | null,
options?: PointerEventInit,
): Promise<void>;
在元素上按下指针按钮, 开火 pointerdown 财务报告和审定财务报表 mousedown 并按浏览器的方式移动焦点。 已禁用元素仍然收到指针事件,但没有 mousedown,当目标本身不具有可聚焦性时,焦点会回到最接近可聚焦的祖先.
这是满分的一步 click;直接用于测试按住行为. 过 options 以设置修改键等事件属性,或 button 键。 事件报告按下按钮 buttons,就像浏览器一样,除非你通过 buttons 来形容一个和弦的姿态 当该值显示另一个按钮已被扣住时, 媒体会起火 pointermove 改为 pointerdown,指针事件引导带和弦的相容性 mousedown 仍然开火。 指针事件报告 pressure: 0.5,值指针事件定义,而没有压力传感器的设备则按下按钮.
示例
await mouseDown(q.button("Resize"));
// ...assert the press state, then release:
await mouseUp(q.button("Resize"));
mouseUp
function mouseUp(
element: Element | null,
options?: PointerEventInit,
): Promise<void>;
释放元素上的指针按钮,开火 pointerup 财务报告和审定财务报表 mouseup。残废元素仍然收到指针事件,但没有 mouseup。 。 。 .
这是对应的 mouseDown 和满分的一步 click。通过 options 以设置修改键等事件属性,或 button 以释放另一个鼠标按钮。 事件报告,没有按钮仍然被扣在 buttons,就像浏览器一样,除非你通过 buttons 来描述一个和弦手势保持的按钮 当该值显示另一个按钮仍被扣住时,释放会起火 pointermove 改为 pointerup,指针事件引导和弦释放的方式,以及兼容性 mouseup 仍然开火。 指针事件报告 pressure: 0,或 0.5 和弦的手势保持了扣子.
示例
await mouseDown(q.button("Resize"));
await mouseUp(q.button("Resize"));
press
function press(
key: string,
element?: Element | null,
options: KeyboardEventInit = {},
): Promise<void>;
按键在一个元素上,模拟真正的用户键盘交互. 火灾 keydown 财务报告和审定财务报表 keyup 并应用浏览器对该密钥的默认行为——移动焦点 Tab,激活按钮并提交表格 Enter,单击按钮、复选框和收音机 Space带着箭移动护身符 Home编号 :End 键,并将可打印字符输入文本字段.
当未通过元素时,使用当前聚焦元素. 快捷键, 如 press.Enter() 财务报告和审定财务报表 press.Tab() 提供通用密钥,以及 press.ShiftTab() 向后移动焦点.
使用 press.down 财务报告和审定财务报表 press.up 只能按键或按键 半个按键。 每个默认到当前聚焦元素,因此焦点移出后释放出的一个密钥——例如,一个在按键下自禁的元素——会到达一个真正的浏览器会提供它的地方.
示例
await press.Tab();
await press.Enter();
// `press.Enter(element)` is shorthand for `press("Enter", element)`:
await press.Enter(q.button("Submit"));
// Split a press so the keyup lands on whatever is focused at release time:
await press.down.Space();
await press.up.Space();
query
type Query = ReturnType<typeof createRoleQuery>;
type TextQuery = ReturnType<typeof createTextQuery>;
type RoleQueries = Record<AriaRole, Query>;
interface QueryObject extends RoleQueries {
text: TextQuery;
labeled: TextQuery;
within: (element?: HTMLElement | null) => QueryObject;
}
const query: QueryObject;
通过ARIA角色查询DOM,可访问的名称,文本,或标签,建于测试库上. 调用一个角色方法, 如 query.button(name) 或者说 query.dialog() 以获取匹配元素,通过字符串或 RegExp 以匹配其无障碍名称。 找不到匹配元素时进行查询。 使用 query.text() 财务报告和审定财务报表 query.labeled() 按文本内容或相关标签查询,以及 query.within(element) 到子树的瞄准查询.
每一个查询都会曝光 .lazy (返回在调用时运行查询的可重用函数), .all (返回所有匹配,包括空阵列), .wait (一旦元素出现即予解决),和 .maybe (返回数) null 当取去)变相. 角色查询 .hidden 包括隐藏的元素.
示例
const dialog = query.dialog.maybe.lazy("Settings");
expect(dialog()).not.toBeInTheDocument();
await click(query.button("Open settings"));
expect(dialog()).toBeVisible();
// Wait for an element to appear, or scope a query to a subtree:
await query.alert.wait();
query.within(dialog()).button("Close");
q
type Query = ReturnType<typeof createRoleQuery>;
type TextQuery = ReturnType<typeof createTextQuery>;
type RoleQueries = Record<AriaRole, Query>;
interface QueryObject extends RoleQueries {
text: TextQuery;
labeled: TextQuery;
within: (element?: HTMLElement | null) => QueryObject;
}
const q: QueryObject;
简称: query通过ARIA角色,无障碍名称,文本,或标签查询DOM.
示例
const dialog = q.dialog.maybe.lazy("Settings");
expect(dialog()).not.toBeInTheDocument();
await click(q.button("Open settings"));
expect(dialog()).toBeVisible();
rightClick
function rightClick(
element: Element | null,
options?: PointerEventInit,
): Promise<void>;
右键点击一个元素,模拟一个真正的二次鼠标点击产生的事件的顺序——在目标上徘徊,然后右键 pointerdown, (中文(简体) ), mousedown, (中文(简体) ), focus, (中文(简体) ), contextmenu, (中文(简体) ), pointerup, (中文(简体) ), mouseup,以及 auxclick。 。 。 .
隐藏元素的处理方式与浏览器相同,没有合成 click 事件被解除。 过 options 以设置修改键等事件属性.
示例
await rightClick(q.text("Open menu"));
select
function select(
text: string,
element: Element | null = document.body,
options?: PointerEventInit,
): Promise<void>;
在元素中选择一个文本范围,模拟一个真正的用户拖过它。 在元素上按住,找到给定的 text 在其后人文字节点中,设置文档选择以覆盖,再放出.
当元素没有传递时, document.body 已使用。 过 options 以设置修改键等事件属性。 每个步骤都会产生 buttons 从它按的按钮, 所以一个明确的 buttons 被忽略.
示例
await select("hello world");
expect(document.getSelection()?.toString()).toBe("hello world");
sleep
function sleep(ms = defaultMs): Promise<void>;
等待DOM通过在两个动画帧之间产生出结果和短暂的超时,在模拟交互之间和解.
此套件中的其他帮助者在内部调用它, 但是您可以直接等待它让待更新, 过渡, 或效果冲洗在坚持前 。 默认延迟为小而取决于环境; 通过 ms 以覆盖它。 在真实的浏览器之外,它也会排出主机调度器,从而同时进行React工作,使得延迟在调用解决之前就解决了过去的问题.
示例
await click(q.button("Open"));
await sleep();
expect(q.dialog()).toBeVisible();
tap
function tap(
element: Element | null,
options?: PointerEventInit,
): Promise<void>;
点击元素而无需短暂延迟 click 等待在按下和放出之间, 复制快速水龙头的时间。 它发射相同的指针,鼠标,并单击事件为 click。通过 options 以设置修改键等事件属性.
示例
await tap(q.button("Submit"));
type
function type(
text: string,
element?: (DirtiableElement & HTMLElement) | null,
options: InputEventInit | KeyboardEventInit = {},
): Promise<void>;
将文本输入元素,模拟一个真正的用户按下每个键。 聚焦元素, 然后为每个字符起火 keydown,通过 input 事件(事前为 keypress 当插入可打印字符时,并点火 keyup。 。 。 .
其密钥的特殊字符映射 : "\b" 是后空间, "\x7f" 删除, "\n" 输入,并且 "\t" 为 Tab 。 当未通过元素时,使用当前聚焦元素. 过 options 以设置诸如修改键或组成状态等事件属性.
示例
await type("Hello", q.textbox());
// Delete the last character with a Backspace:
await type("\b");
waitFor
function waitFor<T>(
callback: () => T,
options?: DOMTestingLibrary.waitForOptions,
): Promise<T>;
重新运行回调, 直到它停止抛出或超时, 重新导出测试库 waitFor 使用此软件包的合成分批处理。 用它来等待一个断言在同步更新后通过. 过 options 来配置 timeout, (中文(简体) ), interval还有其他行为.
示例
await click(q.button("Close"));
await waitFor(() => expect(q.dialog.maybe()).not.toBeInTheDocument());
反应 API 引用
RenderOptions
interface RenderOptions extends Omit<
ReactTestingLibrary.RenderOptions,
"queries"
> {
strictMode?: boolean;
}
B. 关于 render 函数。 接受测试库的每个选项 render (除外) queries),加 (中文(简体) ) strictMode 在 React 中包裹已渲染的 UI StrictMode。 。 。 .
示例
const options: RenderOptions = { strictMode: true };
await render(<App />, options);
render
function render(
ui: ReactNode,
options?: RenderOptions,
): Promise<{
unmount: () => void;
rerender: (newUi: ReactNode) => Promise<void>;
}>;
将一个反应元素放入文档中进行测试,等待效果和下一个框架在解析前冲出.
建于测试库 render返回时 unmount 删除树和自动同步 rerender 用新的UI更新它. 过 strictMode: true 将元素包裹在 React 中 StrictMode,或任何其他测试库选项.
示例
const { rerender, unmount } = await render(<Button>Submit</Button>);
await click(q.button("Submit"));
await rerender(<Button>Sent</Button>);
unmount();
播放作家 API 引用
query
type RoleQuery = (
name?: string | RegExp,
options?: Parameters<Page["getByRole"]>[1],
) => Locator;
type TextQuery = (
name: Parameters<Page["getByText"]>[0],
options?: Parameters<Page["getByText"]>[1],
) => Locator;
type RoleQueries = Record<AriaRole, RoleQuery>;
type Queries = RoleQueries & { text: TextQuery };
function query(locator: Page | Locator | FrameLocator): Queries;
为 Playwright 创建基于角色和文本的查询助手 Page, (中文(简体) ), Locator,或 FrameLocator。称为角色方法,例如 query(page).button(name) 获取一个 Locator 从 getByRole,或 query(page).text(name) 以文本内容匹配.
名称完全对应默认 。 这反映了基于角色的 query 从软件包根进行端到端的 Playwright 测试.
示例
const { button, dialog } = query(page);
await button("Open").click();
await expect(dialog()).toBeVisible();
核心小组
捐款
遵守关于 贡献指南。 。 。 .