mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-77581 behat: Create generators for lesson pages and answers
This commit is contained in:
parent
1184d3c20f
commit
40b918348c
65
mod/lesson/tests/generator/behat_mod_lesson_generator.php
Normal file
65
mod/lesson/tests/generator/behat_mod_lesson_generator.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Behat data generator for mod_lesson.
|
||||
*
|
||||
* @package mod_lesson
|
||||
* @category test
|
||||
* @copyright 2023 Dani Palou <dani@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Behat data generator for mod_lesson.
|
||||
*
|
||||
* @copyright 2023 Dani Palou <dani@nmoodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_mod_lesson_generator extends behat_generator_base {
|
||||
|
||||
/**
|
||||
* Get a list of the entities that can be created.
|
||||
*
|
||||
* @return array entity name => information about how to generate.
|
||||
*/
|
||||
protected function get_creatable_entities(): array {
|
||||
return [
|
||||
'pages' => [
|
||||
'singular' => 'page',
|
||||
'datagenerator' => 'page',
|
||||
'required' => ['lesson', 'qtype'],
|
||||
'switchids' => ['lesson' => 'lessonid'],
|
||||
],
|
||||
'answers' => [
|
||||
'singular' => 'answer',
|
||||
'datagenerator' => 'answer',
|
||||
'required' => ['page'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the id of a lesson from its name.
|
||||
*
|
||||
* @param string $idnumberorname the lesson idnumber or name, for example 'Test lesson'.
|
||||
* @return int corresponding id.
|
||||
*/
|
||||
protected function get_lesson_id(string $idnumberorname): int {
|
||||
return $this->get_cm_by_activity_name('lesson', $idnumberorname)->instance;
|
||||
}
|
||||
|
||||
}
|
@ -25,6 +25,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
|
||||
/**
|
||||
* mod_lesson data generator class.
|
||||
*
|
||||
@ -40,6 +42,24 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
protected $pagecount = 0;
|
||||
|
||||
/**
|
||||
* @var array list of candidate pages to be created when all answers have been added.
|
||||
*/
|
||||
protected $candidatepages = [];
|
||||
|
||||
/**
|
||||
* @var array map of readable jumpto to integer value.
|
||||
*/
|
||||
protected $jumptomap = [
|
||||
'This page' => LESSON_THISPAGE,
|
||||
'Next page' => LESSON_NEXTPAGE,
|
||||
'Previous page' => LESSON_PREVIOUSPAGE,
|
||||
'End of lesson' => LESSON_EOL,
|
||||
'Unseen question within a content page' => LESSON_UNSEENBRANCHPAGE,
|
||||
'Random question within a content page' => LESSON_RANDOMPAGE,
|
||||
'Random content page' => LESSON_RANDOMBRANCH,
|
||||
];
|
||||
|
||||
/**
|
||||
* To be called from data reset code only,
|
||||
* do not use in tests.
|
||||
@ -47,9 +67,17 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function reset() {
|
||||
$this->pagecount = 0;
|
||||
$this->candidatepages = [];
|
||||
parent::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a lesson instance for testing purposes.
|
||||
*
|
||||
* @param null|array|stdClass $record data for module being generated.
|
||||
* @param null|array $options general options for course module.
|
||||
* @return stdClass record from module-defined table with additional field cmid (corresponding id in course_modules table)
|
||||
*/
|
||||
public function create_instance($record = null, array $options = null) {
|
||||
global $CFG;
|
||||
|
||||
@ -92,9 +120,84 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
return parent::create_instance($record, (array)$options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a page for testing purposes. The page will be created when answers are added.
|
||||
*
|
||||
* @param null|array|stdClass $record data for page being generated.
|
||||
* @param null|array $options general options.
|
||||
*/
|
||||
public function create_page($record = null, array $options = null) {
|
||||
$record = (array) $record;
|
||||
|
||||
// Pages require answers to work. Add it as a candidate page to be created once answers have been added.
|
||||
$record['answer_editor'] = [];
|
||||
$record['response_editor'] = [];
|
||||
$record['jumpto'] = [];
|
||||
$record['score'] = [];
|
||||
|
||||
if (!isset($record['previouspage']) || $record['previouspage'] === '') {
|
||||
// Previous page not set, set it to the last candidate page (if any).
|
||||
$record['previouspage'] = empty($this->candidatepages) ? '0' : end($this->candidatepages)['title'];
|
||||
}
|
||||
|
||||
$this->candidatepages[] = $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a page and its answers for testing purposes.
|
||||
*
|
||||
* @param array $record data for page being generated.
|
||||
* @return stdClass created page, null if couldn't be created because it has a jump to a page that doesn't exist.
|
||||
* @throws coding_exception
|
||||
*/
|
||||
private function perform_create_page(array $record): ?stdClass {
|
||||
global $DB;
|
||||
|
||||
$lesson = $DB->get_record('lesson', ['id' => $record['lessonid']], '*', MUST_EXIST);
|
||||
$cm = get_coursemodule_from_instance('lesson', $lesson->id);
|
||||
$lesson->cmid = $cm->id;
|
||||
$qtype = $record['qtype'];
|
||||
|
||||
unset($record['qtype']);
|
||||
unset($record['lessonid']);
|
||||
|
||||
if (isset($record['content'])) {
|
||||
$record['contents_editor'] = [
|
||||
'text' => $record['content'],
|
||||
'format' => FORMAT_MOODLE,
|
||||
'itemid' => 0,
|
||||
];
|
||||
unset($record['content']);
|
||||
}
|
||||
|
||||
$record['pageid'] = $this->get_previouspage_id($lesson->id, $record['previouspage']);
|
||||
unset($record['previouspage']);
|
||||
|
||||
try {
|
||||
$record['jumpto'] = $this->convert_page_jumpto($lesson->id, $record['jumpto']);
|
||||
} catch (coding_exception $e) {
|
||||
// This page has a jump to a page that hasn't been created yet.
|
||||
return null;
|
||||
}
|
||||
|
||||
$funcname = $qtype === 'content' ? 'create_content' : "create_question_{$qtype}";
|
||||
|
||||
if (!method_exists($this, $funcname)) {
|
||||
throw new coding_exception('The page '.$record['title']." has an invalid qtype: $qtype");
|
||||
}
|
||||
|
||||
return $this->{$funcname}($lesson, $record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a content page for testing purposes.
|
||||
*
|
||||
* @param stdClass $lesson instance where to create the page.
|
||||
* @param array|stdClass $record data for page being generated.
|
||||
* @return int Page ID.
|
||||
*/
|
||||
public function create_content($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -124,7 +227,6 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function create_question_truefalse($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -177,7 +279,6 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function create_question_multichoice($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -230,7 +331,6 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function create_question_essay($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -272,7 +372,6 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function create_question_matching($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -351,7 +450,6 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function create_question_shortanswer($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -393,7 +491,6 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
*/
|
||||
public function create_question_numeric($lesson, $record = array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot.'/mod/lesson/locallib.php');
|
||||
$now = time();
|
||||
$this->pagecount++;
|
||||
$record = (array)$record + array(
|
||||
@ -431,6 +528,7 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
* Create a lesson override (either user or group).
|
||||
*
|
||||
* @param array $data must specify lessonid, and one of userid or groupid.
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function create_override(array $data): void {
|
||||
global $DB;
|
||||
@ -449,4 +547,159 @@ class mod_lesson_generator extends testing_module_generator {
|
||||
|
||||
$DB->insert_record('lesson_overrides', (object) $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an answer in a page for testing purposes.
|
||||
*
|
||||
* @param null|array|stdClass $record data for module being generated.
|
||||
* @param null|array $options general options.
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function create_answer($record = null, array $options = null) {
|
||||
$record = (array) $record;
|
||||
|
||||
$candidatepage = null;
|
||||
$pagetitle = $record['page'];
|
||||
$found = false;
|
||||
foreach ($this->candidatepages as &$candidatepage) {
|
||||
if ($candidatepage['title'] === $pagetitle) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
throw new coding_exception("Page '$pagetitle' not found in candidate pages. Please make sure the page exists "
|
||||
. 'and all answers are in the same table.');
|
||||
}
|
||||
|
||||
if (isset($record['answer'])) {
|
||||
$candidatepage['answer_editor'][] = [
|
||||
'text' => $record['answer'],
|
||||
'format' => FORMAT_HTML,
|
||||
];
|
||||
} else {
|
||||
$candidatepage['answer_editor'][] = null;
|
||||
}
|
||||
|
||||
if (isset($record['response'])) {
|
||||
$candidatepage['response_editor'][] = [
|
||||
'text' => $record['response'],
|
||||
'format' => FORMAT_HTML,
|
||||
];
|
||||
} else {
|
||||
$candidatepage['response_editor'][] = null;
|
||||
}
|
||||
|
||||
$candidatepage['jumpto'][] = $record['jumpto'] ?? LESSON_THISPAGE;
|
||||
$candidatepage['score'][] = $record['score'] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* All answers in a table have been generated, create the pages.
|
||||
*/
|
||||
public function finish_generate_answer() {
|
||||
$this->create_candidate_pages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create candidate pages.
|
||||
*
|
||||
* @throws coding_exception
|
||||
*/
|
||||
protected function create_candidate_pages(): void {
|
||||
// For performance reasons it would be better to use a topological sort algorithm. But since test cases shouldn't have
|
||||
// a lot of paged and complex jumps it was implemented using a simpler approach.
|
||||
$consecutiveblocked = 0;
|
||||
|
||||
while (count($this->candidatepages) > 0) {
|
||||
$page = array_shift($this->candidatepages);
|
||||
$id = $this->perform_create_page($page);
|
||||
|
||||
if ($id === null) {
|
||||
// Page cannot be created yet because of jumpto. Move it to the end of list.
|
||||
$consecutiveblocked++;
|
||||
$this->candidatepages[] = $page;
|
||||
|
||||
if ($consecutiveblocked === count($this->candidatepages)) {
|
||||
throw new coding_exception('There is a circular dependency in pages jumps.');
|
||||
}
|
||||
} else {
|
||||
$consecutiveblocked = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the previous page id.
|
||||
* If no page title is supplied, use the last page created in the lesson (0 if no pages).
|
||||
* If page title is supplied, search it in DB and the list of candidate pages.
|
||||
*
|
||||
* @param int $lessonid the lesson id.
|
||||
* @param string $pagetitle the page title, for example 'Test page'. '0' if no previous page.
|
||||
* @return int corresponding id. 0 if no previous page.
|
||||
* @throws coding_exception
|
||||
*/
|
||||
protected function get_previouspage_id(int $lessonid, string $pagetitle): int {
|
||||
global $DB;
|
||||
|
||||
if (is_numeric($pagetitle) && intval($pagetitle) === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$pages = $DB->get_records('lesson_pages', ['lessonid' => $lessonid, 'title' => $pagetitle], 'id ASC', 'id, title');
|
||||
|
||||
if (count($pages) > 1) {
|
||||
throw new coding_exception("More than one page with '$pagetitle' found");
|
||||
} else if (!empty($pages)) {
|
||||
return current($pages)->id;
|
||||
}
|
||||
|
||||
// Page doesn't exist, search if it's a candidate page. If it is, use its previous page instead.
|
||||
foreach ($this->candidatepages as $candidatepage) {
|
||||
if ($candidatepage['title'] === $pagetitle) {
|
||||
return $this->get_previouspage_id($lessonid, $candidatepage['previouspage']);
|
||||
}
|
||||
}
|
||||
|
||||
throw new coding_exception("Page '$pagetitle' not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the jumpto using a string to an integer value.
|
||||
* The jumpto can contain a page name or one of our predefined values.
|
||||
*
|
||||
* @param int $lessonid the lesson id.
|
||||
* @param array|null $jumptolist list of jumpto to treat.
|
||||
* @return array|null list of jumpto already treated.
|
||||
* @throws coding_exception
|
||||
*/
|
||||
protected function convert_page_jumpto(int $lessonid, ?array $jumptolist): ?array {
|
||||
global $DB;
|
||||
|
||||
if (empty($jumptolist)) {
|
||||
return $jumptolist;
|
||||
}
|
||||
|
||||
foreach ($jumptolist as $i => $jumpto) {
|
||||
if (empty($jumpto) || is_numeric($jumpto)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($this->jumptomap[$jumpto])) {
|
||||
$jumptolist[$i] = $this->jumptomap[$jumpto];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$page = $DB->get_record('lesson_pages', ['lessonid' => $lessonid, 'title' => $jumpto], 'id');
|
||||
if ($page === false) {
|
||||
throw new coding_exception("Jump '$jumpto' not found in pages.");
|
||||
}
|
||||
|
||||
$jumptolist[$i] = $page->id;
|
||||
}
|
||||
|
||||
return $jumptolist;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ namespace mod_lesson;
|
||||
* @category test
|
||||
* @copyright 2013 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \mod_lesson_generator
|
||||
*/
|
||||
class generator_test extends \advanced_testcase {
|
||||
|
||||
@ -213,4 +214,454 @@ class generator_test extends \advanced_testcase {
|
||||
$this->assertEquals($page2->id, $records[$page2->id]->id);
|
||||
$this->assertEquals($page2->title, $records[$page2->id]->title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test create some pages and their answers.
|
||||
*
|
||||
* @covers ::create_page
|
||||
* @covers ::create_answer
|
||||
* @covers ::finish_generate_answer
|
||||
*/
|
||||
public function test_create_page_and_answers(): void {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
// Define the pages. Only a couple pages will be created since each page type has their own unit tests.
|
||||
$contentpage = [
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$multichoicepage = [
|
||||
'title' => 'Multichoice question',
|
||||
'content' => 'What animal is an amphibian?',
|
||||
'qtype' => 'multichoice',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
|
||||
$lessongenerator->create_page($contentpage);
|
||||
$lessongenerator->create_page($multichoicepage);
|
||||
|
||||
// Check that pages haven't been generated yet because no answers were added.
|
||||
$pages = $DB->get_records('lesson_pages', ['lessonid' => $lesson->id], 'id');
|
||||
$this->assertEquals(0, count($pages));
|
||||
|
||||
// Now add answers to the pages.
|
||||
$contentpagecontinueanswer = [
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'Continue',
|
||||
'jumpto' => 'Next page',
|
||||
'score' => 1,
|
||||
];
|
||||
$contentpagestayanswer = [
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'Stay',
|
||||
'jumpto' => 'This page',
|
||||
'score' => 0,
|
||||
];
|
||||
$multichoicepagefroganswer = [
|
||||
'page' => $multichoicepage['title'],
|
||||
'answer' => 'Frog',
|
||||
'response' => 'Correct answer',
|
||||
'jumpto' => 'Next page',
|
||||
'score' => 1,
|
||||
];
|
||||
$multichoicepagecatanswer = [
|
||||
'page' => $multichoicepage['title'],
|
||||
'answer' => 'Cat',
|
||||
'response' => 'Incorrect answer',
|
||||
'jumpto' => 'This page',
|
||||
'score' => 0,
|
||||
];
|
||||
$multichoicepagedoganswer = [
|
||||
'page' => $multichoicepage['title'],
|
||||
'answer' => 'Dog',
|
||||
'response' => 'Incorrect answer',
|
||||
'jumpto' => 'This page',
|
||||
'score' => 0,
|
||||
];
|
||||
|
||||
$lessongenerator->create_answer($contentpagecontinueanswer);
|
||||
$lessongenerator->create_answer($contentpagestayanswer);
|
||||
$lessongenerator->create_answer($multichoicepagefroganswer);
|
||||
$lessongenerator->create_answer($multichoicepagecatanswer);
|
||||
$lessongenerator->create_answer($multichoicepagedoganswer);
|
||||
|
||||
// Check that pages and answers haven't been generated yet because maybe not all answers have been added yet.
|
||||
$pages = $DB->get_records('lesson_pages', ['lessonid' => $lesson->id], 'id');
|
||||
$answers = $DB->get_records('lesson_answers', ['lessonid' => $lesson->id], 'id');
|
||||
$this->assertEquals(0, count($pages));
|
||||
$this->assertEquals(0, count($answers));
|
||||
|
||||
// Notify that all answers have been added, so pages can be created.
|
||||
$lessongenerator->finish_generate_answer();
|
||||
|
||||
// Check that pages and answers have been created.
|
||||
$pages = $DB->get_records('lesson_pages', ['lessonid' => $lesson->id], 'title DESC');
|
||||
$this->assertEquals(2, count($pages));
|
||||
|
||||
$contentpagedb = array_pop($pages);
|
||||
$multichoicepagedb = array_pop($pages);
|
||||
$this->assertEquals($contentpage['title'], $contentpagedb->title);
|
||||
$this->assertEquals($contentpage['content'], $contentpagedb->contents);
|
||||
$this->assertEquals(LESSON_PAGE_BRANCHTABLE, $contentpagedb->qtype);
|
||||
$this->assertEquals($multichoicepage['title'], $multichoicepagedb->title);
|
||||
$this->assertEquals($multichoicepage['content'], $multichoicepagedb->contents);
|
||||
$this->assertEquals(LESSON_PAGE_MULTICHOICE, $multichoicepagedb->qtype);
|
||||
|
||||
$answers = $DB->get_records('lesson_answers', ['lessonid' => $lesson->id], 'answer DESC');
|
||||
$this->assertEquals(5, count($answers));
|
||||
|
||||
$multichoicepagecatanswerdb = array_pop($answers);
|
||||
$contentpagecontinueanswerdb = array_pop($answers);
|
||||
$multichoicepagedoganswerdb = array_pop($answers);
|
||||
$multichoicepagefroganswerdb = array_pop($answers);
|
||||
$contentpagestayanswerdb = array_pop($answers);
|
||||
$this->assertEquals($contentpagedb->id, $contentpagecontinueanswerdb->pageid);
|
||||
$this->assertEquals($contentpagecontinueanswer['answer'], $contentpagecontinueanswerdb->answer);
|
||||
$this->assertEquals(LESSON_NEXTPAGE, $contentpagecontinueanswerdb->jumpto);
|
||||
$this->assertEquals($contentpagecontinueanswer['score'], $contentpagecontinueanswerdb->score);
|
||||
$this->assertEquals($contentpagedb->id, $contentpagestayanswerdb->pageid);
|
||||
$this->assertEquals($contentpagestayanswer['answer'], $contentpagestayanswerdb->answer);
|
||||
$this->assertEquals(LESSON_THISPAGE, $contentpagestayanswerdb->jumpto);
|
||||
$this->assertEquals($contentpagestayanswer['score'], $contentpagestayanswerdb->score);
|
||||
$this->assertEquals($multichoicepagedb->id, $multichoicepagefroganswerdb->pageid);
|
||||
$this->assertEquals($multichoicepagefroganswer['answer'], $multichoicepagefroganswerdb->answer);
|
||||
$this->assertEquals($multichoicepagefroganswer['response'], $multichoicepagefroganswerdb->response);
|
||||
$this->assertEquals(LESSON_NEXTPAGE, $multichoicepagefroganswerdb->jumpto);
|
||||
$this->assertEquals($multichoicepagefroganswer['score'], $multichoicepagefroganswerdb->score);
|
||||
$this->assertEquals($multichoicepagedb->id, $multichoicepagedoganswerdb->pageid);
|
||||
$this->assertEquals($multichoicepagedoganswer['answer'], $multichoicepagedoganswerdb->answer);
|
||||
$this->assertEquals($multichoicepagedoganswer['response'], $multichoicepagedoganswerdb->response);
|
||||
$this->assertEquals(LESSON_THISPAGE, $multichoicepagedoganswerdb->jumpto);
|
||||
$this->assertEquals($multichoicepagedoganswer['score'], $multichoicepagedoganswerdb->score);
|
||||
$this->assertEquals($multichoicepagedb->id, $multichoicepagecatanswerdb->pageid);
|
||||
$this->assertEquals($multichoicepagecatanswer['answer'], $multichoicepagecatanswerdb->answer);
|
||||
$this->assertEquals($multichoicepagecatanswer['response'], $multichoicepagecatanswerdb->response);
|
||||
$this->assertEquals(LESSON_THISPAGE, $multichoicepagecatanswerdb->jumpto);
|
||||
$this->assertEquals($multichoicepagecatanswer['score'], $multichoicepagecatanswerdb->score);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating pages defining the previous pages.
|
||||
*
|
||||
* @covers ::create_page
|
||||
*/
|
||||
public function test_create_page_with_previouspage(): void {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$firstpage = [
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
'previouspage' => 0, // No previous page, this will be the first page.
|
||||
];
|
||||
$secondpage = [
|
||||
'title' => 'Second page name',
|
||||
'content' => 'Second page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
'previouspage' => 'First page name',
|
||||
];
|
||||
$thirdpage = [
|
||||
'title' => 'Third page name',
|
||||
'content' => 'Third page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
'previouspage' => 'Second page name',
|
||||
];
|
||||
|
||||
// Create the third page first to check that the added order is not important, the order will still be calculated right.
|
||||
$lessongenerator->create_page($thirdpage);
|
||||
$lessongenerator->create_page($firstpage);
|
||||
$lessongenerator->create_page($secondpage);
|
||||
|
||||
// Don't define any answers, the default answers will be added.
|
||||
$lessongenerator->finish_generate_answer();
|
||||
|
||||
$pages = $DB->get_records('lesson_pages', ['lessonid' => $lesson->id], 'title DESC');
|
||||
$this->assertEquals(3, count($pages));
|
||||
|
||||
$firstpagedb = array_pop($pages);
|
||||
$secondpagedb = array_pop($pages);
|
||||
$thirdpagedb = array_pop($pages);
|
||||
$this->assertEquals($firstpage['title'], $firstpagedb->title);
|
||||
$this->assertEquals(0, $firstpagedb->prevpageid);
|
||||
$this->assertEquals($secondpagedb->id, $firstpagedb->nextpageid);
|
||||
$this->assertEquals($secondpage['title'], $secondpagedb->title);
|
||||
$this->assertEquals($firstpagedb->id, $secondpagedb->prevpageid);
|
||||
$this->assertEquals($thirdpagedb->id, $secondpagedb->nextpageid);
|
||||
$this->assertEquals($thirdpage['title'], $thirdpagedb->title);
|
||||
$this->assertEquals($secondpagedb->id, $thirdpagedb->prevpageid);
|
||||
$this->assertEquals(0, $thirdpagedb->nextpageid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a page with a previous page that doesn't exist.
|
||||
*
|
||||
* @covers ::create_page
|
||||
*/
|
||||
public function test_create_page_invalid_previouspage(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$lessongenerator->create_page([
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
'previouspage' => 'Invalid page',
|
||||
]);
|
||||
$lessongenerator->finish_generate_answer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that circular dependencies are not allowed in previous pages.
|
||||
*
|
||||
* @covers ::create_page
|
||||
*/
|
||||
public function test_create_page_previouspage_circular_dependency(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$lessongenerator->create_page([
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
'previouspage' => 'Second page name',
|
||||
]);
|
||||
$lessongenerator->create_page([
|
||||
'title' => 'Second page name',
|
||||
'content' => 'Second page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
'previouspage' => 'First page name',
|
||||
]);
|
||||
$lessongenerator->finish_generate_answer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating an answer in a page that doesn't exist.
|
||||
*
|
||||
* @covers ::create_answer
|
||||
*/
|
||||
public function test_create_answer_invalid_page(): void {
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$lessongenerator->create_answer([
|
||||
'page' => 'Invalid page',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that all the possible values of jumpto work as expected when creating an answer.
|
||||
*
|
||||
* @covers ::create_answer
|
||||
*/
|
||||
public function test_create_answer_jumpto(): void {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$contentpage = [
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$secondcontentpage = [
|
||||
'title' => 'Second page name',
|
||||
'content' => 'Second page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$thirdcontentpage = [
|
||||
'title' => 'Third page name',
|
||||
'content' => 'Third page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$lessongenerator->create_page($contentpage);
|
||||
$lessongenerator->create_page($secondcontentpage);
|
||||
$lessongenerator->create_page($thirdcontentpage);
|
||||
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'A',
|
||||
'jumpto' => 'This page',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'B',
|
||||
'jumpto' => 'Next page',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'C',
|
||||
'jumpto' => 'Previous page',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $secondcontentpage['title'],
|
||||
'answer' => 'D',
|
||||
'jumpto' => 'End of lesson',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $secondcontentpage['title'],
|
||||
'answer' => 'E',
|
||||
'jumpto' => 'Unseen question within a content page',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $secondcontentpage['title'],
|
||||
'answer' => 'F',
|
||||
'jumpto' => 'Random question within a content page',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $thirdcontentpage['title'],
|
||||
'answer' => 'G',
|
||||
'jumpto' => 'Random content page',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $thirdcontentpage['title'],
|
||||
'answer' => 'H',
|
||||
'jumpto' => 'Unseen question within a cluster',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $thirdcontentpage['title'],
|
||||
'answer' => 'I',
|
||||
'jumpto' => 1234, // A page ID, it doesn't matter that it doesn't exist.
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'J',
|
||||
'jumpto' => 'Third page name',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $thirdcontentpage['title'],
|
||||
'answer' => 'K',
|
||||
'jumpto' => 'Second page name',
|
||||
]);
|
||||
|
||||
$lessongenerator->finish_generate_answer();
|
||||
|
||||
$secondcontentpagedb = $DB->get_record('lesson_pages', ['lessonid' => $lesson->id, 'title' => $secondcontentpage['title']]);
|
||||
$thirdcontentpagedb = $DB->get_record('lesson_pages', ['lessonid' => $lesson->id, 'title' => $thirdcontentpage['title']]);
|
||||
$answers = $DB->get_records('lesson_answers', ['lessonid' => $lesson->id], 'answer DESC');
|
||||
$this->assertEquals(11, count($answers));
|
||||
|
||||
$this->assertEquals(LESSON_THISPAGE, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_NEXTPAGE, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_PREVIOUSPAGE, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_EOL, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_UNSEENBRANCHPAGE, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_RANDOMPAGE, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_RANDOMBRANCH, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(LESSON_CLUSTERJUMP, array_pop($answers)->jumpto);
|
||||
$this->assertEquals(1234, array_pop($answers)->jumpto);
|
||||
$this->assertEquals($thirdcontentpagedb->id, array_pop($answers)->jumpto);
|
||||
$this->assertEquals($secondcontentpagedb->id, array_pop($answers)->jumpto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid jumpto when creating answers.
|
||||
*
|
||||
* @covers ::create_answer
|
||||
*/
|
||||
public function test_create_answer_invalid_jumpto(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$contentpage = [
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$lessongenerator->create_page($contentpage);
|
||||
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'Next',
|
||||
'jumpto' => 'Invalid page',
|
||||
]);
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$lessongenerator->finish_generate_answer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that circular dependencies are not allowed when creating answers.
|
||||
*
|
||||
* @covers ::create_answer
|
||||
*/
|
||||
public function test_create_answer_jumpto_circular_dependency(): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$lesson = $this->getDataGenerator()->create_module('lesson', ['course' => $course]);
|
||||
$lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
|
||||
|
||||
$contentpage = [
|
||||
'title' => 'First page name',
|
||||
'content' => 'First page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$secondcontentpage = [
|
||||
'title' => 'Second page name',
|
||||
'content' => 'Second page contents',
|
||||
'qtype' => 'content',
|
||||
'lessonid' => $lesson->id,
|
||||
];
|
||||
$lessongenerator->create_page($contentpage);
|
||||
$lessongenerator->create_page($secondcontentpage);
|
||||
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'Next',
|
||||
'jumpto' => 'Second page name',
|
||||
]);
|
||||
$lessongenerator->create_answer([
|
||||
'page' => $contentpage['title'],
|
||||
'answer' => 'Back',
|
||||
'jumpto' => 'First page name',
|
||||
]);
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$lessongenerator->finish_generate_answer();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user