diff --git a/build.gradle b/build.gradle index 0b39517..0bfd90b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,10 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.+' + id 'org.springframework.boot' version '3.2.+' id 'io.spring.dependency-management' version '1.+' id "io.github.kobylynskyi.graphql.codegen" version "5.+" id "org.sonarqube" version "5.+" id "jacoco" - } group = 'de.unistuttgart.iste.meitrex' @@ -23,6 +22,7 @@ if (jacocoEnabled.toBoolean()) { sonarqube { properties { property("sonar.projectKey", "MEITREX_quiz_service") + property("sonar.organization", "meitrex") property("sonar.host.url", "https://sonarcloud.io") } @@ -108,7 +108,8 @@ repositories { } dependencies { - implementation 'de.unistuttgart.iste.meitrex:meitrex-common:1.0.6' + + implementation 'de.unistuttgart.iste.meitrex:meitrex-common:1.2' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-graphql' implementation 'org.springframework.boot:spring-boot-starter-validation' @@ -124,7 +125,7 @@ dependencies { runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' - testImplementation 'de.unistuttgart.iste.meitrex:meitrex-common-test:1.0.6' + testImplementation 'de.unistuttgart.iste.meitrex:meitrex-common-test:1.2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework:spring-webflux' testImplementation 'org.springframework.graphql:spring-graphql-test' diff --git a/jacoco.gradle b/jacoco.gradle index e7e99ec..b40443b 100644 --- a/jacoco.gradle +++ b/jacoco.gradle @@ -12,4 +12,4 @@ jacocoTestReport { html.required.set(true) html.outputLocation = layout.buildDirectory.dir('jacocoHtml') } -} +} \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/QuizController.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/QuizController.java index a35da3a..02cd714 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/QuizController.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/QuizController.java @@ -1,11 +1,17 @@ package de.unistuttgart.iste.meitrex.quiz_service.controller; + +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; +import de.unistuttgart.iste.meitrex.quiz_service.service.QuizService; + import de.unistuttgart.iste.meitrex.common.exception.NoAccessToCourseException; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser.UserRoleInCourse; import de.unistuttgart.iste.meitrex.generated.dto.*; + import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.service.QuizService; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.graphql.data.method.annotation.*; @@ -67,62 +73,62 @@ public UUID deleteQuiz(@Argument final UUID assessmentId) { } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz addMultipleChoiceQuestion(@Argument final CreateMultipleChoiceQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_addMultipleChoiceQuestion(@Argument final CreateMultipleChoiceQuestionInput input, final QuizMutation quizMutation) { return quizService.addMultipleChoiceQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz updateMultipleChoiceQuestion(@Argument final UpdateMultipleChoiceQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_updateMultipleChoiceQuestion(@Argument final UpdateMultipleChoiceQuestionInput input, final QuizMutation quizMutation) { return quizService.updateMultipleChoiceQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz addClozeQuestion(@Argument final CreateClozeQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_addClozeQuestion(@Argument final CreateClozeQuestionInput input, final QuizMutation quizMutation) { return quizService.addClozeQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz updateClozeQuestion(@Argument final UpdateClozeQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_updateClozeQuestion(@Argument final UpdateClozeQuestionInput input, final QuizMutation quizMutation) { return quizService.updateClozeQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz addAssociationQuestion(@Argument final CreateAssociationQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_addAssociationQuestion(@Argument final CreateAssociationQuestionInput input, final QuizMutation quizMutation) { return quizService.addAssociationQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz updateAssociationQuestion(@Argument final UpdateAssociationQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_updateAssociationQuestion(@Argument final UpdateAssociationQuestionInput input, final QuizMutation quizMutation) { return quizService.updateAssociationQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz addExactAnswerQuestion(@Argument final CreateExactAnswerQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_addExactAnswerQuestion(@Argument final CreateExactAnswerQuestionInput input, final QuizMutation quizMutation) { return quizService.addExactAnswerQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz updateExactAnswerQuestion(@Argument final UpdateExactAnswerQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_updateExactAnswerQuestion(@Argument final UpdateExactAnswerQuestionInput input, final QuizMutation quizMutation) { return quizService.updateExactAnswerQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz addNumericQuestion(@Argument final CreateNumericQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_addNumericQuestion(@Argument final CreateNumericQuestionInput input, final QuizMutation quizMutation) { return quizService.addNumericQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz updateNumericQuestion(@Argument final UpdateNumericQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_updateNumericQuestion(@Argument final UpdateNumericQuestionInput input, final QuizMutation quizMutation) { return quizService.updateNumericQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz addSelfAssessmentQuestion(@Argument final CreateSelfAssessmentQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_addSelfAssessmentQuestion(@Argument final CreateSelfAssessmentQuestionInput input, final QuizMutation quizMutation) { return quizService.addSelfAssessmentQuestion(quizMutation.getAssessmentId(), input); } @SchemaMapping(typeName = QUIZ_MUTATION_NAME) - public Quiz updateSelfAssessmentQuestion(@Argument final UpdateSelfAssessmentQuestionInput input, final QuizMutation quizMutation) { + public Quiz _internal_noauth_updateSelfAssessmentQuestion(@Argument final UpdateSelfAssessmentQuestionInput input, final QuizMutation quizMutation) { return quizService.updateSelfAssessmentQuestion(quizMutation.getAssessmentId(), input); } diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/SubscriptionController.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/SubscriptionController.java index b989fba..77912b7 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/SubscriptionController.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/controller/SubscriptionController.java @@ -1,7 +1,9 @@ package de.unistuttgart.iste.meitrex.quiz_service.controller; -import de.unistuttgart.iste.meitrex.common.event.ContentChangeEvent; + import de.unistuttgart.iste.meitrex.quiz_service.service.QuizService; +import de.unistuttgart.iste.meitrex.common.event.ContentChangeEvent; + import io.dapr.Topic; import io.dapr.client.domain.CloudEvent; import lombok.RequiredArgsConstructor; @@ -21,7 +23,7 @@ public class SubscriptionController { private final QuizService quizService; - @Topic(name = "content-changed", pubsubName = "gits") + @Topic(name = "content-changed", pubsubName = "meitrex") @PostMapping(path = "/quiz-service/content-changed-pubsub") public Mono updateAssociation(@RequestBody final CloudEvent cloudEvent) { diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/MultipleChoiceQuestionEntity.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/MultipleChoiceQuestionEntity.java index 7dafef8..4254fd2 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/MultipleChoiceQuestionEntity.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/MultipleChoiceQuestionEntity.java @@ -1,13 +1,10 @@ package de.unistuttgart.iste.meitrex.quiz_service.persistence.entity; import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; -import jakarta.persistence.Column; -import jakarta.persistence.ElementCollection; -import jakarta.persistence.Entity; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; + +import jakarta.persistence.*; +import lombok.*; + import lombok.experimental.SuperBuilder; import java.util.ArrayList; diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/QuestionEntity.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/QuestionEntity.java index 305e8a9..6d02906 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/QuestionEntity.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/entity/QuestionEntity.java @@ -22,8 +22,7 @@ public class QuestionEntity { @Id - @GeneratedValue - private UUID id; + private UUID itemId; @Column(nullable = false) private int number; @@ -48,7 +47,7 @@ public boolean equals(final Object o) { if (o == null || getClass() != o.getClass()) return false; final QuestionEntity that = (QuestionEntity) o; if (getNumber() != that.getNumber()) return false; - if (!Objects.equals(getId(), that.getId())) return false; + if (!Objects.equals(getItemId(), that.getItemId())) return false; if (getType() != that.getType()) return false; if (!(Objects.equals(getHint(), that.getHint()))) return false; @@ -62,6 +61,6 @@ public boolean equals(final Object o) { @Override public int hashCode() { - return Objects.hash(getId(), getNumber(), getType(), getHint(), getQuestionStatistics()); + return Objects.hash(getItemId(), getNumber(), getType(), getHint(), getQuestionStatistics()); } } diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/mapper/QuizMapper.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/mapper/QuizMapper.java index 3c1dab9..03c1747 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/mapper/QuizMapper.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/persistence/mapper/QuizMapper.java @@ -1,7 +1,10 @@ package de.unistuttgart.iste.meitrex.quiz_service.persistence.mapper; import de.unistuttgart.iste.meitrex.generated.dto.*; + +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.*; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.*; + import lombok.RequiredArgsConstructor; import org.modelmapper.ModelMapper; import org.springframework.stereotype.Component; @@ -96,7 +99,7 @@ public ClozeQuestion clozeQuestionEntityToDto(final ClozeQuestionEntity clozeQue final ClozeQuestion result = ClozeQuestion.builder() .setType(QuestionType.CLOZE) .setNumber(clozeQuestionEntity.getNumber()) - .setId(clozeQuestionEntity.getId()) + .setItemId(clozeQuestionEntity.getItemId()) .setShowBlanksList(clozeQuestionEntity.isShowBlanksList()) .setAdditionalWrongAnswers(clozeQuestionEntity.getAdditionalWrongAnswers()) .setClozeElements(clozeQuestionEntity.getClozeElements().stream() diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizService.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizService.java index 8c4a1f9..d0393f8 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizService.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizService.java @@ -1,17 +1,17 @@ package de.unistuttgart.iste.meitrex.quiz_service.service; -import de.unistuttgart.iste.meitrex.common.dapr.TopicPublisher; -import de.unistuttgart.iste.meitrex.common.event.ContentChangeEvent; -import de.unistuttgart.iste.meitrex.common.event.ContentProgressedEvent; -import de.unistuttgart.iste.meitrex.common.event.CrudOperation; -import de.unistuttgart.iste.meitrex.common.exception.IncompleteEventMessageException; -import de.unistuttgart.iste.meitrex.generated.dto.*; + +import de.unistuttgart.iste.meitrex.quiz_service.persistence.mapper.QuizMapper; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionStatisticEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.mapper.QuizMapper; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; +import de.unistuttgart.iste.meitrex.common.dapr.TopicPublisher; +import de.unistuttgart.iste.meitrex.common.event.*; +import de.unistuttgart.iste.meitrex.common.exception.IncompleteEventMessageException; +import de.unistuttgart.iste.meitrex.generated.dto.*; import de.unistuttgart.iste.meitrex.quiz_service.validation.QuizValidator; + import jakarta.persistence.EntityNotFoundException; import jakarta.transaction.Transactional; import jakarta.validation.ValidationException; @@ -20,6 +20,7 @@ import org.springframework.stereotype.Service; import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -87,7 +88,7 @@ public Quiz createQuiz(final UUID courseId, final UUID assessmentId, final Creat */ public UUID deleteQuiz(final UUID id) { requireQuizExists(id); - + publishQuizDeletion(id); quizRepository.deleteById(id); return id; @@ -121,7 +122,7 @@ public Quiz addMultipleChoiceQuestion(final UUID quizId, final CreateMultipleCho public Quiz updateMultipleChoiceQuestion(final UUID quizId, final UpdateMultipleChoiceQuestionInput input) { quizValidator.validateUpdateMultipleChoiceQuestionInput(input); - return updateQuestion(quizId, input, input.getId(), quizMapper::multipleChoiceQuestionInputToEntity); + return updateQuestion(quizId, input, input.getItemId(), quizMapper::multipleChoiceQuestionInputToEntity); } /** @@ -153,7 +154,7 @@ public Quiz addClozeQuestion(final UUID quizId, final CreateClozeQuestionInput i public Quiz updateClozeQuestion(final UUID quizId, final UpdateClozeQuestionInput input) { quizValidator.validateUpdateClozeQuestionInput(input); - return updateQuestion(quizId, input, input.getId(), quizMapper::clozeQuestionInputToEntity); + return updateQuestion(quizId, input, input.getItemId(), quizMapper::clozeQuestionInputToEntity); } /** @@ -183,7 +184,7 @@ public Quiz addAssociationQuestion(final UUID assessmentId, final CreateAssociat public Quiz updateAssociationQuestion(final UUID assessmentId, final UpdateAssociationQuestionInput input) { quizValidator.validateUpdateAssociationQuestionInput(input); - return updateQuestion(assessmentId, input, input.getId(), quizMapper::associationQuestionInputToEntity); + return updateQuestion(assessmentId, input, input.getItemId(), quizMapper::associationQuestionInputToEntity); } /** @@ -207,7 +208,7 @@ public Quiz addExactAnswerQuestion(final UUID quizId, final CreateExactAnswerQue * @throws EntityNotFoundException if the quiz or the question does not exist */ public Quiz updateExactAnswerQuestion(final UUID quizId, final UpdateExactAnswerQuestionInput input) { - return updateQuestion(quizId, input, input.getId(), quizMapper::exactAnswerQuestionInputToEntity); + return updateQuestion(quizId, input, input.getItemId(), quizMapper::exactAnswerQuestionInputToEntity); } /** @@ -231,7 +232,7 @@ public Quiz addNumericQuestion(final UUID quizId, final CreateNumericQuestionInp * @throws EntityNotFoundException if the quiz or the question does not exist */ public Quiz updateNumericQuestion(final UUID quizId, final UpdateNumericQuestionInput input) { - return updateQuestion(quizId, input, input.getId(), quizMapper::numericQuestionInputToEntity); + return updateQuestion(quizId, input, input.getItemId(), quizMapper::numericQuestionInputToEntity); } /** @@ -255,7 +256,7 @@ public Quiz addSelfAssessmentQuestion(final UUID quizId, final CreateSelfAssessm * @throws EntityNotFoundException if the quiz or the question does not exist */ public Quiz updateSelfAssessmentQuestion(final UUID quizId, final UpdateSelfAssessmentQuestionInput input) { - return updateQuestion(quizId, input, input.getId(), quizMapper::selfAssessmentQuestionInputToEntity); + return updateQuestion(quizId, input, input.getItemId(), quizMapper::selfAssessmentQuestionInputToEntity); } /** @@ -291,10 +292,9 @@ private Quiz updateQuestion(final UUID quizId, * @param questionNumber the number of the question to add. If null, the number is assigned automatically. * @param mapping the mapping function that maps the input to a question entity. * @param the type of the question input, e.g. {@link CreateMultipleChoiceQuestionInput} - * + * @return the modified quiz * @implNote The second parameter questionNumber is necessary because the input types do not share a common interface, * and we cannot change the input types, as they are generated from the schema. - * @return the modified quiz */ private Quiz addQuestion(final UUID quizId, final I input, @@ -325,7 +325,7 @@ public Quiz removeQuestion(final UUID quizId, final int number) { return modifyQuiz(quizId, entity -> { final QuestionEntity questionEntity = getQuestionInQuizByNumber(entity, number); entity.getQuestionPool().remove(questionEntity); - + publishItemChangeEvent(questionEntity.getItemId()); // decrease the number of all questions with a higher number entity.getQuestionPool().stream() .filter(q -> q.getNumber() > number) @@ -408,7 +408,7 @@ private int assignNumber(final QuizEntity entity) { private QuestionEntity getQuestionInQuizById(final QuizEntity quizEntity, final UUID questionId) { return quizEntity.getQuestionPool().stream() - .filter(q -> q.getId().equals(questionId)) + .filter(q -> q.getItemId().equals(questionId)) .findFirst() .orElseThrow(() -> new EntityNotFoundException(MessageFormat.format( @@ -475,7 +475,16 @@ public QuizCompletionFeedback publishProgress(final QuizCompletedInput input, fi final boolean success = numbCorrectAnswers >= quizEntity.getRequiredCorrectAnswers(); final double correctness = calculateCorrectness(numbCorrectAnswers, quizEntity); final int hintsUsed = countAsInt(input.getCompletedQuestions(), QuestionCompletedInput::getUsedHint); + List responses = new ArrayList(); + for (QuestionCompletedInput question : input.getCompletedQuestions()) { + float answer = 0; + if (question.getCorrect()) { + answer = 1; + } + Response response = new Response(question.getQuestionId(), answer); + responses.add(response); + } // create new user progress event message final ContentProgressedEvent userProgressLogEvent = ContentProgressedEvent.builder() .userId(userId) @@ -484,6 +493,7 @@ public QuizCompletionFeedback publishProgress(final QuizCompletedInput input, fi .success(success) .timeToComplete(null) .correctness(correctness) + .responses(responses) .build(); // publish new user progress event message @@ -512,7 +522,7 @@ private void updateQuestionStatistics(final QuizCompletedInput input, final UUID // create new Question Statistic final QuestionStatisticEntity newQuestionStatistic = QuestionStatisticEntity.builder() - .questionId(questionEntity.getId()) + .questionId(questionEntity.getItemId()) .userId(userId) .answeredCorrectly(completedQuestion.getCorrect()) .build(); @@ -544,7 +554,7 @@ protected double calculateCorrectness(final double correctAnswers, final QuizEnt // in RANDOM mode, the number of questions is not the size of the question pool // but the number of randomly selected questions if (quizEntity.getQuestionPoolingMode().equals(QuestionPoolingMode.RANDOM) - && quizEntity.getNumberOfRandomlySelectedQuestions() != null) { + && quizEntity.getNumberOfRandomlySelectedQuestions() != null) { if (quizEntity.getNumberOfRandomlySelectedQuestions() == 0) { // prevent division by zero @@ -560,4 +570,24 @@ protected double calculateCorrectness(final double correctAnswers, final QuizEnt } } + + private void publishQuizDeletion(UUID quizId) { + Optional quizEntity = quizRepository.findById(quizId); + if (quizEntity.isPresent()) { + QuizEntity quiz = quizEntity.get(); + List questionPool = quiz.getQuestionPool(); + for (QuestionEntity question : questionPool) { + publishItemChangeEvent(question.getItemId()); + } + + } + } + + /*** + * helper function, that creates a ItemChange Event and publish it, when a flashcard was deleted + * @param itemId the id of the item + */ + private void publishItemChangeEvent(final UUID itemId) { + topicPublisher.notifyItemChanges(itemId, CrudOperation.DELETE); + } } diff --git a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/validation/QuizValidator.java b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/validation/QuizValidator.java index 2523e0d..184ba08 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/validation/QuizValidator.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/quiz_service/validation/QuizValidator.java @@ -1,7 +1,7 @@ package de.unistuttgart.iste.meitrex.quiz_service.validation; -import de.unistuttgart.iste.meitrex.generated.dto.*; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; +import de.unistuttgart.iste.meitrex.generated.dto.*; import jakarta.validation.ValidationException; import org.springframework.stereotype.Component; diff --git a/src/main/resources/graphql/service/mutation.graphqls b/src/main/resources/graphql/service/mutation.graphqls index b5bb651..2df4574 100644 --- a/src/main/resources/graphql/service/mutation.graphqls +++ b/src/main/resources/graphql/service/mutation.graphqls @@ -32,56 +32,80 @@ type QuizMutation { assessmentId: UUID! """ Add a multiple choice question to the quiz questions, at the end of the list. + ️⚠️ This query is only accessible internally in the system and allows the caller to create a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - addMultipleChoiceQuestion(input: CreateMultipleChoiceQuestionInput!): Quiz! + _internal_noauth_addMultipleChoiceQuestion(input: CreateMultipleChoiceQuestionInput!): Quiz! """ Update a multiple choice question in the quiz questions. + ️⚠️ This query is only accessible internally in the system and allows the caller to update a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - updateMultipleChoiceQuestion(input: UpdateMultipleChoiceQuestionInput!): Quiz! + _internal_noauth_updateMultipleChoiceQuestion(input: UpdateMultipleChoiceQuestionInput!): Quiz! """ Add a cloze question to the quiz questions, at the end of the list. + ️⚠️ This query is only accessible internally in the system and allows the caller to create a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - addClozeQuestion(input: CreateClozeQuestionInput!): Quiz! + _internal_noauth_addClozeQuestion(input: CreateClozeQuestionInput!): Quiz! """ Update a cloze question in the quiz questions. + ️⚠️ This query is only accessible internally in the system and allows the caller to update a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - updateClozeQuestion(input: UpdateClozeQuestionInput!): Quiz! + _internal_noauth_updateClozeQuestion(input: UpdateClozeQuestionInput!): Quiz! """ Add an association question to the quiz questions, at the end of the list. + ️⚠️ This query is only accessible internally in the system and allows the caller to create a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - addAssociationQuestion(input: CreateAssociationQuestionInput!): Quiz! + _internal_noauth_addAssociationQuestion(input: CreateAssociationQuestionInput!): Quiz! """ Update an association question in the quiz questions. + ️⚠️ This query is only accessible internally in the system and allows the caller to update a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - updateAssociationQuestion(input: UpdateAssociationQuestionInput!): Quiz! + _internal_noauth_updateAssociationQuestion(input: UpdateAssociationQuestionInput!): Quiz! """ Add an free text question with exact answer to the quiz questions, at the end of the list. + ️⚠️ This query is only accessible internally in the system and allows the caller to create a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - addExactAnswerQuestion(input: CreateExactAnswerQuestionInput!): Quiz! + _internal_noauth_addExactAnswerQuestion(input: CreateExactAnswerQuestionInput!): Quiz! """ Update an free text question with exact answer in the quiz questions. + ️⚠️ This query is only accessible internally in the system and allows the caller to update a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - updateExactAnswerQuestion(input: UpdateExactAnswerQuestionInput!): Quiz! + _internal_noauth_updateExactAnswerQuestion(input: UpdateExactAnswerQuestionInput!): Quiz! """ Add a numeric question to the quiz questions, at the end of the list. + ️⚠️ This query is only accessible internally in the system and allows the caller to create a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - addNumericQuestion(input: CreateNumericQuestionInput!): Quiz! + _internal_noauth_addNumericQuestion(input: CreateNumericQuestionInput!): Quiz! """ Update a numeric question in the quiz questions. + ️⚠️ This query is only accessible internally in the system and allows the caller to update a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - updateNumericQuestion(input: UpdateNumericQuestionInput!): Quiz! + _internal_noauth_updateNumericQuestion(input: UpdateNumericQuestionInput!): Quiz! """ Add a self assessment question to the quiz questions, at the end of the list. + ️⚠️ This query is only accessible internally in the system and allows the caller to create a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - addSelfAssessmentQuestion(input: CreateSelfAssessmentQuestionInput!): Quiz! + _internal_noauth_addSelfAssessmentQuestion(input: CreateSelfAssessmentQuestionInput!): Quiz! """ Update a self assessment question in the quiz questions. + ️⚠️ This query is only accessible internally in the system and allows the caller to update a Question without + any permissions check and should not be called without any validation of the caller's permissions. ⚠️ """ - updateSelfAssessmentQuestion(input: UpdateSelfAssessmentQuestionInput!): Quiz! + _internal_noauth_updateSelfAssessmentQuestion(input: UpdateSelfAssessmentQuestionInput!): Quiz! # add other types of questions here @@ -140,6 +164,10 @@ input CreateQuizInput { } input CreateMultipleChoiceQuestionInput { + """ + UUID of the question to update and the id of the corresponding item. + """ + itemId: UUID """ Number of the question, used for ordering. This can be omitted, in which case a number, one higher than the highest number of the existing questions, will be used. @@ -161,9 +189,9 @@ input CreateMultipleChoiceQuestionInput { input UpdateMultipleChoiceQuestionInput { """ - UUID of the question to update. + UUID of the question to update and the id of the corresponding item. """ - id: UUID! + itemId: UUID! """ Text of the question, in SlateJS JSON format. """ @@ -195,6 +223,10 @@ input MultipleChoiceAnswerInput { } input CreateClozeQuestionInput { + """ + id of the corresponding item + """ + itemId:UUID """ Number of the question, used for ordering. This can be omitted, in which case a number, one higher than the highest number of the existing questions, will be used. @@ -220,9 +252,9 @@ input CreateClozeQuestionInput { input UpdateClozeQuestionInput { """ - UUID of the question to update. + UUID of the question to update and the id of the corresponding item. """ - id: UUID! + itemId: UUID! """ List of cloze elements. """ @@ -242,6 +274,10 @@ input UpdateClozeQuestionInput { } input ClozeElementInput { + """ + id of the corresponding item + """ + itemId:UUID """ Type of the element. """ @@ -263,6 +299,10 @@ input ClozeElementInput { } input CreateAssociationQuestionInput { + """ + id of the corresponding item + """ + itemId:UUID """ Number of the question, used for ordering. This can be omitted, in which case a number, one higher than the highest number of the existing questions, will be used. @@ -284,9 +324,9 @@ input CreateAssociationQuestionInput { input UpdateAssociationQuestionInput { """ - UUID of the question to update. + UUID of the question to update and the id of the corresponding item. """ - id: UUID! + itemId: UUID! """ Text of the question, in SlateJS JSON format. """ @@ -302,6 +342,10 @@ input UpdateAssociationQuestionInput { } input AssociationInput { + """ + id of the corresponding item + """ + itemId:UUID """ Text of the left side of the association, in SlateJS JSON format. """ @@ -317,6 +361,10 @@ input AssociationInput { } input CreateExactAnswerQuestionInput { + """ + id of the corresponding item + """ + itemId:UUID """ Number of the question, used for ordering. This can be omitted, in which case a number, one higher than the highest number of the existing questions, will be used. @@ -346,9 +394,9 @@ input CreateExactAnswerQuestionInput { input UpdateExactAnswerQuestionInput { """ - UUID of the question to update. + UUID of the question to update and the id of the corresponding item. """ - id: UUID! + itemId: UUID! """ Text of the question, in SlateJS JSON format. """ @@ -372,6 +420,10 @@ input UpdateExactAnswerQuestionInput { } input CreateNumericQuestionInput { + """ + id of the corresponding item + """ + itemId:UUID """ Number of the question, used for ordering. This can be omitted, in which case a number, one higher than the highest number of the existing questions, will be used. @@ -401,9 +453,9 @@ input CreateNumericQuestionInput { input UpdateNumericQuestionInput { """ - UUID of the question to update. + UUID of the question to update and the id of the corresponding item. """ - id: UUID! + itemId: UUID! """ Text of the question, in SlateJS JSON format. """ @@ -427,6 +479,10 @@ input UpdateNumericQuestionInput { } input CreateSelfAssessmentQuestionInput { + """ + id of the corresponding item + """ + itemId:UUID """ Number of the question, used for ordering. This can be omitted, in which case a number, one higher than the highest number of the existing questions, will be used. @@ -448,9 +504,9 @@ input CreateSelfAssessmentQuestionInput { input UpdateSelfAssessmentQuestionInput { """ - UUID of the question to update. + UUID of the question to update and the id of the corresponding item. """ - id: UUID! + itemId: UUID! """ Text of the question, in SlateJS JSON format. """ diff --git a/src/main/resources/graphql/service/quiz.graphqls b/src/main/resources/graphql/service/quiz.graphqls index 9f6d5fd..5e1b710 100644 --- a/src/main/resources/graphql/service/quiz.graphqls +++ b/src/main/resources/graphql/service/quiz.graphqls @@ -63,9 +63,9 @@ Generic question interface. """ interface Question { """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. @@ -103,9 +103,9 @@ type MultipleChoiceQuestion implements Question { # inherited from Question """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. @@ -159,9 +159,9 @@ type ClozeQuestion implements Question { # inherited from Question """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. Only relevant if questionPoolingMode is ORDERED. @@ -225,9 +225,9 @@ type AssociationQuestion implements Question { # inherited from Question """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. Only relevant if questionPoolingMode is ORDERED. @@ -284,9 +284,9 @@ type ExactAnswerQuestion implements Question { # inherited from Question """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. Only relevant if questionPoolingMode is ORDERED. @@ -323,9 +323,9 @@ type NumericQuestion implements Question { # inherited from Question """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. Only relevant if questionPoolingMode is ORDERED. @@ -358,9 +358,9 @@ type SelfAssessmentQuestion implements Question { # inherited from Question """ - Unique identifier of the question. + Unique identifier of the question and the id of the corresponding item """ - id: UUID! + itemId: UUID! """ Number of the question, i.e., the position of the question in the list of questions. Only relevant if questionPoolingMode is ORDERED. diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/TestData.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/TestData.java index 4f15ccc..55fe6d2 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/TestData.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/TestData.java @@ -1,9 +1,9 @@ package de.unistuttgart.iste.meitrex.quiz_service; -import de.unistuttgart.iste.meitrex.generated.dto.ClozeElementType; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionPoolingMode; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.*; +import de.unistuttgart.iste.meitrex.generated.dto.*; + + import java.util.*; import java.util.stream.Stream; @@ -26,6 +26,7 @@ public static MultipleChoiceQuestionEntity createMultipleChoiceQuestion( final String... wrongAnswerText) { final var builder = MultipleChoiceQuestionEntity.builder() + .itemId(UUID.randomUUID()) .type(QuestionType.MULTIPLE_CHOICE) .hint("hint") .number(number) @@ -51,6 +52,7 @@ public static MultipleChoiceQuestionEntity createMultipleChoiceQuestion( public static ClozeQuestionEntity createClozeQuestion(final int number, final ClozeElementEmbeddable... clozeElements) { return ClozeQuestionEntity.builder() + .itemId(UUID.randomUUID()) .type(QuestionType.CLOZE) .number(number) .showBlanksList(true) @@ -77,6 +79,7 @@ public static ClozeElementEmbeddable clozeBlank(final String correctAnswer) { public static AssociationQuestionEntity createAssociationQuestion(final int number, final AssociationEmbeddable... associations) { return AssociationQuestionEntity.builder() + .itemId(UUID.randomUUID()) .type(QuestionType.ASSOCIATION) .number(number) .text("text") @@ -99,6 +102,7 @@ public static AssociationEmbeddable association(final String left, final String public static ExactAnswerQuestionEntity createExactAnswerQuestion(final int number, final String question, final String answer) { return ExactAnswerQuestionEntity.builder() + .itemId(UUID.randomUUID()) .type(QuestionType.EXACT_ANSWER) .number(number) .text(question) @@ -111,6 +115,7 @@ public static ExactAnswerQuestionEntity createExactAnswerQuestion(final int numb public static NumericQuestionEntity createNumericQuestion(final int number, final String question, final double answer) { return NumericQuestionEntity.builder() + .itemId(UUID.randomUUID()) .type(QuestionType.NUMERIC) .number(number) .text(question) @@ -123,6 +128,7 @@ public static NumericQuestionEntity createNumericQuestion(final int number, fina public static SelfAssessmentQuestionEntity createSelfAssessmentQuestion(final int number, final String question, final String answer) { return SelfAssessmentQuestionEntity.builder() + .itemId(UUID.randomUUID()) .type(QuestionType.SELF_ASSESSMENT) .number(number) .text(question) @@ -149,7 +155,7 @@ public static List createDummyQuestions() { .feedback("Well done!") .build(); final MultipleChoiceQuestionEntity questionEntity = MultipleChoiceQuestionEntity.builder() - .id(UUID.randomUUID()) + .itemId(UUID.randomUUID()) .number(0) .type(QuestionType.MULTIPLE_CHOICE) .text("This is a question") @@ -157,7 +163,7 @@ public static List createDummyQuestions() { .hint("Wink Wink") .build(); final MultipleChoiceQuestionEntity questionEntity2 = MultipleChoiceQuestionEntity.builder() - .id(UUID.randomUUID()) + .itemId(UUID.randomUUID()) .number(0) .type(QuestionType.MULTIPLE_CHOICE) .text("This is a question") diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/AuthorizationTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/AuthorizationTest.java index da32738..c580296 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/AuthorizationTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/AuthorizationTest.java @@ -1,6 +1,9 @@ package de.unistuttgart.iste.meitrex.quiz_service.api; + +import de.unistuttgart.iste.meitrex.quiz_service.TestData; + import de.unistuttgart.iste.meitrex.common.testutil.AuthorizationAsserts; import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; @@ -9,7 +12,7 @@ import de.unistuttgart.iste.meitrex.generated.dto.ClozeElementInput; import de.unistuttgart.iste.meitrex.generated.dto.ClozeElementType; import de.unistuttgart.iste.meitrex.generated.dto.CreateClozeQuestionInput; -import de.unistuttgart.iste.meitrex.quiz_service.TestData; + import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import org.junit.jupiter.api.Test; @@ -30,7 +33,7 @@ public class AuthorizationTest { private static final String ADD_CLOZE_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateClozeQuestionInput!) { mutateQuiz(assessmentId: $id) { - addClozeQuestion(input: $input) { + _internal_noauth_addClozeQuestion(input: $input) { ...QuizAllFields } } @@ -55,6 +58,7 @@ void testAddClozeQuestionForAdminOnly(final GraphQlTester graphQlTester) { quizEntity = quizRepository.save(quizEntity); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(UUID.randomUUID()) .setHint("hint") .setAdditionalWrongAnswers(List.of("wrong1", "wrong2")) .setShowBlanksList(false) diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/QuizFragments.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/QuizFragments.java index 2da744e..5c7a7d4 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/QuizFragments.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/QuizFragments.java @@ -11,7 +11,7 @@ public class QuizFragments { public static final String FRAGMENT_DEFINITION = """ fragment QuestionsAllFields on Question { - id + itemId number type hint diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/CreateQuizMutationTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/CreateQuizMutationTest.java index 01beaae..60932a0 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/CreateQuizMutationTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/CreateQuizMutationTest.java @@ -2,9 +2,7 @@ import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; -import de.unistuttgart.iste.meitrex.generated.dto.CreateQuizInput; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionPoolingMode; +import de.unistuttgart.iste.meitrex.generated.dto.*; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import jakarta.transaction.Transactional; @@ -22,7 +20,6 @@ import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class CreateQuizMutationTest { @Autowired diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/DeleteQuizMutationTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/DeleteQuizMutationTest.java index f9e357b..25afc95 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/DeleteQuizMutationTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/DeleteQuizMutationTest.java @@ -2,8 +2,10 @@ import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.generated.dto.QuestionPoolingMode; + import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + import graphql.ErrorType; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddAssociationQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddAssociationQuestionTest.java index 2b78231..b94b848 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddAssociationQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddAssociationQuestionTest.java @@ -1,18 +1,17 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.AssociationEmbeddable; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.AssociationQuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.AssociationInput; -import de.unistuttgart.iste.meitrex.generated.dto.CreateAssociationQuestionInput; -import de.unistuttgart.iste.meitrex.generated.dto.SingleAssociation; + +import de.unistuttgart.iste.meitrex.generated.dto.*; import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.AssociationEmbeddable; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.AssociationQuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; @@ -28,8 +27,9 @@ import static org.hamcrest.Matchers.*; +import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; + @GraphQlApiTest -@TablesToDelete({"association_question_correct_associations", "association_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizAddAssociationQuestionTest { @Autowired @@ -43,7 +43,7 @@ class MutateQuizAddAssociationQuestionTest { private static final String ADD_ASSOCIATION_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateAssociationQuestionInput!) { mutateQuiz(assessmentId: $id) { - addAssociationQuestion(input: $input) { + _internal_noauth_addAssociationQuestion(input: $input) { ...QuizAllFields } } @@ -63,13 +63,14 @@ void testAddAssociationQuestion(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateAssociationQuestionInput input = CreateAssociationQuestionInput.builder() + .setItemId(itemId) .setHint("hint") .setText("question") .setCorrectAssociations(List.of( - new AssociationInput("a", "b", "feedback1"), - new AssociationInput("c", "d", "feedback2"))) + new AssociationInput(UUID.randomUUID(), "a", "b", "feedback1"), + new AssociationInput(UUID.randomUUID(), "c", "d", "feedback2"))) .build(); @@ -77,29 +78,33 @@ void testAddAssociationQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addAssociationQuestion.questionPool[0].number") + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].number") .entity(Integer.class) .isEqualTo(1) - .path("mutateQuiz.addAssociationQuestion.questionPool[0].text") + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].text") .entity(String.class) .isEqualTo("question") - .path("mutateQuiz.addAssociationQuestion.questionPool[0].hint") + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].hint") .entity(String.class) .isEqualTo("hint") - .path("mutateQuiz.addAssociationQuestion.questionPool[0].correctAssociations") + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].itemId") + .entity(UUID.class) + .isEqualTo(itemId) + + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].correctAssociations") .entityList(SingleAssociation.class) .contains( new SingleAssociation("a", "b", "feedback1"), new SingleAssociation("c", "d", "feedback2")) - .path("mutateQuiz.addAssociationQuestion.questionPool[0].leftSide") + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].leftSide") .entityList(String.class) .contains("a", "c") - .path("mutateQuiz.addAssociationQuestion.questionPool[0].rightSide") + .path("mutateQuiz._internal_noauth_addAssociationQuestion.questionPool[0].rightSide") .entityList(String.class) .contains("b", "d"); @@ -113,6 +118,7 @@ void testAddAssociationQuestion(final GraphQlTester graphQlTester) { assertThat(associationQuestionEntity.getHint(), is("hint")); assertThat(associationQuestionEntity.getText(), is("question")); + assertThat(associationQuestionEntity.getItemId(), is(itemId)); assertThat(associationQuestionEntity.getCorrectAssociations(), hasSize(2)); assertThat(associationQuestionEntity.getCorrectAssociations(), containsInAnyOrder( new AssociationEmbeddable("a", "b", "feedback1"), @@ -132,14 +138,15 @@ void testAddAssociationQuestionNotUniqueAnswer(final GraphQlTester graphQlTester .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateAssociationQuestionInput input = CreateAssociationQuestionInput.builder() + .setItemId(itemId) .setNumber(2) .setHint("hint") .setText("question") .setCorrectAssociations(List.of( - new AssociationInput("a", "b", "feedback1"), - new AssociationInput("c", "b", "feedback2"))) + new AssociationInput(UUID.randomUUID(), "a", "b", "feedback1"), + new AssociationInput(UUID.randomUUID(), "c", "b", "feedback2"))) .build(); graphQlTester.document(ADD_ASSOCIATION_QUESTION_MUTATION) diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddClozeQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddClozeQuestionTest.java index ae53bf3..7277385 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddClozeQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddClozeQuestionTest.java @@ -1,18 +1,17 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.ClozeQuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.ClozeElementInput; -import de.unistuttgart.iste.meitrex.generated.dto.ClozeElementType; -import de.unistuttgart.iste.meitrex.generated.dto.CreateClozeQuestionInput; +import de.unistuttgart.iste.meitrex.generated.dto.*; import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.ClozeQuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + import graphql.ErrorType; import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; @@ -26,16 +25,16 @@ import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; @GraphQlApiTest -@TablesToDelete({"cloze_question_additional_wrong_answers", "cloze_question_cloze_elements", "cloze_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizAddClozeQuestionTest { private static final String ADD_CLOZE_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateClozeQuestionInput!) { mutateQuiz(assessmentId: $id) { - addClozeQuestion(input: $input) { + _internal_noauth_addClozeQuestion(input: $input) { ...QuizAllFields } } @@ -63,8 +62,9 @@ void testAddClozeQuestion(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setHint("hint") .setAdditionalWrongAnswers(List.of("wrong1", "wrong2")) .setShowBlanksList(false) @@ -86,27 +86,31 @@ void testAddClozeQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addClozeQuestion.questionPool[0].number") + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].number") .entity(Integer.class) .isEqualTo(1) - .path("mutateQuiz.addClozeQuestion.questionPool[0].showBlanksList") + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].itemId") + .entity(UUID.class) + .isEqualTo(itemId) + + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].showBlanksList") .entity(Boolean.class) .isEqualTo(false) - .path("mutateQuiz.addClozeQuestion.questionPool[0].additionalWrongAnswers") + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].additionalWrongAnswers") .entityList(String.class) .isEqualTo(List.of("wrong1", "wrong2")) - .path("mutateQuiz.addClozeQuestion.questionPool[0].clozeElements[0].text") + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].clozeElements[0].text") .entity(String.class) .isEqualTo("what is the capital of France?") - .path("mutateQuiz.addClozeQuestion.questionPool[0].clozeElements[1].correctAnswer") + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].clozeElements[1].correctAnswer") .entity(String.class) .isEqualTo("Paris") - .path("mutateQuiz.addClozeQuestion.questionPool[0].clozeElements[1].feedback") + .path("mutateQuiz._internal_noauth_addClozeQuestion.questionPool[0].clozeElements[1].feedback") .entity(String.class) .isEqualTo("feedback"); @@ -141,8 +145,9 @@ void testAddClozeWithoutBlank(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setNumber(1) .setShowBlanksList(true) .setClozeElements(List.of( @@ -175,8 +180,9 @@ void addClozeTextElementWithFeedback(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setNumber(1) .setShowBlanksList(true) .setClozeElements(List.of( @@ -210,8 +216,9 @@ void addClozeElementWithCorrectAnswer(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setNumber(1) .setShowBlanksList(true) .setClozeElements(List.of( @@ -244,8 +251,9 @@ void addClozeTextElementWithoutText(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setNumber(1) .setShowBlanksList(true) .setClozeElements(List.of( @@ -277,8 +285,9 @@ void testAddBlankWithoutCorrectAnswer(final GraphQlTester tester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setNumber(1) .setShowBlanksList(true) .setClozeElements(List.of( @@ -306,8 +315,9 @@ void testAddBlankWithText(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateClozeQuestionInput input = CreateClozeQuestionInput.builder() + .setItemId(itemId) .setNumber(1) .setShowBlanksList(true) .setClozeElements(List.of( diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddExactAnswerQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddExactAnswerQuestionTest.java index 42d66ba..5776c44 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddExactAnswerQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddExactAnswerQuestionTest.java @@ -1,16 +1,18 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; +import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.ExactAnswerQuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; + import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; import de.unistuttgart.iste.meitrex.generated.dto.CreateExactAnswerQuestionInput; import de.unistuttgart.iste.meitrex.quiz_service.TestData; -import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.ExactAnswerQuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -24,9 +26,11 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; + + @GraphQlApiTest -@TablesToDelete({"exact_answer_question_correct_answers", "exact_answer_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizAddExactAnswerQuestionTest { @Autowired @@ -39,7 +43,7 @@ class MutateQuizAddExactAnswerQuestionTest { private static final String ADD_EXACT_ANSWER_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateExactAnswerQuestionInput!) { mutateQuiz(assessmentId: $id) { - addExactAnswerQuestion(input: $input) { + _internal_noauth_addExactAnswerQuestion(input: $input) { ...QuizAllFields } } @@ -59,8 +63,9 @@ void testAddExactAnswerQuestion(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateExactAnswerQuestionInput input = CreateExactAnswerQuestionInput.builder() + .setItemId(itemId) .setHint("hint") .setText("question") .setFeedback("feedback") @@ -73,22 +78,25 @@ void testAddExactAnswerQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addExactAnswerQuestion.questionPool[0].number") + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].number") .entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.addExactAnswerQuestion.questionPool[0].hint") + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].itemId") + .entity(UUID.class).isEqualTo(itemId) + + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].hint") .entity(String.class).isEqualTo("hint") - .path("mutateQuiz.addExactAnswerQuestion.questionPool[0].text") + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].text") .entity(String.class).isEqualTo("question") - .path("mutateQuiz.addExactAnswerQuestion.questionPool[0].feedback") + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].feedback") .entity(String.class).isEqualTo("feedback") - .path("mutateQuiz.addExactAnswerQuestion.questionPool[0].caseSensitive") + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].caseSensitive") .entity(Boolean.class).isEqualTo(true) - .path("mutateQuiz.addExactAnswerQuestion.questionPool[0].correctAnswers") + .path("mutateQuiz._internal_noauth_addExactAnswerQuestion.questionPool[0].correctAnswers") .entityList(String.class).contains("a", "b"); final QuestionEntity questionEntity = quizRepository.findById(quizEntity.getAssessmentId()) @@ -98,7 +106,7 @@ void testAddExactAnswerQuestion(final GraphQlTester graphQlTester) { assertThat(questionEntity, instanceOf(ExactAnswerQuestionEntity.class)); final ExactAnswerQuestionEntity exactAnswerQuestionEntity = (ExactAnswerQuestionEntity) questionEntity; - + assertThat(exactAnswerQuestionEntity.getItemId(), is(itemId)); assertThat(exactAnswerQuestionEntity.getHint(), is("hint")); assertThat(exactAnswerQuestionEntity.getText(), is("question")); assertThat(exactAnswerQuestionEntity.getFeedback(), is("feedback")); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddMultipleChoiceQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddMultipleChoiceQuestionTest.java index 36b8742..b499270 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddMultipleChoiceQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddMultipleChoiceQuestionTest.java @@ -4,13 +4,12 @@ import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.CreateMultipleChoiceQuestionInput; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceAnswerInput; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; +import de.unistuttgart.iste.meitrex.generated.dto.*; import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + import graphql.ErrorType; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -25,15 +24,16 @@ import static de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionDtoToEntityMatcher.matchesEntity; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; + @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizAddMultipleChoiceQuestionTest { private static final String UPDATE_MULTIPLE_CHOICE_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateMultipleChoiceQuestionInput!) { mutateQuiz(assessmentId: $id) { - addMultipleChoiceQuestion(input: $input) { + _internal_noauth_addMultipleChoiceQuestion(input: $input) { ...QuizAllFields } } @@ -59,8 +59,9 @@ void testAddMultipleChoiceQuestion(final GraphQlTester graphQlTester) { createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateMultipleChoiceQuestionInput input = CreateMultipleChoiceQuestionInput.builder() + .setItemId(itemId) .setText("what is the capital of France?") .setNumber(2) .setAnswers(List.of( @@ -78,7 +79,7 @@ void testAddMultipleChoiceQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addMultipleChoiceQuestion.questionPool") + .path("mutateQuiz._internal_noauth_addMultipleChoiceQuestion.questionPool") .entityList(MultipleChoiceQuestion.class) .get(); @@ -99,8 +100,9 @@ void testAddMultipleChoiceQuestionNextNumber(final GraphQlTester graphQlTester) createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateMultipleChoiceQuestionInput input = CreateMultipleChoiceQuestionInput.builder() + .setItemId(itemId) .setText("what is the capital of France?") .setNumber(null) // number should be assigned automatically .setAnswers(List.of( @@ -118,7 +120,7 @@ void testAddMultipleChoiceQuestionNextNumber(final GraphQlTester graphQlTester) .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addMultipleChoiceQuestion.questionPool") + .path("mutateQuiz._internal_noauth_addMultipleChoiceQuestion.questionPool") .entityList(MultipleChoiceQuestion.class) .get(); @@ -141,8 +143,9 @@ void testAddMultipleChoiceQuestionDuplicateNumber(final GraphQlTester graphQlTes createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateMultipleChoiceQuestionInput input = CreateMultipleChoiceQuestionInput.builder() + .setItemId(itemId) .setText("what is the capital of France?") .setNumber(1) // already existing number .setAnswers(List.of( @@ -181,8 +184,9 @@ void testAddMultipleChoiceQuestionNoCorrectAnswer(final GraphQlTester graphQlTes createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateMultipleChoiceQuestionInput input = CreateMultipleChoiceQuestionInput.builder() + .setItemId(itemId) .setText("what is the capital of France?") .setAnswers(List.of( MultipleChoiceAnswerInput.builder() @@ -220,8 +224,9 @@ void testAddMultipleChoiceQuestionTooFewAnswers(final GraphQlTester graphQlTeste createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateMultipleChoiceQuestionInput input = CreateMultipleChoiceQuestionInput.builder() + .setItemId(itemId) .setText("what is the capital of France?") .setAnswers(List.of( MultipleChoiceAnswerInput.builder() diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddNumericQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddNumericQuestionTest.java index 437b293..8eca921 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddNumericQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddNumericQuestionTest.java @@ -1,15 +1,15 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; +import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.NumericQuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; import de.unistuttgart.iste.meitrex.generated.dto.CreateNumericQuestionInput; import de.unistuttgart.iste.meitrex.quiz_service.TestData; -import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.NumericQuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; @@ -26,7 +26,6 @@ import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"numeric_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizAddNumericQuestionTest { @Autowired @@ -39,7 +38,7 @@ class MutateQuizAddNumericQuestionTest { private static final String ADD_NUMERIC_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateNumericQuestionInput!) { mutateQuiz(assessmentId: $id) { - addNumericQuestion(input: $input) { + _internal_noauth_addNumericQuestion(input: $input) { ...QuizAllFields } } @@ -59,8 +58,9 @@ void testAddNumericQuestion(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateNumericQuestionInput input = CreateNumericQuestionInput.builder() + .setItemId(itemId) .setHint("hint") .setText("question") .setFeedback("feedback") @@ -72,22 +72,25 @@ void testAddNumericQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addNumericQuestion.questionPool[0].number") + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].number") .entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.addNumericQuestion.questionPool[0].hint") + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].itemId") + .entity(UUID.class).isEqualTo(itemId) + + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].hint") .entity(String.class).isEqualTo("hint") - .path("mutateQuiz.addNumericQuestion.questionPool[0].text") + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].text") .entity(String.class).isEqualTo("question") - .path("mutateQuiz.addNumericQuestion.questionPool[0].feedback") + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].feedback") .entity(String.class).isEqualTo("feedback") - .path("mutateQuiz.addNumericQuestion.questionPool[0].correctAnswer") + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].correctAnswer") .entity(Double.class).isEqualTo(2.0) - .path("mutateQuiz.addNumericQuestion.questionPool[0].tolerance") + .path("mutateQuiz._internal_noauth_addNumericQuestion.questionPool[0].tolerance") .entity(Double.class).isEqualTo(0.5); final QuestionEntity questionEntity = quizRepository.findById(quizEntity.getAssessmentId()) @@ -98,6 +101,7 @@ void testAddNumericQuestion(final GraphQlTester graphQlTester) { assertThat(questionEntity, instanceOf(NumericQuestionEntity.class)); final NumericQuestionEntity numericQuestionEntity = (NumericQuestionEntity) questionEntity; + assertThat(numericQuestionEntity.getItemId(), is(itemId)); assertThat(numericQuestionEntity.getHint(), is("hint")); assertThat(numericQuestionEntity.getText(), is("question")); assertThat(numericQuestionEntity.getFeedback(), is("feedback")); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddSelfAssessmentQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddSelfAssessmentQuestionTest.java index 5ae9220..4ac48cb 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddSelfAssessmentQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizAddSelfAssessmentQuestionTest.java @@ -1,15 +1,13 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; -import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; -import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; -import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; -import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.CreateSelfAssessmentQuestionInput; -import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.SelfAssessmentQuestionEntity; +import de.unistuttgart.iste.meitrex.common.testutil.*; +import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; +import de.unistuttgart.iste.meitrex.generated.dto.CreateSelfAssessmentQuestionInput; +import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; @@ -26,7 +24,6 @@ import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"self_assessment_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizAddSelfAssessmentQuestionTest { @Autowired @@ -39,7 +36,7 @@ class MutateQuizAddSelfAssessmentQuestionTest { private static final String ADD_SELF_ASSESSMENT_QUESTION_MUTATION = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: CreateSelfAssessmentQuestionInput!) { mutateQuiz(assessmentId: $id) { - addSelfAssessmentQuestion(input: $input) { + _internal_noauth_addSelfAssessmentQuestion(input: $input) { ...QuizAllFields } } @@ -59,8 +56,9 @@ void testAddSelfAssessmentQuestion(final GraphQlTester graphQlTester) { .questionPool(List.of()) .build(); quizEntity = quizRepository.save(quizEntity); - + UUID itemId = UUID.randomUUID(); final CreateSelfAssessmentQuestionInput input = CreateSelfAssessmentQuestionInput.builder() + .setItemId(itemId) .setHint("hint") .setText("question") .setSolutionSuggestion("solution suggestion") @@ -70,16 +68,19 @@ void testAddSelfAssessmentQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.addSelfAssessmentQuestion.questionPool[0].number") + .path("mutateQuiz._internal_noauth_addSelfAssessmentQuestion.questionPool[0].number") .entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.addSelfAssessmentQuestion.questionPool[0].hint") + .path("mutateQuiz._internal_noauth_addSelfAssessmentQuestion.questionPool[0].itemId") + .entity(UUID.class).isEqualTo(itemId) + + .path("mutateQuiz._internal_noauth_addSelfAssessmentQuestion.questionPool[0].hint") .entity(String.class).isEqualTo("hint") - .path("mutateQuiz.addSelfAssessmentQuestion.questionPool[0].text") + .path("mutateQuiz._internal_noauth_addSelfAssessmentQuestion.questionPool[0].text") .entity(String.class).isEqualTo("question") - .path("mutateQuiz.addSelfAssessmentQuestion.questionPool[0].solutionSuggestion") + .path("mutateQuiz._internal_noauth_addSelfAssessmentQuestion.questionPool[0].solutionSuggestion") .entity(String.class).isEqualTo("solution suggestion"); final QuestionEntity questionEntity = quizRepository.findById(quizEntity.getAssessmentId()) @@ -90,6 +91,7 @@ void testAddSelfAssessmentQuestion(final GraphQlTester graphQlTester) { assertThat(questionEntity, instanceOf(SelfAssessmentQuestionEntity.class)); final SelfAssessmentQuestionEntity selfAssessmentQuestionEntity = (SelfAssessmentQuestionEntity) questionEntity; + assertThat(selfAssessmentQuestionEntity.getItemId(), is(itemId)); assertThat(selfAssessmentQuestionEntity.getHint(), is("hint")); assertThat(selfAssessmentQuestionEntity.getText(), is("question")); assertThat(selfAssessmentQuestionEntity.getSolutionSuggestion(), is("solution suggestion")); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizRemoveQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizRemoveQuestionTest.java index e9ee922..b9a237b 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizRemoveQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizRemoveQuestionTest.java @@ -26,7 +26,6 @@ import static org.hamcrest.Matchers.*; @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizRemoveQuestionTest { @Autowired diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizSwitchQuestionsTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizSwitchQuestionsTest.java index 2be0379..0c45b48 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizSwitchQuestionsTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizSwitchQuestionsTest.java @@ -1,16 +1,19 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; -import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; -import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; -import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; -import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; +import de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionDtoToEntityMatcher; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; +import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; +import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; +import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; +import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; +import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; + import jakarta.transaction.Transactional; +import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.graphql.test.tester.GraphQlTester; @@ -20,13 +23,11 @@ import java.util.UUID; import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; -import static de.unistuttgart.iste.meitrex.quiz_service.TestData.createMultipleChoiceQuestion; -import static de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionDtoToEntityMatcher.matchesEntity; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizSwitchQuestionsTest { @Autowired @@ -48,9 +49,9 @@ void testSwitchQuestion(final GraphQlTester graphQlTester) { // store questions in separate variable because spring apparently caches the quiz entity instance // so the following quiz entity instance is updated during the mutation final List questionEntities = List.of( - createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"), - createMultipleChoiceQuestion(2, "what is the capital of France?", "Paris", "Madrid"), - createMultipleChoiceQuestion(3, "what is the capital of Spain?", "Madrid", "Berlin")); + TestData.createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"), + TestData.createMultipleChoiceQuestion(2, "what is the capital of France?", "Paris", "Madrid"), + TestData.createMultipleChoiceQuestion(3, "what is the capital of Spain?", "Madrid", "Berlin")); QuizEntity quizEntity = TestData.exampleQuizBuilder(courseId) .questionPool(questionEntities) @@ -76,18 +77,15 @@ void testSwitchQuestion(final GraphQlTester graphQlTester) { assertThat(questions, hasSize(3)); final QuestionEntity expectedFirstEntity = questionEntities.get(0); - expectedFirstEntity.setId(quizEntity.getQuestionPool().get(0).getId()); - assertThat(questions.get(0), matchesEntity(expectedFirstEntity)); + MatcherAssert.assertThat(questions.get(0), MultipleChoiceQuestionDtoToEntityMatcher.matchesEntity(expectedFirstEntity)); final QuestionEntity expectedSecondEntity = questionEntities.get(2); expectedSecondEntity.setNumber(2); - expectedSecondEntity.setId(quizEntity.getQuestionPool().get(1).getId()); - assertThat(questions.get(1), matchesEntity(expectedSecondEntity)); + MatcherAssert.assertThat(questions.get(1), MultipleChoiceQuestionDtoToEntityMatcher.matchesEntity(expectedSecondEntity)); final QuestionEntity expectedThirdEntity = questionEntities.get(1); expectedThirdEntity.setNumber(3); - expectedThirdEntity.setId(quizEntity.getQuestionPool().get(2).getId()); - assertThat(questions.get(2), matchesEntity(expectedThirdEntity)); + MatcherAssert.assertThat(questions.get(2), MultipleChoiceQuestionDtoToEntityMatcher.matchesEntity(expectedThirdEntity)); final QuizEntity newQuizEntity = quizRepository.findById(quizEntity.getAssessmentId()).orElseThrow(); assertThat(newQuizEntity.getQuestionPool(), hasSize(3)); @@ -106,8 +104,8 @@ void testSwitchQuestion(final GraphQlTester graphQlTester) { void testSwotchQuestionNonExisting(final GraphQlTester graphQlTester) { QuizEntity quizEntity = TestData.exampleQuizBuilder(courseId) .questionPool(List.of( - createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"), - createMultipleChoiceQuestion(2, "what is the capital of France?", "Paris", "Madrid"))) + TestData.createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"), + TestData.createMultipleChoiceQuestion(2, "what is the capital of France?", "Paris", "Madrid"))) .build(); quizEntity = quizRepository.save(quizEntity); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizTest.java index d629874..c4ec7c3 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizTest.java @@ -1,12 +1,15 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; +import de.unistuttgart.iste.meitrex.quiz_service.TestData; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; import de.unistuttgart.iste.meitrex.generated.dto.QuestionPoolingMode; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.graphql.test.tester.GraphQlTester; @@ -15,12 +18,10 @@ import java.util.UUID; import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; -import static de.unistuttgart.iste.meitrex.quiz_service.TestData.createMultipleChoiceQuestion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizTest { @Autowired @@ -44,7 +45,7 @@ void testMutateQuiz(final GraphQlTester graphQlTester) { .numberOfRandomlySelectedQuestions(1) .requiredCorrectAnswers(1) .questionPool(List.of( - createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) + TestData.createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateAssociationQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateAssociationQuestionTest.java index fe12303..f70dd22 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateAssociationQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateAssociationQuestionTest.java @@ -1,18 +1,19 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; -import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; -import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; -import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; -import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.AssociationInput; -import de.unistuttgart.iste.meitrex.generated.dto.SingleAssociation; -import de.unistuttgart.iste.meitrex.generated.dto.UpdateAssociationQuestionInput; + import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.AssociationQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; + +import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; +import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; +import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; +import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; +import de.unistuttgart.iste.meitrex.generated.dto.*; import jakarta.transaction.Transactional; +import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.graphql.test.tester.GraphQlTester; @@ -23,12 +24,10 @@ import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; import static de.unistuttgart.iste.meitrex.quiz_service.TestData.association; -import static de.unistuttgart.iste.meitrex.quiz_service.TestData.createAssociationQuestion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @GraphQlApiTest -@TablesToDelete({"association_question_correct_associations", "association_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizUpdateAssociationQuestionTest { @Autowired @@ -44,23 +43,23 @@ class MutateQuizUpdateAssociationQuestionTest { void testUpdateAssociationQuestion(final GraphQlTester graphQlTester) { QuizEntity quizEntity = TestData.exampleQuizBuilder(courseId) .questionPool(List.of( - createAssociationQuestion(1, association("a", "b"), association("c", "d")))) + TestData.createAssociationQuestion(1, TestData.association("a", "b"), TestData.association("c", "d")))) .build(); quizEntity = quizRepository.save(quizEntity); final UpdateAssociationQuestionInput input = UpdateAssociationQuestionInput.builder() - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setHint("new hint") .setText("new question") .setCorrectAssociations(List.of( - new AssociationInput("newA", "newC", "new feedback1"), - new AssociationInput("newB", "newD", "new feedback2"))) + new AssociationInput(UUID.randomUUID(), "newA", "newC", "new feedback1"), + new AssociationInput(UUID.randomUUID(), "newB", "newD", "new feedback2"))) .build(); final String query = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: UpdateAssociationQuestionInput!) { mutateQuiz(assessmentId: $id) { - updateAssociationQuestion(input: $input) { + _internal_noauth_updateAssociationQuestion(input: $input) { ...QuizAllFields } } @@ -71,10 +70,10 @@ void testUpdateAssociationQuestion(final GraphQlTester graphQlTester) { .variable("id", quizEntity.getAssessmentId()) .variable("input", input) .execute() - .path("mutateQuiz.updateAssociationQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.updateAssociationQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") - .path("mutateQuiz.updateAssociationQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") - .path("mutateQuiz.updateAssociationQuestion.questionPool[0].correctAssociations").entityList(SingleAssociation.class) + .path("mutateQuiz._internal_noauth_updateAssociationQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) + .path("mutateQuiz._internal_noauth_updateAssociationQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") + .path("mutateQuiz._internal_noauth_updateAssociationQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") + .path("mutateQuiz._internal_noauth_updateAssociationQuestion.questionPool[0].correctAssociations").entityList(SingleAssociation.class) .contains( new SingleAssociation("newA", "newC", "new feedback1"), new SingleAssociation("newB", "newD", "new feedback2")); @@ -85,9 +84,9 @@ void testUpdateAssociationQuestion(final GraphQlTester graphQlTester) { assertThat(updatedQuestion.getText(), is("new question")); assertThat(updatedQuestion.getHint(), is("new hint")); assertThat(updatedQuestion.getCorrectAssociations(), hasSize(2)); - assertThat(updatedQuestion.getCorrectAssociations(), containsInAnyOrder( - association("newA", "newC", "new feedback1"), - association("newB", "newD", "new feedback2"))); + assertThat(updatedQuestion.getCorrectAssociations(), Matchers.containsInAnyOrder( + TestData.association("newA", "newC", "new feedback1"), + TestData.association("newB", "newD", "new feedback2"))); } diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateClozeQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateClozeQuestionTest.java index 90b0f89..c4bbf39 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateClozeQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateClozeQuestionTest.java @@ -20,13 +20,12 @@ import java.util.UUID; import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; -import static de.unistuttgart.iste.meitrex.quiz_service.TestData.*; +import static de.unistuttgart.iste.meitrex.quiz_service.TestData.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"cloze_question_additional_wrong_answers", "cloze_question_cloze_elements", "cloze_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizUpdateClozeQuestionTest { @Autowired @@ -49,7 +48,7 @@ void testUpdateClozeQuestion(final GraphQlTester graphQlTester) { quizEntity = quizRepository.save(quizEntity); final UpdateClozeQuestionInput input = UpdateClozeQuestionInput.builder() - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setClozeElements(List.of( ClozeElementInput.builder() .setType(ClozeElementType.TEXT) @@ -68,7 +67,7 @@ void testUpdateClozeQuestion(final GraphQlTester graphQlTester) { final String query = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: UpdateClozeQuestionInput!) { mutateQuiz(assessmentId: $id) { - updateClozeQuestion(input: $input) { + _internal_noauth_updateClozeQuestion(input: $input) { ...QuizAllFields } } @@ -79,32 +78,32 @@ void testUpdateClozeQuestion(final GraphQlTester graphQlTester) { .variable("id", quizEntity.getAssessmentId()) .variable("input", input) .execute() - .path("mutateQuiz.updateClozeQuestion.questionPool[0].number") + .path("mutateQuiz._internal_noauth_updateClozeQuestion.questionPool[0].number") .entity(Integer.class) .isEqualTo(1) - .path("mutateQuiz.updateClozeQuestion.questionPool[0].clozeElements[0]") + .path("mutateQuiz._internal_noauth_updateClozeQuestion.questionPool[0].clozeElements[0]") .entity(ClozeTextElement.class) .isEqualTo(ClozeTextElement.builder() .setText("This is an example text with a blank.") .build()) - .path("mutateQuiz.updateClozeQuestion.questionPool[0].clozeElements[1]") + .path("mutateQuiz._internal_noauth_updateClozeQuestion.questionPool[0].clozeElements[1]") .entity(ClozeBlankElement.class) .isEqualTo(ClozeBlankElement.builder() .setCorrectAnswer("blank") .setFeedback("new feedback") .build()) - .path("mutateQuiz.updateClozeQuestion.questionPool[0].showBlanksList") + .path("mutateQuiz._internal_noauth_updateClozeQuestion.questionPool[0].showBlanksList") .entity(Boolean.class) .isEqualTo(false) - .path("mutateQuiz.updateClozeQuestion.questionPool[0].hint") + .path("mutateQuiz._internal_noauth_updateClozeQuestion.questionPool[0].hint") .entity(String.class) .isEqualTo("new hint") - .path("mutateQuiz.updateClozeQuestion.questionPool[0].additionalWrongAnswers") + .path("mutateQuiz._internal_noauth_updateClozeQuestion.questionPool[0].additionalWrongAnswers") .entityList(String.class) .containsExactly("new wrong answer"); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateExactAnswerQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateExactAnswerQuestionTest.java index e956c9d..bc3625c 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateExactAnswerQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateExactAnswerQuestionTest.java @@ -1,12 +1,12 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; +import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; import de.unistuttgart.iste.meitrex.generated.dto.UpdateExactAnswerQuestionInput; import de.unistuttgart.iste.meitrex.quiz_service.TestData; -import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.ExactAnswerQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; @@ -25,7 +25,6 @@ import static org.hamcrest.Matchers.*; @GraphQlApiTest -@TablesToDelete({"exact_answer_question_correct_answers", "exact_answer_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizUpdateExactAnswerQuestionTest { @Autowired @@ -46,7 +45,7 @@ void testUpdateExactAnswerQuestion(final GraphQlTester graphQlTester) { quizEntity = quizRepository.save(quizEntity); final UpdateExactAnswerQuestionInput input = UpdateExactAnswerQuestionInput.builder() - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setHint("new hint") .setText("new question") .setFeedback("new feedback") @@ -57,7 +56,7 @@ void testUpdateExactAnswerQuestion(final GraphQlTester graphQlTester) { final String query = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: UpdateExactAnswerQuestionInput!) { mutateQuiz(assessmentId: $id) { - updateExactAnswerQuestion(input: $input) { + _internal_noauth_updateExactAnswerQuestion(input: $input) { ...QuizAllFields } } @@ -68,12 +67,12 @@ void testUpdateExactAnswerQuestion(final GraphQlTester graphQlTester) { .variable("id", quizEntity.getAssessmentId()) .variable("input", input) .execute() - .path("mutateQuiz.updateExactAnswerQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.updateExactAnswerQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") - .path("mutateQuiz.updateExactAnswerQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") - .path("mutateQuiz.updateExactAnswerQuestion.questionPool[0].feedback").entity(String.class).isEqualTo("new feedback") - .path("mutateQuiz.updateExactAnswerQuestion.questionPool[0].caseSensitive").entity(Boolean.class).isEqualTo(false) - .path("mutateQuiz.updateExactAnswerQuestion.questionPool[0].correctAnswers").entityList(String.class).contains("newA", "newB"); + .path("mutateQuiz._internal_noauth_updateExactAnswerQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) + .path("mutateQuiz._internal_noauth_updateExactAnswerQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") + .path("mutateQuiz._internal_noauth_updateExactAnswerQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") + .path("mutateQuiz._internal_noauth_updateExactAnswerQuestion.questionPool[0].feedback").entity(String.class).isEqualTo("new feedback") + .path("mutateQuiz._internal_noauth_updateExactAnswerQuestion.questionPool[0].caseSensitive").entity(Boolean.class).isEqualTo(false) + .path("mutateQuiz._internal_noauth_updateExactAnswerQuestion.questionPool[0].correctAnswers").entityList(String.class).contains("newA", "newB"); final QuizEntity updatedQuiz = quizRepository.findById(quizEntity.getAssessmentId()).orElseThrow(); assertThat(updatedQuiz.getQuestionPool(), hasSize(1)); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateMultipleChoiceQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateMultipleChoiceQuestionTest.java index 574022e..63d7c6c 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateMultipleChoiceQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateMultipleChoiceQuestionTest.java @@ -1,17 +1,19 @@ package de.unistuttgart.iste.meitrex.quiz_service.api.mutation; -import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; -import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; -import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; -import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceAnswerInput; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; -import de.unistuttgart.iste.meitrex.generated.dto.UpdateMultipleChoiceQuestionInput; + import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; +import de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionDtoToUpdateInputMatcher; +import de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionEntityToUpdateInputMatcher; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; +import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; +import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; +import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; +import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; +import de.unistuttgart.iste.meitrex.generated.dto.*; import jakarta.transaction.Transactional; +import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.graphql.test.tester.GraphQlTester; @@ -21,14 +23,10 @@ import java.util.UUID; import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; -import static de.unistuttgart.iste.meitrex.quiz_service.TestData.createMultipleChoiceQuestion; -import static de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionDtoToUpdateInputMatcher.matchesInput; -import static de.unistuttgart.iste.meitrex.quiz_service.matcher.MultipleChoiceQuestionEntityToUpdateInputMatcher.matchesUpdateQuizInput; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizUpdateMultipleChoiceQuestionTest { @Autowired @@ -44,12 +42,12 @@ class MutateQuizUpdateMultipleChoiceQuestionTest { void testUpdateMultipleChoiceQuestion(final GraphQlTester graphQlTester) { QuizEntity quizEntity = TestData.exampleQuizBuilder(courseId) .questionPool(List.of( - createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) + TestData.createMultipleChoiceQuestion(1, "what is the capital of Germany?", "Berlin", "Paris"))) .build(); quizEntity = quizRepository.save(quizEntity); final UpdateMultipleChoiceQuestionInput input = UpdateMultipleChoiceQuestionInput.builder() - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setText("what is the capital of France?") .setAnswers(List.of( MultipleChoiceAnswerInput.builder() @@ -65,7 +63,7 @@ void testUpdateMultipleChoiceQuestion(final GraphQlTester graphQlTester) { final String query = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: UpdateMultipleChoiceQuestionInput!) { mutateQuiz(assessmentId: $id) { - updateMultipleChoiceQuestion(input: $input) { + _internal_noauth_updateMultipleChoiceQuestion(input: $input) { ...QuizAllFields } } @@ -76,17 +74,16 @@ void testUpdateMultipleChoiceQuestion(final GraphQlTester graphQlTester) { .variable("input", input) .variable("id", quizEntity.getAssessmentId()) .execute() - .path("mutateQuiz.updateMultipleChoiceQuestion.questionPool") + .path("mutateQuiz._internal_noauth_updateMultipleChoiceQuestion.questionPool") .entityList(MultipleChoiceQuestion.class) .get(); assertThat(questions, hasSize(1)); - System.out.println(questions.get(0)); - assertThat(questions.get(0), matchesInput(input)); + MatcherAssert.assertThat(questions.get(0), MultipleChoiceQuestionDtoToUpdateInputMatcher.matchesInput(input)); final QuizEntity updatedQuiz = quizRepository.findById(quizEntity.getAssessmentId()).orElseThrow(); assertThat(updatedQuiz.getQuestionPool(), hasSize(1)); - assertThat(updatedQuiz.getQuestionPool().get(0), matchesUpdateQuizInput(input)); + assertThat(updatedQuiz.getQuestionPool().get(0), MultipleChoiceQuestionEntityToUpdateInputMatcher.matchesUpdateQuizInput(input)); } } diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateNumericQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateNumericQuestionTest.java index b1dbf66..fc22444 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateNumericQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateNumericQuestionTest.java @@ -5,28 +5,25 @@ import de.unistuttgart.iste.meitrex.common.testutil.TablesToDelete; import de.unistuttgart.iste.meitrex.common.user_handling.LoggedInUser; import de.unistuttgart.iste.meitrex.generated.dto.UpdateNumericQuestionInput; -import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.api.QuizFragments; -import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.NumericQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; +import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.NumericQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; +import de.unistuttgart.iste.meitrex.quiz_service.TestData; + import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.graphql.test.tester.GraphQlTester; import org.springframework.test.annotation.Commit; - import java.util.List; import java.util.UUID; - import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; -import static de.unistuttgart.iste.meitrex.quiz_service.TestData.createNumericQuestion; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"numeric_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizUpdateNumericQuestionTest { @Autowired @@ -42,12 +39,12 @@ class MutateQuizUpdateNumericQuestionTest { void testUpdateNumericQuestion(final GraphQlTester graphQlTester) { QuizEntity quizEntity = TestData.exampleQuizBuilder(courseId) .questionPool(List.of( - createNumericQuestion(1, "question", 2.0))) + TestData.createNumericQuestion(1, "question", 2.0))) .build(); quizEntity = quizRepository.save(quizEntity); final UpdateNumericQuestionInput input = UpdateNumericQuestionInput.builder() - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setHint("new hint") .setText("new question") .setCorrectAnswer(3.0) @@ -58,7 +55,7 @@ void testUpdateNumericQuestion(final GraphQlTester graphQlTester) { final String query = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: UpdateNumericQuestionInput!) { mutateQuiz(assessmentId: $id) { - updateNumericQuestion(input: $input) { + _internal_noauth_updateNumericQuestion(input: $input) { ...QuizAllFields } } @@ -69,11 +66,11 @@ void testUpdateNumericQuestion(final GraphQlTester graphQlTester) { .variable("id", quizEntity.getAssessmentId()) .variable("input", input) .execute() - .path("mutateQuiz.updateNumericQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.updateNumericQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") - .path("mutateQuiz.updateNumericQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") - .path("mutateQuiz.updateNumericQuestion.questionPool[0].correctAnswer").entity(Double.class).isEqualTo(3.0) - .path("mutateQuiz.updateNumericQuestion.questionPool[0].tolerance").entity(Double.class).isEqualTo(0.1); + .path("mutateQuiz._internal_noauth_updateNumericQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) + .path("mutateQuiz._internal_noauth_updateNumericQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") + .path("mutateQuiz._internal_noauth_updateNumericQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") + .path("mutateQuiz._internal_noauth_updateNumericQuestion.questionPool[0].correctAnswer").entity(Double.class).isEqualTo(3.0) + .path("mutateQuiz._internal_noauth_updateNumericQuestion.questionPool[0].tolerance").entity(Double.class).isEqualTo(0.1); final QuizEntity updatedQuiz = quizRepository.findById(quizEntity.getAssessmentId()).orElseThrow(); assertThat(updatedQuiz.getQuestionPool(), hasSize(1)); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateSelfAssessmentQuestionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateSelfAssessmentQuestionTest.java index b38cb15..cf9a3d6 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateSelfAssessmentQuestionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutateQuizUpdateSelfAssessmentQuestionTest.java @@ -26,7 +26,6 @@ import static org.hamcrest.Matchers.is; @GraphQlApiTest -@TablesToDelete({"self_assessment_question", "quiz_question_pool", "question", "quiz"}) class MutateQuizUpdateSelfAssessmentQuestionTest { @Autowired @@ -47,7 +46,7 @@ void testUpdateSelfAssessmentQuestion(final GraphQlTester graphQlTester) { quizEntity = quizRepository.save(quizEntity); final UpdateSelfAssessmentQuestionInput input = UpdateSelfAssessmentQuestionInput.builder() - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setHint("new hint") .setText("new question") .setSolutionSuggestion("new solution suggestion") @@ -56,7 +55,7 @@ void testUpdateSelfAssessmentQuestion(final GraphQlTester graphQlTester) { final String query = QuizFragments.FRAGMENT_DEFINITION + """ mutation($id: UUID!, $input: UpdateSelfAssessmentQuestionInput!) { mutateQuiz(assessmentId: $id) { - updateSelfAssessmentQuestion(input: $input) { + _internal_noauth_updateSelfAssessmentQuestion(input: $input) { ...QuizAllFields } } @@ -67,10 +66,10 @@ void testUpdateSelfAssessmentQuestion(final GraphQlTester graphQlTester) { .variable("id", quizEntity.getAssessmentId()) .variable("input", input) .execute() - .path("mutateQuiz.updateSelfAssessmentQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) - .path("mutateQuiz.updateSelfAssessmentQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") - .path("mutateQuiz.updateSelfAssessmentQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") - .path("mutateQuiz.updateSelfAssessmentQuestion.questionPool[0].solutionSuggestion").entity(String.class).isEqualTo("new solution suggestion"); + .path("mutateQuiz._internal_noauth_updateSelfAssessmentQuestion.questionPool[0].number").entity(Integer.class).isEqualTo(1) + .path("mutateQuiz._internal_noauth_updateSelfAssessmentQuestion.questionPool[0].text").entity(String.class).isEqualTo("new question") + .path("mutateQuiz._internal_noauth_updateSelfAssessmentQuestion.questionPool[0].hint").entity(String.class).isEqualTo("new hint") + .path("mutateQuiz._internal_noauth_updateSelfAssessmentQuestion.questionPool[0].solutionSuggestion").entity(String.class).isEqualTo("new solution suggestion"); final QuizEntity updatedQuiz = quizRepository.findById(quizEntity.getAssessmentId()).orElseThrow(); assertThat(updatedQuiz.getQuestionPool(), hasSize(1)); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutationLogQuizCompletionTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutationLogQuizCompletionTest.java index 102ddf7..4fc6e52 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutationLogQuizCompletionTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/mutation/MutationLogQuizCompletionTest.java @@ -2,6 +2,8 @@ import de.unistuttgart.iste.meitrex.common.dapr.TopicPublisher; import de.unistuttgart.iste.meitrex.common.event.ContentProgressedEvent; +import de.unistuttgart.iste.meitrex.common.event.Response; + import de.unistuttgart.iste.meitrex.common.testutil.GraphQlApiTest; import de.unistuttgart.iste.meitrex.common.testutil.InjectCurrentUserHeader; import de.unistuttgart.iste.meitrex.common.testutil.MockTestPublisherConfiguration; @@ -33,7 +35,6 @@ @GraphQlApiTest @ContextConfiguration(classes = MockTestPublisherConfiguration.class) -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", "quiz_question_pool", "question", "quiz"}) class MutationLogQuizCompletionTest { @Autowired @@ -70,12 +71,12 @@ void testLogQuizCompletion(final HttpGraphQlTester graphQlTester) { // create Inputs final QuestionCompletedInput inputQuestion = QuestionCompletedInput.builder() - .setQuestionId(quizEntity.getQuestionPool().get(0).getId()) + .setQuestionId(quizEntity.getQuestionPool().get(0).getItemId()) .setCorrect(true) .setUsedHint(false) .build(); final QuestionCompletedInput inputQuestion2 = QuestionCompletedInput.builder() - .setQuestionId(quizEntity.getQuestionPool().get(1).getId()) + .setQuestionId(quizEntity.getQuestionPool().get(1).getItemId()) .setCorrect(false) .setUsedHint(true) .build(); @@ -84,7 +85,15 @@ void testLogQuizCompletion(final HttpGraphQlTester graphQlTester) { .setQuizId(assessmentId) .setCompletedQuestions(List.of(inputQuestion, inputQuestion2)) .build(); - + final Response response1 = Response.builder() + .itemId(questions.get(0).getItemId()) + .response(1) + .build(); + final Response response2 = Response.builder() + .itemId(questions.get(1).getItemId()) + .response(0) + .build(); + final List responses = List.of(response1, response2); // create expected Progress event final ContentProgressedEvent expectedUserProgressLogEvent = ContentProgressedEvent.builder() .userId(loggedInUser.getId()) @@ -93,6 +102,7 @@ void testLogQuizCompletion(final HttpGraphQlTester graphQlTester) { .success(false) .timeToComplete(null) .correctness(1.0 / quizEntity.getQuestionPool().size()) + .responses(responses) .build(); final QuizCompletionFeedback expectedQuizCompletionFeedback = QuizCompletionFeedback.builder() .setCorrectness(1.0 / quizEntity.getQuestionPool().size()) diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/query/QueryByIdTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/query/QueryByIdTest.java index 3d9021f..08c9aa2 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/query/QueryByIdTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/api/query/QueryByIdTest.java @@ -23,12 +23,6 @@ import static org.hamcrest.Matchers.*; @GraphQlApiTest -@TablesToDelete({"multiple_choice_question_answers", "multiple_choice_question", - "cloze_question_additional_wrong_answers", "cloze_question_cloze_elements", "cloze_question", - "association_question_correct_associations", "association_question", - "exact_answer_question_correct_answers", "exact_answer_question", - "numeric_question", "self_assessment_question", - "quiz_question_pool", "question", "quiz"}) class QueryByIdTest { @Autowired @@ -118,7 +112,7 @@ void queryQuizWithQuestions(final GraphQlTester graphQlTester) throws Exception .setNumber(1) .setText("What is the answer to life, the universe and everything?") .setHint("hint") - .setId(quizEntity.getQuestionPool().get(0).getId()) + .setItemId(quizEntity.getQuestionPool().get(0).getItemId()) .setAnswers(List.of( MultipleChoiceAnswer.builder() .setAnswerText("42") @@ -135,10 +129,9 @@ void queryQuizWithQuestions(final GraphQlTester graphQlTester) throws Exception .build(), AssociationQuestion.builder() .setNumber(2) - .setId(quizEntity.getQuestionPool().get(1).getId()) .setText("text") .setHint("hint") - .setId(quizEntity.getQuestionPool().get(1).getId()) + .setItemId(quizEntity.getQuestionPool().get(1).getItemId()) .setType(QuestionType.ASSOCIATION) .setCorrectAssociations(List.of( new SingleAssociation("A", "1", "feedback"), @@ -149,7 +142,7 @@ void queryQuizWithQuestions(final GraphQlTester graphQlTester) throws Exception ClozeQuestion.builder() .setNumber(3) .setHint("hint") - .setId(quizEntity.getQuestionPool().get(2).getId()) + .setItemId(quizEntity.getQuestionPool().get(2).getItemId()) .setType(QuestionType.CLOZE) .setShowBlanksList(true) .setAdditionalWrongAnswers(List.of("wrong1", "wrong2")) @@ -166,7 +159,7 @@ void queryQuizWithQuestions(final GraphQlTester graphQlTester) throws Exception ExactAnswerQuestion.builder() .setNumber(4) .setHint("hint") - .setId(quizEntity.getQuestionPool().get(3).getId()) + .setItemId(quizEntity.getQuestionPool().get(3).getItemId()) .setType(QuestionType.EXACT_ANSWER) .setText("question") .setCorrectAnswers(List.of("answer")) @@ -176,7 +169,7 @@ void queryQuizWithQuestions(final GraphQlTester graphQlTester) throws Exception NumericQuestion.builder() .setNumber(5) .setHint("hint") - .setId(quizEntity.getQuestionPool().get(4).getId()) + .setItemId(quizEntity.getQuestionPool().get(4).getItemId()) .setType(QuestionType.NUMERIC) .setText("question") .setCorrectAnswer(42) @@ -186,7 +179,7 @@ void queryQuizWithQuestions(final GraphQlTester graphQlTester) throws Exception SelfAssessmentQuestion.builder() .setNumber(6) .setHint("hint") - .setId(quizEntity.getQuestionPool().get(5).getId()) + .setItemId(quizEntity.getQuestionPool().get(5).getItemId()) .setType(QuestionType.SELF_ASSESSMENT) .setText("question") .setSolutionSuggestion("answer") diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerDtoToEntityMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerDtoToEntityMatcher.java index ffe4dba..9dd89ea 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerDtoToEntityMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerDtoToEntityMatcher.java @@ -1,7 +1,6 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; - -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceAnswer; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.MultipleChoiceAnswerEmbeddable; +import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceAnswer; import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerEntityToInputMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerEntityToInputMatcher.java index 18b6dc5..b69fd60 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerEntityToInputMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceAnswerEntityToInputMatcher.java @@ -1,7 +1,7 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceAnswerInput; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.MultipleChoiceAnswerEmbeddable; +import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceAnswerInput; import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToCreateInputMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToCreateInputMatcher.java index 5e94a68..386d92a 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToCreateInputMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToCreateInputMatcher.java @@ -1,8 +1,7 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; -import de.unistuttgart.iste.meitrex.generated.dto.CreateMultipleChoiceQuestionInput; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; + +import de.unistuttgart.iste.meitrex.generated.dto.*; import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; @@ -25,6 +24,10 @@ public static MultipleChoiceQuestionDtoToCreateInputMatcher matchesInput(final C @Override protected boolean matchesSafely(final MultipleChoiceQuestion item, final Description mismatchDescription) { + if (!Objects.equals(item.getItemId(), expected.getItemId())) { + mismatchDescription.appendText("id was ").appendValue(item.getItemId()); + return false; + } if (!Objects.equals(item.getNumber(), expected.getNumber())) { mismatchDescription.appendText("number was ").appendValue(item.getNumber()); return false; diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToEntityMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToEntityMatcher.java index 4afce0b..4662b88 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToEntityMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToEntityMatcher.java @@ -1,9 +1,9 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.MultipleChoiceQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; +import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; +import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; @@ -30,8 +30,11 @@ protected boolean matchesSafely(final MultipleChoiceQuestion item, final Descrip mismatchDescription.appendText("expected was not a MultipleChoiceQuestionEntity"); return false; } - // for convenience, we do not check the id as it is usually null before saving + if (!Objects.equals(item.getItemId(), expected.getItemId())) { + mismatchDescription.appendText("id was ").appendValue(item.getItemId()); + return false; + } if (item.getNumber() != expected.getNumber()) { mismatchDescription.appendText("number was ").appendValue(item.getNumber()); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToUpdateInputMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToUpdateInputMatcher.java index 3659392..76a6d46 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToUpdateInputMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionDtoToUpdateInputMatcher.java @@ -1,8 +1,6 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; -import de.unistuttgart.iste.meitrex.generated.dto.MultipleChoiceQuestion; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; -import de.unistuttgart.iste.meitrex.generated.dto.UpdateMultipleChoiceQuestionInput; +import de.unistuttgart.iste.meitrex.generated.dto.*; import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; @@ -25,8 +23,8 @@ public static MultipleChoiceQuestionDtoToUpdateInputMatcher matchesInput(final U @Override protected boolean matchesSafely(final MultipleChoiceQuestion item, final Description mismatchDescription) { - if (!Objects.equals(item.getId(), expected.getId())) { - mismatchDescription.appendText("id was ").appendValue(item.getId()); + if (!Objects.equals(item.getItemId(), expected.getItemId())) { + mismatchDescription.appendText("id was ").appendValue(item.getItemId()); return false; } if (!Objects.equals(item.getType(), QuestionType.MULTIPLE_CHOICE)) { diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionEntityToUpdateInputMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionEntityToUpdateInputMatcher.java index a312962..360895f 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionEntityToUpdateInputMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/MultipleChoiceQuestionEntityToUpdateInputMatcher.java @@ -1,9 +1,8 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; - -import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; -import de.unistuttgart.iste.meitrex.generated.dto.UpdateMultipleChoiceQuestionInput; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.MultipleChoiceQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; +import de.unistuttgart.iste.meitrex.generated.dto.QuestionType; +import de.unistuttgart.iste.meitrex.generated.dto.UpdateMultipleChoiceQuestionInput; import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; @@ -26,8 +25,8 @@ public static MultipleChoiceQuestionEntityToUpdateInputMatcher matchesUpdateQuiz @Override protected boolean matchesSafely(final QuestionEntity item, final Description mismatchDescription) { - if (!Objects.equals(item.getId(), expected.getId())) { - mismatchDescription.appendText("id was ").appendValue(item.getId()); + if (!Objects.equals(item.getItemId(), expected.getItemId())) { + mismatchDescription.appendText("id was ").appendValue(item.getItemId()); return false; } if (!Objects.equals(item.getType(), QuestionType.MULTIPLE_CHOICE)) { diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/QuizEntityToCreateInputMatcher.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/QuizEntityToCreateInputMatcher.java index 813c9a8..e784f1c 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/QuizEntityToCreateInputMatcher.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/matcher/QuizEntityToCreateInputMatcher.java @@ -1,7 +1,8 @@ package de.unistuttgart.iste.meitrex.quiz_service.matcher; -import de.unistuttgart.iste.meitrex.generated.dto.CreateQuizInput; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuizEntity; +import de.unistuttgart.iste.meitrex.generated.dto.CreateQuizInput; + import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; diff --git a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizServiceTest.java b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizServiceTest.java index 0055549..65f9278 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizServiceTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/quiz_service/service/QuizServiceTest.java @@ -1,14 +1,6 @@ package de.unistuttgart.iste.meitrex.quiz_service.service; -import de.unistuttgart.iste.meitrex.common.dapr.TopicPublisher; -import de.unistuttgart.iste.meitrex.common.event.ContentChangeEvent; -import de.unistuttgart.iste.meitrex.common.event.ContentProgressedEvent; -import de.unistuttgart.iste.meitrex.common.event.CrudOperation; -import de.unistuttgart.iste.meitrex.common.exception.IncompleteEventMessageException; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionCompletedInput; -import de.unistuttgart.iste.meitrex.generated.dto.QuestionPoolingMode; -import de.unistuttgart.iste.meitrex.generated.dto.QuizCompletedInput; -import de.unistuttgart.iste.meitrex.generated.dto.QuizCompletionFeedback; + import de.unistuttgart.iste.meitrex.quiz_service.TestData; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.MultipleChoiceQuestionEntity; import de.unistuttgart.iste.meitrex.quiz_service.persistence.entity.QuestionEntity; @@ -16,6 +8,11 @@ import de.unistuttgart.iste.meitrex.quiz_service.persistence.mapper.QuizMapper; import de.unistuttgart.iste.meitrex.quiz_service.persistence.repository.QuizRepository; import de.unistuttgart.iste.meitrex.quiz_service.validation.QuizValidator; +import de.unistuttgart.iste.meitrex.common.dapr.TopicPublisher; +import de.unistuttgart.iste.meitrex.common.event.*; +import de.unistuttgart.iste.meitrex.common.exception.IncompleteEventMessageException; +import de.unistuttgart.iste.meitrex.generated.dto.*; + import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.modelmapper.ModelMapper; @@ -153,12 +150,12 @@ void publishProgressRandomModeTest() { // create Inputs final QuestionCompletedInput inputQuestion = QuestionCompletedInput.builder() - .setQuestionId(questions.get(0).getId()) + .setQuestionId(questions.get(0).getItemId()) .setCorrect(true) .setUsedHint(false) .build(); final QuestionCompletedInput inputQuestion2 = QuestionCompletedInput.builder() - .setQuestionId(questions.get(1).getId()) + .setQuestionId(questions.get(1).getItemId()) .setCorrect(true) .setUsedHint(false) .build(); @@ -167,6 +164,16 @@ void publishProgressRandomModeTest() { .setQuizId(assessmentId) .setCompletedQuestions(List.of(inputQuestion, inputQuestion2)) .build(); + final Response response1 = Response.builder() + .itemId(questions.get(0).getItemId()) + .response(1) + .build(); + final Response response2 = Response.builder() + .itemId(questions.get(1).getItemId()) + .response(1) + .build(); + + final List responses = List.of(response1, response2); // create expected Progress event final ContentProgressedEvent expectedUserProgressLogEvent = ContentProgressedEvent.builder() @@ -176,6 +183,7 @@ void publishProgressRandomModeTest() { .success(true) .timeToComplete(null) .correctness(2.0 / quizEntity.getNumberOfRandomlySelectedQuestions()) + .responses(responses) .build(); final QuizCompletionFeedback expectedQuizCompletionFeedback = QuizCompletionFeedback.builder() .setSuccess(true) @@ -214,12 +222,12 @@ void publishProgressOrderedModeTest() { // create Inputs final QuestionCompletedInput inputQuestion = QuestionCompletedInput.builder() - .setQuestionId(questions.get(0).getId()) + .setQuestionId(questions.get(0).getItemId()) .setCorrect(true) .setUsedHint(false) .build(); final QuestionCompletedInput inputQuestion2 = QuestionCompletedInput.builder() - .setQuestionId(questions.get(1).getId()) + .setQuestionId(questions.get(1).getItemId()) .setCorrect(false) .setUsedHint(true) .build(); @@ -228,7 +236,16 @@ void publishProgressOrderedModeTest() { .setQuizId(assessmentId) .setCompletedQuestions(List.of(inputQuestion, inputQuestion2)) .build(); + final Response response1 = Response.builder() + .itemId(questions.get(0).getItemId()) + .response(1) + .build(); + final Response response2 = Response.builder() + .itemId(questions.get(1).getItemId()) + .response(0) + .build(); + final List responses = List.of(response1, response2); // create expected Progress event final ContentProgressedEvent expectedUserProgressLogEvent = ContentProgressedEvent.builder() .userId(userId) @@ -237,6 +254,7 @@ void publishProgressOrderedModeTest() { .success(false) .timeToComplete(null) .correctness(1.0 / quizEntity.getQuestionPool().size()) + .responses(responses) .build(); final QuizCompletionFeedback expectedQuizCompletionFeedback = QuizCompletionFeedback.builder() .setCorrectness(1.0 / quizEntity.getQuestionPool().size())