# User Event - 模擬使用者操作 - [為什麼要使用 user event 呢?](https://hackmd.io/s1KmikUFQviFYIoHdWexBA#%E7%82%BA%E4%BB%80%E9%BA%BC%E8%A6%81%E4%BD%BF%E7%94%A8-user-event-%E5%91%A2%EF%BC%9F) - [常用的操作行為](https://hackmd.io/s1KmikUFQviFYIoHdWexBA#%E5%B8%B8%E7%94%A8%E7%9A%84%E6%93%8D%E4%BD%9C%E8%A1%8C%E7%82%BA) --- #### 為什麼要使用 user event 呢? fireEvent 雖然一樣能調用事件,但 use event 可以更容易模擬使用者與瀏覽器的交互行為,官方文件上有舉例: ```! For example, when a user types into a text box, the element has to be focused, and then keyboard and input events are fired and the selection and value on the element are manipulated as they type. ``` 用戶輸入文字框時會有一連串的交互行為,包含一開始文字框的 focus 後續會觸發鍵盤的輸入事件再輸入內容時也同時在操作元素的值。 --- **User Event 可以更容易模擬使用者與瀏覽器的交互行為** <aside> 👉 使用 creat-react-app 建立專案的情況下,已經幫我們安裝好 user event 了,而安裝好的版本是 v13 ,目前 user event 已更新至 v14 版本,但文章還是會先按照 v13 版本進行解釋。 </aside> -- 如果專案還沒有安裝 user event ,可以透過底下指令安裝: ```node! npm install --save-dev @testing-library/user-event @testing-library/dom ``` 接下來來認識 user event 好用的幾種操作行為吧! --- #### 常用的操作行為 - User Event 的好用操作行為: - `Click`, `dblClick` ```jsx! // 記得引入 userEvent import userEvent from '@testing-library/user-event' ``` ```jsx! test('click', () => { render( <div> <label htmlFor="checkbox">Check</label> <input id="checkbox" type="checkbox" /> </div>, ) userEvent.click(screen.getByText('Check')) expect(screen.getByLabelText('Check')).toBeChecked() }) ``` 除此之外跟 click 相關的還有 dblClick 可以透過此方式判斷點擊 checkbox 兩次後是否不是打勾狀態: ```javascript! test('click', () => { render( <div> <label htmlFor="checkbox">Check</label> <input id="checkbox" type="checkbox" /> </div>, ) userEvent.dblClick(screen.getByText('Check')) expect(screen.getByLabelText('Check')).not.toBeChecked() }) ``` - `type` - `type(element, text, [options])` 該方法可以使用在 **input** 或 **textarea**,透過 React Testing Library 選取該 input 或 textarea 後可以輸入要顯示的數字,會**模擬使用者操作時點擊 input 的行為後再去做輸入**。 - 假設今天有一個元件 Input 如下: ```javascript import { useState } from "react"; const Input = () => { const [value, setValue] = useState(''); const changeValue = (value) => setValue(value); return ( <> <input value={value} onChange={(e) => changeValue(e.target.value)} /> <h1>{value}</h1> </> ); }; export default Input; ``` 可透過 type 去模擬使用者輸入進行測試: ```javascript import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import Input from "./TestInput"; test("type", () => { render(<Input />); userEvent.type(screen.getByRole("textbox"), 'Hello'); expect(screen.getByText('Hello')).toBeInTheDocument(); }); ``` 且除了輸入文字內容外,也可以輸入一些特殊符號,如下圖(圖片取自官方文件): ![特殊符號](https://i.imgur.com/zF75iIW.png) 使用方式只要像這樣直接加進去: ```javascript test("type", () => { render(<Input />); userEvent.type(screen.getByRole("textbox"), 'Helli{backspace}o'); expect(screen.getByText('Hello')).toBeInTheDocument(); }); ``` 其他還有很多方法像是: - `keyboard` :輸入的鍵盤事件,與 type 相似但**並沒有單擊行為** - `upload`:用於**檔案上傳**的測試 - `selectOptions` :選擇 **selet** 的選項 都可以參閱[官方文件](https://testing-library.com/docs/user-event/intro/)唷! --- 參考文章 https://testing-library.com/docs/ecosystem-user-event https://testing-library.com/docs/user-event/intro/