From 4338fc8b3fbea8e1a7cbb79100ff1ad98f77aa50 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:48:04 +0900 Subject: [PATCH 01/14] =?UTF-8?q?:sparkles:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=EC=97=90=EC=84=9C=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90,=20=EB=B9=8C=EB=8D=94=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moment/auth/dto/request/AuthRequest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/dto/request/AuthRequest.java b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/dto/request/AuthRequest.java index 2d55043556..a9820f38e8 100644 --- a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/dto/request/AuthRequest.java +++ b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/dto/request/AuthRequest.java @@ -2,9 +2,7 @@ import jakarta.validation.constraints.NotEmpty; -import lombok.Getter; -import lombok.Setter; - +import lombok.*; public class AuthRequest { @@ -12,6 +10,7 @@ public class AuthRequest { //자체회원가입 폼 @Getter @Setter + @Builder public static class Login { private String email; @@ -23,6 +22,7 @@ public static class Login { @Getter @Setter + @Builder public static class SendCode { private String email; private String isSignUp; @@ -30,12 +30,18 @@ public static class SendCode { @Getter @Setter + @Builder + @AllArgsConstructor + @NoArgsConstructor public static class VerifyCode { private String code; } @Getter @Setter + @Builder + @AllArgsConstructor + @NoArgsConstructor public static class ChangePassword { private String code; From ae1481fc7a5c66f06013b7bc53fb527fea6b76ff Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:48:32 +0900 Subject: [PATCH 02/14] =?UTF-8?q?:sparkles:=20RestDocs=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EB=94=94=ED=8E=9C=EB=8D=98?= =?UTF-8?q?=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moment/moment-server/auth/build.gradle | 36 ++++++++++++ .../moment/moment-server/core/build.gradle | 57 ++++++++++++------- .../moment-server/scheduler/build.gradle | 1 + 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/backend/moment/moment-server/auth/build.gradle b/backend/moment/moment-server/auth/build.gradle index c0490b2a19..7978190401 100644 --- a/backend/moment/moment-server/auth/build.gradle +++ b/backend/moment/moment-server/auth/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.1.7' id 'io.spring.dependency-management' version '1.1.4' + id "org.asciidoctor.jvm.convert" version "3.3.2" } group = 'com.moment' @@ -15,6 +16,7 @@ configurations { compileOnly { extendsFrom annotationProcessor } + asciidoctorExt // asciidoctorExt에 대한 선언 } repositories { @@ -39,9 +41,15 @@ dependencies { implementation 'javax.xml.bind:jaxb-api:2.3.0' implementation 'commons-io:commons-io:2.11.0' implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1' + + testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.21.0' + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' // asciidoctorExt에 spring-restdocs-asciidoctor 의존성 추가 + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' // mockMvc 사용 + } ext { set('springCloudVersion', "2022.0.3") + snippetsDir = file('build/generated-snippets') // 스니펫이 생성되는 디렉터리 경로를 설정 } dependencyManagement { @@ -53,3 +61,31 @@ dependencyManagement { tasks.named('test') { useJUnitPlatform() } +asciidoctor { // Gradle이 asciidoctor Task를 수행하는 설정 (함수 선언) + configurations 'asciidoctorExt' // asciidoctor 확장 설정 + baseDirFollowsSourceFile() // .adoc 파일을 include 하면서 사용하기 위한 설정 + inputs.dir snippetsDir // 스니펫을 불러올 위치 설정 + dependsOn test // Gradle의 test Task 이후 asciidoctor를 수행 +} + +asciidoctor.doFirst { // asciidoctor Task가 수행될 때 가장 먼저 수행 + delete file('src/main/resources/static/docs') +} + +task copyDocument(type: Copy) { // 생성된 html 파일을 옮긴다 + dependsOn asciidoctor // Gradle의 asciidoctor Task 이후 수행 + from file("${asciidoctor.outputDir}") + into file("src/main/resources/static/docs") +} + +build { + dependsOn copyDocument // build 이후 html 파일 복사 +} + +bootJar { + dependsOn asciidoctor // asciidoctor 이후 bootJar 수행 + from ("${asciidoctor.outputDir}") { + into 'static/docs' + } + +} diff --git a/backend/moment/moment-server/core/build.gradle b/backend/moment/moment-server/core/build.gradle index 0fab742848..9a40d40afa 100644 --- a/backend/moment/moment-server/core/build.gradle +++ b/backend/moment/moment-server/core/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.1.7' id 'io.spring.dependency-management' version '1.1.4' + id "org.asciidoctor.jvm.convert" version "3.3.2" } group = 'com.moment' @@ -15,6 +16,7 @@ configurations { compileOnly { extendsFrom annotationProcessor } + asciidoctorExt // asciidoctorExt에 대한 선언 } repositories { @@ -31,30 +33,17 @@ dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.4' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' + testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.21.0' + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' // asciidoctorExt에 spring-restdocs-asciidoctor 의존성 추가 + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' // mockMvc 사용 + implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.12.4' + } ext { set('springCloudVersion', "2022.0.3") + snippetsDir = file('build/generated-snippets') // 스니펫이 생성되는 디렉터리 경로를 설정 } -//dependencies { -// compileOnly 'org.projectlombok:lombok' -// annotationProcessor 'org.projectlombok:lombok' -// testImplementation 'org.springframework.boot:spring-boot-starter-test' -// implementation 'org.springframework.boot:spring-boot-starter-web' -// implementation 'org.springframework.boot:spring-boot-starter-jdbc' -// implementation 'org.springframework.kafka:spring-kafka' -// runtimeOnly 'com.mysql:mysql-connector-j' -// implementation 'org.springframework.boot:spring-boot-starter-data-jpa' -// implementation 'org.springframework.boot:spring-boot-starter-actuator' -// // Eureka 서비스 디스커버리 -// implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' -// // Ribbon 로드 밸런싱 -// implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-ribbon', version: '2.2.6.RELEASE' -// // Hystrix 회로 차단기 -// implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-hystrix', version: '2.2.10.RELEASE' -// // Zipkin 분산 트레이싱 -// implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-zipkin', version: '2.2.8.RELEASE' -// implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-config', version: '4.0.4' -//} + dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" @@ -63,3 +52,31 @@ dependencyManagement { tasks.named('test') { useJUnitPlatform() } +asciidoctor { // Gradle이 asciidoctor Task를 수행하는 설정 (함수 선언) + configurations 'asciidoctorExt' // asciidoctor 확장 설정 + baseDirFollowsSourceFile() // .adoc 파일을 include 하면서 사용하기 위한 설정 + inputs.dir snippetsDir // 스니펫을 불러올 위치 설정 + dependsOn test // Gradle의 test Task 이후 asciidoctor를 수행 +} + +asciidoctor.doFirst { // asciidoctor Task가 수행될 때 가장 먼저 수행 + delete file('src/main/resources/static/docs') +} + +task copyDocument(type: Copy) { // 생성된 html 파일을 옮긴다 + dependsOn asciidoctor // Gradle의 asciidoctor Task 이후 수행 + from file("${asciidoctor.outputDir}") + into file("src/main/resources/static/docs") +} + +build { + dependsOn copyDocument // build 이후 html 파일 복사 +} + +bootJar { + dependsOn asciidoctor // asciidoctor 이후 bootJar 수행 + from ("${asciidoctor.outputDir}") { + into 'static/docs' + } + +} diff --git a/backend/moment/moment-server/scheduler/build.gradle b/backend/moment/moment-server/scheduler/build.gradle index de3bac29f8..920ece1c3e 100644 --- a/backend/moment/moment-server/scheduler/build.gradle +++ b/backend/moment/moment-server/scheduler/build.gradle @@ -34,6 +34,7 @@ dependencies { } ext { set('springCloudVersion', "2022.0.3") +// snippetsDir = file('build/generated-snippets') } dependencyManagement { From 32ec308cdd1b984155aaf1ea388bf5fdfae20a96 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:48:56 +0900 Subject: [PATCH 03/14] =?UTF-8?q?:sparkles:=20Delete=20Path=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/moment/core/controller/TripController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/TripController.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/TripController.java index a22c7d8cda..91fc9731ce 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/TripController.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/TripController.java @@ -57,7 +57,7 @@ public ResponseEntity> getAllTrip( } // 여행 삭제 - @DeleteMapping() + @DeleteMapping("/{tripId}") @Operation(summary = "여행 삭제", description = "여행을 삭제합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "성공"), @@ -66,7 +66,7 @@ public ResponseEntity> getAllTrip( }) public ResponseEntity deleteTrip( @RequestHeader Long userId, - @RequestParam Long tripId + @PathVariable Long tripId ) { userService.validateUserWithTrip(userId, tripId); tripService.delete(tripId); From 73fc7d03bd9cf02457e9eb2b123fb92bbdbda6b1 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:49:57 +0900 Subject: [PATCH 04/14] =?UTF-8?q?:sparkles:=20AlreadyBookedDate=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/docs/asciidoc/AlreadyBookedDate.adoc | 9 ++ .../AlreadyBookedDateControllerTest.java | 98 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 backend/moment/moment-server/core/src/docs/asciidoc/AlreadyBookedDate.adoc create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/controller/AlreadyBookedDateControllerTest.java diff --git a/backend/moment/moment-server/core/src/docs/asciidoc/AlreadyBookedDate.adoc b/backend/moment/moment-server/core/src/docs/asciidoc/AlreadyBookedDate.adoc new file mode 100644 index 0000000000..4e5d44018a --- /dev/null +++ b/backend/moment/moment-server/core/src/docs/asciidoc/AlreadyBookedDate.adoc @@ -0,0 +1,9 @@ +== AlreadyBookedDate +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 +=== 예약일 전부 조회 + +operation::alreadyBookedDate/getAll[snippets="http-request,request-headers,http-response,response-fields"] \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/AlreadyBookedDateControllerTest.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/AlreadyBookedDateControllerTest.java new file mode 100644 index 0000000000..1503c8e0aa --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/AlreadyBookedDateControllerTest.java @@ -0,0 +1,98 @@ +package com.moment.core.controller; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moment.core.dto.response.AlreadyBookedDateResponseDTO; +import com.moment.core.service.AlreadyBookedDateService; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.time.LocalDate; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureRestDocs +class AlreadyBookedDateControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private AlreadyBookedDateService alreadyBookedDateService; + + @InjectMocks + private AlreadyBookedDateController alreadyBookedDateController; + + @Test + void testGetAll() throws Exception { + // Mock 데이터 생성 + Long userId = 1L; + // 목업 객체 return + AlreadyBookedDateResponseDTO.GetCardView getCardView1 = AlreadyBookedDateResponseDTO.GetCardView.builder() + .bookedDate(LocalDate.now()) + .build(); + AlreadyBookedDateResponseDTO.GetCardView getCardView2 = AlreadyBookedDateResponseDTO.GetCardView.builder() + .bookedDate(LocalDate.of(2023, 10, 10)) + .build(); + AlreadyBookedDateResponseDTO.GetAllCardView mockResponseDTO = AlreadyBookedDateResponseDTO.GetAllCardView.builder() + .cardViews(List.of(getCardView1, getCardView2)) + .build(); + + + // Mock Service의 동작 설정 + when(alreadyBookedDateService.getAll(userId)).thenReturn(mockResponseDTO); + + // MockMvc를 사용하여 컨트롤러 호출 및 결과 검증 + mockMvc.perform(MockMvcRequestBuilders.get("/core/alreadyBookedDate/all") + .header("userId", String.valueOf(userId)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + // 추가적인 검증 필요시, JSON 응답을 파싱하여 내용을 검증할 수 있음 + //.andExpect(jsonPath("$.data").value(mockResponseDTO)) + .andDo( + document( + "alreadyBookedDate/getAll", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.cardViews[].bookedDate").type(JsonFieldType.STRING).description("예약된 날짜 목록") + ) + ) + ) + .andDo(print()); + + ; + + // 서비스가 정확히 호출되었는지 확인 + // verify(alreadyBookedDateService, times(1)).getAll(userId); + } +} From 6b9b5ed810bfcdcc47fef00ad1bcb63a8a5e6865 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:51:41 +0900 Subject: [PATCH 05/14] =?UTF-8?q?:sparkles:=20API=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=B4=20adoc=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/src/docs/asciidoc/Auth.adoc | 14 +++++++++++ .../auth/src/docs/asciidoc/index.adoc | 10 ++++++++ .../core/src/docs/asciidoc/Auth.adoc | 14 +++++++++++ .../core/src/docs/asciidoc/CardView.adoc | 24 +++++++++++++++++++ .../core/src/docs/asciidoc/Trip.adoc | 14 +++++++++++ .../core/src/docs/asciidoc/index.adoc | 13 ++++++++++ 6 files changed, 89 insertions(+) create mode 100644 backend/moment/moment-server/auth/src/docs/asciidoc/Auth.adoc create mode 100644 backend/moment/moment-server/auth/src/docs/asciidoc/index.adoc create mode 100644 backend/moment/moment-server/core/src/docs/asciidoc/Auth.adoc create mode 100644 backend/moment/moment-server/core/src/docs/asciidoc/CardView.adoc create mode 100644 backend/moment/moment-server/core/src/docs/asciidoc/Trip.adoc create mode 100644 backend/moment/moment-server/core/src/docs/asciidoc/index.adoc diff --git a/backend/moment/moment-server/auth/src/docs/asciidoc/Auth.adoc b/backend/moment/moment-server/auth/src/docs/asciidoc/Auth.adoc new file mode 100644 index 0000000000..95d9114c83 --- /dev/null +++ b/backend/moment/moment-server/auth/src/docs/asciidoc/Auth.adoc @@ -0,0 +1,14 @@ +== Auth +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 +=== 로그인 +operation::auth/login[snippets="http-request,request-body,request-fields,http-response,response-fields"] +=== 비밀번호 변경 +operation::auth/changePassword[snippets="http-request,request-headers,request-body,request-fields,http-response,response-fields"] +=== 인증코드 요청 +operation::auth/sendCode[snippets="http-request,request-body,request-fields,http-response,response-fields"] +=== 인증코드 확인 +operation::auth/verifyCode[snippets="http-request,request-headers,request-body,request-fields,http-response,response-fields"] \ No newline at end of file diff --git a/backend/moment/moment-server/auth/src/docs/asciidoc/index.adoc b/backend/moment/moment-server/auth/src/docs/asciidoc/index.adoc new file mode 100644 index 0000000000..80118729b2 --- /dev/null +++ b/backend/moment/moment-server/auth/src/docs/asciidoc/index.adoc @@ -0,0 +1,10 @@ +// index.adoc += Moment Application API Document +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 + +include::Auth.adoc[] + diff --git a/backend/moment/moment-server/core/src/docs/asciidoc/Auth.adoc b/backend/moment/moment-server/core/src/docs/asciidoc/Auth.adoc new file mode 100644 index 0000000000..95d9114c83 --- /dev/null +++ b/backend/moment/moment-server/core/src/docs/asciidoc/Auth.adoc @@ -0,0 +1,14 @@ +== Auth +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 +=== 로그인 +operation::auth/login[snippets="http-request,request-body,request-fields,http-response,response-fields"] +=== 비밀번호 변경 +operation::auth/changePassword[snippets="http-request,request-headers,request-body,request-fields,http-response,response-fields"] +=== 인증코드 요청 +operation::auth/sendCode[snippets="http-request,request-body,request-fields,http-response,response-fields"] +=== 인증코드 확인 +operation::auth/verifyCode[snippets="http-request,request-headers,request-body,request-fields,http-response,response-fields"] \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/docs/asciidoc/CardView.adoc b/backend/moment/moment-server/core/src/docs/asciidoc/CardView.adoc new file mode 100644 index 0000000000..38fbc5b122 --- /dev/null +++ b/backend/moment/moment-server/core/src/docs/asciidoc/CardView.adoc @@ -0,0 +1,24 @@ +== CardView +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 +=== 녹음본 업로드 +operation::cardView/uploadRecord[snippets="http-request,request-headers,request-part-uploadRecord-fields,http-response,response-fields"] + +=== 카드뷰 삭제 +operation::cardView/deleteRecord[snippets="http-request,request-headers,path-parameters,http-response,response-fields"] + +=== 여행파일ID로 카드뷰 전체 조회 +operation::cardView/getAllCardView[snippets="http-request,request-headers,http-response,response-fields"] + +=== 카드뷰 수정 +operation::cardView/updateRecord[snippets="http-request,request-headers,path-parameters,request-body,request-fields,http-response,response-fields"] + +=== 카드뷰 좋아요 누르기 +operation::cardView/likeCardView[snippets="http-request,request-headers,path-parameters,http-response,response-fields"] + +=== 좋아요 상태의 카드뷰 조회 +operation::cardView/getLikeCardView[snippets="http-request,request-headers,http-response,response-fields"] + diff --git a/backend/moment/moment-server/core/src/docs/asciidoc/Trip.adoc b/backend/moment/moment-server/core/src/docs/asciidoc/Trip.adoc new file mode 100644 index 0000000000..725ad8386f --- /dev/null +++ b/backend/moment/moment-server/core/src/docs/asciidoc/Trip.adoc @@ -0,0 +1,14 @@ +== Trip +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 +=== 여행 등록 +operation::trip/register[snippets="http-request,request-headers,request-body,request-fields,http-response,response-fields"] +=== 여행 목록 조회 +operation::trip/getAll[snippets="http-request,request-headers,http-response,response-fields"] +=== 여행 수정 +operation::trip/update[snippets="http-request,request-headers,request-body,request-fields,http-response,response-fields"] +=== 여행 삭제 +operation::trip/delete[snippets="http-request,request-headers,path-parameters,http-response,response-fields"] \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/docs/asciidoc/index.adoc b/backend/moment/moment-server/core/src/docs/asciidoc/index.adoc new file mode 100644 index 0000000000..02430cdd92 --- /dev/null +++ b/backend/moment/moment-server/core/src/docs/asciidoc/index.adoc @@ -0,0 +1,13 @@ +// index.adoc += Moment Application API Document +:doctype: book +:source-highlighter: highlightjs +:sectlinks: +:toc: left +:toclevels: 3 + +include::AlreadyBookedDate.adoc[] +include::CardView.adoc[] +include::Auth.adoc[] +include::Trip.adoc[] + From 81b38020ca49f19879cb90f5dab7a8e80d96919f Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:52:20 +0900 Subject: [PATCH 06/14] =?UTF-8?q?:sparkles:=20Auth=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B8=ED=8C=85=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moment/auth/config/RestDocsBasic.java | 47 +++++ .../auth/config/RestDocsConfiguration.java | 17 ++ .../auth/controller/AuthControllerTest.java | 197 ++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsBasic.java create mode 100644 backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsConfiguration.java create mode 100644 backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java diff --git a/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsBasic.java b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsBasic.java new file mode 100644 index 0000000000..cde034fb29 --- /dev/null +++ b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsBasic.java @@ -0,0 +1,47 @@ +package com.moment.auth.config; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.CharacterEncodingFilter; + +@Import(RestDocsConfiguration.class) +@ExtendWith(RestDocumentationExtension.class) +//@WebMvcTest(MemberController.class) +public class RestDocsBasic { + + @Autowired + MockMvc mvc; + + @Autowired + RestDocumentationResultHandler restDocs; + + @Autowired + ObjectMapper mapper; + + @BeforeEach + void setUp(WebApplicationContext context, RestDocumentationContextProvider provider){ + this.mvc= MockMvcBuilders.webAppContextSetup(context) + .apply(MockMvcRestDocumentation.documentationConfiguration(provider)) + .alwaysDo(MockMvcResultHandlers.print()) + .alwaysDo(restDocs) + .addFilters(new CharacterEncodingFilter("UTF-8",true)) + .build(); + } + + protected String createStringJson(Object dto) throws JsonProcessingException { + return mapper.writeValueAsString(dto); + } + +} diff --git a/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsConfiguration.java b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsConfiguration.java new file mode 100644 index 0000000000..60fce76049 --- /dev/null +++ b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/RestDocsConfiguration.java @@ -0,0 +1,17 @@ +package com.moment.auth.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.operation.preprocess.Preprocessors; + +@TestConfiguration +public class RestDocsConfiguration { + @Bean + public RestDocumentationResultHandler write() { + return MockMvcRestDocumentation.document("{class-name}/{method-name}", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint())); + } +} diff --git a/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java new file mode 100644 index 0000000000..efb9afeabf --- /dev/null +++ b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java @@ -0,0 +1,197 @@ +package com.moment.auth.controller; + +import com.moment.auth.domain.Role; +import com.moment.auth.dto.request.AuthRequest; +import com.moment.auth.dto.response.TokenResponseDTO; +import com.moment.auth.service.AuthService; +import io.swagger.v3.core.util.Json; +import jakarta.ws.rs.core.MediaType; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.http.RequestEntity.post; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureRestDocs +class AuthControllerTest { + @Autowired + MockMvc mockMvc; + + @MockBean + private AuthService authService; + + @InjectMocks + private AuthController authController; + + @Test + void login() throws Exception { + TokenResponseDTO.GetToken responseDTO = TokenResponseDTO.GetToken.builder() + .accessToken("accessToken") + .refreshToken("refresh") + .grantType("Bearer") + .role(Role.ROLE_AUTH_USER) + .build(); + + AuthRequest.Login login = AuthRequest.Login.builder() + .email("alexj99@naver.com") + .password("1234") + .build(); + + when(authService.login(any(AuthRequest.Login.class))).thenReturn(responseDTO); + + mockMvc.perform(RestDocumentationRequestBuilders.post("/auth/login") + .contentType(MediaType.APPLICATION_JSON) + .content(Json.pretty(login))) + .andExpect(status().isOk()) + .andDo(document("auth/login", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestFields( + fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"), + fieldWithPath("password").type(JsonFieldType.STRING).description("비밀번호") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.grantType").type(JsonFieldType.STRING).description("토큰 타입"), + fieldWithPath("data.accessToken").type(JsonFieldType.STRING).description("액세스 토큰"), + fieldWithPath("data.refreshToken").type(JsonFieldType.STRING).description("리프레시 토큰"), + fieldWithPath("data.role").type(JsonFieldType.STRING).description("사용자 권한") + + ) + )) + .andDo(print()); + } + + @Test + void sendCode() throws Exception { + TokenResponseDTO.GetTempToken tempToken = TokenResponseDTO.GetTempToken.builder() + .accessToken("accessToken") + .grantType("Bearer") + .role(Role.ROLE_AUTH_USER) + .userId(1L) + .build(); + + AuthRequest.SendCode sendCode = AuthRequest.SendCode.builder() + .email("alexj99@naver.com") + .isSignUp("true") + .build(); + + when(authService.sendCode(any(AuthRequest.SendCode.class))).thenReturn(tempToken); + + mockMvc.perform(RestDocumentationRequestBuilders.post("/auth/code") + .contentType(MediaType.APPLICATION_JSON) + .header("userId", 1L) + .content(Json.pretty(sendCode))) + .andExpect(status().isOk()) + .andDo(document("auth/sendCode", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestFields( + fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"), + fieldWithPath("isSignUp").type(JsonFieldType.STRING).description("회원가입 여부") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.grantType").type(JsonFieldType.STRING).description("토큰 타입"), + fieldWithPath("data.accessToken").type(JsonFieldType.STRING).description("액세스 토큰"), + fieldWithPath("data.role").type(JsonFieldType.STRING).description("사용자 권한"), + fieldWithPath("data.userId").type(JsonFieldType.NUMBER).description("사용자 ID") + ) + )) + .andDo(print()); + } + + @Test + void verifyCode() throws Exception { + AuthRequest.VerifyCode verifyCode = AuthRequest.VerifyCode.builder() + .code("1234") + .build(); + + Mockito.doNothing().when(authService).verifyCode(any(AuthRequest.VerifyCode.class), any()); + + mockMvc.perform(RestDocumentationRequestBuilders.patch("/auth/verify") + .contentType(MediaType.APPLICATION_JSON) + .header("userId", 1L) + .content(Json.pretty(verifyCode))) + .andExpect(status().isOk()) + .andDo(document("auth/verifyCode", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + requestFields( + fieldWithPath("code").type(JsonFieldType.STRING).description("인증 코드") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + )) + .andDo(print()); + } + + @Test + void changePassword() throws Exception { + AuthRequest.ChangePassword changePassword = AuthRequest.ChangePassword.builder() + .code("1234") + .newPassword("12345") + .build(); + + Mockito.doNothing().when(authService).changePassword(any(AuthRequest.ChangePassword.class), any()); + + mockMvc.perform(RestDocumentationRequestBuilders.patch("/auth/password") + .header("userId", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(Json.pretty(changePassword))) + .andExpect(status().isOk()) + .andDo(document("auth/changePassword", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + requestFields( + fieldWithPath("code").type(JsonFieldType.STRING).description("인증 코드"), + fieldWithPath("newPassword").type(JsonFieldType.STRING).description("새로운 비밀번호") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + )) + .andDo(print()); + } +} \ No newline at end of file From d86036b9b28d7d4be4e20fdbbdb92d2a279c5256 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:52:30 +0900 Subject: [PATCH 07/14] =?UTF-8?q?:sparkles:=20Auth=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B8=ED=8C=85=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/config/DocumentFormatGenerator.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/DocumentFormatGenerator.java diff --git a/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/DocumentFormatGenerator.java b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/DocumentFormatGenerator.java new file mode 100644 index 0000000000..a7e6066f16 --- /dev/null +++ b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/config/DocumentFormatGenerator.java @@ -0,0 +1,20 @@ +package com.moment.auth.config; + +import org.springframework.restdocs.snippet.Attributes; + +import static org.springframework.restdocs.snippet.Attributes.key; + +public interface DocumentFormatGenerator { + + static Attributes.Attribute getDateFormat() { // (2) + return key("format").value("yyyy-MM-dd"); + } + + static Attributes.Attribute getDateTimeFormat() { // (2) + return key("format").value("yyyy-MM-dd'T'HH:mm:ss"); + } + + static Attributes.Attribute getBooleanFormat() { // (3) + return key("format").value("true or false"); + } +} From 39d2d0f1071bc93e0e8b5f1d3140168b13fa8c87 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:52:54 +0900 Subject: [PATCH 08/14] =?UTF-8?q?:sparkles:=20core=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B8=ED=8C=85=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/config/DocumentFormatGenerator.java | 20 ++++++++ .../com/moment/core/config/RestDocsBasic.java | 48 +++++++++++++++++++ .../core/config/RestDocsConfiguration.java | 17 +++++++ 3 files changed, 85 insertions(+) create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/config/DocumentFormatGenerator.java create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsBasic.java create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsConfiguration.java diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/config/DocumentFormatGenerator.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/config/DocumentFormatGenerator.java new file mode 100644 index 0000000000..4ce53b6638 --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/config/DocumentFormatGenerator.java @@ -0,0 +1,20 @@ +package com.moment.core.config; + +import org.springframework.restdocs.snippet.Attributes; + +import static org.springframework.restdocs.snippet.Attributes.key; + +public interface DocumentFormatGenerator { + + static Attributes.Attribute getDateFormat() { // (2) + return key("format").value("yyyy-MM-dd"); + } + + static Attributes.Attribute getDateTimeFormat() { // (2) + return key("format").value("yyyy-MM-dd'T'HH:mm:ss"); + } + + static Attributes.Attribute getBooleanFormat() { // (3) + return key("format").value("true or false"); + } +} diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsBasic.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsBasic.java new file mode 100644 index 0000000000..42abbfb9d8 --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsBasic.java @@ -0,0 +1,48 @@ +package com.moment.core.config; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.CharacterEncodingFilter; + +@Import(RestDocsConfiguration.class) +@ExtendWith(RestDocumentationExtension.class) +//@WebMvcTest(MemberController.class) +public class RestDocsBasic { + + @Autowired + MockMvc mvc; + + @Autowired + RestDocumentationResultHandler restDocs; + + @Autowired + ObjectMapper mapper; + + @BeforeEach + void setUp(WebApplicationContext context, RestDocumentationContextProvider provider){ + this.mvc= MockMvcBuilders.webAppContextSetup(context) + .apply(MockMvcRestDocumentation.documentationConfiguration(provider)) + .alwaysDo(MockMvcResultHandlers.print()) + .alwaysDo(restDocs) + .addFilters(new CharacterEncodingFilter("UTF-8",true)) + .build(); + } + + protected String createStringJson(Object dto) throws JsonProcessingException { + return mapper.writeValueAsString(dto); + } + +} diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsConfiguration.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsConfiguration.java new file mode 100644 index 0000000000..7210b14b70 --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/config/RestDocsConfiguration.java @@ -0,0 +1,17 @@ +package com.moment.core.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.operation.preprocess.Preprocessors; + +@TestConfiguration +public class RestDocsConfiguration { + @Bean + public RestDocumentationResultHandler write() { + return MockMvcRestDocumentation.document("{class-name}/{method-name}", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint())); + } +} From 4dfaba21721716f09bc3e496e179f7843ebfe044 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:53:20 +0900 Subject: [PATCH 09/14] =?UTF-8?q?:sparkles:=20CardView=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CardViewControllerTest.java | 452 ++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/controller/CardViewControllerTest.java diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/CardViewControllerTest.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/CardViewControllerTest.java new file mode 100644 index 0000000000..7d83bb35f8 --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/CardViewControllerTest.java @@ -0,0 +1,452 @@ +package com.moment.core.controller; + +import com.moment.core.dto.request.CardViewRequestDTO; +import com.moment.core.dto.response.CardViewResponseDTO; +import com.moment.core.service.CardViewService; +import com.moment.core.service.UserService; +import io.swagger.v3.core.util.Json; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; + +import static com.moment.core.config.DocumentFormatGenerator.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; + + +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureRestDocs +class CardViewControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private CardViewService cardViewService; + @MockBean + private UserService userService; + + @InjectMocks + private CardViewController cardViewController; + + @Test + void uploadRecord() throws Exception { + // given + Long userId = 1L; + String jsonStr = "{\n" + + " \"location\": \"서울\",\n" + + " \"recordedAt\": \"2024-02-08T14:30:00\",\n" + + " \"temperature\": \"20\",\n" + + " \"weather\": \"맑음\",\n" + + " \"question\": \"질문\"\n" + + "}"; + MockMultipartFile recordFile = new MockMultipartFile("recordFile", "test.mp3", "audio/mp3", "test".getBytes()); + MockMultipartFile uploadRecord = new MockMultipartFile("uploadRecord", "", "application/json", jsonStr.getBytes()); + CardViewResponseDTO.GetCardView mockResponseDto = CardViewResponseDTO.GetCardView.builder() + .Id(1L) + .tripFileId(1L) + .recordFileName("test.mp3") + .recordFileUrl("http://localhost:8080/") + .location("서울") + .recordFileLength(100L) + .recordedAt(LocalDateTime.parse("2024-02-08T14:30:00")) + .temperature("20") + .weather("맑음") + .stt("test") + .happy(0.1f) + .angry(0.1f) + .neutral(0.1f) + .isLoved(true) + .sad(0.1f) + .recordFileStatus("WAIT") + .question("질문") + .build(); + + when(cardViewService.uploadRecord(any(CardViewRequestDTO.UploadRecord.class), any(), eq(userId))).thenReturn(mockResponseDto); + + + ResultActions result = mockMvc.perform(MockMvcRequestBuilders.multipart("/core/cardView/upload") + .file(recordFile) + .file(uploadRecord) +// .param("uploadRecord", jsonStr) + .header("userId", String.valueOf(userId)) + .contentType("multipart/form-data")); + + result.andExpect(status().isOk()) + .andDo( + document("cardView/uploadRecord", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + requestPartFields("uploadRecord", + fieldWithPath("location").type(JsonFieldType.STRING).description("녹음본 장소"), + fieldWithPath("recordedAt").type(JsonFieldType.STRING).attributes(getDateTimeFormat()).description("녹음 시점"), + fieldWithPath("temperature").type(JsonFieldType.STRING).description("온도"), + fieldWithPath("weather").type(JsonFieldType.STRING).description("날씨"), + fieldWithPath("question").type(JsonFieldType.STRING).description("질문") + ), + requestParts( + partWithName("recordFile").description("녹음 파일"), + partWithName("uploadRecord").description("녹음 정보") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.id").type(JsonFieldType.NUMBER).description("cardView ID"), + fieldWithPath("data.tripFileId").type(JsonFieldType.NUMBER).description("tripFile ID"), + fieldWithPath("data.recordedAt").type(JsonFieldType.STRING).attributes(getDateTimeFormat()).description("녹음 시점"), + fieldWithPath("data.recordFileName").type(JsonFieldType.STRING).description("파일이름"), + fieldWithPath("data.recordFileUrl").type(JsonFieldType.STRING).description("파일 저장 위치"), + fieldWithPath("data.location").type(JsonFieldType.STRING).description("위치"), + fieldWithPath("data.recordFileLength").type(JsonFieldType.NUMBER).description("파일길이"), + fieldWithPath("data.weather").type(JsonFieldType.STRING).description("날씨"), + fieldWithPath("data.temperature").type(JsonFieldType.STRING).description("온도"), + fieldWithPath("data.stt").type(JsonFieldType.STRING).description("STT"), + fieldWithPath("data.happy").type(JsonFieldType.NUMBER).description("기쁨"), + fieldWithPath("data.sad").type(JsonFieldType.NUMBER).description("슬픔"), + fieldWithPath("data.angry").type(JsonFieldType.NUMBER).description("화남"), + fieldWithPath("data.neutral").type(JsonFieldType.NUMBER).description("중립"), + fieldWithPath("data.question").type(JsonFieldType.STRING).description("질문"), + fieldWithPath("data.loved").type(JsonFieldType.BOOLEAN).description("즐겨찾기"), + fieldWithPath("data.recordFileStatus").type(JsonFieldType.STRING).description("분석 상태") + ) + ) + ) + .andDo(print()); + // then + } + + @Test + void getAllCardView() throws Exception { + CardViewResponseDTO.GetCardView mockResponseDto1 = CardViewResponseDTO.GetCardView.builder() + .Id(1L) + .tripFileId(1L) + .recordFileName("test.mp3") + .recordFileUrl("http://localhost:8080/") + .location("서울") + .recordFileLength(100L) + .recordedAt(LocalDateTime.parse("2024-02-08T14:30:00")) + .temperature("20") + .weather("맑음") + .stt("test") + .happy(0.1f) + .angry(0.1f) + .neutral(0.1f) + .isLoved(true) + .sad(0.1f) + .recordFileStatus("WAIT") + .question("질문") + .build(); + + CardViewResponseDTO.GetCardView mockResponseDto2 = CardViewResponseDTO.GetCardView.builder() + .Id(2L) + .tripFileId(1L) + .recordFileName("test.mp3") + .recordFileUrl("http://localhost:8080/") + .location("서울") + .recordFileLength(100L) + .recordedAt(LocalDateTime.parse("2024-02-08T15:30:00")) + .temperature("20") + .weather("맑음") + .stt("test") + .happy(0.1f) + .angry(0.1f) + .neutral(0.1f) + .isLoved(false) + .sad(0.1f) + .recordFileStatus("WAIT") + .question("질문") + .build(); + + List cardViews = List.of(mockResponseDto1, mockResponseDto2); + CardViewResponseDTO.GetAllCardView mockResponseDto = CardViewResponseDTO.GetAllCardView.builder() + .cardViews(cardViews) + .build(); + + Mockito.doNothing().when(userService).validateUserWithTripFile(any(), any()); + when(cardViewService.getAllCardView(any(), any())).thenReturn(mockResponseDto); + + ResultActions result = mockMvc.perform(RestDocumentationRequestBuilders.get("/core/cardView/all/{tripFileId}", 1L) + .header("userId", 1L) + .contentType(MediaType.APPLICATION_JSON) + ); + + result.andExpect(status().isOk()) + .andDo( + document("cardView/getAllCardView", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + pathParameters( + parameterWithName("tripFileId").description("여행 파일 ID") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.cardViews[].id").type(JsonFieldType.NUMBER).description("cardView ID"), + fieldWithPath("data.cardViews[].tripFileId").type(JsonFieldType.NUMBER).description("tripFile ID"), + fieldWithPath("data.cardViews[].recordedAt").type(JsonFieldType.STRING).attributes(getDateTimeFormat()).description("녹음 시점"), + fieldWithPath("data.cardViews[].recordFileName").type(JsonFieldType.STRING).description("파일이름"), + fieldWithPath("data.cardViews[].recordFileUrl").type(JsonFieldType.STRING).description("파일 저장 위치"), + fieldWithPath("data.cardViews[].location").type(JsonFieldType.STRING).description("위치"), + fieldWithPath("data.cardViews[].recordFileLength").type(JsonFieldType.NUMBER).description("파일길이"), + fieldWithPath("data.cardViews[].weather").type(JsonFieldType.STRING).description("날씨"), + fieldWithPath("data.cardViews[].temperature").type(JsonFieldType.STRING).description("온도"), + fieldWithPath("data.cardViews[].stt").type(JsonFieldType.STRING).description("STT"), + fieldWithPath("data.cardViews[].happy").type(JsonFieldType.NUMBER).description("기쁨"), + fieldWithPath("data.cardViews[].sad").type(JsonFieldType.NUMBER).description("슬픔"), + fieldWithPath("data.cardViews[].angry").type(JsonFieldType.NUMBER).description("화남"), + fieldWithPath("data.cardViews[].neutral").type(JsonFieldType.NUMBER).description("중립"), + fieldWithPath("data.cardViews[].question").type(JsonFieldType.STRING).description("질문"), + fieldWithPath("data.cardViews[].loved").type(JsonFieldType.BOOLEAN).description("즐겨찾기"), + fieldWithPath("data.cardViews[].recordFileStatus").type(JsonFieldType.STRING).description("분석 상태") + ) + ) + ) + .andDo(print()); + } + + @Test + void updateRecord() throws Exception { + Mockito.doNothing().when(userService).validateUserWithCardView(any(), any()); + Mockito.doNothing().when(cardViewService).updateRecord(any(Long.class), any(CardViewRequestDTO.UpdateRecord.class)); + + CardViewRequestDTO.UpdateRecord updateRecord = CardViewRequestDTO.UpdateRecord.builder() + .location("서울") + .stt("test") + .temperature("20") + .weather("맑음") + .question("질문") + .build(); + + ResultActions result = mockMvc.perform(RestDocumentationRequestBuilders.put("/core/cardView/{cardViewId}", 1L) + .header("userId", "1") + .contentType("application/json") + .content(Json.pretty(updateRecord)) + ); + + result.andExpect(status().isOk()) + .andDo( + document("cardView/updateRecord", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + pathParameters( + parameterWithName("cardViewId").description("카드뷰 ID") + ), + requestFields( + fieldWithPath("location").type(JsonFieldType.STRING).description("녹음본 장소"), + fieldWithPath("weather").type(JsonFieldType.STRING).description("날씨"), + fieldWithPath("temperature").type(JsonFieldType.STRING).description("온도"), + fieldWithPath("question").type(JsonFieldType.STRING).description("질문"), + fieldWithPath("stt").type(JsonFieldType.STRING).description("STT") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + ) + ) + .andDo(print()); + } + + @Test + void deleteRecord() throws Exception { + Mockito.doNothing().when(userService).validateUserWithCardView(any(), any()); + Mockito.doNothing().when(cardViewService).deleteRecord(any(Long.class)); + + ResultActions result = mockMvc.perform(RestDocumentationRequestBuilders.delete("/core/cardView/{cardViewId}", 1L) + .header("userId", "1") + .contentType("application/json") + ); + + result.andExpect(status().isOk()) + .andDo( + document("cardView/deleteRecord", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + pathParameters( + parameterWithName("cardViewId").description("카드뷰 ID") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + ) + ) + .andDo(print()); + } + + @Test + void likeCardView() throws Exception { + Mockito.doNothing().when(userService).validateUserWithCardView(any(), any()); + Mockito.doNothing().when(cardViewService).likeCardView(any(Long.class)); + + ResultActions result = mockMvc.perform(RestDocumentationRequestBuilders.put("/core/cardView/like/{cardViewId}", 1L) + .header("userId", "1") + .contentType("application/json") + ); + + result.andExpect(status().isOk()) + .andDo( + document("cardView/likeCardView", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + pathParameters( + parameterWithName("cardViewId").description("카드뷰 ID") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + ) + ) + .andDo(print()); + + } + + @Test + void getLikeCardView() throws Exception{ + CardViewResponseDTO.GetCardView mockResponseDto1 = CardViewResponseDTO.GetCardView.builder() + .Id(1L) + .tripFileId(1L) + .recordFileName("test.mp3") + .recordFileUrl("http://localhost:8080/") + .location("서울") + .recordFileLength(100L) + .recordedAt(LocalDateTime.parse("2024-02-08T14:30:00")) + .temperature("20") + .weather("맑음") + .stt("test") + .happy(0.1f) + .angry(0.1f) + .neutral(0.1f) + .isLoved(true) + .sad(0.1f) + .recordFileStatus("WAIT") + .question("질문") + .build(); + + CardViewResponseDTO.GetCardView mockResponseDto2 = CardViewResponseDTO.GetCardView.builder() + .Id(2L) + .tripFileId(1L) + .recordFileName("test.mp3") + .recordFileUrl("http://localhost:8080/") + .location("서울") + .recordFileLength(100L) + .recordedAt(LocalDateTime.parse("2024-02-08T15:30:00")) + .temperature("20") + .weather("맑음") + .stt("test") + .happy(0.1f) + .angry(0.1f) + .neutral(0.1f) + .isLoved(false) + .sad(0.1f) + .recordFileStatus("WAIT") + .question("질문") + .build(); + + List cardViews = List.of(mockResponseDto1, mockResponseDto2); + CardViewResponseDTO.GetAllCardView mockResponseDto = CardViewResponseDTO.GetAllCardView.builder() + .cardViews(cardViews) + .build(); + + when(cardViewService.getLikeCardView(any(Long.class))).thenReturn(mockResponseDto); + + ResultActions result = mockMvc.perform(RestDocumentationRequestBuilders.get("/core/cardView/like") + .header("userId", "1") + .contentType("application/json") + ); + + result.andExpect(status().isOk()) + .andDo( + document("cardView/getLikeCardView", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.cardViews[].id").type(JsonFieldType.NUMBER).description("cardView ID"), + fieldWithPath("data.cardViews[].tripFileId").type(JsonFieldType.NUMBER).description("tripFile ID"), + fieldWithPath("data.cardViews[].recordedAt").type(JsonFieldType.STRING).attributes(getDateTimeFormat()).description("녹음 시점"), + fieldWithPath("data.cardViews[].recordFileName").type(JsonFieldType.STRING).description("파일이름"), + fieldWithPath("data.cardViews[].recordFileUrl").type(JsonFieldType.STRING).description("파일 저장 위치"), + fieldWithPath("data.cardViews[].location").type(JsonFieldType.STRING).description("위치"), + fieldWithPath("data.cardViews[].recordFileLength").type(JsonFieldType.NUMBER).description("파일길이"), + fieldWithPath("data.cardViews[].weather").type(JsonFieldType.STRING).description("날씨"), + fieldWithPath("data.cardViews[].temperature").type(JsonFieldType.STRING).description("온도"), + fieldWithPath("data.cardViews[].stt").type(JsonFieldType.STRING).description("STT"), + fieldWithPath("data.cardViews[].happy").type(JsonFieldType.NUMBER).description("기쁨"), + fieldWithPath("data.cardViews[].sad").type(JsonFieldType.NUMBER).description("슬픔"), + fieldWithPath("data.cardViews[].angry").type(JsonFieldType.NUMBER).description("화남"), + fieldWithPath("data.cardViews[].neutral").type(JsonFieldType.NUMBER).description("중립"), + fieldWithPath("data.cardViews[].question").type(JsonFieldType.STRING).description("질문"), + fieldWithPath("data.cardViews[].loved").type(JsonFieldType.BOOLEAN).description("즐겨찾기"), + fieldWithPath("data.cardViews[].recordFileStatus").type(JsonFieldType.STRING).description("분석 상태") + ) + ) + ) + .andDo(print()); + } +} \ No newline at end of file From c05c5c76c9875a8b31072abdfdbc6460e2de192b Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:53:30 +0900 Subject: [PATCH 10/14] =?UTF-8?q?:sparkles:=20Trip=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/controller/TripControllerTest.java | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripControllerTest.java diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripControllerTest.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripControllerTest.java new file mode 100644 index 0000000000..46bb5d1ada --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripControllerTest.java @@ -0,0 +1,244 @@ +package com.moment.core.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moment.core.domain.trip.Trip; +import com.moment.core.dto.request.CardViewRequestDTO; +import com.moment.core.dto.request.TripRequestDTO; +import com.moment.core.dto.response.TripResponseDTO; +import com.moment.core.service.TripService; +import com.moment.core.service.UserService; +import io.swagger.v3.core.util.Json; +import jakarta.ws.rs.core.MediaType; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.time.LocalDate; +import java.util.List; + +import static com.moment.core.config.DocumentFormatGenerator.getDateFormat; +import static com.moment.core.config.DocumentFormatGenerator.getDateTimeFormat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static reactor.core.publisher.Mono.when; + +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureRestDocs +class TripControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private TripService tripService; + @MockBean + private UserService userService; + + @InjectMocks + private TripController tripController; + + + @Test + void registerTrip() throws Exception { + TripRequestDTO.RegisterTrip registerTrip = TripRequestDTO.RegisterTrip.builder() + .tripName("test") + .startDate(LocalDate.now()) + .endDate(LocalDate.now().plusDays(1)) + .build(); + Mockito.doNothing().when(tripService).register(any(TripRequestDTO.RegisterTrip.class), any(Long.class)); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/core/trip/register") + .header("userId", 1L) + .content(Json.pretty(registerTrip)) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)); + + resultActions.andExpect(status().isOk()) + .andDo( + document("trip/register", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + requestFields( + fieldWithPath("tripName").description("여행 이름"), + fieldWithPath("startDate").attributes(getDateFormat()).description("여행 시작 날짜"), + fieldWithPath("endDate").attributes(getDateFormat()).description("여행 종료 날짜") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + + ) + ) + .andDo(print()) + ; + } + + @Test + void getAllTrip() throws Exception{ + List tripList = List.of( + TripResponseDTO.GetTrip.builder() + .id(1L) + .email("test") + .startDate(LocalDate.now()) + .endDate(LocalDate.now().plusDays(1)) + .analyzingCount(0) + .tripName("test") + .build(), + TripResponseDTO.GetTrip.builder() + .id(2L) + .email("test") + .startDate(LocalDate.now()) + .endDate(LocalDate.now().plusDays(1)) + .analyzingCount(1) + .tripName("test") + .build(), + TripResponseDTO.GetTrip.builder() + .id(3L) + .email("test") + .startDate(LocalDate.now()) + .endDate(LocalDate.now().plusDays(1)) + .analyzingCount(2) + .tripName("test") + .build() + ); + TripResponseDTO.GetAllTrip allTrip = TripResponseDTO.GetAllTrip.builder() + .trips(tripList) + .build(); + Mockito.when(tripService.getAllTrip(any(Long.class))).thenReturn(allTrip); + + + mockMvc.perform(MockMvcRequestBuilders.get("/core/trip/all") + .header("userId", 1L) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo( + document("trip/getAll", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.trips[].id").type(JsonFieldType.NUMBER).description("여행 ID"), + fieldWithPath("data.trips[].email").type(JsonFieldType.STRING).description("유저 email"), + fieldWithPath("data.trips[].startDate").attributes(getDateFormat()).description("출발일"), + fieldWithPath("data.trips[].endDate").attributes(getDateFormat()).description("도착일"), + fieldWithPath("data.trips[].analyzingCount").type(JsonFieldType.NUMBER).description("분석 중 파일 개수"), + fieldWithPath("data.trips[].tripName").type(JsonFieldType.STRING).description("여행 이름") + ) + ) + ) + .andDo(print()); + } + + @Test + void deleteTrip() throws Exception{ + Mockito.doNothing().when(userService).validateUserWithTrip(any(Long.class), any(Long.class)); + Mockito.when(tripService.delete(any(Long.class))).thenReturn(new Trip()); + + mockMvc.perform(RestDocumentationRequestBuilders.delete("/core/trip/{tripId}", 1L) + .header("userId", 1L) + + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo( + document("trip/delete", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + pathParameters( + parameterWithName("tripId").description("삭제할 여행 ID") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + ) + ) + .andDo(print()); + + } + + @Test + void updateTrip() throws Exception { + TripRequestDTO.UpdateTrip updateTrip = TripRequestDTO.UpdateTrip.builder() + .tripId(1L) + .startDate(LocalDate.now()) + .endDate(LocalDate.now().plusDays(1)) + .tripName("test") + .build(); + Mockito.doNothing().when(userService).validateUserWithTrip(any(Long.class), any(Long.class)); + Mockito.doNothing().when(tripService).update(any(Long.class), any(TripRequestDTO.UpdateTrip.class)); + + mockMvc.perform(MockMvcRequestBuilders.put("/core/trip") + .header("userId", 1L) + .content(Json.pretty(updateTrip)) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo( + document("trip/update", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + requestFields( + fieldWithPath("tripId").type(JsonFieldType.NUMBER).description("여행 ID"), + fieldWithPath("startDate").attributes(getDateFormat()).description("출발일"), + fieldWithPath("endDate").attributes(getDateFormat()).description("도착일"), + fieldWithPath("tripName").type(JsonFieldType.STRING).description("여행 이름") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + ) + ) + .andDo(print()); + + } +} \ No newline at end of file From fbecfb6e5eca7d3d6ef72cfcbbaddcf06a51cead Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:53:38 +0900 Subject: [PATCH 11/14] =?UTF-8?q?:sparkles:=20TripFile=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/vcs.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..35eb1ddfbb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From b10ac0ece4c21b7e7c772c9e2b6b8cbfdc3f025c Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:53:40 +0900 Subject: [PATCH 12/14] =?UTF-8?q?:sparkles:=20TripFile=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TripFileControllerTest.java | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripFileControllerTest.java diff --git a/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripFileControllerTest.java b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripFileControllerTest.java new file mode 100644 index 0000000000..31b2096220 --- /dev/null +++ b/backend/moment/moment-server/core/src/test/java/com/moment/core/controller/TripFileControllerTest.java @@ -0,0 +1,175 @@ +package com.moment.core.controller; + +import com.moment.core.domain.trip.Trip; +import com.moment.core.dto.response.TripFileResponseDTO; +import com.moment.core.service.TripFileService; +import com.moment.core.service.TripService; +import com.moment.core.service.UserService; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.operation.preprocess.Preprocessors; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDate; +import java.util.List; + +import static com.moment.core.config.DocumentFormatGenerator.getDateFormat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureRestDocs +class TripFileControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private TripFileService tripFileService; + @MockBean + private TripService tripService; + @MockBean + private UserService userService; + + @InjectMocks + private TripFileController tripFileController; + + @Test + void getTripFiles() throws Exception { + List tripFiles = List.of( + TripFileResponseDTO.GetTripFile.builder() + .id(1L) + .tripId(1L) + .email("test") + .yearDate(LocalDate.now()) + .analyzingCount(1) + .build(), + TripFileResponseDTO.GetTripFile.builder() + .id(2L) + .tripId(2L) + .email("test") + .yearDate(LocalDate.now().plusDays(1)) + .analyzingCount(2) + .build(), + TripFileResponseDTO.GetTripFile.builder() + .id(3L) + .tripId(3L) + .email("test") + .yearDate(LocalDate.now().plusDays(2)) + .analyzingCount(1) + .build() + ); + TripFileResponseDTO.GetAllTripFile allTripFile = TripFileResponseDTO.GetAllTripFile.builder() + .tripFiles(tripFiles) + .build(); + + Mockito.when(tripFileService.getTripFiles(any(Long.class))).thenReturn(allTripFile); + Mockito.doNothing().when(userService).validateUserWithTrip(any(Long.class), any(Long.class)); + + mockMvc.perform(RestDocumentationRequestBuilders.get("/core/tripfile/{tripId}", 1L) + .header("userId", 1L) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andDo(document("tripfile/getTripFiles", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + pathParameters( + parameterWithName("tripId").description("여행 ID") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.tripFiles[].id").type(JsonFieldType.NUMBER).description("파일 ID"), + fieldWithPath("data.tripFiles[].tripId").type(JsonFieldType.NUMBER).description("여행 ID"), + fieldWithPath("data.tripFiles[].email").type(JsonFieldType.STRING).description("유저 email"), + fieldWithPath("data.tripFiles[].yearDate").type(JsonFieldType.STRING).attributes(getDateFormat()).description("연월일"), + fieldWithPath("data.tripFiles[].analyzingCount").type(JsonFieldType.NUMBER).description("분석 중 파일 개수") + ) + ) + ) + .andDo(print()); + } + + @Test + void getUntitledTripFiles() throws Exception { + List tripFiles = List.of( + TripFileResponseDTO.GetTripFile.builder() + .id(1L) + .tripId(1L) + .email("test") + .yearDate(LocalDate.now()) + .analyzingCount(1) + .build(), + TripFileResponseDTO.GetTripFile.builder() + .id(2L) + .tripId(2L) + .email("test") + .yearDate(LocalDate.now().plusDays(1)) + .analyzingCount(2) + .build(), + TripFileResponseDTO.GetTripFile.builder() + .id(3L) + .tripId(3L) + .email("test") + .yearDate(LocalDate.now().plusDays(2)) + .analyzingCount(1) + .build() + ); + TripFileResponseDTO.GetAllTripFile allTripFile = TripFileResponseDTO.GetAllTripFile.builder() + .tripFiles(tripFiles) + .build(); + Mockito.when(tripService.getUntitledTripById(any(Long.class))).thenReturn(new Trip()); + Mockito.when(tripFileService.getTripFiles(any())).thenReturn(allTripFile); + + mockMvc.perform(RestDocumentationRequestBuilders.get("/core/tripfile/untitled") + .header("userId", 1L) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andDo(document("tripfile/getUntitledTripFiles", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data.tripFiles[].id").type(JsonFieldType.NUMBER).description("파일 ID"), + fieldWithPath("data.tripFiles[].tripId").type(JsonFieldType.NUMBER).description("여행 ID"), + fieldWithPath("data.tripFiles[].email").type(JsonFieldType.STRING).description("유저 email"), + fieldWithPath("data.tripFiles[].yearDate").type(JsonFieldType.STRING).attributes(getDateFormat()).description("연월일"), + fieldWithPath("data.tripFiles[].analyzingCount").type(JsonFieldType.NUMBER).description("분석 중 파일 개수") + ) + ) + ) + .andDo(print()); + } +} \ No newline at end of file From ce2891d9437253b3feca89b4963cf671f4b0b949 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:53:55 +0900 Subject: [PATCH 13/14] =?UTF-8?q?:sparkles:=20Request-Field=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../restdocs/templates/request-fields.snippet | 11 +++++++++++ .../restdocs/templates/request-fields.snippet | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 backend/moment/moment-server/auth/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet create mode 100644 backend/moment/moment-server/core/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet diff --git a/backend/moment/moment-server/auth/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet b/backend/moment/moment-server/auth/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet new file mode 100644 index 0000000000..5a59aa878d --- /dev/null +++ b/backend/moment/moment-server/auth/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet @@ -0,0 +1,11 @@ +|=== +|필드명|타입|필수값|양식|설명 + +{{#fields}} +|{{#tableCellContent}}`+{{path}}+`{{/tableCellContent}} +|{{#tableCellContent}}`+{{type}}+`{{/tableCellContent}} +|{{#tableCellContent}}{{^optional}}true{{/optional}}{{/tableCellContent}} +|{{#tableCellContent}}{{#format}}{{.}}{{/format}}{{/tableCellContent}} +|{{#tableCellContent}}{{description}}{{/tableCellContent}} +{{/fields}} +|=== \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet b/backend/moment/moment-server/core/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet new file mode 100644 index 0000000000..5a59aa878d --- /dev/null +++ b/backend/moment/moment-server/core/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet @@ -0,0 +1,11 @@ +|=== +|필드명|타입|필수값|양식|설명 + +{{#fields}} +|{{#tableCellContent}}`+{{path}}+`{{/tableCellContent}} +|{{#tableCellContent}}`+{{type}}+`{{/tableCellContent}} +|{{#tableCellContent}}{{^optional}}true{{/optional}}{{/tableCellContent}} +|{{#tableCellContent}}{{#format}}{{.}}{{/format}}{{/tableCellContent}} +|{{#tableCellContent}}{{description}}{{/tableCellContent}} +{{/fields}} +|=== \ No newline at end of file From 3b4465a67208004463a2a9ce3c208fb0ae7055ec Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Thu, 11 Apr 2024 20:54:14 +0900 Subject: [PATCH 14/14] =?UTF-8?q?:sparkles:=20gateway=EC=97=90=20=EB=9D=84?= =?UTF-8?q?=EC=9A=B8=20=EC=B5=9C=EC=A2=85=20html=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/static/docs/index.html | 3057 +++++++++++++++++ 1 file changed, 3057 insertions(+) create mode 100644 backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html diff --git a/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html b/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html new file mode 100644 index 0000000000..75a81c2a25 --- /dev/null +++ b/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html @@ -0,0 +1,3057 @@ + + + + + + + +Moment Application API Document + + + + + + +
+
+

AlreadyBookedDate

+
+
+

예약일 전부 조회

+
+

HTTP request

+
+
+
GET /core/alreadyBookedDate/all HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 211
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "SELECT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "cardViews" : [ {
+      "bookedDate" : "2024-04-11"
+    }, {
+      "bookedDate" : "2023-10-10"
+    } ]
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.cardViews[].bookedDate

