이번 글은 셀렉트 박스를 react testing library를 통해서 어떻게 테스트하는지에 대한 포스트다.
react testing library는 Semantic HTML을 사용할수록 더 간편하게 query를 할 수가 있다. 아래의 Select
컴포넌트 같은 경우는 semantic 하게 html을 사용했기 때문에 label
태그와 같이 사용되었다.
import { FC } from 'react';
const Select: FC = () => {
return (
<div>
<label htmlFor="language-select">
Choose a country
<select id="language-select">
<option value="">choose a country</option>
<option value="ko">한국</option>
<option value="usa">미국</option>
</select>
</label>
</div>
);
};
export default Select;
import React from 'react';
import { render, screen, userEvent } from '@test-utils';
import Select from './Select';
test('default option should be falsy when different option is selected', () => {
render(<Select />);
const selectElement = screen.getByRole('combobox', { name: 'Choose a country' });
userEvent.selectOptions(selectElement, 'usa');
const defaultOption = screen.getByRole('option', { name: 'choose a country' }) as HTMLOptionElement;
const selectedOption = screen.getByRole('option', { name: '미국' }) as HTMLOptionElement;
expect(defaultOption.selected).toBeFalsy();
expect(selectedOption.selected).toBeTruthy();
});
위의 테스트 코드는 짧지만, step by step으로 최대한 자세하게 설명을 해보겠다.
- 먼저 Select 컴포넌트를 렌더링을 시켜줘야 한다.
render
를 통해서 해당 컴포넌트를 렌더링했다.
- react testing library의 Query는 여러 가지 종류가 있는데 공식 홈페이지에서 정해놓은 우선순위가 있다.
- 우선순위에서 1순위인
getByRole
쿼리 같은 경우는 DOM의 Accessibility tree 안에 있는 aria-role 을 통해서 DOM 접근을 한 다음에 해당 엘레멘트를 반환을 해준다.
-
select 태그의 role은
listbox
또는combobox
가 이고, multiple attribute가 사용되지 않고, size attribute가 없거나 또는 사이즈가 1보다 크지 않을 때에는combobox
로 분류가 된다.
-
Select
컴포넌트는 여러 개의 select 태그가 없기 때문에getByRole
의 두 번째 인자인 option 객체를 통해서 다시 쿼리를 해줄 필요가 없다. 하지만 만약에 이 컴포넌트 안에서 여러개의 select 태그가 있으면 에러가 나게 된다.
- 이러면 두번째 인자로 옵션 객체의 name 속성을 이용해서. 다시 한 번 더 쿼리를 할 필요성이 있다. 화면에 표시되는 텍스트가 돔의 Accessibility tree의 name(레이블 텍스트: Choose a country)이 되기 때문에 옵션객채에 name속성을 넣어줘서 쿼리를 해준다.
- 만약에 semantic한 html을 사용하지 않았을 경우에는(label이 없이 select를 사용한 경우),
aria-label
attribute를 select 태그에 추가해주면 name으로 query가 가능하다. 다만 aria-label을 화면상에 보이는 label이 없는 경우에만 사용을 권장하고 또한 Accessibility Tree의 name을 덮어씌울 수 있기 때문에 무조건 사용해서는 안 된다.
- 이제 해당
Select
컴포넌트의 value를 바뀌기 위해서 이벤트를 실행해보아야 하는데, 공식 홈페이지에서fireEvent
보다는userEvent
사용을 권장하고 있기 때문에 userEvent를 사용해서 select의 value를 usa로 바꿔주었다.
- 다음 단계는 getByRole의 인자로 option을 넣어줘서 쿼리를 해준다. option엘레멘트의 role은 option이다. option 태그 또한 여러개기 때문에 옵션객체에 name을 이용해서 쿼리를 했다. 다만 get쿼리 같은 경우는 항상 타입을
HTMLElement
를 반환하기 때문에 selected라는 속성이 없기 때문에 타입 assertion을 통해서HTMLOptionElement
를 반환을 했다.
- 자 이제 마지막으로 처음에 선택이 돼 있던
defaultOption
의 selected 속성이falsy
인게 확인이 됐고, 새로 선택이 된selectedOption
의 selected 속성이truthy
인걸 확인할 수 있다.
Top comments (0)