본문 바로가기

리액트

[React] 테스팅의 친구, userEvent 이해하기 with 예제 코드

반응형

포스트 목적

userEvent 를 빠르게 이해하고, 테스트에 적용하기 위한 목적으로 userEvent 가 가지는 핵심 메서드에 대해 정리 하였습니다. 예시는 최대한 공식문서의 내용을 참고해서, 이러한 예시로 사용할 수 있겠구나 싶은 것으로 작성해 보았습니다.

 

userEvent.click(element, [options])

주어진 엘리먼트를 클릭합니다. 옵션 객체를 제공하여 Shift, Ctrl 및 Alt 키와 같은 수정자를 추가할 수 있습니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Clicking a button', () => {
  const user = userEvent.setup();
  render(<button>Click me</button>);
  
  // button 변수에 role="button" 이고, 텍스트로 click me 를 가진 요소를 저장합니다.
  const button = screen.getByRole('button', { name: /click me/i });
  
  // button 요소에 click 이벤트를 등록합니다.
  user.click(button);
  
  // 버튼 요소의 텍스트로 Clicked! 를 가질 것임을 예상합니다.
  // 당연히 이 텍스트는  click me 가 아니므로 테스트는 실패할 것입니다.
  expect(button).toHaveTextContent('Clicked!');
});

userEvent.type(element, text, [options]) 

주어진 텍스트를 주어진 엘리먼트에 타이핑합니다. 옵션 객체를 사용하여 다양한 수정자 (Shift, Ctrl, Alt 및 Meta)를 추가하거나 입력 지연을 추가할 수 있습니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Typing into an input', () => {
  const user = userEvent.setup();
  render(<input />);
  
  // role ="textbox" 인 요소를 찾아서 input 변수에 저장합니다.
  const input = screen.getByRole('textbox');
  
  // 0.1s 뒤에 input 요소의 value 속성값으로 Hello, World! 가 타이핑 됩니다.
  user.type(input, 'Hello, World!', { delay: 100 });
  
  // input 요소의 value 값으로 Hello, World! 를 가질 것임을 예상합니다.
  expect(input).toHaveValue('Hello, World!');
});

userEvent.clear(element)

주어진 엘리먼트의 값을 삭제합니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Clearing an input', () => {
  const user = userEvent.setup();
//input 요소의 value 으로 Hello,World! 가진 요소를 렌더링합니다.
  render(<input value="Hello, World!" />);

// role="textbox" 인 요소를 찾아서 input 변수에 저장합니다.
  const input = screen.getByRole('textbox');
  
// 해당 input 요소의 value 값을 제거합니다.
  user.clear(input);
  
 // input 요소의 value 값은 빈공백('')임을 예상합니다.
  expect(input).toHaveValue('');
});

userEvent.paste(element, text)

주어진 텍스트를 주어진 엘리먼트에 붙여넣습니다(복사 -> 붙여넣기).

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Pasting into an input', () => {
  const user = userEvent.setup();
  render(<input />);
  
  // role="textbox" 인 요소를 찾아서 input 변수에 저장합니다.
  const input = screen.getByRole('textbox');
  
  // input 요소의 value 에 Hello, World! 를 붙여넣습니다. 
  user.paste(input, 'Hello, World!');
  
  //input 요소는 value 값으로 Hello, World! 를 가질 것임을 예상합니다.
  expect(input).toHaveValue('Hello, World!');
});

userEvent.upload(element, fileOrFiles)

주어진 파일을 업로드할 수 있는 엘리먼트를 찾아서 해당 파일을 선택합니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Uploading a file', () => {
  const user = userEvent.setup();
//type 이 'file'인 input 태그를 렌더링 합니다.
  render(<input type="file" />);
  
//input 변수에 role ="button"을 가진 choose file 이라는 텍스트를 가진 input 요소를 할당합니다.
  const input = screen.getByRole('button', { name: /choose file/i });

//file 변수에 Hello, World 라는 데이터를 저장한 test.txt 파일을 할당합니다.
  const file = new File(['Hello, World!'], 'test.txt', { type: 'text/plain' });

//file과 버튼 input 요소를 매칭시킵니다.
  user.upload(input, file);

//file 타입은 업로드된 파일이 배열요소로 저장되므로 저장된 후 배열 길이는 1이 되며,
  expect(input.files).toHaveLength(1);

//files[0] 번째 자리에는 file 변수에 할당된 파일과 일치하는 파일이 존재할 것임을 예상합니다.
  expect(input.files[0]).toStrictEqual(file);
});

userEvent.hover(element)

