PageRenderTime 38ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/question/tests/behat/behat_core_question.php

https://bitbucket.org/moodle/moodle
PHP | 217 lines | 84 code | 24 blank | 109 comment | 8 complexity | 2b68d17221dc83bb21230f07f4e6b167 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  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. // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
  17. require_once(__DIR__ . '/behat_question_base.php');
  18. use Behat\Gherkin\Node\TableNode as TableNode;
  19. use Behat\Mink\Exception\ExpectationException as ExpectationException;
  20. use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
  21. /**
  22. * Steps definitions related with the question bank management.
  23. *
  24. * @package core_question
  25. * @category test
  26. * @copyright 2013 David MonllaĆ³
  27. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28. */
  29. class behat_core_question extends behat_question_base {
  30. /**
  31. * Convert page names to URLs for steps like 'When I am on the "[page name]" page'.
  32. *
  33. * Recognised page names are:
  34. * | None so far! | |
  35. *
  36. * @param string $page name of the page, with the component name removed e.g. 'Admin notification'.
  37. * @return moodle_url the corresponding URL.
  38. * @throws Exception with a meaningful error message if the specified page cannot be found.
  39. */
  40. protected function resolve_page_url(string $page): moodle_url {
  41. switch (strtolower($page)) {
  42. default:
  43. throw new Exception('Unrecognised core_question page type "' . $page . '."');
  44. }
  45. }
  46. /**
  47. * Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
  48. *
  49. * Recognised page names are:
  50. * | pagetype | name meaning | description |
  51. * | course question bank | Course name | The question bank for a course |
  52. * | course question import | Course name | The import questions screen for a course |
  53. * | course question export | Course name | The export questions screen for a course |
  54. * | preview | Question name | The screen to preview a question |
  55. * | edit | Question name | The screen to edit a question |
  56. *
  57. * @param string $type identifies which type of page this is, e.g. 'Preview'.
  58. * @param string $identifier identifies the particular page, e.g. 'My question'.
  59. * @return moodle_url the corresponding URL.
  60. * @throws Exception with a meaningful error message if the specified page cannot be found.
  61. */
  62. protected function resolve_page_instance_url(string $type, string $identifier): moodle_url {
  63. switch (strtolower($type)) {
  64. case 'course question bank':
  65. return new moodle_url('/question/edit.php',
  66. ['courseid' => $this->get_course_id($identifier)]);
  67. case 'course question import':
  68. return new moodle_url('/question/bank/importquestions/import.php',
  69. ['courseid' => $this->get_course_id($identifier)]);
  70. case 'course question export':
  71. return new moodle_url('/question/bank/exportquestions/export.php',
  72. ['courseid' => $this->get_course_id($identifier)]);
  73. case 'preview':
  74. [$questionid, $otheridtype, $otherid] = $this->find_question_by_name($identifier);
  75. return new moodle_url('/question/bank/previewquestion/preview.php',
  76. ['id' => $questionid, $otheridtype => $otherid]);
  77. case 'edit':
  78. [$questionid, $otheridtype, $otherid] = $this->find_question_by_name($identifier);
  79. return new moodle_url('/question/bank/editquestion/question.php',
  80. ['id' => $questionid, $otheridtype => $otherid]);
  81. default:
  82. throw new Exception('Unrecognised core_question page type "' . $type . '."');
  83. }
  84. }
  85. /**
  86. * Find a question, and where it is, from the question name.
  87. *
  88. * This is a helper used by resolve_page_instance_url.
  89. *
  90. * @param string $questionname
  91. * @return array with three elemnets, int question id, a string 'cmid' or 'courseid',
  92. * and int either cmid or courseid as applicable.
  93. */
  94. protected function find_question_by_name(string $questionname): array {
  95. global $DB;
  96. $questionid = $DB->get_field('question', 'id', ['name' => $questionname], MUST_EXIST);
  97. $question = question_bank::load_question_data($questionid);
  98. $context = context_helper::instance_by_id($question->contextid);
  99. if ($context->contextlevel == CONTEXT_MODULE) {
  100. return [$questionid, 'cmid', $context->instanceid];
  101. } else if ($context->contextlevel == CONTEXT_COURSE) {
  102. return [$questionid, 'courseid', $context->instanceid];
  103. } else {
  104. throw new coding_exception('Unsupported context level ' . $context->contextlevel);
  105. }
  106. }
  107. /**
  108. * Creates a question in the current course questions bank with the provided data.
  109. * This step can only be used when creating question types composed by a single form.
  110. *
  111. * @Given /^I add a "(?P<question_type_name_string>(?:[^"]|\\")*)" question filling the form with:$/
  112. * @param string $questiontypename The question type name
  113. * @param TableNode $questiondata The data to fill the question type form.
  114. */
  115. public function i_add_a_question_filling_the_form_with($questiontypename, TableNode $questiondata) {
  116. // Click on create question.
  117. $this->execute('behat_forms::press_button', get_string('createnewquestion', 'question'));
  118. // Add question.
  119. $this->finish_adding_question($questiontypename, $questiondata);
  120. }
  121. /**
  122. * Checks the state of the specified question.
  123. *
  124. * @Then /^the state of "(?P<question_description_string>(?:[^"]|\\")*)" question is shown as "(?P<state_string>(?:[^"]|\\")*)"$/
  125. * @throws ExpectationException
  126. * @throws ElementNotFoundException
  127. * @param string $questiondescription
  128. * @param string $state
  129. */
  130. public function the_state_of_question_is_shown_as($questiondescription, $state) {
  131. // Using xpath literal to avoid quotes problems.
  132. $questiondescriptionliteral = behat_context_helper::escape($questiondescription);
  133. $stateliteral = behat_context_helper::escape($state);
  134. // Split in two checkings to give more feedback in case of exception.
  135. $exception = new ElementNotFoundException($this->getSession(), 'Question "' . $questiondescription . '" ');
  136. $questionxpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' que ')]" .
  137. "[contains(div[@class='content']/div[contains(concat(' ', normalize-space(@class), ' '), ' formulation ')]," .
  138. "{$questiondescriptionliteral})]";
  139. $this->find('xpath', $questionxpath, $exception);
  140. $exception = new ExpectationException('Question "' . $questiondescription .
  141. '" state is not "' . $state . '"', $this->getSession());
  142. $xpath = $questionxpath . "/div[@class='info']/div[@class='state' and contains(., {$stateliteral})]";
  143. $this->find('xpath', $xpath, $exception);
  144. }
  145. /**
  146. * Activates a particular action on a particular question in the question bank UI.
  147. *
  148. * @When I choose :action action for :questionname in the question bank
  149. * @param string $action the label for the action you want to activate.
  150. * @param string $questionname the question name.
  151. */
  152. public function i_action_the_question($action, $questionname) {
  153. // Open the menu.
  154. $this->execute("behat_general::i_click_on_in_the",
  155. [get_string('edit'), 'link', $questionname, 'table_row']);
  156. // Click the action from the menu.
  157. $this->execute("behat_general::i_click_on_in_the",
  158. [$action, 'link', $questionname, 'table_row']);
  159. }
  160. /**
  161. * A particular bulk action is visible in the question bank UI.
  162. *
  163. * @When I should see question bulk action :action
  164. * @param string $action the value of the input for the action.
  165. */
  166. public function i_should_see_question_bulk_action($action) {
  167. // Check if its visible.
  168. $this->execute("behat_general::should_be_visible",
  169. ["#bulkactionsui-container input[name='$action']", "css_element"]);
  170. }
  171. /**
  172. * A particular bulk action should not be visible in the question bank UI.
  173. *
  174. * @When I should not see question bulk action :action
  175. * @param string $action the value of the input for the action.
  176. */
  177. public function i_should_not_see_question_bulk_action($action) {
  178. // Check if its visible.
  179. $this->execute("behat_general::should_not_be_visible",
  180. ["#bulkactionsui-container input[name='$action']", "css_element"]);
  181. }
  182. /**
  183. * A click on a particular bulk action in the question bank UI.
  184. *
  185. * @When I click on question bulk action :action
  186. * @param string $action the value of the input for the action.
  187. */
  188. public function i_click_on_question_bulk_action($action) {
  189. // Click the bulk action.
  190. $this->execute("behat_general::i_click_on",
  191. ["#bulkactionsui-container input[name='$action']", "css_element"]);
  192. }
  193. }