String

예약된 날짜 목록

+
+
+
+
+
+

CardView

+
+
+

녹음본 업로드

+
+

HTTP request

+
+
+
POST /core/cardView/upload HTTP/1.1
+Content-Type: multipart/form-data;charset=UTF-8; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
+userId: 1
+Host: localhost:8080
+
+--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
+Content-Disposition: form-data; name=recordFile; filename=test.mp3
+Content-Type: audio/mp3
+
+test
+--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
+Content-Disposition: form-data; name=uploadRecord
+Content-Type: application/json
+
+{
+  "location": "서울",
+  "recordedAt": "2024-02-08T14:30:00",
+  "temperature": "20",
+  "weather": "맑음",
+  "question": "질문"
+}
+--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm--
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Request part-uploadrecord-fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

location

String

녹음본 장소

recordedAt

String

녹음 시점

temperature

String

온도

weather

String

날씨

question

String

질문

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 549
+
+{
+  "status" : 201,
+  "code" : "201",
+  "msg" : "INSERT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "tripFileId" : 1,
+    "recordedAt" : "2024-02-08T14:30:00",
+    "recordFileName" : "test.mp3",
+    "recordFileUrl" : "http://localhost:8080/",
+    "location" : "서울",
+    "recordFileLength" : 100,
+    "weather" : "맑음",
+    "temperature" : "20",
+    "stt" : "test",
+    "happy" : 0.1,
+    "sad" : 0.1,
+    "angry" : 0.1,
+    "neutral" : 0.1,
+    "question" : "질문",
+    "recordFileStatus" : "WAIT",
+    "id" : 1,
+    "loved" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.id

Number

cardView ID

data.tripFileId

Number

tripFile ID

data.recordedAt

String

녹음 시점

data.recordFileName

String

파일이름

data.recordFileUrl

String

파일 저장 위치

data.location

String

위치

data.recordFileLength

Number

파일길이

data.weather

String

날씨

data.temperature

String

온도

data.stt

String

STT

data.happy

Number

기쁨

data.sad

Number

슬픔

data.angry

Number

화남

data.neutral

Number

중립

data.question

String

질문

data.loved

Boolean

즐겨찾기

data.recordFileStatus

String

분석 상태

+
+
+
+

카드뷰 삭제

+
+

HTTP request

+
+
+
DELETE /core/cardView/1 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /core/cardView/{cardViewId}
ParameterDescription

cardViewId

카드뷰 ID

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "DELETE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+

여행파일ID로 카드뷰 전체 조회

+
+

HTTP request

+
+
+
GET /core/cardView/all/1 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 1102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "SELECT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "cardViews" : [ {
+      "tripFileId" : 1,
+      "recordedAt" : "2024-02-08T14:30:00",
+      "recordFileName" : "test.mp3",
+      "recordFileUrl" : "http://localhost:8080/",
+      "location" : "서울",
+      "recordFileLength" : 100,
+      "weather" : "맑음",
+      "temperature" : "20",
+      "stt" : "test",
+      "happy" : 0.1,
+      "sad" : 0.1,
+      "angry" : 0.1,
+      "neutral" : 0.1,
+      "question" : "질문",
+      "recordFileStatus" : "WAIT",
+      "id" : 1,
+      "loved" : true
+    }, {
+      "tripFileId" : 1,
+      "recordedAt" : "2024-02-08T15:30:00",
+      "recordFileName" : "test.mp3",
+      "recordFileUrl" : "http://localhost:8080/",
+      "location" : "서울",
+      "recordFileLength" : 100,
+      "weather" : "맑음",
+      "temperature" : "20",
+      "stt" : "test",
+      "happy" : 0.1,
+      "sad" : 0.1,
+      "angry" : 0.1,
+      "neutral" : 0.1,
+      "question" : "질문",
+      "recordFileStatus" : "WAIT",
+      "id" : 2,
+      "loved" : false
+    } ]
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.cardViews[].id

