TodoForm 만들기

새로운 할 일 항목을 등록 할 수 있는 TodoForm 이라는 컴포넌트를 만들 것입니다.

먼저 비이었는 함수형 컴포넌트를 하나 만들어줍시다.

TodoForm.js

import React from 'react';

const TodoForm = () => {
  return (
    <div>

    </div>
  );
};

export default TodoForm;

그 다음에는 실패하는 테스트 케이스를 하나 작성해봅시다.

TodoForm.test.js

import React from 'react';
import { render } from 'react-testing-library';
import TodoForm from './TodoForm';

describe('TodoForm', () => {
  it('has input and button', () => {
    const { getByText, getByPlaceholderText } = render(<TodoForm />);
    getByPlaceholderText('할 일을 입력하세요');
    getByText('등록'); // 버튼이 있는지 확인
  });
});

테스트 코드를 작성하고 나면 당연히 실패 할 것입니다. 우리가 아직 구현을 안해줬으니까요. 구현을 해봅시다!

TodoForm.js

import React from 'react';

const TodoForm = () => {
  return (
    <form>
      <input placeholder="할 일을 입력하세요" />
      <button type="submit">등록</button>
    </form>
  );
};

export default TodoForm;

인풋과 버튼을 만들어주었으니, 테스트 케이스가 통과 할 것입니다.

이제 이 컴포넌트의 기능들을 위한 테스트 코드를 작성해봅시다.

TodoForm.test.js

import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import TodoForm from './TodoForm';

describe('TodoForm', () => {
  it('has input and button', () => {
    const { getByText, getByPlaceholderText } = render(<TodoForm />);
    getByPlaceholderText('할 일을 입력하세요');
    getByText('등록'); // 버튼이 있는지 확인
  });

  it('changes input', () => {
    const { getByPlaceholderText } = render(<TodoForm />);
    const input = getByPlaceholderText('할 일을 입력하세요');
    fireEvent.change(input, {
      target: {
        value: 'TDD 배우기'
      }
    });
    expect(input.value).toBe('TDD 배우기');
  });
});

이 테스트는 우리가 컴포넌트에 기능을 구현하기 전에도 통과 할 것입니다. 왜냐하면 input 에 우리가 onChange 및 value 값을 설정하지 않았기 때문이죠. 우선 기능을 구현해보고, 테스트가 여전히 통과하는지 확인해보세요.

TodoForm.js

import React, { useState, useCallback } from 'react';

const TodoForm = () => {
  const [value, setValue] = useState('');
  const onChange = useCallback(e => {
    setValue(e.target.value);
  }, []);
  return (
    <form>
      <input
        placeholder="할 일을 입력하세요"
        value={value}
        onChange={onChange}
      />
      <button type="submit">등록</button>
    </form>
  );
};

export default TodoForm;

테스트 코드가 정말 잘 작동하는지 검증하는 좋은 방법은 일부러 틀려보는 것 입니다.

TodoForm 컴포넌트의 onChange 함수 내부에서 setValue 함수를 호출하는 부분을 주석처리해보세요.

  const onChange = useCallback(e => {
    // setValue(e.target.value);
  }, []);
 FAIL  src/TodoForm.test.js
  ● TodoForm › changes input

    expect(received).toBe(expected) // Object.is equality

    Expected: "TDD 배우기"
    Received: ""

      19 |       }
      20 |     });
    > 21 |     expect(input.value).toBe('TDD 배우기');
         |                         ^
      22 |   });
      23 | });
      24 | 

      at Object.toBe (src/TodoForm.test.js:21:25)

위와 같이 실패하는것을 확인했다면 다시 원상복구 하세요.

그 다음에는 등록 버튼을 누르는 기능을 위한 테스트 코드를 작성하겠습니다. 이번에는 Mock 함수라는 것을 사용합니다. Mock 함수는 Jest 에서 제공하는 가짜 함수를 만들어주는 기능이며 이 가짜 함수를 사용하면 함수가 몇번 호출이 되었는지, 그리고 함수의 파라미터에는 무엇이 전달 되었는지 알아낼 수 있습니다.

import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import TodoForm from './TodoForm';

describe('TodoForm', () => {
  it('has input and button', () => {
    const { getByText, getByPlaceholderText } = render(<TodoForm />);
    getByPlaceholderText('할 일을 입력하세요');
    getByText('등록'); // 버튼이 있는지 확인
  });

  it('changes input', () => {
    // 인풋 값이 잘 바뀌는지 확인
    const { getByPlaceholderText } = render(<TodoForm />);
    const input = getByPlaceholderText('할 일을 입력하세요');
    fireEvent.change(input, {
      target: {
        value: 'TDD 배우기'
      }
    });
    expect(input.value).toBe('TDD 배우기');
  });

  it('submits form', () => {
    // 등록 기능을 확인
    const onInsert = jest.fn(); // Mock 함수를 만듭니다
    const { getByPlaceholderText, getByText } = render(
      <TodoForm onInsert={onInsert} />
    );
    const button = getByText('등록');
    const input = getByPlaceholderText('할 일을 입력하세요');
    // 인풋에 입력하고
    fireEvent.change(input, {
      target: {
        value: 'TDD 배우기'
      }
    });
    // 버튼을 클릭했을 때
    fireEvent.click(button);
    expect(input.value).toBe(''); // 인풋 값이 비워져야함
    expect(onInsert).toBeCalled(); // 함수가 호출 됐어야함
    expect(onInsert).toBeCalledWith('TDD 배우기'); // 함수가 'TDD 배우기' 라는 파라미터로 호출돼썽야함
  });
});

이제 위 테스트 케이스를 통과시키기 위하여 기능을 구현해봅시다.

TodoForm.js

import React, { useState, useCallback } from 'react';

const TodoForm = ({ onInsert }) => {
  const [value, setValue] = useState('');
  const onChange = useCallback(e => {
    setValue(e.target.value);
  }, []);
  const onSubmit = useCallback(e => {
    e.preventDefault();
    onInsert(value);
    setValue('');
  });
  return (
    <form onSubmit={onSubmit}>
      <input
        placeholder="할 일을 입력하세요"
        value={value}
        onChange={onChange}
      />
      <button type="submit">등록</button>
    </form>
  );
};

export default TodoForm;

이제 TodoForm 을 모두 구현하셨습니다!

results matching ""

    No results matching ""