주어진 엘리먼트 위에 마우스를 올립니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Hovering over an element', () => {
  const user = userEvent.setup();
  render(<div />);

  // role ="div" 인 요소를 찾아서 div 변수에 저장합니다.
  const div = screen.getByRole('div');
  
 // div 태그에 hover 합니다.
  user.hover(div);
  
 // hover 된 태그의 스타일 속성의 값으로 background-color: 'blue'를 가질 것임 예상합니다.
  expect(div).toHaveStyle('background-color: blue');
});

userEvent.unhover(element)

주어진 엘리먼트에서 마우스를 뗍니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Unhovering over an element', () => {
  const user = userEvent.setup();
// 배경색으로 blue 를 가진 div 태그를 렌더링합니다.
  render(<div style={{ backgroundColor: 'blue' }} />);
  
// role ="div" 인 요소를 찾아서 div 변수에 저장합니다.
  const div = screen.getByRole('div');
  
// div 태그에서 unhover 합니다.
  user.unhover(div);
  
// unhover 시 div 태그의 style 속성의 값인 background-color의 값으로 white를 가질 것임을 예상합니다.
  expect(div).toHaveStyle('background-color: white');
});

userEvent.selectOptions(selectElement, values)

주어진 <select> 엘리먼트에서 주어진 값(들)을 선택합니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Selecting options in a select element', () => {
  const user = userEvent.setup();
// 다중 선택이 가능한 option 태그를 가진 select 태그를 렌더링합니다.
  render(
    <select multiple>
      <option value="1">One</option>
      <option value="2">Two</option>
      <option value="3">Three</option>
    </select>
  );
  
// role="listbox" 인 요소를 찾아서 select 변수에 저장합니다.
  const select = screen.getByRole('listbox');
  
// role="option" 이고 텍스트로 two 를 가지는 요소를 찾아 optionTwo 변수에 저장합니다.
  const optionTwo = screen.getByRole('option', { name: /two/i });
  
// select 태그의 옵션 중 optionTwo 에 해당하는 요소를 선택합니다.
  user.selectOptions(select, optionTwo);
 
// 선택된 select 태그의 옵션의 value 은 '2' 를 가지고 있을 것임을 예상합니다.
  expect(select).toHaveValue(['2']);
});

userEvent.dblClick(element, [options])

주어진 엘리먼트를 더블 클릭합니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Double-clicking an element', () => {
  const user = userEvent.setup();
  render(<div />);
  
  //role ="div" 인 요소를 찾아서 div 변수에 저장합니다.
  const div = screen.getByRole('div');
  
  // div 태그에 더블클릭 이벤트를 적용합니다.
  user.dblClick(div);
  
  // 더블클릭된 div 태그의 style 속성의 값으로 background-color:blue를 가질 것임을 예상합니다.
  expect(div).toHaveStyle('background-color: blue');
});

userEvent.tab()

현재 활성화된 엘리먼트에서 탭 키를 눌러 다음 포커스 가능한 엘리먼트로 이동합니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Pressing the tab key', () => {
  const user = userEvent.setup();
// input 태그와 Click me 텍스트를 가진 button 태그를 렌더링합니다.
  render(
    <>
      <input />
      <button>Click me</button>
    </>
  );
  
// role ="textbox"를 가진 요소를 input 변수에 저장합니다.
// role ="button" 이며, 텍스트로 click me 를 가진 요소를 찾아 button 변수에 저장합니다.
  const input = screen.getByRole('textbox');
  const button = screen.getByRole('button', { name: /click me/i });
  
//tab 을 입력합니다. 
//tab 입력 이후 input 요소가 활성화될 것임을 예상합니다.
  user.tab();
  expect(document.activeElement).toBe(input);
  
// 다시 tab을 입력합니다.
// tab 입력 이후에는 button 요소가 활성화될 것임을 예상합니다.
  user.tab();
  expect(document.activeElement).toBe(button);
});

userEvent.keyboard(key, [options])

주어진 키보드 이벤트를 발생시킵니다. key는 문자열 또는 문자열 배열일 수 있으며, options 객체를 사용하여 수정자 키 (Shift, Ctrl, Alt 및 Meta)를 추가할 수 있습니다.

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('Pressing a key', () => {
  const user = userEvent.setup();
  render(<input />);
  
  // role ="textbox" 인 요소를 찾아서 input 변수에 저장합니다.
  const input = screen.getByRole('textbox');

  // a 키를 입력합니다.
  user.keyboard('a');

 //input 요소의 value 으로 a 를 가질 것임을 예상합니다.
  expect(input).toHaveValue('a');
});

 

반응형