HTML의 role attribute
최근 이직 후 테스트 코드를 작성하는 과정에서 role attribute 에 대해 알게되어 정리해보려고 한다. 사내에서 Jest를 통해서 단위 테스트를 진행하고 있는데 컴포넌트를 테스트하려 한다면 기본적으로 원하는 요소가 제대로 렌더링 되는지를 검사하는 테스트를 많이 진행하게 된다.
it('CheckboxWithLabel changes the text after click', () => {
const { queryByLabelText, getByLabelText } = render(<CheckboxWithLabel labelOn="On" labelOff="Off" />);
expect(queryByLabelText(/off/i)).toBeTruthy();
fireEvent.click(getByLabelText(/off/i));
expect(queryByLabelText(/on/i)).toBeTruthy();
});
이럴 때 DOM에서 query를 날려 내가 원하는 요소를 찾아야하는데, getByLabelText, getByPlaceholderText, getByAltText 등 검색할 수 있는 방법은 많지만 무엇이 올바른 방법인지 테스트에 익숙하지 않다면 헷갈리기 쉽다.
그래서 Query 우선순위에 대해 정리된 공식문서가 있는데 About Queries
여기서 가장 우선으로 추천하는 것이 바로 getByRole
이다.
Role attribute설명
HTML의 role 속성은 요소의 접근성(A11Y) 을 향상시키기 위해 사용됩니다. 주로 화면 읽기 프로그램(screen readers)과 같은 보조 기술이 요소의 목적과 동작을 더 잘 이해할 수 있도록 도와줍니다.
저렇게 봤을땐 와닿지 않아서 실제로 MDN 에서 a 태그의 role을 임의로 button으로 지정하고, voiceover로 실행시켜 읽어보았더니
원래 a 태그의 Role은 link지만 button으로 읽고 있는 모습을 확인할 수 있다.
개발자가 다 지정해줘야해?
그렇지 않다. 대부분의 경우 기본적으로 정의되어있기 때문에 일일히 지정해줄 필요는 없다. 예를 들어서,
- button 태그는 기본적으로 role="button"
- a 태그는 기본적으로 role="link"
- input 태그는 기본적으로 role="textbox"
- li 태그는 기본적으로 role="listitem"
등 html 에서 기본적으로 정의가 되어있다.
테스트 코드에서의 사용
그래서 위에서 테스트 코드에서 query시 우선순위가 가장 높은것이 바로 role 이니 어떻게 테스트 코드에서 사용하는지 알아보자.
<button>Click to submit!</button>
위와 같은 요소를 검색하기 위해서는
getByRole('button', { name: '/submit/i' });
이렇게 role과 name을 통해서 원하는 요소를 찾을 수 있다.
name: /submit/i
는 getByRole 함수에서 정규표현식으로 원하는 텍스트 패턴을 지정해주는 옵션이다. 이 옵션을 통해서 역할(role) 뿐만 아니라 접근 가능한 이름(accessible name) 을 기준으로 요소를 검색하는 데 사용된다.
기본적으로 HTML DOM 테스트를 위해서는 접근 가능한 이름을 가지고 테스트를 하는것이 바람직하다. 접근가능한 이름은 눈에 보이는 요소가 우선순위가 높다. button에 텍스트라던지 placeholder, input 같은경우는 aria-label 속성으로도 지정 해줄 수 있다. 테스트뿐만 아니라 웹 접근성에도 도움이되니 앞으로 잘 활용해보도록 하자.