diff --git a/mod/quiz/tests/events_test.php b/mod/quiz/tests/events_test.php index ca6bfe70bde..1771846bb79 100644 --- a/mod/quiz/tests/events_test.php +++ b/mod/quiz/tests/events_test.php @@ -39,11 +39,11 @@ require_once($CFG->dirroot . '/mod/quiz/attemptlib.php'); class mod_quiz_events_testcase extends advanced_testcase { /** - * Setup some convenience test data with a single attempt. + * Setup a quiz. * - * @param bool $ispreview Make the attempt a preview attempt when true. + * @return quiz the generated quiz. */ - protected function prepare_quiz_data($ispreview = false) { + protected function prepare_quiz() { $this->resetAfterTest(true); @@ -53,8 +53,8 @@ class mod_quiz_events_testcase extends advanced_testcase { // Make a quiz. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); - $quiz = $quizgenerator->create_instance(array('course'=>$course->id, 'questionsperpage' => 0, - 'grade' => 100.0, 'sumgrades' => 2)); + $quiz = $quizgenerator->create_instance(array('course' => $course->id, 'questionsperpage' => 0, + 'grade' => 100.0, 'sumgrades' => 2)); $cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id); @@ -73,8 +73,17 @@ class mod_quiz_events_testcase extends advanced_testcase { $user1 = $this->getDataGenerator()->create_user(); $this->setUser($user1); - $quizobj = quiz::create($quiz->id, $user1->id); + return quiz::create($quiz->id, $user1->id); + } + /** + * Setup a quiz attempt at the quiz created by {@link prepare_quiz()}. + * + * @param quiz $quizobj the generated quiz. + * @param bool $ispreview Make the attempt a preview attempt when true. + * @return array with three elements, array($quizobj, $quba, $attempt) + */ + protected function prepare_quiz_attempt($quizobj, $ispreview = false) { // Start the attempt. $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); @@ -87,6 +96,17 @@ class mod_quiz_events_testcase extends advanced_testcase { return array($quizobj, $quba, $attempt); } + /** + * Setup some convenience test data with a single attempt. + * + * @param bool $ispreview Make the attempt a preview attempt when true. + * @return array with three elements, array($quizobj, $quba, $attempt) + */ + protected function prepare_quiz_data($ispreview = false) { + $quizobj = $this->prepare_quiz(); + return $this->prepare_quiz_attempt($quizobj, $ispreview); + } + public function test_attempt_submitted() { list($quizobj, $quba, $attempt) = $this->prepare_quiz_data(); @@ -194,10 +214,14 @@ class mod_quiz_events_testcase extends advanced_testcase { } public function test_attempt_started() { - list($quizobj, $quba, $attempt) = $this->prepare_quiz_data(); + $quizobj = $this->prepare_quiz(); - // Create another attempt. - $attempt = quiz_create_attempt($quizobj, 1, false, time(), false, 2); + $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); + $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); + + $timenow = time(); + $attempt = quiz_create_attempt($quizobj, 1, false, $timenow); + quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); // Trigger and capture the event. $sink = $this->redirectEvents(); @@ -666,11 +690,14 @@ class mod_quiz_events_testcase extends advanced_testcase { * Test the attempt previewed event. */ public function test_attempt_preview_started() { - list($quizobj, $quba, $attempt) = $this->prepare_quiz_data(); + $quizobj = $this->prepare_quiz(); - // We want to preview this attempt. - $attempt = quiz_create_attempt($quizobj, 1, false, time(), false, 2); - $attempt->preview = 1; + $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); + $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); + + $timenow = time(); + $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, true); + quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); // Trigger and capture the event. $sink = $this->redirectEvents(); diff --git a/question/engine/datalib.php b/question/engine/datalib.php index 0ef5816aba6..26af89ade9f 100644 --- a/question/engine/datalib.php +++ b/question/engine/datalib.php @@ -104,6 +104,8 @@ class question_engine_data_mapper { if ($stepdata) { $this->insert_all_step_data($stepdata); } + + $quba->set_observer(new question_engine_unit_of_work($quba)); } /** diff --git a/question/engine/tests/datalib_test.php b/question/engine/tests/datalib_test.php index af8b9d613a5..42b938e03d8 100644 --- a/question/engine/tests/datalib_test.php +++ b/question/engine/tests/datalib_test.php @@ -154,4 +154,80 @@ class question_engine_data_mapper_testcase extends qbehaviour_walkthrough_test_b array($questiondata1->id, $questiondata2->id, $questiondata3->id), new qubaid_list(array($quba->get_id())))); } + + public function test_repeated_usage_saving_new_usage() { + global $DB; + + $this->resetAfterTest(); + + $initialqurows = $DB->count_records('question_usages'); + $initialqarows = $DB->count_records('question_attempts'); + $initialqasrows = $DB->count_records('question_attempt_steps'); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(); + $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); + + $quba = question_engine::make_questions_usage_by_activity('test', context_system::instance()); + $quba->set_preferred_behaviour('deferredfeedback'); + $quba->add_question(question_bank::load_question($questiondata1->id)); + $quba->start_all_questions(); + question_engine::save_questions_usage_by_activity($quba); + + // Check one usage, question_attempts and step added. + $firstid = $quba->get_id(); + $this->assertEquals(1, $DB->count_records('question_usages') - $initialqurows); + $this->assertEquals(1, $DB->count_records('question_attempts') - $initialqarows); + $this->assertEquals(1, $DB->count_records('question_attempt_steps') - $initialqasrows); + + $quba->finish_all_questions(); + question_engine::save_questions_usage_by_activity($quba); + + // Check usage id not changed. + $this->assertEquals($firstid, $quba->get_id()); + + // Check still one usage, question_attempts, but now two steps. + $this->assertEquals(1, $DB->count_records('question_usages') - $initialqurows); + $this->assertEquals(1, $DB->count_records('question_attempts') - $initialqarows); + $this->assertEquals(2, $DB->count_records('question_attempt_steps') - $initialqasrows); + } + + public function test_repeated_usage_saving_existing_usage() { + global $DB; + + $this->resetAfterTest(); + + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(); + $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id)); + + $initquba = question_engine::make_questions_usage_by_activity('test', context_system::instance()); + $initquba->set_preferred_behaviour('deferredfeedback'); + $slot = $initquba->add_question(question_bank::load_question($questiondata1->id)); + $initquba->start_all_questions(); + question_engine::save_questions_usage_by_activity($initquba); + + $quba = question_engine::load_questions_usage_by_activity($initquba->get_id()); + + $initialqurows = $DB->count_records('question_usages'); + $initialqarows = $DB->count_records('question_attempts'); + $initialqasrows = $DB->count_records('question_attempt_steps'); + + $quba->process_all_actions(time(), $quba->prepare_simulated_post_data( + [$slot => ['answer' => 'Frog']])); + question_engine::save_questions_usage_by_activity($quba); + + // Check one usage, question_attempts and step added. + $this->assertEquals(0, $DB->count_records('question_usages') - $initialqurows); + $this->assertEquals(0, $DB->count_records('question_attempts') - $initialqarows); + $this->assertEquals(1, $DB->count_records('question_attempt_steps') - $initialqasrows); + + $quba->finish_all_questions(); + question_engine::save_questions_usage_by_activity($quba); + + // Check still one usage, question_attempts, but now two steps. + $this->assertEquals(0, $DB->count_records('question_usages') - $initialqurows); + $this->assertEquals(0, $DB->count_records('question_attempts') - $initialqarows); + $this->assertEquals(2, $DB->count_records('question_attempt_steps') - $initialqasrows); + } }