MDL-39980 question engine: Attempt on last loses response files

When doing Each attempt builds on last, we need to copy any response
files into a draft file area, and then re-save them.

While writing the unit test for this, I had to deal with a todo in the
question engine so that questions with files in the response could be
unit-tested.

I also found an fixed a bug with qtype_essay_question::is_same_response
and fixed some notices in the existing essay/manual graded unit tests.
This commit is contained in:
Tim Hunt 2013-08-05 16:51:05 +01:00
parent 838d78a9ff
commit afb1b3d03b
8 changed files with 221 additions and 18 deletions

View file

@ -87,12 +87,12 @@ class qtype_essay_question extends question_with_responses {
public function is_same_response(array $prevresponse, array $newresponse) {
if (array_key_exists('answer', $prevresponse) && $prevresponse['answer'] !== $this->responsetemplate) {
$value1 = $prevresponse['answer'];
$value1 = (string) $prevresponse['answer'];
} else {
$value1 = '';
}
if (array_key_exists('answer', $newresponse) && $newresponse['answer'] !== $this->responsetemplate) {
$value2 = $newresponse['answer'];
$value2 = (string) $newresponse['answer'];
} else {
$value2 = '';
}

View file

@ -78,6 +78,29 @@ class qtype_essay_test_helper extends question_test_helper {
return $q;
}
/**
* Make the data what would be received from the editing form for an essay
* question using the HTML editor allowing embedded files as input, and up
* to three attachments.
*
* @return stdClass the data that would be returned by $form->get_gata();
*/
public function get_essay_question_form_data_editorfilepicker() {
$fromform = new stdClass();
$fromform->name = 'Essay question with filepicker and attachments';
$fromform->questiontext = array('text' => 'Please write a story about a frog.', 'format' => FORMAT_HTML);
$fromform->defaultmark = 1.0;
$fromform->generalfeedback = array('text' => 'I hope your story had a beginning, a middle and an end.', 'format' => FORMAT_HTML);
$fromform->responseformat = 'editorfilepicker';
$fromform->responsefieldlines = 10;
$fromform->attachments = 3;
$fromform->graderinfo = array('text' => '', 'format' => FORMAT_HTML);
$fromform->responsetemplate = array('text' => '', 'format' => FORMAT_HTML);
return $fromform;
}
/**
* Makes an essay question using plain text input.
* @return qtype_essay_question

View file

@ -36,7 +36,7 @@ require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_essay_question_test extends advanced_testcase {
class qtype_essay_question_testcase extends advanced_testcase {
public function test_get_question_summary() {
$essay = test_question_maker::make_an_essay_question();
$essay->questiontext = 'Hello <img src="http://example.com/globe.png" alt="world" />';
@ -46,8 +46,8 @@ class qtype_essay_question_test extends advanced_testcase {
public function test_summarise_response() {
$longstring = str_repeat('0123456789', 50);
$essay = test_question_maker::make_an_essay_question();
$this->assertEquals($longstring,
$essay->summarise_response(array('answer' => $longstring, 'answerformat' => FORMAT_PLAIN)));
$this->assertEquals($longstring, $essay->summarise_response(
array('answer' => $longstring, 'answerformat' => FORMAT_HTML)));
}
public function test_is_same_response() {

View file

@ -35,7 +35,7 @@ require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_essay_walkthrough_test extends qbehaviour_walkthrough_test_base {
class qtype_essay_walkthrough_testcase extends qbehaviour_walkthrough_test_base {
protected function check_contains_textarea($name, $content = '', $height = 10) {
$fieldname = $this->quba->get_field_prefix($this->slot) . $name;
@ -50,6 +50,28 @@ class qtype_essay_walkthrough_test extends qbehaviour_walkthrough_test_base {
}
}
/**
* Helper method: Store a test file with a given name and contents in a
* draft file area.
*
* @param int $usercontextid user context id.
* @param int $draftitemid draft item id.
* @param string $filename filename.
* @param string $contents file contents.
*/
protected function save_file_to_draft_area($usercontextid, $draftitemid, $filename, $contents) {
$fs = get_file_storage();
$filerecord = new stdClass();
$filerecord->contextid = $usercontextid;
$filerecord->component = 'user';
$filerecord->filearea = 'draft';
$filerecord->itemid = $draftitemid;
$filerecord->filepath = '/';
$filerecord->filename = $filename;
$fs->create_file_from_string($filerecord, $contents);
}
public function test_deferred_feedback_html_editor() {
// Create an essay question.
@ -204,4 +226,126 @@ class qtype_essay_walkthrough_test extends qbehaviour_walkthrough_test_base {
$this->get_contains_question_text_expectation($q),
$this->get_contains_general_feedback_expectation($q));
}
public function test_deferred_feedback_html_editor_with_files_attempt_on_last() {
global $CFG, $USER;
$this->resetAfterTest(true);
$this->setAdminUser();
$usercontextid = context_user::instance($USER->id)->id;
$fs = get_file_storage();
// Create an essay question in the DB.
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
$cat = $generator->create_question_category();
$question = $generator->create_question('essay', 'editorfilepicker', array('category' => $cat->id));
// Start attempt at the question.
$q = question_bank::load_question($question->id);
$this->start_attempt_at_question($q, 'deferredfeedback', 1);
$this->check_current_state(question_state::$todo);
$this->check_current_mark(null);
$this->check_step_count(1);
// Process a response and check the expected result.
// First we need to get the draft item ids.
$this->render();
if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
throw new coding_exception('Editor draft item id not found.');
}
$editordraftid = $matches[1];
if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
throw new coding_exception('File manager draft item id not found.');
}
$attachementsdraftid = $matches[1];
$this->save_file_to_draft_area($usercontextid, $editordraftid, 'smile.txt', ':-)');
$this->save_file_to_draft_area($usercontextid, $attachementsdraftid, 'greeting.txt', 'Hello world!');
$this->process_submission(array(
'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
"/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
'" alt="smile">.',
'answerformat' => FORMAT_HTML,
'answer:itemid' => $editordraftid,
'attachments' => $attachementsdraftid));
$this->check_current_state(question_state::$complete);
$this->check_current_mark(null);
$this->check_step_count(2);
$this->save_quba();
// Save the same response again, and verify no new step is created.
$this->load_quba();
$this->render();
if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
throw new coding_exception('Editor draft item id not found.');
}
$editordraftid = $matches[1];
if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
throw new coding_exception('File manager draft item id not found.');
}
$attachementsdraftid = $matches[1];
$this->process_submission(array(
'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
"/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
'" alt="smile">.',
'answerformat' => FORMAT_HTML,
'answer:itemid' => $editordraftid,
'attachments' => $attachementsdraftid));
$this->check_current_state(question_state::$complete);
$this->check_current_mark(null);
$this->check_step_count(2);
// Now submit all and finish.
$this->finish();
$this->check_current_state(question_state::$needsgrading);
$this->check_current_mark(null);
$this->check_step_count(3);
$this->save_quba();
// Now start a new attempt based on the old one.
$this->load_quba();
$oldqa = $this->get_question_attempt();
$q = question_bank::load_question($question->id);
$this->quba = question_engine::make_questions_usage_by_activity('unit_test',
context_system::instance());
$this->quba->set_preferred_behaviour('deferredfeedback');
$this->slot = $this->quba->add_question($q, 1);
$this->quba->start_question_based_on($this->slot, $oldqa);
$this->check_current_state(question_state::$complete);
$this->check_current_mark(null);
$this->check_step_count(1);
$this->save_quba();
// Now save the same response again, and ensure that a new step is not created.
$this->load_quba();
$this->render();
if (!preg_match('/env=editor&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
throw new coding_exception('Editor draft item id not found.');
}
$editordraftid = $matches[1];
if (!preg_match('/env=filemanager&amp;action=browse&amp;.*?itemid=(\d+)&amp;/', $this->currentoutput, $matches)) {
throw new coding_exception('File manager draft item id not found.');
}
$attachementsdraftid = $matches[1];
$this->process_submission(array(
'answer' => 'Here is a picture: <img src="' . $CFG->wwwroot .
"/draftfile.php/{$usercontextid}/user/draft/{$editordraftid}/smile.txt" .
'" alt="smile">.',
'answerformat' => FORMAT_HTML,
'answer:itemid' => $editordraftid,
'attachments' => $attachementsdraftid));
$this->check_current_state(question_state::$complete);
$this->check_current_mark(null);
$this->check_step_count(1);
}
}