on-demand release 4.0dev+
[moodle.git] / question / type / essay / tests / walkthrough_test.php
CommitLineData
c0d12fc1
TH
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * This file contains tests that walks essay questions through some attempts.
19 *
20 * @package qtype_essay
21 * @copyright 2013 The Open University
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
30
31
32/**
33 * Unit tests for the essay question type.
34 *
35 * @copyright 2013 The Open University
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 */
afb1b3d0 38class qtype_essay_walkthrough_testcase extends qbehaviour_walkthrough_test_base {
c0d12fc1
TH
39
40 protected function check_contains_textarea($name, $content = '', $height = 10) {
41 $fieldname = $this->quba->get_field_prefix($this->slot) . $name;
42
43 $this->assertTag(array('tag' => 'textarea',
44 'attributes' => array('cols' => '60', 'rows' => $height,
45 'name' => $fieldname)),
46 $this->currentoutput);
47
48 if ($content) {
ba5b6089 49 $this->assertMatchesRegularExpression('/' . preg_quote(s($content), '/') . '/', $this->currentoutput);
c0d12fc1
TH
50 }
51 }
52
afb1b3d0
TH
53 /**
54 * Helper method: Store a test file with a given name and contents in a
55 * draft file area.
56 *
57 * @param int $usercontextid user context id.
58 * @param int $draftitemid draft item id.
59 * @param string $filename filename.
60 * @param string $contents file contents.
61 */
62 protected function save_file_to_draft_area($usercontextid, $draftitemid, $filename, $contents) {
63 $fs = get_file_storage();
64
65 $filerecord = new stdClass();
66 $filerecord->contextid = $usercontextid;
67 $filerecord->component = 'user';
68 $filerecord->filearea = 'draft';
69 $filerecord->itemid = $draftitemid;
70 $filerecord->filepath = '/';
71 $filerecord->filename = $filename;
72 $fs->create_file_from_string($filerecord, $contents);
73 }
74
c0d12fc1 75 public function test_deferred_feedback_html_editor() {
d32bc7d6 76 global $PAGE;
c0d12fc1 77
6e4dcb9a 78 // The current text editor depends on the users profile setting - so it needs a valid user.
c9697538 79 $this->setAdminUser();
d32bc7d6
DW
80 // Required to init a text editor.
81 $PAGE->set_url('/');
c9697538 82
60527d0c 83 // Create an essay question.
c0d12fc1
TH
84 $q = test_question_maker::make_question('essay', 'editor');
85 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
86
87 $prefix = $this->quba->get_field_prefix($this->slot);
88 $fieldname = $prefix . 'answer';
89 $response = '<p>The <b>cat</b> sat on the mat. Then it ate a <b>frog</b>.</p>';
90
91 // Check the initial state.
92 $this->check_current_state(question_state::$todo);
93 $this->check_current_mark(null);
94 $this->render();
95 $this->check_contains_textarea('answer', '');
96 $this->check_current_output(
97 $this->get_contains_question_text_expectation($q),
98 $this->get_does_not_contain_feedback_expectation());
99 $this->check_step_count(1);
100
101 // Save a response.
102 $this->quba->process_all_actions(null, array(
103 'slots' => $this->slot,
104 $fieldname => $response,
105 $fieldname . 'format' => FORMAT_HTML,
106 $prefix . ':sequencecheck' => '1',
107 ));
108
109 // Verify.
110 $this->check_current_state(question_state::$complete);
111 $this->check_current_mark(null);
112 $this->check_step_count(2);
113 $this->render();
114 $this->check_contains_textarea('answer', $response);
115 $this->check_current_output(
116 $this->get_contains_question_text_expectation($q),
117 $this->get_does_not_contain_feedback_expectation());
118 $this->check_step_count(2);
119
120 // Finish the attempt.
121 $this->quba->finish_all_questions();
122
123 // Verify.
124 $this->check_current_state(question_state::$needsgrading);
125 $this->check_current_mark(null);
126 $this->render();
ba5b6089 127 $this->assertMatchesRegularExpression('/' . preg_quote($response, '/') . '/', $this->currentoutput);
c0d12fc1
TH
128 $this->check_current_output(
129 $this->get_contains_question_text_expectation($q),
130 $this->get_contains_general_feedback_expectation($q));
131 }
132
133 public function test_deferred_feedback_plain_text() {
134
60527d0c 135 // Create an essay question.
c0d12fc1
TH
136 $q = test_question_maker::make_question('essay', 'plain');
137 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
138
139 $prefix = $this->quba->get_field_prefix($this->slot);
140 $fieldname = $prefix . 'answer';
141 $response = "x < 1\nx > 0\nFrog & Toad were friends.";
142
143 // Check the initial state.
144 $this->check_current_state(question_state::$todo);
145 $this->check_current_mark(null);
146 $this->render();
147 $this->check_contains_textarea('answer', '');
148 $this->check_current_output(
149 $this->get_contains_question_text_expectation($q),
150 $this->get_does_not_contain_feedback_expectation());
151 $this->check_step_count(1);
152
153 // Save a response.
154 $this->quba->process_all_actions(null, array(
155 'slots' => $this->slot,
156 $fieldname => $response,
157 $fieldname . 'format' => FORMAT_HTML,
158 $prefix . ':sequencecheck' => '1',
159 ));
160
161 // Verify.
162 $this->check_current_state(question_state::$complete);
163 $this->check_current_mark(null);
164 $this->check_step_count(2);
165 $this->render();
166 $this->check_contains_textarea('answer', $response);
167 $this->check_current_output(
168 $this->get_contains_question_text_expectation($q),
169 $this->get_does_not_contain_feedback_expectation());
170 $this->check_step_count(2);
171
172 // Finish the attempt.
173 $this->quba->finish_all_questions();
174
175 // Verify.
176 $this->check_current_state(question_state::$needsgrading);
177 $this->check_current_mark(null);
178 $this->render();
ba5b6089 179 $this->assertMatchesRegularExpression('/' . preg_quote(s($response), '/') . '/', $this->currentoutput);
c0d12fc1
TH
180 $this->check_current_output(
181 $this->get_contains_question_text_expectation($q),
182 $this->get_contains_general_feedback_expectation($q));
183 }
60527d0c
JMV
184
185 public function test_responsetemplate() {
d32bc7d6 186 global $PAGE;
60527d0c 187
6e4dcb9a 188 // The current text editor depends on the users profile setting - so it needs a valid user.
c9697538 189 $this->setAdminUser();
d32bc7d6
DW
190 // Required to init a text editor.
191 $PAGE->set_url('/');
c9697538 192
60527d0c
JMV
193 // Create an essay question.
194 $q = test_question_maker::make_question('essay', 'responsetemplate');
195 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
196
197 $prefix = $this->quba->get_field_prefix($this->slot);
198 $fieldname = $prefix . 'answer';
199
200 // Check the initial state.
201 $this->check_current_state(question_state::$todo);
202 $this->check_current_mark(null);
203 $this->render();
204 $this->check_contains_textarea('answer', 'Once upon a time');
205 $this->check_current_output(
206 $this->get_contains_question_text_expectation($q),
207 $this->get_does_not_contain_feedback_expectation());
208 $this->check_step_count(1);
209
210 // Save.
211 $this->quba->process_all_actions(null, array(
212 'slots' => $this->slot,
213 $fieldname => 'Once upon a time there was a little green frog.',
214 $fieldname . 'format' => FORMAT_HTML,
215 $prefix . ':sequencecheck' => '1',
216 ));
217
218 // Verify.
219 $this->check_current_state(question_state::$complete);
220 $this->check_current_mark(null);
221 $this->check_step_count(2);
222 $this->render();
223 $this->check_contains_textarea('answer', 'Once upon a time there was a little green frog.');
224 $this->check_current_output(
225 $this->get_contains_question_text_expectation($q),
226 $this->get_does_not_contain_feedback_expectation());
227 $this->check_step_count(2);
228
229 // Finish the attempt.
230 $this->quba->finish_all_questions();
231
232 // Verify.
233 $this->check_current_state(question_state::$needsgrading);
234 $this->check_current_mark(null);
235 $this->render();
713722c3
EL
236 $this->assertMatchesRegularExpression(
237 '/' . preg_quote(s('Once upon a time there was a little green frog.'), '/') . '/', $this->currentoutput);
60527d0c
JMV
238 $this->check_current_output(
239 $this->get_contains_question_text_expectation($q),
240 $this->get_contains_general_feedback_expectation($q));
241 }
afb1b3d0
TH
242
243 public function test_deferred_feedback_html_editor_with_files_attempt_on_last() {
d32bc7d6 244 global $CFG, $USER, $PAGE;
afb1b3d0
TH
245
246 $this->resetAfterTest(true);
247 $this->setAdminUser();
d32bc7d6
DW
248 // Required to init a text editor.
249 $PAGE->set_url('/');
afb1b3d0
TH
250 $usercontextid = context_user::instance($USER->id)->id;
251 $fs = get_file_storage();
252
253 // Create an essay question in the DB.
254 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
255 $cat = $generator->create_question_category();
256 $question = $generator->create_question('essay', 'editorfilepicker', array('category' => $cat->id));
257
258 // Start attempt at the question.
259 $q = question_bank::load_question($question->id);
260 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
261
262 $this->check_current_state(question_state::$todo);
263 $this->check_current_mark(null);
264 $this->check_step_count(1);
265
266 // Process a response and check the expected result.
267 // First we need to get the draft item ids.
268 $this->render();
269 if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
270 throw new coding_exception('Editor draft item id not found.');
271 }
272 $editordraftid = $matches[1];
273 if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
274 throw new coding_exception('File manager draft item id not found.');
275 }
276 $attachementsdraftid = $matches[1];
277
278 $this->save_file_to_draft_area($usercontextid, $editordraftid, 'smile.txt', ':-)');
279 $this->save_file_to_draft_area($usercontextid, $attachementsdraftid, 'greeting.txt', 'Hello world!');
280 $this->process_submission(array(
281 'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
282 "/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
283 '" alt="smile">.',
284 'answerformat' => FORMAT_HTML,
285 'answer:itemid' => $editordraftid,
286 'attachments' => $attachementsdraftid));
287
288 $this->check_current_state(question_state::$complete);
289 $this->check_current_mark(null);
290 $this->check_step_count(2);
291 $this->save_quba();
292
293 // Save the same response again, and verify no new step is created.
294 $this->load_quba();
295
296 $this->render();
297 if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
298 throw new coding_exception('Editor draft item id not found.');
299 }
300 $editordraftid = $matches[1];
301 if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
302 throw new coding_exception('File manager draft item id not found.');
303 }
304 $attachementsdraftid = $matches[1];
305
306 $this->process_submission(array(
307 'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
308 "/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
309 '" alt="smile">.',
310 'answerformat' => FORMAT_HTML,
311 'answer:itemid' => $editordraftid,
312 'attachments' => $attachementsdraftid));
313
314 $this->check_current_state(question_state::$complete);
315 $this->check_current_mark(null);
316 $this->check_step_count(2);
317
318 // Now submit all and finish.
319 $this->finish();
320 $this->check_current_state(question_state::$needsgrading);
321 $this->check_current_mark(null);
322 $this->check_step_count(3);
323 $this->save_quba();
324
325 // Now start a new attempt based on the old one.
326 $this->load_quba();
327 $oldqa = $this->get_question_attempt();
328
329 $q = question_bank::load_question($question->id);
330 $this->quba = question_engine::make_questions_usage_by_activity('unit_test',
331 context_system::instance());
332 $this->quba->set_preferred_behaviour('deferredfeedback');
333 $this->slot = $this->quba->add_question($q, 1);
334 $this->quba->start_question_based_on($this->slot, $oldqa);
335
336 $this->check_current_state(question_state::$complete);
337 $this->check_current_mark(null);
338 $this->check_step_count(1);
339 $this->save_quba();
340
341 // Now save the same response again, and ensure that a new step is not created.
342 $this->load_quba();
343
344 $this->render();
345 if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
346 throw new coding_exception('Editor draft item id not found.');
347 }
348 $editordraftid = $matches[1];
349 if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
350 throw new coding_exception('File manager draft item id not found.');
351 }
352 $attachementsdraftid = $matches[1];
353
354 $this->process_submission(array(
355 'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
356 "/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
357 '" alt="smile">.',
358 'answerformat' => FORMAT_HTML,
359 'answer:itemid' => $editordraftid,
360 'attachments' => $attachementsdraftid));
361
362 $this->check_current_state(question_state::$complete);
363 $this->check_current_mark(null);
364 $this->check_step_count(1);
365 }
d629327a
TH
366
367 public function test_deferred_feedback_html_editor_with_files_attempt_on_last_no_files_uploaded() {
d32bc7d6 368 global $CFG, $USER, $PAGE;
d629327a
TH
369
370 $this->resetAfterTest(true);
371 $this->setAdminUser();
d32bc7d6
DW
372 // Required to init a text editor.
373 $PAGE->set_url('/');
d629327a
TH
374 $usercontextid = context_user::instance($USER->id)->id;
375 $fs = get_file_storage();
376
377 // Create an essay question in the DB.
378 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
379 $cat = $generator->create_question_category();
380 $question = $generator->create_question('essay', 'editorfilepicker', array('category' => $cat->id));
381
382 // Start attempt at the question.
383 $q = question_bank::load_question($question->id);
384 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
385
386 $this->check_current_state(question_state::$todo);
387 $this->check_current_mark(null);
388 $this->check_step_count(1);
389
390 // Process a response and check the expected result.
391 // First we need to get the draft item ids.
392 $this->render();
393 if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
394 throw new coding_exception('Editor draft item id not found.');
395 }
396 $editordraftid = $matches[1];
397 if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
398 throw new coding_exception('File manager draft item id not found.');
399 }
400 $attachementsdraftid = $matches[1];
401
402 $this->process_submission(array(
403 'answer' => 'I refuse to draw you a picture, so there!',
404 'answerformat' => FORMAT_HTML,
405 'answer:itemid' => $editordraftid,
406 'attachments' => $attachementsdraftid));
407
408 $this->check_current_state(question_state::$complete);
409 $this->check_current_mark(null);
410 $this->check_step_count(2);
411 $this->save_quba();
412
413 // Now submit all and finish.
414 $this->finish();
415 $this->check_current_state(question_state::$needsgrading);
416 $this->check_current_mark(null);
417 $this->check_step_count(3);
418 $this->save_quba();
419
420 // Now start a new attempt based on the old one.
421 $this->load_quba();
422 $oldqa = $this->get_question_attempt();
423
424 $q = question_bank::load_question($question->id);
425 $this->quba = question_engine::make_questions_usage_by_activity('unit_test',
426 context_system::instance());
427 $this->quba->set_preferred_behaviour('deferredfeedback');
428 $this->slot = $this->quba->add_question($q, 1);
429 $this->quba->start_question_based_on($this->slot, $oldqa);
430
431 $this->check_current_state(question_state::$complete);
432 $this->check_current_mark(null);
433 $this->check_step_count(1);
434 $this->save_quba();
435
436 // Check the display.
437 $this->load_quba();
438 $this->render();
ba5b6089 439 $this->assertMatchesRegularExpression('/I refuse to draw you a picture, so there!/', $this->currentoutput);
d629327a 440 }
3fc9410f
TH
441
442 public function test_deferred_feedback_plain_attempt_on_last() {
443 global $CFG, $USER;
444
445 $this->resetAfterTest(true);
446 $this->setAdminUser();
447 $usercontextid = context_user::instance($USER->id)->id;
448
449 // Create an essay question in the DB.
450 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
451 $cat = $generator->create_question_category();
452 $question = $generator->create_question('essay', 'plain', array('category' => $cat->id));
453
454 // Start attempt at the question.
455 $q = question_bank::load_question($question->id);
456 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
457
458 $this->check_current_state(question_state::$todo);
459 $this->check_current_mark(null);
460 $this->check_step_count(1);
461
462 // Process a response and check the expected result.
463
464 $this->process_submission(array(
465 'answer' => 'Once upon a time there was a frog called Freddy. He lived happily ever after.',
466 'answerformat' => FORMAT_PLAIN,
467 ));
468
469 $this->check_current_state(question_state::$complete);
470 $this->check_current_mark(null);
471 $this->check_step_count(2);
472 $this->save_quba();
473
474 // Now submit all and finish.
475 $this->finish();
476 $this->check_current_state(question_state::$needsgrading);
477 $this->check_current_mark(null);
478 $this->check_step_count(3);
479 $this->save_quba();
480
481 // Now start a new attempt based on the old one.
482 $this->load_quba();
483 $oldqa = $this->get_question_attempt();
484
485 $q = question_bank::load_question($question->id);
486 $this->quba = question_engine::make_questions_usage_by_activity('unit_test',
487 context_system::instance());
488 $this->quba->set_preferred_behaviour('deferredfeedback');
489 $this->slot = $this->quba->add_question($q, 1);
490 $this->quba->start_question_based_on($this->slot, $oldqa);
491
492 $this->check_current_state(question_state::$complete);
493 $this->check_current_mark(null);
494 $this->check_step_count(1);
495 $this->save_quba();
496
497 // Check the display.
498 $this->load_quba();
499 $this->render();
500 // Test taht no HTML comment has been added to the response.
713722c3
EL
501 $this->assertMatchesRegularExpression(
502 '/Once upon a time there was a frog called Freddy. He lived happily ever after.(?!&lt;!--)/', $this->currentoutput);
3fc9410f 503 // Test for the hash of an empty file area.
40de097e 504 $this->assertStringNotContainsString('d41d8cd98f00b204e9800998ecf8427e', $this->currentoutput);
3fc9410f 505 }
94cb5a66
LB
506
507 public function test_deferred_feedback_html_editor_with_files_attempt_wrong_filetypes() {
508 global $CFG, $USER, $PAGE;
509
510 $this->resetAfterTest(true);
511 $this->setAdminUser();
512 // Required to init a text editor.
513 $PAGE->set_url('/');
514 $usercontextid = context_user::instance($USER->id)->id;
515 $fs = get_file_storage();
516
517 // Create an essay question in the DB.
518 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
519 $cat = $generator->create_question_category();
520 $question = $generator->create_question('essay', 'editorfilepicker', array('category' => $cat->id));
521
522 // Start attempt at the question.
523 $q = question_bank::load_question($question->id);
99778a61 524 $q->filetypeslist = '.pdf,.docx';
94cb5a66
LB
525 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
526
527 $this->check_current_state(question_state::$todo);
528 $this->check_current_mark(null);
529 $this->check_step_count(1);
530
531 // Process a response and check the expected result.
532 // First we need to get the draft item ids.
533 $this->render();
534 if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
535 throw new coding_exception('Editor draft item id not found.');
536 }
537 $editordraftid = $matches[1];
538 if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
539 throw new coding_exception('File manager draft item id not found.');
540 }
541 $attachementsdraftid = $matches[1];
542
543 $this->save_file_to_draft_area($usercontextid, $editordraftid, 'smile.txt', ':-)');
544 $this->save_file_to_draft_area($usercontextid, $attachementsdraftid, 'greeting.txt', 'Hello world!');
545 $this->process_submission(array(
546 'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
547 "/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
548 '" alt="smile">.',
549 'answerformat' => FORMAT_HTML,
550 'answer:itemid' => $editordraftid,
551 'attachments' => $attachementsdraftid));
552
553 $this->check_current_state(question_state::$invalid);
554 $this->check_current_mark(null);
555 $this->check_step_count(2);
556 $this->save_quba();
557
558 // Now submit all and finish.
559 $this->finish();
560 $this->check_current_state(question_state::$needsgrading);
561 $this->check_current_mark(null);
562 $this->check_step_count(3);
563 $this->save_quba();
564 }
565
566 public function test_deferred_feedback_html_editor_with_files_attempt_correct_filetypes() {
567 global $CFG, $USER, $PAGE;
568
569 $this->resetAfterTest(true);
570 $this->setAdminUser();
571 // Required to init a text editor.
572 $PAGE->set_url('/');
573 $usercontextid = context_user::instance($USER->id)->id;
574 $fs = get_file_storage();
575
576 // Create an essay question in the DB.
577 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
578 $cat = $generator->create_question_category();
579 $question = $generator->create_question('essay', 'editorfilepicker', array('category' => $cat->id));
580
581 // Start attempt at the question.
582 $q = question_bank::load_question($question->id);
99778a61 583 $q->filetypeslist = '.txt,.docx';
94cb5a66
LB
584 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
585
586 $this->check_current_state(question_state::$todo);
587 $this->check_current_mark(null);
588 $this->check_step_count(1);
589
590 // Process a response and check the expected result.
591 // First we need to get the draft item ids.
592 $this->render();
593 if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
594 throw new coding_exception('Editor draft item id not found.');
595 }
596 $editordraftid = $matches[1];
597 if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
598 throw new coding_exception('File manager draft item id not found.');
599 }
600 $attachementsdraftid = $matches[1];
601
602 $this->save_file_to_draft_area($usercontextid, $editordraftid, 'smile.txt', ':-)');
603 $this->save_file_to_draft_area($usercontextid, $attachementsdraftid, 'greeting.txt', 'Hello world!');
604 $this->process_submission(array(
605 'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
606 "/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
607 '" alt="smile">.',
608 'answerformat' => FORMAT_HTML,
609 'answer:itemid' => $editordraftid,
610 'attachments' => $attachementsdraftid));
611
612 $this->check_current_state(question_state::$complete);
613 $this->check_current_mark(null);
614 $this->check_step_count(2);
615 $this->save_quba();
616
617 // Now submit all and finish.
618 $this->finish();
619 $this->check_current_state(question_state::$needsgrading);
620 $this->check_current_mark(null);
621 $this->check_step_count(3);
622 $this->save_quba();
623 }
d9b0da85
TH
624
625 public function test_deferred_feedback_word_limits() {
626 global $PAGE;
627
628 // The current text editor depends on the users profile setting - so it needs a valid user.
629 $this->setAdminUser();
630 // Required to init a text editor.
631 $PAGE->set_url('/');
632
633 // Create an essay question.
634 /** @var qtype_essay_question $q */
635 $q = test_question_maker::make_question('essay', 'editor');
636 $q->minwordlimit = 3;
637 $q->maxwordlimit = 7;
638 $this->start_attempt_at_question($q, 'deferredfeedback', 1);
639
640 // Check the initial state.
641 $this->check_current_state(question_state::$todo);
642 $this->check_current_mark(null);
643 $this->render();
644 $this->check_contains_textarea('answer', '');
645 $this->check_current_output(
646 $this->get_contains_question_text_expectation($q),
647 $this->get_does_not_contain_validation_error_expectation(),
648 $this->get_does_not_contain_feedback_expectation());
649
650 // Save a response that is too short (and give the word-count code a tricky case).
651 $response = '<div class="card">
652 <div class="card-body">
653 <h3 class="card-title">One</h3>
654 <div class="card-text">
655 <ul>
656 <li>Two</li>
657 </ul>
658 </div>
659 </div>
660 </div>';
661 $this->process_submission(['answer' => $response, 'answerformat' => FORMAT_HTML]);
662
663 // Verify.
664 $this->check_current_state(question_state::$invalid);
665 $this->check_current_mark(null);
666 $this->render();
667 $this->check_contains_textarea('answer', $response);
668 $this->check_current_output(
669 $this->get_contains_question_text_expectation($q),
670 $this->get_contains_validation_error_expectation(),
671 $this->get_does_not_contain_feedback_expectation());
672 $this->assertStringContainsString('This question requires a response of at least 3 words and you are ' .
673 'attempting to submit 2 words. Please expand your response and try again.',
674 $this->currentoutput);
675
676 // Save a response that is just long enough.
677 $this->process_submission(['answer' => '<p>One two three.</p>', 'answerformat' => FORMAT_HTML]);
678
679 // Verify.
680 $this->check_current_state(question_state::$complete);
681 $this->check_current_mark(null);
682 $this->render();
683 $this->check_contains_textarea('answer', '<p>One two three.</p>');
684 $this->check_current_output(
685 $this->get_contains_question_text_expectation($q),
686 $this->get_does_not_contain_validation_error_expectation(),
687 $this->get_does_not_contain_feedback_expectation());
688
689 // Save a response that is as long as possible short.
690 $this->process_submission(['answer' => '<p>One two three four five six seven.</p>',
691 'answerformat' => FORMAT_HTML]);
692
693 // Verify.
694 $this->check_current_state(question_state::$complete);
695 $this->check_current_mark(null);
696 $this->render();
697 $this->check_contains_textarea('answer', '<p>One two three four five six seven.</p>');
698 $this->check_current_output(
699 $this->get_contains_question_text_expectation($q),
700 $this->get_does_not_contain_validation_error_expectation(),
701 $this->get_does_not_contain_feedback_expectation());
702
703 // Save a response that is just too long.
704 $this->process_submission(['answer' => '<p>One two three four five six seven eight.</p>',
705 'answerformat' => FORMAT_HTML]);
706
707 // Verify.
708 $this->check_current_state(question_state::$invalid);
709 $this->check_current_mark(null);
710 $this->render();
711 $this->check_contains_textarea('answer', '<p>One two three four five six seven eight.</p>');
712 $this->check_current_output(
713 $this->get_contains_question_text_expectation($q),
714 $this->get_contains_validation_error_expectation(),
715 $this->get_does_not_contain_feedback_expectation());
716 $this->assertStringContainsString('The word limit for this question is 7 words and you are ' .
717 'attempting to submit 8 words. Please shorten your response and try again.',
718 $this->currentoutput);
719
c4e2b67c
TH
720 // Now submit all and finish.
721 $this->finish();
722
723 // Verify.
724 $this->check_current_state(question_state::$needsgrading);
725 $this->check_current_mark(null);
726 $this->render();
727 $this->check_current_output(
728 $this->get_contains_question_text_expectation($q),
729 $this->get_contains_general_feedback_expectation($q));
730 $this->assertStringContainsString('Word count: 8, more than the limit of 7 words.',
731 $this->currentoutput);
d9b0da85 732 }
c0d12fc1 733}