diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/interview/model/InterviewReviewStatus.java b/backend/src/main/java/com/shyashyashya/refit/domain/interview/model/InterviewReviewStatus.java index 99e8fa64a..fdf700862 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/interview/model/InterviewReviewStatus.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/interview/model/InterviewReviewStatus.java @@ -3,7 +3,7 @@ public enum InterviewReviewStatus { NOT_LOGGED, // 기록 전 LOG_DRAFT, // 기록 중 - QNA_SET_DRAFT, + QNA_SET_DRAFT, // 질답 세트 검토 중 SELF_REVIEW_DRAFT, // 회고 중 DEBRIEF_COMPLETED // 회고 완료 } diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/api/QnaSetController.java b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/api/QnaSetController.java index b6741a9e1..b4a4c721e 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/api/QnaSetController.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/api/QnaSetController.java @@ -73,7 +73,7 @@ public ResponseEntity> unmarkDifficultQuestion(@PathVariable L return ResponseEntity.ok(response); } - @Operation(summary = "지정한 질문 답변 세트의 질문 답변 내용을 수정합니다.", description = "질문 답변 내용 수정은 'QnaSetDraft' 상태에서만 가능합니다.") + @Operation(summary = "지정한 질문 답변 세트의 질문 답변 내용을 수정합니다.", description = "질문 답변 내용 수정은 질답 세트 검토 중 상태에서만 가능합니다.") @PutMapping("/{qnaSetId}") public ResponseEntity> updateQnaSet( @PathVariable Long qnaSetId, @Valid @RequestBody QnaSetUpdateRequest request) { @@ -82,7 +82,7 @@ public ResponseEntity> updateQnaSet( return ResponseEntity.ok(response); } - @Operation(summary = "지정한 질문 답변 세트를 삭제합니다.", description = "질문 답변 세트 삭제는 'QnaSetDraft' 상태에서만 가능합니다.") + @Operation(summary = "지정한 질문 답변 세트를 삭제합니다.", description = "질문 답변 세트 삭제는 질답 세트 검토 중 상태에서만 가능합니다.") @DeleteMapping("/{qnaSetId}") public ResponseEntity> deleteQnaSet(@PathVariable Long qnaSetId) { qnaSetService.deleteQnaSet(qnaSetId); @@ -92,7 +92,7 @@ public ResponseEntity> deleteQnaSet(@PathVariable Long qnaSetI @Operation( summary = "지정한 질문 답변 세트에 대해 PDF 하이라이팅 정보를 등록/수정합니다.", - description = "PDF 하이라이팅 정보 등록/수정은 'QnaSetDraft' 상태에서만 가능합니다.") + description = "PDF 하이라이팅 정보 등록/수정은 질답 세트 검토 중 상태에서만 가능합니다.") @PutMapping("/{qnaSetId}/pdf-highlightings") public ResponseEntity> updatePdfHighlighting( @PathVariable Long qnaSetId, @Valid @RequestBody List request) { diff --git a/backend/src/main/java/com/shyashyashya/refit/global/exception/ErrorCode.java b/backend/src/main/java/com/shyashyashya/refit/global/exception/ErrorCode.java index 2eedc3525..4d4e4b23b 100644 --- a/backend/src/main/java/com/shyashyashya/refit/global/exception/ErrorCode.java +++ b/backend/src/main/java/com/shyashyashya/refit/global/exception/ErrorCode.java @@ -17,9 +17,8 @@ public enum ErrorCode { INTERVIEW_NOT_ACCESSIBLE(FORBIDDEN, "인터뷰에 접근할 수 없습니다."), INTERVIEW_NOT_IN_DRAFT_STATUS(BAD_REQUEST, "임시저장 상태의 인터뷰만 조회할 수 있습니다."), INTERVIEW_REVIEW_STATUS_NOT_UPDATABLE_TO_LOG_DRAFT(BAD_REQUEST, "인터뷰 상태가 기록전 상태일 때만 기록중으로 바뀔 수 있습니다"), - INTERVIEW_REVIEW_STATUS_NOT_UPDATABLE_TO_QNA_SET_DRAFT(BAD_REQUEST, "인터뷰 상태가 기록중 상태일 때만 QnaSetDraft로 바뀔 수 있습니다"), - INTERVIEW_REVIEW_STATUS_NOT_UPDATABLE_TO_SELF_REVIEW_DRAFT( - BAD_REQUEST, "인터뷰 상태가 QnaSetDraft 상태일 때만 회고중으로 바뀔 수 있습니다"), + INTERVIEW_REVIEW_STATUS_NOT_UPDATABLE_TO_QNA_SET_DRAFT(BAD_REQUEST, "인터뷰 상태가 기록중 상태일 때만 질답세트검토중으로 바뀔 수 있습니다"), + INTERVIEW_REVIEW_STATUS_NOT_UPDATABLE_TO_SELF_REVIEW_DRAFT(BAD_REQUEST, "인터뷰 상태가 질답세트검토중 상태일 때만 회고중으로 바뀔 수 있습니다"), INTERVIEW_REVIEW_STATUS_NOT_UPDATABLE_TO_DEBRIEF_COMPLETED(BAD_REQUEST, "인터뷰 상태가 회고중 상태일 때만 회고완료로 바뀔 수 있습니다"), INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED(BAD_REQUEST, "요청을 처리하는데 필요한 인터뷰 상태의 검증에 실패하였습니다."), diff --git a/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java b/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java index 177dfaa2f..3d49c188b 100644 --- a/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java +++ b/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java @@ -17,6 +17,15 @@ import com.shyashyashya.refit.domain.qnaset.model.PdfHighlighting; import com.shyashyashya.refit.domain.qnaset.model.PdfHighlightingRect; import com.shyashyashya.refit.domain.qnaset.model.QnaSet; +import com.shyashyashya.refit.domain.qnaset.model.QnaSetCategory; +import com.shyashyashya.refit.domain.qnaset.repository.PdfHighlightingRectRepository; +import com.shyashyashya.refit.domain.qnaset.repository.PdfHighlightingRepository; +import com.shyashyashya.refit.domain.qnaset.repository.QnaSetCategoryRepository; +import com.shyashyashya.refit.domain.qnaset.repository.QnaSetRepository; +import com.shyashyashya.refit.domain.qnaset.dto.request.PdfHighlightingUpdateRequest; +import com.shyashyashya.refit.domain.qnaset.model.PdfHighlighting; +import com.shyashyashya.refit.domain.qnaset.model.PdfHighlightingRect; +import com.shyashyashya.refit.domain.qnaset.model.QnaSet; import com.shyashyashya.refit.domain.qnaset.repository.PdfHighlightingRectRepository; import com.shyashyashya.refit.domain.qnaset.repository.PdfHighlightingRepository; import com.shyashyashya.refit.domain.qnaset.repository.QnaSetRepository; @@ -66,6 +75,9 @@ public abstract class IntegrationTest { protected Company company1; protected Company company2; protected Company company3; + protected QnaSetCategory qnaSetCategory1; + protected QnaSetCategory qnaSetCategory2; + protected QnaSetCategory qnaSetCategory3; @PersistenceContext private EntityManager em; @@ -97,6 +109,9 @@ public abstract class IntegrationTest { @Autowired private PdfHighlightingRectRepository pdfHighlightingRectRepository; + @Autowired + private QnaSetCategoryRepository qnaSetCategoryRepository; + @BeforeEach void restAssuredSetUp() { clearDatabase(); @@ -111,6 +126,9 @@ void restAssuredSetUp() { company1 = companyRepository.save(Company.create("현대자동차", "logo1", true)); company2 = companyRepository.save(Company.create("카카오", "logo2", true)); company3 = companyRepository.save(Company.create("네이버", "logo3", true)); + qnaSetCategory1 = qnaSetCategoryRepository.save(QnaSetCategory.create("리더십 질문", "당신은 리더십있는 사람입니까?", 3.141592)); + qnaSetCategory2 = qnaSetCategoryRepository.save(QnaSetCategory.create("인성 질문", "당신은 인성이 좋은 사람입니까?", 2.145)); + qnaSetCategory3 = qnaSetCategoryRepository.save(QnaSetCategory.create("기술 질문", "당신은 기술 있는 사람입니까?", 0.001)); requestUser = createAndSaveUser("test@example.com", "default", industry1, jobCategory1); Instant issuedAt = Instant.now(); @@ -206,7 +224,11 @@ protected Company createAndSaveCompany(String companyName) { return companyRepository.save(company); } - protected QnaSet createQnaSet(QnaSetCreateRequest request, Interview interview, boolean isMarkedDifficult) { + protected QnaSet createAndSaveQnaSet(QnaSetCreateRequest request, Interview interview) { + return createAndSaveQnaSet(request, interview, false); + } + + protected QnaSet createAndSaveQnaSet(QnaSetCreateRequest request, Interview interview, boolean isMarkedDifficult) { QnaSet qnaSet = QnaSet.create( request.questionText(), request.answerText(), @@ -218,6 +240,18 @@ protected QnaSet createQnaSet(QnaSetCreateRequest request, Interview interview, return qnaSetRepository.save(qnaSet); } + protected QnaSet createAndSaveQnaSet(QnaSetCreateRequest request, Interview interview, QnaSetCategory qnaSetCategory) { + QnaSet qnaSet = QnaSet.create( + request.questionText(), + request.answerText(), + false, + interview, + qnaSetCategory + ); + + return qnaSetRepository.save(qnaSet); + } + protected List createAndSavePdfHighlighting(List requests, QnaSet qnaSet) { List result = new ArrayList<>(); diff --git a/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetIntegrationTest.java b/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetIntegrationTest.java index 56eb5c31c..348ab0bbf 100644 --- a/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetIntegrationTest.java +++ b/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetIntegrationTest.java @@ -27,6 +27,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; @@ -39,11 +41,51 @@ public class QnaSetIntegrationTest extends IntegrationTest { @Autowired private QnaSetRepository qnaSetRepository; + private Long qnaSetDraftQnaSetId; + private Long debriefCompletedQnaSetId; + private Long qnaSetWithPdfHighlightingId; + private Long otherUserQnaSetId; + + @BeforeEach + void setUp() { + var interviewCreateRequest1 = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + Interview qnaSetDraftInterview = createAndSaveInterview(interviewCreateRequest1, InterviewReviewStatus.QNA_SET_DRAFT); + + var interviewCreateRequest2 = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); + + var qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); + QnaSet qnaSetDraftQnaSet = createAndSaveQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); + qnaSetDraftQnaSetId = qnaSetDraftQnaSet.getId(); + + var qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); + QnaSet debriefCompletedQnaSet = createAndSaveQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); + debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); + + var qnaSetCreateRequest3 = new QnaSetCreateRequest("this qna has pdf highlighting", "hello PDF"); + QnaSet qnaSetWithPdfHighlighting = createAndSaveQnaSet(qnaSetCreateRequest3,qnaSetDraftInterview, false); + qnaSetWithPdfHighlightingId = qnaSetWithPdfHighlighting.getId(); + + var interviewCreateRequest4 = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + User user = createAndSaveUser("other@example.com", "other", industry1, jobCategory1); + Interview otherUserInterview = createAndSaveInterview(interviewCreateRequest4, InterviewReviewStatus.NOT_LOGGED, user); + + QnaSetCreateRequest qnaSetCreateRequest4 = new QnaSetCreateRequest("this qna is others", "hello stranger"); + QnaSet otherUserQnaSet = createAndSaveQnaSet(qnaSetCreateRequest4, otherUserInterview, false); + otherUserQnaSetId = otherUserQnaSet.getId(); + + List pdfHighlightUpdateRequest = createPdfHighlightUpdateRequest(); + createAndSavePdfHighlighting(pdfHighlightUpdateRequest, qnaSetWithPdfHighlighting); + } + @Nested class 질답_세트_생성_시 { @Test - void 인터뷰가_QNA_SET_DRAFT_상태이면_질답_세트_생성에_성공한다() { + void 인터뷰가_질답_세트_검토_중_상태이면_질답_세트_생성에_성공한다() { // given InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); @@ -63,20 +105,26 @@ class 질답_세트_생성_시 { .body("result.qnaSetId", notNullValue()); } - @Test - void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_생성에_실패한다() { + @ParameterizedTest + @EnumSource( + value = InterviewReviewStatus.class, + mode = EnumSource.Mode.EXCLUDE, + names = "QNA_SET_DRAFT" + ) + void 인터뷰가_질답_세트_검토_중_상태가_아니라면_질답_세트_생성에_실패한다(InterviewReviewStatus reviewStatus) { // given InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview interview1 = createAndSaveInterview(interviewCreateRequest); + + Interview interview = createAndSaveInterview(interviewCreateRequest, reviewStatus); QnaSetCreateRequest request = new QnaSetCreateRequest("test question text", "test answer text"); // when & then given(spec) .body(request) - .when() - .post("/interview/" + interview1.getId() + "/qna-set") - .then() + .when() + .post("/interview/" + interview.getId() + "/qna-set") + .then() .statusCode(400) .body("code", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.name())) .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) @@ -97,7 +145,7 @@ void setUp() { LocalDateTime.of(2023, 1, 10, 10, 0, 0), InterviewType.FIRST, company1.getName(), industry1.getId(), jobCategory1.getId(), "Developer" )); QnaSetCreateRequest qnaSetCreateRequest = new QnaSetCreateRequest ("test qqq text", "test aaa text"); - QnaSet qnaSet = createQnaSet(qnaSetCreateRequest, interview, false); + QnaSet qnaSet = createAndSaveQnaSet(qnaSetCreateRequest, interview, false); qnaSetId = qnaSet.getId(); } @@ -141,32 +189,31 @@ void setUp() { @Nested class 질답_세트_수정_시 { - private Long qnaSetDraftQnaSetId; - private Long debriefCompletedQnaSetId; - - @BeforeEach - void setUp() { - InterviewCreateRequest interviewCreateRequest1 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview qnaSetDraftInterview = createAndSaveInterview(interviewCreateRequest1, InterviewReviewStatus.QNA_SET_DRAFT); - - InterviewCreateRequest interviewCreateRequest2 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); + @Test + void 인터뷰가_질답_세트_검토_중_상태이면_질답_세트_수정에_성공한다() { + // given + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", "self review self review"); - QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); - qnaSetDraftQnaSetId = qnaSetDraftQnaSet.getId(); + // when & then + given(spec) + .body(qnaSetUpdateRequest) + .when() + .put("/qna-set/" + qnaSetDraftQnaSetId) + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", nullValue()); - QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); - debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); + QnaSet updated = qnaSetRepository.findById(qnaSetDraftQnaSetId).get(); + assertThat(updated.getQuestionText()).isEqualTo("update question"); + assertThat(updated.getAnswerText()).isEqualTo("update answer"); } @Test - void 인터뷰가_QNA_SET_DRAFT_상태이면_질답_세트_수정에_성공한다() { + void 수정_요청에_질문만_존재할_때_질답_세트_수정에_성공한다() { // given - QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", "self review self review"); + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("only question text update", null, null); // when & then given(spec) @@ -178,12 +225,16 @@ void setUp() { .body("code", equalTo(COMMON200.name())) .body("message", equalTo(COMMON200.getMessage())) .body("result", nullValue()); + + QnaSet updated = qnaSetRepository.findById(qnaSetDraftQnaSetId).get(); + assertThat(updated.getQuestionText()).isEqualTo("only question text update"); + assertThat(updated.getAnswerText()).isEqualTo("test answer text"); } @Test - void 수정_요청에_필드가_하나일_때_질답_세트_수정에_성공한다() { + void 수정_요청에_답변만_존재할_때_질답_세트_수정에_성공한다() { // given - QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("only question text update", null, null); + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest(null, "only answer text update", null); // when & then given(spec) @@ -195,6 +246,10 @@ void setUp() { .body("code", equalTo(COMMON200.name())) .body("message", equalTo(COMMON200.getMessage())) .body("result", nullValue()); + + QnaSet updated = qnaSetRepository.findById(qnaSetDraftQnaSetId).get(); + assertThat(updated.getQuestionText()).isEqualTo("test question text"); + assertThat(updated.getAnswerText()).isEqualTo("only answer text update"); } @Test @@ -215,7 +270,7 @@ void setUp() { } @Test - void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_수정에_실패한다() { + void 인터뷰가_질답_세트_검토_중_상태가_아니라면_질답_세트_수정에_실패한다() { // given QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); @@ -232,7 +287,7 @@ void setUp() { } @Test - void QNA_SET_이_존재하지_않으면_질답_세트_수정에_실패한다() { + void 질답_세트가_존재하지_않으면_질답_세트_수정에_실패한다() { // given QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); @@ -247,36 +302,30 @@ void setUp() { .body("message", equalTo(QNA_SET_NOT_FOUND.getMessage())) .body("result", nullValue()); } + + @Test + void 다른_사람의_질답_세트_수정에_실패한다() { + // given + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); + + // when & then + given(spec) + .body(qnaSetUpdateRequest) + .when() + .put("/qna-set/" + otherUserQnaSetId) + .then() + .statusCode(403) + .body("code", equalTo(INTERVIEW_NOT_ACCESSIBLE.name())) + .body("message", equalTo(INTERVIEW_NOT_ACCESSIBLE.getMessage())) + .body("result", nullValue()); + } } @Nested class 질답_세트_삭제_시 { - // TODO 반복 코드 - private Long qnaSetDraftQnaSetId; - private Long debriefCompletedQnaSetId; - - @BeforeEach - void setUp() { - InterviewCreateRequest interviewCreateRequest1 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview qnaSetDraftInterview = createAndSaveInterview(interviewCreateRequest1, InterviewReviewStatus.QNA_SET_DRAFT); - - InterviewCreateRequest interviewCreateRequest2 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); - - QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); - qnaSetDraftQnaSetId = qnaSetDraftQnaSet.getId(); - - QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); - debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); - } - @Test - void 인터뷰가_QNA_SET_DRAFT_상태이면_질답_세트_삭제에_성공한다() { + void 인터뷰가_질답_세트_검토_중_상태이면_질답_세트_삭제에_성공한다() { // given // when & then @@ -291,7 +340,7 @@ void setUp() { } @Test - void 인터뷰가_QNA_SET_DRAFT_상태가_아니면_질답_세트_삭제에_실패한다() { + void 인터뷰가_질답_세트_검토_중_상태가_아니면_질답_세트_삭제에_실패한다() { // given // when & then @@ -304,35 +353,42 @@ void setUp() { .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) .body("result", nullValue()); } - } - - @Nested - class PDF_하이라이팅_등록_수정_시 { - - private Long qnaSetDraftQnaSetId; - private Long debriefCompletedQnaSetId; - - @BeforeEach - void setUp() { - InterviewCreateRequest interviewCreateRequest1 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview qnaSetDraftInterview = createAndSaveInterview(interviewCreateRequest1, InterviewReviewStatus.QNA_SET_DRAFT); + @Test + void 질답_세트가_존재하지_않으면_질답_세트_삭제에_실패한다() { + // given - InterviewCreateRequest interviewCreateRequest2 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); + // when & then + given(spec) + .when() + .delete("/qna-set/" + Long.MAX_VALUE) + .then() + .statusCode(404) + .body("code", equalTo(QNA_SET_NOT_FOUND.name())) + .body("message", equalTo(QNA_SET_NOT_FOUND.getMessage())) + .body("result", nullValue()); + } - QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); - qnaSetDraftQnaSetId = qnaSetDraftQnaSet.getId(); + @Test + void 다른_사람의_질답_세트_삭제에_실패한다() { + // given - QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); - debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); + // when & then + given(spec) + .when() + .delete("/qna-set/" + otherUserQnaSetId) + .then() + .statusCode(403) + .body("code", equalTo(INTERVIEW_NOT_ACCESSIBLE.name())) + .body("message", equalTo(INTERVIEW_NOT_ACCESSIBLE.getMessage())) + .body("result", nullValue()); } + } + + @Nested + class PDF_하이라이팅_등록_수정_시 { @Test - void 인터뷰가_QNA_SET_DRAFT_상태이면_PDF_하이라이팅_등록에_성공한다() { + void 인터뷰가_질답_세트_검토_중_상태이면_PDF_하이라이팅_등록에_성공한다() { // given List request = createPdfHighlightUpdateRequest(); @@ -349,7 +405,7 @@ void setUp() { } @Test - void 인터뷰가_QNA_SET_DRAFT_상태이면_비어있는_PDF_하이라이팅_등록에_성공한다() { + void 인터뷰가_질답_세트_검토_중_상태이면_비어있는_PDF_하이라이팅_등록에_성공한다() { // given List request = List.of(); @@ -365,67 +421,73 @@ void setUp() { .body("result", nullValue()); } - @Test - void 인터뷰가_QNA_SET_DRAFT_상태가_아니면_PDF_하이라이팅_등록에_실패한다() { + @ParameterizedTest + @EnumSource( + value = InterviewReviewStatus.class, + mode = EnumSource.Mode.EXCLUDE, + names = "QNA_SET_DRAFT" + ) + void 인터뷰가_질답_세트_검토_중_상태가_아니면_PDF_하이라이팅_등록에_실패한다(InterviewReviewStatus reviewStatus) { // given + var interviewCreateRequest = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + var interview = createAndSaveInterview(interviewCreateRequest, reviewStatus); + var qnaSetCreateRequest = new QnaSetCreateRequest("test question text", "test answer text"); + var qnaSetId = createAndSaveQnaSet(qnaSetCreateRequest, interview).getId(); + List request = createPdfHighlightUpdateRequest(); // when & then given(spec) .body(request) .when() - .put("/qna-set/" + debriefCompletedQnaSetId + "/pdf-highlightings") + .put("/qna-set/" + qnaSetId + "/pdf-highlightings") .then() .statusCode(400) .body("code", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.name())) .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) .body("result", nullValue()); } - } - @Nested - class PDF_하이라이팅_조회_시 { - - private Long qnaSetDraftQnaSetId; - private Long debriefCompletedQnaSetId; - private Long qnaSetWithPdfHighlightingId; - private Long otherUserQnaSetId; - - @BeforeEach - void setUp() { - InterviewCreateRequest interviewCreateRequest1 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview qnaSetDraftInterview = createAndSaveInterview(interviewCreateRequest1, InterviewReviewStatus.QNA_SET_DRAFT); - - InterviewCreateRequest interviewCreateRequest2 = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); - - QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); - qnaSetDraftQnaSetId = qnaSetDraftQnaSet.getId(); + @Test + void 존재하지_않는_질답에_PDF_하이라이팅_등록을_시도하면_실패한다() { + // given + List request = createPdfHighlightUpdateRequest(); - QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); - QnaSet debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); - debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); + // when & then + given(spec) + .body(request) + .when() + .put("/qna-set/" + Long.MAX_VALUE + "/pdf-highlightings") + .then() + .statusCode(404) + .body("code", equalTo(QNA_SET_NOT_FOUND.name())) + .body("message", equalTo(QNA_SET_NOT_FOUND.getMessage())) + .body("result", nullValue()); + } - QnaSetCreateRequest qnaSetCreateRequest3 = new QnaSetCreateRequest("this qna has pdf highlighting", "hello PDF"); - QnaSet qnaSetWithPdfHighlighting = createQnaSet(qnaSetCreateRequest3,qnaSetDraftInterview, false); - qnaSetWithPdfHighlightingId = qnaSetWithPdfHighlighting.getId(); + @Test + void 타인의_질답에_PDF_하이라이팅_등록을_시도하면_실패한다() { + // given + List request = createPdfHighlightUpdateRequest(); + // when & then + given(spec) + .body(request) + .when() + .put("/qna-set/" + otherUserQnaSetId + "/pdf-highlightings") + .then() + .statusCode(403) + .body("code", equalTo(INTERVIEW_NOT_ACCESSIBLE.name())) + .body("message", equalTo(INTERVIEW_NOT_ACCESSIBLE.getMessage())) + .body("result", nullValue()); + } - InterviewCreateRequest request = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - User user = createAndSaveUser("other@example.com", "other", industry1, jobCategory1); - Interview otherUserInterview = createAndSaveInterview(request, InterviewReviewStatus.NOT_LOGGED, user); - QnaSetCreateRequest qnaSetCreateRequest4 = new QnaSetCreateRequest("this qna is others", "hello stranger"); - QnaSet otherUserQnaSet = createQnaSet(qnaSetCreateRequest4, otherUserInterview, false); - otherUserQnaSetId = otherUserQnaSet.getId(); + } - List pdfHighlightUpdateRequest = createPdfHighlightUpdateRequest(); - createAndSavePdfHighlighting(pdfHighlightUpdateRequest, qnaSetWithPdfHighlighting); - } + @Nested + class PDF_하이라이팅_조회_시 { @Test void 나의_빈_PDF_하이라이팅_정보_조회를_성공한다() { diff --git a/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetMyIntegrationTest.java b/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetMyIntegrationTest.java new file mode 100644 index 000000000..22f597f4b --- /dev/null +++ b/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetMyIntegrationTest.java @@ -0,0 +1,148 @@ +package com.shyashyashya.refit.integration.qnaset; + +import com.shyashyashya.refit.core.IntegrationTest; +import com.shyashyashya.refit.domain.interview.dto.request.InterviewCreateRequest; +import com.shyashyashya.refit.domain.interview.dto.request.QnaSetCreateRequest; +import com.shyashyashya.refit.domain.interview.model.Interview; +import com.shyashyashya.refit.domain.interview.model.InterviewReviewStatus; +import com.shyashyashya.refit.domain.interview.model.InterviewType; +import com.shyashyashya.refit.domain.qnaset.dto.request.QnaSetSearchRequest; +import com.shyashyashya.refit.domain.qnaset.model.QnaSet; +import com.shyashyashya.refit.domain.qnaset.model.StarInclusionLevel; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.shyashyashya.refit.global.model.ResponseCode.COMMON200; +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +public class QnaSetMyIntegrationTest extends IntegrationTest { + + @BeforeEach + void setUp() { + Interview interview = createAndSaveInterview( + new InterviewCreateRequest( + LocalDateTime.of(2023, 1, 10, 10, 0, 0), InterviewType.FIRST, company1.getName(), industry1.getId(), jobCategory1.getId(), "Developer" + ), InterviewReviewStatus.DEBRIEF_COMPLETED); + + // category가 null인 qnaSet 존재하면 NPE 발생 + // QnaSet qnaSet1 = createAndSaveQnaSet(new QnaSetCreateRequest("q text", "a text"), interview); + + QnaSet qnaSet2 = createAndSaveQnaSet( + new QnaSetCreateRequest("q text2", "a text"), + interview, + qnaSetCategory1); + + QnaSet qnaSet3 = createAndSaveQnaSet( + new QnaSetCreateRequest("q text3", "a text"), + interview, + qnaSetCategory1); + + QnaSet qnaSet4 = createAndSaveQnaSet( + new QnaSetCreateRequest("q text3", "a text"), + interview, + qnaSetCategory1); + + QnaSet qnaSet5 = createAndSaveQnaSet( + new QnaSetCreateRequest("q text3", "a text"), + interview, + qnaSetCategory3); + } + + @Nested + class 빈출_질문_카테고리_조회할_때 { + + @Test + void 성공한다() { + // given + + // when & then + given(spec) + .when() + .get("/qna-set/my/frequent/category") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()); + } + } + + @Nested + class 특정_카테고리_질문_조회할_때 { + + @Test + void 질문이_있는_카테고리의_조회를_성공한다() { + // given + + // when & then + given(spec) + .when() + .get("/qna-set/my/frequent/category/" + qnaSetCategory1.getId()) + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()); + } + + @Test + void 질문이_없는_카테고리의_조회를_성공한다() { + // given + + // when & then + given(spec) + .when() + .get("/qna-set/my/frequent/category/" + qnaSetCategory2.getId()) + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()) + .body("result.content", hasSize(0)); + } + } + + @Nested + class 나의_면접_질문_검색할_때 { + + @Test + void 모든_질문_검색을_성공한다() { + // given + Set inclusionLevels = new HashSet<>(); + inclusionLevels.add(StarInclusionLevel.NULL); + + QnaSetSearchRequest request = new QnaSetSearchRequest( + null, + new QnaSetSearchRequest.QnaSearchFilter( + null, + inclusionLevels, + inclusionLevels, + inclusionLevels, + inclusionLevels + ) + ); + + // when & then + given(spec) + .body(request) + .when() + .post("/qna-set/my/search") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()) + .body("result.content", hasSize(4)); + } + } +}