package pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.service
import pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.domain.TeacherDashboard
import pt.ulisboa.tecnico.socialsoftware.tutor.exceptions.ErrorMessage
import pt.ulisboa.tecnico.socialsoftware.tutor.exceptions.TutorException
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.boot.test.context.TestConfiguration
import pt.ulisboa.tecnico.socialsoftware.tutor.BeanConfiguration;
import pt.ulisboa.tecnico.socialsoftware.tutor.SpockTest
import pt.ulisboa.tecnico.socialsoftware.tutor.user.domain.Teacher
import pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.domain.QuestionStats;
import pt.ulisboa.tecnico.socialsoftware.tutor.quiz.domain.Quiz
import pt.ulisboa.tecnico.socialsoftware.tutor.user.domain.Student
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.Question
import pt.ulisboa.tecnico.socialsoftware.tutor.quiz.domain.QuizQuestion
import pt.ulisboa.tecnico.socialsoftware.tutor.answer.domain.QuestionAnswer
import pt.ulisboa.tecnico.socialsoftware.tutor.answer.domain.QuizAnswer
import pt.ulisboa.tecnico.socialsoftware.tutor.auth.domain.AuthUser
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.MultipleChoiceQuestion
import pt.ulisboa.tecnico.socialsoftware.tutor.answer.domain.MultipleChoiceAnswer
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.Option
import pt.ulisboa.tecnico.socialsoftware.tutor.utils.DateHandler
import spock.lang.Unroll
@DataJpaTest
class UpdateTeacherDashboardTest extends SpockTest {
def teacher
def teacherdashboard
def questionStats
def setup() {
createExternalCourseAndExecution()
teacher = new Teacher(USER_1_NAME, false)
userRepository.save(teacher)
teacherdashboard = new TeacherDashboard(externalCourseExecution, teacher)
teacherDashboardRepository.save(teacherdashboard)
questionStats = new QuestionStats(teacherdashboard, externalCourseExecution)
questionStatsRepository.save(questionStats)
}
def createQuiz () {
def quiz = new Quiz()
quiz.setKey(1)
quiz.setTitle("Quiz Title")
quiz.setType(Quiz.QuizType.PROPOSED.toString())
quiz.setCourseExecution(externalCourseExecution)
quiz.setAvailableDate(DateHandler.now())
quizRepository.save(quiz)
}
def createQuizQuestion(quiz, question, seq) {
def quizQuestion = new QuizQuestion(quiz, question, seq)
quizQuestionRepository.save(quizQuestion)
}
def createStudent(name, user, mail) {
def student = new Student(name, user, mail, false, AuthUser.Type.TECNICO)
student.addCourse(externalCourseExecution)
userRepository.save(student)
}
def createQuestion(key, available=true) {
def question = new Question()
question.setTitle("Question Title")
question.setCourse(externalCourse)
if(available == true){
question.setStatus(Question.Status.AVAILABLE)
}
else{
question.setStatus(Question.Status.SUBMITTED)
}
question.setKey(key)
def questionDetails = new MultipleChoiceQuestion()
question.setQuestionDetails(questionDetails)
questionRepository.save(question)
def option = new Option()
option.setContent("Option Content")
option.setCorrect(true)
option.setSequence(0)
option.setQuestionDetails(questionDetails)
optionRepository.save(option)
def optionKO = new Option()
optionKO.setContent("Option Content")
optionKO.setCorrect(false)
optionKO.setSequence(1)
optionKO.setQuestionDetails(questionDetails)
optionRepository.save(optionKO)
return question;
}
def createQuizAnswer (user, quiz, date = DateHandler.now()) {
def quizAnswer = new QuizAnswer()
quizAnswer.setCompleted(true)
quizAnswer.setCreationDate(date)
quizAnswer.setAnswerDate(date)
quizAnswer.setStudent(user)
quizAnswer.setQuiz(quiz)
quizAnswerRepository.save(quizAnswer)
}
def createQuestionAnswer (quizQuestion, quizAnswer, sequence, correct, answered = true) {
def questionAnswer = new QuestionAnswer()
questionAnswer.setTimeTaken(1)
questionAnswer.setQuizAnswer(quizAnswer)
questionAnswer.setQuizQuestion(quizQuestion)
questionAnswer.setSequence(sequence)
questionAnswerRepository.save(questionAnswer)
def answerDetails
def correctOption = quizQuestion.getQuestion().getQuestionDetails().getCorrectOption()
def incorrectOption = quizQuestion.getQuestion().getQuestionDetails().getOptions().stream().filter(option -> option != correctOption).findAny().orElse(null)
if (answered && correct) answerDetails = new MultipleChoiceAnswer(questionAnswer, correctOption)
else if (answered && !correct) answerDetails = new MultipleChoiceAnswer(questionAnswer, incorrectOption)
else {
questionAnswerRepository.save(questionAnswer)
return questionAnswer
}
questionAnswer.setAnswerDetails(answerDetails)
answerDetailsRepository.save(answerDetails)
return questionAnswer
}
/*def "test stats of an updated and empty dashboard"() {
given: "a dashboard"
when: "the user update the dashboard"
teacherDashboardService.updateTeacherDashboard(teacherdashboard.getId())
then: "the dashboard is updated"
questionStatsRepository.count() == 1L
teacherdashboard.getQuestionStats().size() == 1
}*/
def "update a dashboard"() {
given: "two students"
def s1 = createStudent(USER_1_NAME, USER_1_USERNAME, USER_1_EMAIL)
def s2 = createStudent(USER_2_NAME, USER_2_USERNAME, USER_2_EMAIL)
and: "three questions"
def q1 = createQuestion(1)
def q2 = createQuestion(2)
def q3 = createQuestion(3)
and: "a submitted question"
def q4 = createQuestion(4, false)
and: "a quiz"
def quiz = createQuiz()
def qq1 = createQuizQuestion(quiz, q1, 0)
def qq2 = createQuizQuestion(quiz, q2, 1)
def qq3 = createQuizQuestion(quiz, q3, 2)
and: "question stats"
and: "students answer questions"
def quizAs1 = createQuizAnswer(s1, quiz)
def quizAs2 = createQuizAnswer(s2, quiz)
createQuestionAnswer(qq1, quizAs1, 0, true)
createQuestionAnswer(qq2, quizAs1, 1, false)
createQuestionAnswer(qq2, quizAs2, 0, true)
when: "the stats are updates"
teacherDashboardService.updateTeacherDashboard(teacherdashboard.getId())
then: "the stats are correct"
questionStats.getAnsweredQuestionsUnique() == 2
questionStats.getAverageQuestionsAnswered() == (float) 3 / 2
questionStats.getNumAvailable() == 3
}
@Unroll
def "cannot update a dashboard that doesn't exist with the dashboardId=#dashboardId"() {
when: "an incorrect dashboard id is updated"
teacherDashboardService.updateTeacherDashboard(dashboardId)
then: "an exception is thrown"
def exception = thrown(TutorException)
exception.getErrorMessage() == ErrorMessage.DASHBOARD_NOT_FOUND
where:
dashboardId << [null, 10, -1]
}
@TestConfiguration
static class LocalBeanConfiguration extends BeanConfiguration {}
}