2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Unit tests for the drag-and-drop onto image question type.
20 * @package qtype_ddimageortext
21 * @copyright 2010 The Open University
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
29 require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
30 require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php');
34 * Unit tests for the drag-and-drop onto image question type.
36 * @copyright 2010 The Open University
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base {
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.
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);
58 public function test_interactive_behaviour() {
60 // Create a drag-and-drop question.
61 $dd = test_question_maker::make_question('ddimageortext');
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),
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'));
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));
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 new question_pattern_expectation('/' .
136 preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'),
137 $this->get_contains_hint_expectation('This is the first hint'));
140 $this->process_submission(array('-tryagain' => 1));
143 $this->check_current_state(question_state::$todo);
144 $this->check_current_mark(null);
146 $this->check_current_output(
147 $this->get_contains_drag_image_home_expectation(1, 1, 1),
148 $this->get_contains_drag_image_home_expectation(2, 2, 1),
149 $this->get_contains_drag_image_home_expectation(3, 1, 2),
150 $this->get_contains_drag_image_home_expectation(4, 2, 2),
151 $this->get_contains_hidden_expectation(
152 $this->quba->get_field_prefix($this->slot) . 'p1', '2'),
153 $this->get_contains_hidden_expectation(
154 $this->quba->get_field_prefix($this->slot) . 'p2', '1'),
155 $this->get_contains_hidden_expectation(
156 $this->quba->get_field_prefix($this->slot) . 'p3', '2'),
157 $this->get_contains_hidden_expectation(
158 $this->quba->get_field_prefix($this->slot) . 'p4', '1'),
159 $this->get_contains_submit_button_expectation(true),
160 $this->get_does_not_contain_correctness_expectation(),
161 $this->get_does_not_contain_feedback_expectation(),
162 $this->get_tries_remaining_expectation(2),
163 $this->get_no_hint_visible_expectation());
165 // Submit the right answer.
166 $this->process_submission(
167 array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1));
170 $this->check_current_state(question_state::$gradedright);
171 $this->check_current_mark(8);
172 $this->check_current_output(
173 $this->get_contains_drag_image_home_expectation(1, 1, 1),
174 $this->get_contains_drag_image_home_expectation(2, 2, 1),
175 $this->get_contains_drag_image_home_expectation(3, 1, 2),
176 $this->get_contains_drag_image_home_expectation(4, 2, 2),
177 $this->get_contains_hidden_expectation(
178 $this->quba->get_field_prefix($this->slot) . 'p1', '1'),
179 $this->get_contains_hidden_expectation(
180 $this->quba->get_field_prefix($this->slot) . 'p2', '2'),
181 $this->get_contains_hidden_expectation(
182 $this->quba->get_field_prefix($this->slot) . 'p3', '1'),
183 $this->get_contains_hidden_expectation(
184 $this->quba->get_field_prefix($this->slot) . 'p4', '2'),
185 $this->get_contains_submit_button_expectation(false),
186 $this->get_contains_correct_expectation(),
187 $this->get_no_hint_visible_expectation());
189 // Check regrading does not mess anything up.
190 $this->quba->regrade_all_questions();
193 $this->check_current_state(question_state::$gradedright);
194 $this->check_current_mark(8);
197 public function test_deferred_feedback() {
199 // Create a drag-and-drop question.
200 $dd = test_question_maker::make_question('ddimageortext');
201 $dd->shufflechoices = false;
202 $this->start_attempt_at_question($dd, 'deferredfeedback', 12);
204 // Check the initial state.
205 $this->check_current_state(question_state::$todo);
206 $this->check_current_mark(null);
208 $this->check_current_output(
209 $this->get_contains_drag_image_home_expectation(1, 1, 1),
210 $this->get_contains_drag_image_home_expectation(2, 2, 1),
211 $this->get_contains_drag_image_home_expectation(3, 1, 2),
212 $this->get_contains_drag_image_home_expectation(4, 2, 2),
213 $this->get_contains_hidden_expectation(
214 $this->quba->get_field_prefix($this->slot) . 'p1'),
215 $this->get_contains_hidden_expectation(
216 $this->quba->get_field_prefix($this->slot) . 'p2'),
217 $this->get_contains_hidden_expectation(
218 $this->quba->get_field_prefix($this->slot) . 'p3'),
219 $this->get_contains_hidden_expectation(
220 $this->quba->get_field_prefix($this->slot) . 'p4'),
221 $this->get_does_not_contain_feedback_expectation());
223 // Save a partial answer.
224 $this->process_submission(array('p1' => '2', 'p2' => '1'));
226 $this->check_current_state(question_state::$invalid);
227 $this->check_current_mark(null);
229 $this->check_current_output(
230 $this->get_contains_drag_image_home_expectation(1, 1, 1),
231 $this->get_contains_drag_image_home_expectation(2, 2, 1),
232 $this->get_contains_drag_image_home_expectation(3, 1, 2),
233 $this->get_contains_drag_image_home_expectation(4, 2, 2),
234 $this->get_contains_hidden_expectation(
235 $this->quba->get_field_prefix($this->slot) . 'p1', 2),
236 $this->get_contains_hidden_expectation(
237 $this->quba->get_field_prefix($this->slot) . 'p2', 1),
238 $this->get_contains_hidden_expectation(
239 $this->quba->get_field_prefix($this->slot) . 'p3', ''),
240 $this->get_contains_hidden_expectation(
241 $this->quba->get_field_prefix($this->slot) . 'p4', ''),
242 $this->get_does_not_contain_correctness_expectation(),
243 $this->get_does_not_contain_feedback_expectation());
244 // Save the right answer.
245 $this->process_submission(
246 array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'));
249 $this->check_current_state(question_state::$complete);
250 $this->check_current_mark(null);
251 $this->check_current_output(
252 $this->get_contains_drag_image_home_expectation(1, 1, 1),
253 $this->get_contains_drag_image_home_expectation(2, 2, 1),
254 $this->get_contains_drag_image_home_expectation(3, 1, 2),
255 $this->get_contains_drag_image_home_expectation(4, 2, 2),
256 $this->get_contains_hidden_expectation(
257 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
258 $this->get_contains_hidden_expectation(
259 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
260 $this->get_contains_hidden_expectation(
261 $this->quba->get_field_prefix($this->slot) . 'p3', 1),
262 $this->get_contains_hidden_expectation(
263 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
264 $this->get_does_not_contain_correctness_expectation(),
265 $this->get_does_not_contain_feedback_expectation());
267 // Finish the attempt.
268 $this->quba->finish_all_questions();
271 $this->check_current_state(question_state::$gradedright);
272 $this->check_current_mark(12);
274 $this->check_current_output(
275 $this->get_contains_drag_image_home_expectation(1, 1, 1),
276 $this->get_contains_drag_image_home_expectation(2, 2, 1),
277 $this->get_contains_drag_image_home_expectation(3, 1, 2),
278 $this->get_contains_drag_image_home_expectation(4, 2, 2),
279 $this->get_contains_hidden_expectation(
280 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
281 $this->get_contains_hidden_expectation(
282 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
283 $this->get_contains_hidden_expectation(
284 $this->quba->get_field_prefix($this->slot) . 'p3', 1),
285 $this->get_contains_hidden_expectation(
286 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
287 $this->get_contains_correct_expectation());
289 // Change the right answer a bit.
290 $dd->rightchoices[2] = 1;
292 // Check regrading does not mess anything up.
293 $this->quba->regrade_all_questions();
296 $this->check_current_state(question_state::$gradedpartial);
297 $this->check_current_mark(9);
300 public function test_deferred_feedback_unanswered() {
302 // Create a drag-and-drop question.
303 $dd = test_question_maker::make_question('ddimageortext');
304 $dd->shufflechoices = false;
305 $this->start_attempt_at_question($dd, 'deferredfeedback', 12);
307 // Check the initial state.
308 $this->check_current_state(question_state::$todo);
309 $this->check_current_mark(null);
310 $this->check_current_output(
311 $this->get_contains_drag_image_home_expectation(1, 1, 1),
312 $this->get_contains_drag_image_home_expectation(2, 2, 1),
313 $this->get_contains_drag_image_home_expectation(3, 1, 2),
314 $this->get_contains_drag_image_home_expectation(4, 2, 2),
315 $this->get_contains_hidden_expectation(
316 $this->quba->get_field_prefix($this->slot) . 'p1'),
317 $this->get_contains_hidden_expectation(
318 $this->quba->get_field_prefix($this->slot) . 'p2'),
319 $this->get_contains_hidden_expectation(
320 $this->quba->get_field_prefix($this->slot) . 'p3'),
321 $this->get_contains_hidden_expectation(
322 $this->quba->get_field_prefix($this->slot) . 'p4'),
323 $this->get_does_not_contain_correctness_expectation(),
324 $this->get_does_not_contain_feedback_expectation());
325 $this->check_step_count(1);
327 // Save a blank response.
328 $this->process_submission(array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''));
331 $this->check_current_state(question_state::$todo);
332 $this->check_current_mark(null);
333 $this->check_current_output(
334 $this->get_contains_drag_image_home_expectation(1, 1, 1),
335 $this->get_contains_drag_image_home_expectation(2, 2, 1),
336 $this->get_contains_drag_image_home_expectation(3, 1, 2),
337 $this->get_contains_drag_image_home_expectation(4, 2, 2),
338 $this->get_contains_hidden_expectation(
339 $this->quba->get_field_prefix($this->slot) . 'p1', ''),
340 $this->get_contains_hidden_expectation(
341 $this->quba->get_field_prefix($this->slot) . 'p2', ''),
342 $this->get_contains_hidden_expectation(
343 $this->quba->get_field_prefix($this->slot) . 'p3', ''),
344 $this->get_contains_hidden_expectation(
345 $this->quba->get_field_prefix($this->slot) . 'p4', ''),
346 $this->get_does_not_contain_correctness_expectation(),
347 $this->get_does_not_contain_feedback_expectation());
348 $this->check_step_count(1);
350 // Finish the attempt.
351 $this->quba->finish_all_questions();
354 $this->check_current_state(question_state::$gaveup);
355 $this->check_current_mark(null);
356 $this->check_current_output(
357 $this->get_contains_drag_image_home_expectation(1, 1, 1),
358 $this->get_contains_drag_image_home_expectation(2, 2, 1),
359 $this->get_contains_drag_image_home_expectation(3, 1, 2),
360 $this->get_contains_drag_image_home_expectation(4, 2, 2));
363 public function test_deferred_feedback_partial_answer() {
365 // Create a drag-and-drop question.
366 $dd = test_question_maker::make_question('ddimageortext');
367 $dd->shufflechoices = false;
368 $this->start_attempt_at_question($dd, 'deferredfeedback', 3);
370 // Check the initial state.
371 $this->check_current_state(question_state::$todo);
372 $this->check_current_mark(null);
373 $this->check_current_output(
374 $this->get_contains_drag_image_home_expectation(1, 1, 1),
375 $this->get_contains_drag_image_home_expectation(2, 2, 1),
376 $this->get_contains_drag_image_home_expectation(3, 1, 2),
377 $this->get_contains_drag_image_home_expectation(4, 2, 2),
378 $this->get_contains_hidden_expectation(
379 $this->quba->get_field_prefix($this->slot) . 'p1'),
380 $this->get_contains_hidden_expectation(
381 $this->quba->get_field_prefix($this->slot) . 'p2'),
382 $this->get_contains_hidden_expectation(
383 $this->quba->get_field_prefix($this->slot) . 'p3'),
384 $this->get_contains_hidden_expectation(
385 $this->quba->get_field_prefix($this->slot) . 'p4'),
386 $this->get_does_not_contain_correctness_expectation(),
387 $this->get_does_not_contain_feedback_expectation());
389 // Save a partial response.
390 $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => ''));
393 $this->check_current_state(question_state::$invalid);
394 $this->check_current_mark(null);
395 $this->check_current_output(
396 $this->get_contains_drag_image_home_expectation(1, 1, 1),
397 $this->get_contains_drag_image_home_expectation(2, 2, 1),
398 $this->get_contains_drag_image_home_expectation(3, 1, 2),
399 $this->get_contains_drag_image_home_expectation(4, 2, 2),
400 $this->get_contains_hidden_expectation(
401 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
402 $this->get_contains_hidden_expectation(
403 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
404 $this->get_contains_hidden_expectation(
405 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
406 $this->get_contains_hidden_expectation(
407 $this->quba->get_field_prefix($this->slot) . 'p4', 0),
408 $this->get_does_not_contain_correctness_expectation(),
409 $this->get_does_not_contain_feedback_expectation());
411 // Finish the attempt.
412 $this->quba->finish_all_questions();
415 $this->check_current_state(question_state::$gradedpartial);
416 $this->check_current_mark(1.5);
417 $this->check_current_output(
418 $this->get_contains_drag_image_home_expectation(1, 1, 1),
419 $this->get_contains_drag_image_home_expectation(2, 2, 1),
420 $this->get_contains_drag_image_home_expectation(3, 1, 2),
421 $this->get_contains_drag_image_home_expectation(4, 2, 2),
422 $this->get_contains_partcorrect_expectation());
425 public function test_interactive_grading() {
427 // Create a drag-and-drop question.
428 $dd = test_question_maker::make_question('ddimageortext');
430 new question_hint_with_parts(1, 'This is the first hint.',
431 FORMAT_MOODLE, true, true),
432 new question_hint_with_parts(2, 'This is the second hint.',
433 FORMAT_MOODLE, true, true),
435 $dd->shufflechoices = false;
436 $this->start_attempt_at_question($dd, 'interactive', 12);
438 // Check the initial state.
439 $this->check_current_state(question_state::$todo);
440 $this->check_current_mark(null);
441 $this->assertEquals('interactivecountback',
442 $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
443 $this->check_current_output(
444 $this->get_contains_drag_image_home_expectation(1, 1, 1),
445 $this->get_contains_drag_image_home_expectation(2, 2, 1),
446 $this->get_contains_drag_image_home_expectation(3, 1, 2),
447 $this->get_contains_drag_image_home_expectation(4, 2, 2),
448 $this->get_contains_hidden_expectation(
449 $this->quba->get_field_prefix($this->slot) . 'p1'),
450 $this->get_contains_hidden_expectation(
451 $this->quba->get_field_prefix($this->slot) . 'p2'),
452 $this->get_contains_hidden_expectation(
453 $this->quba->get_field_prefix($this->slot) . 'p3'),
454 $this->get_contains_hidden_expectation(
455 $this->quba->get_field_prefix($this->slot) . 'p4'),
456 $this->get_contains_submit_button_expectation(true),
457 $this->get_does_not_contain_feedback_expectation(),
458 $this->get_tries_remaining_expectation(3),
459 $this->get_does_not_contain_num_parts_correct(),
460 $this->get_no_hint_visible_expectation());
462 // Submit an response with the first two parts right.
463 $this->process_submission(
464 array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '1', '-submit' => 1));
467 $this->check_current_state(question_state::$todo);
468 $this->check_current_mark(null);
469 $this->check_current_output(
470 $this->get_contains_drag_image_home_expectation(1, 1, 1),
471 $this->get_contains_drag_image_home_expectation(2, 2, 1),
472 $this->get_contains_drag_image_home_expectation(3, 1, 2),
473 $this->get_contains_drag_image_home_expectation(4, 2, 2),
474 $this->get_contains_submit_button_expectation(false),
475 $this->get_contains_try_again_button_expectation(true),
476 $this->get_does_not_contain_correctness_expectation(),
477 new question_pattern_expectation('/' .
478 preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'),
479 $this->get_contains_hint_expectation('This is the first hint'),
480 $this->get_contains_num_parts_correct(2),
481 $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),
482 $this->get_contains_hidden_expectation(
483 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
484 $this->get_contains_hidden_expectation(
485 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
486 $this->get_contains_hidden_expectation(
487 $this->quba->get_field_prefix($this->slot) . 'p3', 2),
488 $this->get_contains_hidden_expectation(
489 $this->quba->get_field_prefix($this->slot) . 'p4', 1));
491 // Check that extract responses will return the reset data.
492 $prefix = $this->quba->get_field_prefix($this->slot);
493 $this->assertEquals(array('p1' => '1', 'p2' => '2'),
494 $this->quba->extract_responses($this->slot,
495 array($prefix . 'p1' => '1', $prefix . 'p2' => '2', '-tryagain' => 1)));
498 // keys p3 and p4 are extra hidden fields to clear data.
499 $this->process_submission(
500 array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '', '-tryagain' => 1));
503 $this->check_current_state(question_state::$todo);
504 $this->check_current_mark(null);
505 $this->check_current_output(
506 $this->get_contains_drag_image_home_expectation(1, 1, 1),
507 $this->get_contains_drag_image_home_expectation(2, 2, 1),
508 $this->get_contains_drag_image_home_expectation(3, 1, 2),
509 $this->get_contains_drag_image_home_expectation(4, 2, 2),
510 $this->get_contains_hidden_expectation(
511 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
512 $this->get_contains_hidden_expectation(
513 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
514 $this->get_contains_hidden_expectation(
515 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
516 $this->get_contains_hidden_expectation(
517 $this->quba->get_field_prefix($this->slot) . 'p4', 0),
518 $this->get_contains_submit_button_expectation(true),
519 $this->get_does_not_contain_try_again_button_expectation(),
520 $this->get_does_not_contain_correctness_expectation(),
521 $this->get_does_not_contain_feedback_expectation(),
522 $this->get_tries_remaining_expectation(2),
523 $this->get_no_hint_visible_expectation());
525 // Submit an response with the first and last parts right.
526 $this->process_submission(
527 array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2', '-submit' => 1));
530 $this->check_current_state(question_state::$todo);
531 $this->check_current_mark(null);
532 $this->check_current_output(
533 $this->get_contains_drag_image_home_expectation(1, 1, 1),
534 $this->get_contains_drag_image_home_expectation(2, 2, 1),
535 $this->get_contains_drag_image_home_expectation(3, 1, 2),
536 $this->get_contains_drag_image_home_expectation(4, 2, 2),
537 $this->get_contains_submit_button_expectation(false),
538 $this->get_contains_try_again_button_expectation(true),
539 $this->get_does_not_contain_correctness_expectation(),
540 new question_pattern_expectation('/' .
541 preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'),
542 $this->get_contains_hint_expectation('This is the second hint'),
543 $this->get_contains_num_parts_correct(2),
544 $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),
545 $this->get_contains_hidden_expectation(
546 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
547 $this->get_contains_hidden_expectation(
548 $this->quba->get_field_prefix($this->slot) . 'p2', 1),
549 $this->get_contains_hidden_expectation(
550 $this->quba->get_field_prefix($this->slot) . 'p3', 2),
551 $this->get_contains_hidden_expectation(
552 $this->quba->get_field_prefix($this->slot) . 'p4', 2));
555 $this->process_submission(
556 array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => '2', '-tryagain' => 1));
559 $this->check_current_state(question_state::$todo);
560 $this->check_current_mark(null);
561 $this->check_current_output(
562 $this->get_contains_drag_image_home_expectation(1, 1, 1),
563 $this->get_contains_drag_image_home_expectation(2, 2, 1),
564 $this->get_contains_drag_image_home_expectation(3, 1, 2),
565 $this->get_contains_drag_image_home_expectation(4, 2, 2),
566 $this->get_contains_hidden_expectation(
567 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
568 $this->get_contains_hidden_expectation(
569 $this->quba->get_field_prefix($this->slot) . 'p2', 0),
570 $this->get_contains_hidden_expectation(
571 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
572 $this->get_contains_hidden_expectation(
573 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
574 $this->get_contains_submit_button_expectation(true),
575 $this->get_does_not_contain_try_again_button_expectation(),
576 $this->get_does_not_contain_correctness_expectation(),
577 $this->get_does_not_contain_feedback_expectation(),
578 $this->get_tries_remaining_expectation(1),
579 $this->get_no_hint_visible_expectation());
581 // Submit the right answer.
582 $this->process_submission(
583 array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1));
586 $this->check_current_state(question_state::$gradedright);
587 $this->check_current_mark(7);
588 $this->check_current_output(
589 $this->get_contains_drag_image_home_expectation(1, 1, 1),
590 $this->get_contains_drag_image_home_expectation(2, 2, 1),
591 $this->get_contains_drag_image_home_expectation(3, 1, 2),
592 $this->get_contains_drag_image_home_expectation(4, 2, 2),
593 $this->get_contains_hidden_expectation(
594 $this->quba->get_field_prefix($this->slot) . 'p1', 1),
595 $this->get_contains_hidden_expectation(
596 $this->quba->get_field_prefix($this->slot) . 'p2', 2),
597 $this->get_contains_hidden_expectation(
598 $this->quba->get_field_prefix($this->slot) . 'p3', 1),
599 $this->get_contains_hidden_expectation(
600 $this->quba->get_field_prefix($this->slot) . 'p4', 2),
601 $this->get_contains_submit_button_expectation(false),
602 $this->get_does_not_contain_try_again_button_expectation(),
603 $this->get_contains_correct_expectation(),
604 $this->get_no_hint_visible_expectation(),
605 $this->get_does_not_contain_num_parts_correct(),
606 $this->get_contains_standard_correct_combined_feedback_expectation());
609 public function test_interactive_correct_no_submit() {
611 // Create a drag-and-drop question.
612 $dd = test_question_maker::make_question('ddimageortext');
614 new question_hint_with_parts(23, 'This is the first hint.',
615 FORMAT_MOODLE, false, false),
616 new question_hint_with_parts(24, 'This is the second hint.',
617 FORMAT_MOODLE, true, true),
619 $dd->shufflechoices = false;
620 $this->start_attempt_at_question($dd, 'interactive', 3);
622 // Check the initial state.
623 $this->check_current_state(question_state::$todo);
624 $this->check_current_mark(null);
625 $this->check_current_output(
626 $this->get_contains_drag_image_home_expectation(1, 1, 1),
627 $this->get_contains_drag_image_home_expectation(2, 2, 1),
628 $this->get_contains_drag_image_home_expectation(3, 1, 2),
629 $this->get_contains_drag_image_home_expectation(4, 2, 2),
630 $this->get_contains_hidden_expectation(
631 $this->quba->get_field_prefix($this->slot) . 'p1'),
632 $this->get_contains_hidden_expectation(
633 $this->quba->get_field_prefix($this->slot) . 'p2'),
634 $this->get_contains_hidden_expectation(
635 $this->quba->get_field_prefix($this->slot) . 'p3'),
636 $this->get_contains_hidden_expectation(
637 $this->quba->get_field_prefix($this->slot) . 'p4'),
638 $this->get_contains_submit_button_expectation(true),
639 $this->get_does_not_contain_feedback_expectation(),
640 $this->get_tries_remaining_expectation(3),
641 $this->get_no_hint_visible_expectation());
643 // Save the right answer.
644 $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'));
646 // Finish the attempt without clicking check.
647 $this->quba->finish_all_questions();
650 $this->check_current_state(question_state::$gradedright);
651 $this->check_current_mark(3);
652 $this->check_current_output(
653 $this->get_contains_drag_image_home_expectation(1, 1, 1),
654 $this->get_contains_drag_image_home_expectation(2, 2, 1),
655 $this->get_contains_drag_image_home_expectation(3, 1, 2),
656 $this->get_contains_drag_image_home_expectation(4, 2, 2),
657 $this->get_contains_submit_button_expectation(false),
658 $this->get_contains_correct_expectation(),
659 $this->get_no_hint_visible_expectation());
661 // Check regrading does not mess anything up.
662 $this->quba->regrade_all_questions();
665 $this->check_current_state(question_state::$gradedright);
666 $this->check_current_mark(3);
669 public function test_interactive_partial_no_submit() {
671 // Create a drag-and-drop question.
672 $dd = test_question_maker::make_question('ddimageortext');
674 new question_hint_with_parts(23, 'This is the first hint.',
675 FORMAT_MOODLE, false, false),
676 new question_hint_with_parts(24, 'This is the second hint.',
677 FORMAT_MOODLE, true, true),
679 $dd->shufflechoices = false;
680 $this->start_attempt_at_question($dd, 'interactive', 4);
682 // Check the initial state.
683 $this->check_current_state(question_state::$todo);
684 $this->check_current_mark(null);
686 $this->check_current_output(
687 $this->get_contains_drag_image_home_expectation(1, 1, 1),
688 $this->get_contains_drag_image_home_expectation(2, 2, 1),
689 $this->get_contains_drag_image_home_expectation(3, 1, 2),
690 $this->get_contains_drag_image_home_expectation(4, 2, 2),
691 $this->get_contains_hidden_expectation(
692 $this->quba->get_field_prefix($this->slot) . 'p1'),
693 $this->get_contains_hidden_expectation(
694 $this->quba->get_field_prefix($this->slot) . 'p2'),
695 $this->get_contains_hidden_expectation(
696 $this->quba->get_field_prefix($this->slot) . 'p3'),
697 $this->get_contains_hidden_expectation(
698 $this->quba->get_field_prefix($this->slot) . 'p4'),
699 $this->get_contains_submit_button_expectation(true),
700 $this->get_does_not_contain_feedback_expectation(),
701 $this->get_tries_remaining_expectation(3),
702 $this->get_no_hint_visible_expectation());
704 // Save the a partially right answer.
705 $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '1'));
707 // Finish the attempt without clicking check.
708 $this->quba->finish_all_questions();
711 $this->check_current_state(question_state::$gradedpartial);
712 $this->check_current_mark(1);
714 $this->check_current_output(
715 $this->get_contains_drag_image_home_expectation(1, 1, 1),
716 $this->get_contains_drag_image_home_expectation(2, 2, 1),
717 $this->get_contains_drag_image_home_expectation(3, 1, 2),
718 $this->get_contains_drag_image_home_expectation(4, 2, 2),
719 $this->get_contains_submit_button_expectation(false),
720 $this->get_contains_partcorrect_expectation(),
721 $this->get_no_hint_visible_expectation());
723 // Check regrading does not mess anything up.
724 $this->quba->regrade_all_questions();
727 $this->check_current_state(question_state::$gradedpartial);
728 $this->check_current_mark(1);
731 public function test_interactive_no_right_clears() {
733 // Create a drag-and-drop question.
734 $dd = test_question_maker::make_question('ddimageortext');
736 new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true),
737 new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true),
739 $dd->shufflechoices = false;
740 $this->start_attempt_at_question($dd, 'interactive', 3);
742 // Check the initial state.
743 $this->check_current_state(question_state::$todo);
744 $this->check_current_mark(null);
746 $this->check_current_output(
747 $this->get_contains_marked_out_of_summary(),
748 $this->get_contains_drag_image_home_expectation(1, 1, 1),
749 $this->get_contains_drag_image_home_expectation(2, 2, 1),
750 $this->get_contains_drag_image_home_expectation(3, 1, 2),
751 $this->get_contains_drag_image_home_expectation(4, 2, 2),
752 $this->get_contains_hidden_expectation(
753 $this->quba->get_field_prefix($this->slot) . 'p1'),
754 $this->get_contains_hidden_expectation(
755 $this->quba->get_field_prefix($this->slot) . 'p2'),
756 $this->get_contains_hidden_expectation(
757 $this->quba->get_field_prefix($this->slot) . 'p3'),
758 $this->get_contains_hidden_expectation(
759 $this->quba->get_field_prefix($this->slot) . 'p4'),
760 $this->get_contains_submit_button_expectation(true),
761 $this->get_does_not_contain_feedback_expectation(),
762 $this->get_tries_remaining_expectation(3),
763 $this->get_no_hint_visible_expectation());
765 // Save the a completely wrong answer.
766 $this->process_submission(
767 array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1));
770 $this->check_current_state(question_state::$todo);
771 $this->check_current_mark(null);
772 $this->check_current_output(
773 $this->get_contains_marked_out_of_summary(),
774 $this->get_contains_drag_image_home_expectation(1, 1, 1),
775 $this->get_contains_drag_image_home_expectation(2, 2, 1),
776 $this->get_contains_drag_image_home_expectation(3, 1, 2),
777 $this->get_contains_drag_image_home_expectation(4, 2, 2),
778 $this->get_contains_submit_button_expectation(false),
779 $this->get_contains_hint_expectation('This is the first hint'));
782 $this->process_submission(
783 array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '', '-tryagain' => 1));
785 // Check that all the wrong answers have been cleared.
786 $this->check_current_state(question_state::$todo);
787 $this->check_current_mark(null);
788 $this->check_current_output(
789 $this->get_contains_marked_out_of_summary(),
790 $this->get_contains_drag_image_home_expectation(1, 1, 1),
791 $this->get_contains_drag_image_home_expectation(2, 2, 1),
792 $this->get_contains_drag_image_home_expectation(3, 1, 2),
793 $this->get_contains_drag_image_home_expectation(4, 2, 2),
794 $this->get_contains_hidden_expectation(
795 $this->quba->get_field_prefix($this->slot) . 'p1', 0),
796 $this->get_contains_hidden_expectation(
797 $this->quba->get_field_prefix($this->slot) . 'p2', 0),
798 $this->get_contains_hidden_expectation(
799 $this->quba->get_field_prefix($this->slot) . 'p3', 0),
800 $this->get_contains_hidden_expectation(
801 $this->quba->get_field_prefix($this->slot) . 'p4', 0),
802 $this->get_contains_submit_button_expectation(true),
803 $this->get_does_not_contain_feedback_expectation(),
804 $this->get_tries_remaining_expectation(2),
805 $this->get_no_hint_visible_expectation());
808 public function test_display_of_right_answer_when_shuffled() {
810 // Create a drag-and-drop question.
811 $dd = test_question_maker::make_question('ddimageortext');
812 $this->start_attempt_at_question($dd, 'deferredfeedback', 3);
814 // Check the initial state.
815 $this->check_current_state(question_state::$todo);
816 $this->check_current_mark(null);
818 $this->check_current_output(
819 $this->get_contains_hidden_expectation(
820 $this->quba->get_field_prefix($this->slot) . 'p1'),
821 $this->get_contains_hidden_expectation(
822 $this->quba->get_field_prefix($this->slot) . 'p2'),
823 $this->get_contains_hidden_expectation(
824 $this->quba->get_field_prefix($this->slot) . 'p3'),
825 $this->get_contains_hidden_expectation(
826 $this->quba->get_field_prefix($this->slot) . 'p4'),
827 $this->get_does_not_contain_feedback_expectation());
829 // Save a partial answer.
830 $this->process_submission($dd->get_correct_response());
833 $this->check_current_state(question_state::$complete);
834 $this->check_current_mark(null);
835 $this->check_current_output(
836 $this->get_contains_hidden_expectation(
837 $this->quba->get_field_prefix($this->slot) . 'p1',
838 $dd->get_right_choice_for(1)),
839 $this->get_contains_hidden_expectation(
840 $this->quba->get_field_prefix($this->slot) . 'p2',
841 $dd->get_right_choice_for(2)),
842 $this->get_contains_hidden_expectation(
843 $this->quba->get_field_prefix($this->slot) . 'p3',
844 $dd->get_right_choice_for(3)),
845 $this->get_contains_hidden_expectation(
846 $this->quba->get_field_prefix($this->slot) . 'p4',
847 $dd->get_right_choice_for(4)),
848 $this->get_does_not_contain_correctness_expectation(),
849 $this->get_does_not_contain_feedback_expectation());
851 // Finish the attempt.
852 $this->quba->finish_all_questions();
855 $this->displayoptions->rightanswer = question_display_options::VISIBLE;
856 $this->assertEquals('Drop zone 1 -> {1. quick} '.
857 'Drop zone 2 -> {2. fox} '.
858 'Drop zone 3 -> {3. lazy} '.
859 'Drop zone 4 -> {4. dog}',
860 $dd->get_right_answer_summary());
861 $this->check_current_state(question_state::$gradedright);
862 $this->check_current_mark(3);