Number

cardView ID

data.cardViews[].tripFileId

Number

tripFile ID

data.cardViews[].recordedAt

String

녹음 시점

data.cardViews[].recordFileName

String

파일이름

data.cardViews[].recordFileUrl

String

파일 저장 위치

data.cardViews[].location

String

위치

data.cardViews[].recordFileLength

Number

파일길이

data.cardViews[].weather

String

날씨

data.cardViews[].temperature

String

온도

data.cardViews[].stt

String

STT

data.cardViews[].happy

Number

기쁨

data.cardViews[].sad

Number

슬픔

data.cardViews[].angry

Number

화남

data.cardViews[].neutral

Number

중립

data.cardViews[].question

String

질문

data.cardViews[].loved

Boolean

즐겨찾기

data.cardViews[].recordFileStatus

String

분석 상태

+
+
+
+

카드뷰 수정

+
+

HTTP request

+
+
+
PUT /core/cardView/1 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Content-Length: 118
+Host: localhost:8080
+
+{
+  "location" : "서울",
+  "weather" : "맑음",
+  "temperature" : "20",
+  "question" : "질문",
+  "stt" : "test"
+}
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /core/cardView/{cardViewId}
ParameterDescription

cardViewId

카드뷰 ID

+
+
+

Request body

+
+
+
{
+  "location" : "서울",
+  "weather" : "맑음",
+  "temperature" : "20",
+  "question" : "질문",
+  "stt" : "test"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

location

String

true

녹음본 장소

weather

String

true

날씨

temperature

String

true

온도

question

String

true

질문

stt

String

true

STT

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "UPDATE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+

카드뷰 좋아요 누르기

+
+

HTTP request

+
+
+
PUT /core/cardView/like/1 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /core/cardView/like/{cardViewId}
ParameterDescription

cardViewId

카드뷰 ID

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "UPDATE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+

좋아요 상태의 카드뷰 조회

+
+

HTTP request

+
+
+
GET /core/cardView/like HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 1102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "SELECT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "cardViews" : [ {
+      "tripFileId" : 1,
+      "recordedAt" : "2024-02-08T14:30:00",
+      "recordFileName" : "test.mp3",
+      "recordFileUrl" : "http://localhost:8080/",
+      "location" : "서울",
+      "recordFileLength" : 100,
+      "weather" : "맑음",
+      "temperature" : "20",
+      "stt" : "test",
+      "happy" : 0.1,
+      "sad" : 0.1,
+      "angry" : 0.1,
+      "neutral" : 0.1,
+      "question" : "질문",
+      "recordFileStatus" : "WAIT",
+      "id" : 1,
+      "loved" : true
+    }, {
+      "tripFileId" : 1,
+      "recordedAt" : "2024-02-08T15:30:00",
+      "recordFileName" : "test.mp3",
+      "recordFileUrl" : "http://localhost:8080/",
+      "location" : "서울",
+      "recordFileLength" : 100,
+      "weather" : "맑음",
+      "temperature" : "20",
+      "stt" : "test",
+      "happy" : 0.1,
+      "sad" : 0.1,
+      "angry" : 0.1,
+      "neutral" : 0.1,
+      "question" : "질문",
+      "recordFileStatus" : "WAIT",
+      "id" : 2,
+      "loved" : false
+    } ]
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.cardViews[].id

