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