"contains(., {$questionnumberliteral}) and contains(preceding-sibling::h3[1], {$headingliteral})]";
$this->find('xpath', $xpath);
}
+
+ /**
+ * Attempt a quiz.
+ *
+ * The first row should be column names:
+ * | slot | actualquestion | variant | response |
+ * The first two of those are required. The others are optional.
+ *
+ * slot The slot
+ * actualquestion This column is optional, and is only needed if the quiz contains
+ * random questions. If so, this will let you control which acutal
+ * question gets picked when this slot is 'randomised' at the
+ * start of the attempt. If you don't specify, then one will be picked
+ * at random (which might make the reponse meaningless).
+ * variant This column is similar, and also options. It is only needed if
+ * the question that ends up in this slot returns something greater
+ * than 1 for $question->get_num_variants(). Like with actualquestion,
+ * if you specify a value here it is used the fix the 'random' choice
+ * made when the quiz is started.
+ * response The response that was submitted. How this is interpreted depends on
+ * the question type. It gets passed to
+ * {@link core_question_generator::get_simulated_post_data_for_question_attempt()
+ * and therefore to the un_summarise_response method of the question to decode.
+ *
+ * Then there should be a number of rows of data, one for each question you want to add.
+ * There is no need to supply answers to all questions. If so, other qusetions will be
+ * left unanswered.
+ *
+ * @param string $quizname the name of the quiz the user will attempt.
+ * @param string $username the username of the user that will attempt.
+ * @param TableNode $attemptinfo information about the questions to add, as above.
+ * @Given /^I attempt quiz "([^"]*)" as "([^"]*)" with the following responses:$/
+ */
+ public function i_attempt_quiz_as_user_setting_the_following_responses($quizname, $username, TableNode $attemptinfo) {
+ global $DB, $USER;
+
+ /** @var mod_quiz_generator $quizgenerator */
+ $quizgenerator = behat_util::get_data_generator()->get_plugin_generator('mod_quiz');
+
+ $quizid = $DB->get_field('quiz', 'id', ['name' => $quizname], MUST_EXIST);
+ $user = $DB->get_record('user', ['username' => $username], '*', MUST_EXIST);
+
+ $forcedrandomquestions = [];
+ $forcedvariants = [];
+ $responses = [];
+ foreach ($attemptinfo->getHash() as $slotinfo) {
+ if (empty($slotinfo['slot'])) {
+ throw new ExpectationException('When simulating a quiz attempt, ' .
+ 'the slot column is required.', $this->getSession());
+ }
+ if (!array_key_exists('response', $slotinfo)) {
+ throw new ExpectationException('When simulating a quiz attempt, ' .
+ 'the response column is required.', $this->getSession());
+ }
+ $responses[$slotinfo['slot']] = $slotinfo['response'];
+
+ if (!empty($slotinfo['actualquestion'])) {
+ $forcedrandomquestions[$slotinfo['slot']] = $DB->get_field('question', 'id',
+ ['name' => $slotinfo['actualquestion']], MUST_EXIST);
+ }
+
+ if (!empty($slotinfo['variant'])) {
+ $forcedvariants[$slotinfo['slot']] = (int) $slotinfo['variant'];
+ }
+ }
+
+ $saveduser = $USER; // TODO there is probably a better way to do this. If not, there should be.
+ $USER = $user;
+
+ $attempt = $quizgenerator->create_attempt($quizid, $user->id,
+ $forcedrandomquestions, $forcedvariants);
+
+ $quizgenerator->submit_responses($attempt->id, $responses, true);
+
+ $USER = $saveduser;
+ }
}