DEV Community

Cover image for Testing select option with React Testing Library
leo
leo

Posted on

Testing select option with React Testing Library

이번 글은 셀렉트 박스를 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;
Enter fullscreen mode Exit fullscreen mode
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();
});
Enter fullscreen mode Exit fullscreen mode
위의 테스트 코드는 짧지만, 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)