11import CssBaseline from '@mui/material/CssBaseline' ;
22import { ThemeProvider , createTheme } from '@mui/material/styles' ;
3- import { render , screen , within , act , fireEvent , RenderResult , waitFor } from '@testing-library/react' ;
3+ import {
4+ render ,
5+ screen ,
6+ within ,
7+ act ,
8+ fireEvent ,
9+ RenderResult ,
10+ waitFor ,
11+ } from '@testing-library/react' ;
412import { UserEvent , userEvent } from '@testing-library/user-event' ;
513import { http , HttpResponse } from 'msw' ;
614import { SnackbarProvider } from 'notistack' ;
715import { ReactElement } from 'react' ;
816
917import App from '../App' ;
1018import { server } from '../setupTests' ;
11- import { Event } from '../types' ;
19+ import { Event , EventForm } from '../types' ;
1220
1321const renderApp = ( ) => {
1422 const theme = createTheme ( ) ;
@@ -22,35 +30,97 @@ const renderApp = () => {
2230 ) ;
2331} ;
2432
25- describe ( '일정 CRUD 및 기본 기능' , ( ) => {
26- it . only ( '입력한 새로운 일정 정보에 맞춰 모든 필드가 이벤트 리스트에 정확히 저장된다.' , async ( ) => {
27- renderApp ( ) ;
33+ async function clearEvent ( ) {
34+ fireEvent . change ( screen . getByLabelText ( '제목' ) , { target : { value : '' } } ) ;
35+ fireEvent . change ( screen . getByLabelText ( '날짜' ) , { target : { value : '' } } ) ;
36+ fireEvent . change ( screen . getByLabelText ( '설명' ) , { target : { value : '' } } ) ;
37+ fireEvent . change ( screen . getByLabelText ( '시작 시간' ) , { target : { value : '' } } ) ;
38+ fireEvent . change ( screen . getByLabelText ( '종료 시간' ) , { target : { value : '' } } ) ;
39+ }
40+
41+ async function createEvent ( { title, date, description, startTime, endTime } : Partial < EventForm > ) {
42+ fireEvent . change ( screen . getByLabelText ( '제목' ) , { target : { value : title } } ) ;
43+ fireEvent . change ( screen . getByLabelText ( '날짜' ) , { target : { value : date } } ) ;
44+ fireEvent . change ( screen . getByLabelText ( '설명' ) , { target : { value : description } } ) ;
45+ fireEvent . change ( screen . getByLabelText ( '시작 시간' ) , { target : { value : startTime } } ) ;
46+ fireEvent . change ( screen . getByLabelText ( '종료 시간' ) , { target : { value : endTime } } ) ;
47+
48+ await fireEvent . click ( screen . getByTestId ( 'event-submit-button' ) ) ;
2849
29- fireEvent . change ( screen . getByLabelText ( '제목' ) , { target : { value : '테스트 - 새 회의' } } ) ;
30- fireEvent . change ( screen . getByLabelText ( '날짜' ) , { target : { value : '2025-08-01' } } ) ;
31- fireEvent . change ( screen . getByLabelText ( '설명' ) , { target : { value : '테스트 - 설명' } } ) ;
32- fireEvent . change ( screen . getByLabelText ( '시작 시간' ) , { target : { value : '17:00' } } ) ;
33- fireEvent . change ( screen . getByLabelText ( '종료 시간' ) , { target : { value : '18:00' } } ) ;
50+ clearEvent ( ) ;
51+ }
3452
35- await fireEvent . click (
36- screen . getByTestId ( 'event-submit-button' )
37- ) ;
53+ async function updateEvent ( { title, date, description, startTime, endTime } : Partial < EventForm > ) {
54+ fireEvent . click ( screen . getByLabelText ( 'Edit event' ) ) ;
3855
39- await waitFor ( ( ) => {
40- screen . getByTestId ( 'event-list' ) ;
41- } )
56+ fireEvent . change ( screen . getByLabelText ( '제목' ) , { target : { value : title } } ) ;
57+ date && fireEvent . change ( screen . getByLabelText ( '날짜' ) , { target : { value : date } } ) ;
58+ description && fireEvent . change ( screen . getByLabelText ( '설명' ) , { target : { value : description } } ) ;
59+ startTime && fireEvent . change ( screen . getByLabelText ( '시작 시간' ) , { target : { value : startTime } } ) ;
60+ endTime && fireEvent . change ( screen . getByLabelText ( '종료 시간' ) , { target : { value : endTime } } ) ;
4261
43- const eventList = within ( screen . getByTestId ( 'event-list' ) ) ;
62+ await fireEvent . click ( screen . getByTestId ( 'event-submit-button' ) ) ;
63+
64+ clearEvent ( ) ;
65+ }
66+
67+ describe . only ( '일정 CRUD 및 기본 기능' , ( ) => {
68+ it ( '입력한 새로운 일정 정보에 맞춰 모든 필드가 이벤트 리스트에 정확히 저장된다.' , async ( ) => {
69+ renderApp ( ) ;
70+
71+ // 기존 회의 날짜로 이동
72+ fireEvent . click ( screen . getByLabelText ( 'Next' ) ) ;
73+ fireEvent . click ( screen . getByLabelText ( 'Next' ) ) ;
74+
75+ await createEvent ( {
76+ title : '테스트 - 새 회의' ,
77+ date : '2025-10-16' ,
78+ description : '테스트 - 설명' ,
79+ startTime : '17:00' ,
80+ endTime : '18:00' ,
81+ } ) ;
82+
83+ const eventList = within ( await screen . findByTestId ( 'event-list' ) ) ;
4484 expect ( eventList . getByText ( '테스트 - 새 회의' ) ) . toBeInTheDocument ( ) ;
45- expect ( eventList . getByText ( '2025-08-01 ' ) ) . toBeInTheDocument ( ) ;
85+ expect ( eventList . getByText ( '2025-10-16 ' ) ) . toBeInTheDocument ( ) ;
4686 expect ( eventList . getByText ( '테스트 - 설명' ) ) . toBeInTheDocument ( ) ;
4787
88+ // TODO: 구현에 몇가지 validation 을 넣어서 더 안정적으로 바꾸기
4889 // ! HINT. event를 추가 제거하고 저장하는 로직을 잘 살펴보고, 만약 그대로 구현한다면 어떤 문제가 있을 지 고민해보세요.
4990 } ) ;
5091
51- it ( '기존 일정의 세부 정보를 수정하고 변경사항이 정확히 반영된다' , async ( ) => { } ) ;
92+ it ( '기존 일정의 세부 정보를 수정하고 변경사항이 정확히 반영된다' , async ( ) => {
93+ renderApp ( ) ;
94+
95+ // 기존 회의 날짜로 이동
96+ fireEvent . click ( screen . getByLabelText ( 'Next' ) ) ;
97+ fireEvent . click ( screen . getByLabelText ( 'Next' ) ) ;
5298
53- it ( '일정을 삭제하고 더 이상 조회되지 않는지 확인한다' , async ( ) => { } ) ;
99+ const eventList = within ( await screen . findByTestId ( 'event-list' ) ) ;
100+ expect ( eventList . getByText ( '기존 회의' ) ) . toBeInTheDocument ( ) ;
101+
102+ await updateEvent ( { title : '바뀐 회의' } ) ;
103+
104+ const eventListAfterUpdate = within ( await screen . findByTestId ( 'event-list' ) ) ;
105+ expect ( eventListAfterUpdate . getByText ( '바뀐 회의' ) ) . toBeInTheDocument ( ) ;
106+ } ) ;
107+
108+ it ( '일정을 삭제하고 더 이상 조회되지 않는지 확인한다' , async ( ) => {
109+ renderApp ( ) ;
110+
111+ // 기존 회의 날짜로 이동
112+ fireEvent . click ( screen . getByLabelText ( 'Next' ) ) ;
113+ fireEvent . click ( screen . getByLabelText ( 'Next' ) ) ;
114+
115+ const eventList = within ( await screen . findByTestId ( 'event-list' ) ) ;
116+ expect ( eventList . getByText ( '기존 회의' ) ) . toBeInTheDocument ( ) ;
117+
118+ await fireEvent . click ( screen . getByLabelText ( 'Delete event' ) ) ;
119+
120+ const eventListAfterDelete = within ( await screen . findByTestId ( 'event-list' ) ) ;
121+ expect ( await eventListAfterDelete . queryByText ( '기존 회의' ) ) . toBeNull ( ) ;
122+ expect ( await eventListAfterDelete . getByText ( '검색 결과가 없습니다.' ) ) . toBeInTheDocument ( ) ;
123+ } ) ;
54124} ) ;
55125
56126describe ( '일정 뷰' , ( ) => {
0 commit comments