로케이터 2.1.0+
로케이터는 하나 또는 여러 개의 요소를 나타냅니다. 모든 로케이터는 셀렉터라고 하는 문자열로 정의됩니다. Vitest는 이러한 셀렉터를 편리한 메서드를 통해 추상화하며, 이 메서드는 내부적으로 셀렉터를 생성합니다.
로케이터 API는 Playwright의 로케이터를 포크한 Ivya를 사용합니다. Vitest는 이 API를 모든 프로바이더에 제공합니다.
getByRole
function getByRole(
role: ARIARole | string,
options?: LocatorByRoleOptions
): Locator;
ARIA 역할, ARIA 속성 및 접근 가능한 이름으로 요소를 찾는 로케이터를 생성합니다.
TIP
getByText('The name')
으로 단일 요소만 쿼리하는 경우, getByRole(expectedRole, { name: 'The name' })
을 사용하는 것이 더 나은 경우가 많습니다. 접근 가능한 이름 쿼리는 *ByAltText
나 *ByTitle
과 같은 다른 쿼리를 대체하지 않습니다. 접근 가능한 이름이 이러한 속성과 같을 수 있지만, 이러한 속성의 기능을 대체하지는 않습니다.
다음 DOM 구조를 고려하십시오.
<h3>Sign up</h3>
<label>
Login
<input type="text" />
</label>
<label>
Password
<input type="password" />
</label>
<br />
<button>Submit</button>
각 요소를 암시적 역할로 찾을 수 있습니다.
await expect
.element(page.getByRole('heading', { name: 'Sign up' }))
.toBeVisible();
await page.getByRole('textbox', { name: 'Login' }).fill('admin');
await page.getByRole('textbox', { name: 'Password' }).fill('admin');
await page.getByRole('button', { name: /submit/i }).click();
WARNING
역할은 ARIA 역할 계층 구조를 상속하지 않고 문자열 일치로만 비교됩니다. 결과적으로 checkbox
와 같은 상위 클래스 역할을 쿼리하면 switch
와 같은 하위 클래스 역할을 가진 요소는 포함되지 않습니다.
기본적으로 HTML의 많은 시맨틱 요소는 역할을 가집니다. 예를 들어, <input type="radio">
는 "radio" 역할을 가집니다. 시맨틱하지 않은 요소는 역할을 가지지 않습니다. 추가된 시맨틱이 없는 <div>
와 <span>
는 null
을 반환합니다. role
속성은 시맨틱을 제공할 수 있습니다.
이미 암시적 역할이 있는 내장 요소에 role
또는 aria-*
속성을 통해 역할을 제공하는 것은 ARIA 가이드라인에서 강력히 권장되지 않습니다.
옵션
exact: boolean
name
이 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.name
이 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.tsx<button>Hello World</button>; page.getByRole('button', { name: 'hello world' }); // ✅ page.getByRole('button', { name: 'hello world', exact: true }); // ❌ page.getByRole('button', { name: 'Hello World', exact: true }); // ✅
checked: boolean
체크된 요소(
aria-checked
또는<input type="checkbox"/>
로 설정됨)를 포함할지 여부입니다. 기본적으로 필터는 적용되지 않습니다.자세한 내용은
aria-checked
를 참조하십시오.tsx<> <button role="checkbox" aria-checked="true" /> <input type="checkbox" checked /> </>; page.getByRole('checkbox', { checked: true }); // ✅ page.getByRole('checkbox', { checked: false }); // ❌
disabled: boolean
비활성 상태의 요소를 포함할지 여부입니다. 기본적으로 필터는 적용되지 않습니다. 다른 속성과 달리
disable
상태는 상속됩니다.자세한 내용은
aria-disabled
를 참조하십시오.tsx<input type="text" disabled />; page.getByRole('textbox', { disabled: true }); // ✅ page.getByRole('textbox', { disabled: false }); // ❌
expanded: boolean
펼쳐진 상태의 요소를 포함할지 여부입니다. 기본적으로 필터는 적용되지 않습니다.
자세한 내용은
aria-expanded
를 참조하십시오.tsx<a aria-expanded="true" href="example.com"> Link </a>; page.getByRole('link', { expanded: true }); // ✅ page.getByRole('link', { expanded: false }); // ❌
includeHidden: boolean
접근성 트리에서 일반적으로 제외되는 요소를 쿼리할지 여부입니다. 기본적으로 숨김 처리되지 않은 요소만 역할 셀렉터에 의해 일치됩니다.
none
및presentation
역할은 항상 포함됩니다.tsx<button style="display: none" />; page.getByRole('button'); // ❌ page.getByRole('button', { includeHidden: false }); // ❌ page.getByRole('button', { includeHidden: true }); // ✅
level: number
heading
,listitem
,row
,treeitem
역할에 대해 일반적으로 존재하는 숫자 속성으로,<h1>-<h6>
요소에 대한 기본값이 있습니다. 기본적으로 필터는 적용되지 않습니다.자세한 내용은
aria-level
를 참조하십시오.tsx<> <h1>Heading Level One</h1> <div role="heading" aria-level="1"> Second Heading Level One </div> </>; page.getByRole('heading', { level: 1 }); // ✅ page.getByRole('heading', { level: 2 }); // ❌
name: string | RegExp
접근 가능한 이름입니다. 기본적으로 일치는 대소문자를 구분하지 않으며 부분 문자열을 검색합니다. 이 동작을 제어하려면
exact
옵션을 사용하십시오.tsx<button>Click Me!</button>; page.getByRole('button', { name: 'Click Me!' }); // ✅ page.getByRole('button', { name: 'click me!' }); // ✅ page.getByRole('button', { name: 'Click Me?' }); // ❌
pressed: boolean
눌린 요소를 포함할지 여부입니다. 기본적으로 필터는 적용되지 않습니다.
자세한 내용은
aria-pressed
를 참조하십시오.tsx<button aria-pressed="true">👍</button>; page.getByRole('button', { pressed: true }); // ✅ page.getByRole('button', { pressed: false }); // ❌
selected: boolean
선택된 요소를 포함할지 여부입니다. 기본적으로 필터는 적용되지 않습니다.
자세한 내용은
aria-selected
를 참조하십시오.tsx<button role="tab" aria-selected="true"> Vue </button>; page.getByRole('button', { selected: true }); // ✅ page.getByRole('button', { selected: false }); // ❌
참고
getByAltText
function getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
텍스트와 일치하는 alt
속성을 가진 요소를 찾는 로케이터를 생성합니다. testing-library의 구현과 달리 Vitest는 일치하는 alt
속성을 가진 모든 요소를 일치시킵니다.
<img alt="Incredibles 2 Poster" src="/incredibles-2.png" />;
page.getByAltText(/incredibles.*? poster/i); // ✅
page.getByAltText('non existing alt text'); // ❌
옵션
exact: boolean
text
가 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.text
가 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.
참고
getByLabelText
function getByLabelText(
text: string | RegExp,
options?: LocatorOptions
): Locator;
연관된 레이블을 가진 요소를 찾는 로케이터를 생성합니다.
page.getByLabelText('Username')
로케이터는 아래 예제의 모든 입력을 찾습니다.
<!-- for/htmlFor 관계 (레이블과 폼 요소 id 간) -->
<label for="username-input">Username</label>
<input id="username-input" />
<!-- aria-labelledby 속성 (폼 요소와 함께) -->
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />
<!-- 래퍼 레이블 -->
<label>Username <input /></label>
<!-- 레이블 텍스트가 다른 자식 요소에 있는 래퍼 레이블 -->
<label>
<span>Username</span>
<input />
</label>
<!-- aria-label 속성 -->
<!-- 사용자가 페이지에서 볼 수 있는 레이블이 아니므로 주의해야 합니다. -->
<!-- 따라서 입력의 목적은 시각적 사용자에게 명확해야 합니다. -->
<input aria-label="Username" />
옵션
exact: boolean
text
가 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.text
가 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.
참고
getByPlaceholder
function getByPlaceholder(
text: string | RegExp,
options?: LocatorOptions
): Locator;
지정된 placeholder
속성을 가진 요소를 찾는 로케이터를 생성합니다. Vitest는 input
뿐만 아니라 일치하는 placeholder
속성을 가진 모든 요소를 일치시킵니다.
<input placeholder="Username" />;
page.getByPlaceholder('Username'); // ✅
page.getByPlaceholder('not found'); // ❌
WARNING
일반적으로 플레이스홀더보다 getByLabelText
를 사용하여 레이블에 의존하는 것이 더 좋습니다.
옵션
exact: boolean
text
가 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.text
가 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.
참고
getByText
function getByText(text: string | RegExp, options?: LocatorOptions): Locator;
지정된 텍스트를 포함하는 요소를 찾는 로케이터를 생성합니다. 텍스트는 TextNode의 nodeValue
또는 타입이 button
또는 reset
인 경우 input의 값과 일치됩니다. 텍스트로 일치시킬 때는 정확한 일치에서도 항상 공백을 정규화합니다. 예를 들어, 여러 공백을 하나로 바꾸고, 줄 바꿈을 공백으로 바꾸며, 앞뒤 공백을 무시합니다.
<a href="/about">About ℹ️</a>;
page.getByText(/about/i); // ✅
page.getByText('about', { exact: true }); // ❌
TIP
이 로케이터는 비대화형 요소를 찾는 데 유용합니다. 버튼이나 입력과 같은 대화형 요소를 찾아야 하는 경우 getByRole
을 선호하십시오.
옵션
exact: boolean
text
가 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.text
가 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.
참고
getByTitle
function getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
지정된 title
속성을 가진 요소를 찾는 로케이터를 생성합니다. testing-library의 getByTitle
과 달리 Vitest는 SVG 내의 title
요소를 찾을 수 없습니다.
<span title="Delete" id="2"></span>;
page.getByTitle('Delete'); // ✅
page.getByTitle('Create'); // ❌
옵션
exact: boolean
text
가 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.text
가 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.
참고
getByTestId
function getByTestId(text: string | RegExp): Locator;
지정된 테스트 ID 속성과 일치하는 요소를 찾는 로케이터를 생성합니다. browser.locators.testIdAttribute
를 사용하여 속성 이름을 구성할 수 있습니다.
<div data-testid="custom-element" />;
page.getByTestId('custom-element'); // ✅
page.getByTestId('non-existing-element'); // ❌
WARNING
다른 로케이터가 사용 사례에 적합하지 않은 경우에만 이 방법을 사용하는 것이 좋습니다. data-testid
속성을 사용하는 것은 소프트웨어가 사용되는 방식과 유사하지 않으므로 가능하면 피해야 합니다.
옵션
exact: boolean
text
가 대소문자를 구분하고 전체 문자열로 정확히 일치하는지 여부입니다. 기본적으로 비활성화되어 있습니다.text
가 정규 표현식인 경우 이 옵션은 무시됩니다. 정확한 일치도 공백을 제거합니다.
참고
메서드
모든 메서드는 비동기식이며 await
로 처리해야 합니다. Vitest 2.2부터 메서드가 await
되지 않으면 테스트가 실패합니다.
click
function click(options?: UserEventClickOptions): Promise<void>;
요소를 클릭합니다. 옵션을 사용하여 커서 위치를 설정할 수 있습니다.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).click();
dblClick
function dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
요소에 더블클릭 이벤트를 발생시킵니다. 옵션을 사용하여 커서 위치를 설정할 수 있습니다.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).dblClick();
tripleClick
function tripleClick(options?: UserEventTripleClickOptions): Promise<void>;
요소에 트리플 클릭 이벤트를 트리거합니다. 브라우저 API에 tripleclick
이 없기 때문에 이 메서드는 세 번의 클릭 이벤트를 연속으로 발생시킵니다.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).tripleClick();
clear
function clear(): Promise<void>;
입력 요소의 내용을 지웁니다.
import { page } from '@vitest/browser/context';
await page.getByRole('textbox', { name: 'Full Name' }).clear();
hover
function hover(options?: UserEventHoverOptions): Promise<void>;
커서 위치를 선택된 요소로 이동합니다.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).hover();
unhover
function unhover(options?: UserEventHoverOptions): Promise<void>;
이것은 locator.hover
와 동일하게 작동하지만, 커서를 document.body
로 이동합니다.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).unhover();
fill
function fill(text: string, options?: UserEventFillOptions): Promise<void>;
현재 input
, textarea
또는 conteneditable
요소의 값을 설정합니다.
import { page } from '@vitest/browser/context';
await page.getByRole('input', { name: 'Full Name' }).fill('Mr. Bean');
dropTo
function dropTo(
target: Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
현재 요소를 목표 위치로 드래그합니다.
import { page } from '@vitest/browser/context';
const paris = page.getByText('Paris');
const france = page.getByText('France');
await paris.dropTo(france);
selectOptions
function selectOptions(
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
<select>
요소에서 하나 이상의 값을 선택합니다.
import { page } from '@vitest/browser/context';
const languages = page.getByRole('select', { name: 'Languages' });
await languages.selectOptions('EN');
await languages.selectOptions(['ES', 'FR']);
await languages.selectOptions([
languages.getByRole('option', { name: 'Spanish' }),
languages.getByRole('option', { name: 'French' }),
]);
screenshot
function screenshot(
options: LocatorScreenshotOptions & { base64: true }
): Promise<{
path: string;
base64: string;
}>;
function screenshot(
options?: LocatorScreenshotOptions & { base64?: false }
): Promise<string>;
로케이터의 셀렉터와 일치하는 요소의 스크린샷을 찍습니다.
path
옵션을 사용하여 스크린샷의 저장 위치를 지정할 수 있으며, 이는 현재 테스트 파일에 상대적입니다. path
옵션이 설정되지 않으면 Vitest는 기본적으로 browser.screenshotDirectory
(__screenshot__
기본값)와 파일 및 테스트 이름을 사용하여 스크린샷 파일 경로를 결정합니다.
스크린샷의 내용도 필요한 경우 base64: true
를 지정하여 스크린샷이 저장된 파일 경로와 함께 반환할 수 있습니다.
import { page } from '@vitest/browser/context';
const button = page.getByRole('button', { name: 'Click Me!' });
const path = await button.screenshot();
const { path, base64 } = await button.screenshot({
path: './button-click-me.png',
base64: true, // base64 문자열도 반환
});
// path - 스크린샷의 전체 경로
// base64 - 스크린샷의 base64 인코딩 문자열
query
function query(): Element | null;
이 메서드는 로케이터의 셀렉터와 일치하는 단일 요소를 반환하거나, 일치하는 요소가 없으면 null
을 반환합니다.
여러 요소가 셀렉터와 일치하는 경우 이 메서드는 오류를 발생시킵니다. 일치하는 모든 DOM 요소가 필요한 경우 .elements()
를 사용하거나, 셀렉터와 일치하는 로케이터 배열이 필요한 경우 .all()
을 사용하십시오.
다음 DOM 구조를 고려하십시오.
<div>Hello <span>World</span></div>
<div>Hello</div>
이 로케이터는 오류를 발생시키지 않습니다.
page.getByText('Hello World').query(); // ✅ HTMLDivElement
page.getByText('Hello Germany').query(); // ✅ null
page.getByText('World').query(); // ✅ HTMLSpanElement
page.getByText('Hello', { exact: true }).query(); // ✅ HTMLSpanElement
이 로케이터는 오류를 발생시킵니다.
// 여러 요소를 반환
page.getByText('Hello').query(); // ❌
page.getByText(/^Hello/).query(); // ❌
element
function element(): Element;
이 메서드는 로케이터의 셀렉터와 일치하는 단일 요소를 반환합니다.
셀렉터와 일치하는 요소가 없는 경우 오류가 발생합니다. 요소가 존재하는지 확인하기만 하면 되는 경우 .query()
를 사용하는 것을 고려하십시오.
셀렉터와 일치하는 여러 요소가 있는 경우 오류가 발생합니다. 일치하는 모든 DOM 요소가 필요한 경우 .elements()
를 사용하거나, 셀렉터와 일치하는 로케이터 배열이 필요한 경우 .all()
을 사용하십시오.
TIP
이 메서드는 외부 라이브러리로 전달해야 할 때 유용할 수 있습니다. 로케이터가 expect.element
와 함께 사용될 때마다 어설션이 재시도될 때 자동으로 호출됩니다.
await expect.element(page.getByRole('button')).toBeDisabled();
다음 DOM 구조를 고려하십시오.
<div>Hello <span>World</span></div>
<div>Hello Germany</div>
<div>Hello</div>
이 로케이터는 오류를 발생시키지 않습니다.
page.getByText('Hello World').element(); // ✅
page.getByText('Hello Germany').element(); // ✅
page.getByText('World').element(); // ✅
page.getByText('Hello', { exact: true }).element(); // ✅
이 로케이터는 오류를 발생시킵니다.
// 여러 요소를 반환
page.getByText('Hello').element(); // ❌
page.getByText(/^Hello/).element(); // ❌
// 요소가 없음
page.getByText('Hello USA').element(); // ❌
elements
function elements(): Element[];
이 메서드는 로케이터의 셀렉터와 일치하는 요소 배열을 반환합니다.
이 함수는 오류를 발생시키지 않습니다. 셀렉터와 일치하는 요소가 없으면 이 메서드는 빈 배열을 반환합니다.
다음 DOM 구조를 고려하십시오.
<div>Hello <span>World</span></div>
<div>Hello</div>
이 로케이터는 항상 성공합니다.
page.getByText('Hello World').elements(); // ✅ [HTMLElement]
page.getByText('World').elements(); // ✅ [HTMLElement]
page.getByText('Hello', { exact: true }).elements(); // ✅ [HTMLElement]
page.getByText('Hello').elements(); // ✅ [HTMLElement, HTMLElement]
page.getByText('Hello USA').elements(); // ✅ []
all
function all(): Locator[];
이 메서드는 셀렉터와 일치하는 새 로케이터 배열을 반환합니다.
내부적으로 이 메서드는 .elements
를 호출하고 page.elementLocator
를 사용하여 모든 요소를 래핑합니다.