@@ -7,7 +7,9 @@ import com.benecia.lifetracker.test.api.RestDocsUtils.responsePreprocessor
77import com.benecia.lifetracker.todocore.model.command.ModifyTodo
88import com.benecia.lifetracker.todocore.model.command.NewTodo
99import com.benecia.lifetracker.todocore.model.info.CategoryInfo
10+ import com.benecia.lifetracker.todocore.model.info.CategoryStatisticsInfo
1011import com.benecia.lifetracker.todocore.model.info.TodoInfo
12+ import com.benecia.lifetracker.todocore.model.info.TodoStatisticsInfo
1113import com.benecia.lifetracker.todocore.service.TodoService
1214import io.mockk.every
1315import io.mockk.mockk
@@ -526,4 +528,67 @@ class TodoControllerTest : RestDocsTest() {
526528 ),
527529 )
528530 }
531+
532+ @Test
533+ fun getMonthlyStatistics () {
534+ val userId = UUID .randomUUID()
535+ val loginUser = createLoginUser(userId)
536+
537+ val stats = TodoStatisticsInfo (
538+ year = 2026 ,
539+ month = 3 ,
540+ totalCount = 10 ,
541+ doneCount = 7 ,
542+ pendingCount = 3 ,
543+ categoryBreakdown = listOf (
544+ CategoryStatisticsInfo (
545+ categoryId = 1L ,
546+ categoryName = " 개발" ,
547+ totalCount = 6 ,
548+ doneCount = 5 ,
549+ ),
550+ CategoryStatisticsInfo (
551+ categoryId = null ,
552+ categoryName = null ,
553+ totalCount = 4 ,
554+ doneCount = 2 ,
555+ ),
556+ ),
557+ )
558+ every { todoService.getMonthlyStatistics(userId, 2026 , 3 ) } returns stats
559+
560+ setupAuthentication(loginUser)
561+ given()
562+ .contentType(ContentType .JSON )
563+ .queryParam(" year" , 2026 )
564+ .queryParam(" month" , 3 )
565+ .get(" /api/v1/todos/statistics" )
566+ .then()
567+ .status(HttpStatus .OK )
568+ .apply (
569+ document(
570+ " getTodoStatistics" ,
571+ requestPreprocessor(),
572+ responsePreprocessor(),
573+ queryParameters(
574+ parameterWithName(" year" ).description(" 조회 연도" ),
575+ parameterWithName(" month" ).description(" 조회 월" ),
576+ ),
577+ responseFields(
578+ fieldWithPath(" status" ).type(JsonFieldType .NUMBER ).description(" HTTP 상태 코드" ),
579+ fieldWithPath(" message" ).type(JsonFieldType .STRING ).description(" 응답 메시지" ),
580+ fieldWithPath(" data.year" ).type(JsonFieldType .NUMBER ).description(" 조회 연도" ),
581+ fieldWithPath(" data.month" ).type(JsonFieldType .NUMBER ).description(" 조회 월" ),
582+ fieldWithPath(" data.totalCount" ).type(JsonFieldType .NUMBER ).description(" 전체 할 일 수" ),
583+ fieldWithPath(" data.doneCount" ).type(JsonFieldType .NUMBER ).description(" 완료된 할 일 수" ),
584+ fieldWithPath(" data.pendingCount" ).type(JsonFieldType .NUMBER ).description(" 미완료 할 일 수" ),
585+ fieldWithPath(" data.categoryBreakdown[].categoryId" ).type(JsonFieldType .NUMBER ).description(" 카테고리 ID (미분류는 null)" ).optional(),
586+ fieldWithPath(" data.categoryBreakdown[].categoryName" ).type(JsonFieldType .STRING ).description(" 카테고리 이름 (미분류는 null)" ).optional(),
587+ fieldWithPath(" data.categoryBreakdown[].totalCount" ).type(JsonFieldType .NUMBER ).description(" 카테고리별 전체 할 일 수" ),
588+ fieldWithPath(" data.categoryBreakdown[].doneCount" ).type(JsonFieldType .NUMBER ).description(" 카테고리별 완료된 할 일 수" ),
589+ fieldWithPath(" timestamp" ).type(JsonFieldType .STRING ).description(" 응답 생성 시간" ),
590+ ),
591+ ),
592+ )
593+ }
529594}
0 commit comments