Rev 1 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?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/>./*** Unit tests for the Moodle XML format.** @package qformat_xml* @copyright 2010 The Open University* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/namespace qformat_xml;use qformat_xml;use qtype_numerical_answer;use question_answer;use question_bank;use question_check_specified_fields_expectation;use question_hint;use question_hint_with_parts;defined('MOODLE_INTERNAL') || die();global $CFG;require_once($CFG->libdir . '/questionlib.php');require_once($CFG->dirroot . '/question/format/xml/format.php');require_once($CFG->dirroot . '/question/engine/tests/helpers.php');/*** Unit tests for the matching question definition class.** @package qformat_xml* @copyright 2009 The Open University* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class xmlformat_test extends \question_testcase {public function make_test_question() {global $USER;$q = new \stdClass();$q->id = 0;$q->contextid = 0;$q->idnumber = null;$q->category = 0;$q->parent = 0;$q->questiontextformat = FORMAT_HTML;$q->generalfeedbackformat = FORMAT_HTML;$q->defaultmark = 1;$q->penalty = 0.3333333;$q->length = 1;$q->stamp = make_unique_id_code();$q->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$q->timecreated = time();$q->timemodified = time();$q->createdby = $USER->id;$q->modifiedby = $USER->id;return $q;}/*** The data the XML import format sends to save_question is not exactly* the same as the data returned from the editing form, so this method* makes necessary changes to the return value of* \test_question_maker::get_question_form_data so that the tests can work.* @param object $expectedq as returned by get_question_form_data.* @return object one more likely to match the return value of import_...().*/public function remove_irrelevant_form_data_fields($expectedq) {return $this->itemid_to_files($expectedq);}/*** Becuase XML import uses a files array instead of an itemid integer to* handle saving files with a question, we need to covert the output of* \test_question_maker::get_question_form_data to match. This method recursively* replaces all array elements with key itemid with an array entry with* key files and value an empty array.** @param mixed $var any data structure.* @return mixed an equivalent structure with the relacements made.*/protected function itemid_to_files($var) {if (is_object($var)) {$newvar = new \stdClass();foreach (get_object_vars($var) as $field => $value) {$newvar->$field = $this->itemid_to_files($value);}} else if (is_array($var)) {$newvar = array();foreach ($var as $index => $value) {if ($index === 'itemid') {$newvar['files'] = array();} else {$newvar[$index] = $this->itemid_to_files($value);}}} else {$newvar = $var;}return $newvar;}public function test_xml_escape_simple_input_not_escaped(): void {$exporter = new qformat_xml();$string = 'Nothing funny here. Even if we go to a café or to 日本.';$this->assertEquals($string, $exporter->xml_escape($string));}public function test_xml_escape_html_wrapped_in_cdata(): void {$exporter = new qformat_xml();$string = '<p>Nothing <b>funny<b> here. Even if we go to a café or to 日本.</p>';$this->assertEquals('<![CDATA[' . $string . ']]>', $exporter->xml_escape($string));}public function test_xml_escape_script_tag_handled_ok(): void {$exporter = new qformat_xml();$input = '<script><![CDATA[alert(1<2);]]></script>';$expected = '<![CDATA[<script><![CDATA[alert(1<2);]]]]><![CDATA[></script>]]>';$this->assertEquals($expected, $exporter->xml_escape($input));// Check that parsing the expected result does give the input again.$parsed = simplexml_load_string('<div>' . $expected . '</div>');$this->assertEquals($input, $parsed->xpath('//div')[0]);}public function test_xml_escape_code_that_looks_like_cdata_end_ok(): void {$exporter = new qformat_xml();$input = "if (x[[0]]>a) print('hah');";$expected = "<![CDATA[if (x[[0]]]]><![CDATA[>a) print('hah');]]>";$this->assertEquals($expected, $exporter->xml_escape($input));// Check that parsing the expected result does give the input again.$parsed = simplexml_load_string('<div>' . $expected . '</div>');$this->assertEquals($input, $parsed->xpath('//div')[0]);}public function test_write_hint_basic(): void {$q = $this->make_test_question();$q->contextid = \context_system::instance()->id;$q->name = 'Short answer question';$q->questiontext = 'Name an amphibian: __________';$q->generalfeedback = 'Generalfeedback: frog or toad would have been OK.';if (!isset($q->options)) {$q->options = new \stdClass();}$q->options->usecase = false;$q->options->answers = array(13 => new question_answer(13, 'frog', 1.0, 'Frog is a very good answer.', FORMAT_HTML),14 => new question_answer(14, 'toad', 0.8, 'Toad is an OK good answer.', FORMAT_HTML),15 => new question_answer(15, '*', 0.0, 'That is a bad answer.', FORMAT_HTML),);$q->qtype = 'shortanswer';$q->hints = array(new question_hint(0, 'This is the first hint.', FORMAT_MOODLE),);$exporter = new qformat_xml();$xml = $exporter->writequestion($q);$this->assertMatchesRegularExpression('|<hint format=\"moodle_auto_format\">\s*<text>\s*' .'This is the first hint\.\s*</text>\s*</hint>|', $xml);$this->assertDoesNotMatchRegularExpression('|<shownumcorrect/>|', $xml);$this->assertDoesNotMatchRegularExpression('|<clearwrong/>|', $xml);$this->assertDoesNotMatchRegularExpression('|<options>|', $xml);}public function test_write_hint_with_parts(): void {$q = $this->make_test_question();$q->contextid = \context_system::instance()->id;$q->name = 'Matching question';$q->questiontext = 'Classify the animals.';$q->generalfeedback = 'Frogs and toads are amphibians, the others are mammals.';$q->qtype = 'match';if (!isset($q->options)) {$q->options = new \stdClass();}$q->options->shuffleanswers = 1;$q->options->correctfeedback = '';$q->options->correctfeedbackformat = FORMAT_HTML;$q->options->partiallycorrectfeedback = '';$q->options->partiallycorrectfeedbackformat = FORMAT_HTML;$q->options->incorrectfeedback = '';$q->options->incorrectfeedbackformat = FORMAT_HTML;$q->options->subquestions = array();$q->hints = array(new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, true),new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, false),);$exporter = new qformat_xml();$xml = $exporter->writequestion($q);$this->assertMatchesRegularExpression('|<hint format=\"html\">\s*<text>\s*This is the first hint\.\s*</text>|', $xml);$this->assertMatchesRegularExpression('|<hint format=\"html\">\s*<text>\s*This is the second hint\.\s*</text>|', $xml);list($ignored, $hint1, $hint2) = explode('<hint', $xml);$this->assertDoesNotMatchRegularExpression('|<shownumcorrect/>|', $hint1);$this->assertMatchesRegularExpression('|<clearwrong/>|', $hint1);$this->assertMatchesRegularExpression('|<shownumcorrect/>|', $hint2);$this->assertDoesNotMatchRegularExpression('|<clearwrong/>|', $hint2);$this->assertDoesNotMatchRegularExpression('|<options>|', $xml);}public function test_import_hints_no_parts(): void {$xml = <<<END<question><hint><text>This is the first hint</text><clearwrong/></hint><hint><text>This is the second hint</text><shownumcorrect/></hint></question>END;$questionxml = xmlize($xml);$qo = new \stdClass();$importer = new qformat_xml();$importer->import_hints($qo, $questionxml['question'], false, false, 'html');$this->assertEquals(array(array('text' => 'This is the first hint','format' => FORMAT_HTML),array('text' => 'This is the second hint','format' => FORMAT_HTML),), $qo->hint);$this->assertFalse(isset($qo->hintclearwrong));$this->assertFalse(isset($qo->hintshownumcorrect));}public function test_import_hints_with_parts(): void {$xml = <<<END<question><hint><text>This is the first hint</text><clearwrong/></hint><hint><text>This is the second hint</text><shownumcorrect/></hint></question>END;$questionxml = xmlize($xml);$qo = new \stdClass();$importer = new qformat_xml();$importer->import_hints($qo, $questionxml['question'], true, true, 'html');$this->assertEquals(array(array('text' => 'This is the first hint','format' => FORMAT_HTML),array('text' => 'This is the second hint','format' => FORMAT_HTML),), $qo->hint);$this->assertEquals(array(1, 0), $qo->hintclearwrong);$this->assertEquals(array(0, 1), $qo->hintshownumcorrect);}public function test_import_no_hints_no_error(): void {$xml = <<<END<question></question>END;$questionxml = xmlize($xml);$qo = new \stdClass();$importer = new qformat_xml();$importer->import_hints($qo, $questionxml['question'], 'html');$this->assertFalse(isset($qo->hint));}public function test_import_description(): void {$xml = ' <question type="description"><name><text>A description</text></name><questiontext format="html"><text>The question text.</text></questiontext><generalfeedback><text>Here is some general feedback.</text></generalfeedback><defaultgrade>0</defaultgrade><penalty>0</penalty><hidden>0</hidden><tags><tag><text>tagDescription</text></tag><tag><text>tagTest</text></tag></tags></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_description($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'description';$expectedq->name = 'A description';$expectedq->questiontext = 'The question text.';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->generalfeedback = 'Here is some general feedback.';$expectedq->defaultmark = 0;$expectedq->length = 0;$expectedq->penalty = 0;$expectedq->tags = array('tagDescription', 'tagTest');$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_description(): void {$qdata = new \stdClass();$qdata->id = 123;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'description';$qdata->name = 'A description';$qdata->questiontext = 'The question text.';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'Here is some general feedback.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 0;$qdata->length = 0;$qdata->penalty = 0;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 123 --><question type="description"><name><text>A description</text></name><questiontext format="html"><text>The question text.</text></questiontext><generalfeedback format="html"><text>Here is some general feedback.</text></generalfeedback><defaultgrade>0</defaultgrade><penalty>0</penalty><hidden>0</hidden><idnumber></idnumber></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_essay_20(): void {$xml = ' <question type="essay"><name><text>An essay</text></name><questiontext format="moodle_auto_format"><text>Write something.</text></questiontext><generalfeedback><text>I hope you wrote something interesting.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0</penalty><hidden>0</hidden><tags><tag><text>tagEssay</text></tag><tag><text>tagEssay20</text></tag><tag><text>tagTest</text></tag></tags></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_essay($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'essay';$expectedq->name = 'An essay';$expectedq->questiontext = 'Write something.';$expectedq->questiontextformat = FORMAT_MOODLE;$expectedq->generalfeedback = 'I hope you wrote something interesting.';$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 0;$expectedq->responseformat = 'editor';$expectedq->responserequired = 1;$expectedq->responsefieldlines = 15;$expectedq->minwordlimit = null;$expectedq->minwordenabled = false;$expectedq->maxwordlimit = null;$expectedq->maxwordenabled = false;$expectedq->attachments = 0;$expectedq->attachmentsrequired = 0;$expectedq->maxbytes = 0;$expectedq->filetypeslist = null;$expectedq->graderinfo['text'] = '';$expectedq->graderinfo['format'] = FORMAT_MOODLE;$expectedq->responsetemplate['text'] = '';$expectedq->responsetemplate['format'] = FORMAT_MOODLE;$expectedq->tags = array('tagEssay', 'tagEssay20', 'tagTest');$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_import_essay_21(): void {$xml = ' <question type="essay"><name><text>An essay</text></name><questiontext format="moodle_auto_format"><text>Write something.</text></questiontext><generalfeedback><text>I hope you wrote something interesting.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0</penalty><hidden>0</hidden><responseformat>monospaced</responseformat><responserequired>0</responserequired><responsefieldlines>42</responsefieldlines><attachments>-1</attachments><attachmentsrequired>1</attachmentsrequired><graderinfo format="html"><text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text></graderinfo><responsetemplate format="html"><text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text></responsetemplate><tags><tag><text>tagEssay</text></tag><tag><text>tagEssay21</text></tag><tag><text>tagTest</text></tag></tags></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_essay($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'essay';$expectedq->name = 'An essay';$expectedq->questiontext = 'Write something.';$expectedq->questiontextformat = FORMAT_MOODLE;$expectedq->generalfeedback = 'I hope you wrote something interesting.';$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 0;$expectedq->responseformat = 'monospaced';$expectedq->responserequired = 0;$expectedq->responsefieldlines = 42;$expectedq->minwordlimit = null;$expectedq->minwordenabled = false;$expectedq->maxwordlimit = null;$expectedq->maxwordenabled = false;$expectedq->attachments = -1;$expectedq->attachmentsrequired = 1;$expectedq->maxbytes = 0;$expectedq->filetypeslist = null;$expectedq->graderinfo['text'] = '<p>Grade <b>generously</b>!</p>';$expectedq->graderinfo['format'] = FORMAT_HTML;$expectedq->responsetemplate['text'] = '<p>Here is something <b>really</b> interesting.</p>';$expectedq->responsetemplate['format'] = FORMAT_HTML;$expectedq->tags = array('tagEssay', 'tagEssay21', 'tagTest');$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_import_essay_311(): void {$xml = ' <question type="essay"><name><text>An essay</text></name><questiontext format="moodle_auto_format"><text>Write something.</text></questiontext><generalfeedback><text>I hope you wrote something interesting.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0</penalty><hidden>0</hidden><responseformat>monospaced</responseformat><responserequired>0</responserequired><responsefieldlines>42</responsefieldlines><minwordlimit>10</minwordlimit><maxwordlimit>20</maxwordlimit><attachments>-1</attachments><attachmentsrequired>1</attachmentsrequired><maxbytes>52428800</maxbytes><filetypeslist>.pdf,.zip.,.docx</filetypeslist><graderinfo format="html"><text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text></graderinfo><responsetemplate format="html"><text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text></responsetemplate><tags><tag><text>tagEssay</text></tag><tag><text>tagEssay21</text></tag><tag><text>tagTest</text></tag></tags></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_essay($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'essay';$expectedq->name = 'An essay';$expectedq->questiontext = 'Write something.';$expectedq->questiontextformat = FORMAT_MOODLE;$expectedq->generalfeedback = 'I hope you wrote something interesting.';$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 0;$expectedq->responseformat = 'monospaced';$expectedq->responserequired = 0;$expectedq->responsefieldlines = 42;$expectedq->minwordlimit = 10;$expectedq->minwordenabled = true;$expectedq->maxwordlimit = 20;$expectedq->maxwordenabled = true;$expectedq->attachments = -1;$expectedq->attachmentsrequired = 1;$expectedq->maxbytes = 52428800; // 50MB.$expectedq->filetypeslist = '.pdf,.zip.,.docx';$expectedq->graderinfo['text'] = '<p>Grade <b>generously</b>!</p>';$expectedq->graderinfo['format'] = FORMAT_HTML;$expectedq->responsetemplate['text'] = '<p>Here is something <b>really</b> interesting.</p>';$expectedq->responsetemplate['format'] = FORMAT_HTML;$expectedq->tags = array('tagEssay', 'tagEssay21', 'tagTest');$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_essay(): void {$qdata = new \stdClass();$qdata->id = 123;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'essay';$qdata->name = 'An essay';$qdata->questiontext = 'Write something.';$qdata->questiontextformat = FORMAT_MOODLE;$qdata->generalfeedback = 'I hope you wrote something interesting.';$qdata->generalfeedbackformat = FORMAT_MOODLE;$qdata->defaultmark = 1;$qdata->length = 1;$qdata->penalty = 0;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$qdata->options = new \stdClass();$qdata->options->id = 456;$qdata->options->questionid = 123;$qdata->options->responseformat = 'monospaced';$qdata->options->responserequired = 0;$qdata->options->responsefieldlines = 42;$qdata->options->minwordlimit = 10;$qdata->options->maxwordlimit = 20;$qdata->options->attachments = -1;$qdata->options->attachmentsrequired = 1;$qdata->options->graderinfo = '<p>Grade <b>generously</b>!</p>';$qdata->options->graderinfoformat = FORMAT_HTML;$qdata->options->responsetemplate = '<p>Here is something <b>really</b> interesting.</p>';$qdata->options->responsetemplateformat = FORMAT_HTML;$qdata->options->maxbytes = 52428800; // 50MB.$qdata->options->filetypeslist = '.pdf,.zip.,.docx';$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 123 --><question type="essay"><name><text>An essay</text></name><questiontext format="moodle_auto_format"><text>Write something.</text></questiontext><generalfeedback format="moodle_auto_format"><text>I hope you wrote something interesting.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0</penalty><hidden>0</hidden><idnumber></idnumber><responseformat>monospaced</responseformat><responserequired>0</responserequired><responsefieldlines>42</responsefieldlines><minwordlimit>10</minwordlimit><maxwordlimit>20</maxwordlimit><attachments>-1</attachments><attachmentsrequired>1</attachmentsrequired><maxbytes>52428800</maxbytes><filetypeslist>.pdf,.zip.,.docx</filetypeslist><graderinfo format="html"><text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text></graderinfo><responsetemplate format="html"><text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text></responsetemplate></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_match_19(): void {$xml = ' <question type="matching"><name><text>Matching question</text></name><questiontext format="html"><text>Match the upper and lower case letters.</text></questiontext><generalfeedback><text>The answer is A -> a, B -> b and C -> c.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0.3333333</penalty><hidden>0</hidden><shuffleanswers>false</shuffleanswers><correctfeedback><text>Well done.</text></correctfeedback><partiallycorrectfeedback><text>Not entirely.</text></partiallycorrectfeedback><incorrectfeedback><text>Completely wrong!</text></incorrectfeedback><subquestion><text>A</text><answer><text>a</text></answer></subquestion><subquestion><text>B</text><answer><text>b</text></answer></subquestion><subquestion><text>C</text><answer><text>c</text></answer></subquestion><subquestion><text></text><answer><text>d</text></answer></subquestion><hint><text>Hint 1</text><shownumcorrect /></hint><hint><text></text><shownumcorrect /><clearwrong /></hint><tags><tag><text>tagMatching</text></tag><tag><text>tagTest</text></tag></tags></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_match($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'match';$expectedq->name = 'Matching question';$expectedq->questiontext = 'Match the upper and lower case letters.';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->correctfeedback = array('text' => 'Well done.','format' => FORMAT_HTML);$expectedq->partiallycorrectfeedback = array('text' => 'Not entirely.','format' => FORMAT_HTML);$expectedq->shownumcorrect = false;$expectedq->incorrectfeedback = array('text' => 'Completely wrong!','format' => FORMAT_HTML);$expectedq->generalfeedback = 'The answer is A -> a, B -> b and C -> c.';$expectedq->generalfeedbackformat = FORMAT_HTML;$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 0.3333333;$expectedq->shuffleanswers = 0;$expectedq->subquestions = array(array('text' => 'A', 'format' => FORMAT_HTML),array('text' => 'B', 'format' => FORMAT_HTML),array('text' => 'C', 'format' => FORMAT_HTML),array('text' => '', 'format' => FORMAT_HTML));$expectedq->subanswers = array('a', 'b', 'c', 'd');$expectedq->hint = array(array('text' => 'Hint 1', 'format' => FORMAT_HTML),array('text' => '', 'format' => FORMAT_HTML),);$expectedq->hintshownumcorrect = array(true, true);$expectedq->hintclearwrong = array(false, true);$expectedq->tags = array('tagMatching', 'tagTest');$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_match(): void {$qdata = new \stdClass();$qdata->id = 123;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'match';$qdata->name = 'Matching question';$qdata->questiontext = 'Match the upper and lower case letters.';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'The answer is A -> a, B -> b and C -> c.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 1;$qdata->length = 1;$qdata->penalty = 0.3333333;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$qdata->options = new \stdClass();$qdata->options->shuffleanswers = 1;$qdata->options->correctfeedback = 'Well done.';$qdata->options->correctfeedbackformat = FORMAT_HTML;$qdata->options->partiallycorrectfeedback = 'Not entirely.';$qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;$qdata->options->shownumcorrect = false;$qdata->options->incorrectfeedback = 'Completely wrong!';$qdata->options->incorrectfeedbackformat = FORMAT_HTML;$subq1 = new \stdClass();$subq1->id = -4;$subq1->questiontext = 'A';$subq1->questiontextformat = FORMAT_HTML;$subq1->answertext = 'a';$subq2 = new \stdClass();$subq2->id = -3;$subq2->questiontext = 'B';$subq2->questiontextformat = FORMAT_HTML;$subq2->answertext = 'b';$subq3 = new \stdClass();$subq3->id = -2;$subq3->questiontext = 'C';$subq3->questiontextformat = FORMAT_HTML;$subq3->answertext = 'c';$subq4 = new \stdClass();$subq4->id = -1;$subq4->questiontext = '';$subq4->questiontextformat = FORMAT_HTML;$subq4->answertext = 'd';$qdata->options->subquestions = array($subq1, $subq2, $subq3, $subq4);$qdata->hints = array(new question_hint_with_parts(0, 'Hint 1', FORMAT_HTML, true, false),new question_hint_with_parts(0, '', FORMAT_HTML, true, true),);$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 123 --><question type="matching"><name><text>Matching question</text></name><questiontext format="html"><text>Match the upper and lower case letters.</text></questiontext><generalfeedback format="html"><text><![CDATA[The answer is A -> a, B -> b and C -> c.]]></text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0.3333333</penalty><hidden>0</hidden><idnumber></idnumber><shuffleanswers>true</shuffleanswers><correctfeedback format="html"><text>Well done.</text></correctfeedback><partiallycorrectfeedback format="html"><text>Not entirely.</text></partiallycorrectfeedback><incorrectfeedback format="html"><text>Completely wrong!</text></incorrectfeedback><subquestion format="html"><text>A</text><answer><text>a</text></answer></subquestion><subquestion format="html"><text>B</text><answer><text>b</text></answer></subquestion><subquestion format="html"><text>C</text><answer><text>c</text></answer></subquestion><subquestion format="html"><text></text><answer><text>d</text></answer></subquestion><hint format="html"><text>Hint 1</text><shownumcorrect/></hint><hint format="html"><text></text><shownumcorrect/><clearwrong/></hint></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_multichoice_19(): void {$xml = ' <question type="multichoice"><name><text>Multiple choice question</text></name><questiontext format="html"><text>Which are the even numbers?</text></questiontext><generalfeedback><text>The even numbers are 2 and 4.</text></generalfeedback><defaultgrade>2</defaultgrade><penalty>0.3333333</penalty><hidden>0</hidden><single>false</single><shuffleanswers>false</shuffleanswers><answernumbering>abc</answernumbering><correctfeedback><text><![CDATA[<p>Your answer is correct.</p>]]></text></correctfeedback><partiallycorrectfeedback><text><![CDATA[<p>Your answer is partially correct.</p>]]></text></partiallycorrectfeedback><incorrectfeedback><text><![CDATA[<p>Your answer is incorrect.</p>]]></text></incorrectfeedback><shownumcorrect/><answer fraction="0"><text>1</text><feedback><text></text></feedback></answer><answer fraction="100"><text>2</text><feedback><text></text></feedback></answer><answer fraction="0"><text>3</text><feedback><text></text></feedback></answer><answer fraction="100"><text>4</text><feedback><text></text></feedback></answer><hint><text>Hint 1.</text></hint><hint><text>Hint 2.</text></hint></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_multichoice($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'multichoice';$expectedq->name = 'Multiple choice question';$expectedq->questiontext = 'Which are the even numbers?';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->correctfeedback = array('text' => '<p>Your answer is correct.</p>','format' => FORMAT_HTML);$expectedq->shownumcorrect = false;$expectedq->partiallycorrectfeedback = array('text' => '<p>Your answer is partially correct.</p>','format' => FORMAT_HTML);$expectedq->shownumcorrect = true;$expectedq->incorrectfeedback = array('text' => '<p>Your answer is incorrect.</p>','format' => FORMAT_HTML);$expectedq->generalfeedback = 'The even numbers are 2 and 4.';$expectedq->defaultmark = 2;$expectedq->length = 1;$expectedq->penalty = 0.3333333;$expectedq->shuffleanswers = 0;$expectedq->single = false;$expectedq->answer = array(array('text' => '1', 'format' => FORMAT_HTML),array('text' => '2', 'format' => FORMAT_HTML),array('text' => '3', 'format' => FORMAT_HTML),array('text' => '4', 'format' => FORMAT_HTML));$expectedq->fraction = array(0, 1, 0, 1);$expectedq->feedback = array(array('text' => '', 'format' => FORMAT_HTML),array('text' => '', 'format' => FORMAT_HTML),array('text' => '', 'format' => FORMAT_HTML),array('text' => '', 'format' => FORMAT_HTML));$expectedq->hint = array(array('text' => 'Hint 1.', 'format' => FORMAT_HTML),array('text' => 'Hint 2.', 'format' => FORMAT_HTML),);$expectedq->hintshownumcorrect = array(false, false);$expectedq->hintclearwrong = array(false, false);$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_multichoice(): void {$qdata = new \stdClass();$qdata->id = 123;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'multichoice';$qdata->name = 'Multiple choice question';$qdata->questiontext = 'Which are the even numbers?';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'The even numbers are 2 and 4.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 2;$qdata->length = 1;$qdata->penalty = 0.3333333;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$qdata->options = new \stdClass();$qdata->options->single = 0;$qdata->options->shuffleanswers = 0;$qdata->options->answernumbering = 'abc';$qdata->options->showstandardinstruction = 0;$qdata->options->correctfeedback = '<p>Your answer is correct.</p>';$qdata->options->correctfeedbackformat = FORMAT_HTML;$qdata->options->partiallycorrectfeedback = '<p>Your answer is partially correct.</p>';$qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;$qdata->options->shownumcorrect = 1;$qdata->options->incorrectfeedback = '<p>Your answer is incorrect.</p>';$qdata->options->incorrectfeedbackformat = FORMAT_HTML;$qdata->options->answers = array(13 => new question_answer(13, '1', 0, '', FORMAT_HTML),14 => new question_answer(14, '2', 1, '', FORMAT_HTML),15 => new question_answer(15, '3', 0, '', FORMAT_HTML),16 => new question_answer(16, '4', 1, '', FORMAT_HTML),);$qdata->hints = array(new question_hint_with_parts(0, 'Hint 1.', FORMAT_HTML, false, false),new question_hint_with_parts(0, 'Hint 2.', FORMAT_HTML, false, false),);$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 123 --><question type="multichoice"><name><text>Multiple choice question</text></name><questiontext format="html"><text>Which are the even numbers?</text></questiontext><generalfeedback format="html"><text>The even numbers are 2 and 4.</text></generalfeedback><defaultgrade>2</defaultgrade><penalty>0.3333333</penalty><hidden>0</hidden><idnumber></idnumber><single>false</single><shuffleanswers>false</shuffleanswers><answernumbering>abc</answernumbering><showstandardinstruction>0</showstandardinstruction><correctfeedback format="html"><text><![CDATA[<p>Your answer is correct.</p>]]></text></correctfeedback><partiallycorrectfeedback format="html"><text><![CDATA[<p>Your answer is partially correct.</p>]]></text></partiallycorrectfeedback><incorrectfeedback format="html"><text><![CDATA[<p>Your answer is incorrect.</p>]]></text></incorrectfeedback><shownumcorrect/><answer fraction="0" format="plain_text"><text>1</text><feedback format="html"><text></text></feedback></answer><answer fraction="100" format="plain_text"><text>2</text><feedback format="html"><text></text></feedback></answer><answer fraction="0" format="plain_text"><text>3</text><feedback format="html"><text></text></feedback></answer><answer fraction="100" format="plain_text"><text>4</text><feedback format="html"><text></text></feedback></answer><hint format="html"><text>Hint 1.</text></hint><hint format="html"><text>Hint 2.</text></hint></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_numerical_19(): void {$xml = ' <question type="numerical"><name><text>Numerical question</text></name><questiontext format="html"><text>What is the answer?</text></questiontext><generalfeedback><text>General feedback: Think Hitch-hikers guide to the Galaxy.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0.1</penalty><hidden>0</hidden><answer fraction="100"><text>42</text><feedback><text>Well done!</text></feedback><tolerance>0.001</tolerance></answer><answer fraction="0"><text>13</text><feedback><text>What were you thinking?!</text></feedback><tolerance>1</tolerance></answer><answer fraction="0"><text>*</text><feedback><text>Completely wrong.</text></feedback><tolerance></tolerance></answer></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_numerical($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'numerical';$expectedq->name = 'Numerical question';$expectedq->questiontext = 'What is the answer?';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.';$expectedq->generalfeedbackformat = FORMAT_HTML;$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 0.1;$expectedq->answer = array('42', '13', '*');$expectedq->fraction = array(1, 0, 0);$expectedq->feedback = array(array('text' => 'Well done!','format' => FORMAT_HTML),array('text' => 'What were you thinking?!','format' => FORMAT_HTML),array('text' => 'Completely wrong.','format' => FORMAT_HTML));$expectedq->tolerance = array(0.001, 1, '');$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_numerical(): void {question_bank::load_question_definition_classes('numerical');$qdata = new \stdClass();$qdata->id = 123;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'numerical';$qdata->name = 'Numerical question';$qdata->questiontext = 'What is the answer?';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 1;$qdata->length = 1;$qdata->penalty = 0.1;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$qdata->options = new \stdClass();$qdata->options->answers = array(13 => new qtype_numerical_answer(13, '42', 1, 'Well done!',FORMAT_HTML, 0.001),14 => new qtype_numerical_answer(14, '13', 0, 'What were you thinking?!',FORMAT_HTML, 1),15 => new qtype_numerical_answer(15, '*', 0, 'Completely wrong.',FORMAT_HTML, ''),);$qdata->options->units = array();$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 123 --><question type="numerical"><name><text>Numerical question</text></name><questiontext format="html"><text>What is the answer?</text></questiontext><generalfeedback format="html"><text>General feedback: Think Hitch-hikers guide to the Galaxy.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0.1</penalty><hidden>0</hidden><idnumber></idnumber><answer fraction="100" format="plain_text"><text>42</text><feedback format="html"><text>Well done!</text></feedback><tolerance>0.001</tolerance></answer><answer fraction="0" format="plain_text"><text>13</text><feedback format="html"><text>What were you thinking?!</text></feedback><tolerance>1</tolerance></answer><answer fraction="0" format="plain_text"><text>*</text><feedback format="html"><text>Completely wrong.</text></feedback><tolerance>0</tolerance></answer></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_shortanswer_19(): void {$xml = ' <question type="shortanswer"><name><text>Short answer question</text></name><questiontext format="html"><text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text></questiontext><generalfeedback><text>The answer is Beta.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0.3333333</penalty><hidden>0</hidden><usecase>0</usecase><answer fraction="100" format="plain_text"><text>Beta</text><feedback><text>Well done!</text></feedback></answer><answer fraction="0" format="plain_text"><text>*</text><feedback><text>Doh!</text></feedback></answer><hint><text>Hint 1</text></hint><hint><text>Hint 2</text></hint></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_shortanswer($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'shortanswer';$expectedq->name = 'Short answer question';$expectedq->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->generalfeedback = 'The answer is Beta.';$expectedq->usecase = false;$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 0.3333333;$expectedq->answer = array('Beta', '*');$expectedq->fraction = array(1, 0);$expectedq->feedback = array(array('text' => 'Well done!', 'format' => FORMAT_HTML),array('text' => 'Doh!', 'format' => FORMAT_HTML));$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_shortanswer(): void {$qdata = new \stdClass();$qdata->id = 123;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'shortanswer';$qdata->name = 'Short answer question';$qdata->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'The answer is Beta.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 1;$qdata->length = 1;$qdata->penalty = 0.3333333;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$qdata->options = new \stdClass();$qdata->options->usecase = 0;$qdata->options->answers = array(13 => new question_answer(13, 'Beta', 1, 'Well done!', FORMAT_HTML),14 => new question_answer(14, '*', 0, 'Doh!', FORMAT_HTML),);$qdata->hints = array(new question_hint(0, 'Hint 1', FORMAT_HTML),new question_hint(0, 'Hint 2', FORMAT_HTML),);$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 123 --><question type="shortanswer"><name><text>Short answer question</text></name><questiontext format="html"><text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text></questiontext><generalfeedback format="html"><text>The answer is Beta.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>0.3333333</penalty><hidden>0</hidden><idnumber></idnumber><usecase>0</usecase><answer fraction="100" format="plain_text"><text>Beta</text><feedback format="html"><text>Well done!</text></feedback></answer><answer fraction="0" format="plain_text"><text>*</text><feedback format="html"><text>Doh!</text></feedback></answer><hint format="html"><text>Hint 1</text></hint><hint format="html"><text>Hint 2</text></hint></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_truefalse_19(): void {$xml = ' <question type="truefalse"><name><text>True false question</text></name><questiontext format="html"><text>The answer is true.</text></questiontext><generalfeedback><text>General feedback: You should have chosen true.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>1</penalty><hidden>0</hidden><answer fraction="100"><text>true</text><feedback><text>Well done!</text></feedback></answer><answer fraction="0"><text>false</text><feedback><text>Doh!</text></feedback></answer></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_truefalse($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'truefalse';$expectedq->name = 'True false question';$expectedq->questiontext = 'The answer is true.';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->generalfeedback = 'General feedback: You should have chosen true.';$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 1;$expectedq->feedbacktrue = array('text' => 'Well done!','format' => FORMAT_HTML);$expectedq->feedbackfalse = array('text' => 'Doh!','format' => FORMAT_HTML);$expectedq->correctanswer = true;$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_import_truefalse_with_idnumber(): void {$xml = ' <question type="truefalse"><name><text>True false question</text></name><questiontext format="html"><text>The answer is true.</text></questiontext><generalfeedback><text>General feedback: You should have chosen true.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>1</penalty><hidden>0</hidden><idnumber>TestIdNum1</idnumber><answer fraction="100"><text>true</text><feedback><text>Well done!</text></feedback></answer><answer fraction="0"><text>false</text><feedback><text>Doh!</text></feedback></answer></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_truefalse($xmldata['question']);$expectedq = new \stdClass();$expectedq->qtype = 'truefalse';$expectedq->name = 'True false question';$expectedq->questiontext = 'The answer is true.';$expectedq->questiontextformat = FORMAT_HTML;$expectedq->generalfeedback = 'General feedback: You should have chosen true.';$expectedq->defaultmark = 1;$expectedq->length = 1;$expectedq->penalty = 1;$expectedq->idnumber = 'TestIdNum1';$expectedq->feedbacktrue = array('text' => 'Well done!','format' => FORMAT_HTML);$expectedq->feedbackfalse = array('text' => 'Doh!','format' => FORMAT_HTML);$expectedq->correctanswer = true;$this->assert(new question_check_specified_fields_expectation($expectedq), $q);}public function test_export_truefalse(): void {$qdata = new \stdClass();$qdata->id = 12;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'truefalse';$qdata->name = 'True false question';$qdata->questiontext = 'The answer is true.';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'General feedback: You should have chosen true.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 1;$qdata->length = 1;$qdata->penalty = 1;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = null;$qdata->options = new \stdClass();$qdata->options->answers = array(1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML),2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML),);$qdata->options->trueanswer = 1;$qdata->options->falseanswer = 2;$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 12 --><question type="truefalse"><name><text>True false question</text></name><questiontext format="html"><text>The answer is true.</text></questiontext><generalfeedback format="html"><text>General feedback: You should have chosen true.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>1</penalty><hidden>0</hidden><idnumber></idnumber><answer fraction="100" format="plain_text"><text>true</text><feedback format="html"><text>Well done!</text></feedback></answer><answer fraction="0" format="plain_text"><text>false</text><feedback format="html"><text>Doh!</text></feedback></answer></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_export_truefalse_with_idnumber(): void {$qdata = new \stdClass();$qdata->id = 12;$qdata->contextid = \context_system::instance()->id;$qdata->qtype = 'truefalse';$qdata->name = 'True false question';$qdata->questiontext = 'The answer is true.';$qdata->questiontextformat = FORMAT_HTML;$qdata->generalfeedback = 'General feedback: You should have chosen true.';$qdata->generalfeedbackformat = FORMAT_HTML;$qdata->defaultmark = 1;$qdata->length = 1;$qdata->penalty = 1;$qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;$qdata->idnumber = 'TestIDNum2';$qdata->options = new \stdClass();$qdata->options->answers = array(1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML),2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML),);$qdata->options->trueanswer = 1;$qdata->options->falseanswer = 2;$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 12 --><question type="truefalse"><name><text>True false question</text></name><questiontext format="html"><text>The answer is true.</text></questiontext><generalfeedback format="html"><text>General feedback: You should have chosen true.</text></generalfeedback><defaultgrade>1</defaultgrade><penalty>1</penalty><hidden>0</hidden><idnumber>TestIDNum2</idnumber><answer fraction="100" format="plain_text"><text>true</text><feedback format="html"><text>Well done!</text></feedback></answer><answer fraction="0" format="plain_text"><text>false</text><feedback format="html"><text>Doh!</text></feedback></answer></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_multianswer(): void {$xml = ' <question type="cloze"><name><text>Simple multianswer</text></name><questiontext format="html"><text><![CDATA[Complete this opening line of verse: "The {1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer} and the {1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!} went to sea".]]></text></questiontext><generalfeedback format="html"><text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".]]></text></generalfeedback><penalty>0.5</penalty><hidden>0</hidden><idnumber>id-101</idnumber><hint format="html"><text>Hint 1</text></hint><hint format="html"><text>Hint 2</text></hint><tags><tag><text>tagCloze</text></tag><tag><text>tagTest</text></tag></tags></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_multianswer($xmldata['question']);// Annoyingly, import works in a weird way (it duplicates code, rather// than just calling save_question) so we cannot use// \test_question_maker::get_question_form_data('multianswer', 'twosubq').$expectedqa = new \stdClass();$expectedqa->name = 'Simple multianswer';$expectedqa->qtype = 'multianswer';$expectedqa->questiontext = 'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';$expectedqa->idnumber = 'id-101';$expectedqa->generalfeedback ='General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".';$expectedqa->defaultmark = 2;$expectedqa->penalty = 0.5;$expectedqa->hint = array(array('text' => 'Hint 1', 'format' => FORMAT_HTML),array('text' => 'Hint 2', 'format' => FORMAT_HTML),);$sa = new \stdClass();$sa->questiontext = array('text' => '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer}','format' => FORMAT_HTML, 'itemid' => null);$sa->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);$sa->defaultmark = 1.0;$sa->qtype = 'shortanswer';$sa->usecase = 0;$sa->answer = array('Dog', 'Owl', '*');$sa->fraction = array(0, 1, 0);$sa->feedback = array(array('text' => 'Wrong, silly!', 'format' => FORMAT_HTML, 'itemid' => null),array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),array('text' => 'Wrong answer', 'format' => FORMAT_HTML, 'itemid' => null),);$mc = new \stdClass();$mc->generalfeedback = '';$mc->questiontext = array('text' => '{1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~' .'Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}','format' => FORMAT_HTML, 'itemid' => null);$mc->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);$mc->defaultmark = 1.0;$mc->qtype = 'multichoice';$mc->layout = 0;$mc->single = 1;$mc->shuffleanswers = 0;$mc->correctfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);$mc->partiallycorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);$mc->incorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);$mc->answernumbering = 0;$mc->answer = array(array('text' => 'Bow-wow', 'format' => FORMAT_HTML, 'itemid' => null),array('text' => 'Wiggly worm', 'format' => FORMAT_HTML, 'itemid' => null),array('text' => 'Pussy-cat', 'format' => FORMAT_HTML, 'itemid' => null),);$mc->fraction = array(0, 0, 1);$mc->feedback = array(array('text' => 'You seem to have a dog obsessions!', 'format' => FORMAT_HTML, 'itemid' => null),array('text' => 'Now you are just being ridiculous!', 'format' => FORMAT_HTML, 'itemid' => null),array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),);$expectedqa->options = new \stdClass();$expectedqa->options->questions = array(1 => $sa,2 => $mc,);$expectedqa->tags = array('tagCloze', 'tagTest');$this->assertEquals($expectedqa->hint, $q->hint);$this->assertEquals($expectedqa->options->questions[1], $q->options->questions[1]);$this->assertEquals($expectedqa->options->questions[2], $q->options->questions[2]);$this->assert(new question_check_specified_fields_expectation($expectedqa), $q);}public function test_export_multianswer(): void {$qdata = \test_question_maker::get_question_data('multianswer', 'twosubq');$qdata->contextid = \context_system::instance()->id;$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 0 --><question type="cloze"><name><text>Simple multianswer</text></name><questiontext format="html"><text><![CDATA[Complete this opening line of verse: "The {1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer} and the {1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!} went to sea".]]></text></questiontext><generalfeedback format="html"><text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea]]></text></generalfeedback><penalty>0.3333333</penalty><hidden>0</hidden><idnumber></idnumber><hint format="html"><text>Hint 1</text></hint><hint format="html"><text>Hint 2</text></hint></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_export_multianswer_withdollars(): void {$qdata = \test_question_maker::get_question_data('multianswer', 'dollarsigns');$qdata->contextid = \context_system::instance()->id;$exporter = new qformat_xml();$xml = $exporter->writequestion($qdata);$expectedxml = '<!-- question: 0 --><question type="cloze"><name><text>Multianswer with $s</text></name><questiontext format="html"><text>Which is the right order? {1:MULTICHOICE:=y,y,$3~$3,y,y}</text></questiontext><generalfeedback format="html"><text></text></generalfeedback><penalty>0.3333333</penalty><hidden>0</hidden><idnumber></idnumber></question>';$this->assert_same_xml($expectedxml, $xml);}public function test_import_files_as_draft(): void {$this->resetAfterTest();$this->setAdminUser();$xml = <<<END<questiontext format="html"><text><![CDATA[<p><a href="@@PLUGINFILE@@/moodle.txt">This text file</a> contains the word 'Moodle'.</p>]]></text><file name="moodle.txt" encoding="base64">TW9vZGxl</file></questiontext>END;$textxml = xmlize($xml);$qo = new \stdClass();$importer = new qformat_xml();$draftitemid = $importer->import_files_as_draft($textxml['questiontext']['#']['file']);$files = file_get_drafarea_files($draftitemid);$this->assertEquals(1, count($files->list));$file = $files->list[0];$this->assertEquals('moodle.txt', $file->filename);$this->assertEquals('/', $file->filepath);$this->assertEquals(6, $file->size);}public function test_import_truefalse_wih_files(): void {$this->resetAfterTest();$this->setAdminUser();$xml = '<question type="truefalse"><name><text>truefalse</text></name><questiontext format="html"><text><![CDATA[<p><a href="@@PLUGINFILE@@/myfolder/moodle.txt">This text file</a> contains the word Moodle.</p>]]></text><file name="moodle.txt" path="/myfolder/" encoding="base64">TW9vZGxl</file></questiontext><generalfeedback format="html"><text><![CDATA[<p>For further information, see the documentation about Moodle.</p>]]></text></generalfeedback><defaultgrade>1.0000000</defaultgrade><penalty>1.0000000</penalty><hidden>0</hidden><answer fraction="100" format="moodle_auto_format"><text>true</text><feedback format="html"><text></text></feedback></answer><answer fraction="0" format="moodle_auto_format"><text>false</text><feedback format="html"><text></text></feedback></answer></question>';$xmldata = xmlize($xml);$importer = new qformat_xml();$q = $importer->import_truefalse($xmldata['question']);$draftitemid = $q->questiontextitemid;$files = file_get_drafarea_files($draftitemid, '/myfolder/');$this->assertEquals(1, count($files->list));$file = $files->list[0];$this->assertEquals('moodle.txt', $file->filename);$this->assertEquals('/myfolder/', $file->filepath);$this->assertEquals(6, $file->size);}public function test_create_dummy_question(): void {$testobject = new mock_qformat_xml();$categoryname = 'name1';$categoryinfo = new \stdClass();$categoryinfo->info = 'info1';$categoryinfo->infoformat = 'infoformat1';$categoryinfo->idnumber = null;$dummyquestion = $testobject->mock_create_dummy_question_representing_category($categoryname, $categoryinfo);$this->assertEquals('category', $dummyquestion->qtype);$this->assertEquals($categoryname, $dummyquestion->category);$this->assertEquals($categoryinfo->info, $dummyquestion->info);$this->assertEquals($categoryinfo->infoformat, $dummyquestion->infoformat);$this->assertEquals('Switch category to ' . $categoryname, $dummyquestion->name);$this->assertEquals(0, $dummyquestion->id);$this->assertEquals('', $dummyquestion->questiontextformat);$this->assertEquals(0, $dummyquestion->contextid);}}/*** Class mock_qformat_xml exists only to enable testing of the create dummy question category.* @package qformat_xml* @copyright 2018 The Open University* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class mock_qformat_xml extends qformat_xml {/*** Make public an otherwise protected function.* @param string $categoryname the name of the category* @param object $categoryinfo description of the category*/public function mock_create_dummy_question_representing_category(string $categoryname, $categoryinfo) {return $this->create_dummy_question_representing_category($categoryname, $categoryinfo);}}