Skip to content

Commit

Permalink
[BE] docs: 답변 하이라이트 API 문서 작성 (#800)
Browse files Browse the repository at this point in the history
* feat: 하이라이트 요청 dto 생성

* feat: 하이라이트 뼈대 코드 작성

* docs: API 문서 작성

* docs: request cookie 필드 추가

* fix: 재귀적 `@Valid` 적용

* fix: 세션 값 추가

* refactor: API에 질문 ID 필드 추가

* refactor: 비어있지 않으면 안 되는 부분들에 대한 검증 추가
  • Loading branch information
donghoony authored Oct 10, 2024
1 parent 65bdfb3 commit 1c5b177
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 2 deletions.
3 changes: 3 additions & 0 deletions backend/src/docs/asciidoc/highlight-answers.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
==== 리뷰 하이라이트 변경 (추가, 삭제, 수정 포함)

operation::highlight-answer[snippets="curl-request,request-cookies,http-response,request-fields"]
6 changes: 5 additions & 1 deletion backend/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ include::review-list.adoc[]

=== 리뷰 모아보기

include::review-gather.adoc[]
include::review-gather.adoc[]

=== 답변 하이라이트

include::highlight-answers.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package reviewme.highlight.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;
import reviewme.highlight.service.HighlightService;
import reviewme.highlight.service.dto.HighlightsRequest;

@RestController
@RequiredArgsConstructor
public class HighlightController {

private final HighlightService highlightService;

@PostMapping("/v2/highlight")
public ResponseEntity<Void> highlight(@Valid @RequestBody HighlightsRequest request,
@SessionAttribute("reviewRequestCode") String reviewRequestCode) {
highlightService.highlight(request);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package reviewme.highlight.service;

import org.springframework.stereotype.Service;
import reviewme.highlight.service.dto.HighlightsRequest;

@Service
public class HighlightService {

public void highlight(HighlightsRequest request) {
// TODO: implement method
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package reviewme.highlight.service.dto;

import jakarta.validation.constraints.NotNull;

public record HighlightIndexRangeRequest(

@NotNull(message = "시작 인덱스를 입력해주세요.")
Long startIndex,

@NotNull(message = "끝 인덱스를 입력해주세요.")
Long endIndex
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package reviewme.highlight.service.dto;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;

public record HighlightRequest(

@NotNull(message = "답변 ID를 입력해주세요.")
Long answerId,

@Valid @NotEmpty(message = "하이라이트 된 라인을 입력해주세요.")
List<HighlightedLineRequest> lines
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package reviewme.highlight.service.dto;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;

public record HighlightedLineRequest(

@NotNull(message = "인덱스를 입력해주세요.")
Long index,

@Valid @NotEmpty(message = "하이라이트 범위를 입력해주세요.")
List<HighlightIndexRangeRequest> ranges
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package reviewme.highlight.service.dto;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;

public record HighlightsRequest(

@NotNull(message = "질문 ID를 입력해주세요.")
Long questionId,

@Valid @NotNull(message = "하이라이트할 부분을 입력해주세요.")
List<HighlightRequest> highlights
) {
}
8 changes: 7 additions & 1 deletion backend/src/test/java/reviewme/api/ApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import reviewme.highlight.controller.HighlightController;
import reviewme.highlight.service.HighlightService;
import reviewme.review.controller.ReviewController;
import reviewme.review.service.GatheredReviewLookupService;
import reviewme.review.service.ReviewDetailLookupService;
Expand All @@ -44,7 +46,8 @@
ReviewGroupController.class,
ReviewController.class,
TemplateController.class,
SectionController.class
SectionController.class,
HighlightController.class
})
@ExtendWith(RestDocumentationExtension.class)
public abstract class ApiTest {
Expand Down Expand Up @@ -78,6 +81,9 @@ public abstract class ApiTest {
@MockBean
protected GatheredReviewLookupService gatheredReviewLookupService;

@MockBean
protected HighlightService highlightService;

Filter sessionCookieFilter = (request, response, chain) -> {
chain.doFilter(request, response);
HttpSession session = ((HttpServletRequest) request).getSession(false);
Expand Down
62 changes: 62 additions & 0 deletions backend/src/test/java/reviewme/api/HighlightApiTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package reviewme.api;

import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName;
import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;

import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.restdocs.cookies.CookieDescriptor;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
import org.springframework.restdocs.payload.FieldDescriptor;

class HighlightApiTest extends ApiTest {

@Test
void 존재하는_답변에_하이라이트를_생성한다() {
String request = """
{
"questionId": 1,
"highlights": [{
"answerId": 3,
"lines": [{
"index": 5,
"ranges": [{
"startIndex": 6,
"endIndex": 9
}]
}]
}]
}
""";

CookieDescriptor[] cookieDescriptors = {
cookieWithName("JSESSIONID").description("세션 ID")
};

FieldDescriptor[] requestFields = {
fieldWithPath("questionId").description("질문 ID"),
fieldWithPath("highlights").description("하이라이트 목록"),
fieldWithPath("highlights[].answerId").description("답변 ID"),
fieldWithPath("highlights[].lines[].index").description("개행으로 구분되는 라인 번호, 0-based"),
fieldWithPath("highlights[].lines[].ranges[].startIndex").description("하이라이트 시작 인덱스, 0-based"),
fieldWithPath("highlights[].lines[].ranges[].endIndex").description("하이라이트 끝 인덱스, 0-based")
};

RestDocumentationResultHandler handler = document(
"highlight-answer",
requestFields(requestFields),
requestCookies(cookieDescriptors)
);

givenWithSpec().log().all()
.cookie("JSESSIONID", "AVEBNKLCL13TNVZ")
.body(request)
.when().post("/v2/highlight")
.then().log().all()
.apply(handler)
.status(HttpStatus.OK);
}
}

0 comments on commit 1c5b177

Please sign in to comment.