
강의 목표
강의시간에 학습한 내용을 정리합니다.
강의 내용 정리
강의시간에 학습한 내용을 정리합니다.
실습 - ToDoMVC 모델 테스트하기
- “jest” branch로 체크아웃
- /frameworkless 디렉토리로 이동하여 npm 모듈 설치
- /frameworkless/model 위치에 model.test.js 파일 생성 후 테스트 작성
내 코드
import createModel from "./model";
describe("model.js", () => {
let model;
beforeEach(() => {
model = createModel();
});
test("초기 상태 확인", () => {
const state = model.getState();
expect(state.todos).toEqual([]);
expect(state.currentFilter).toBe("All");
});
test("addItem 함수 - 새로운 항목 추가", () => {
model.addItem("new task");
const state = model.getState();
expect(state.todos).toHaveLength(1);
expect(state.todos[0].text).toBe("new task");
expect(state.todos[0].completed).toBe(false);
});
test("addItem 함수 - 빈 문자열 추가 시 무시", () => {
model.addItem("");
const state = model.getState();
expect(state.todos).toHaveLength(0);
});
test("updateItem 함수 - 항목 업데이트", () => {
model.addItem("task 1");
model.updateItem(0, "updated task");
const state = model.getState();
expect(state.todos[0].text).toBe("updated task");
});
test("updateItem 함수 - 유효하지 않은 인덱스 무시", () => {
model.addItem("task 1");
model.updateItem(-1, "invalid");
model.updateItem(99, "invalid");
const state = model.getState();
expect(state.todos[0].text).toBe("task 1");
});
test("deleteItem 함수 - 항목 삭제", () => {
model.addItem("task to delete");
model.deleteItem(0);
const state = model.getState();
expect(state.todos).toHaveLength(0);
});
test("deleteItem 함수 - 유효하지 않은 인덱스 무시", () => {
model.addItem("task 1");
model.deleteItem(-1);
model.deleteItem(99);
const state = model.getState();
expect(state.todos).toHaveLength(1);
});
test("toggleItemCompleted 함수 - 항목 완료 토글", () => {
model.addItem("task to toggle");
model.toggleItemCompleted(0);
let state = model.getState();
expect(state.todos[0].completed).toBe(true);
model.toggleItemCompleted(0);
state = model.getState();
expect(state.todos[0].completed).toBe(false);
});
test("completeAll 함수 - 모든 항목 완료", () => {
model.addItem("task 1");
model.addItem("task 2");
model.completeAll();
const state = model.getState();
state.todos.forEach((todo) => expect(todo.completed).toBe(true));
});
test("clearCompleted 함수 - 완료된 항목 제거", () => {
model.addItem("task 1");
model.addItem("task 2");
model.toggleItemCompleted(0);
model.clearCompleted();
const state = model.getState();
expect(state.todos).toHaveLength(1);
expect(state.todos[0].text).toBe("task 2");
});
test("changeFilter 함수 - 필터 변경", () => {
model.changeFilter("Completed");
const state = model.getState();
expect(state.currentFilter).toBe("Completed");
});
});
정답 코드
import modelFactory from './model.js'
describe('TodoMVC Model', () => {
test('data should be immutable', () => {
const model = modelFactory()
expect(() => {
model.getState().currentFilter = 'WRONG'
}).toThrow()
})
test('should add an item', () => {
const model = modelFactory()
model.addItem('dummy')
const { todos } = model.getState()
expect(todos.length).toBe(1)
expect(todos[0]).toEqual({
text: 'dummy',
completed: false
})
})
test('should not add an item when a falsy text is provided', () => {
const model = modelFactory()
model.addItem('')
model.addItem(undefined)
model.addItem(0)
model.addItem()
model.addItem(false)
const { todos } = model.getState()
expect(todos.length).toBe(0)
})
test('should update an item', () => {
const model = modelFactory({
todos: [{
text: 'dummy',
completed: false
}]
})
model.updateItem(0, 'new-dummy')
const { todos } = model.getState()
expect(todos[0].text).toBe('new-dummy')
})
test('should not update an item when an invalid index is provided', () => {
const model = modelFactory({
todos: [{
text: 'dummy',
completed: false
}]
})
model.updateItem(1, 'new-dummy')
const { todos } = model.getState()
expect(todos[0].text).toBe('dummy')
})
})
추가로 봐야할 자료
[JEST] 📚 모킹 Mocking 정리 - jest.fn / jest.mock /jest.spyOn
실습 1
- /frameworkless/view 위치에 filters.test.js 파일 생성 후 테스트 작성
- ‘filtersView()’ 함수에 넘겨줄 인자로 ‘targetElement’가 필요한데,
‘beforeEach’ hook에서 이 인자를 준비하고 세팅할 것
정답 코드
import filtersView from './filters.js'
let targetElement
const TEMPLATE = `<ul class="filters">
<li>
<a href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>`
const events = {
changeFilter: filter => {
model.changeFilter(filter)
render(model.getState())
}
}
describe('filtersView', () => {
beforeEach(() => {
const tempElement = document.createElement('div')
tempElement.innerHTML = TEMPLATE
targetElement = tempElement.childNodes[0]
})
test('should add the class "selected" to the anchor with the same text of the currentFilter', () => {
const newCounter = filtersView(targetElement, {
currentFilter: 'Active'
}, events)
const selectedItem = newCounter.querySelector('li a.selected')
expect(selectedItem.textContent).toBe('Active')
})
})
실습 2
- /frameworkless/view 위치에 counter.test.js 파일 생성 후 테스트 작성
- 새 DOM 요소에 완료되지 않은 TODO 수를 입력하도록 작성
- 단수형/복수형을 잘 구분해서 레이블이 표시되는지 검증
정답 코드
import counterView from './counter.js'
let targetElement
describe('counterView', () => {
beforeEach(() => {
targetElement = document.createElement('div')
})
test('should put the number of not completed todo in a new DOM elements', () => {
const newCounter = counterView(targetElement, {
todos: [
{
text: 'First',
completed: true
},
{
text: 'Second',
completed: false
},
{
text: 'Third',
completed: false
}
]
})
expect(newCounter.textContent).toBe('2 Items left')
})
test('should consider the singular form when only one item is left', () => {
const newCounter = counterView(targetElement, {
todos: [
{
text: 'First',
completed: true
},
{
text: 'Third',
completed: false
}
]
})
expect(newCounter.textContent).toBe('1 Item left')
})
})
실습 - 리액트 테스팅 라이브러리 실습
- 라이브러리 기본 API 문법 익히기 ( 1 )
- /components 디렉토리에 UpperInput.tsx 파일 추가
- /components 디렉토리에 UpperInput.test.jsx 파일 생성 후 테스트 작성
정답 코드
import * as React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import UpperInput from "./UpperInput";
test("sets the value to the upper version of the value", async () => {
// UpperInput 컴포넌트를 렌더링합니다.
render(<UpperInput />);
// input 요소를 찾습니다.
const upperInput = screen.getByLabelText(/upper/i);
// input 요소에 "stuff"를 입력합니다.
const text = "stuff";
fireEvent.change(upperInput, { target: { value: text } });
// input 요소의 값이 대문자로 변환되었는지 확인합니다.
expect(upperInput.value).toEqual(text.toUpperCase());
});
반응형
'교육 > 코드잇 스프린트 : 단기심화 5기' 카테고리의 다른 글
| [ 코드잇 스프린트 ] 교육기간 9일차 TIL (1) | 2024.11.21 |
|---|---|
| [ 코드잇 스프린트 ] 교육기간 7일차 TIL (1) | 2024.11.16 |
| [ 코드잇 스프린트 ] 교육기간 6일차 TIL (3) | 2024.11.15 |
| [ 코드잇 스프린트 ] 교육기간 5일차 TIL (1) | 2024.11.14 |
| [ 코드잇 스프린트 ] 교육기간 4일차 TIL (3) | 2024.11.13 |
