Skip to content

Commit

Permalink
add get user exams
Browse files Browse the repository at this point in the history
  • Loading branch information
pionas committed Dec 18, 2023
1 parent 7f9d761 commit dd0f60b
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/main/java/info/pionas/quiz/api/exam/ExamApiMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ interface ExamApiMapper {
ExamResponseDto map(ExamResult examResult);

List<PassExamAnswer> map(List<NewExamAnswerDto> answers);

List<ExamResponseDto> mapToDto(List<ExamResult> userExams);
}
10 changes: 10 additions & 0 deletions src/main/java/info/pionas/quiz/api/exam/ExamRestController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@RestController
@RequestMapping("exam")
@RequiredArgsConstructor
Expand All @@ -25,4 +29,10 @@ Mono<ExamResponseDto> endExam(@Valid @RequestBody NewExamDto examDto, Authentica
return Mono.just(examApiMapper.map(examService.getExamDetails(examId)));
}

@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ResponseStatus(HttpStatus.OK)
Flux<ExamResponseDto> exams(Authentication authentication) {
return Flux.fromIterable(examApiMapper.mapToDto(examService.getUserExams(String.valueOf(authentication.getPrincipal()))));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@ public UUID endExam(String username, UUID quizId, List<PassExamAnswer> answers)
}

@Override
@org.springframework.transaction.annotation.Transactional(readOnly = true)
@Transactional(readOnly = true)
public ExamResult getExamDetails(UUID id) {
return examRepository.getById(id)
.orElseThrow(() -> new ExamResultNotFoundException(id));
}

@Override
@Transactional(readOnly = true)
public List<ExamResult> getUserExams(String username) {
return examRepository.getUserExams(username);
}

