Skip to content

Commit

Permalink
fix [back] [QCMPLUS-40] update Questions endpoints
Browse files Browse the repository at this point in the history
Signed-off-by: teklit_tewolde <[email protected]>
  • Loading branch information
teklit_tewolde committed Aug 23, 2024
1 parent 7d8cb7b commit 2412f54
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 48 deletions.
10 changes: 10 additions & 0 deletions qcmplusweb/src/services/QuestionService.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axiosInstance, {API_BASE_URL} from './AxiosInstance';

const QUESTION_REST_API_URL = `${API_BASE_URL}/api/questions`;

export const getQuestionsByQuizId = (quizId) => axiosInstance.get(`${QUESTION_REST_API_URL}/quizzes/${quizId}`);
export const getQuestionById = (quizId, questionId) => axiosInstance.get(`${QUESTION_REST_API_URL}/${questionId}/quizzes/${quizId}`);
export const createQuestion = (quizId, questionData) => axiosInstance.post(`${QUESTION_REST_API_URL}/quizzes/${quizId}`, questionData);
export const updateQuestion = (quizId, questionId, questionData) => axiosInstance.put(`${QUESTION_REST_API_URL}/${questionId}/quizzes/${quizId}`, questionData);
export const deleteQuestion = (quizId, questionId) => axiosInstance.delete(`${QUESTION_REST_API_URL}/${questionId}/quizzes/${quizId}`);
export const getAllQuestions = () => axiosInstance.get(`${QUESTION_REST_API_URL}/all`);
29 changes: 17 additions & 12 deletions src/main/java/com/pmn/qcmplus/controller/QuestionController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.pmn.qcmplus.model.Quiz;
import com.pmn.qcmplus.service.QuestionService;
import com.pmn.qcmplus.service.QuizService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
Expand All @@ -15,11 +16,9 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping("/api/quizzes/{quizId}/questions")
@RequestMapping("/api/questions")
public class QuestionController {

private final QuestionService questionService;
Expand All @@ -31,29 +30,35 @@ public QuestionController(QuestionService questionService, QuizService quizServi
this.quizService = quizService;
}

@GetMapping
@GetMapping("/quizzes/{quizId}")
public ResponseEntity<List<Question>> getQuestionsByQuizId(@PathVariable Integer quizId) {
List<Question> questions = questionService.getQuestionsByQuizId(quizId);
return ResponseEntity.ok(questions);
}

@PostMapping
@PostMapping("/quizzes/{quizId}")
public ResponseEntity<Question> createQuestion(@RequestBody Question question, @PathVariable Integer quizId) {
Quiz quiz = quizService.getQuizById(quizId);
question.setQuiz(quiz);
Question createdQuestion = questionService.saveQuestion(question);
return ResponseEntity.ok(createdQuestion);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteQuestion(@PathVariable Integer quizId, @PathVariable Integer id) {
questionService.deleteQuestion(id);
@DeleteMapping("/{questionId}/quizzes/{quizId}")
public ResponseEntity<Void> deleteQuestion(@PathVariable Integer quizId, @PathVariable Integer questionId) {
questionService.deleteQuestion(questionId);
return ResponseEntity.noContent().build();
}

@GetMapping("/{id}")
public ResponseEntity<Question> getQuestionById(@PathVariable Integer quizId, @PathVariable Integer id) {
Question question = questionService.getQuestionById(id);
@GetMapping("/{questionId}/quizzes/{quizId}")
public ResponseEntity<Question> getQuestionById(@PathVariable Integer quizId, @PathVariable Integer questionId) {
Question question = questionService.getQuestionById(questionId);
return ResponseEntity.ok(question);
}
}

@GetMapping("/all")
public ResponseEntity<List<Question>> getAllQuestions() {
List<Question> questions = questionService.getAllQuestions();
return ResponseEntity.ok(questions);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.pmn.qcmplus.exception;

public class QuestionNotFoundException extends RuntimeException {
public QuestionNotFoundException(Integer id) {
super("Question with id " + id + " not found.");
}
}
4 changes: 3 additions & 1 deletion src/main/java/com/pmn/qcmplus/service/QuestionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ public interface QuestionService {
Question saveQuestion(Question question);

void deleteQuestion(Integer id);
}

List<Question> getAllQuestions(); // New method
}
30 changes: 18 additions & 12 deletions src/main/java/com/pmn/qcmplus/service/impl/QuestionServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.pmn.qcmplus.service.impl;

import com.pmn.qcmplus.exception.QuestionNotFoundException;
import com.pmn.qcmplus.model.Question;
import com.pmn.qcmplus.model.Quiz;
import com.pmn.qcmplus.repository.QuestionRepository;
import com.pmn.qcmplus.repository.QuizRepository;
import com.pmn.qcmplus.service.QuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class QuestionServiceImpl implements QuestionService {
Expand All @@ -31,31 +31,37 @@ public List<Question> getQuestionsByQuizId(Integer quizId) {
@Override
public Question getQuestionById(Integer id) {
return questionRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Question not found with id: " + id));
.orElseThrow(() -> new QuestionNotFoundException(id));
}


@Override
public Question saveQuestion(Question question) {
// Validate that the quiz exists
if (question == null) {
throw new IllegalArgumentException("Question cannot be null.");
}
if (question.getQuiz() == null || question.getQuiz().getQuizId() == null) {
throw new IllegalArgumentException("Quiz or Quiz ID cannot be null.");
}

Optional<Quiz> quiz = quizRepository.findById(question.getQuiz().getQuizId());
if (quiz.isEmpty()) {
throw new IllegalArgumentException("Quiz does not exist.");
}

// Save the question
return questionRepository.save(question);
}

@Override
public void deleteQuestion(Integer id) {
// Validate that the question exists
Optional<Question> question = questionRepository.findById(id);
if (question.isEmpty()) {
throw new IllegalArgumentException("Question does not exist.");
throw new QuestionNotFoundException(id);
}

// Delete the question
questionRepository.deleteById(id);
}
}

@Override
public List<Question> getAllQuestions() {
return questionRepository.findAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@
import com.pmn.qcmplus.model.Quiz;
import com.pmn.qcmplus.service.QuestionService;
import com.pmn.qcmplus.service.QuizService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.MockitoAnnotations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

class QuestionControllerTest {

Expand All @@ -47,7 +46,7 @@ void setUp() {

@Test
void testGetQuestionsByQuizId() {
when(questionService.getQuestionsByQuizId(eq(1))).thenReturn(Arrays.asList(question));
when(questionService.getQuestionsByQuizId(eq(1))).thenReturn(Collections.singletonList(question));

ResponseEntity<List<Question>> response = questionController.getQuestionsByQuizId(1);

Expand All @@ -60,7 +59,6 @@ void testGetQuestionsByQuizId() {
void testGetQuestionById() {
when(questionService.getQuestionById(eq(1))).thenReturn(question);

// Update: Include quizId as a parameter in the method call
ResponseEntity<Question> response = questionController.getQuestionById(1, 1);

assertEquals(HttpStatus.OK, response.getStatusCode());
Expand All @@ -84,10 +82,23 @@ void testCreateQuestion() {
void testDeleteQuestion() {
doNothing().when(questionService).deleteQuestion(eq(1));

// Update: Include quizId as a parameter in the method call
ResponseEntity<Void> response = questionController.deleteQuestion(1, 1);

assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
verify(questionService, times(1)).deleteQuestion(eq(1));
}

@Test
void testGetAllQuestions() {
when(questionService.getAllQuestions()).thenReturn(Collections.singletonList(question));

ResponseEntity<List<Question>> response = questionController.getAllQuestions();

assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(1, response.getBody().size());
verify(questionService, times(1)).getAllQuestions();
}



}
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
package com.pmn.qcmplus.repository;

import com.pmn.qcmplus.exception.QuestionNotFoundException;
import com.pmn.qcmplus.model.Question;
import com.pmn.qcmplus.model.Quiz;
import com.pmn.qcmplus.service.impl.QuestionServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.mockito.ArgumentMatchers.any;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.jupiter.MockitoExtension;


@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -116,13 +115,13 @@ void testDeleteQuestion() {
void testDeleteQuestion_NotFound() {
when(questionRepository.findById(1)).thenReturn(Optional.empty());

IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
QuestionNotFoundException exception = assertThrows(QuestionNotFoundException.class, () -> {
questionService.deleteQuestion(1);
});

assertEquals("Question does not exist.", exception.getMessage());
assertEquals("Question with id 1 not found.", exception.getMessage());

verify(questionRepository, times(1)).findById(1);
verify(questionRepository, times(0)).deleteById(1);
}
}
}
Loading

0 comments on commit 2412f54

Please sign in to comment.