# 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();
});
```
且除了輸入文字內容外,也可以輸入一些特殊符號,如下圖(圖片取自官方文件):

使用方式只要像這樣直接加進去:
```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/