MDL-47494 ddimageortext: Fix unit tests for 3.0 compatibility.
[moodle.git] / question / type / ddimageortext / tests / walkthrough_test.php
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/>.
17 /**
18  * Unit tests for the drag-and-drop onto image question type.
19  *
20  * @package   qtype_ddimageortext
21  * @copyright 2010 The Open University
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
30 require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php');
33 /**
34  * Unit tests for the drag-and-drop onto image question type.
35  *
36  * @copyright 2010 The Open University
37  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base {
41     /**
42      * Get an expectation that the output contains an item ready to drag.
43      * @param int $dragitemno the item number.
44      * @param int $choice which choice this is.
45      * @param int $group which drag group it belongs to.
46      * @return question_contains_tag_with_attributes the required expectation.
47      */
48     protected function get_contains_drag_image_home_expectation($dragitemno, $choice, $group) {
49         $class = 'group' . $group;
50         $class .= ' draghome dragitemhomes' . $dragitemno. ' choice'.$choice.' yui3-cssfonts';
52         $expectedattrs = array();
53         $expectedattrs['class'] = $class;
55         return new question_contains_tag_with_attributes('div', $expectedattrs);
56     }
58     public function test_interactive_behaviour() {
60         // Create a drag-and-drop question.
61         $dd = test_question_maker::make_question('ddimageortext');
62         $dd->hints = array(
63             new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false),
64             new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true),
65         );
66         $dd->shufflechoices = false;
67         $this->start_attempt_at_question($dd, 'interactive', 12);
69         // Check the initial state.
70         $this->check_current_state(question_state::$todo);
71         $this->check_current_mark(null);
73         $this->check_current_output(
74             $this->get_contains_drag_image_home_expectation(1, 1, 1),
75             $this->get_contains_drag_image_home_expectation(2, 2, 1),
76             $this->get_contains_drag_image_home_expectation(3, 1, 2),
77             $this->get_contains_drag_image_home_expectation(4, 2, 2),
78             $this->get_contains_hidden_expectation(
79                 $this->quba->get_field_prefix($this->slot) . 'p1'),
80             $this->get_contains_hidden_expectation(
81                 $this->quba->get_field_prefix($this->slot) . 'p2'),
82             $this->get_contains_hidden_expectation(
83                 $this->quba->get_field_prefix($this->slot) . 'p3'),
84             $this->get_contains_hidden_expectation(
85                 $this->quba->get_field_prefix($this->slot) . 'p4'),
86             $this->get_contains_submit_button_expectation(true),
87             $this->get_does_not_contain_feedback_expectation(),
88             $this->get_tries_remaining_expectation(3),
89             $this->get_no_hint_visible_expectation());
91         // Save the wrong answer.
92         $this->process_submission(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1'));
93         // Verify.
94         $this->check_current_state(question_state::$todo);
95         $this->check_current_mark(null);
97         $this->check_current_output(
98             $this->get_contains_drag_image_home_expectation(1, 1, 1),
99             $this->get_contains_drag_image_home_expectation(2, 2, 1),
100             $this->get_contains_drag_image_home_expectation(3, 1, 2),
101             $this->get_contains_drag_image_home_expectation(4, 2, 2),
102             $this->get_contains_hidden_expectation(
103                 $this->quba->get_field_prefix($this->slot) . 'p1', 2),
104             $this->get_contains_hidden_expectation(
105                 $this->quba->get_field_prefix($this->slot) . 'p2', 1),
106             $this->get_contains_hidden_expectation(
107                 $this->quba->get_field_prefix($this->slot) . 'p3', 2),
108             $this->get_contains_hidden_expectation(
109                 $this->quba->get_field_prefix($this->slot) . 'p4', 1),
110             $this->get_contains_submit_button_expectation(true),
111             $this->get_does_not_contain_feedback_expectation(),
112             $this->get_tries_remaining_expectation(3),
113             $this->get_no_hint_visible_expectation());
114         // Submit the wrong answer.
115         $this->process_submission(
116             array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1));
118         // Verify.
119         $this->check_current_state(question_state::$todo);
120         $this->check_current_mark(null);
121         $this->check_current_output(
122             $this->get_contains_drag_image_home_expectation(1, 1, 1),
123             $this->get_contains_drag_image_home_expectation(2, 2, 1),
124             $this->get_contains_drag_image_home_expectation(3, 1, 2),
125             $this->get_contains_drag_image_home_expectation(4, 2, 2),
126             $this->get_contains_hidden_expectation(
127                 $this->quba->get_field_prefix($this->slot) . 'p1', 2),
128             $this->get_contains_hidden_expectation(
129                 $this->quba->get_field_prefix($this->slot) . 'p2', 1),
130             $this->get_contains_hidden_expectation(
131                 $this->quba->get_field_prefix($this->slot) . 'p3', 2),
132             $this->get_contains_hidden_expectation(
133                 $this->quba->get_field_prefix($this->slot) . 'p4', 1),
134             $this->get_contains_try_again_button_expectation(true),
135             $this->get_contains_hint_expectation('This is the first hint'));
137         // Do try again.
138         $this->process_submission(array('-tryagain' => 1));
140         // Verify.
141         $this->check_current_state(question_state::$todo);
142         $this->check_current_mark(null);
144         $this->check_current_output(
145             $this->get_contains_drag_image_home_expectation(1, 1, 1),
146             $this->get_contains_drag_image_home_expectation(2, 2, 1),
147             $this->get_contains_drag_image_home_expectation(3, 1, 2),
148             $this->get_contains_drag_image_home_expectation(4, 2, 2),
149             $this->get_contains_hidden_expectation(
150                 $this->quba->get_field_prefix($this->slot) . 'p1', '2'),
151             $this->get_contains_hidden_expectation(
152                 $this->quba->get_field_prefix($this->slot) . 'p2', '1'),
153             $this->get_contains_hidden_expectation(
154                 $this->quba->get_field_prefix($this->slot) . 'p3', '2'),
155             $this->get_contains_hidden_expectation(
156                 $this->quba->get_field_prefix($this->slot) . 'p4', '1'),
157             $this->get_contains_submit_button_expectation(true),
158             $this->get_does_not_contain_correctness_expectation(),
159             $this->get_does_not_contain_feedback_expectation(),
160             $this->get_tries_remaining_expectation(2),
161             $this->get_no_hint_visible_expectation());
163         // Submit the right answer.
164         $this->process_submission(
165             array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1));
167         // Verify.
168         $this->check_current_state(question_state::$gradedright);
169         $this->check_current_mark(8);
170         $this->check_current_output(
171             $this->get_contains_drag_image_home_expectation(1, 1, 1),
172             $this->get_contains_drag_image_home_expectation(2, 2, 1),
173             $this->get_contains_drag_image_home_expectation(3, 1, 2),
174             $this->get_contains_drag_image_home_expectation(4, 2, 2),
175             $this->get_contains_hidden_expectation(
176                 $this->quba->get_field_prefix($this->slot) . 'p1', '1'),
177             $this->get_contains_hidden_expectation(
178                 $this->quba->get_field_prefix($this->slot) . 'p2', '2'),
179             $this->get_contains_hidden_expectation(
180                 $this->quba->get_field_prefix($this->slot) . 'p3', '1'),
181             $this->get_contains_hidden_expectation(
182                 $this->quba->get_field_prefix($this->slot) . 'p4', '2'),
183             $this->get_contains_submit_button_expectation(false),
184             $this->get_contains_correct_expectation(),
185             $this->get_no_hint_visible_expectation());
187         // Check regrading does not mess anything up.
188         $this->quba->regrade_all_questions();
190         // Verify.
191         $this->check_current_state(question_state::$gradedright);
192         $this->check_current_mark(8);
193     }
195     public function test_deferred_feedback() {
197         // Create a drag-and-drop question.
198         $dd = test_question_maker::make_question('ddimageortext');
199         $dd->shufflechoices = false;
200         $this->start_attempt_at_question($dd, 'deferredfeedback', 12);
202         // Check the initial state.
203         $this->check_current_state(question_state::$todo);
204         $this->check_current_mark(null);
206         $this->check_current_output(
207             $this->get_contains_drag_image_home_expectation(1, 1, 1),
208             $this->get_contains_drag_image_home_expectation(2, 2, 1),
209             $this->get_contains_drag_image_home_expectation(3, 1, 2),
210             $this->get_contains_drag_image_home_expectation(4, 2, 2),
211             $this->get_contains_hidden_expectation(
212                 $this->quba->get_field_prefix($this->slot) . 'p1'),
213             $this->get_contains_hidden_expectation(
214                 $this->quba->get_field_prefix($this->slot) . 'p2'),
215             $this->get_contains_hidden_expectation(
216                 $this->quba->get_field_prefix($this->slot) . 'p3'),
217             $this->get_contains_hidden_expectation(
218                 $this->quba->get_field_prefix($this->slot) . 'p4'),
219             $this->get_does_not_contain_feedback_expectation());
221         // Save a partial answer.
222         $this->process_submission(array('p1' => '2', 'p2' => '1'));
223         // Verify.
224         $this->check_current_state(question_state::$invalid);
225         $this->check_current_mark(null);
227         $this->check_current_output(
228             $this->get_contains_drag_image_home_expectation(1, 1, 1),
229             $this->get_contains_drag_image_home_expectation(2, 2, 1),
230             $this->get_contains_drag_image_home_expectation(3, 1, 2),
231             $this->get_contains_drag_image_home_expectation(4, 2, 2),
232             $this->get_contains_hidden_expectation(
233                 $this->quba->get_field_prefix($this->slot) . 'p1', 2),
234             $this->get_contains_hidden_expectation(
235                 $this->quba->get_field_prefix($this->slot) . 'p2', 1),
236             $this->get_contains_hidden_expectation(
237                 $this->quba->get_field_prefix($this->slot) . 'p3', ''),
238             $this->get_contains_hidden_expectation(
239                 $this->quba->get_field_prefix($this->slot) . 'p4', ''),
240             $this->get_does_not_contain_correctness_expectation(),
241             $this->get_does_not_contain_feedback_expectation());
242         // Save the right answer.
243         $this->process_submission(
244             array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'));
246         // Verify.
247         $this->check_current_state(question_state::$complete);
248         $this->check_current_mark(null);
249         $this->check_current_output(
250             $this->get_contains_drag_image_home_expectation(1, 1, 1),
251             $this->get_contains_drag_image_home_expectation(2, 2, 1),
252             $this->get_contains_drag_image_home_expectation(3, 1, 2),
253             $this->get_contains_drag_image_home_expectation(4, 2, 2),
254             $this->get_contains_hidden_expectation(
255                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
256             $this->get_contains_hidden_expectation(
257                 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
258             $this->get_contains_hidden_expectation(
259                 $this->quba->get_field_prefix($this->slot) . 'p3', 1),
260             $this->get_contains_hidden_expectation(
261                 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
262             $this->get_does_not_contain_correctness_expectation(),
263             $this->get_does_not_contain_feedback_expectation());
265         // Finish the attempt.
266         $this->quba->finish_all_questions();
268         // Verify.
269         $this->check_current_state(question_state::$gradedright);
270         $this->check_current_mark(12);
272         $this->check_current_output(
273             $this->get_contains_drag_image_home_expectation(1, 1, 1),
274             $this->get_contains_drag_image_home_expectation(2, 2, 1),
275             $this->get_contains_drag_image_home_expectation(3, 1, 2),
276             $this->get_contains_drag_image_home_expectation(4, 2, 2),
277             $this->get_contains_hidden_expectation(
278                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
279             $this->get_contains_hidden_expectation(
280                 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
281             $this->get_contains_hidden_expectation(
282                 $this->quba->get_field_prefix($this->slot) . 'p3', 1),
283             $this->get_contains_hidden_expectation(
284                 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
285             $this->get_contains_correct_expectation());
287         // Change the right answer a bit.
288         $dd->rightchoices[2] = 1;
290         // Check regrading does not mess anything up.
291         $this->quba->regrade_all_questions();
293         // Verify.
294         $this->check_current_state(question_state::$gradedpartial);
295         $this->check_current_mark(9);
296     }
298     public function test_deferred_feedback_unanswered() {
300         // Create a drag-and-drop question.
301         $dd = test_question_maker::make_question('ddimageortext');
302         $dd->shufflechoices = false;
303         $this->start_attempt_at_question($dd, 'deferredfeedback', 12);
305         // Check the initial state.
306         $this->check_current_state(question_state::$todo);
307         $this->check_current_mark(null);
308         $this->check_current_output(
309             $this->get_contains_drag_image_home_expectation(1, 1, 1),
310             $this->get_contains_drag_image_home_expectation(2, 2, 1),
311             $this->get_contains_drag_image_home_expectation(3, 1, 2),
312             $this->get_contains_drag_image_home_expectation(4, 2, 2),
313             $this->get_contains_hidden_expectation(
314                 $this->quba->get_field_prefix($this->slot) . 'p1'),
315             $this->get_contains_hidden_expectation(
316                 $this->quba->get_field_prefix($this->slot) . 'p2'),
317             $this->get_contains_hidden_expectation(
318                 $this->quba->get_field_prefix($this->slot) . 'p3'),
319             $this->get_contains_hidden_expectation(
320                 $this->quba->get_field_prefix($this->slot) . 'p4'),
321             $this->get_does_not_contain_correctness_expectation(),
322             $this->get_does_not_contain_feedback_expectation());
323         $this->check_step_count(1);
325         // Save a blank response.
326         $this->process_submission(array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''));
328         // Verify.
329         $this->check_current_state(question_state::$todo);
330         $this->check_current_mark(null);
331         $this->check_current_output(
332             $this->get_contains_drag_image_home_expectation(1, 1, 1),
333             $this->get_contains_drag_image_home_expectation(2, 2, 1),
334             $this->get_contains_drag_image_home_expectation(3, 1, 2),
335             $this->get_contains_drag_image_home_expectation(4, 2, 2),
336             $this->get_contains_hidden_expectation(
337                 $this->quba->get_field_prefix($this->slot) . 'p1', ''),
338             $this->get_contains_hidden_expectation(
339                 $this->quba->get_field_prefix($this->slot) . 'p2', ''),
340             $this->get_contains_hidden_expectation(
341                 $this->quba->get_field_prefix($this->slot) . 'p3', ''),
342             $this->get_contains_hidden_expectation(
343                 $this->quba->get_field_prefix($this->slot) . 'p4', ''),
344             $this->get_does_not_contain_correctness_expectation(),
345             $this->get_does_not_contain_feedback_expectation());
346         $this->check_step_count(1);
348         // Finish the attempt.
349         $this->quba->finish_all_questions();
351         // Verify.
352         $this->check_current_state(question_state::$gaveup);
353         $this->check_current_mark(null);
354         $this->check_current_output(
355             $this->get_contains_drag_image_home_expectation(1, 1, 1),
356             $this->get_contains_drag_image_home_expectation(2, 2, 1),
357             $this->get_contains_drag_image_home_expectation(3, 1, 2),
358             $this->get_contains_drag_image_home_expectation(4, 2, 2));
359     }
361     public function test_deferred_feedback_partial_answer() {
363         // Create a drag-and-drop question.
364         $dd = test_question_maker::make_question('ddimageortext');
365         $dd->shufflechoices = false;
366         $this->start_attempt_at_question($dd, 'deferredfeedback', 3);
368         // Check the initial state.
369         $this->check_current_state(question_state::$todo);
370         $this->check_current_mark(null);
371         $this->check_current_output(
372             $this->get_contains_drag_image_home_expectation(1, 1, 1),
373             $this->get_contains_drag_image_home_expectation(2, 2, 1),
374             $this->get_contains_drag_image_home_expectation(3, 1, 2),
375             $this->get_contains_drag_image_home_expectation(4, 2, 2),
376             $this->get_contains_hidden_expectation(
377                 $this->quba->get_field_prefix($this->slot) . 'p1'),
378             $this->get_contains_hidden_expectation(
379                 $this->quba->get_field_prefix($this->slot) . 'p2'),
380             $this->get_contains_hidden_expectation(
381                 $this->quba->get_field_prefix($this->slot) . 'p3'),
382             $this->get_contains_hidden_expectation(
383                 $this->quba->get_field_prefix($this->slot) . 'p4'),
384             $this->get_does_not_contain_correctness_expectation(),
385             $this->get_does_not_contain_feedback_expectation());
387         // Save a partial response.
388         $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => ''));
390         // Verify.
391         $this->check_current_state(question_state::$invalid);
392         $this->check_current_mark(null);
393         $this->check_current_output(
394             $this->get_contains_drag_image_home_expectation(1, 1, 1),
395             $this->get_contains_drag_image_home_expectation(2, 2, 1),
396             $this->get_contains_drag_image_home_expectation(3, 1, 2),
397             $this->get_contains_drag_image_home_expectation(4, 2, 2),
398             $this->get_contains_hidden_expectation(
399                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
400             $this->get_contains_hidden_expectation(
401                 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
402             $this->get_contains_hidden_expectation(
403                 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
404             $this->get_contains_hidden_expectation(
405                 $this->quba->get_field_prefix($this->slot) . 'p4', 0),
406             $this->get_does_not_contain_correctness_expectation(),
407             $this->get_does_not_contain_feedback_expectation());
409         // Finish the attempt.
410         $this->quba->finish_all_questions();
412         // Verify.
413         $this->check_current_state(question_state::$gradedpartial);
414         $this->check_current_mark(1.5);
415         $this->check_current_output(
416             $this->get_contains_drag_image_home_expectation(1, 1, 1),
417             $this->get_contains_drag_image_home_expectation(2, 2, 1),
418             $this->get_contains_drag_image_home_expectation(3, 1, 2),
419             $this->get_contains_drag_image_home_expectation(4, 2, 2),
420             $this->get_contains_partcorrect_expectation());
421     }
423     public function test_interactive_grading() {
425         // Create a drag-and-drop question.
426         $dd = test_question_maker::make_question('ddimageortext');
427         $dd->hints = array(
428             new question_hint_with_parts(1, 'This is the first hint.',
429                 FORMAT_MOODLE, true, true),
430             new question_hint_with_parts(2, 'This is the second hint.',
431                 FORMAT_MOODLE, true, true),
432         );
433         $dd->shufflechoices = false;
434         $this->start_attempt_at_question($dd, 'interactive', 12);
436         // Check the initial state.
437         $this->check_current_state(question_state::$todo);
438         $this->check_current_mark(null);
439         $this->assertEquals('interactivecountback',
440             $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
441         $this->check_current_output(
442             $this->get_contains_drag_image_home_expectation(1, 1, 1),
443             $this->get_contains_drag_image_home_expectation(2, 2, 1),
444             $this->get_contains_drag_image_home_expectation(3, 1, 2),
445             $this->get_contains_drag_image_home_expectation(4, 2, 2),
446             $this->get_contains_hidden_expectation(
447                 $this->quba->get_field_prefix($this->slot) . 'p1'),
448             $this->get_contains_hidden_expectation(
449                 $this->quba->get_field_prefix($this->slot) . 'p2'),
450             $this->get_contains_hidden_expectation(
451                 $this->quba->get_field_prefix($this->slot) . 'p3'),
452             $this->get_contains_hidden_expectation(
453                 $this->quba->get_field_prefix($this->slot) . 'p4'),
454             $this->get_contains_submit_button_expectation(true),
455             $this->get_does_not_contain_feedback_expectation(),
456             $this->get_tries_remaining_expectation(3),
457             $this->get_does_not_contain_num_parts_correct(),
458             $this->get_no_hint_visible_expectation());
460         // Submit an response with the first two parts right.
461         $this->process_submission(
462             array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '1', '-submit' => 1));
464         // Verify.
465         $this->check_current_state(question_state::$todo);
466         $this->check_current_mark(null);
467         $this->check_current_output(
468             $this->get_contains_drag_image_home_expectation(1, 1, 1),
469             $this->get_contains_drag_image_home_expectation(2, 2, 1),
470             $this->get_contains_drag_image_home_expectation(3, 1, 2),
471             $this->get_contains_drag_image_home_expectation(4, 2, 2),
472             $this->get_contains_submit_button_expectation(false),
473             $this->get_contains_try_again_button_expectation(true),
474             $this->get_does_not_contain_correctness_expectation(),
475             $this->get_contains_hint_expectation('This is the first hint'),
476             $this->get_contains_num_parts_correct(2),
477             $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),
478             $this->get_contains_hidden_expectation(
479                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
480             $this->get_contains_hidden_expectation(
481                 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
482             $this->get_contains_hidden_expectation(
483                 $this->quba->get_field_prefix($this->slot) . 'p3', 2),
484             $this->get_contains_hidden_expectation(
485                 $this->quba->get_field_prefix($this->slot) . 'p4', 1));
487         // Check that extract responses will return the reset data.
488         $prefix = $this->quba->get_field_prefix($this->slot);
489         $this->assertEquals(array('p1' => '1', 'p2' => '2'),
490             $this->quba->extract_responses($this->slot,
491                 array($prefix . 'p1' => '1', $prefix . 'p2' => '2', '-tryagain' => 1)));
493         // Do try again.
494         // keys p3 and p4 are extra hidden fields to clear data.
495         $this->process_submission(
496             array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '', '-tryagain' => 1));
498         // Verify.
499         $this->check_current_state(question_state::$todo);
500         $this->check_current_mark(null);
501         $this->check_current_output(
502             $this->get_contains_drag_image_home_expectation(1, 1, 1),
503             $this->get_contains_drag_image_home_expectation(2, 2, 1),
504             $this->get_contains_drag_image_home_expectation(3, 1, 2),
505             $this->get_contains_drag_image_home_expectation(4, 2, 2),
506             $this->get_contains_hidden_expectation(
507                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
508             $this->get_contains_hidden_expectation(
509                 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
510             $this->get_contains_hidden_expectation(
511                 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
512             $this->get_contains_hidden_expectation(
513                 $this->quba->get_field_prefix($this->slot) . 'p4', 0),
514             $this->get_contains_submit_button_expectation(true),
515             $this->get_does_not_contain_try_again_button_expectation(),
516             $this->get_does_not_contain_correctness_expectation(),
517             $this->get_does_not_contain_feedback_expectation(),
518             $this->get_tries_remaining_expectation(2),
519             $this->get_no_hint_visible_expectation());
521         // Submit an response with the first and last parts right.
522         $this->process_submission(
523             array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2', '-submit' => 1));
525         // Verify.
526         $this->check_current_state(question_state::$todo);
527         $this->check_current_mark(null);
528         $this->check_current_output(
529             $this->get_contains_drag_image_home_expectation(1, 1, 1),
530             $this->get_contains_drag_image_home_expectation(2, 2, 1),
531             $this->get_contains_drag_image_home_expectation(3, 1, 2),
532             $this->get_contains_drag_image_home_expectation(4, 2, 2),
533             $this->get_contains_submit_button_expectation(false),
534             $this->get_contains_try_again_button_expectation(true),
535             $this->get_does_not_contain_correctness_expectation(),
536             $this->get_contains_hint_expectation('This is the second hint'),
537             $this->get_contains_num_parts_correct(2),
538             $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),
539             $this->get_contains_hidden_expectation(
540                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
541             $this->get_contains_hidden_expectation(
542                 $this->quba->get_field_prefix($this->slot) . 'p2', 1),
543             $this->get_contains_hidden_expectation(
544                 $this->quba->get_field_prefix($this->slot) . 'p3', 2),
545             $this->get_contains_hidden_expectation(
546                 $this->quba->get_field_prefix($this->slot) . 'p4', 2));
548         // Do try again.
549         $this->process_submission(
550             array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => '2', '-tryagain' => 1));
552         // Verify.
553         $this->check_current_state(question_state::$todo);
554         $this->check_current_mark(null);
555         $this->check_current_output(
556             $this->get_contains_drag_image_home_expectation(1, 1, 1),
557             $this->get_contains_drag_image_home_expectation(2, 2, 1),
558             $this->get_contains_drag_image_home_expectation(3, 1, 2),
559             $this->get_contains_drag_image_home_expectation(4, 2, 2),
560             $this->get_contains_hidden_expectation(
561                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
562             $this->get_contains_hidden_expectation(
563                 $this->quba->get_field_prefix($this->slot) . 'p2', 0),
564             $this->get_contains_hidden_expectation(
565                 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
566             $this->get_contains_hidden_expectation(
567                 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
568             $this->get_contains_submit_button_expectation(true),
569             $this->get_does_not_contain_try_again_button_expectation(),
570             $this->get_does_not_contain_correctness_expectation(),
571             $this->get_does_not_contain_feedback_expectation(),
572             $this->get_tries_remaining_expectation(1),
573             $this->get_no_hint_visible_expectation());
575         // Submit the right answer.
576         $this->process_submission(
577             array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1));
579         // Verify.
580         $this->check_current_state(question_state::$gradedright);
581         $this->check_current_mark(7);
582         $this->check_current_output(
583             $this->get_contains_drag_image_home_expectation(1, 1, 1),
584             $this->get_contains_drag_image_home_expectation(2, 2, 1),
585             $this->get_contains_drag_image_home_expectation(3, 1, 2),
586             $this->get_contains_drag_image_home_expectation(4, 2, 2),
587             $this->get_contains_hidden_expectation(
588                 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
589             $this->get_contains_hidden_expectation(
590                 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
591             $this->get_contains_hidden_expectation(
592                 $this->quba->get_field_prefix($this->slot) . 'p3', 1),
593             $this->get_contains_hidden_expectation(
594                 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
595             $this->get_contains_submit_button_expectation(false),
596             $this->get_does_not_contain_try_again_button_expectation(),
597             $this->get_contains_correct_expectation(),
598             $this->get_no_hint_visible_expectation(),
599             $this->get_does_not_contain_num_parts_correct(),
600             $this->get_contains_standard_correct_combined_feedback_expectation());
601     }
603     public function test_interactive_correct_no_submit() {
605         // Create a drag-and-drop question.
606         $dd = test_question_maker::make_question('ddimageortext');
607         $dd->hints = array(
608             new question_hint_with_parts(23, 'This is the first hint.',
609                 FORMAT_MOODLE, false, false),
610             new question_hint_with_parts(24, 'This is the second hint.',
611                 FORMAT_MOODLE, true, true),
612         );
613         $dd->shufflechoices = false;
614         $this->start_attempt_at_question($dd, 'interactive', 3);
616         // Check the initial state.
617         $this->check_current_state(question_state::$todo);
618         $this->check_current_mark(null);
619         $this->check_current_output(
620             $this->get_contains_drag_image_home_expectation(1, 1, 1),
621             $this->get_contains_drag_image_home_expectation(2, 2, 1),
622             $this->get_contains_drag_image_home_expectation(3, 1, 2),
623             $this->get_contains_drag_image_home_expectation(4, 2, 2),
624             $this->get_contains_hidden_expectation(
625                 $this->quba->get_field_prefix($this->slot) . 'p1'),
626             $this->get_contains_hidden_expectation(
627                 $this->quba->get_field_prefix($this->slot) . 'p2'),
628             $this->get_contains_hidden_expectation(
629                 $this->quba->get_field_prefix($this->slot) . 'p3'),
630             $this->get_contains_hidden_expectation(
631                 $this->quba->get_field_prefix($this->slot) . 'p4'),
632             $this->get_contains_submit_button_expectation(true),
633             $this->get_does_not_contain_feedback_expectation(),
634             $this->get_tries_remaining_expectation(3),
635             $this->get_no_hint_visible_expectation());
637         // Save the right answer.
638         $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'));
640         // Finish the attempt without clicking check.
641         $this->quba->finish_all_questions();
643         // Verify.
644         $this->check_current_state(question_state::$gradedright);
645         $this->check_current_mark(3);
646         $this->check_current_output(
647             $this->get_contains_drag_image_home_expectation(1, 1, 1),
648             $this->get_contains_drag_image_home_expectation(2, 2, 1),
649             $this->get_contains_drag_image_home_expectation(3, 1, 2),
650             $this->get_contains_drag_image_home_expectation(4, 2, 2),
651             $this->get_contains_submit_button_expectation(false),
652             $this->get_contains_correct_expectation(),
653             $this->get_no_hint_visible_expectation());
655         // Check regrading does not mess anything up.
656         $this->quba->regrade_all_questions();
658         // Verify.
659         $this->check_current_state(question_state::$gradedright);
660         $this->check_current_mark(3);
661     }
663     public function test_interactive_partial_no_submit() {
665         // Create a drag-and-drop question.
666         $dd = test_question_maker::make_question('ddimageortext');
667         $dd->hints = array(
668             new question_hint_with_parts(23, 'This is the first hint.',
669                 FORMAT_MOODLE, false, false),
670             new question_hint_with_parts(24, 'This is the second hint.',
671                 FORMAT_MOODLE, true, true),
672         );
673         $dd->shufflechoices = false;
674         $this->start_attempt_at_question($dd, 'interactive', 4);
676         // Check the initial state.
677         $this->check_current_state(question_state::$todo);
678         $this->check_current_mark(null);
680         $this->check_current_output(
681             $this->get_contains_drag_image_home_expectation(1, 1, 1),
682             $this->get_contains_drag_image_home_expectation(2, 2, 1),
683             $this->get_contains_drag_image_home_expectation(3, 1, 2),
684             $this->get_contains_drag_image_home_expectation(4, 2, 2),
685             $this->get_contains_hidden_expectation(
686                 $this->quba->get_field_prefix($this->slot) . 'p1'),
687             $this->get_contains_hidden_expectation(
688                 $this->quba->get_field_prefix($this->slot) . 'p2'),
689             $this->get_contains_hidden_expectation(
690                 $this->quba->get_field_prefix($this->slot) . 'p3'),
691             $this->get_contains_hidden_expectation(
692                 $this->quba->get_field_prefix($this->slot) . 'p4'),
693             $this->get_contains_submit_button_expectation(true),
694             $this->get_does_not_contain_feedback_expectation(),
695             $this->get_tries_remaining_expectation(3),
696             $this->get_no_hint_visible_expectation());
698         // Save the a partially right answer.
699         $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '1'));
701         // Finish the attempt without clicking check.
702         $this->quba->finish_all_questions();
704         // Verify.
705         $this->check_current_state(question_state::$gradedpartial);
706         $this->check_current_mark(1);
708         $this->check_current_output(
709             $this->get_contains_drag_image_home_expectation(1, 1, 1),
710             $this->get_contains_drag_image_home_expectation(2, 2, 1),
711             $this->get_contains_drag_image_home_expectation(3, 1, 2),
712             $this->get_contains_drag_image_home_expectation(4, 2, 2),
713             $this->get_contains_submit_button_expectation(false),
714             $this->get_contains_partcorrect_expectation(),
715             $this->get_no_hint_visible_expectation());
717         // Check regrading does not mess anything up.
718         $this->quba->regrade_all_questions();
720         // Verify.
721         $this->check_current_state(question_state::$gradedpartial);
722         $this->check_current_mark(1);
723     }
725     public function test_interactive_no_right_clears() {
727         // Create a drag-and-drop question.
728         $dd = test_question_maker::make_question('ddimageortext');
729         $dd->hints = array(
730             new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true),
731             new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true),
732         );
733         $dd->shufflechoices = false;
734         $this->start_attempt_at_question($dd, 'interactive', 3);
736         // Check the initial state.
737         $this->check_current_state(question_state::$todo);
738         $this->check_current_mark(null);
740         $this->check_current_output(
741             $this->get_contains_marked_out_of_summary(),
742             $this->get_contains_drag_image_home_expectation(1, 1, 1),
743             $this->get_contains_drag_image_home_expectation(2, 2, 1),
744             $this->get_contains_drag_image_home_expectation(3, 1, 2),
745             $this->get_contains_drag_image_home_expectation(4, 2, 2),
746             $this->get_contains_hidden_expectation(
747                 $this->quba->get_field_prefix($this->slot) . 'p1'),
748             $this->get_contains_hidden_expectation(
749                 $this->quba->get_field_prefix($this->slot) . 'p2'),
750             $this->get_contains_hidden_expectation(
751                 $this->quba->get_field_prefix($this->slot) . 'p3'),
752             $this->get_contains_hidden_expectation(
753                 $this->quba->get_field_prefix($this->slot) . 'p4'),
754             $this->get_contains_submit_button_expectation(true),
755             $this->get_does_not_contain_feedback_expectation(),
756             $this->get_tries_remaining_expectation(3),
757             $this->get_no_hint_visible_expectation());
759         // Save the a completely wrong answer.
760         $this->process_submission(
761             array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1));
763         // Verify.
764         $this->check_current_state(question_state::$todo);
765         $this->check_current_mark(null);
766         $this->check_current_output(
767             $this->get_contains_marked_out_of_summary(),
768             $this->get_contains_drag_image_home_expectation(1, 1, 1),
769             $this->get_contains_drag_image_home_expectation(2, 2, 1),
770             $this->get_contains_drag_image_home_expectation(3, 1, 2),
771             $this->get_contains_drag_image_home_expectation(4, 2, 2),
772             $this->get_contains_submit_button_expectation(false),
773             $this->get_contains_hint_expectation('This is the first hint'));
775         // Do try again.
776         $this->process_submission(
777             array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '', '-tryagain' => 1));
779         // Check that all the wrong answers have been cleared.
780         $this->check_current_state(question_state::$todo);
781         $this->check_current_mark(null);
782         $this->check_current_output(
783             $this->get_contains_marked_out_of_summary(),
784             $this->get_contains_drag_image_home_expectation(1, 1, 1),
785             $this->get_contains_drag_image_home_expectation(2, 2, 1),
786             $this->get_contains_drag_image_home_expectation(3, 1, 2),
787             $this->get_contains_drag_image_home_expectation(4, 2, 2),
788             $this->get_contains_hidden_expectation(
789                 $this->quba->get_field_prefix($this->slot) . 'p1', 0),
790             $this->get_contains_hidden_expectation(
791                 $this->quba->get_field_prefix($this->slot) . 'p2', 0),
792             $this->get_contains_hidden_expectation(
793                 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
794             $this->get_contains_hidden_expectation(
795                 $this->quba->get_field_prefix($this->slot) . 'p4', 0),
796             $this->get_contains_submit_button_expectation(true),
797             $this->get_does_not_contain_feedback_expectation(),
798             $this->get_tries_remaining_expectation(2),
799             $this->get_no_hint_visible_expectation());
800     }
802     public function test_display_of_right_answer_when_shuffled() {
804         // Create a drag-and-drop question.
805         $dd = test_question_maker::make_question('ddimageortext');
806         $this->start_attempt_at_question($dd, 'deferredfeedback', 3);
808         // Check the initial state.
809         $this->check_current_state(question_state::$todo);
810         $this->check_current_mark(null);
812         $this->check_current_output(
813             $this->get_contains_hidden_expectation(
814                 $this->quba->get_field_prefix($this->slot) . 'p1'),
815             $this->get_contains_hidden_expectation(
816                 $this->quba->get_field_prefix($this->slot) . 'p2'),
817             $this->get_contains_hidden_expectation(
818                 $this->quba->get_field_prefix($this->slot) . 'p3'),
819             $this->get_contains_hidden_expectation(
820                 $this->quba->get_field_prefix($this->slot) . 'p4'),
821             $this->get_does_not_contain_feedback_expectation());
823         // Save a partial answer.
824         $this->process_submission($dd->get_correct_response());
826         // Verify.
827         $this->check_current_state(question_state::$complete);
828         $this->check_current_mark(null);
829         $this->check_current_output(
830             $this->get_contains_hidden_expectation(
831                 $this->quba->get_field_prefix($this->slot) . 'p1',
832                 $dd->get_right_choice_for(1)),
833             $this->get_contains_hidden_expectation(
834                 $this->quba->get_field_prefix($this->slot) . 'p2',
835                 $dd->get_right_choice_for(2)),
836             $this->get_contains_hidden_expectation(
837                 $this->quba->get_field_prefix($this->slot) . 'p3',
838                 $dd->get_right_choice_for(3)),
839             $this->get_contains_hidden_expectation(
840                 $this->quba->get_field_prefix($this->slot) . 'p4',
841                 $dd->get_right_choice_for(4)),
842             $this->get_does_not_contain_correctness_expectation(),
843             $this->get_does_not_contain_feedback_expectation());
845         // Finish the attempt.
846         $this->quba->finish_all_questions();
848         // Verify.
849         $this->displayoptions->rightanswer = question_display_options::VISIBLE;
850         $this->assertEquals('Drop zone 1 -> {1. quick} '.
851                 'Drop zone 2 -> {2. fox} '.
852                 'Drop zone 3 -> {3. lazy} '.
853                 'Drop zone 4 -> {4. dog}',
854             $dd->get_right_answer_summary());
855         $this->check_current_state(question_state::$gradedright);
856         $this->check_current_mark(3);
857     }