본문 바로가기
IT/React

RN(ReactNative) TDD TODO 앱 만들기 #4

by DOSGamer 2022. 8. 11.
반응형

2022.08.10 - [IT/React] - RN(ReactNative) TDD TODO 앱 만들기 #3

 

RN(ReactNative) TDD TODO 앱 만들기 #3

2022.08.09 - [IT/React] - RN(ReactNative) TDD 설정 및 TODO 앱 만들기 2022.08.10 - [IT/React] - RN(ReactNative) TDD TODO 앱 만들기 #2 이전 테스트시에 한가지 Warning 이 보이는데 Warning: Each child..

skyksit.tistory.com

 

데이터에 unique 한 id 를 부여하기

이전에 초기 데이터의 id 를 1,2,3 이렇게 넣었는데 좀 더 고유한 id 를 넣기 위해서 shortid 라는 라이브러리를 사용합니다 

const initialData = [
  {id: '1', subject: 'Learn React Native'},
  {id: '2', subject: 'Create a React Native app'},
];

shortid 설치

 npm install --save shortid

 

HomeScreen 에서 shortid 를 이용해서 id 값을 생성해줍니다

//HomeScreen.jsx
import React from 'react';

import Title from '../components/Title';
import TaskInput from '../components/TaskInput';
import TaskList from '../components/TaskList';
import shortid from 'shortid';

const initialData = [
  {id: shortid.generate(), subject: 'Learn React Native'},
  {id: shortid.generate(), subject: 'Create a React Native app'},
];

export default function App() {
  console.log(initialData);
  return (
    <>
      <Title title="Todo TDD" />
      <TaskInput />
      <TaskList data={initialData} />
    </>
  );
}

shortid

이제 id 값으로 zy3AZ01Zy 같은 고유값들이 생성되어서 들어가 있습니다

 

Task 추가 기능 만들기

TaskInput 에서 값을 입력하면 TaskInput value 에 적용되는 지 확인

Enter 키를 누르면 Task 추가 함수가 불러지는 지 확인

TDD 니깐 테스트 케이스 부터 추가한다

TaskInput-test.js 에 테스트 케이스 추가

import 'react-native';
import React from 'react';
import {render, fireEvent, cleanup} from '@testing-library/react-native';

import TaskInput from '../TaskInput';

describe('TaskInput Component Rendering', () => {
  let wrapper;
  let props;

  beforeEach(() => {
    props = {};
    wrapper = render(<TaskInput {...props} />);
  });
  afterEach(cleanup);

  it('should render placeholder', () => {
    expect(wrapper.getByPlaceholderText('+ Add a Task')).toBeTruthy();
    expect(wrapper.getByPlaceholderText('+ Add a Task')).toBeEnabled();
  });
});

describe('TaskInput Component Interaction', () => {
  let wrapper;
  let props;
  const inputText = 'Build a React Native App';

  beforeEach(() => {
    props = {
      value: '',
      onChangeText: jest.fn(),
      onSubmitEditing: jest.fn(),
    };
    wrapper = render(<TaskInput {...props} />);
  });
  afterEach(cleanup);

  it('Check Input Value empty', () => {
    const element = wrapper.getByPlaceholderText('+ Add a Task');
    expect(element.props.value).toBe('');
  });

  it('Should call onChangeText when typing', () => {
    const element = wrapper.getByPlaceholderText('+ Add a Task');
    fireEvent.changeText(element, inputText);
    expect(element.props.onChangeText).toHaveBeenCalledTimes(1);
  });

  it('Should change input value when typing', () => {
    const element = wrapper.getByPlaceholderText('+ Add a Task');
    fireEvent.changeText(element, inputText);
    expect(element.props.onChangeText).toBeCalledWith(inputText);
  });
});
  • wrapper, props 는 예전에 enzyme 에서 사용하던 형식으로 변경
  • 랜더링 되는지
  • 초기값이 '' 인지
  • 값을 입력하면 onChangeText 함수가 호출되는지
  • 값을 입력하면 onChangeText 함수로 값이 제대로 전달되는지

