Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
7c43769
hard
jung-han Jul 12, 2025
e6a1d47
hard
jung-han Aug 9, 2025
70cadf1
msw 세팅
Yangs1s Aug 17, 2025
346c94c
Revert "msw 세팅"
Aug 17, 2025
1b5ce45
chore: eslint/js 패키지 설치
Aug 18, 2025
00d7819
test: getDaysInMonth 단위 테스트 추가
Aug 18, 2025
36e32a1
test: getWeekDates 단위 테스트 추가
Aug 18, 2025
2a9936f
test: getWeeksAtMonth 단위 테스트 추가
Aug 18, 2025
d1bd412
test: getEventsForDay 단위 테스트 추가
Aug 18, 2025
0b86f0e
test: formatWeek 단위 테스트 추가
Aug 18, 2025
3df88d9
test: formatMonth 테스트 코드 추가
Aug 18, 2025
b7703a4
test: isDateInRange 단위 테스트 추가
Aug 18, 2025
f3925fc
test: fillZero 단위 테스트 추가
Aug 18, 2025
9d87d60
test: formatDate 단위 테스트 추가
Aug 18, 2025
c7287b4
test: easy.eventOverlap 모든 단위테스트 작성
snaps-odin Aug 19, 2025
1cafe7a
test: easy.eventUtils 모든 단위 테스트 추가
snaps-odin Aug 19, 2025
2f2b711
Merge branch 'hard' of github.com:minjaeleee/front_6th_chapter3-1 int…
Aug 19, 2025
3f078f0
test: easy.fetchHolidays 단위 테스트 작성
Aug 19, 2025
38c7eec
test: easy.notificationUtils 모든 단위 테스트 작성
Aug 19, 2025
979d052
test: easy.timeValidatioon 단위 테스트 작성
Aug 19, 2025
c0911ff
test: useCalendarView 테스트 작성
Aug 20, 2025
fb52273
test: useSearch 테스트 작성
Aug 20, 2025
9109217
test: useEventOperation 테스트 작성
Aug 20, 2025
7dc04ce
test: handlersUtils - setupMockHandlerCreation 추가
Aug 20, 2025
69751c5
feat: handlersUtils - setupMockHandlerUpdating 함수 추가
Aug 20, 2025
e8a2347
test: useEventOperations 테스트 작성 - 업데이트 테스트 추가
Aug 20, 2025
b543733
test: handlersUtils - setupMockHandlerDeletion 함수 작성
Aug 20, 2025
aa58a2f
tesT: useEventOperation 테스트 - 삭제 추가
Aug 20, 2025
03b20d2
hard -> medium 변경
Aug 20, 2025
766d3bd
Merge branch 'hard' into medium
Aug 20, 2025
413e0ad
test: useEventOptionerats 하드 -> 미디움 난이도 변경에따라 handlersUtils 수정되어 내부 테…
snaps-odin Aug 21, 2025
888bf7d
test: useEventOperation 모든 테스트 작성
snaps-odin Aug 21, 2025
0bda80e
Merge branch 'medium' of github.com:minjaeleee/front_6th_chapter3-1 i…
Aug 21, 2025
e47129f
test: medium.useNotification 모든 테스트 작성
Aug 21, 2025
d9970a8
test: medium.integartion 통합 테스트 작성 완료
Aug 21, 2025
78f4e7c
lint: lint 에러 처리
Aug 21, 2025
204563d
refactor: vitest-preview 흔적 제거
Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"react-dom": "19.1.0"
},
"devDependencies": {
"@eslint/js": "^9.33.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.5.2",
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
onlyBuiltDependencies:
- '@swc/core'
- esbuild
- msw
7 changes: 6 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Notifications, ChevronLeft, ChevronRight, Delete, Edit, Close } from '@mui/icons-material';
import ChevronLeft from '@mui/icons-material/ChevronLeft';
import ChevronRight from '@mui/icons-material/ChevronRight';
import Close from '@mui/icons-material/Close';
import Delete from '@mui/icons-material/Delete';
import Edit from '@mui/icons-material/Edit';
import Notifications from '@mui/icons-material/Notifications';
import {
Alert,
AlertTitle,
Expand Down
45 changes: 45 additions & 0 deletions src/__mocks__/handlersUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,48 @@ export const setupMockHandlerDeletion = () => {
})
);
};

export const setupMockHandlerLoadingError = () => {
server.use(
http.get('/api/events', () => {
return new HttpResponse(null, { status: 500 });
})
);
};

export const setupMockHandlerSaveError = () => {
server.use(
http.get('/api/events', () => {
return HttpResponse.json({ events: [] });
}),
http.put('/api/events/:id', () => {
return new HttpResponse(null, { status: 404 });
})
);
};

