From 032377587f8614114766a5039c18b87a8bc581cd Mon Sep 17 00:00:00 2001 From: zxc534 Date: Wed, 11 Feb 2026 14:19:09 +0900 Subject: [PATCH 01/20] =?UTF-8?q?feat:=20QnaSetIntegrationTest=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/prompt/star_analysis_header.txt | 48 +++++++++++++++++++ backend/prompt/star_analysis_tail.txt | 12 +++++ .../qnaset/QnaSetIntegrationTest.java | 6 +++ 3 files changed, 66 insertions(+) create mode 100644 backend/prompt/star_analysis_header.txt create mode 100644 backend/prompt/star_analysis_tail.txt create mode 100644 backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetIntegrationTest.java diff --git a/backend/prompt/star_analysis_header.txt b/backend/prompt/star_analysis_header.txt new file mode 100644 index 000000000..6e0f06037 --- /dev/null +++ b/backend/prompt/star_analysis_header.txt @@ -0,0 +1,48 @@ +너는 면접 답변을 구조적으로 분석하는 도우미다. +답변의 좋고 나쁨을 평가하거나 점수화하지 말고, +STAR 기법 기준으로 구조적 요소의 포함 수준만 판단하라. + +STAR 정의는 다음과 같다: + +- Situation (S): 상황, 배경, 문제 발생 맥락 + → 언제, 어떤 환경에서, 어떤 문제가 발생했는지가 제3자가 이해 가능해야 한다. + +- Task (T): 당시 본인의 역할, 책임, 해결해야 했던 과제 + → 팀이 아닌 ‘본인’에게 주어진 역할이나 책임이 명확히 드러나야 한다. + +- Action (A): 본인이 실제로 수행한 구체적인 행동 + → 단순 참여가 아니라, 무엇을 어떻게 했는지가 드러나야 한다. + +- Result (R): 행동의 결과, 성과, 변화 또는 배운 점 + → 수치, 전후 비교, 명확한 변화 중 하나 이상이 포함되어야 한다. + +--- + +각 요소는 아래 3단계 중 하나로 판단한다: + +- "PRESENT" + → 해당 요소가 명시적으로 언급되었고, + 내용이 구체적이며 제3자가 읽어도 충분히 이해 가능하다. + +- "INSUFFICIENT" + → 요소가 언급되었으나, + 추상적이거나 설명이 짧아 맥락·행동·결과가 충분히 드러나지 않는다. + +- "ABSENT" + → 해당 요소에 대한 언급이 전혀 없다. + +--- + +판단 시 공통 규칙: + +- 암시적 언급은 반드시 "INSUFFICIENT"으로 판단한다. +- 역할, 행동, 결과가 불명확한 경우 "PRESENT"으로 판단하지 마라. +- 단순한 표현 + (예: “회의를 진행했다”, “문제가 줄었다”, “잘 마무리되었다”)는 + 구체적 설명이 없을 경우 반드시 "INSUFFICIENT"이다. +- 판단이 애매한 경우에는 반드시 "INSUFFICIENT"으로 판단하라. +- 평가, 점수화, 조언은 하지 말고 구조적 판단만 수행한다. + +--- + +아래 면접 답변을 STAR 기준으로 분석하라. \ No newline at end of file diff --git a/backend/prompt/star_analysis_tail.txt b/backend/prompt/star_analysis_tail.txt new file mode 100644 index 000000000..25d3e09db --- /dev/null +++ b/backend/prompt/star_analysis_tail.txt @@ -0,0 +1,12 @@ +--- + +반드시 아래 JSON 형식으로만 출력하라. +JSON 외의 텍스트는 절대 출력하지 마라. + +{ + "S": "PRESENT | INSUFFICIENT | ABSENT", + "T": "PRESENT | INSUFFICIENT | ABSENT", + "A": "PRESENT | INSUFFICIENT | ABSENT", + "R": "PRESENT | INSUFFICIENT | ABSENT", + "overall_summary": "string" +} \ No newline at end of file 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 new file mode 100644 index 000000000..a0ea61ad0 --- /dev/null +++ b/backend/src/test/java/com/shyashyashya/refit/integration/qnaset/QnaSetIntegrationTest.java @@ -0,0 +1,6 @@ +package com.shyashyashya.refit.integration.qnaset; + +import com.shyashyashya.refit.core.IntegrationTest; + +public class QnaSetIntegrationTest extends IntegrationTest { +} From 69fb4cd10d215d470f42a3962719af515de0122c Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 09:11:36 +0900 Subject: [PATCH 02/20] =?UTF-8?q?test:=20=EC=A7=88=EB=8B=B5=5F=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=5F=EC=83=9D=EC=84=B1=EC=97=90=5F=EC=84=B1=EA=B3=B5?= =?UTF-8?q?=ED=95=9C=EB=8B=A4=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qnaset/QnaSetIntegrationTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) 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 a0ea61ad0..761afebcd 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 @@ -1,6 +1,73 @@ package com.shyashyashya.refit.integration.qnaset; +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.notNullValue; + 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.InterviewType; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; public class QnaSetIntegrationTest extends IntegrationTest { + + @Nested + class 질답_세트_생성_시 { + + @Test + void 질답_세트_생성에_성공한다() { + // given + InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + Interview interview1 = createInterview(interviewCreateRequest); + QnaSetCreateRequest request = new QnaSetCreateRequest("test question text", "test answer text"); + + // when & then + given(spec) + .body(request) + .when() + .post("/interview/" + interview1.getId() + "/qna-set") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()) + .body("result.qnaSetId", notNullValue()); + } + + } + +// @Nested +// class 어려웠던_질문_마킹_해제_시 { +// +// private static final String path = "/qna-set"; +// private Long qnaSetId; +// +// @BeforeEach +// void setUp() { +// +// } +// +// @Test +// void 어려웠던_질문_마킹에_성공한다() { +// // given +// +// +// // when & then +// given(spec). +// when(). +// patch(path + "/" + qnaSetId). +// then(). +// statusCode(200). +// body("code", equalTo(COMMON200.name())). +// body("message", equalTo(COMMON200.getMessage())). +// body("result", nullValue()); +// } +// } } From 19674de49a0cc996113c9e6efa60a90caea60667 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 09:12:41 +0900 Subject: [PATCH 03/20] =?UTF-8?q?feat:=20=EC=A7=88=EB=8B=B5=20=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20interview=EA=B0=80?= =?UTF-8?q?=20qnaSetDraft=20=EC=83=81=ED=83=9C=EC=9D=B8=EC=A7=80=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?:=20=E2=82=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refit/domain/interview/service/InterviewService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/interview/service/InterviewService.java b/backend/src/main/java/com/shyashyashya/refit/domain/interview/service/InterviewService.java index cbf804171..c69b72198 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/interview/service/InterviewService.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/interview/service/InterviewService.java @@ -217,6 +217,7 @@ public QnaSetCreateResponse createQnaSet(Long interviewId, QnaSetCreateRequest r Interview interview = interviewRepository.findById(interviewId).orElseThrow(() -> new CustomException(INTERVIEW_NOT_FOUND)); interviewValidator.validateInterviewOwner(interview, requestUser); + interviewValidator.validateInterviewReviewStatusQnaSetDraft(interview); QnaSet createdQnaSet = qnaSetRepository.save( QnaSet.create(request.questionText(), request.answerText(), false, interview, null)); From 90c60c3e9a680bfdf8c50aa04a70098df4cdfad6 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 09:26:48 +0900 Subject: [PATCH 04/20] =?UTF-8?q?test:=20=EC=9D=B8=ED=84=B0=EB=B7=B0=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EC=97=90=20=EA=B2=80=EC=A6=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EB=A1=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/qnaset/QnaSetIntegrationTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 761afebcd..062f92919 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 @@ -3,6 +3,7 @@ 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.in; import static org.hamcrest.Matchers.notNullValue; import com.shyashyashya.refit.core.IntegrationTest; @@ -10,22 +11,30 @@ import com.shyashyashya.refit.domain.interview.dto.request.QnaSetCreateRequest; import com.shyashyashya.refit.domain.interview.model.Interview; import com.shyashyashya.refit.domain.interview.model.InterviewType; +import com.shyashyashya.refit.domain.interview.repository.InterviewRepository; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; public class QnaSetIntegrationTest extends IntegrationTest { + @Autowired + private InterviewRepository interviewRepository; + @Nested class 질답_세트_생성_시 { @Test - void 질답_세트_생성에_성공한다() { + void 인터뷰가_QNA_SET_DRAFT_상태이면_질답_세트_생성에_성공한다() { // given InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); Interview interview1 = createInterview(interviewCreateRequest); + interview1.startLogging(); + interview1.completeLogging(); + interviewRepository.save(interview1); QnaSetCreateRequest request = new QnaSetCreateRequest("test question text", "test answer text"); // when & then From 0fd411bd3834553305339b95670e2280e7a37ca4 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 09:59:35 +0900 Subject: [PATCH 05/20] =?UTF-8?q?chore:=20=ED=94=84=EB=A1=AC=ED=94=84?= =?UTF-8?q?=ED=8A=B8=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/prompt/star_analysis_header.txt | 48 ------------------------- backend/prompt/star_analysis_tail.txt | 12 ------- 2 files changed, 60 deletions(-) delete mode 100644 backend/prompt/star_analysis_header.txt delete mode 100644 backend/prompt/star_analysis_tail.txt diff --git a/backend/prompt/star_analysis_header.txt b/backend/prompt/star_analysis_header.txt deleted file mode 100644 index 6e0f06037..000000000 --- a/backend/prompt/star_analysis_header.txt +++ /dev/null @@ -1,48 +0,0 @@ -너는 면접 답변을 구조적으로 분석하는 도우미다. -답변의 좋고 나쁨을 평가하거나 점수화하지 말고, -STAR 기법 기준으로 구조적 요소의 포함 수준만 판단하라. - -STAR 정의는 다음과 같다: - -- Situation (S): 상황, 배경, 문제 발생 맥락 - → 언제, 어떤 환경에서, 어떤 문제가 발생했는지가 제3자가 이해 가능해야 한다. - -- Task (T): 당시 본인의 역할, 책임, 해결해야 했던 과제 - → 팀이 아닌 ‘본인’에게 주어진 역할이나 책임이 명확히 드러나야 한다. - -- Action (A): 본인이 실제로 수행한 구체적인 행동 - → 단순 참여가 아니라, 무엇을 어떻게 했는지가 드러나야 한다. - -- Result (R): 행동의 결과, 성과, 변화 또는 배운 점 - → 수치, 전후 비교, 명확한 변화 중 하나 이상이 포함되어야 한다. - ---- - -각 요소는 아래 3단계 중 하나로 판단한다: - -- "PRESENT" - → 해당 요소가 명시적으로 언급되었고, - 내용이 구체적이며 제3자가 읽어도 충분히 이해 가능하다. - -- "INSUFFICIENT" - → 요소가 언급되었으나, - 추상적이거나 설명이 짧아 맥락·행동·결과가 충분히 드러나지 않는다. - -- "ABSENT" - → 해당 요소에 대한 언급이 전혀 없다. - ---- - -판단 시 공통 규칙: - -- 암시적 언급은 반드시 "INSUFFICIENT"으로 판단한다. -- 역할, 행동, 결과가 불명확한 경우 "PRESENT"으로 판단하지 마라. -- 단순한 표현 - (예: “회의를 진행했다”, “문제가 줄었다”, “잘 마무리되었다”)는 - 구체적 설명이 없을 경우 반드시 "INSUFFICIENT"이다. -- 판단이 애매한 경우에는 반드시 "INSUFFICIENT"으로 판단하라. -- 평가, 점수화, 조언은 하지 말고 구조적 판단만 수행한다. - ---- - -아래 면접 답변을 STAR 기준으로 분석하라. \ No newline at end of file diff --git a/backend/prompt/star_analysis_tail.txt b/backend/prompt/star_analysis_tail.txt deleted file mode 100644 index 25d3e09db..000000000 --- a/backend/prompt/star_analysis_tail.txt +++ /dev/null @@ -1,12 +0,0 @@ ---- - -반드시 아래 JSON 형식으로만 출력하라. -JSON 외의 텍스트는 절대 출력하지 마라. - -{ - "S": "PRESENT | INSUFFICIENT | ABSENT", - "T": "PRESENT | INSUFFICIENT | ABSENT", - "A": "PRESENT | INSUFFICIENT | ABSENT", - "R": "PRESENT | INSUFFICIENT | ABSENT", - "overall_summary": "string" -} \ No newline at end of file From c2c6785fd131db0a4f6d9c64d639e50ff201b689 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 11:00:51 +0900 Subject: [PATCH 06/20] =?UTF-8?q?test:=20=EC=96=B4=EB=A0=A4=EC=9B=A0?= =?UTF-8?q?=EB=8D=98=20=EC=A7=88=EB=AC=B8=20=EB=A7=88=ED=82=B9=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D/=ED=95=B4=EC=A0=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refit/core/IntegrationTest.java | 17 ++++ .../qnaset/QnaSetIntegrationTest.java | 97 +++++++++++++------ 2 files changed, 87 insertions(+), 27 deletions(-) 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 1bc7783e4..743366ca9 100644 --- a/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java +++ b/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java @@ -7,10 +7,13 @@ import com.shyashyashya.refit.domain.industry.model.Industry; import com.shyashyashya.refit.domain.industry.repository.IndustryRepository; 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.repository.InterviewRepository; import com.shyashyashya.refit.domain.jobcategory.model.JobCategory; import com.shyashyashya.refit.domain.jobcategory.repository.JobCategoryRepository; +import com.shyashyashya.refit.domain.qnaset.model.QnaSet; +import com.shyashyashya.refit.domain.qnaset.repository.QnaSetRepository; import com.shyashyashya.refit.domain.user.model.User; import com.shyashyashya.refit.domain.user.repository.UserRepository; import com.shyashyashya.refit.global.auth.service.JwtEncoder; @@ -78,6 +81,8 @@ public abstract class IntegrationTest { @Autowired private CompanyRepository companyRepository; + @Autowired + private QnaSetRepository qnaSetRepository; @BeforeEach void restAssuredSetUp() { @@ -161,4 +166,16 @@ protected Company createCompany(String companyName) { Company company = Company.create(companyName, "logo.url", true); return companyRepository.save(company); } + + protected QnaSet createQnaSet(QnaSetCreateRequest request, Interview interview, boolean isMarkedDifficult) { + QnaSet qnaSet = QnaSet.create( + request.questionText(), + request.answerText(), + isMarkedDifficult, + interview, + null + ); + + return qnaSetRepository.save(qnaSet); + } } 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 062f92919..cd9eb1531 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 @@ -1,10 +1,12 @@ package com.shyashyashya.refit.integration.qnaset; +import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT; 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.in; import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; import com.shyashyashya.refit.core.IntegrationTest; import com.shyashyashya.refit.domain.interview.dto.request.InterviewCreateRequest; @@ -12,6 +14,8 @@ import com.shyashyashya.refit.domain.interview.model.Interview; import com.shyashyashya.refit.domain.interview.model.InterviewType; import com.shyashyashya.refit.domain.interview.repository.InterviewRepository; +import com.shyashyashya.refit.domain.qnaset.model.QnaSet; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -50,33 +54,72 @@ class 질답_세트_생성_시 { .body("result.qnaSetId", notNullValue()); } + @Test + void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_생성에_성공한다() { + // given + InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + Interview interview1 = createInterview(interviewCreateRequest); + QnaSetCreateRequest request = new QnaSetCreateRequest("test question text", "test answer text"); + + // when & then + given(spec) + .body(request) + .when() + .post("/interview/" + interview1.getId() + "/qna-set") + .then() + .statusCode(400) + .body("code", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.name())) + .body("message", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.getMessage())) + .body("result", nullValue()); + } } -// @Nested -// class 어려웠던_질문_마킹_해제_시 { -// -// private static final String path = "/qna-set"; -// private Long qnaSetId; -// -// @BeforeEach -// void setUp() { -// -// } -// -// @Test -// void 어려웠던_질문_마킹에_성공한다() { -// // given -// -// -// // when & then -// given(spec). -// when(). -// patch(path + "/" + qnaSetId). -// then(). -// statusCode(200). -// body("code", equalTo(COMMON200.name())). -// body("message", equalTo(COMMON200.getMessage())). -// body("result", nullValue()); -// } -// } + @Nested + class 어려웠던_질문_마킹_시 { + + private Interview interview; + private Long qnaSetId; + + @BeforeEach + void setUp() { + InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + interview = createInterview(interviewCreateRequest); + + QnaSetCreateRequest qnaSetCreateRequest = new QnaSetCreateRequest ("test qqq text", "test aaa text"); + QnaSet qnaSet = createQnaSet(qnaSetCreateRequest, interview, false); + qnaSetId = qnaSet.getId(); + } + + @Test + void 어려웠던_질문_마킹에_성공한다() { + // given + + // when & then + given(spec). + when(). + patch("/qna-set/" + qnaSetId + "/difficult/mark"). + then(). + statusCode(200). + body("code", equalTo(COMMON200.name())). + body("message", equalTo(COMMON200.getMessage())). + body("result", nullValue()); + } + + @Test + void 어려웠던_질문_마킹_해제에_성공한다() { + // given + + // when & then + given(spec). + when(). + patch("/qna-set/" + qnaSetId + "/difficult/unmark"). + then(). + statusCode(200). + body("code", equalTo(COMMON200.name())). + body("message", equalTo(COMMON200.getMessage())). + body("result", nullValue()); + } + } } From 3176285ddc12ec1324579d90d8311be7091280bd Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 11:37:17 +0900 Subject: [PATCH 07/20] =?UTF-8?q?feat:=20=EC=9D=B8=ED=84=B0=EB=B7=B0=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=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 --- .../shyashyashya/refit/domain/qnaset/api/QnaSetController.java | 1 - .../shyashyashya/refit/domain/qnaset/service/QnaSetService.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) 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 c1f691c6e..dce062659 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 @@ -74,7 +74,6 @@ public ResponseEntity> unmarkDifficultQuestion(@PathVariable L @PutMapping("/{qnaSetId}") public ResponseEntity> updateQnaSet( @PathVariable Long qnaSetId, @Valid @RequestBody QnaSetUpdateRequest request) { - // TODO : 질문 답변 내용 수정이 '기록중' 상태에서만 가능하도록 검증 추가 qnaSetService.updateQnaSet(qnaSetId, request); var response = ApiResponse.success(COMMON200); return ResponseEntity.ok(response); diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java index 4a0f4859d..82e2f25cc 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java @@ -76,6 +76,7 @@ public void unmarkDifficultQuestion(Long qnaSetId) { @Transactional public void updateQnaSet(Long qnaSetId, QnaSetUpdateRequest request) { QnaSet qnaSet = getValidatedQnaSet(qnaSetId); + interviewValidator.validateInterviewReviewStatusQnaSetDraft(qnaSet.getInterview()); qnaSet.updateQuestionText(request.questionText()); qnaSet.updateAnswerText(request.answerText()); updateOrCreateSelfReview(qnaSet, request.selfReviewText()); From 572fdaea4732e470868e37dcef896dbe67ce6d0b Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 11:37:40 +0900 Subject: [PATCH 08/20] =?UTF-8?q?test:=20=EC=A7=88=EB=8B=B5=20=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qnaset/QnaSetIntegrationTest.java | 77 ++++++++++++++++++- 1 file changed, 73 insertions(+), 4 deletions(-) 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 cd9eb1531..496f073df 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 @@ -14,6 +14,7 @@ import com.shyashyashya.refit.domain.interview.model.Interview; import com.shyashyashya.refit.domain.interview.model.InterviewType; import com.shyashyashya.refit.domain.interview.repository.InterviewRepository; +import com.shyashyashya.refit.domain.qnaset.dto.request.QnaSetUpdateRequest; import com.shyashyashya.refit.domain.qnaset.model.QnaSet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -83,10 +84,10 @@ class 어려웠던_질문_마킹_시 { @BeforeEach void setUp() { - InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( - LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - interview = createInterview(interviewCreateRequest); - + interview = createInterview( + new InterviewCreateRequest( + 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); qnaSetId = qnaSet.getId(); @@ -122,4 +123,72 @@ void setUp() { body("result", nullValue()); } } + + @Nested + class 질답_세트_수정_시 { + + private Interview qnaSetDraftInterview; + private Interview debriefCompletedInterview; + private QnaSet qnaSetDraftQnaSet; + private QnaSet debriefCompletedQnaSet; + + @BeforeEach + void setUp() { + InterviewCreateRequest interviewCreateRequest1 = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + qnaSetDraftInterview = createInterview(interviewCreateRequest1); + qnaSetDraftInterview.startLogging(); + qnaSetDraftInterview.completeLogging(); + interviewRepository.save(qnaSetDraftInterview); + + InterviewCreateRequest interviewCreateRequest2 = new InterviewCreateRequest( + LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); + debriefCompletedInterview = createInterview(interviewCreateRequest2); + debriefCompletedInterview.startLogging(); + debriefCompletedInterview.completeLogging(); + debriefCompletedInterview.completeQnaSetDraft(); + debriefCompletedInterview.completeReview(); + interviewRepository.save(debriefCompletedInterview); + + QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); + qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); + + QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); + debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); + } + + @Test + void 인터뷰가_QNA_SET_DRAFT_상태이면_질답_세트_수정에_성공한다() { + // given + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); + + // when & then + given(spec) + .body(qnaSetUpdateRequest) + .when() + .put("/qna-set/" + qnaSetDraftQnaSet.getId()) + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", nullValue()); + } + + @Test + void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_수정에_실패한다() { + // given + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); + + // when & then + given(spec) + .body(qnaSetUpdateRequest) + .when() + .put("/qna-set/" + debriefCompletedQnaSet.getId()) + .then() + .statusCode(400) + .body("code", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.name())) + .body("message", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.getMessage())) + .body("result", nullValue()); + } + } } From 5e187144dc04e4d687a3a55e5b0aaeb1fd9208f2 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 11:54:19 +0900 Subject: [PATCH 09/20] =?UTF-8?q?test:=20=EB=A9=B4=EC=A0=91=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20=EA=B0=84=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/qnaset/service/QnaSetService.java | 2 +- .../qnaset/QnaSetIntegrationTest.java | 35 ++++++------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java index 42a41e138..3c57790cd 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java @@ -75,7 +75,7 @@ public void unmarkDifficultQuestion(Long qnaSetId) { @Transactional public void updateQnaSet(Long qnaSetId, QnaSetUpdateRequest request) { QnaSet qnaSet = getValidatedQnaSet(qnaSetId); - interviewValidator.validateInterviewReviewStatusQnaSetDraft(qnaSet.getInterview()); + interviewValidator.validateInterviewReviewStatus(qnaSet.getInterview(), InterviewReviewStatus.QNA_SET_DRAFT); qnaSet.updateQuestionText(request.questionText()); qnaSet.updateAnswerText(request.answerText()); updateOrCreateSelfReview(qnaSet, request.selfReviewText()); 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 efc2d3a2a..abcb285ae 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 @@ -1,10 +1,9 @@ package com.shyashyashya.refit.integration.qnaset; -import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT; +import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED; 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.in; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -12,6 +11,7 @@ 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.interview.repository.InterviewRepository; import com.shyashyashya.refit.domain.qnaset.dto.request.QnaSetUpdateRequest; @@ -36,10 +36,7 @@ class 질답_세트_생성_시 { // given InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview interview1 = createInterview(interviewCreateRequest); - interview1.startLogging(); - interview1.completeLogging(); - interviewRepository.save(interview1); + Interview interview1 = createAndSaveInterview(interviewCreateRequest, InterviewReviewStatus.QNA_SET_DRAFT); QnaSetCreateRequest request = new QnaSetCreateRequest("test question text", "test answer text"); // when & then @@ -60,7 +57,7 @@ class 질답_세트_생성_시 { // given InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - Interview interview1 = createInterview(interviewCreateRequest); + Interview interview1 = createAndSaveInterview(interviewCreateRequest); QnaSetCreateRequest request = new QnaSetCreateRequest("test question text", "test answer text"); // when & then @@ -70,8 +67,8 @@ class 질답_세트_생성_시 { .post("/interview/" + interview1.getId() + "/qna-set") .then() .statusCode(400) - .body("code", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.name())) - .body("message", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.getMessage())) + .body("code", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.name())) + .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) .body("result", nullValue()); } } @@ -84,7 +81,7 @@ class 어려웠던_질문_마킹_시 { @BeforeEach void setUp() { - interview = createInterview( + interview = createAndSaveInterview( new InterviewCreateRequest( LocalDateTime.of(2023, 1, 10, 10, 0, 0), InterviewType.FIRST, company1.getName(), industry1.getId(), jobCategory1.getId(), "Developer" )); @@ -127,8 +124,6 @@ void setUp() { @Nested class 질답_세트_수정_시 { - private Interview qnaSetDraftInterview; - private Interview debriefCompletedInterview; private QnaSet qnaSetDraftQnaSet; private QnaSet debriefCompletedQnaSet; @@ -136,19 +131,11 @@ class 질답_세트_수정_시 { void setUp() { InterviewCreateRequest interviewCreateRequest1 = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer"); - qnaSetDraftInterview = createInterview(interviewCreateRequest1); - qnaSetDraftInterview.startLogging(); - qnaSetDraftInterview.completeLogging(); - interviewRepository.save(qnaSetDraftInterview); + 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"); - debriefCompletedInterview = createInterview(interviewCreateRequest2); - debriefCompletedInterview.startLogging(); - debriefCompletedInterview.completeLogging(); - debriefCompletedInterview.completeQnaSetDraft(); - debriefCompletedInterview.completeReview(); - interviewRepository.save(debriefCompletedInterview); + Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); @@ -203,8 +190,8 @@ void setUp() { .put("/qna-set/" + debriefCompletedQnaSet.getId()) .then() .statusCode(400) - .body("code", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.name())) - .body("message", equalTo(INTERVIEW_REVIEW_STATUS_IS_NOT_QNA_SET_DRAFT.getMessage())) + .body("code", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.name())) + .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) .body("result", nullValue()); } } From 3a67be1bff864db175fc28c840464130ce3c3463 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 11:57:53 +0900 Subject: [PATCH 10/20] =?UTF-8?q?test:=20=EC=A7=88=EB=8B=B5=20=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../qnaset/QnaSetIntegrationTest.java | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) 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 abcb285ae..00f4b3d15 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 @@ -1,6 +1,7 @@ package com.shyashyashya.refit.integration.qnaset; import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED; +import static com.shyashyashya.refit.global.exception.ErrorCode.QNA_SET_NOT_FOUND; import static com.shyashyashya.refit.global.model.ResponseCode.COMMON200; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; @@ -124,8 +125,8 @@ void setUp() { @Nested class 질답_세트_수정_시 { - private QnaSet qnaSetDraftQnaSet; - private QnaSet debriefCompletedQnaSet; + private Long qnaSetDraftQnaSetId; + private Long debriefCompletedQnaSetId; @BeforeEach void setUp() { @@ -138,22 +139,24 @@ void setUp() { Interview debriefCompletedInterview = createAndSaveInterview(interviewCreateRequest2, InterviewReviewStatus.DEBRIEF_COMPLETED); QnaSetCreateRequest qnaSetCreateRequest1 = new QnaSetCreateRequest("test question text", "test answer text"); - qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); + QnaSet qnaSetDraftQnaSet = createQnaSet(qnaSetCreateRequest1, qnaSetDraftInterview, true); + qnaSetDraftQnaSetId = qnaSetDraftQnaSet.getId(); QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); - debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); + QnaSet debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); + debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); } @Test void 인터뷰가_QNA_SET_DRAFT_상태이면_질답_세트_수정에_성공한다() { // given - QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", "self review self review"); // when & then given(spec) .body(qnaSetUpdateRequest) .when() - .put("/qna-set/" + qnaSetDraftQnaSet.getId()) + .put("/qna-set/" + qnaSetDraftQnaSetId) .then() .statusCode(200) .body("code", equalTo(COMMON200.name())) @@ -162,7 +165,7 @@ void setUp() { } @Test - void 수정_요청에_필드가_하나여도_질답_세트_수정에_성공한다() { + void 수정_요청에_필드가_하나일_때_질답_세트_수정에_성공한다() { // given QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("only question text update", null, null); @@ -170,7 +173,7 @@ void setUp() { given(spec) .body(qnaSetUpdateRequest) .when() - .put("/qna-set/" + qnaSetDraftQnaSet.getId()) + .put("/qna-set/" + qnaSetDraftQnaSetId) .then() .statusCode(200) .body("code", equalTo(COMMON200.name())) @@ -178,6 +181,23 @@ void setUp() { .body("result", nullValue()); } + @Test + void 수정_요청이_빈_문자열일_때_질답_세트_수정에_성공한다() { + // given + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("", null, ""); + + // 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()); + } + @Test void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_수정에_실패한다() { // given @@ -187,12 +207,29 @@ void setUp() { given(spec) .body(qnaSetUpdateRequest) .when() - .put("/qna-set/" + debriefCompletedQnaSet.getId()) + .put("/qna-set/" + debriefCompletedQnaSetId) .then() .statusCode(400) .body("code", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.name())) .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) .body("result", nullValue()); } + + @Test + void QNA_SET_이_존재하지_않으면_질답_세트_수정에_실패한다() { + // given + QnaSetUpdateRequest qnaSetUpdateRequest = new QnaSetUpdateRequest("update question", "update answer", null); + + // when & then + given(spec) + .body(qnaSetUpdateRequest) + .when() + .put("/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()); + } } } From 6b70636eed6872798b85ec035c262441ff3b5c49 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 12:11:54 +0900 Subject: [PATCH 11/20] =?UTF-8?q?test:=20=EC=A7=88=EB=AC=B8=20=EB=8B=B5?= =?UTF-8?q?=EB=B3=80=20=EC=84=B8=ED=8A=B8=20=EC=82=AD=EC=A0=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qnaset/QnaSetIntegrationTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) 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 00f4b3d15..d1124ff34 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 @@ -3,6 +3,7 @@ import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED; import static com.shyashyashya.refit.global.exception.ErrorCode.QNA_SET_NOT_FOUND; import static com.shyashyashya.refit.global.model.ResponseCode.COMMON200; +import static com.shyashyashya.refit.global.model.ResponseCode.COMMON204; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; @@ -232,4 +233,61 @@ void setUp() { .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_상태이면_질답_세트_삭제에_성공한다() { + // given + + // when & then + given(spec) + .when() + .delete("/qna-set/" + qnaSetDraftQnaSetId) + .then() + .statusCode(200) + .body("code", equalTo(COMMON204.name())) + .body("message", equalTo(COMMON204.getMessage())) + .body("result", nullValue()); + } + + @Test + void 인터뷰가_QNA_SET_DRAFT_상태가_아니면_질답_세트_삭제에_실패한다() { + // given + + // when & then + given(spec) + .when() + .delete("/qna-set/" + debriefCompletedQnaSetId) + .then() + .statusCode(400) + .body("code", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.name())) + .body("message", equalTo(INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED.getMessage())) + .body("result", nullValue()); + } + } } From 80090dc597dc9e926b982723afab24fa6fdcc39e Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 12:14:20 +0900 Subject: [PATCH 12/20] =?UTF-8?q?docs:=20=ED=95=98=EC=9D=B4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=ED=8C=85=20=EB=93=B1=EB=A1=9D/=EC=88=98=EC=A0=95=20AP?= =?UTF-8?q?I=20swagger=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refit/domain/qnaset/api/QnaSetController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 8616284fa..df47eeaf1 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 @@ -71,7 +71,7 @@ public ResponseEntity> unmarkDifficultQuestion(@PathVariable L return ResponseEntity.ok(response); } - @Operation(summary = "지정한 질문 답변 세트의 질문 답변 내용을 수정합니다.", description = "질문 답변 내용 수정은 '기록중' 상태에서만 가능합니다.") + @Operation(summary = "지정한 질문 답변 세트의 질문 답변 내용을 수정합니다.", description = "질문 답변 내용 수정은 'QnaSetDraft' 상태에서만 가능합니다.") @PutMapping("/{qnaSetId}") public ResponseEntity> updateQnaSet( @PathVariable Long qnaSetId, @Valid @RequestBody QnaSetUpdateRequest request) { @@ -88,7 +88,7 @@ public ResponseEntity> deleteQnaSet(@PathVariable Long qnaSetI return ResponseEntity.ok(resposne); } - @Operation(summary = "지정한 질문 답변 세트에 대해 PDF 하이라이팅 정보를 등록/수정합니다.") + @Operation(summary = "지정한 질문 답변 세트에 대해 PDF 하이라이팅 정보를 등록/수정합니다.", description = "PDF 하이라이팅 정보 등록/수정은 'QnaSetDraft' 상태에서만 가능합니다.") @PutMapping("/{qnaSetId}/pdf-highlightings") public ResponseEntity> updatePdfHighlighting( @PathVariable Long qnaSetId, @Valid @RequestBody List request) { From 4f2558b157ebec17b6bed27d074df648bd11c839 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 12:18:47 +0900 Subject: [PATCH 13/20] =?UTF-8?q?feat:=20PDF=20=ED=95=98=EC=9D=B4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=ED=8C=85=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EC=8B=9C=20=EB=A9=B4=EC=A0=91=20=EC=83=81=ED=83=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refit/domain/qnaset/service/QnaSetService.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java index 3c57790cd..2c3ca2916 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/service/QnaSetService.java @@ -91,6 +91,7 @@ public void deleteQnaSet(Long qnaSetId) { @Transactional public void updatePdfHighlighting(Long qnaSetId, List request) { QnaSet qnaSet = getValidatedQnaSet(qnaSetId); + interviewValidator.validateInterviewReviewStatus(qnaSet.getInterview(), InterviewReviewStatus.QNA_SET_DRAFT); deleteAllHighlightingsAndRects(qnaSet); saveAllHighlightings(qnaSet, request); } @@ -136,13 +137,6 @@ public Page getMyScrapFoldersWithQnaSetContainingInfo return qnaSetScrapFolderRepository.findAllScrapFoldersWithQnaSetContainingInfo(requestUser, qnaSet, pageable); } - private List removeDuplicatedIds(List list) { - if (list == null) { - return null; - } - return list.stream().distinct().toList(); - } - private QnaSet getValidatedQnaSet(Long qnaSetId) { QnaSet qnaSet = qnaSetRepository.findById(qnaSetId).orElseThrow(() -> new CustomException(QNA_SET_NOT_FOUND)); User requestUser = requestUserContext.getRequestUser(); From 3071b23ecdab53136cc6e8c9071bae7c28852ce4 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 12:50:23 +0900 Subject: [PATCH 14/20] =?UTF-8?q?test:=20PDF=20=ED=95=98=EC=9D=B4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=ED=8C=85=20=EB=93=B1=EB=A1=9D=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qnaset/QnaSetIntegrationTest.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) 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 d1124ff34..780009a6f 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 @@ -16,6 +16,8 @@ import com.shyashyashya.refit.domain.interview.model.InterviewReviewStatus; import com.shyashyashya.refit.domain.interview.model.InterviewType; import com.shyashyashya.refit.domain.interview.repository.InterviewRepository; +import com.shyashyashya.refit.domain.qnaset.dto.PdfHighlightingRectDto; +import com.shyashyashya.refit.domain.qnaset.dto.request.PdfHighlightingUpdateRequest; import com.shyashyashya.refit.domain.qnaset.dto.request.QnaSetUpdateRequest; import com.shyashyashya.refit.domain.qnaset.model.QnaSet; import org.junit.jupiter.api.BeforeEach; @@ -24,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; +import java.util.List; public class QnaSetIntegrationTest extends IntegrationTest { @@ -290,4 +293,131 @@ void setUp() { .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); + + 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_상태이면_PDF_하이라이팅_등록에_성공한다() { + // given + List request = List.of( + new PdfHighlightingUpdateRequest( + "highlighting1 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 10), + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), + new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 1) + )), + new PdfHighlightingUpdateRequest( + "highlighting2 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 1), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 2), + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 3), + new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 4) + )), + new PdfHighlightingUpdateRequest( + "highlighting3 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 20201483.2, 13), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 13), + new PdfHighlightingRectDto(0.04, 1.592, 30.12, 4123.432, 13), + new PdfHighlightingRectDto(452.1, 123123.1, 30.12, 4123.432, 13) + )) + ); + + // when & then + given(spec) + .body(request) + .when() + .put("/qna-set/" + qnaSetDraftQnaSetId + "/pdf-highlightings") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", nullValue()); + } + + @Test + void 인터뷰가_QNA_SET_DRAFT_상태이면_비어있는_PDF_하이라이팅_등록에_성공한다() { + // given + List request = List.of(); + + // when & then + given(spec) + .body(request) + .when() + .put("/qna-set/" + qnaSetDraftQnaSetId + "/pdf-highlightings") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", nullValue()); + } + + @Test + void 인터뷰가_QNA_SET_DRAFT_상태가_아니면_PDF_하이라이팅_등록에_실패한다() { + // given + List request = List.of( + new PdfHighlightingUpdateRequest( + "highlighting1 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 10), + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), + new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 1) + )), + new PdfHighlightingUpdateRequest( + "highlighting2 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 1), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 2), + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 3), + new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 4) + )), + new PdfHighlightingUpdateRequest( + "highlighting3 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 20201483.2, 13), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 13), + new PdfHighlightingRectDto(0.04, 1.592, 30.12, 4123.432, 13), + new PdfHighlightingRectDto(452.1, 123123.1, 30.12, 4123.432, 13) + )) + ); + + // when & then + given(spec) + .body(request) + .when() + .put("/qna-set/" + debriefCompletedQnaSetId + "/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()); + } + } } From cad5846459e6a9ae4874fa021c954c10763f7c6d Mon Sep 17 00:00:00 2001 From: zxc534 Date: Fri, 13 Feb 2026 17:24:11 +0900 Subject: [PATCH 15/20] =?UTF-8?q?test:=20createAndSavePdfHighlighting=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refit/core/IntegrationTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) 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 75e4ff89b..177dfaa2f 100644 --- a/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java +++ b/backend/src/test/java/com/shyashyashya/refit/core/IntegrationTest.java @@ -13,7 +13,12 @@ import com.shyashyashya.refit.domain.interview.repository.InterviewRepository; import com.shyashyashya.refit.domain.jobcategory.model.JobCategory; import com.shyashyashya.refit.domain.jobcategory.repository.JobCategoryRepository; +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; import com.shyashyashya.refit.domain.user.model.User; import com.shyashyashya.refit.domain.user.repository.UserRepository; @@ -82,9 +87,16 @@ public abstract class IntegrationTest { @Autowired private CompanyRepository companyRepository; + @Autowired private QnaSetRepository qnaSetRepository; + @Autowired + private PdfHighlightingRepository pdfHighlightingRepository; + + @Autowired + private PdfHighlightingRectRepository pdfHighlightingRectRepository; + @BeforeEach void restAssuredSetUp() { clearDatabase(); @@ -205,4 +217,29 @@ protected QnaSet createQnaSet(QnaSetCreateRequest request, Interview interview, return qnaSetRepository.save(qnaSet); } + + protected List createAndSavePdfHighlighting(List requests, QnaSet qnaSet) { + List result = new ArrayList<>(); + + requests.forEach(request -> { + PdfHighlighting pdfHighlighting = PdfHighlighting.create(request.highlightingText(), qnaSet); + result.add(pdfHighlightingRepository.save(pdfHighlighting)); + + request.rects().forEach( + rectDto -> { + PdfHighlightingRect rect = PdfHighlightingRect.create( + rectDto.x(), + rectDto.y(), + rectDto.width(), + rectDto.height(), + rectDto.pageNumber(), + pdfHighlighting); + + pdfHighlightingRectRepository.save(rect); + } + ); + }); + + return result; + } } From 20b14372bf828d95f429d2a549ae91fa3b913602 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Sat, 14 Feb 2026 01:38:38 +0900 Subject: [PATCH 16/20] =?UTF-8?q?test:=20PDF=20=ED=95=98=EC=9D=B4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=ED=8C=85=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/qnaset/api/QnaSetController.java | 3 + .../qnaset/QnaSetIntegrationTest.java | 191 +++++++++++++----- 2 files changed, 140 insertions(+), 54 deletions(-) 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 df47eeaf1..3be443cc3 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 @@ -42,6 +42,7 @@ public class QnaSetController { private final QnaSetService qnaSetService; private final StarAnalysisAsyncService starAnalysisAsyncService; + // TODO 통합 테스트 작성 @Operation( summary = "지정한 산업군 / 직무의 빈출 질문 답변 세트를 조회합니다.", description = "지정한 산업군 / 직무의 빈출 질문 답변 세트를 조회합니다. 지정하지 않은 필드에 대해서는 전체를 대상으로 조회합니다.") @@ -105,6 +106,7 @@ public ResponseEntity>> getPdfHighlightings return ResponseEntity.ok(response); } + // TODO 통합 테스트 작성 (E2E 테스트는 일단 보류) @Operation(summary = "지정한 질문 답변 세트에 대해 스타 분석 생성을 요청합니다.", description = "Gemini 요청을 수행하고 10~20초 뒤에 응답이 반환됩니다.") @PostMapping("/{qnaSetId}/star-analysis") public CompletableFuture>> createStarAnalysis( @@ -114,6 +116,7 @@ public CompletableFuture>> createSta .thenApply(rsp -> ResponseEntity.ok(ApiResponse.success(COMMON200, rsp))); } + // TODO 통합 테스트 작성 @Operation(summary = "지정한 질문 답변 세트가 스크랩 폴더에 포함되어 있는 지 여부가 포함된 스크랩 폴더 리스트를 조회합니다.") @GetMapping("/{qnaSetId}/scrap-folder") public ResponseEntity>> getScrapFoldersContainingQnaSet( 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 780009a6f..82a184945 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 @@ -1,5 +1,6 @@ package com.shyashyashya.refit.integration.qnaset; +import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_NOT_ACCESSIBLE; import static com.shyashyashya.refit.global.exception.ErrorCode.INTERVIEW_REVIEW_STATUS_VALIDATION_FAILED; import static com.shyashyashya.refit.global.exception.ErrorCode.QNA_SET_NOT_FOUND; import static com.shyashyashya.refit.global.model.ResponseCode.COMMON200; @@ -20,6 +21,7 @@ import com.shyashyashya.refit.domain.qnaset.dto.request.PdfHighlightingUpdateRequest; import com.shyashyashya.refit.domain.qnaset.dto.request.QnaSetUpdateRequest; import com.shyashyashya.refit.domain.qnaset.model.QnaSet; +import com.shyashyashya.refit.domain.user.model.User; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -322,32 +324,7 @@ void setUp() { @Test void 인터뷰가_QNA_SET_DRAFT_상태이면_PDF_하이라이팅_등록에_성공한다() { // given - List request = List.of( - new PdfHighlightingUpdateRequest( - "highlighting1 text", - List.of( - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), - new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 10), - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), - new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 1) - )), - new PdfHighlightingUpdateRequest( - "highlighting2 text", - List.of( - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 1), - new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 2), - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 3), - new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 4) - )), - new PdfHighlightingUpdateRequest( - "highlighting3 text", - List.of( - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 20201483.2, 13), - new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 13), - new PdfHighlightingRectDto(0.04, 1.592, 30.12, 4123.432, 13), - new PdfHighlightingRectDto(452.1, 123123.1, 30.12, 4123.432, 13) - )) - ); + List request = createPdfHighlightUpdateRequest(); // when & then given(spec) @@ -381,43 +358,149 @@ void setUp() { @Test void 인터뷰가_QNA_SET_DRAFT_상태가_아니면_PDF_하이라이팅_등록에_실패한다() { // given - List request = List.of( - new PdfHighlightingUpdateRequest( - "highlighting1 text", - List.of( - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), - new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 10), - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), - new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 1) - )), - new PdfHighlightingUpdateRequest( - "highlighting2 text", - List.of( - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 1), - new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 2), - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 3), - new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 4) - )), - new PdfHighlightingUpdateRequest( - "highlighting3 text", - List.of( - new PdfHighlightingRectDto(3.14, 1.592, 30.12, 20201483.2, 13), - new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 13), - new PdfHighlightingRectDto(0.04, 1.592, 30.12, 4123.432, 13), - new PdfHighlightingRectDto(452.1, 123123.1, 30.12, 4123.432, 13) - )) - ); + List request = createPdfHighlightUpdateRequest(); // when & then given(spec) .body(request) - .when() + .when() .put("/qna-set/" + debriefCompletedQnaSetId + "/pdf-highlightings") - .then() + .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(); + + QnaSetCreateRequest qnaSetCreateRequest2 = new QnaSetCreateRequest("test question text", "test answer text"); + QnaSet debriefCompletedQnaSet = createQnaSet(qnaSetCreateRequest2, debriefCompletedInterview, true); + debriefCompletedQnaSetId = debriefCompletedQnaSet.getId(); + + QnaSetCreateRequest qnaSetCreateRequest3 = new QnaSetCreateRequest("this qna has pdf highlighting", "hello PDF"); + QnaSet qnaSetWithPdfHighlighting = createQnaSet(qnaSetCreateRequest3,qnaSetDraftInterview, false); + qnaSetWithPdfHighlightingId = qnaSetWithPdfHighlighting.getId(); + + + 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); + } + + @Test + void 나의_빈_PDF_하이라이팅_정보_조회를_성공한다() { + // given + + // when & then + given(spec) + .when() + .get("/qna-set/" + qnaSetDraftQnaSetId + "/pdf-highlightings") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()); + } + + @Test + void 나의_데이터가_있는_PDF_하이라이팅_정보_조회를_성공한다() { + // given + + // when & then + given(spec) + .when() + .get("/qna-set/" + qnaSetWithPdfHighlightingId + "/pdf-highlightings") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()); + } + + @Test + void 회고_완료_면접의_나의_PDF_하이라이팅_정보_조회를_성공한다() { + // given + + // when & then + given(spec) + .when() + .get("/qna-set/" + debriefCompletedQnaSetId + "/pdf-highlightings") + .then() + .statusCode(200) + .body("code", equalTo(COMMON200.name())) + .body("message", equalTo(COMMON200.getMessage())) + .body("result", notNullValue()); + } + + @Test + void 다른_사람의_PDF_하이라이팅_정보_조회를_실패한다() { + given(spec) + .when() + .get("/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()); + } + } + + private List createPdfHighlightUpdateRequest() { + return List.of( + new PdfHighlightingUpdateRequest( + "highlighting1 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 10), + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 10), + new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 1) + )), + new PdfHighlightingUpdateRequest( + "highlighting2 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 1), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 2), + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 4123.432, 3), + new PdfHighlightingRectDto(3.14, 123123.1, 30.12, 4123.432, 4) + )), + new PdfHighlightingUpdateRequest( + "highlighting3 text", + List.of( + new PdfHighlightingRectDto(3.14, 1.592, 30.12, 20201483.2, 13), + new PdfHighlightingRectDto(0.0, 1.592, 34.0, 4123.432, 13), + new PdfHighlightingRectDto(0.04, 1.592, 30.12, 4123.432, 13), + new PdfHighlightingRectDto(452.1, 123123.1, 30.12, 4123.432, 13) + )) + ); + } } From 3240dd8b04afdf86d469fbed61e15fb8a6316eae Mon Sep 17 00:00:00 2001 From: zxc534 Date: Sat, 14 Feb 2026 01:53:09 +0900 Subject: [PATCH 17/20] =?UTF-8?q?chore:=20spotless=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refit/domain/qnaset/api/QnaSetController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 3be443cc3..cf22b3dbf 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 @@ -89,7 +89,9 @@ public ResponseEntity> deleteQnaSet(@PathVariable Long qnaSetI return ResponseEntity.ok(resposne); } - @Operation(summary = "지정한 질문 답변 세트에 대해 PDF 하이라이팅 정보를 등록/수정합니다.", description = "PDF 하이라이팅 정보 등록/수정은 'QnaSetDraft' 상태에서만 가능합니다.") + @Operation( + summary = "지정한 질문 답변 세트에 대해 PDF 하이라이팅 정보를 등록/수정합니다.", + description = "PDF 하이라이팅 정보 등록/수정은 'QnaSetDraft' 상태에서만 가능합니다.") @PutMapping("/{qnaSetId}/pdf-highlightings") public ResponseEntity> updatePdfHighlighting( @PathVariable Long qnaSetId, @Valid @RequestBody List request) { From 35f80501b4ffe44beef3c3330bda730fa0745a93 Mon Sep 17 00:00:00 2001 From: zxc534 Date: Sat, 14 Feb 2026 02:04:38 +0900 Subject: [PATCH 18/20] =?UTF-8?q?test:=20=EC=8B=A4=EC=A0=9C=20=EA=B0=92=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=EC=9D=84=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 --- .../integration/qnaset/QnaSetIntegrationTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 82a184945..32675d7f0 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 @@ -6,6 +6,7 @@ import static com.shyashyashya.refit.global.model.ResponseCode.COMMON200; import static com.shyashyashya.refit.global.model.ResponseCode.COMMON204; import static io.restassured.RestAssured.given; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -21,6 +22,7 @@ import com.shyashyashya.refit.domain.qnaset.dto.request.PdfHighlightingUpdateRequest; import com.shyashyashya.refit.domain.qnaset.dto.request.QnaSetUpdateRequest; import com.shyashyashya.refit.domain.qnaset.model.QnaSet; +import com.shyashyashya.refit.domain.qnaset.repository.QnaSetRepository; import com.shyashyashya.refit.domain.user.model.User; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -34,6 +36,8 @@ public class QnaSetIntegrationTest extends IntegrationTest { @Autowired private InterviewRepository interviewRepository; + @Autowired + private QnaSetRepository qnaSetRepository; @Nested class 질답_세트_생성_시 { @@ -110,6 +114,9 @@ void setUp() { body("code", equalTo(COMMON200.name())). body("message", equalTo(COMMON200.getMessage())). body("result", nullValue()); + + QnaSet result = qnaSetRepository.findById(qnaSetId).get(); + assertThat(result.isMarkedDifficult()).isTrue(); } @Test @@ -125,6 +132,9 @@ void setUp() { body("code", equalTo(COMMON200.name())). body("message", equalTo(COMMON200.getMessage())). body("result", nullValue()); + + QnaSet result = qnaSetRepository.findById(qnaSetId).get(); + assertThat(result.isMarkedDifficult()).isFalse(); } } From 82e3ced8a266e50792dc709605ec530b52b2e60e Mon Sep 17 00:00:00 2001 From: zxc534 Date: Sat, 14 Feb 2026 02:05:09 +0900 Subject: [PATCH 19/20] =?UTF-8?q?fix:=20unmark=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EA=B0=92=EC=9D=84=20false=EB=A1=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=ED=95=98=EB=8F=84=EB=A1=9D=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 --- .../java/com/shyashyashya/refit/domain/qnaset/model/QnaSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/model/QnaSet.java b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/model/QnaSet.java index 02f76e1b3..f3519b60c 100644 --- a/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/model/QnaSet.java +++ b/backend/src/main/java/com/shyashyashya/refit/domain/qnaset/model/QnaSet.java @@ -79,7 +79,7 @@ public void markDifficult() { } public void unmarkDifficult() { - this.isMarkedDifficult = true; + this.isMarkedDifficult = false; } @Builder(access = AccessLevel.PRIVATE) From 9c8e3ec6531cccff71f43587dace4e9daf45694e Mon Sep 17 00:00:00 2001 From: zxc534 Date: Sat, 14 Feb 2026 02:06:56 +0900 Subject: [PATCH 20/20] =?UTF-8?q?chore:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9D=B4=EB=A6=84=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 --- .../refit/integration/qnaset/QnaSetIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 32675d7f0..56eb5c31c 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 @@ -64,7 +64,7 @@ class 질답_세트_생성_시 { } @Test - void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_생성에_성공한다() { + void 인터뷰가_QNA_SET_DRAFT_상태가_아니라면_질답_세트_생성에_실패한다() { // given InterviewCreateRequest interviewCreateRequest = new InterviewCreateRequest( LocalDateTime.of(2025, 12, 29, 10, 0, 0), InterviewType.FIRST, "현대자동차", 1L, 1L, "BE Developer");