7f55debb1650d58d565eb8ae8b98bcca0c2e87ee
[moodle.git] / question / type / ddmarker / 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 markers question type.
19  *
20  * @package   qtype_ddmarker
21  * @copyright 2012 The Open University
22  * @author    Jamie Pratt <me@jamiep.org>
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
27 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
31 require_once($CFG->dirroot . '/question/type/ddmarker/tests/helper.php');
34 /**
35  * Unit tests for the drag-and-drop markers question type.
36  *
37  * @copyright 2012 The Open University
38  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class qtype_ddmarker_walkthrough_test extends qbehaviour_walkthrough_test_base {
42     /**
43      * Get an expectation that the output contains a marker.
44      * @param unknown $choice which choice.
45      * @param unknown $infinite whether there are infinitely many of that choice.
46      * @return question_contains_tag_with_attributes the expectation.
47      */
48     protected function get_contains_draggable_marker_home_expectation($choice, $infinite) {
49         $class = 'draghome choice'.$choice;
50         if ($infinite) {
51             $class .= ' infinite';
52         }
54         $expectedattrs = array();
55         $expectedattrs['class'] = $class;
57         return new question_contains_tag_with_attributes('span', $expectedattrs);
58     }
60     /**
61      * (non-PHPdoc)
62      * @see qbehaviour_walkthrough_test_base::get_contains_hidden_expectation()
63      */
64     protected function get_contains_hidden_expectation($choiceno, $value = null) {
65         $name = $this->quba->get_field_prefix($this->slot) .'c'. $choiceno;
66         $expectedattributes = array('type' => 'hidden', 'name' => s($name));
67         $expectedattributes['class'] = "choices choice{$choiceno}";
68         if (!is_null($value)) {
69             $expectedattributes['value'] = s($value);
70         }
71         return new question_contains_tag_with_attributes('input', $expectedattributes);
72     }
74     public function test_interactive_behaviour() {
76         // Create a drag-and-drop question.
77         $dd = test_question_maker::make_question('ddmarker');
78         $dd->hints = array(
79             new question_hint_ddmarker(13, 'This is the first hint.',
80                                                             FORMAT_HTML, false, false, false),
81             new question_hint_ddmarker(14, 'This is the second hint.',
82                                                             FORMAT_HTML, true, true, false),
83         );
84         $dd->shufflechoices = false;
85         $this->start_attempt_at_question($dd, 'interactive', 12);
87         // Check the initial state.
88         $this->check_current_state(question_state::$todo);
89         $this->check_current_mark(null);
91         $this->check_current_output(
92                 $this->get_contains_draggable_marker_home_expectation(1, false),
93                 $this->get_contains_draggable_marker_home_expectation(2, false),
94                 $this->get_contains_draggable_marker_home_expectation(3, false),
95                 $this->get_contains_hidden_expectation(1),
96                 $this->get_contains_hidden_expectation(2),
97                 $this->get_contains_hidden_expectation(3),
98                 $this->get_contains_submit_button_expectation(true),
99                 $this->get_does_not_contain_feedback_expectation(),
100                 $this->get_tries_remaining_expectation(3),
101                 $this->get_no_hint_visible_expectation());
103         $completelywrong = array('c1' => '0,250', 'c2' => '100,250', 'c3' => '150,250');
104         // Save the wrong answer.
105         $this->process_submission($completelywrong);
106         // Verify.
107         $this->check_current_state(question_state::$todo);
108         $this->check_current_mark(null);
110         $this->check_current_output(
111                 $this->get_contains_draggable_marker_home_expectation(1, false),
112                 $this->get_contains_draggable_marker_home_expectation(2, false),
113                 $this->get_contains_draggable_marker_home_expectation(3, false),
114                 $this->get_contains_hidden_expectation(1, '0,250'),
115                 $this->get_contains_hidden_expectation(2, '100,250'),
116                 $this->get_contains_hidden_expectation(3, '150,250'),
117                 $this->get_contains_submit_button_expectation(true),
118                 $this->get_does_not_contain_feedback_expectation(),
119                 $this->get_tries_remaining_expectation(3),
120                 $this->get_no_hint_visible_expectation());
121         // Submit the wrong answer.
122         $this->process_submission($completelywrong + array('-submit' => 1));
124         // Verify.
125         $this->check_current_state(question_state::$todo);
126         $this->check_current_mark(null);
127         $this->check_current_output(
128                 $this->get_contains_draggable_marker_home_expectation(1, false),
129                 $this->get_contains_draggable_marker_home_expectation(2, false),
130                 $this->get_contains_draggable_marker_home_expectation(3, false),
131                 $this->get_contains_hidden_expectation(1, '0,250'),
132                 $this->get_contains_hidden_expectation(2, '100,250'),
133                 $this->get_contains_hidden_expectation(3, '150,250'),
134                 $this->get_contains_try_again_button_expectation(true),
135                 new question_pattern_expectation('/' .
136                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'),
137                 $this->get_contains_hint_expectation('This is the first hint'));
139         // Do try again.
140         $this->process_submission(array('-tryagain' => 1));
142         // Verify.
143         $this->check_current_state(question_state::$todo);
144         $this->check_current_mark(null);
146         $this->check_current_output(
147                 $this->get_contains_draggable_marker_home_expectation(1, false),
148                 $this->get_contains_draggable_marker_home_expectation(2, false),
149                 $this->get_contains_draggable_marker_home_expectation(3, false),
150                 $this->get_contains_hidden_expectation(1, '0,250'),
151                 $this->get_contains_hidden_expectation(2, '100,250'),
152                 $this->get_contains_hidden_expectation(3, '150,250'),
153                 $this->get_contains_submit_button_expectation(true),
154                 $this->get_does_not_contain_correctness_expectation(),
155                 $this->get_does_not_contain_feedback_expectation(),
156                 $this->get_tries_remaining_expectation(2),
157                 $this->get_no_hint_visible_expectation());
159         // Submit the right answer.
160         $this->process_submission(
161                     array('c1' => '50,50', 'c2' => '150,50', 'c3' => '100,150', '-submit' => 1));
163         // Verify.
164         $this->check_current_state(question_state::$gradedright);
165         $this->check_current_mark(8);
166         $this->check_current_output(
167                 $this->get_contains_draggable_marker_home_expectation(1, false),
168                 $this->get_contains_draggable_marker_home_expectation(2, false),
169                 $this->get_contains_draggable_marker_home_expectation(3, false),
170                 $this->get_contains_hidden_expectation(1, '50,50'),
171                 $this->get_contains_hidden_expectation(2, '150,50'),
172                 $this->get_contains_hidden_expectation(3, '100,150'),
173                 $this->get_contains_submit_button_expectation(false),
174                 $this->get_contains_correct_expectation(),
175                 $this->get_no_hint_visible_expectation());
177         // Check regrading does not mess anything up.
178         $this->quba->regrade_all_questions();
180         // Verify.
181         $this->check_current_state(question_state::$gradedright);
182         $this->check_current_mark(8);
183     }
185     public function test_deferred_feedback() {
187         // Create a drag-and-drop question.
188         $dd = test_question_maker::make_question('ddmarker');
189         $dd->shufflechoices = false;
190         $this->start_attempt_at_question($dd, 'deferredfeedback', 12);
192         // Check the initial state.
193         $this->check_current_state(question_state::$todo);
194         $this->check_current_mark(null);
196         $this->check_current_output(
197                 $this->get_contains_draggable_marker_home_expectation(1, false),
198                 $this->get_contains_draggable_marker_home_expectation(2, false),
199                 $this->get_contains_draggable_marker_home_expectation(3, false),
200                 $this->get_contains_hidden_expectation(1),
201                 $this->get_contains_hidden_expectation(2),
202                 $this->get_contains_hidden_expectation(3),
203                 $this->get_does_not_contain_feedback_expectation());
205         // Save a partial answer.
206         $this->process_submission(array('c1' => '150,50', 'c2' => '50,50'));
207         // Verify.
208         $this->check_current_state(question_state::$complete);
209         $this->check_current_mark(null);
211         $this->check_current_output(
212                 $this->get_contains_draggable_marker_home_expectation(1, false),
213                 $this->get_contains_draggable_marker_home_expectation(2, false),
214                 $this->get_contains_draggable_marker_home_expectation(3, false),
215                 $this->get_contains_hidden_expectation(1, '150,50'),
216                 $this->get_contains_hidden_expectation(2, '50,50'),
217                 $this->get_contains_hidden_expectation(3, ''),
218                 $this->get_does_not_contain_correctness_expectation(),
219                 $this->get_does_not_contain_feedback_expectation());
220         // Save the right answer.
221         $this->process_submission(
222                         array('c1' => '50,50', 'c2' => '150,50', 'c3' => '100,150'));
224         // Verify.
225         $this->check_current_state(question_state::$complete);
226         $this->check_current_mark(null);
227         $this->check_current_output(
228                 $this->get_contains_draggable_marker_home_expectation(1, false),
229                 $this->get_contains_draggable_marker_home_expectation(2, false),
230                 $this->get_contains_draggable_marker_home_expectation(3, false),
231                 $this->get_contains_hidden_expectation(1, '50,50'),
232                 $this->get_contains_hidden_expectation(2, '150,50'),
233                 $this->get_contains_hidden_expectation(3, '100,150'),
234                 $this->get_does_not_contain_correctness_expectation(),
235                 $this->get_does_not_contain_feedback_expectation());
237         // Finish the attempt.
238         $this->quba->finish_all_questions();
240         // Verify.
241         $this->check_current_state(question_state::$gradedright);
242         $this->check_current_mark(12);
244         $this->check_current_output(
245                 $this->get_contains_draggable_marker_home_expectation(1, false),
246                 $this->get_contains_draggable_marker_home_expectation(2, false),
247                 $this->get_contains_draggable_marker_home_expectation(3, false),
248                 $this->get_contains_hidden_expectation(1, '50,50'),
249                 $this->get_contains_hidden_expectation(2, '150,50'),
250                 $this->get_contains_hidden_expectation(3, '100,150'),
251                 $this->get_contains_correct_expectation());
253         // Change the right answer a bit.
254         $dd->rightchoices[2] = 1;
256         // Check regrading does not mess anything up.
257         $this->quba->regrade_all_questions();
259         // Verify.
260         $this->check_current_state(question_state::$gradedpartial);
261         $this->check_current_mark(8);
262     }
264     public function test_deferred_feedback_unanswered() {
266         // Create a drag-and-drop question.
267         $dd = test_question_maker::make_question('ddmarker');
268         $dd->shufflechoices = false;
269         $this->start_attempt_at_question($dd, 'deferredfeedback', 12);
271         // Check the initial state.
272         $this->check_current_state(question_state::$todo);
273         $this->check_current_mark(null);
274         $this->check_current_output(
275                 $this->get_contains_draggable_marker_home_expectation(1, false),
276                 $this->get_contains_draggable_marker_home_expectation(2, false),
277                 $this->get_contains_draggable_marker_home_expectation(3, false),
278                 $this->get_contains_hidden_expectation(1),
279                 $this->get_contains_hidden_expectation(2),
280                 $this->get_contains_hidden_expectation(3),
281                 $this->get_does_not_contain_correctness_expectation(),
282                 $this->get_does_not_contain_feedback_expectation());
283         $this->check_step_count(1);
285         // Save a blank response.
286         $this->process_submission(array('c1' => '', 'c2' => '', 'c3' => ''));
288         // Verify.
289         $this->check_current_state(question_state::$todo);
290         $this->check_current_mark(null);
291         $this->check_current_output(
292                 $this->get_contains_draggable_marker_home_expectation(1, false),
293                 $this->get_contains_draggable_marker_home_expectation(2, false),
294                 $this->get_contains_draggable_marker_home_expectation(3, false),
295                 $this->get_contains_hidden_expectation(1, ''),
296                 $this->get_contains_hidden_expectation(2, ''),
297                 $this->get_contains_hidden_expectation(3, ''),
298                 $this->get_does_not_contain_correctness_expectation(),
299                 $this->get_does_not_contain_feedback_expectation());
300         $this->check_step_count(1);
302         // Finish the attempt.
303         $this->quba->finish_all_questions();
305         // Verify.
306         $this->check_current_state(question_state::$gaveup);
307         $this->check_current_mark(null);
308         $this->check_current_output(
309                 $this->get_contains_draggable_marker_home_expectation(1, false),
310                 $this->get_contains_draggable_marker_home_expectation(2, false),
311                 $this->get_contains_draggable_marker_home_expectation(3, false));
312     }
314     public function test_deferred_feedback_partial_answer() {
316         // Create a drag-and-drop question.
317         $dd = test_question_maker::make_question('ddmarker');
318         $dd->shufflechoices = false;
319         $this->start_attempt_at_question($dd, 'deferredfeedback', 3);
321         // Check the initial state.
322         $this->check_current_state(question_state::$todo);
323         $this->check_current_mark(null);
324         $this->check_current_output(
325                 $this->get_contains_draggable_marker_home_expectation(1, false),
326                 $this->get_contains_draggable_marker_home_expectation(2, false),
327                 $this->get_contains_draggable_marker_home_expectation(3, false),
328                 $this->get_contains_hidden_expectation(1),
329                 $this->get_contains_hidden_expectation(2),
330                 $this->get_contains_hidden_expectation(3),
331                 $this->get_does_not_contain_correctness_expectation(),
332                 $this->get_does_not_contain_feedback_expectation());
334         $this->process_submission(array('c1' => '50,50', 'c2' => '150,50', 'c3' => ''));
336         // Verify.
337         $this->check_current_state(question_state::$complete);
338         $this->check_current_mark(null);
339         $this->check_current_output(
340                 $this->get_contains_draggable_marker_home_expectation(1, false),
341                 $this->get_contains_draggable_marker_home_expectation(2, false),
342                 $this->get_contains_draggable_marker_home_expectation(3, false),
343                 $this->get_contains_hidden_expectation(1, '50,50'),
344                 $this->get_contains_hidden_expectation(2, '150,50'),
345                 $this->get_contains_hidden_expectation(3, ''),
346                 $this->get_does_not_contain_correctness_expectation(),
347                 $this->get_does_not_contain_feedback_expectation());
349         // Finish the attempt.
350         $this->quba->finish_all_questions();
352         // Verify.
353         $this->check_current_state(question_state::$gradedpartial);
354         $this->check_current_mark(2);
355         $this->check_current_output(
356                 $this->get_contains_draggable_marker_home_expectation(1, false),
357                 $this->get_contains_draggable_marker_home_expectation(2, false),
358                 $this->get_contains_draggable_marker_home_expectation(3, false),
359                 $this->get_contains_partcorrect_expectation());
360     }
362     public function test_interactive_grading() {
364         // Create a drag-and-drop question.
365         $dd = test_question_maker::make_question('ddmarker');
366         $dd->hints = array(
367             new question_hint_ddmarker(1, 'This is the first hint.',
368                     FORMAT_MOODLE, true, true, false),
369             new question_hint_ddmarker(2, 'This is the second hint.',
370                     FORMAT_MOODLE, true, true, false),
371         );
372         $dd->shufflechoices = false;
373         $this->start_attempt_at_question($dd, 'interactive', 12);
375         // Check the initial state.
376         $this->check_current_state(question_state::$todo);
377         $this->check_current_mark(null);
378         $this->assertEquals('interactivecountback',
379                 $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
380         $this->check_current_output(
381                 $this->get_contains_draggable_marker_home_expectation(1, false),
382                 $this->get_contains_draggable_marker_home_expectation(2, false),
383                 $this->get_contains_draggable_marker_home_expectation(3, false),
384                 $this->get_contains_hidden_expectation(1),
385                 $this->get_contains_hidden_expectation(2),
386                 $this->get_contains_hidden_expectation(3),
387                 $this->get_contains_submit_button_expectation(true),
388                 $this->get_does_not_contain_feedback_expectation(),
389                 $this->get_tries_remaining_expectation(3),
390                 $this->get_does_not_contain_num_parts_correct(),
391                 $this->get_no_hint_visible_expectation());
393         // Submit an response with the first two parts right.
394         $this->process_submission(
395                     array('c1' => '50,50', 'c2' => '150,50', 'c3' => '150,50', '-submit' => 1));
397         // Verify.
398         $this->check_current_state(question_state::$todo);
399         $this->check_current_mark(null);
400         $this->check_current_output(
401                 $this->get_contains_draggable_marker_home_expectation(1, false),
402                 $this->get_contains_draggable_marker_home_expectation(2, false),
403                 $this->get_contains_draggable_marker_home_expectation(3, false),
404                 $this->get_contains_submit_button_expectation(false),
405                 $this->get_contains_try_again_button_expectation(true),
406                 $this->get_does_not_contain_correctness_expectation(),
407                 new question_pattern_expectation('/' .
408                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'),
409                 $this->get_contains_hint_expectation('This is the first hint'),
410                 $this->get_contains_num_parts_correct(2),
411                 $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),
412                 $this->get_contains_hidden_expectation(1, '50,50'),
413                 $this->get_contains_hidden_expectation(2, '150,50'),
414                 $this->get_contains_hidden_expectation(3, '150,50'));
416         // Check that extract responses will return the reset data.
417         $prefix = $this->quba->get_field_prefix($this->slot);
418         $this->assertEquals(array('c1' => '50,50', 'c2' => '150,50'),
419                 $this->quba->extract_responses($this->slot,
420                 array($prefix . 'c1' => '50,50', $prefix . 'c2' => '150,50', '-tryagain' => 1)));
422         // Do try again.
423         // keys c3 is an extra hidden fields to clear data.
424         $this->process_submission(
425                         array('c1' => '50,50', 'c2' => '150,50', 'c3' => '', '-tryagain' => 1));
427         // Verify.
428         $this->check_current_state(question_state::$todo);
429         $this->check_current_mark(null);
430         $this->check_current_output(
431                 $this->get_contains_draggable_marker_home_expectation(1, false),
432                 $this->get_contains_draggable_marker_home_expectation(2, false),
433                 $this->get_contains_draggable_marker_home_expectation(3, false),
434                 $this->get_contains_hidden_expectation(1, '50,50'),
435                 $this->get_contains_hidden_expectation(2, '150,50'),
436                 $this->get_contains_hidden_expectation(3, ''),
437                 $this->get_contains_submit_button_expectation(true),
438                 $this->get_does_not_contain_try_again_button_expectation(),
439                 $this->get_does_not_contain_correctness_expectation(),
440                 $this->get_does_not_contain_feedback_expectation(),
441                 $this->get_tries_remaining_expectation(2),
442                 $this->get_no_hint_visible_expectation());
444         // Submit an response with the first and last parts right.
445         $this->process_submission(
446                     array('c1' => '50,50', 'c2' => '150,150', 'c3' => '100,150', '-submit' => 1));
448         // Verify.
449         $this->check_current_state(question_state::$todo);
450         $this->check_current_mark(null);
451         $this->check_current_output(
452                 $this->get_contains_draggable_marker_home_expectation(1, false),
453                 $this->get_contains_draggable_marker_home_expectation(2, false),
454                 $this->get_contains_draggable_marker_home_expectation(3, false),
455                 $this->get_contains_submit_button_expectation(false),
456                 $this->get_contains_try_again_button_expectation(true),
457                 $this->get_does_not_contain_correctness_expectation(),
458                 new question_pattern_expectation('/' .
459                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'),
460                 $this->get_contains_hint_expectation('This is the second hint'),
461                 $this->get_contains_num_parts_correct(2),
462                 $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),
463                 $this->get_contains_hidden_expectation(1, '50,50'),
464                 $this->get_contains_hidden_expectation(2, '150,150'),
465                 $this->get_contains_hidden_expectation(3, '100,150'));
467         // Do try again.
468         $this->process_submission(
469                         array('c1' => '50,50', 'c2' => '', 'c3' => '', '-tryagain' => 1));
471         // Verify.
472         $this->check_current_state(question_state::$todo);
473         $this->check_current_mark(null);
474         $this->check_current_output(
475                 $this->get_contains_draggable_marker_home_expectation(1, false),
476                 $this->get_contains_draggable_marker_home_expectation(2, false),
477                 $this->get_contains_draggable_marker_home_expectation(3, false),
478                 $this->get_contains_hidden_expectation(1, '50,50'),
479                 $this->get_contains_hidden_expectation(2, ''),
480                 $this->get_contains_hidden_expectation(3, ''),
481                 $this->get_contains_submit_button_expectation(true),
482                 $this->get_does_not_contain_try_again_button_expectation(),
483                 $this->get_does_not_contain_correctness_expectation(),
484                 $this->get_does_not_contain_feedback_expectation(),
485                 $this->get_tries_remaining_expectation(1),
486                 $this->get_no_hint_visible_expectation());
488         // Submit the right answer.
489         $this->process_submission(
490                     array('c1' => '50,50', 'c2' => '150,50', 'c3' => '100,150', '-submit' => 1));
492         // Verify.
493         $this->check_current_state(question_state::$gradedright);
494         $this->check_current_mark(8);
495         $this->check_current_output(
496                 $this->get_contains_draggable_marker_home_expectation(1, false),
497                 $this->get_contains_draggable_marker_home_expectation(2, false),
498                 $this->get_contains_draggable_marker_home_expectation(3, false),
499                 $this->get_contains_hidden_expectation(1, '50,50'),
500                 $this->get_contains_hidden_expectation(2, '150,50'),
501                 $this->get_contains_hidden_expectation(3, '100,150'),
502                 $this->get_contains_submit_button_expectation(false),
503                 $this->get_does_not_contain_try_again_button_expectation(),
504                 $this->get_contains_correct_expectation(),
505                 $this->get_no_hint_visible_expectation(),
506                 $this->get_does_not_contain_num_parts_correct(),
507                 $this->get_contains_standard_correct_combined_feedback_expectation());
508     }
510     public function test_interactive_correct_no_submit() {
512         // Create a drag-and-drop question.
513         $dd = test_question_maker::make_question('ddmarker');
514         $dd->hints = array(
515             new question_hint_ddmarker(23, 'This is the first hint.',
516                     FORMAT_MOODLE, false, false, false),
517             new question_hint_ddmarker(24, 'This is the second hint.',
518                     FORMAT_MOODLE, true, true, false),
519         );
520         $dd->shufflechoices = false;
521         $this->start_attempt_at_question($dd, 'interactive', 3);
523         // Check the initial state.
524         $this->check_current_state(question_state::$todo);
525         $this->check_current_mark(null);
526         $this->check_current_output(
527                 $this->get_contains_draggable_marker_home_expectation(1, false),
528                 $this->get_contains_draggable_marker_home_expectation(2, false),
529                 $this->get_contains_draggable_marker_home_expectation(3, false),
530                 $this->get_contains_hidden_expectation(1),
531                 $this->get_contains_hidden_expectation(2),
532                 $this->get_contains_hidden_expectation(3),
533                 $this->get_contains_submit_button_expectation(true),
534                 $this->get_does_not_contain_feedback_expectation(),
535                 $this->get_tries_remaining_expectation(3),
536                 $this->get_no_hint_visible_expectation());
538         // Save the right answer.
539         $this->process_submission(array('c1' => '50,50', 'c2' => '150,50', 'c3' => '100,150'));
541         // Finish the attempt without clicking check.
542         $this->quba->finish_all_questions();
544         // Verify.
545         $this->check_current_state(question_state::$gradedright);
546         $this->check_current_mark(3);
547         $this->check_current_output(
548                 $this->get_contains_draggable_marker_home_expectation(1, false),
549                 $this->get_contains_draggable_marker_home_expectation(2, false),
550                 $this->get_contains_draggable_marker_home_expectation(3, false),
551                 $this->get_contains_submit_button_expectation(false),
552                 $this->get_contains_correct_expectation(),
553                 $this->get_no_hint_visible_expectation());
555         // Check regrading does not mess anything up.
556         $this->quba->regrade_all_questions();
558         // Verify.
559         $this->check_current_state(question_state::$gradedright);
560         $this->check_current_mark(3);
561     }
563     public function test_interactive_partial_no_submit() {
565         // Create a drag-and-drop question.
566         $dd = test_question_maker::make_question('ddmarker');
567         $dd->hints = array(
568             new question_hint_ddmarker(23, 'This is the first hint.',
569                     FORMAT_MOODLE, false, false, false),
570             new question_hint_ddmarker(24, 'This is the second hint.',
571                     FORMAT_MOODLE, true, true, false),
572         );
573         $dd->shufflechoices = false;
574         $this->start_attempt_at_question($dd, 'interactive', 3);
576         // Check the initial state.
577         $this->check_current_state(question_state::$todo);
578         $this->check_current_mark(null);
580         $this->check_current_output(
581                 $this->get_contains_draggable_marker_home_expectation(1, false),
582                 $this->get_contains_draggable_marker_home_expectation(2, false),
583                 $this->get_contains_draggable_marker_home_expectation(3, false),
584                 $this->get_contains_hidden_expectation(1),
585                 $this->get_contains_hidden_expectation(2),
586                 $this->get_contains_hidden_expectation(3),
587                 $this->get_contains_submit_button_expectation(true),
588                 $this->get_does_not_contain_feedback_expectation(),
589                 $this->get_tries_remaining_expectation(3),
590                 $this->get_no_hint_visible_expectation());
592         // Save the a partially right answer.
593         $this->process_submission(array('c1' => '50,50', 'c2' => '50,50', 'c3' => '100,150'));
595         // Finish the attempt without clicking check.
596         $this->quba->finish_all_questions();
598         // Verify.
599         $this->check_current_state(question_state::$gradedpartial);
600         $this->check_current_mark(2);
602         $this->check_current_output(
603                 $this->get_contains_draggable_marker_home_expectation(1, false),
604                 $this->get_contains_draggable_marker_home_expectation(2, false),
605                 $this->get_contains_draggable_marker_home_expectation(3, false),
606                 $this->get_contains_submit_button_expectation(false),
607                 $this->get_contains_partcorrect_expectation(),
608                 $this->get_no_hint_visible_expectation());
610         // Check regrading does not mess anything up.
611         $this->quba->regrade_all_questions();
613         // Verify.
614         $this->check_current_state(question_state::$gradedpartial);
615         $this->check_current_mark(2);
616     }
618     public function test_interactive_no_right_clears() {
620         // Create a drag-and-drop question.
621         $dd = test_question_maker::make_question('ddmarker');
622         $dd->hints = array(
623             new question_hint_ddmarker(23, 'This is the first hint.',
624                                                                 FORMAT_MOODLE, false, true, false),
625             new question_hint_ddmarker(24, 'This is the second hint.',
626                                                                 FORMAT_MOODLE, true, true, false),
627         );
628         $dd->shufflechoices = false;
629         $this->start_attempt_at_question($dd, 'interactive', 3);
631         // Check the initial state.
632         $this->check_current_state(question_state::$todo);
633         $this->check_current_mark(null);
635         $this->check_current_output(
636                 $this->get_contains_marked_out_of_summary(),
637                 $this->get_contains_draggable_marker_home_expectation(1, false),
638                 $this->get_contains_draggable_marker_home_expectation(2, false),
639                 $this->get_contains_draggable_marker_home_expectation(3, false),
640                 $this->get_contains_hidden_expectation(1),
641                 $this->get_contains_hidden_expectation(2),
642                 $this->get_contains_hidden_expectation(3),
643                 $this->get_contains_submit_button_expectation(true),
644                 $this->get_does_not_contain_feedback_expectation(),
645                 $this->get_tries_remaining_expectation(3),
646                 $this->get_no_hint_visible_expectation());
648         // Save the a completely wrong answer.
649         $this->process_submission(
650                     array('c1' => '100,150', 'c2' => '100,150', 'c3' => '50,50', '-submit' => 1));
652         // Verify.
653         $this->check_current_state(question_state::$todo);
654         $this->check_current_mark(null);
655         $this->check_current_output(
656                 $this->get_contains_marked_out_of_summary(),
657                 $this->get_contains_draggable_marker_home_expectation(1, false),
658                 $this->get_contains_draggable_marker_home_expectation(2, false),
659                 $this->get_contains_draggable_marker_home_expectation(3, false),
660                 $this->get_contains_submit_button_expectation(false),
661                 $this->get_contains_hint_expectation('This is the first hint'));
663         // Do try again.
664         $this->process_submission(
665                         array('c1' => '', 'c2' => '', 'c3' => '', '-tryagain' => 1));
667         // Check that all the wrong answers have been cleared.
668         $this->check_current_state(question_state::$todo);
669         $this->check_current_mark(null);
670         $this->check_current_output(
671                 $this->get_contains_marked_out_of_summary(),
672                 $this->get_contains_draggable_marker_home_expectation(1, false),
673                 $this->get_contains_draggable_marker_home_expectation(2, false),
674                 $this->get_contains_draggable_marker_home_expectation(3, false),
675                 $this->get_contains_hidden_expectation(1, ''),
676                 $this->get_contains_hidden_expectation(2, ''),
677                 $this->get_contains_hidden_expectation(3, ''),
678                 $this->get_contains_submit_button_expectation(true),
679                 $this->get_does_not_contain_feedback_expectation(),
680                 $this->get_tries_remaining_expectation(2),
681                 $this->get_no_hint_visible_expectation());
682     }
684     public function test_display_of_right_answer_when_shuffled() {
686         // Create a drag-and-drop question.
687         $dd = test_question_maker::make_question('ddmarker');
688         $this->start_attempt_at_question($dd, 'deferredfeedback', 3);
690         // Check the initial state.
691         $this->check_current_state(question_state::$todo);
692         $this->check_current_mark(null);
694         $this->check_current_output(
695                 $this->get_contains_hidden_expectation(1),
696                 $this->get_contains_hidden_expectation(2),
697                 $this->get_contains_hidden_expectation(3),
698                 $this->get_does_not_contain_feedback_expectation());
700         // Save a partial answer.
701         $this->process_submission($dd->get_correct_response());
703         // Verify.
704         $this->check_current_state(question_state::$complete);
705         $this->check_current_mark(null);
706         $rightanswer = array($dd->get_right_choice_for(1) => '50,50',
707                                 $dd->get_right_choice_for(2) => '150,50',
708                                 $dd->get_right_choice_for(3) => '100,150');
709         $this->check_current_output(
710             $this->get_contains_hidden_expectation(1, $rightanswer[1]),
711             $this->get_contains_hidden_expectation(2, $rightanswer[2]),
712             $this->get_contains_hidden_expectation(3, $rightanswer[3]),
713             $this->get_does_not_contain_correctness_expectation(),
714             $this->get_does_not_contain_feedback_expectation());
716         // Finish the attempt.
717         $this->quba->finish_all_questions();
719         // Verify.
720         $this->displayoptions->rightanswer = question_display_options::VISIBLE;
721         $this->assertEquals('{Drop zone 1 -> quick}, '.
722                             '{Drop zone 2 -> fox}, '.
723                             '{Drop zone 3 -> lazy}',
724                             $dd->get_right_answer_summary());
725         $this->check_current_state(question_state::$gradedright);
726         $this->check_current_mark(3);
727     }