export const setupMockHandlerDeleteError = () => {
const mockEvents: Event[] = [
{
id: '1',
title: '삭제할 이벤트',
date: '2025-10-15',
startTime: '09:00',
endTime: '10:00',
description: '삭제할 이벤트입니다',
location: '어딘가',
category: '기타',
repeat: { type: 'none', interval: 0 },
notificationTime: 10,
},
];

server.use(
http.get('/api/events', () => {
return HttpResponse.json({ events: mockEvents });
}),
http.delete('/api/events/:id', () => {
return new HttpResponse(null, { status: 500 });
})
);
};
138 changes: 129 additions & 9 deletions src/__tests__/hooks/easy.useCalendarView.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,141 @@ import { useCalendarView } from '../../hooks/useCalendarView.ts';
import { assertDate } from '../utils.ts';

describe('초기 상태', () => {
it('view는 "month"이어야 한다', () => {});
it('view는 "month"이어야 한다', () => {
const { result } = renderHook(() => useCalendarView());

it('currentDate는 오늘 날짜인 "2025-10-01"이어야 한다', () => {});
expect(result.current.view).toBe('month');
});

it('holidays는 10월 휴일인 개천절, 한글날, 추석이 지정되어 있어야 한다', () => {});
it('currentDate는 오늘 날짜여야 한다', () => {
const { result } = renderHook(() => useCalendarView());
const today = new Date();

assertDate(result.current.currentDate, today);
});

it('currentDate를 2025년 10월로 설정하면 해당 월의 휴일들이 로드되어야 한다', () => {
const { result } = renderHook(() => useCalendarView());

act(() => {
result.current.setCurrentDate(new Date(2025, 9, 1)); // 2025년 10월 1일
});

expect(result.current.holidays).toEqual({
'2025-10-03': '개천절',
'2025-10-05': '추석',
'2025-10-06': '추석',
'2025-10-07': '추석',
'2025-10-09': '한글날',
});
});
});

it("view를 'week'으로 변경 시 적절하게 반영된다", () => {
const { result } = renderHook(() => useCalendarView());

act(() => {
result.current.setView('week');
});

expect(result.current.view).toBe('week');
});

it('주간 뷰에서 다음으로 navigate시 다음주 7일 후 날짜로 지정이 된다', () => {
const { result } = renderHook(() => useCalendarView());

act(() => {
result.current.setView('week');
});

act(() => {
result.current.navigate('next');
});

const expectedDate = new Date();
expectedDate.setDate(expectedDate.getDate() + 7);

assertDate(result.current.currentDate, expectedDate);
});

it("view를 'week'으로 변경 시 적절하게 반영된다", () => {});
it('주간 뷰에서 이전으로 navigate시 7일 전 날짜로 지정이 된다', () => {
const { result } = renderHook(() => useCalendarView());

it("주간 뷰에서 다음으로 navigate시 7일 후 '2025-10-08' 날짜로 지정이 된다", () => {});
const currentDate = new Date();

it("주간 뷰에서 이전으로 navigate시 7일 후 '2025-09-24' 날짜로 지정이 된다", () => {});
act(() => {
result.current.setCurrentDate(currentDate);
result.current.setView('week');
});

act(() => {
result.current.navigate('prev');
});

const expectedDate = new Date(currentDate);
expectedDate.setDate(expectedDate.getDate() - 7);

assertDate(result.current.currentDate, expectedDate);
});

it("월간 뷰에서 다음으로 navigate시 한 달 후 '2025-11-01' 날짜여야 한다", () => {});
it('월간 뷰에서 다음으로 navigate시 다음 달 첫째 날로 지정이 된다', () => {
const { result } = renderHook(() => useCalendarView());

it("월간 뷰에서 이전으로 navigate시 한 달 전 '2025-09-01' 날짜여야 한다", () => {});
const initialDate = new Date();

it("currentDate가 '2025-03-01' 변경되면 3월 휴일 '삼일절'로 업데이트되어야 한다", async () => {});
act(() => {
result.current.setCurrentDate(initialDate);
result.current.setView('month');
});

act(() => {
result.current.navigate('next');
});

const expectedDate = new Date(initialDate);
expectedDate.setMonth(expectedDate.getMonth() + 1);
expectedDate.setDate(1);

assertDate(result.current.currentDate, expectedDate);
});

it('월간 뷰에서 이전으로 navigate시 이전 달 첫째 날로 지정이 된다', () => {
const { result } = renderHook(() => useCalendarView());

const currentDate = new Date();

act(() => {
result.current.setCurrentDate(currentDate);
result.current.setView('month');
});

act(() => {
result.current.navigate('prev');
});

const expectedDate = new Date(currentDate);
expectedDate.setMonth(expectedDate.getMonth() - 1);
expectedDate.setDate(1);

assertDate(result.current.currentDate, expectedDate);
});

it('currentDate가 변경되면 해당 월의 휴일로 업데이트되어야 한다', () => {
const { result } = renderHook(() => useCalendarView());

act(() => {
result.current.setCurrentDate(new Date(2025, 2, 1)); // 2025-03-01
});

expect(result.current.holidays).toEqual({
'2025-03-01': '삼일절',
});

act(() => {
result.current.setCurrentDate(new Date(2025, 4, 1)); // 2025-05-01
});

expect(result.current.holidays).toEqual({
'2025-05-05': '어린이날',
});
});
101 changes: 96 additions & 5 deletions src/__tests__/hooks/easy.useSearch.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,105 @@
import { act, renderHook } from '@testing-library/react';

