> For the complete documentation index, see [llms.txt](https://yamoo9.gitbook.io/learning-react-app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yamoo9.gitbook.io/learning-react-app/tip-and-references/react-testing-library/get-by-element.md).

# 컴포넌트 요소 선택

React 컴포넌트를 렌더링 한 후, RTL는 다양한 검색 기능을 제공하여 요소를 가져오는 명령을 실행합니다. 가저온 요소는 어설션(assertion) 테스트에 사용되거나, 사용자와의 인터랙션(interaction) 테스트에 사용됩니다.

## getByText

{% tabs %}
{% tab title="app/App.test.js" %}

```jsx
import { render, screen } from '@testing-library/react'
import App from './App'

describe('App 컴포넌트', () => {
  test('React 앱 렌더링 학습 링크 포함 여부 확인', () => {
    render(<App />)
    
    // screen의 getByText()를 사용해 매칭되는 텍스트 값으로 대상(요소)을 찾을 수 있습니다.
    const linkElement = screen.getByText(/React를 배워보세요/i)
    
    expect(linkElement).toBeInTheDocument()
  })
})
```

{% endtab %}
{% endtabs %}

컴포넌트 랜더링 결과를 유추하기 어려운 경우, [`screen.debug()`](/learning-react-app/tip-and-references/react-testing-library/react-component-test.md#screen-debug)를 사용해 터미널에서 렌더링 결과를 확인합니다.

![](https://597303073-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MUfqhMWK9ILIx0SXJTa%2F-MVLycIaIy7ySDzuuK5r%2F-MVLzFZLIvLWhgElD9-7%2Fimage.png?alt=media\&token=fc36f4b6-dfda-4339-964c-662c273f16f2)

커스텀 매처를 사용해 [**특정 텍스트를 가진 요소가 문서에 있는지 검사**](https://github.com/testing-library/jest-dom#tobeinthedocument) 할 수 있습니다.

```jsx
test('"React 테스팅 라이브러리" 문구를 포함합니다', () => {
  render(<App />);
  
  // 특정 텍스트를 가진 요소가 문서에 포함되어 있는 지 검사합니다.
  expect(screen.getByText('React 테스팅 라이브러리')).toBeInTheDocument()
})
```

문자 값을 **정확히 특정하기 어려운 경우,** [**정규 표현식을 사용해 검사**](https://ko.javascript.info/regular-expressions) 할 수도 있습니다.

```jsx
test('App 컴포넌트 렌더링', () => {
  render(<App />);

  // 테스트 예시: ' 테스트 '

  // 실패
  expect(screen.getByText('테스팅')).toBeInTheDocument()

  // 실패
  expect(screen.getByText(' 테스팅')).toBeInTheDocument()

  // 성공!
  expect(screen.getByText(/\s?테스팅\s?/)).toBeInTheDocument()
})
```

## getByRole

[getByRole()](https://testing-library.com/docs/queries/byrole) 함수는 일반적으로 WAI-ARIA [aria-label](https://developer.mozilla.org/ko/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute), [role ](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles)속성을 가진 요소를 검색하는 데 사용됩니다. RTL은 시각적으로 표시되는 텍스트 외에도 접근성 역할(Role)을 통해 대상(요소)를 선택할 수 있습니다. [getByText()](https://testing-library.com/docs/queries/bytext)와 함께 RTL에서 널리 사용되는 검색 함수입니다.

```jsx
test('img 요소를 포함하는 지 검사합니다.', () => {
  render(<App />)

  // 이미지(img) 역할을 가진 요소가 문서에 포함되어 있는 지 검사합니다.
  expect(screen.getByRole('img')).toBeInTheDocument()
})
```

## 다른 검색 함수 <a href="#athor-search-function" id="athor-search-function"></a>

이 외에도 RTL은 요소 별로 검색 가능한 다양한 함수를 제공합니다.

| 검색         | 함수                                                                                   | 예시 코드                                |
| ---------- | ------------------------------------------------------------------------------------ | ------------------------------------ |
| 레이블 텍스트    | [getByLabelText()](https://testing-library.com/docs/queries/bylabeltext)             | \<label htmlFor="검색" />              |
| 플레이스홀더 텍스트 | [getByPlaceholderText()](https://testing-library.com/docs/queries/byplaceholdertext) | \<input placeholder="검색어를 입력하세요." /> |
| 대체 텍스트     | [getByAltText()](https://testing-library.com/docs/queries/byalttext)                 | \<img alt="교통 안내를 하는 포돌이" />         |
| 디스플레이 값    | [getByDisplayValue()](https://testing-library.com/docs/queries/bydisplayvalue)       | \<input value="React 테스팅 라이브러리" />   |

## 변형 검색 함수 <a href="#query-or-find-search-functions" id="query-or-find-search-functions"></a>

`getBy*()` 함수 외에도, 변형 된 `queryBy*()`, `findBy*()` 함수를 사용해 대상(요소)을 찾을 수 있습니다.

#### **queryBy**

* queryByText()
* queryByRole()
* queryByLabelText()
* queryByPlaceholderText()
* queryByAltText()
* queryByDisplayValue()

#### **findBy**

* findByText()
* findByRole()
* findByLabelText()
* findByPlaceholderText()
* findByAltText()
* findByDisplayValue()

### getBy VS queryBy 비교

**getBy**로 존재하지 않는 대상을 검색할 때 다음과 같은 오류가 출력됩니다. 오류 메시지를 살펴보면 검색한 텍스트가 여러 요소로 구분되어 있어 문제가 발생한 오류임을 안내합니다.

![](https://597303073-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MUfqhMWK9ILIx0SXJTa%2F-MVM9YHODbF3RaLHFLd3%2F-MVMAwUYxH8p9EA9zaJC%2Fimage.png?alt=media\&token=8b0cb2d2-3ba4-4f40-bd6f-1d958e1bb1e9)

{% hint style="danger" %}
TestingLibraryElementError: Unable to find an element with the text: /React 테스팅 라이브러리/. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

/Ract 테스팅 라이브러리/ 텍스트로 요소를 찾을 수 없습니다. 이는 텍스트가 여러 요소에 의해 분할되었기 때문일 수 있습니다. 이 경우 텍스트 매처를 보다 유연하게 만드는 함수를 제공할 수 있습니다.
{% endhint %}

```jsx
test('"React 테스팅 라이브러리" 문구를 포함합니다', () => {
  render(<App />)

  // TestingLibraryElementError 오류 출력 ✔︎
  expect(screen.getByText(/React 테스팅 라이브러리/)).toBeNull()
})
```

이런 경우 `getByText` 대신, `queryByText`를 사용하면 존재하지 않는 대상을 검색해도 오류가 발생하지 않습니다.

```jsx
test('"React 테스팅 라이브러리" 문구를 포함합니다', () => {
  render(<App />)

  // TestingLibraryElementError 오류 출력 ✘
  expect(screen.queryByText(/React 테스팅 라이브러리/)).toBeNull()
})
```

{% hint style="info" %}
[toBeNull()](https://jestjs.io/docs/en/expect#tobenull)은 toBe(null)과 동일하지만, 출력되는 오류 메시지가 좀 더 명확합니다. 무언가가 null 인지 확인하고 싶을 때 사용합니다.
{% endhint %}

### findBy는 언제 사용할까? <a href="#when-using-findby" id="when-using-findby"></a>

`findByText()`는 비동기(async) 처리 과정에 사용합니다. 아례 예를 살펴보면 컴포넌트에서 초기 렌더링 시점이 아닌, 상태 변경에 따른 업데이트 시점에 문서의 대상을 찾아야 할 때 `findByText()` 검색 함수를 사용합니다.

{% tabs %}
{% tab title="UserSearch.test.js" %}

```jsx
// 비동기(async) 콜백 함수
test('UserSearch 테스트', async () => {

  render(<UserSearch />)

  // FAIL 실패! null 반환
  expect(screen.queryByText(/로그인 사용자:/)).toBeInTheDocument()
  
  // 스크린 디버깅 (초기 렌더링 된 UI)
  screen.debug()

  // PASS 통과! await 비동기 처리 후, 업데이트 된 UI에서 대상(요소)를 찾음
  expect(await screen.findByText(/로그인 사용자:/)).toBeInTheDocument();

  // 스크린 디버깅 (업데이트 된 UI)
  screen.debug(); 

})
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="UserSearch.js" %}

```jsx
/**
 * 사용자 정보 가져오기 함수
 */
function getUser() {
  // Promise 객체 반환
  return Promise.resolve({ id: 'pzke1', name: '야무' })
}

/**
 * Search 컴포넌트
 */
function Search({ value, onChange, children }) {
  return (
    <div>
      <label htmlFor="search">{children}</label>
      <input
        id="search"
        type="text"
        value={value}
        onChange={onChange}
      />
    </div>
  )
}

/**
 * UserSearch 컴포넌트
 */
class UserSearch extends React.Component {
  state = {
    search: '',
    user: null,
  }

  loadUser = async () => {
    const user = await getUser();
    this.setState({ user });
  }

  handleChange = (event) => {
    this.setState({
      search: event.target.value,
    })
  }

  componentDidMount() {
    this.loadUser();
  }

  render() {
    const { search, user } = this.state;

    return (
      <div>
        {user ? <p>로그인 사용자: {user.name}</p> : null}

        <Search value={search} onChange={this.handleChange}>검색</Search>

        <p>검색어: {search ? search : '...'}</p>
      </div>
    )
  }
}

export default UserSearch
```

{% endtab %}
{% endtabs %}

## 복수 대상 찾기 <a href="#find-multiple-target" id="find-multiple-target"></a>

앞서 `getBy`, `queryBy`, `findBy` 검색 함수를 살펴봤습니다. 3가지 유형의 함수 모두 단수(1개) 대상을 검색해 찾을 때 사용합니다. 만약 복수(2개 이상)의 대상을 검색해 찾고자 한다면? `getAllBy`, `queryAllBy`, `findAllBy` 검색 함수를 활용합니다. `All`이 들어간 검색 함수는 대상 집합(배열)을 반환합니다.
