Skip to content
Vitest 2
Main Navigation 가이드API구성브라우저 모드고급
3.2.0
2.1.9
1.6.1
0.34.6

한국어

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
Italiano
Polski
Türkçe
čeština
magyar

한국어

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
Italiano
Polski
Türkçe
čeština
magyar

외관

Sidebar Navigation

Why Browser Mode?

Getting Started

Context API

Interactivity API

Locators

Assertion API

Commands API

이 페이지에서

상호작용 API ​

Vitest는 이벤트를 모방하는 대신 Chrome DevTools Protocol 또는 webdriver를 사용하여 @testing-library/user-event API의 하위 집합을 구현합니다. 이는 브라우저 동작을 사용자가 페이지와 상호작용하는 방식과 더 안정적이고 일관되게 만듭니다.

ts
import { userEvent } from '@vitest/browser/context';

await userEvent.click(document.querySelector('.button'));

대부분의 userEvent 메서드는 제공자 옵션을 상속합니다. IDE에서 사용 가능한 모든 옵션을 보려면 tsconfig.json 파일에 webdriver 또는 playwright 유형(제공자에 따라 다름)을 추가하세요.

json
{
  "compilerOptions": {
    "types": ["@vitest/browser/providers/playwright"]
  }
}
json
{
  "compilerOptions": {
    "types": ["@vitest/browser/providers/webdriverio"]
  }
}

userEvent.setup ​

ts
function setup(): UserEvent;

새로운 사용자 이벤트 인스턴스를 생성합니다. 이는 키보드 상태를 유지하여 버튼을 올바르게 누르고 놓는 데 유용합니다.

WARNING

@testing-library/user-event와 달리 @vitest/browser/context의 기본 userEvent 인스턴스는 메서드가 호출될 때마다 생성되는 것이 아니라 한 번만 생성됩니다. 다음 스니펫에서 작동 방식의 차이를 확인할 수 있습니다.

ts
import { userEvent as vitestUserEvent } from '@vitest/browser/context';
import { userEvent as originalUserEvent } from '@testing-library/user-event';

await vitestUserEvent.keyboard('{Shift}'); // Shift 키를 누르고 놓지 않음
await vitestUserEvent.keyboard('{/Shift}'); // Shift 키를 놓음

await originalUserEvent.keyboard('{Shift}'); // Shift 키를 누르고 놓지 않음
await originalUserEvent.keyboard('{/Shift}'); // 상태가 다르기 때문에 Shift 키를 놓지 않음

이 동작은 키보드를 에뮬레이션하는 것이 아니라 실제로 Shift 키를 누르기 때문에 더 유용합니다. 따라서 원래 동작을 유지하면 필드에 입력할 때 예상치 못한 문제가 발생할 수 있습니다.

userEvent.click ​

ts
function click(
  element: Element | Locator,
  options?: UserEventClickOptions
): Promise<void>;

요소를 클릭합니다. 제공자의 옵션을 상속합니다. 이 메서드가 작동하는 방식에 대한 자세한 설명은 제공자의 문서를 참조하세요.

ts
import { page, userEvent } from '@vitest/browser/context';

test('clicks on an element', async () => {
  const logo = page.getByRole('img', { name: /logo/ });

  await userEvent.click(logo);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await logo.click();
});

참고 자료:

  • Playwright locator.click API
  • WebdriverIO element.click API
  • testing-library click API

userEvent.dblClick ​

ts
function dblClick(
  element: Element | Locator,
  options?: UserEventDoubleClickOptions
): Promise<void>;

요소에 더블 클릭 이벤트를 트리거합니다.

이 메서드가 작동하는 방식에 대한 자세한 설명은 제공자의 문서를 참조하세요.

ts
import { page, userEvent } from '@vitest/browser/context';

test('triggers a double click on an element', async () => {
  const logo = page.getByRole('img', { name: /logo/ });

  await userEvent.dblClick(logo);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await logo.dblClick();
});