Number

cardView ID

data.cardViews[].tripFileId

Number

tripFile ID

data.cardViews[].recordedAt

String

녹음 시점

data.cardViews[].recordFileName

String

파일이름

data.cardViews[].recordFileUrl

String

파일 저장 위치

data.cardViews[].location

String

위치

data.cardViews[].recordFileLength

Number

파일길이

data.cardViews[].weather

String

날씨

data.cardViews[].temperature

String

온도

data.cardViews[].stt

String

STT

data.cardViews[].happy

Number

기쁨

data.cardViews[].sad

Number

슬픔

data.cardViews[].angry

Number

화남

data.cardViews[].neutral

Number

중립

data.cardViews[].question

String

질문

data.cardViews[].loved

Boolean

즐겨찾기

data.cardViews[].recordFileStatus

String

분석 상태

+
+
+
+
+
+

Auth

+
+
+

로그인

+
+

HTTP request

+
+
+
POST /auth/login HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 58
+Host: localhost:8080
+
+{
+  "email" : "alexj99@naver.com",
+  "password" : "1234"
+}
+
+
+
+
+

Request body

+
+
+
{
+  "email" : "alexj99@naver.com",
+  "password" : "1234"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

email

String

true

이메일

password

String

true

비밀번호

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 229
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "SELECT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "grantType" : "Bearer",
+    "accessToken" : "accessToken",
+    "refreshToken" : "refresh",
+    "role" : "ROLE_AUTH_USER"
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.grantType

String

토큰 타입

data.accessToken

String

액세스 토큰

data.refreshToken

String

리프레시 토큰

data.role

String

사용자 권한

+
+
+
+

비밀번호 변경

+
+

HTTP request

+
+
+
PATCH /auth/password HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Content-Length: 48
+Host: localhost:8080
+
+{
+  "code" : "1234",
+  "newPassword" : "12345"
+}
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Request body

+
+
+
{
+  "code" : "1234",
+  "newPassword" : "12345"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

code

String

true

인증 코드

newPassword

String

true

새로운 비밀번호

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "UPDATE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+

인증코드 요청

+
+

HTTP request

+
+
+
POST /auth/code HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 58
+Host: localhost:8080
+
+{
+  "email" : "alexj99@naver.com",
+  "isSignUp" : "true"
+}
+
+
+
+
+

Request body

+
+
+
{
+  "email" : "alexj99@naver.com",
+  "isSignUp" : "true"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

email

String

true

이메일

isSignUp

String

true

회원가입 여부

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 215
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "SELECT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "grantType" : "Bearer",
+    "accessToken" : "accessToken",
+    "role" : "ROLE_AUTH_USER",
+    "userId" : 1
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.grantType

String

토큰 타입

data.accessToken

String

액세스 토큰

data.role

String

사용자 권한

data.userId

Number

사용자 ID

+
+
+
+

인증코드 확인

+
+

HTTP request

+
+
+
PATCH /auth/verify HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Content-Length: 21
+Host: localhost:8080
+
+{
+  "code" : "1234"
+}
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Request body

+
+
+
{
+  "code" : "1234"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

code

String

true

인증 코드

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "UPDATE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+
+
+

Trip

+
+
+

여행 등록

+
+

HTTP request

+
+
+
POST /core/trip/register HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Accept: application/json
+Content-Length: 83
+Host: localhost:8080
+
+{
+  "startDate" : "2024-04-11",
+  "endDate" : "2024-04-12",
+  "tripName" : "test"
+}
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Request body

+
+
+
{
+  "startDate" : "2024-04-11",
+  "endDate" : "2024-04-12",
+  "tripName" : "test"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

tripName

String

true

여행 이름

startDate

String

true

yyyy-MM-dd

여행 시작 날짜

endDate

String

true

yyyy-MM-dd

여행 종료 날짜

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 201,
+  "code" : "201",
+  "msg" : "INSERT SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+

여행 목록 조회

+
+

HTTP request

+
+
+
GET /core/trip/all HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 628
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "SELECT SUCCESS",
+  "detailMsg" : "",
+  "data" : {
+    "trips" : [ {
+      "id" : 1,
+      "email" : "test",
+      "startDate" : "2024-04-11",
+      "endDate" : "2024-04-12",
+      "analyzingCount" : 0,
+      "tripName" : "test"
+    }, {
+      "id" : 2,
+      "email" : "test",
+      "startDate" : "2024-04-11",
+      "endDate" : "2024-04-12",
+      "analyzingCount" : 1,
+      "tripName" : "test"
+    }, {
+      "id" : 3,
+      "email" : "test",
+      "startDate" : "2024-04-11",
+      "endDate" : "2024-04-12",
+      "analyzingCount" : 2,
+      "tripName" : "test"
+    } ]
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data.trips[].id

Number

여행 ID

data.trips[].email

String

유저 email

data.trips[].startDate

String

출발일

data.trips[].endDate

String

도착일

data.trips[].analyzingCount

Number

분석 중 파일 개수

data.trips[].tripName

String

여행 이름

+
+
+
+

여행 수정

+
+

HTTP request

+
+
+
PUT /core/trip HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Accept: application/json
+Content-Length: 99
+Host: localhost:8080
+
+{
+  "tripId" : 1,
+  "startDate" : "2024-04-11",
+  "endDate" : "2024-04-12",
+  "tripName" : "test"
+}
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Request body

+
+
+
{
+  "tripId" : 1,
+  "startDate" : "2024-04-11",
+  "endDate" : "2024-04-12",
+  "tripName" : "test"
+}
+
+
+
+
+

Request fields

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
필드명타입필수값양식설명

tripId

Number

true

여행 ID

startDate

String

true

yyyy-MM-dd

출발일

endDate

String

true

yyyy-MM-dd

도착일

tripName

String

true

여행 이름

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "UPDATE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+

여행 삭제

+
+

HTTP request

+
+
+
DELETE /core/trip/1 HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+userId: 1
+Accept: application/json
+Host: localhost:8080
+
+
+
+
+

Request headers

+ ++++ + + + + + + + + + + + + +
NameDescription

userId

Bearer Token

+
+
+

Path parameters

+ + ++++ + + + + + + + + + + + + +
Table 1. /core/trip/{tripId}
ParameterDescription

tripId

삭제할 여행 ID

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 102
+
+{
+  "status" : 200,
+  "code" : "200",
+  "msg" : "DELETE SUCCESS",
+  "detailMsg" : "",
+  "data" : { }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

status

Number

응답 상태 코드

code

String

응답 코드

msg

String

응답 메시지

detailMsg

String

상세 메시지

data

Object

데이터 없음

+
+
+
+
+
+ + + + + \ No newline at end of file