테스트 진행하면 당연히 싹 실패

랜더링만 성공이고 전부 실패

왜냐면 TaskInput 에서 props 를 정의 하지 않아서 값을 받을 수가 없어요

그럼 이제 TaskInput.jsx 수정

value 하나 추가하니 1개 테스트 추가 성공

value 추가하고 테스트 = > 성공

onChangeText 를 TaskInput 에 props 추가 하고 테스트 => 성공

 

입력 버튼을 안 만들 거라서 Enter 치면 입력되도록 테스트 케이스를 추가한다

React Native Testing Library 에는 key Down, key Press 라는 개념이 없다 (엔터도 안드로이드, iOS 다르다)

onSubmitEditing 이벤트들 바로 호출해야 한다

  it('Should call onSubmitEditing when pressing enter', () => {
    const element = wrapper.getByPlaceholderText('+ Add a Task');
    fireEvent.changeText(element, inputText);
    fireEvent(element, 'onSubmitEditing');
    expect(element.props.onSubmitEditing).toHaveBeenCalledTimes(1);
  });

TaskInput 에 value, onChangeText, onSubmitEditing 을 추가해주니

const TaskInput = ({value, onChangeText, onSubmitEditing}) => {
  return (
    <TextInput
      value={value}
      onChangeText={onChangeText}
      onSubmitEditing={onSubmitEditing}
      style={styles.taskInput}
      placeholder="+ Add a Task"
    />
  );
};

깔끔하게 모든 테스트 통과

 

이제 컴포넌트 단위 테스트는 통과되었으니

coverage 한번 찍고 간다

HomeScreen 에 변경된 TaskInput 을 적용한다

HomeScreen-test 를 만들어준다

import 'react-native';
import React from 'react';
import {render, fireEvent, cleanup} from '@testing-library/react-native';

import HomeScreen from '../HomeScreen';

describe('HomeScreen Component Rendering', () => {
  let wrapper;
  let props;
  const inputText = 'Build a React Native App';

  beforeEach(() => {
    props = {};
    wrapper = render(<HomeScreen {...props} />);
  });

  afterEach(cleanup);

  it('should render Title', () => {
    expect(wrapper.getByText('Todo TDD')).toBeTruthy();
  });
  it('should add a new task', async () => {
    const element = wrapper.getByPlaceholderText('+ Add a Task');
    fireEvent.changeText(element, inputText);
    fireEvent(element, 'onSubmitEditing');
    await expect(wrapper.getByText(inputText)).toBeTruthy();
  });
});

title 이 잘 나오는지

그리고 Task 를 추가하면 화면에 나오는지 테스트 케이스를 추가한다

 

테스트 케이스를 통과할 수 있게 HomeScreen 에 기능을 수정한다

//HomeScreen.jsx
import React from 'react';

import Title from '../components/Title';
import TaskInput from '../components/TaskInput';
import TaskList from '../components/TaskList';
import shortid from 'shortid';

const initialData = [
  {id: shortid.generate(), subject: 'Learn React Native'},
  {id: shortid.generate(), subject: 'Create a React Native app'},
];

export default function App() {
  const [data, setData] = React.useState(initialData);
  const [newTask, setNewTask] = React.useState('');

  const handleInputTextChange = text => {
    setNewTask(text);
  };

  const handleAddTask = () => {
    setData([...data, {id: shortid.generate(), subject: newTask}]);
    setNewTask('');
  };

  return (
    <>
      <Title title="Todo TDD" />
      <TaskInput
        value={newTask}
        onChangeText={handleInputTextChange}
        onSubmitEditing={handleAddTask}
      />
      <TaskList data={data} />
    </>
  );
}

useState 로 전체 Task 를 관리하는 data 와 새로 입력되는 Task 인 newTask 를 추가하고

TaskInput 에서 Change 와 Submit 이벤트로 사용할 handle 함수를 만들어 주었다

그리고, TaskList 에 data 로 useState 로 만든 data 를 연결해주었다

 

테스트 전부 통과. Add a Task 로 추가하면 리스트에 적용

반응형