참고 자료:

  • Playwright locator.dblclick API
  • WebdriverIO element.doubleClick API
  • testing-library dblClick API

userEvent.tripleClick ​

ts
function tripleClick(
  element: Element | Locator,
  options?: UserEventTripleClickOptions
): Promise<void>;

요소에 트리플 클릭 이벤트를 트리거합니다. 브라우저 API에는 tripleclick이 없으므로 이 메서드는 세 번의 클릭 이벤트를 연속으로 발생시킵니다. 따라서 이벤트를 필터링하려면 클릭 이벤트 상세 정보에서 evt.detail === 3인지 확인해야 합니다.

이 메서드가 작동하는 방식에 대한 자세한 설명은 제공자의 문서를 참조하세요.

ts
import { page, userEvent } from '@vitest/browser/context';

test('triggers a triple click on an element', async () => {
  const logo = page.getByRole('img', { name: /logo/ });
  let tripleClickFired = false;
  logo.addEventListener('click', evt => {
    if (evt.detail === 3) {
      tripleClickFired = true;
    }
  });

  await userEvent.tripleClick(logo);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await logo.tripleClick();

  expect(tripleClickFired).toBe(true);
});

참고 자료:

  • Playwright locator.click API: clickCount: 3으로 click을 통해 구현됩니다.
  • WebdriverIO browser.action API: move와 세 번의 down + up + pause 이벤트를 연속으로 사용하여 액션 API를 통해 구현됩니다.
  • testing-library tripleClick API

userEvent.fill ​

ts
function fill(element: Element | Locator, text: string): Promise<void>;

input/textarea/conteneditable 필드에 값을 설정합니다. 이렇게 하면 새 값을 설정하기 전에 입력 필드의 기존 텍스트가 모두 제거됩니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('update input', async () => {
  const input = page.getByRole('input');

  await userEvent.fill(input, 'foo'); // input.value == foo
  await userEvent.fill(input, '{{a[['); // input.value == {{a[[
  await userEvent.fill(input, '{Shift}'); // input.value == {Shift}

  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await input.fill('foo'); // input.value == foo
});

이 메서드는 요소에 포커스를 맞추고 값을 채운 후 input 이벤트를 트리거합니다. 빈 문자열을 사용하면 필드를 비울 수 있습니다.

TIP

이 API는 userEvent.type 또는 userEvent.keyboard보다 빠르지만, user-event keyboard 구문 (예: {Shift}{selectall})은 지원하지 않습니다.

특수 문자 입력이나 키 누름 이벤트의 세밀한 제어가 필요하지 않은 경우에는 userEvent.type 대신 이 API를 사용하는 것이 좋습니다.

참고 자료:

  • Playwright locator.fill API
  • WebdriverIO element.setValue API
  • testing-library type API

userEvent.keyboard ​

ts
function keyboard(text: string): Promise<void>;

userEvent.keyboard를 사용하면 키보드 스트로크를 트리거할 수 있습니다. 어떤 입력 필드가 포커스되어 있으면 해당 입력 필드에 문자를 입력합니다. 그렇지 않으면 현재 포커스된 요소(document.body에 포커스된 요소가 없으면)에 키보드 이벤트를 트리거합니다.

이 API는 user-event keyboard 구문을 지원합니다.

ts
import { userEvent } from '@vitest/browser/context';

test('trigger keystrokes', async () => {
  await userEvent.keyboard('foo'); // 다음으로 변환: f, o, o
  await userEvent.keyboard('{{a[['); // 다음으로 변환: {, a, [
  await userEvent.keyboard('{Shift}{f}{o}{o}'); // 다음으로 변환: Shift, f, o, o
  await userEvent.keyboard('{a>5}'); // a를 누른 상태로 5번의 keydown 이벤트 발생
  await userEvent.keyboard('{a>5/}'); // a를 5번 keydown하고 놓음
});

