210509 ReferenceError regeneratorRuntime is not defined


NodeJS 프로젝트를 진행하면서 비동기로 작성한 함수를 위한 테스트 코드를 작성하고 실행을 했는데 ReferenceError: regeneratorRuntime is not defined 에러가 발생했다.
이전에 ReactJS 프로젝트를 진행하면서 테스트 코드를 작성했을때도 위와 똑같은 에러가 발생했었는데 이러한 경우에는 아래의 두 방법으로 해결을 할 수 있다.

Solution 1) regenerator-runtime를 설치해서 비동기 함수를 작성한 파일의 최상단에 import 'regenerator-runtime/runtime';를 선언해주면 간단하게 해결할 수 있다.

Solution 2) .babelrc 의 설정을 아래와 같이 업데이트한다.

Using @babel/preset-env without that target set will result in the tests using async failing with ReferenceError: regeneratorRuntime is not defined.

1
2
3
4
5
6
7
8
9
10
11
12
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}

이 regenerator-runtime이 무엇인가 한 번 구글링을 해보니,
regenerator-runtime은 compiled/transpiled 비동기 함수들을 위한 runtime을 지원해주는 녀석이라고 한다.
Babel과 같은 컴파일러는 자바스크립트 syntax에 대해서 최신 문법을 이전 문법으로 변환을 해주지만, runtime에 의존적인 결과 코드(비동기 코드)들은 regenerator-runtime으로부터 지원을 받는다고 한다.

210505 screen.getBy*와 getBy의 차이, findBy*/getBy*/queryBy* method의 차이


테스트 코드를 작성하던 도중에 헷갈렸던 개념들에 대해서 반복학습을 위해 포스팅을 해두려고 한다.

screen.getBy vs getBy

screen을 사용하는 이점은 필요한 query를 추가할 때 더 이상 render 함수로 컴포넌트를 렌더링해서 최신 상태를 유지 하지 않아도 된다는 점이다.
beforeEach()함수 내에서 공통적으로 컴포넌트를 렌더링했다면, 이하의 test 블럭에서는 screen을 통해 렌더링된 컴포넌트를 통해 테스트 코드를 작성할 수 있다.

findBy* / getBy* / queryBy* method의 차이

  • getBy*

    조건에 맞는 요소를 찾았을때 query에 일치하는 노드를 반환
    조건에 맞는 요소를 못 찾았을때 에러를 반환
    → 존재하지 않는 DOM element를 assert할때에는 try-catch문으로 발생한 에러를 별도의 함수에 담아 tobedefined() matcher로 확인을 해야 한다. 이 경우에는 queryBy*를 사용해서 assert하는 것이 좋다.

  • queryBy*

    조건에 맞는 요소를 찾았을때 query에 일치하는 노드를 반환
    조건에 맞는 요소를 못 찾았을때 null을 반환
    → 존재하지 않는 DOM element를 assert할때 유용하다.

  • findBy*

    조건에 맞는 요소를 찾았을때 resolved Promise 반환
    조건에 맞는 요소를 못 찾았을때 rejected Promise 반환

    기존의 waitForElement()함수는 이제 deprecated되었기 때문에 findBy* 함수를 사용해야 한다.

    1
    2
    3
    4
    5
    6
    test('nowPlaying API method 테스트 - 데이터가 문제없이 화면에 로드되는지 확인', async () => {
    const { findByTestId } = render(<Movie />);

    await findByTestId('loading-text');
    await findByTestId('contents-list');
    });

210504 Error) You should not use Link outside a <Router>


<StaticRouter>와 <MemoryRouter>를 사용

이번에 컴포넌트 단위로 단위테스트를 하던 중에 You should not use XXX and <withRouter> outside a <Router>에러를 접했다.
Router의 내부에서만 사용할 수 있는 <withRouter>와 <Link>를 사용한 컴포넌트를 테스트를 할때에는 개별 컴포넌트만 호출해서 렌더링한 후에 테스트를 진행하기 때문에 실제로는 Router 내에 구현이 되어있다고 하더라도 위와같은 에러가 발생하게 되는 것이다.

위의 에러에 대한 해결책은 테스트 코드에서 <MemoryRouter> 또는 <StaticRouter>를 사용해서 테스트하려는 컴포넌트를 감싸서 렌더링해주면 된다.
Header.test.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import Header from './Header';
import { MemoryRouter } from 'react-router';



describe('header 컴포넌트 내부의 메인 메뉴관련 테스트 코드', () => {
let header;
beforeEach(() => {
header = render(<MemoryRouter><Header/></MemoryRouter>)
});

describe('메뉴 클릭시 제대로 연결된 페이지가 렌더링되는지 확인하는 테스트 코드', () => {
test('Movie 메뉴 클릭시 Movie page component가 렌더링된다.', () => {
const { getByTestId } = header;
expect(getByTestId('movie-menu')).toBeTruthy();
fireEvent.click(getByTestId('movie-menu'));
expect(screen.findByTestId('movie-page-container')).toBeInTheDocument;
});
......