From 221477d96dabeb8c75b6919d0b4296bfda091e36 Mon Sep 17 00:00:00 2001 From: BGuga Date: Mon, 23 Oct 2023 14:50:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=BB=A4=EB=A6=AC=ED=81=98?= =?UTF-8?q?=EB=9F=BC=20=EB=B3=84=20Quiz=20=EA=B2=80=EC=83=89=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prolog/roadmap/application/QuizService.java | 5 +++++ .../application/dto/CurriculumQuizResponse.java | 8 ++++++++ .../roadmap/domain/repository/QuizRepository.java | 10 ++++++++++ .../java/wooteco/prolog/roadmap/ui/QuizController.java | 9 +++++++++ 4 files changed, 32 insertions(+) create mode 100644 backend/src/main/java/wooteco/prolog/roadmap/application/dto/CurriculumQuizResponse.java diff --git a/backend/src/main/java/wooteco/prolog/roadmap/application/QuizService.java b/backend/src/main/java/wooteco/prolog/roadmap/application/QuizService.java index d83684cdc..06fcae13f 100644 --- a/backend/src/main/java/wooteco/prolog/roadmap/application/QuizService.java +++ b/backend/src/main/java/wooteco/prolog/roadmap/application/QuizService.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import wooteco.prolog.common.exception.BadRequestException; +import wooteco.prolog.roadmap.application.dto.CurriculumQuizResponse; import wooteco.prolog.roadmap.application.dto.QuizRequest; import wooteco.prolog.roadmap.application.dto.QuizResponse; import wooteco.prolog.roadmap.application.dto.QuizzesResponse; @@ -73,4 +74,8 @@ public QuizResponse findById(Long quizId, Long memberId) { .orElseThrow(() -> new BadRequestException(ROADMAP_QUIZ_NOT_FOUND_EXCEPTION)); return QuizResponse.of(quiz, isLearning(memberId, quizId)); } + + public List findQuizzesByCurriculumId(Long curriculumId) { + return quizRepository.findQuizzesByCurriculum(curriculumId); + } } diff --git a/backend/src/main/java/wooteco/prolog/roadmap/application/dto/CurriculumQuizResponse.java b/backend/src/main/java/wooteco/prolog/roadmap/application/dto/CurriculumQuizResponse.java new file mode 100644 index 000000000..43f1eb238 --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/roadmap/application/dto/CurriculumQuizResponse.java @@ -0,0 +1,8 @@ +package wooteco.prolog.roadmap.application.dto; + +public interface CurriculumQuizResponse { + + Long getId(); + + String getQuestion(); +} diff --git a/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/QuizRepository.java b/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/QuizRepository.java index 6ecdf58a1..33702685f 100644 --- a/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/QuizRepository.java +++ b/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/QuizRepository.java @@ -3,6 +3,8 @@ import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import wooteco.prolog.roadmap.application.dto.CurriculumQuizResponse; import wooteco.prolog.roadmap.domain.Quiz; public interface QuizRepository extends JpaRepository { @@ -11,4 +13,12 @@ public interface QuizRepository extends JpaRepository { + " JOIN FETCH q.keyword k" + " WHERE q.keyword.id = :keywordId") List findFetchQuizByKeywordId(Long keywordId); + + @Query(nativeQuery = true, + value = "SELECT q.id, q.question " + + "FROM curriculum c " + + "JOIN session s ON c.id = :curriculumId AND s.curriculum_id = c.id " + + "JOIN keyword k ON k.session_id = s.id " + + "JOIN quiz q ON q.keyword_id = k.id") + List findQuizzesByCurriculum(@Param("curriculumId") Long curriculumId); } diff --git a/backend/src/main/java/wooteco/prolog/roadmap/ui/QuizController.java b/backend/src/main/java/wooteco/prolog/roadmap/ui/QuizController.java index fd3e0a597..3f610c952 100644 --- a/backend/src/main/java/wooteco/prolog/roadmap/ui/QuizController.java +++ b/backend/src/main/java/wooteco/prolog/roadmap/ui/QuizController.java @@ -1,6 +1,7 @@ package wooteco.prolog.roadmap.ui; import java.net.URI; +import java.util.List; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -14,6 +15,7 @@ import wooteco.prolog.login.domain.AuthMemberPrincipal; import wooteco.prolog.login.ui.LoginMember; import wooteco.prolog.roadmap.application.QuizService; +import wooteco.prolog.roadmap.application.dto.CurriculumQuizResponse; import wooteco.prolog.roadmap.application.dto.QuizRequest; import wooteco.prolog.roadmap.application.dto.QuizResponse; import wooteco.prolog.roadmap.application.dto.QuizzesResponse; @@ -64,6 +66,13 @@ public ResponseEntity newFindQuizzesByKeyword( return ResponseEntity.ok(quizService.findQuizzesByKeywordId(keywordId, member.getId())); } + @GetMapping("/curriculums/{curriculumId}/quizzes") + public ResponseEntity> findQuizzesByCurriculum( + @PathVariable Long curriculumId + ) { + return ResponseEntity.ok(quizService.findQuizzesByCurriculumId(curriculumId)); + } + @PutMapping("/sessions/{sessionId}/keywords/{keywordId}/quizs/{quizId}") ResponseEntity updateQuiz(@PathVariable Long sessionId, @PathVariable Long keywordId, From 1ca9d9b5cf7e13ccbfbc1cd3ec0923fc52a94808 Mon Sep 17 00:00:00 2001 From: BGuga Date: Mon, 23 Oct 2023 15:00:13 +0900 Subject: [PATCH 2/3] =?UTF-8?q?test:=20repository=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 --- .../repository/QuizRepositoryTest.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/backend/src/test/java/wooteco/prolog/roadmap/repository/QuizRepositoryTest.java b/backend/src/test/java/wooteco/prolog/roadmap/repository/QuizRepositoryTest.java index 9b0c5cee8..563441382 100644 --- a/backend/src/test/java/wooteco/prolog/roadmap/repository/QuizRepositoryTest.java +++ b/backend/src/test/java/wooteco/prolog/roadmap/repository/QuizRepositoryTest.java @@ -1,5 +1,7 @@ package wooteco.prolog.roadmap.repository; +import static org.assertj.core.api.Assertions.assertThat; + import java.util.Arrays; import java.util.List; import org.assertj.core.api.Assertions; @@ -7,8 +9,11 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import wooteco.prolog.roadmap.application.dto.CurriculumQuizResponse; +import wooteco.prolog.roadmap.domain.Curriculum; import wooteco.prolog.roadmap.domain.Keyword; import wooteco.prolog.roadmap.domain.Quiz; +import wooteco.prolog.roadmap.domain.repository.CurriculumRepository; import wooteco.prolog.roadmap.domain.repository.KeywordRepository; import wooteco.prolog.roadmap.domain.repository.QuizRepository; import wooteco.prolog.session.domain.Session; @@ -24,9 +29,14 @@ class QuizRepositoryTest { @Autowired private KeywordRepository keywordRepository; + @Autowired + private CurriculumRepository curriculumRepository; + @Autowired private SessionRepository sessionRepository; + private Curriculum 백엔드; + private Session session_백엔드_레벨1; private Keyword 자바; @@ -38,15 +48,15 @@ class QuizRepositoryTest { @BeforeEach void setUp() { - session_백엔드_레벨1 = sessionRepository.save(new Session("백엔드Java 레벨1")); + 백엔드 = curriculumRepository.save(new Curriculum("백엔드")); + + session_백엔드_레벨1 = sessionRepository.save(new Session(백엔드.getId(), "백엔드Java 레벨1")); 자바 = keywordRepository.save( new Keyword(null, "자바", "자바입니다", 1, 1, session_백엔드_레벨1.getId(), null, null)); - session_백엔드_레벨1 = sessionRepository.save(new Session("백엔드Java 레벨1")); 깃 = keywordRepository.save( new Keyword(null, "깃", "깃입니다", 2, 2, session_백엔드_레벨1.getId(), null, null)); - session_백엔드_레벨1 = sessionRepository.save(new Session("백엔드Java 레벨1")); 자바_질문1 = quizRepository.save(new Quiz(자바, "자바의 아버지는 제임스 고슬링일까요 ? 제이슨일까요 ?")); 자바_질문2 = quizRepository.save(new Quiz(자바, "Stream 은 자바 몇 버전부터 지원했을까요?")); @@ -61,6 +71,19 @@ void findQuizzesByKeyword() { final List expect = Arrays.asList(자바_질문1, 자바_질문2); final List actual = quizRepository.findFetchQuizByKeywordId(자바.getId()); - Assertions.assertThat(actual).containsExactlyElementsOf(expect); + assertThat(actual).containsExactlyElementsOf(expect); + } + + @DisplayName("커리큘럼 id 로 퀴즈 List 를 조회한다.") + @Test + void findQuizzesByCurriculum() { + // given + Long 백엔드_커리큘럼_Id = 백엔드.getId(); + + // when + List acutal = quizRepository.findQuizzesByCurriculum(백엔드_커리큘럼_Id); + + // then + assertThat(acutal).hasSize(3); } } From 593982f68c2b4d03eb15dd56d4527bcfa0970192 Mon Sep 17 00:00:00 2001 From: BGuga Date: Mon, 23 Oct 2023 16:24:37 +0900 Subject: [PATCH 3/3] =?UTF-8?q?test:=20=EB=AC=B8=EC=84=9C=ED=99=94=20?= =?UTF-8?q?=ED=85=8C=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 --- backend/src/documentation/adoc/quiz.adoc | 14 +++++- .../prolog/docu/QuizDocumentation.java | 46 ++++++++++++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/backend/src/documentation/adoc/quiz.adoc b/backend/src/documentation/adoc/quiz.adoc index 335881caf..085234723 100644 --- a/backend/src/documentation/adoc/quiz.adoc +++ b/backend/src/documentation/adoc/quiz.adoc @@ -25,11 +25,21 @@ include::{snippets}/quiz/detail/http-response.adoc[] ==== Request -include::{snippets}/quiz/list/http-request.adoc[] +include::{snippets}/quiz/list-keyword/http-request.adoc[] ==== Response -include::{snippets}/quiz/list/http-response.adoc[] +include::{snippets}/quiz/list-keyword/http-response.adoc[] + +=== 커리큘럼별 퀴즈 목록 조회 + +==== Request + +include::{snippets}/quiz/list-curriculum/http-request.adoc[] + +==== Response + +include::{snippets}/quiz/list-curriculum/http-response.adoc[] === 퀴즈 삭제 diff --git a/backend/src/documentation/java/wooteco/prolog/docu/QuizDocumentation.java b/backend/src/documentation/java/wooteco/prolog/docu/QuizDocumentation.java index 45bfeee7c..e6d3a81ec 100644 --- a/backend/src/documentation/java/wooteco/prolog/docu/QuizDocumentation.java +++ b/backend/src/documentation/java/wooteco/prolog/docu/QuizDocumentation.java @@ -2,17 +2,24 @@ import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.Test; +import org.mockito.BDDMockito; +import org.mockito.Mockito; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import wooteco.prolog.NewDocumentation; import wooteco.prolog.roadmap.application.QuizService; +import wooteco.prolog.roadmap.application.dto.CurriculumQuizResponse; import wooteco.prolog.roadmap.application.dto.QuizRequest; import wooteco.prolog.roadmap.application.dto.QuizResponse; import wooteco.prolog.roadmap.application.dto.QuizzesResponse; @@ -61,10 +68,47 @@ public class QuizDocumentation extends NewDocumentation { given .when().get("/sessions/{sessionId}/keywords/{keywordId}/quizs", 1L, 1L) - .then().log().all().apply(document("quiz/list")) + .then().log().all().apply(document("quiz/list-keyword")) .statusCode(HttpStatus.OK.value()); } + @Test + void Curriculum별_Quiz_조회() { + given(quizService.findQuizzesByCurriculumId(anyLong())) + .willReturn(makeMockResponse()); + + given + .when().get("/curriculums/{curriculumId}/quizzes", 1L) + .then().log().all().apply(document("quiz/list-curriculum")) + .statusCode(HttpStatus.OK.value()); + } + + private List makeMockResponse() { + CurriculumQuizResponse response1 = new CurriculumQuizResponse() { + @Override + public Long getId() { + return 1L; + } + + @Override + public String getQuestion() { + return "question1"; + } + }; + CurriculumQuizResponse response2 = new CurriculumQuizResponse() { + @Override + public Long getId() { + return 2L; + } + + @Override + public String getQuestion() { + return "question2"; + } + }; + return Arrays.asList(response1, response2); + } + @Test void 퀴즈_수정() { doNothing().when(quizService).updateQuiz(any(), any());