참고 자료:

  • Playwright Keyboard API
  • WebdriverIO action('key') API
  • testing-library type API

userEvent.tab ​

ts
function tab(options?: UserEventTabOptions): Promise<void>;

Tab 키 이벤트를 보냅니다. 이는 userEvent.keyboard('{tab}')의 약어입니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('tab works', async () => {
  const [input1, input2] = page.getByRole('input').elements();

  expect(input1).toHaveFocus();

  await userEvent.tab();

  expect(input2).toHaveFocus();

  await userEvent.tab({ shift: true });

  expect(input1).toHaveFocus();
});

참고 자료:

  • Playwright Keyboard API
  • WebdriverIO action('key') API
  • testing-library tab API

userEvent.type ​

ts
function type(
  element: Element | Locator,
  text: string,
  options?: UserEventTypeOptions
): Promise<void>;

WARNING

특수 문자 (예: {shift} 또는 {selectall})에 의존하지 않는다면, 더 나은 성능을 위해 userEvent.fill을 대신 사용하는 것이 좋습니다.

type 메서드는 keyboard API를 기반으로 구축된 @testing-library/user-event의 type 유틸리티를 구현합니다.

이 함수는 input/textarea/contenteditable 요소에 문자를 입력할 수 있게 해줍니다. user-event keyboard 구문을 지원합니다.

입력 필드 없이 단순히 키 입력만 필요한 경우 userEvent.keyboard API를 사용하세요.

ts
import { page, userEvent } from '@vitest/browser/context';

test('update input', async () => {
  const input = page.getByRole('input');

  await userEvent.type(input, 'foo'); // input.value == foo
  await userEvent.type(input, '{{a[['); // input.value == foo{a[
  await userEvent.type(input, '{Shift}'); // input.value == foo{a[
});

INFO

Vitest는 input.type과 같이 로케이터에 .type 메서드를 노출하지 않습니다. 이는 userEvent 라이브러리와의 호환성을 위해서만 존재하기 때문입니다. 대신 .fill을 사용하는 것이 더 빠르므로 고려해 보세요.

참고 자료:

  • Playwright locator.press API
  • WebdriverIO action('key') API
  • testing-library type API

userEvent.clear ​

ts
function clear(element: Element | Locator): Promise<void>;

이 메서드는 입력 요소의 내용을 비웁니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('clears input', async () => {
  const input = page.getByRole('input');

  await userEvent.fill(input, 'foo');
  expect(input).toHaveValue('foo');

  await userEvent.clear(input);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await input.clear();

  expect(input).toHaveValue('');
});

참고 자료:

  • Playwright locator.clear API
  • WebdriverIO element.clearValue API
  • testing-library clear API

userEvent.selectOptions ​

ts
function selectOptions(
  element: Element | Locator,
  values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
  options?: UserEventSelectOptions
): Promise<void>;

userEvent.selectOptions를 사용하면 <select> 요소에서 값을 선택할 수 있습니다.

WARNING

select 요소에 multiple 속성이 없으면 Vitest는 배열의 첫 번째 요소만 선택합니다.

@testing-library와 달리 Vitest는 현재 listbox를 지원하지 않지만, 향후 지원을 추가할 계획입니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('clears input', async () => {
  const select = page.getByRole('select');

  await userEvent.selectOptions(select, 'Option 1');
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await select.selectOptions('Option 1');

  expect(select).toHaveValue('option-1');

  await userEvent.selectOptions(select, 'option-1');
  expect(select).toHaveValue('option-1');

  await userEvent.selectOptions(select, [
    page.getByRole('option', { name: 'Option 1' }),
    page.getByRole('option', { name: 'Option 2' }),
  ]);
  expect(select).toHaveValue(['option-1', 'option-2']);
});

WARNING

webdriverio 프로바이더는 다중 요소 선택 API를 제공하지 않아 이 기능을 지원하지 않습니다.