private NewExamDetails getNewExamDetails(UUID resultId, UUID quizId, String username, LocalDateTime dateTime) {
return NewExamDetails.builder()
.id(resultId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package info.pionas.quiz.domain.exam.api;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

Expand All @@ -8,4 +9,6 @@ public interface ExamRepository {
void save(NewExamDetails newExamDetails);

Optional<ExamResult> getById(UUID id);

List<ExamResult> getUserExams(String username);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package info.pionas.quiz.domain.exam.api;

import info.pionas.quiz.api.exam.api.NewExamAnswerDto;

import java.util.List;
import java.util.UUID;

Expand All @@ -8,4 +10,6 @@ public interface ExamService {
UUID endExam(String username, UUID uuid, List<PassExamAnswer> answers);

ExamResult getExamDetails(UUID examId);

List<ExamResult> getUserExams(String username);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import java.util.List;

@Mapper(componentModel = "spring")
interface ExamJpaMapper {

Expand All @@ -15,5 +17,7 @@ interface ExamJpaMapper {
@Mapping(target = "created", source = "created")
ExamEntity map(NewExamDetails newExamDetails);

ExamResult map(ExamResultReadModel examEntity);
ExamResult map(ExamResultReadModel examResultReadModel);

List<ExamResult> map(List<ExamResultReadModel> examResultReadModels);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

Expand All @@ -27,4 +28,9 @@ public Optional<ExamResult> getById(UUID id) {
return examResultJpaRepository.findById(id)
.map(examJpaMapper::map);
}

@Override
public List<ExamResult> getUserExams(String username) {
return examJpaMapper.map(examResultJpaRepository.findAllByUsername(username));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
interface ExamResultJpaRepository extends JpaRepository<ExamResultReadModel, UUID> {

List<ExamResultReadModel> findAllByUsername(String username);
}
15 changes: 12 additions & 3 deletions src/main/resources/db/changelog/init.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,27 @@ databaseChangeLog:
- column:
name: result_id
type: UUID
constraints:
nullable: false
- column:
name: question_id
type: UUID
constraints:
nullable: false
- column:
name: answer_id
type: UUID
- column:
name: username
type: VARCHAR(255)
constraints:
nullable: false
- column:
name: correct
type: BOOLEAN
constraints:
nullable: false
- column:
name: created
type: DATETIME
- addPrimaryKey:
columnNames: result_id, question_id, answer_id
constraintName: pk_quiz_exam_answer
tableName: quiz_exam_answers
32 changes: 27 additions & 5 deletions src/test/java/info/pionas/quiz/api/exam/ExamRestControllerIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,6 @@ void should_end_exam() {
.exchange()
.returnResult(ExamResponseDto.class);
//then
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ExamResponseDto examResponseDto = response.getResponseBody().blockLast();
assertThat(response.getStatus()).isEqualTo(HttpStatus.CREATED);
assertThat(examResponseDto).isNotNull();
Expand Down Expand Up @@ -122,6 +117,33 @@ void should_throw_bad_request_when_answer_for_question_not_exist() throws IOExce
.containsExactlyInAnyOrder("There is no answer to the question ce703f5b-274c-4398-b855-d461887c7ed5");
}

@Test
@Sql({"/db/quiz.sql", "/db/question.sql", "/db/answer.sql", "/db/exam_result.sql"})
void should_return_user_exam_list() {
//given
final var user = new User("admin", "admin", Collections.emptyList());
//when
final var response = webTestClient
.get().uri("/api/v1/exam")
.accept(MediaType.TEXT_EVENT_STREAM)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + generateToken(user))
.exchange();
//then
response.expectStatus().isOk()
.expectHeader().contentType("text/event-stream;charset=UTF-8")
.expectBodyList(ExamResponseDto.class)
.consumeWith(listEntityExchangeResult -> {
List<ExamResponseDto> examResponseDtos = listEntityExchangeResult.getResponseBody();
assertThat(examResponseDtos).hasSize(2);
ExamResponseDto examResponseDto1 = examResponseDtos.getFirst();
assertThat(examResponseDto1).isNotNull();
assertThat(examResponseDto1.getId()).isEqualTo(UUID.fromString("a375ca97-33f9-4251-aaa0-f9d95b55003f"));
ExamResponseDto examResponseDto2 = examResponseDtos.getLast();
assertThat(examResponseDto2).isNotNull();
assertThat(examResponseDto2.getId()).isEqualTo(UUID.fromString("b8acee24-edaf-4725-876c-c37ec4512a8c"));
});
}

private NewExamDto getNewExamDto() {
final var newExamDto = new NewExamDto();
newExamDto.setQuizId(UUID.fromString("b4a63897-60f7-4e94-846e-e199d8734144"));
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/info/pionas/quiz/domain/exam/ExamServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,23 @@ void should_throw_exam_not_found_exception_when_exam_by_id_not_exist() {
.isEqualTo("Exam result by ID 7a398eb6-1d20-4a05-b13b-c752c3c7c5d3 not exist");
}

@Test
void should_return_exam_list_for_user() {
//given
final var examResultId = UUID.fromString("7a398eb6-1d20-4a05-b13b-c752c3c7c5d3");
final var quizId = UUID.fromString("b83d5c22-7b78-4435-9daa-17bb532c0f63");
final var answers = getAnswers();
final var quiz = getQuiz(quizId);
when(examRepository.getUserExams("username")).thenReturn(List.of(createExamResult(examResultId, quiz, answers)));
//when
final var examResults = service.getUserExams("username");
//then
assertThat(examResults).hasSize(1);
ExamResult examResult = examResults.getFirst();
assertThat(examResult.getUsername()).isEqualTo("username");
assertThat(examResult.getCorrectAnswer()).isEqualTo(1);
}

private Quiz getQuiz(UUID quizId) {
final var questionId1 = UUID.fromString("03df4c0e-a760-4b23-aebe-ac0fd8761804");
final var questionId2 = UUID.fromString("0feb6e91-a25c-4c9a-8f6c-acf489a5af6b");
Expand Down
8 changes: 8 additions & 0 deletions src/test/resources/db/exam_result.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
insert into quiz_exams (id, username, quiz_id, created) values ('a375ca97-33f9-4251-aaa0-f9d95b55003f', 'admin', 'b4a63897-60f7-4e94-846e-e199d8734144', '2023-12-18T13:47:02.159316600')
insert into quiz_exam_answers (correct,created,answer_id,question_id,result_id) values (false,'2023-12-18T13:47:02.159316600','a4bd2133-d4e8-4b73-9264-4afb02096ffd','ce703f5b-274c-4398-b855-d461887c7ed5','a375ca97-33f9-4251-aaa0-f9d95b55003f')

insert into quiz_exams (id, username, quiz_id, created) values ('c6639ddd-8602-4e4b-acb3-c0f138a7f1f1', 'adminek', 'b4a63897-60f7-4e94-846e-e199d8734144', '2023-12-18T13:47:03.159316600')
insert into quiz_exam_answers (correct,created,answer_id,question_id,result_id) values (false,'2023-12-18T13:47:03.159316600','a4bd2133-d4e8-4b73-9264-4afb02096ffd','ce703f5b-274c-4398-b855-d461887c7ed5','c6639ddd-8602-4e4b-acb3-c0f138a7f1f1')

insert into quiz_exams (id, username, quiz_id, created) values ('b8acee24-edaf-4725-876c-c37ec4512a8c', 'admin', 'b4a63897-60f7-4e94-846e-e199d8734144', '2023-12-18T13:47:04.159316600')
insert into quiz_exam_answers (correct,created,answer_id,question_id,result_id) values (false,'2023-12-18T13:47:04.159316600','a4bd2133-d4e8-4b73-9264-4afb02096ffd','ce703f5b-274c-4398-b855-d461887c7ed5','b8acee24-edaf-4725-876c-c37ec4512a8c')

0 comments on commit dd0f60b

Please sign in to comment.