MDL-61410 question: fix unit tests failures
[moodle.git] / question / format / xml / tests / xmlformat_test.php
CommitLineData
603bd001
PS
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Unit tests for the Moodle XML format.
19 *
d2fd7262 20 * @package qformat_xml
603bd001
PS
21 * @copyright 2010 The Open University
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29require_once($CFG->libdir . '/questionlib.php');
30require_once($CFG->dirroot . '/question/format/xml/format.php');
31require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
32
33
34/**
35 * Unit tests for the matching question definition class.
36 *
37 * @copyright 2009 The Open University
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
40class qformat_xml_test extends question_testcase {
41 public function assert_same_xml($expectedxml, $xml) {
42 $this->assertEquals(str_replace("\r\n", "\n", $expectedxml),
43 str_replace("\r\n", "\n", $xml));
44 }
45
46 public function make_test_question() {
47 global $USER;
48 $q = new stdClass();
49 $q->id = 0;
50 $q->contextid = 0;
51 $q->category = 0;
52 $q->parent = 0;
53 $q->questiontextformat = FORMAT_HTML;
54 $q->generalfeedbackformat = FORMAT_HTML;
55 $q->defaultmark = 1;
56 $q->penalty = 0.3333333;
57 $q->length = 1;
58 $q->stamp = make_unique_id_code();
59 $q->version = make_unique_id_code();
60 $q->hidden = 0;
61 $q->timecreated = time();
62 $q->timemodified = time();
63 $q->createdby = $USER->id;
64 $q->modifiedby = $USER->id;
65 return $q;
66 }
67
68 /**
69 * The data the XML import format sends to save_question is not exactly
70 * the same as the data returned from the editing form, so this method
71 * makes necessary changes to the return value of
72 * test_question_maker::get_question_form_data so that the tests can work.
73 * @param object $expectedq as returned by get_question_form_data.
74 * @return object one more likely to match the return value of import_...().
75 */
76 public function remove_irrelevant_form_data_fields($expectedq) {
77 return $this->itemid_to_files($expectedq);
78 }
79
80 /**
81 * Becuase XML import uses a files array instead of an itemid integer to
82 * handle saving files with a question, we need to covert the output of
83 * test_question_maker::get_question_form_data to match. This method recursively
84 * replaces all array elements with key itemid with an array entry with
85 * key files and value an empty array.
86 *
87 * @param mixed $var any data structure.
88 * @return mixed an equivalent structure with the relacements made.
89 */
90 protected function itemid_to_files($var) {
91 if (is_object($var)) {
92 $newvar = new stdClass();
d2fd7262 93 foreach (get_object_vars($var) as $field => $value) {
603bd001
PS
94 $newvar->$field = $this->itemid_to_files($value);
95 }
96
97 } else if (is_array($var)) {
98 $newvar = array();
99 foreach ($var as $index => $value) {
100 if ($index === 'itemid') {
101 $newvar['files'] = array();
102 } else {
103 $newvar[$index] = $this->itemid_to_files($value);
104 }
105 }
106
107 } else {
108 $newvar = $var;
109 }
110
111 return $newvar;
112 }
113
46e4c35a
TH
114 public function test_xml_escape_simple_input_not_escaped() {
115 $exporter = new qformat_xml();
116 $string = 'Nothing funny here. Even if we go to a café or to 日本.';
117 $this->assertEquals($string, $exporter->xml_escape($string));
118 }
119
120 public function test_xml_escape_html_wrapped_in_cdata() {
121 $exporter = new qformat_xml();
122 $string = '<p>Nothing <b>funny<b> here. Even if we go to a café or to 日本.</p>';
123 $this->assertEquals('<![CDATA[' . $string . ']]>', $exporter->xml_escape($string));
124 }
125
126 public function test_xml_escape_script_tag_handled_ok() {
127 $exporter = new qformat_xml();
128 $input = '<script><![CDATA[alert(1<2);]]></script>';
129 $expected = '<![CDATA[<script><![CDATA[alert(1<2);]]]]><![CDATA[></script>]]>';
130 $this->assertEquals($expected, $exporter->xml_escape($input));
131
132 // Check that parsing the expected result does give the input again.
133 $parsed = simplexml_load_string('<div>' . $expected . '</div>');
134 $this->assertEquals($input, $parsed->xpath('//div')[0]);
135 }
136
137 public function test_xml_escape_code_that_looks_like_cdata_end_ok() {
138 $exporter = new qformat_xml();
139 $input = "if (x[[0]]>a) print('hah');";
140 $expected = "<![CDATA[if (x[[0]]]]><![CDATA[>a) print('hah');]]>";
141 $this->assertEquals($expected, $exporter->xml_escape($input));
142
143 // Check that parsing the expected result does give the input again.
144 $parsed = simplexml_load_string('<div>' . $expected . '</div>');
145 $this->assertEquals($input, $parsed->xpath('//div')[0]);
146 }
147
603bd001
PS
148 public function test_write_hint_basic() {
149 $q = $this->make_test_question();
1796eb18 150 $q->contextid = \context_system::instance()->id;
603bd001
PS
151 $q->name = 'Short answer question';
152 $q->questiontext = 'Name an amphibian: __________';
153 $q->generalfeedback = 'Generalfeedback: frog or toad would have been OK.';
154 if (!isset($q->options)) {
155 $q->options = new stdClass();
156 }
157 $q->options->usecase = false;
158 $q->options->answers = array(
159 13 => new question_answer(13, 'frog', 1.0, 'Frog is a very good answer.', FORMAT_HTML),
160 14 => new question_answer(14, 'toad', 0.8, 'Toad is an OK good answer.', FORMAT_HTML),
161 15 => new question_answer(15, '*', 0.0, 'That is a bad answer.', FORMAT_HTML),
162 );
163 $q->qtype = 'shortanswer';
164 $q->hints = array(
165 new question_hint(0, 'This is the first hint.', FORMAT_MOODLE),
166 );
167
168 $exporter = new qformat_xml();
169 $xml = $exporter->writequestion($q);
170
171 $this->assertRegExp('|<hint format=\"moodle_auto_format\">\s*<text>\s*' .
172 'This is the first hint\.\s*</text>\s*</hint>|', $xml);
173 $this->assertNotRegExp('|<shownumcorrect/>|', $xml);
174 $this->assertNotRegExp('|<clearwrong/>|', $xml);
175 $this->assertNotRegExp('|<options>|', $xml);
176 }
177
178 public function test_write_hint_with_parts() {
179 $q = $this->make_test_question();
1796eb18 180 $q->contextid = \context_system::instance()->id;
603bd001
PS
181 $q->name = 'Matching question';
182 $q->questiontext = 'Classify the animals.';
183 $q->generalfeedback = 'Frogs and toads are amphibians, the others are mammals.';
184 $q->qtype = 'match';
185
186 if (!isset($q->options)) {
187 $q->options = new stdClass();
188 }
189 $q->options->shuffleanswers = 1;
190 $q->options->correctfeedback = '';
191 $q->options->correctfeedbackformat = FORMAT_HTML;
192 $q->options->partiallycorrectfeedback = '';
193 $q->options->partiallycorrectfeedbackformat = FORMAT_HTML;
194 $q->options->incorrectfeedback = '';
195 $q->options->incorrectfeedbackformat = FORMAT_HTML;
196
197 $q->options->subquestions = array();
198 $q->hints = array(
199 new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, true),
200 new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, false),
201 );
202
203 $exporter = new qformat_xml();
204 $xml = $exporter->writequestion($q);
205
206 $this->assertRegExp(
207 '|<hint format=\"html\">\s*<text>\s*This is the first hint\.\s*</text>|', $xml);
208 $this->assertRegExp(
209 '|<hint format=\"html\">\s*<text>\s*This is the second hint\.\s*</text>|', $xml);
210 list($ignored, $hint1, $hint2) = explode('<hint', $xml);
211 $this->assertNotRegExp('|<shownumcorrect/>|', $hint1);
212 $this->assertRegExp('|<clearwrong/>|', $hint1);
213 $this->assertRegExp('|<shownumcorrect/>|', $hint2);
214 $this->assertNotRegExp('|<clearwrong/>|', $hint2);
215 $this->assertNotRegExp('|<options>|', $xml);
216 }
217
218 public function test_import_hints_no_parts() {
219 $xml = <<<END
220<question>
221 <hint>
222 <text>This is the first hint</text>
223 <clearwrong/>
224 </hint>
225 <hint>
226 <text>This is the second hint</text>
227 <shownumcorrect/>
228 </hint>
229</question>
230END;
231
232 $questionxml = xmlize($xml);
233 $qo = new stdClass();
234
235 $importer = new qformat_xml();
236 $importer->import_hints($qo, $questionxml['question'], false, false, 'html');
237
238 $this->assertEquals(array(
239 array('text' => 'This is the first hint',
2387d1cd 240 'format' => FORMAT_HTML),
603bd001 241 array('text' => 'This is the second hint',
2387d1cd 242 'format' => FORMAT_HTML),
603bd001
PS
243 ), $qo->hint);
244 $this->assertFalse(isset($qo->hintclearwrong));
245 $this->assertFalse(isset($qo->hintshownumcorrect));
246 }
247
248 public function test_import_hints_with_parts() {
249 $xml = <<<END
250<question>
251 <hint>
252 <text>This is the first hint</text>
253 <clearwrong/>
254 </hint>
255 <hint>
256 <text>This is the second hint</text>
257 <shownumcorrect/>
258 </hint>
259</question>
260END;
261
262 $questionxml = xmlize($xml);
263 $qo = new stdClass();
264
265 $importer = new qformat_xml();
266 $importer->import_hints($qo, $questionxml['question'], true, true, 'html');
267
268 $this->assertEquals(array(
269 array('text' => 'This is the first hint',
2387d1cd 270 'format' => FORMAT_HTML),
603bd001 271 array('text' => 'This is the second hint',
2387d1cd 272 'format' => FORMAT_HTML),
603bd001
PS
273 ), $qo->hint);
274 $this->assertEquals(array(1, 0), $qo->hintclearwrong);
275 $this->assertEquals(array(0, 1), $qo->hintshownumcorrect);
276 }
277
278 public function test_import_no_hints_no_error() {
279 $xml = <<<END
280<question>
281</question>
282END;
283
284 $questionxml = xmlize($xml);
285 $qo = new stdClass();
286
287 $importer = new qformat_xml();
288 $importer->import_hints($qo, $questionxml['question'], 'html');
289
290 $this->assertFalse(isset($qo->hint));
291 }
292
293 public function test_import_description() {
294 $xml = ' <question type="description">
295 <name>
296 <text>A description</text>
297 </name>
298 <questiontext format="html">
299 <text>The question text.</text>
300 </questiontext>
301 <generalfeedback>
302 <text>Here is some general feedback.</text>
303 </generalfeedback>
304 <defaultgrade>0</defaultgrade>
305 <penalty>0</penalty>
306 <hidden>0</hidden>
dcd4464e
EC
307 <tags>
308 <tag><text>tagDescription</text></tag>
309 <tag><text>tagTest</text></tag>
310 </tags>
603bd001
PS
311 </question>';
312 $xmldata = xmlize($xml);
313
314 $importer = new qformat_xml();
315 $q = $importer->import_description($xmldata['question']);
316
317 $expectedq = new stdClass();
318 $expectedq->qtype = 'description';
319 $expectedq->name = 'A description';
320 $expectedq->questiontext = 'The question text.';
321 $expectedq->questiontextformat = FORMAT_HTML;
322 $expectedq->generalfeedback = 'Here is some general feedback.';
323 $expectedq->defaultmark = 0;
324 $expectedq->length = 0;
325 $expectedq->penalty = 0;
dcd4464e 326 $expectedq->tags = array('tagDescription', 'tagTest');
603bd001
PS
327
328 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
329 }
330
331 public function test_export_description() {
332 $qdata = new stdClass();
333 $qdata->id = 123;
1796eb18 334 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
335 $qdata->qtype = 'description';
336 $qdata->name = 'A description';
337 $qdata->questiontext = 'The question text.';
338 $qdata->questiontextformat = FORMAT_HTML;
339 $qdata->generalfeedback = 'Here is some general feedback.';
340 $qdata->generalfeedbackformat = FORMAT_HTML;
341 $qdata->defaultmark = 0;
342 $qdata->length = 0;
343 $qdata->penalty = 0;
344 $qdata->hidden = 0;
345
346 $exporter = new qformat_xml();
347 $xml = $exporter->writequestion($qdata);
348
349 $expectedxml = '<!-- question: 123 -->
350 <question type="description">
351 <name>
352 <text>A description</text>
353 </name>
354 <questiontext format="html">
355 <text>The question text.</text>
356 </questiontext>
357 <generalfeedback format="html">
358 <text>Here is some general feedback.</text>
359 </generalfeedback>
360 <defaultgrade>0</defaultgrade>
361 <penalty>0</penalty>
362 <hidden>0</hidden>
363 </question>
364';
365
366 $this->assert_same_xml($expectedxml, $xml);
367 }
368
369 public function test_import_essay_20() {
370 $xml = ' <question type="essay">
371 <name>
372 <text>An essay</text>
373 </name>
374 <questiontext format="moodle_auto_format">
375 <text>Write something.</text>
376 </questiontext>
377 <generalfeedback>
378 <text>I hope you wrote something interesting.</text>
379 </generalfeedback>
380 <defaultgrade>1</defaultgrade>
381 <penalty>0</penalty>
382 <hidden>0</hidden>
dcd4464e
EC
383 <tags>
384 <tag><text>tagEssay</text></tag>
385 <tag><text>tagEssay20</text></tag>
386 <tag><text>tagTest</text></tag>
387 </tags>
603bd001
PS
388 </question>';
389 $xmldata = xmlize($xml);
390
391 $importer = new qformat_xml();
392 $q = $importer->import_essay($xmldata['question']);
393
394 $expectedq = new stdClass();
395 $expectedq->qtype = 'essay';
396 $expectedq->name = 'An essay';
397 $expectedq->questiontext = 'Write something.';
398 $expectedq->questiontextformat = FORMAT_MOODLE;
399 $expectedq->generalfeedback = 'I hope you wrote something interesting.';
400 $expectedq->defaultmark = 1;
401 $expectedq->length = 1;
402 $expectedq->penalty = 0;
403 $expectedq->responseformat = 'editor';
a4f765eb 404 $expectedq->responserequired = 1;
603bd001
PS
405 $expectedq->responsefieldlines = 15;
406 $expectedq->attachments = 0;
a4f765eb 407 $expectedq->attachmentsrequired = 0;
603bd001
PS
408 $expectedq->graderinfo['text'] = '';
409 $expectedq->graderinfo['format'] = FORMAT_MOODLE;
60527d0c
JMV
410 $expectedq->responsetemplate['text'] = '';
411 $expectedq->responsetemplate['format'] = FORMAT_MOODLE;
dcd4464e 412 $expectedq->tags = array('tagEssay', 'tagEssay20', 'tagTest');
603bd001
PS
413
414 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
415 }
416
417 public function test_import_essay_21() {
418 $xml = ' <question type="essay">
419 <name>
420 <text>An essay</text>
421 </name>
422 <questiontext format="moodle_auto_format">
423 <text>Write something.</text>
424 </questiontext>
425 <generalfeedback>
426 <text>I hope you wrote something interesting.</text>
427 </generalfeedback>
428 <defaultgrade>1</defaultgrade>
429 <penalty>0</penalty>
430 <hidden>0</hidden>
431 <responseformat>monospaced</responseformat>
a4f765eb 432 <responserequired>0</responserequired>
603bd001
PS
433 <responsefieldlines>42</responsefieldlines>
434 <attachments>-1</attachments>
a4f765eb 435 <attachmentsrequired>1</attachmentsrequired>
603bd001
PS
436 <graderinfo format="html">
437 <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text>
438 </graderinfo>
60527d0c
JMV
439 <responsetemplate format="html">
440 <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text>
441 </responsetemplate>
dcd4464e
EC
442 <tags>
443 <tag><text>tagEssay</text></tag>
444 <tag><text>tagEssay21</text></tag>
445 <tag><text>tagTest</text></tag>
446 </tags>
603bd001
PS
447 </question>';
448 $xmldata = xmlize($xml);
449
450 $importer = new qformat_xml();
451 $q = $importer->import_essay($xmldata['question']);
452
453 $expectedq = new stdClass();
454 $expectedq->qtype = 'essay';
455 $expectedq->name = 'An essay';
456 $expectedq->questiontext = 'Write something.';
457 $expectedq->questiontextformat = FORMAT_MOODLE;
458 $expectedq->generalfeedback = 'I hope you wrote something interesting.';
459 $expectedq->defaultmark = 1;
460 $expectedq->length = 1;
461 $expectedq->penalty = 0;
462 $expectedq->responseformat = 'monospaced';
a4f765eb 463 $expectedq->responserequired = 0;
603bd001
PS
464 $expectedq->responsefieldlines = 42;
465 $expectedq->attachments = -1;
a4f765eb 466 $expectedq->attachmentsrequired = 1;
603bd001
PS
467 $expectedq->graderinfo['text'] = '<p>Grade <b>generously</b>!</p>';
468 $expectedq->graderinfo['format'] = FORMAT_HTML;
60527d0c
JMV
469 $expectedq->responsetemplate['text'] = '<p>Here is something <b>really</b> interesting.</p>';
470 $expectedq->responsetemplate['format'] = FORMAT_HTML;
dcd4464e 471 $expectedq->tags = array('tagEssay', 'tagEssay21', 'tagTest');
603bd001
PS
472
473 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
474 }
475
476 public function test_export_essay() {
477 $qdata = new stdClass();
478 $qdata->id = 123;
1796eb18 479 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
480 $qdata->qtype = 'essay';
481 $qdata->name = 'An essay';
482 $qdata->questiontext = 'Write something.';
483 $qdata->questiontextformat = FORMAT_MOODLE;
484 $qdata->generalfeedback = 'I hope you wrote something interesting.';
485 $qdata->generalfeedbackformat = FORMAT_MOODLE;
486 $qdata->defaultmark = 1;
487 $qdata->length = 1;
488 $qdata->penalty = 0;
489 $qdata->hidden = 0;
490 $qdata->options = new stdClass();
491 $qdata->options->id = 456;
492 $qdata->options->questionid = 123;
493 $qdata->options->responseformat = 'monospaced';
a4f765eb 494 $qdata->options->responserequired = 0;
603bd001
PS
495 $qdata->options->responsefieldlines = 42;
496 $qdata->options->attachments = -1;
a4f765eb 497 $qdata->options->attachmentsrequired = 1;
603bd001
PS
498 $qdata->options->graderinfo = '<p>Grade <b>generously</b>!</p>';
499 $qdata->options->graderinfoformat = FORMAT_HTML;
60527d0c
JMV
500 $qdata->options->responsetemplate = '<p>Here is something <b>really</b> interesting.</p>';
501 $qdata->options->responsetemplateformat = FORMAT_HTML;
603bd001
PS
502 $exporter = new qformat_xml();
503 $xml = $exporter->writequestion($qdata);
504
505 $expectedxml = '<!-- question: 123 -->
506 <question type="essay">
507 <name>
508 <text>An essay</text>
509 </name>
510 <questiontext format="moodle_auto_format">
511 <text>Write something.</text>
512 </questiontext>
513 <generalfeedback format="moodle_auto_format">
514 <text>I hope you wrote something interesting.</text>
515 </generalfeedback>
516 <defaultgrade>1</defaultgrade>
517 <penalty>0</penalty>
518 <hidden>0</hidden>
519 <responseformat>monospaced</responseformat>
a4f765eb 520 <responserequired>0</responserequired>
603bd001
PS
521 <responsefieldlines>42</responsefieldlines>
522 <attachments>-1</attachments>
a4f765eb 523 <attachmentsrequired>1</attachmentsrequired>
603bd001
PS
524 <graderinfo format="html">
525 <text><![CDATA[<p>Grade <b>generously</b>!</p>]]></text>
526 </graderinfo>
60527d0c
JMV
527 <responsetemplate format="html">
528 <text><![CDATA[<p>Here is something <b>really</b> interesting.</p>]]></text>
529 </responsetemplate>
603bd001
PS
530 </question>
531';
532
533 $this->assert_same_xml($expectedxml, $xml);
534 }
535
536 public function test_import_match_19() {
537 $xml = ' <question type="matching">
538 <name>
539 <text>Matching question</text>
540 </name>
541 <questiontext format="html">
542 <text>Match the upper and lower case letters.</text>
543 </questiontext>
544 <generalfeedback>
545 <text>The answer is A -> a, B -> b and C -> c.</text>
546 </generalfeedback>
547 <defaultgrade>1</defaultgrade>
548 <penalty>0.3333333</penalty>
549 <hidden>0</hidden>
550 <shuffleanswers>false</shuffleanswers>
551 <correctfeedback>
552 <text>Well done.</text>
553 </correctfeedback>
554 <partiallycorrectfeedback>
555 <text>Not entirely.</text>
556 </partiallycorrectfeedback>
557 <incorrectfeedback>
558 <text>Completely wrong!</text>
559 </incorrectfeedback>
560 <subquestion>
561 <text>A</text>
562 <answer>
563 <text>a</text>
564 </answer>
565 </subquestion>
566 <subquestion>
567 <text>B</text>
568 <answer>
569 <text>b</text>
570 </answer>
571 </subquestion>
572 <subquestion>
573 <text>C</text>
574 <answer>
575 <text>c</text>
576 </answer>
577 </subquestion>
578 <subquestion>
579 <text></text>
580 <answer>
581 <text>d</text>
582 </answer>
583 </subquestion>
584 <hint>
585 <text>Hint 1</text>
586 <shownumcorrect />
587 </hint>
588 <hint>
589 <text></text>
590 <shownumcorrect />
591 <clearwrong />
592 </hint>
dcd4464e
EC
593 <tags>
594 <tag><text>tagMatching</text></tag>
595 <tag><text>tagTest</text></tag>
596 </tags>
603bd001
PS
597 </question>';
598 $xmldata = xmlize($xml);
599
600 $importer = new qformat_xml();
601 $q = $importer->import_match($xmldata['question']);
602
603 $expectedq = new stdClass();
604 $expectedq->qtype = 'match';
605 $expectedq->name = 'Matching question';
606 $expectedq->questiontext = 'Match the upper and lower case letters.';
607 $expectedq->questiontextformat = FORMAT_HTML;
608 $expectedq->correctfeedback = array('text' => 'Well done.',
2387d1cd 609 'format' => FORMAT_HTML);
603bd001 610 $expectedq->partiallycorrectfeedback = array('text' => 'Not entirely.',
2387d1cd 611 'format' => FORMAT_HTML);
603bd001
PS
612 $expectedq->shownumcorrect = false;
613 $expectedq->incorrectfeedback = array('text' => 'Completely wrong!',
2387d1cd 614 'format' => FORMAT_HTML);
603bd001
PS
615 $expectedq->generalfeedback = 'The answer is A -> a, B -> b and C -> c.';
616 $expectedq->generalfeedbackformat = FORMAT_HTML;
617 $expectedq->defaultmark = 1;
618 $expectedq->length = 1;
619 $expectedq->penalty = 0.3333333;
620 $expectedq->shuffleanswers = 0;
621 $expectedq->subquestions = array(
2387d1cd
JMV
622 array('text' => 'A', 'format' => FORMAT_HTML),
623 array('text' => 'B', 'format' => FORMAT_HTML),
624 array('text' => 'C', 'format' => FORMAT_HTML),
625 array('text' => '', 'format' => FORMAT_HTML));
603bd001
PS
626 $expectedq->subanswers = array('a', 'b', 'c', 'd');
627 $expectedq->hint = array(
2387d1cd
JMV
628 array('text' => 'Hint 1', 'format' => FORMAT_HTML),
629 array('text' => '', 'format' => FORMAT_HTML),
603bd001
PS
630 );
631 $expectedq->hintshownumcorrect = array(true, true);
632 $expectedq->hintclearwrong = array(false, true);
dcd4464e 633 $expectedq->tags = array('tagMatching', 'tagTest');
603bd001
PS
634
635 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
636 }
637
638 public function test_export_match() {
639 $qdata = new stdClass();
640 $qdata->id = 123;
1796eb18 641 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
642 $qdata->qtype = 'match';
643 $qdata->name = 'Matching question';
644 $qdata->questiontext = 'Match the upper and lower case letters.';
645 $qdata->questiontextformat = FORMAT_HTML;
646 $qdata->generalfeedback = 'The answer is A -> a, B -> b and C -> c.';
647 $qdata->generalfeedbackformat = FORMAT_HTML;
648 $qdata->defaultmark = 1;
649 $qdata->length = 1;
650 $qdata->penalty = 0.3333333;
651 $qdata->hidden = 0;
652
653 $qdata->options = new stdClass();
654 $qdata->options->shuffleanswers = 1;
655 $qdata->options->correctfeedback = 'Well done.';
656 $qdata->options->correctfeedbackformat = FORMAT_HTML;
657 $qdata->options->partiallycorrectfeedback = 'Not entirely.';
658 $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;
659 $qdata->options->shownumcorrect = false;
660 $qdata->options->incorrectfeedback = 'Completely wrong!';
661 $qdata->options->incorrectfeedbackformat = FORMAT_HTML;
662
663 $subq1 = new stdClass();
664 $subq1->id = -4;
665 $subq1->questiontext = 'A';
666 $subq1->questiontextformat = FORMAT_HTML;
667 $subq1->answertext = 'a';
668
669 $subq2 = new stdClass();
670 $subq2->id = -3;
671 $subq2->questiontext = 'B';
672 $subq2->questiontextformat = FORMAT_HTML;
673 $subq2->answertext = 'b';
674
675 $subq3 = new stdClass();
676 $subq3->id = -2;
677 $subq3->questiontext = 'C';
678 $subq3->questiontextformat = FORMAT_HTML;
679 $subq3->answertext = 'c';
680
681 $subq4 = new stdClass();
682 $subq4->id = -1;
683 $subq4->questiontext = '';
684 $subq4->questiontextformat = FORMAT_HTML;
685 $subq4->answertext = 'd';
686
687 $qdata->options->subquestions = array(
688 $subq1, $subq2, $subq3, $subq4);
689
690 $qdata->hints = array(
691 new question_hint_with_parts(0, 'Hint 1', FORMAT_HTML, true, false),
692 new question_hint_with_parts(0, '', FORMAT_HTML, true, true),
693 );
694
695 $exporter = new qformat_xml();
696 $xml = $exporter->writequestion($qdata);
697
698 $expectedxml = '<!-- question: 123 -->
699 <question type="matching">
700 <name>
701 <text>Matching question</text>
702 </name>
703 <questiontext format="html">
704 <text>Match the upper and lower case letters.</text>
705 </questiontext>
706 <generalfeedback format="html">
707 <text><![CDATA[The answer is A -> a, B -> b and C -> c.]]></text>
708 </generalfeedback>
709 <defaultgrade>1</defaultgrade>
710 <penalty>0.3333333</penalty>
711 <hidden>0</hidden>
712 <shuffleanswers>true</shuffleanswers>
713 <correctfeedback format="html">
714 <text>Well done.</text>
715 </correctfeedback>
716 <partiallycorrectfeedback format="html">
717 <text>Not entirely.</text>
718 </partiallycorrectfeedback>
719 <incorrectfeedback format="html">
720 <text>Completely wrong!</text>
721 </incorrectfeedback>
722 <subquestion format="html">
723 <text>A</text>
724 <answer>
725 <text>a</text>
726 </answer>
727 </subquestion>
728 <subquestion format="html">
729 <text>B</text>
730 <answer>
731 <text>b</text>
732 </answer>
733 </subquestion>
734 <subquestion format="html">
735 <text>C</text>
736 <answer>
737 <text>c</text>
738 </answer>
739 </subquestion>
740 <subquestion format="html">
741 <text></text>
742 <answer>
743 <text>d</text>
744 </answer>
745 </subquestion>
746 <hint format="html">
747 <text>Hint 1</text>
748 <shownumcorrect/>
749 </hint>
750 <hint format="html">
751 <text></text>
752 <shownumcorrect/>
753 <clearwrong/>
754 </hint>
755 </question>
756';
757
758 $this->assert_same_xml($expectedxml, $xml);
759 }
760
761 public function test_import_multichoice_19() {
762 $xml = ' <question type="multichoice">
763 <name>
764 <text>Multiple choice question</text>
765 </name>
766 <questiontext format="html">
767 <text>Which are the even numbers?</text>
768 </questiontext>
769 <generalfeedback>
770 <text>The even numbers are 2 and 4.</text>
771 </generalfeedback>
772 <defaultgrade>2</defaultgrade>
773 <penalty>0.3333333</penalty>
774 <hidden>0</hidden>
775 <single>false</single>
776 <shuffleanswers>false</shuffleanswers>
777 <answernumbering>abc</answernumbering>
778 <correctfeedback>
779 <text><![CDATA[<p>Your answer is correct.</p>]]></text>
780 </correctfeedback>
781 <partiallycorrectfeedback>
782 <text><![CDATA[<p>Your answer is partially correct.</p>]]></text>
783 </partiallycorrectfeedback>
784 <incorrectfeedback>
785 <text><![CDATA[<p>Your answer is incorrect.</p>]]></text>
786 </incorrectfeedback>
787 <shownumcorrect/>
788 <answer fraction="0">
789 <text>1</text>
790 <feedback>
791 <text></text>
792 </feedback>
793 </answer>
794 <answer fraction="100">
795 <text>2</text>
796 <feedback>
797 <text></text>
798 </feedback>
799 </answer>
800 <answer fraction="0">
801 <text>3</text>
802 <feedback>
803 <text></text>
804 </feedback>
805 </answer>
806 <answer fraction="100">
807 <text>4</text>
808 <feedback>
809 <text></text>
810 </feedback>
811 </answer>
812 <hint>
813 <text>Hint 1.</text>
814 </hint>
815 <hint>
816 <text>Hint 2.</text>
817 </hint>
818 </question>';
819 $xmldata = xmlize($xml);
820
821 $importer = new qformat_xml();
822 $q = $importer->import_multichoice($xmldata['question']);
823
824 $expectedq = new stdClass();
825 $expectedq->qtype = 'multichoice';
826 $expectedq->name = 'Multiple choice question';
827 $expectedq->questiontext = 'Which are the even numbers?';
828 $expectedq->questiontextformat = FORMAT_HTML;
829 $expectedq->correctfeedback = array(
830 'text' => '<p>Your answer is correct.</p>',
2387d1cd 831 'format' => FORMAT_HTML);
603bd001
PS
832 $expectedq->shownumcorrect = false;
833 $expectedq->partiallycorrectfeedback = array(
834 'text' => '<p>Your answer is partially correct.</p>',
2387d1cd 835 'format' => FORMAT_HTML);
603bd001
PS
836 $expectedq->shownumcorrect = true;
837 $expectedq->incorrectfeedback = array(
838 'text' => '<p>Your answer is incorrect.</p>',
2387d1cd 839 'format' => FORMAT_HTML);
603bd001
PS
840 $expectedq->generalfeedback = 'The even numbers are 2 and 4.';
841 $expectedq->defaultmark = 2;
842 $expectedq->length = 1;
843 $expectedq->penalty = 0.3333333;
844 $expectedq->shuffleanswers = 0;
845 $expectedq->single = false;
846
847 $expectedq->answer = array(
2387d1cd
JMV
848 array('text' => '1', 'format' => FORMAT_HTML),
849 array('text' => '2', 'format' => FORMAT_HTML),
850 array('text' => '3', 'format' => FORMAT_HTML),
851 array('text' => '4', 'format' => FORMAT_HTML));
603bd001
PS
852 $expectedq->fraction = array(0, 1, 0, 1);
853 $expectedq->feedback = array(
2387d1cd
JMV
854 array('text' => '', 'format' => FORMAT_HTML),
855 array('text' => '', 'format' => FORMAT_HTML),
856 array('text' => '', 'format' => FORMAT_HTML),
857 array('text' => '', 'format' => FORMAT_HTML));
603bd001
PS
858
859 $expectedq->hint = array(
2387d1cd
JMV
860 array('text' => 'Hint 1.', 'format' => FORMAT_HTML),
861 array('text' => 'Hint 2.', 'format' => FORMAT_HTML),
603bd001
PS
862 );
863 $expectedq->hintshownumcorrect = array(false, false);
864 $expectedq->hintclearwrong = array(false, false);
865
866 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
867 }
868
869 public function test_export_multichoice() {
870 $qdata = new stdClass();
871 $qdata->id = 123;
1796eb18 872 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
873 $qdata->qtype = 'multichoice';
874 $qdata->name = 'Multiple choice question';
875 $qdata->questiontext = 'Which are the even numbers?';
876 $qdata->questiontextformat = FORMAT_HTML;
877 $qdata->generalfeedback = 'The even numbers are 2 and 4.';
878 $qdata->generalfeedbackformat = FORMAT_HTML;
879 $qdata->defaultmark = 2;
880 $qdata->length = 1;
881 $qdata->penalty = 0.3333333;
882 $qdata->hidden = 0;
883
884 $qdata->options = new stdClass();
885 $qdata->options->single = 0;
886 $qdata->options->shuffleanswers = 0;
887 $qdata->options->answernumbering = 'abc';
888 $qdata->options->correctfeedback = '<p>Your answer is correct.</p>';
889 $qdata->options->correctfeedbackformat = FORMAT_HTML;
890 $qdata->options->partiallycorrectfeedback = '<p>Your answer is partially correct.</p>';
891 $qdata->options->partiallycorrectfeedbackformat = FORMAT_HTML;
892 $qdata->options->shownumcorrect = 1;
893 $qdata->options->incorrectfeedback = '<p>Your answer is incorrect.</p>';
894 $qdata->options->incorrectfeedbackformat = FORMAT_HTML;
895
896 $qdata->options->answers = array(
897 13 => new question_answer(13, '1', 0, '', FORMAT_HTML),
898 14 => new question_answer(14, '2', 1, '', FORMAT_HTML),
899 15 => new question_answer(15, '3', 0, '', FORMAT_HTML),
900 16 => new question_answer(16, '4', 1, '', FORMAT_HTML),
901 );
902
903 $qdata->hints = array(
904 new question_hint_with_parts(0, 'Hint 1.', FORMAT_HTML, false, false),
905 new question_hint_with_parts(0, 'Hint 2.', FORMAT_HTML, false, false),
906 );
907
908 $exporter = new qformat_xml();
909 $xml = $exporter->writequestion($qdata);
910
911 $expectedxml = '<!-- question: 123 -->
912 <question type="multichoice">
913 <name>
914 <text>Multiple choice question</text>
915 </name>
916 <questiontext format="html">
917 <text>Which are the even numbers?</text>
918 </questiontext>
919 <generalfeedback format="html">
920 <text>The even numbers are 2 and 4.</text>
921 </generalfeedback>
922 <defaultgrade>2</defaultgrade>
923 <penalty>0.3333333</penalty>
924 <hidden>0</hidden>
925 <single>false</single>
926 <shuffleanswers>false</shuffleanswers>
927 <answernumbering>abc</answernumbering>
928 <correctfeedback format="html">
929 <text><![CDATA[<p>Your answer is correct.</p>]]></text>
930 </correctfeedback>
931 <partiallycorrectfeedback format="html">
932 <text><![CDATA[<p>Your answer is partially correct.</p>]]></text>
933 </partiallycorrectfeedback>
934 <incorrectfeedback format="html">
935 <text><![CDATA[<p>Your answer is incorrect.</p>]]></text>
936 </incorrectfeedback>
937 <shownumcorrect/>
938 <answer fraction="0" format="plain_text">
939 <text>1</text>
940 <feedback format="html">
941 <text></text>
942 </feedback>
943 </answer>
944 <answer fraction="100" format="plain_text">
945 <text>2</text>
946 <feedback format="html">
947 <text></text>
948 </feedback>
949 </answer>
950 <answer fraction="0" format="plain_text">
951 <text>3</text>
952 <feedback format="html">
953 <text></text>
954 </feedback>
955 </answer>
956 <answer fraction="100" format="plain_text">
957 <text>4</text>
958 <feedback format="html">
959 <text></text>
960 </feedback>
961 </answer>
962 <hint format="html">
963 <text>Hint 1.</text>
964 </hint>
965 <hint format="html">
966 <text>Hint 2.</text>
967 </hint>
968 </question>
969';
970
971 $this->assert_same_xml($expectedxml, $xml);
972 }
973
974 public function test_import_numerical_19() {
975 $xml = ' <question type="numerical">
976 <name>
977 <text>Numerical question</text>
978 </name>
979 <questiontext format="html">
980 <text>What is the answer?</text>
981 </questiontext>
982 <generalfeedback>
983 <text>General feedback: Think Hitch-hikers guide to the Galaxy.</text>
984 </generalfeedback>
985 <defaultgrade>1</defaultgrade>
986 <penalty>0.1</penalty>
987 <hidden>0</hidden>
988 <answer fraction="100">
989 <text>42</text>
990 <feedback>
991 <text>Well done!</text>
992 </feedback>
993 <tolerance>0.001</tolerance>
994 </answer>
995 <answer fraction="0">
996 <text>13</text>
997 <feedback>
998 <text>What were you thinking?!</text>
999 </feedback>
1000 <tolerance>1</tolerance>
1001 </answer>
1002 <answer fraction="0">
1003 <text>*</text>
1004 <feedback>
1005 <text>Completely wrong.</text>
1006 </feedback>
1007 <tolerance></tolerance>
1008 </answer>
1009 </question>';
1010 $xmldata = xmlize($xml);
1011
1012 $importer = new qformat_xml();
1013 $q = $importer->import_numerical($xmldata['question']);
1014
1015 $expectedq = new stdClass();
1016 $expectedq->qtype = 'numerical';
1017 $expectedq->name = 'Numerical question';
1018 $expectedq->questiontext = 'What is the answer?';
1019 $expectedq->questiontextformat = FORMAT_HTML;
1020 $expectedq->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.';
1021 $expectedq->generalfeedbackformat = FORMAT_HTML;
1022 $expectedq->defaultmark = 1;
1023 $expectedq->length = 1;
1024 $expectedq->penalty = 0.1;
1025
1026 $expectedq->answer = array('42', '13', '*');
1027 $expectedq->fraction = array(1, 0, 0);
1028 $expectedq->feedback = array(
1029 array('text' => 'Well done!',
2387d1cd 1030 'format' => FORMAT_HTML),
603bd001 1031 array('text' => 'What were you thinking?!',
2387d1cd 1032 'format' => FORMAT_HTML),
603bd001 1033 array('text' => 'Completely wrong.',
2387d1cd 1034 'format' => FORMAT_HTML));
603bd001
PS
1035 $expectedq->tolerance = array(0.001, 1, 0);
1036
1037 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
1038 }
1039
1040 public function test_export_numerical() {
1041 question_bank::load_question_definition_classes('numerical');
1042
1043 $qdata = new stdClass();
1044 $qdata->id = 123;
1796eb18 1045 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
1046 $qdata->qtype = 'numerical';
1047 $qdata->name = 'Numerical question';
1048 $qdata->questiontext = 'What is the answer?';
1049 $qdata->questiontextformat = FORMAT_HTML;
1050 $qdata->generalfeedback = 'General feedback: Think Hitch-hikers guide to the Galaxy.';
1051 $qdata->generalfeedbackformat = FORMAT_HTML;
1052 $qdata->defaultmark = 1;
1053 $qdata->length = 1;
1054 $qdata->penalty = 0.1;
1055 $qdata->hidden = 0;
1056
1057 $qdata->options = new stdClass();
1058 $qdata->options->answers = array(
1059 13 => new qtype_numerical_answer(13, '42', 1, 'Well done!',
1060 FORMAT_HTML, 0.001),
1061 14 => new qtype_numerical_answer(14, '13', 0, 'What were you thinking?!',
1062 FORMAT_HTML, 1),
1063 15 => new qtype_numerical_answer(15, '*', 0, 'Completely wrong.',
1064 FORMAT_HTML, ''),
1065 );
1066
1067 $qdata->options->units = array();
1068
1069 $exporter = new qformat_xml();
1070 $xml = $exporter->writequestion($qdata);
1071
1072 $expectedxml = '<!-- question: 123 -->
1073 <question type="numerical">
1074 <name>
1075 <text>Numerical question</text>
1076 </name>
1077 <questiontext format="html">
1078 <text>What is the answer?</text>
1079 </questiontext>
1080 <generalfeedback format="html">
1081 <text>General feedback: Think Hitch-hikers guide to the Galaxy.</text>
1082 </generalfeedback>
1083 <defaultgrade>1</defaultgrade>
1084 <penalty>0.1</penalty>
1085 <hidden>0</hidden>
1086 <answer fraction="100" format="plain_text">
1087 <text>42</text>
1088 <feedback format="html">
1089 <text>Well done!</text>
1090 </feedback>
1091 <tolerance>0.001</tolerance>
1092 </answer>
1093 <answer fraction="0" format="plain_text">
1094 <text>13</text>
1095 <feedback format="html">
1096 <text>What were you thinking?!</text>
1097 </feedback>
1098 <tolerance>1</tolerance>
1099 </answer>
1100 <answer fraction="0" format="plain_text">
1101 <text>*</text>
1102 <feedback format="html">
1103 <text>Completely wrong.</text>
1104 </feedback>
1105 <tolerance>0</tolerance>
1106 </answer>
1107 </question>
1108';
1109
1110 $this->assert_same_xml($expectedxml, $xml);
1111 }
1112
1113 public function test_import_shortanswer_19() {
1114 $xml = ' <question type="shortanswer">
1115 <name>
1116 <text>Short answer question</text>
1117 </name>
1118 <questiontext format="html">
1119 <text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text>
1120 </questiontext>
1121 <generalfeedback>
1122 <text>The answer is Beta.</text>
1123 </generalfeedback>
1124 <defaultgrade>1</defaultgrade>
1125 <penalty>0.3333333</penalty>
1126 <hidden>0</hidden>
1127 <usecase>0</usecase>
1128 <answer fraction="100" format="plain_text">
1129 <text>Beta</text>
1130 <feedback>
1131 <text>Well done!</text>
1132 </feedback>
1133 </answer>
1134 <answer fraction="0" format="plain_text">
1135 <text>*</text>
1136 <feedback>
1137 <text>Doh!</text>
1138 </feedback>
1139 </answer>
1140 <hint>
1141 <text>Hint 1</text>
1142 </hint>
1143 <hint>
1144 <text>Hint 2</text>
1145 </hint>
1146 </question>';
1147 $xmldata = xmlize($xml);
1148
1149 $importer = new qformat_xml();
1150 $q = $importer->import_shortanswer($xmldata['question']);
1151
1152 $expectedq = new stdClass();
1153 $expectedq->qtype = 'shortanswer';
1154 $expectedq->name = 'Short answer question';
1155 $expectedq->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.';
1156 $expectedq->questiontextformat = FORMAT_HTML;
1157 $expectedq->generalfeedback = 'The answer is Beta.';
1158 $expectedq->usecase = false;
1159 $expectedq->defaultmark = 1;
1160 $expectedq->length = 1;
1161 $expectedq->penalty = 0.3333333;
1162
1163 $expectedq->answer = array('Beta', '*');
1164 $expectedq->fraction = array(1, 0);
1165 $expectedq->feedback = array(
2387d1cd
JMV
1166 array('text' => 'Well done!', 'format' => FORMAT_HTML),
1167 array('text' => 'Doh!', 'format' => FORMAT_HTML));
603bd001
PS
1168
1169 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
1170 }
1171
1172 public function test_export_shortanswer() {
1173 $qdata = new stdClass();
1174 $qdata->id = 123;
1796eb18 1175 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
1176 $qdata->qtype = 'shortanswer';
1177 $qdata->name = 'Short answer question';
1178 $qdata->questiontext = 'Fill in the gap in this sequence: Alpha, ________, Gamma.';
1179 $qdata->questiontextformat = FORMAT_HTML;
1180 $qdata->generalfeedback = 'The answer is Beta.';
1181 $qdata->generalfeedbackformat = FORMAT_HTML;
1182 $qdata->defaultmark = 1;
1183 $qdata->length = 1;
1184 $qdata->penalty = 0.3333333;
1185 $qdata->hidden = 0;
1186
1187 $qdata->options = new stdClass();
1188 $qdata->options->usecase = 0;
1189
1190 $qdata->options->answers = array(
1191 13 => new question_answer(13, 'Beta', 1, 'Well done!', FORMAT_HTML),
1192 14 => new question_answer(14, '*', 0, 'Doh!', FORMAT_HTML),
1193 );
1194
1195 $qdata->hints = array(
1196 new question_hint(0, 'Hint 1', FORMAT_HTML),
1197 new question_hint(0, 'Hint 2', FORMAT_HTML),
1198 );
1199
1200 $exporter = new qformat_xml();
1201 $xml = $exporter->writequestion($qdata);
1202
1203 $expectedxml = '<!-- question: 123 -->
1204 <question type="shortanswer">
1205 <name>
1206 <text>Short answer question</text>
1207 </name>
1208 <questiontext format="html">
1209 <text>Fill in the gap in this sequence: Alpha, ________, Gamma.</text>
1210 </questiontext>
1211 <generalfeedback format="html">
1212 <text>The answer is Beta.</text>
1213 </generalfeedback>
1214 <defaultgrade>1</defaultgrade>
1215 <penalty>0.3333333</penalty>
1216 <hidden>0</hidden>
1217 <usecase>0</usecase>
1218 <answer fraction="100" format="plain_text">
1219 <text>Beta</text>
1220 <feedback format="html">
1221 <text>Well done!</text>
1222 </feedback>
1223 </answer>
1224 <answer fraction="0" format="plain_text">
1225 <text>*</text>
1226 <feedback format="html">
1227 <text>Doh!</text>
1228 </feedback>
1229 </answer>
1230 <hint format="html">
1231 <text>Hint 1</text>
1232 </hint>
1233 <hint format="html">
1234 <text>Hint 2</text>
1235 </hint>
1236 </question>
1237';
1238
1239 $this->assert_same_xml($expectedxml, $xml);
1240 }
1241
1242 public function test_import_truefalse_19() {
1243 $xml = ' <question type="truefalse">
1244 <name>
1245 <text>True false question</text>
1246 </name>
1247 <questiontext format="html">
1248 <text>The answer is true.</text>
1249 </questiontext>
1250 <generalfeedback>
1251 <text>General feedback: You should have chosen true.</text>
1252 </generalfeedback>
1253 <defaultgrade>1</defaultgrade>
1254 <penalty>1</penalty>
1255 <hidden>0</hidden>
1256 <answer fraction="100">
1257 <text>true</text>
1258 <feedback>
1259 <text>Well done!</text>
1260 </feedback>
1261 </answer>
1262 <answer fraction="0">
1263 <text>false</text>
1264 <feedback>
1265 <text>Doh!</text>
1266 </feedback>
1267 </answer>
1268 </question>';
1269 $xmldata = xmlize($xml);
1270
1271 $importer = new qformat_xml();
1272 $q = $importer->import_truefalse($xmldata['question']);
1273
1274 $expectedq = new stdClass();
1275 $expectedq->qtype = 'truefalse';
1276 $expectedq->name = 'True false question';
1277 $expectedq->questiontext = 'The answer is true.';
1278 $expectedq->questiontextformat = FORMAT_HTML;
1279 $expectedq->generalfeedback = 'General feedback: You should have chosen true.';
1280 $expectedq->defaultmark = 1;
1281 $expectedq->length = 1;
1282 $expectedq->penalty = 1;
1283
1284 $expectedq->feedbacktrue = array('text' => 'Well done!',
2387d1cd 1285 'format' => FORMAT_HTML);
603bd001 1286 $expectedq->feedbackfalse = array('text' => 'Doh!',
2387d1cd 1287 'format' => FORMAT_HTML);
603bd001
PS
1288 $expectedq->correctanswer = true;
1289
1290 $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
1291 }
1292
1293 public function test_export_truefalse() {
1294 $qdata = new stdClass();
1295 $qdata->id = 12;
1796eb18 1296 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
1297 $qdata->qtype = 'truefalse';
1298 $qdata->name = 'True false question';
1299 $qdata->questiontext = 'The answer is true.';
1300 $qdata->questiontextformat = FORMAT_HTML;
1301 $qdata->generalfeedback = 'General feedback: You should have chosen true.';
1302 $qdata->generalfeedbackformat = FORMAT_HTML;
1303 $qdata->defaultmark = 1;
1304 $qdata->length = 1;
1305 $qdata->penalty = 1;
1306 $qdata->hidden = 0;
1307
1308 $qdata->options = new stdClass();
1309 $qdata->options->answers = array(
1310 1 => new question_answer(1, 'True', 1, 'Well done!', FORMAT_HTML),
1311 2 => new question_answer(2, 'False', 0, 'Doh!', FORMAT_HTML),
1312 );
1313 $qdata->options->trueanswer = 1;
1314 $qdata->options->falseanswer = 2;
1315
1316 $exporter = new qformat_xml();
1317 $xml = $exporter->writequestion($qdata);
1318
1319 $expectedxml = '<!-- question: 12 -->
1320 <question type="truefalse">
1321 <name>
1322 <text>True false question</text>
1323 </name>
1324 <questiontext format="html">
1325 <text>The answer is true.</text>
1326 </questiontext>
1327 <generalfeedback format="html">
1328 <text>General feedback: You should have chosen true.</text>
1329 </generalfeedback>
1330 <defaultgrade>1</defaultgrade>
1331 <penalty>1</penalty>
1332 <hidden>0</hidden>
1333 <answer fraction="100" format="plain_text">
1334 <text>true</text>
1335 <feedback format="html">
1336 <text>Well done!</text>
1337 </feedback>
1338 </answer>
1339 <answer fraction="0" format="plain_text">
1340 <text>false</text>
1341 <feedback format="html">
1342 <text>Doh!</text>
1343 </feedback>
1344 </answer>
1345 </question>
1346';
1347
1348 $this->assert_same_xml($expectedxml, $xml);
1349 }
1350
1351 public function test_import_multianswer() {
1352 $xml = ' <question type="cloze">
1353 <name>
1354 <text>Simple multianswer</text>
1355 </name>
1356 <questiontext format="html">
1357 <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>
1358 </questiontext>
1359 <generalfeedback format="html">
1360 <text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".]]></text>
1361 </generalfeedback>
1362 <penalty>0.5</penalty>
1363 <hidden>0</hidden>
1364 <hint format="html">
1365 <text>Hint 1</text>
1366 </hint>
1367 <hint format="html">
1368 <text>Hint 2</text>
1369 </hint>
dcd4464e
EC
1370 <tags>
1371 <tag><text>tagCloze</text></tag>
1372 <tag><text>tagTest</text></tag>
1373 </tags>
603bd001
PS
1374 </question>
1375';
1376 $xmldata = xmlize($xml);
1377
1378 $importer = new qformat_xml();
1379 $q = $importer->import_multianswer($xmldata['question']);
1380
1381 // Annoyingly, import works in a weird way (it duplicates code, rather
1382 // than just calling save_question) so we cannot use
1383 // test_question_maker::get_question_form_data('multianswer', 'twosubq').
1384 $expectedqa = new stdClass();
1385 $expectedqa->name = 'Simple multianswer';
1386 $expectedqa->qtype = 'multianswer';
1387 $expectedqa->questiontext = 'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';
d2fd7262
JMV
1388 $expectedqa->generalfeedback =
1389 'General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".';
603bd001
PS
1390 $expectedqa->defaultmark = 2;
1391 $expectedqa->penalty = 0.5;
1392
1393 $expectedqa->hint = array(
2387d1cd
JMV
1394 array('text' => 'Hint 1', 'format' => FORMAT_HTML),
1395 array('text' => 'Hint 2', 'format' => FORMAT_HTML),
603bd001
PS
1396 );
1397
1398 $sa = new stdClass();
1399
1400 $sa->questiontext = array('text' => '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer}',
1401 'format' => FORMAT_HTML, 'itemid' => null);
1402 $sa->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
1403 $sa->defaultmark = 1.0;
1404 $sa->qtype = 'shortanswer';
1405 $sa->usecase = 0;
1406
1407 $sa->answer = array('Dog', 'Owl', '*');
1408 $sa->fraction = array(0, 1, 0);
1409 $sa->feedback = array(
1410 array('text' => 'Wrong, silly!', 'format' => FORMAT_HTML, 'itemid' => null),
1411 array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),
1412 array('text' => 'Wrong answer', 'format' => FORMAT_HTML, 'itemid' => null),
1413 );
1414
1415 $mc = new stdClass();
1416
1417 $mc->generalfeedback = '';
1418 $mc->questiontext = array('text' => '{1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~' .
1419 'Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}',
1420 'format' => FORMAT_HTML, 'itemid' => null);
1421 $mc->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
1422 $mc->defaultmark = 1.0;
1423 $mc->qtype = 'multichoice';
1424
1425 $mc->layout = 0;
1426 $mc->single = 1;
bd156853 1427 $mc->shuffleanswers = 0;
603bd001
PS
1428 $mc->correctfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
1429 $mc->partiallycorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
1430 $mc->incorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
1431 $mc->answernumbering = 0;
1432
1433 $mc->answer = array(
1434 array('text' => 'Bow-wow', 'format' => FORMAT_HTML, 'itemid' => null),
1435 array('text' => 'Wiggly worm', 'format' => FORMAT_HTML, 'itemid' => null),
1436 array('text' => 'Pussy-cat', 'format' => FORMAT_HTML, 'itemid' => null),
1437 );
1438 $mc->fraction = array(0, 0, 1);
1439 $mc->feedback = array(
1440 array('text' => 'You seem to have a dog obsessions!', 'format' => FORMAT_HTML, 'itemid' => null),
1441 array('text' => 'Now you are just being ridiculous!', 'format' => FORMAT_HTML, 'itemid' => null),
1442 array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),
1443 );
1444
1445 $expectedqa->options = new stdClass();
1446 $expectedqa->options->questions = array(
1447 1 => $sa,
1448 2 => $mc,
1449 );
dcd4464e 1450 $expectedqa->tags = array('tagCloze', 'tagTest');
603bd001
PS
1451
1452 $this->assertEquals($expectedqa->hint, $q->hint);
1453 $this->assertEquals($expectedqa->options->questions[1], $q->options->questions[1]);
1454 $this->assertEquals($expectedqa->options->questions[2], $q->options->questions[2]);
1455 $this->assert(new question_check_specified_fields_expectation($expectedqa), $q);
1456 }
1457
1458 public function test_export_multianswer() {
1459 $qdata = test_question_maker::get_question_data('multianswer', 'twosubq');
1796eb18 1460 $qdata->contextid = \context_system::instance()->id;
603bd001
PS
1461 $exporter = new qformat_xml();
1462 $xml = $exporter->writequestion($qdata);
1463
1464 $expectedxml = '<!-- question: 0 -->
1465 <question type="cloze">
1466 <name>
1467 <text>Simple multianswer</text>
1468 </name>
1469 <questiontext format="html">
1470 <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>
1471 </questiontext>
1472 <generalfeedback format="html">
1473 <text><![CDATA[General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea]]></text>
1474 </generalfeedback>
1475 <penalty>0.3333333</penalty>
1476 <hidden>0</hidden>
1477 <hint format="html">
1478 <text>Hint 1</text>
1479 </hint>
1480 <hint format="html">
1481 <text>Hint 2</text>
1482 </hint>
1483 </question>
1484';
1485
1486 $this->assert_same_xml($expectedxml, $xml);
1487 }
2387d1cd 1488
5c0b5ba5
TH
1489 public function test_export_multianswer_withdollars() {
1490 $qdata = test_question_maker::get_question_data('multianswer', 'dollarsigns');
1796eb18 1491 $qdata->contextid = \context_system::instance()->id;
5c0b5ba5
TH
1492 $exporter = new qformat_xml();
1493 $xml = $exporter->writequestion($qdata);
1494
1495 $expectedxml = '<!-- question: 0 -->
1496 <question type="cloze">
1497 <name>
1498 <text>Multianswer with $s</text>
1499 </name>
1500 <questiontext format="html">
1501 <text>Which is the right order? {1:MULTICHOICE:=y,y,$3~$3,y,y}</text>
1502 </questiontext>
1503 <generalfeedback format="html">
1504 <text></text>
1505 </generalfeedback>
1506 <penalty>0.3333333</penalty>
1507 <hidden>0</hidden>
1508 </question>
1509';
1510
1511 $this->assert_same_xml($expectedxml, $xml);
1512 }
1513
2387d1cd
JMV
1514 public function test_import_files_as_draft() {
1515 $this->resetAfterTest();
1516 $this->setAdminUser();
1517
1518 $xml = <<<END
1519<questiontext format="html">
1520 <text><![CDATA[<p><a href="@@PLUGINFILE@@/moodle.txt">This text file</a> contains the word 'Moodle'.</p>]]></text>
1521 <file name="moodle.txt" encoding="base64">TW9vZGxl</file>
1522</questiontext>
1523END;
1524
1525 $textxml = xmlize($xml);
1526 $qo = new stdClass();
1527
1528 $importer = new qformat_xml();
1529 $draftitemid = $importer->import_files_as_draft($textxml['questiontext']['#']['file']);
1530 $files = file_get_drafarea_files($draftitemid);
1531
1532 $this->assertEquals(1, count($files->list));
1533
1534 $file = $files->list[0];
1535 $this->assertEquals('moodle.txt', $file->filename);
1536 $this->assertEquals('/', $file->filepath);
1537 $this->assertEquals(6, $file->size);
1538 }
624ff5ba
JMV
1539
1540 public function test_import_truefalse_wih_files() {
1541 $this->resetAfterTest();
1542 $this->setAdminUser();
1543
1544 $xml = '<question type="truefalse">
1545 <name>
1546 <text>truefalse</text>
1547 </name>
1548 <questiontext format="html">
1549 <text><![CDATA[<p><a href="@@PLUGINFILE@@/myfolder/moodle.txt">This text file</a> contains the word Moodle.</p>]]></text>
1550<file name="moodle.txt" path="/myfolder/" encoding="base64">TW9vZGxl</file>
1551 </questiontext>
1552 <generalfeedback format="html">
1553 <text><![CDATA[<p>For further information, see the documentation about Moodle.</p>]]></text>
1554</generalfeedback>
1555 <defaultgrade>1.0000000</defaultgrade>
1556 <penalty>1.0000000</penalty>
1557 <hidden>0</hidden>
1558 <answer fraction="100" format="moodle_auto_format">
1559 <text>true</text>
1560 <feedback format="html">
1561 <text></text>
1562 </feedback>
1563 </answer>
1564 <answer fraction="0" format="moodle_auto_format">
1565 <text>false</text>
1566 <feedback format="html">
1567 <text></text>
1568 </feedback>
1569 </answer>
1570 </question>';
1571 $xmldata = xmlize($xml);
1572
1573 $importer = new qformat_xml();
1574 $q = $importer->import_truefalse($xmldata['question']);
1575
1576 $draftitemid = $q->questiontextitemid;
1577 $files = file_get_drafarea_files($draftitemid, '/myfolder/');
1578
1579 $this->assertEquals(1, count($files->list));
1580
1581 $file = $files->list[0];
1582 $this->assertEquals('moodle.txt', $file->filename);
1583 $this->assertEquals('/myfolder/', $file->filepath);
1584 $this->assertEquals(6, $file->size);
1585 }
603bd001 1586}