참고 자료:

  • Playwright locator.selectOption API
  • WebdriverIO element.selectByIndex API
  • testing-library selectOptions API

userEvent.hover ​

ts
function hover(
  element: Element | Locator,
  options?: UserEventHoverOptions
): Promise<void>;

이 메서드는 커서를 선택된 요소로 이동시킵니다. 이 메서드가 작동하는 방식에 대한 자세한 설명은 제공자의 문서를 참조하세요.

WARNING

webdriverio 제공자를 사용하는 경우 커서는 기본적으로 요소의 중앙으로 이동합니다.

playwright 제공자를 사용하는 경우 커서는 요소의 "어떤" 보이는 지점으로 이동합니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('hovers logo element', async () => {
  const logo = page.getByRole('img', { name: /logo/ });

  await userEvent.hover(logo);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await logo.hover();
});

참고 자료:

  • Playwright locator.hover API
  • WebdriverIO element.moveTo API
  • testing-library hover API

userEvent.unhover ​

ts
function unhover(
  element: Element | Locator,
  options?: UserEventHoverOptions
): Promise<void>;

이는 userEvent.hover와 동일하게 작동하지만, 커서를 document.body 요소로 이동합니다.

WARNING

기본적으로 커서 위치는 body 요소의 "어떤" 보이는 위치(playwright 제공자) 또는 중앙(webdriverio 제공자)에 있습니다. 따라서 현재 호버된 요소가 이미 같은 위치에 있으면 이 메서드는 아무 효과가 없습니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('unhover logo element', async () => {
  const logo = page.getByRole('img', { name: /logo/ });

  await userEvent.unhover(logo);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await logo.unhover();
});

참고 자료:

  • Playwright locator.hover API
  • WebdriverIO element.moveTo API
  • testing-library hover API

userEvent.upload ​

ts
function upload(
  element: Element | Locator,
  files: string[] | string | File[] | File
): Promise<void>;

파일 입력 요소에 지정된 파일을 할당합니다.

ts
import { page, userEvent } from '@vitest/browser/context';

test('can upload a file', async () => {
  const input = page.getByRole('button', { name: /Upload files/ });

  const file = new File(['file'], 'file.png', { type: 'image/png' });

  await userEvent.upload(input, file);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await input.upload(file);

  // 테스트 파일에 상대적인 파일 경로를 사용할 수도 있습니다.
  await userEvent.upload(input, '../fixtures/file.png');
});

WARNING

webdriverio 제공자는 chrome 및 edge 브라우저에서만 이 명령을 지원합니다. 또한 현재 문자열 유형만 지원합니다.

참고 자료:

  • Playwright locator.setInputFiles API
  • WebdriverIO browser.uploadFile API
  • testing-library upload API

userEvent.dragAndDrop ​

ts
function dragAndDrop(
  source: Element | Locator,
  target: Element | Locator,
  options?: UserEventDragAndDropOptions
): Promise<void>;

소스 요소를 대상 요소 위로 드래그 앤 드롭합니다. source 요소에 draggable 속성이 true로 설정되어 있어야 함을 잊지 마세요.

ts
import { page, userEvent } from '@vitest/browser/context';

test('drag and drop works', async () => {
  const source = page.getByRole('img', { name: /logo/ });
  const target = page.getByTestId('logo-target');

  await userEvent.dragAndDrop(source, target);
  // 또는 로케이터에서 직접 접근할 수 있습니다.
  await source.dropTo(target);

  await expect.element(target).toHaveTextContent('Logo is processed');
});

WARNING

이 API는 기본 preview 제공자에서 지원되지 않습니다.

참고 자료:

  • Playwright frame.dragAndDrop API
  • WebdriverIO element.dragAndDrop API
Pager
이전Context API
다음Locators

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2021-Present Vitest Team

https://v2.vitest.dev/guide/browser/interactivity-api

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2021-Present Vitest Team