import { events } from '../../__mocks__/response/realEvents.json';
import { useSearch } from '../../hooks/useSearch.ts';
import { Event } from '../../types.ts';

it('검색어가 비어있을 때 모든 이벤트를 반환해야 한다', () => {});
it('검색어가 비어있을 때 모든 이벤트를 반환해야 한다', () => {
const mockEvents = events as Event[];
const currentDate = new Date(2025, 7, 20); // 2025-08-20
const { result } = renderHook(() => useSearch(mockEvents, currentDate, 'month'));

it('검색어에 맞는 이벤트만 필터링해야 한다', () => {});
expect(result.current.searchTerm).toBe('');
expect(result.current.filteredEvents).toHaveLength(5);
});

it('검색어가 제목, 설명, 위치 중 하나라도 일치하면 해당 이벤트를 반환해야 한다', () => {});
it('검색어에 맞는 이벤트만 필터링해야 한다', () => {
const mockEvents = events as Event[];
const currentDate = new Date(2025, 7, 20); // 2025-08-20
const { result } = renderHook(() => useSearch(mockEvents, currentDate, 'month'));

it('현재 뷰(주간/월간)에 해당하는 이벤트만 반환해야 한다', () => {});
act(() => {
result.current.setSearchTerm('회의');
});

it("검색어를 '회의'에서 '점심'으로 변경하면 필터링된 결과가 즉시 업데이트되어야 한다", () => {});
expect(result.current.searchTerm).toBe('회의');
expect(result.current.filteredEvents).toHaveLength(1);
expect(result.current.filteredEvents[0].title).toBe('팀 회의');
});

it('검색어가 제목, 설명, 위치 중 하나라도 일치하면 해당 이벤트를 반환해야 한다', () => {
const mockEvents = events as Event[];
const currentDate = new Date(2025, 7, 20); // 2025-08-20
const { result } = renderHook(() => useSearch(mockEvents, currentDate, 'month'));

// 제목 검색
act(() => {
result.current.setSearchTerm('점심');
});
expect(result.current.filteredEvents).toHaveLength(1);
expect(result.current.filteredEvents[0].title).toBe('점심 약속');

// 설명 검색
act(() => {
result.current.setSearchTerm('미팅');
});
expect(result.current.filteredEvents).toHaveLength(1);
expect(result.current.filteredEvents[0].title).toBe('팀 회의');

// 위치 검색
act(() => {
result.current.setSearchTerm('헬스장');
});
expect(result.current.filteredEvents).toHaveLength(1);
expect(result.current.filteredEvents[0].title).toBe('운동');
});

it('주간 뷰에서는 해당 주의 이벤트만 반환해야 한다', () => {
const mockEvents = events as Event[];
const currentDate = new Date(2025, 7, 20); // 2025-08-20 (수요일)
const { result } = renderHook(() => useSearch(mockEvents, currentDate, 'week'));

// 8월 20일이 포함된 주의 이벤트 (8/20, 8/21, 8/22)
expect(result.current.filteredEvents).toHaveLength(3);
const eventDates = result.current.filteredEvents.map((e) => e.date).sort();
expect(eventDates).toEqual(['2025-08-20', '2025-08-21', '2025-08-22']);
});

it('월간 뷰에서는 해당 달의 이벤트만 반환해야 한다', () => {
const mockEvents = events as Event[];
const currentDate = new Date(2025, 7, 15); // 2025-08-15
const { result } = renderHook(() => useSearch(mockEvents, currentDate, 'month'));

expect(result.current.filteredEvents).toHaveLength(5);
result.current.filteredEvents.forEach((event) => {
expect(event.date.startsWith('2025-08')).toBe(true);
});
});

it("검색어를 '회의'에서 '점심'으로 변경하면 필터링된 결과가 즉시 업데이트되어야 한다", () => {
const mockEvents = events as Event[];
const currentDate = new Date(2025, 7, 20); // 2025-08-20
const { result } = renderHook(() => useSearch(mockEvents, currentDate, 'month'));

expect(result.current.filteredEvents).toHaveLength(5);

// '회의' 검색
act(() => {
result.current.setSearchTerm('회의');
});
expect(result.current.filteredEvents).toHaveLength(1);
expect(result.current.filteredEvents[0].title).toBe('팀 회의');

// '점심'으로 변경
act(() => {
result.current.setSearchTerm('점심');
});
expect(result.current.filteredEvents).toHaveLength(1);
expect(result.current.filteredEvents[0].title).toBe('점심 약속');

// 빈 문자열로 변경
act(() => {
result.current.setSearchTerm('');
});
expect(result.current.filteredEvents).toHaveLength(5);
});
Loading
Loading