first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
@core @core_question
Feature: A bank view with questions can be managed
In order to manage a question bank from the course
As a teacher
I need to be able to view and manage questions
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
@javascript
Scenario: Viewing question bank should not load individual questions
When the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Test questions | essay | Essay test question | Write about whatever you want | qid |
| Test questions | numerical | Numerical test question | Write about whatever you want | qid |
And I am on the "C1" "Course" page logged in as "teacher1"
And I navigate to "Question bank" in current page administration
And I should see "Essay test question"
And I should see "Numerical test question"
And I choose "Delete" action for "Essay test question" in the question bank
And I press "Delete"
And I should not see "Essay test question"
And I choose "Delete" action for "Numerical test question" in the question bank
And I press "Delete"
@javascript
Scenario: Unknown qtype does not break the view
When the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | missingtype | Unknown type question | Write about whatever you want |
| Test questions | truefalse | Truefalse type question | Write about whatever you want |
| Test questions | essay | Essay type question | Write about whatever you want |
And I am on the "C1" "Course" page logged in as "teacher1"
And I navigate to "Question bank" in current page administration
And I should see "Unknown type question"
And I should see "Truefalse type question"
And I should see "Essay type question"
@@ -0,0 +1,367 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/behat_question_base.php');
use Behat\Gherkin\Node\TableNode as TableNode;
use Behat\Mink\Exception\ExpectationException as ExpectationException;
use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
/**
* Steps definitions related with the question bank management.
*
* @package core_question
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_core_question extends behat_question_base {
/**
* Convert page names to URLs for steps like 'When I am on the "[page name]" page'.
*
* Recognised page names are:
* | None so far! | |
*
* @param string $page name of the page, with the component name removed e.g. 'Admin notification'.
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_page_url(string $page): moodle_url {
switch (strtolower($page)) {
default:
throw new Exception('Unrecognised core_question page type "' . $page . '."');
}
}
/**
* Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.
*
* Recognised page names are:
* | pagetype | name meaning | description |
* | course question bank | Course name | The question bank for a course |
* | course question import | Course name | The import questions screen for a course |
* | course question export | Course name | The export questions screen for a course |
* | preview | Question name | The screen to preview a question |
* | edit | Question name | The screen to edit a question |
*
* @param string $type identifies which type of page this is, e.g. 'Preview'.
* @param string $identifier identifies the particular page, e.g. 'My question'.
* @return moodle_url the corresponding URL.
* @throws Exception with a meaningful error message if the specified page cannot be found.
*/
protected function resolve_page_instance_url(string $type, string $identifier): moodle_url {
switch (strtolower($type)) {
case 'course question bank':
// The question bank does not handle fields at the edge of the viewport well.
// Increase the size to avoid this.
$this->execute('behat_general::i_change_window_size_to', ['window', 'large']);
return new moodle_url('/question/edit.php', [
'courseid' => $this->get_course_id($identifier),
]);
case 'course question categories':
return new moodle_url('/question/bank/managecategories/category.php',
['courseid' => $this->get_course_id($identifier)]);
case 'course question import':
return new moodle_url('/question/bank/importquestions/import.php',
['courseid' => $this->get_course_id($identifier)]);
case 'course question export':
return new moodle_url('/question/bank/exportquestions/export.php',
['courseid' => $this->get_course_id($identifier)]);
case 'preview':
[$questionid, $otheridtype, $otherid] = $this->find_question_by_name($identifier);
return new moodle_url('/question/bank/previewquestion/preview.php',
['id' => $questionid, $otheridtype => $otherid]);
case 'edit':
[$questionid, $otheridtype, $otherid] = $this->find_question_by_name($identifier);
return new moodle_url('/question/bank/editquestion/question.php',
['id' => $questionid, $otheridtype => $otherid]);
default:
throw new Exception('Unrecognised core_question page type "' . $type . '."');
}
}
/**
* Find a question, and where it is, from the question name.
*
* This is a helper used by resolve_page_instance_url.
*
* @param string $questionname
* @return array with three elemnets, int question id, a string 'cmid' or 'courseid',
* and int either cmid or courseid as applicable.
*/
protected function find_question_by_name(string $questionname): array {
global $DB;
$questionid = $DB->get_field('question', 'id', ['name' => $questionname], MUST_EXIST);
$question = question_bank::load_question_data($questionid);
$context = context_helper::instance_by_id($question->contextid);
if ($context->contextlevel == CONTEXT_MODULE) {
return [$questionid, 'cmid', $context->instanceid];
} else if ($context->contextlevel == CONTEXT_COURSE) {
return [$questionid, 'courseid', $context->instanceid];
} else {
throw new coding_exception('Unsupported context level ' . $context->contextlevel);
}
}
/**
* Creates a question in the current course questions bank with the provided data.
* This step can only be used when creating question types composed by a single form.
*
* @Given /^I add a "(?P<question_type_name_string>(?:[^"]|\\")*)" question filling the form with:$/
* @param string $questiontypename The question type name
* @param TableNode $questiondata The data to fill the question type form.
*/
public function i_add_a_question_filling_the_form_with($questiontypename, TableNode $questiondata) {
// Click on create question.
$this->execute('behat_forms::press_button', get_string('createnewquestion', 'question'));
// Add question.
$this->finish_adding_question($questiontypename, $questiondata);
}
/**
* Checks the state of the specified question.
*
* @Then /^the state of "(?P<question_description_string>(?:[^"]|\\")*)" question is shown as "(?P<state_string>(?:[^"]|\\")*)"$/
* @throws ExpectationException
* @throws ElementNotFoundException
* @param string $questiondescription
* @param string $state
*/
public function the_state_of_question_is_shown_as($questiondescription, $state) {
// Using xpath literal to avoid quotes problems.
$questiondescriptionliteral = behat_context_helper::escape($questiondescription);
$stateliteral = behat_context_helper::escape($state);
// Split in two checkings to give more feedback in case of exception.
$exception = new ElementNotFoundException($this->getSession(), 'Question "' . $questiondescription . '" ');
$questionxpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' que ')]" .
"[contains(div[@class='content']/div[contains(concat(' ', normalize-space(@class), ' '), ' formulation ')]," .
"{$questiondescriptionliteral})]";
$this->find('xpath', $questionxpath, $exception);
$exception = new ExpectationException('Question "' . $questiondescription .
'" state is not "' . $state . '"', $this->getSession());
$xpath = $questionxpath . "/div[@class='info']/div[@class='state' and contains(., {$stateliteral})]";
$this->find('xpath', $xpath, $exception);
}
/**
* Activates a particular action on a particular question in the question bank UI.
*
* @When I choose :action action for :questionname in the question bank
* @param string $action the label for the action you want to activate.
* @param string $questionname the question name.
*/
public function i_action_the_question($action, $questionname) {
if ($this->running_javascript()) {
// This method isn't allowed unless Javascript is running.
$this->execute('behat_action_menu::i_open_the_action_menu_in', [
$questionname,
'table_row',
]);
$this->execute('behat_action_menu::i_choose_in_the_open_action_menu', [
$action
]);
} else {
// This method doesn't open the menu correctly when Javascript is running.
$this->execute('behat_action_menu::i_choose_in_the_named_menu_in_container', [
$action,
get_string('edit', 'core'),
$questionname,
'table_row',
]);
}
}
/**
* Checks that action does exist for a question.
*
* @Then the :action action should exist for the :questionname question in the question bank
* @param string $action the label for the action you want to activate.
* @param string $questionname the question name.
*/
public function action_exists($action, $questionname) {
$this->execute('behat_action_menu::item_should_exist_in_the', [
$action,
get_string('edit', 'core'),
$questionname,
'table_row',
]);
}
/**
* Checks that action does not exist for a question.
*
* @Then the :action action should not exist for the :questionname question in the question bank
* @param string $action the label for the action you want to activate.
* @param string $questionname the question name.
*/
public function action_not_exists($action, $questionname) {
$this->execute('behat_action_menu::item_should_not_exist_in_the', [
$action,
get_string('edit', 'core'),
$questionname,
'table_row',
]);
}
/**
* A particular bulk action is visible in the question bank UI.
*
* @When I should see question bulk action :action
* @param string $action the value of the input for the action.
*/
public function i_should_see_question_bulk_action($action) {
// Check if its visible.
$this->execute("behat_general::should_be_visible",
["#bulkactionsui-container input[name='$action']", "css_element"]);
}
/**
* A particular bulk action should not be visible in the question bank UI.
*
* @When I should not see question bulk action :action
* @param string $action the value of the input for the action.
*/
public function i_should_not_see_question_bulk_action($action) {
// Check if its visible.
$this->execute("behat_general::should_not_be_visible",
["#bulkactionsui-container input[name='$action']", "css_element"]);
}
/**
* A click on a particular bulk action in the question bank UI.
*
* @When I click on question bulk action :action
* @param string $action the value of the input for the action.
*/
public function i_click_on_question_bulk_action($action) {
// Click the bulk action.
$this->execute("behat_general::i_click_on",
["#bulkactionsui-container input[name='$action']", "css_element"]);
}
/**
* Change the question type of the give question to a type that does not exist.
*
* This is useful for testing robustness of the code when a question type
* has been uninstalled, even though there are still questions of that type
* or attempts at them.
*
* In order to set things up, you probably need to start by generating
* questions of a valid type, then using this to change the type once the
* data is created.
*
* @Given question :questionname is changed to simulate being of an uninstalled type
* @param string $questionname the question name.
*/
public function change_question_to_nonexistant_type($questionname) {
global $DB;
[$id] = $this->find_question_by_name($questionname);
// Check our assumption.
$nonexistanttype = 'invalidqtype';
if (question_bank::is_qtype_installed($nonexistanttype)) {
throw new coding_exception('This code assumes that the qtype_' . $nonexistanttype .
' is not a valid plugin name, but that plugin now seems to exist!');
}
$DB->set_field('question', 'qtype', $nonexistanttype, ['id' => $id]);
question_bank::notify_question_edited($id);
}
/**
* Forcibly delete a question from the database.
*
* This is useful for testing robustness of the code when a question
* record is no longer in the database, even though it is referred to.
* Obviously, this should never happen, but it has been known to in the past
* and so we sometimes need to be able to test the code can handle this situation.
*
* In order to set things up, you probably need to start by generating
* a valid questions, then using this to remove it once the data is created.
*
* @Given question :questionname no longer exists in the database
* @param string $questionname the question name.
*/
public function remove_question_from_db($questionname) {
global $DB;
[$id] = $this->find_question_by_name($questionname);
$DB->delete_records('question', ['id' => $id]);
question_bank::notify_question_edited($id);
}
/**
* Add a question bank filter
*
* This will add the filter if it does not exist, but leave the value empty.
*
* @When I add question bank filter :filtertype
* @param string $filtertype The filter we are adding
*/
public function i_add_question_bank_filter(string $filtertype) {
$filter = $this->getSession()->getPage()->find('css',
'[data-filterregion=filter] [data-field-title="' . $filtertype . '"]');
if ($filter === null) {
$this->execute('behat_forms::press_button', [get_string('addcondition')]);
$this->execute('behat_forms::i_set_the_field_in_container_to', [
"type",
"[data-filterregion=filter]:last-child fieldset",
"css_element",
$filtertype
]);
}
}
/**
* Apply question bank filter.
*
* This will change the existing value of the specified filter, or add the filter and set its value if it doesn't already
* exist.
*
* @When I apply question bank filter :filtertype with value :value
* @param string $filtertype The filter to apply. This should match the get_title() return value from the
* filter's condition class.
* @param string $value The value to set for the condition.
*/
public function i_apply_question_bank_filter(string $filtertype, string $value) {
// Add the filter if needed.
$this->execute('behat_core_question::i_add_question_bank_filter', [
$filtertype,
]);
// Set the filter value.
$this->execute('behat_forms::i_set_the_field_to', [
$filtertype,
$value
]);
// Apply filters.
$this->execute("behat_forms::press_button", [get_string('applyfilters')]);
}
}
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Behat question-related helper code.
*
* @package core_question
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
use Behat\Gherkin\Node\TableNode as TableNode,
Behat\Mink\Exception\ExpectationException as ExpectationException,
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
/**
* Steps definitions related with the question bank management.
*
* @package core_question
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_question_base extends behat_base {
/**
* Helper used by {@link i_add_a_question_filling_the_form_with()} and
* {@link behat_mod_quiz::i_add_question_to_the_quiz_with to finish creating()}.
*
* @param string $questiontypename The question type name
* @param TableNode $questiondata The data to fill the question type form
*/
protected function finish_adding_question($questiontypename, TableNode $questiondata) {
$this->execute('behat_forms::i_set_the_field_to', [$this->escape($questiontypename), 1]);
$this->execute("behat_general::i_click_on", ['.submitbutton', "css_element"]);
$this->execute("behat_forms::i_set_the_following_fields_to_these_values", $questiondata);
$this->execute("behat_forms::press_button", 'id_submitbutton');
}
}
@@ -0,0 +1,37 @@
@core @core_question
Feature: An activity module instance with questions in its context can be deleted
In order to delete an activity module from the course
As a teacher
I need to be able to delete the activity even if it has questions created in its context
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
Scenario: Synchronously deleting a quiz with existing questions in its context
Given the following config values are set as admin:
| coursebinenable | 0 | tool_recyclebin |
And the following "activity" exists:
| activity | quiz |
| course | C1 |
| name | Test quiz Q001 |
And the following "question categories" exist:
| contextlevel | reference | name |
| Activity module | Test quiz Q001 | Default for Test quiz Q001 |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Default for Test quiz Q001 | truefalse | Test used question to be deleted | Write about whatever you want |
And quiz "Test quiz Q001" contains the following questions:
| question | page |
| Test used question to be deleted | 1 |
And I am on the "Course 1" course page logged in as teacher1
And I am on "Course 1" course homepage with editing mode on
When I delete "Test quiz Q001" activity
Then I should not see "Test quiz Q001"
@@ -0,0 +1,86 @@
@core @core_question
Feature: A teacher can delete questions in the question bank
In order to remove unused questions from the question bank
As a teacher
I need to delete questions
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | essay | Test question to be deleted | Write about whatever you want |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
@javascript
Scenario: A question not used anywhere can really be deleted
When I choose "Delete" action for "Test question to be deleted" in the question bank
And I press "Delete"
And I apply question bank filter "Show hidden questions" with value "Yes"
Then I should not see "Test question to be deleted"
Scenario: Deleting a question can be cancelled
When I choose "Delete" action for "Test question to be deleted" in the question bank
And I press "Cancel"
Then I should see "Test question to be deleted"
@javascript
Scenario: Delete a question used in a quiz
Given the following "activity" exists:
| course | C1 |
| activity | quiz |
| idnumber | Test quiz |
| name | Test quiz |
And the following "question" exists:
| questioncategory | Test questions |
| qtype | truefalse |
| name | Test used question to be deleted |
| questiontext | Write about whatever you want |
And quiz "Test quiz" contains the following questions:
| question | page | requireprevious |
| Test used question to be deleted | 1 | 0 |
When I am on the "Course 1" "core_question > course question bank" page
And I choose "Delete" action for "Test used question to be deleted" in the question bank
And I should see "This will delete the following question and all its versions:"
And I should see "* Denotes questions which can't be deleted because they are in use. Instead, they will be hidden in the question bank unless you set 'Show hidden questions' to 'Yes'."
And I press "Delete"
Then I should not see "Test used question to be deleted"
And I apply question bank filter "Show hidden questions" with value "Yes"
And I should see "Test used question to be deleted"
And I am on the "Test quiz" "quiz activity" page
And I click on "Preview quiz" "button"
And I should see "Write about whatever you want"
@javascript
Scenario: A question can be deleted even if that question type is no longer installed
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | missingtype | Broken question | Write something |
And I reload the page
When I choose "Delete" action for "Broken question" in the question bank
And I press "Delete"
And I apply question bank filter "Show hidden questions" with value "Yes"
Then I should not see "Broken question"
@javascript
Scenario: Delete question has multiple versions in question bank page
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When the following "core_question > updated questions" exist:
| questioncategory | question | questiontext |
| Test questions | Test question to be deleted | Test question to be deleted version 2 |
And I choose "Delete" action for "Test question to be deleted" in the question bank
And I should see "This will delete the following question and all its versions:"
And I should not see "* Denotes questions which can't be deleted because they are in use. Instead, they will be hidden in the question bank unless you set 'Show hidden questions' to 'Yes'."
And I press "Delete"
Then I should not see "Test question to be deleted"
And I should not see "Test question to be deleted version2"
@@ -0,0 +1,55 @@
@core @core_question
Feature: A teacher can duplicate questions in the question bank
In order to efficiently expand my question bank
As a teacher
I need to be able to duplicate existing questions and make small changes
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher | Teacher | One | teacher@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Test questions | essay | Test question to be copied | Write about whatever you want | qid |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher"
Scenario: Duplicating a previously created question
When I choose "Duplicate" action for "Test question to be copied" in the question bank
And I set the following fields to these values:
| Question name | Duplicated question name |
| Question text | Write a lot about duplicating questions |
And I press "id_submitbutton"
Then I should see "Duplicated question name"
And I should see "Test question to be copied"
And I should see "ID number" in the "Test question to be copied" "table_row"
And I should see "qid" in the "Test question to be copied" "table_row"
Scenario: Duplicated questions automatically get a new name suggested
When I choose "Duplicate" action for "Test question to be copied" in the question bank
Then the field "Question name" matches value "Test question to be copied (copy)"
@javascript
Scenario: The duplicate operation can be cancelled
When I choose "Duplicate" action for "Test question to be copied" in the question bank
And I press "Cancel"
Then I should see "Test question to be copied"
And I should see "Test questions (1)" in the "Filter 1" "fieldset"
Scenario: Duplicating a question with an idnumber increments it
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Test questions | essay | Question with idnumber | Write about whatever you want | id101 |
And I reload the page
When I choose "Duplicate" action for "Question with idnumber" in the question bank
And I press "id_submitbutton"
Then I should see "Question with idnumber (copy)"
Then I should see "id102" in the "Question with idnumber (copy)" "table_row"
@@ -0,0 +1,42 @@
@core @core_question
Feature: A teacher can manage tags on questions in the question bank
In order to organise my questions
As a teacher
I need to be able to tag them
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | essay | Test question to be tagged | Write about whatever you want |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
@javascript
Scenario: Manage tags on a question
When I choose "Manage tags" action for "Test question to be tagged" in the question bank
And I should see "Test question to be tagged" in the "Question tags" "dialogue"
And I set the field "Tags" to "my-tag"
And I click on "Save changes" "button" in the "Question tags" "dialogue"
Then I should see "my-tag" in the "Test question to be tagged" "table_row"
@javascript
Scenario: Manage tags works even on questions of a type is no longer installed
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | missingtype | Broken question | Write something |
And I reload the page
When I choose "Manage tags" action for "Broken question" in the question bank
And I set the field "Tags" to "my-tag"
And I click on "Save changes" "button" in the "Question tags" "dialogue"
Then I should see "my-tag" in the "Broken question" "table_row"
@@ -0,0 +1,48 @@
@core @core_question
Feature: Questions in the question bank have versions
In order to see modified questions
As a teacher
I want to view them as different versions
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Quiz 1 | C1 | quiz1 |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext | answer 1 |
| Test questions | truefalse | First question | Answer the first question | True |
And quiz "Quiz 1" contains the following questions:
| question | page |
| First question | 1 |
@javascript
Scenario: Question version is displayed
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I choose "Edit question" action for "First question" in the question bank
Then I should see "Version 1"
@javascript
Scenario: Question version change when question is altered
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I choose "Edit question" action for "First question" in the question bank
And I should see "Version 1"
When I set the field "id_name" to "Renamed question v2"
And I set the field "id_questiontext" to "edited question"
And I press "id_submitbutton"
Then I should not see "First question"
And I should see "Renamed question v2"
When I choose "Edit question" action for "Renamed question v2" in the question bank
Then I should see "Version 2"
And I should not see "Version 1"
@@ -0,0 +1,92 @@
@core @core_question @javascript
Feature: A teacher can edit questions in the question bank
In order to improve my questions
As a teacher
I need to be able to edit questions
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | essay | Test question to be edited | Write about whatever you want |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
@javascript
Scenario: Edit a previously created question
When I am on the "Test question to be edited" "core_question > edit" page logged in as "teacher1"
And I set the following fields to these values:
| Question name | Edited question name |
| Question text | Write a lot about what you want |
And I press "id_submitbutton"
Then I should see "Edited question name"
And I should not see "Test question to be edited"
And I should see "Teacher 1"
Scenario: Edit a previously created question without permission 'moodle/question:moveall' and 'moodle/question:movemine'
Given I log in as "admin"
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/question:movemine | Prevent | editingteacher | System | |
| moodle/question:moveall | Prevent | editingteacher | System | |
When I am on the "Test question to be edited" "core_question > edit" page logged in as "teacher1"
And I set the following fields to these values:
| Question name | Edited question name |
| Question text | Write a lot about what you want |
And I press "id_submitbutton"
Then I should see "Edited question name"
And I should not see "Test question to be edited"
And I should see "Teacher 1"
Scenario: Edit a previously created question without permission 'moodle/question:editall' and 'moodle/question:editmine'
Given I log in as "admin"
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/question:editmine | Prevent | editingteacher | System | |
| moodle/question:editall | Prevent | editingteacher | System | |
When I am on the "Test question to be edited" "core_question > edit" page logged in as "teacher1"
And I set the following fields to these values:
| Question name | Edited question name |
| Question text | Write a lot about what you want |
And I press "id_submitbutton"
Then I should see "You don't have permission to edit questions from here."
Scenario: Editing a question can be cancelled
When I am on the "Test question to be edited" "core_question > edit" page logged in as "teacher1"
And I set the field "Question name" to "Edited question name"
And I press "Cancel"
Then I should see "Test question to be edited"
And I should see "Admin User"
Scenario: A question can have its idnumber removed
Given the following "questions" exist:
| questioncategory | qtype | name | idnumber |
| Test questions | essay | Question with idnumber | frog |
When I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
Then I should see "frog" in the "Question with idnumber" "table_row"
When I choose "Edit question" action for "Question with idnumber" in the question bank
And I set the field "ID number" to ""
And I press "id_submitbutton"
Then I should not see "frog" in the "Question with idnumber" "table_row"
Scenario: If the question type is no longer installed, then most edit actions are not present
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | missingtype | Broken question | Write something |
When I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
Then the "Edit question" item should not exist in the "Edit" action menu of the "Broken question" "table_row"
And the "Duplicate" item should not exist in the "Edit" action menu of the "Broken question" "table_row"
And the "Preview" item should not exist in the "Edit" action menu of the "Broken question" "table_row"
And the "Export as XML" item should not exist in the "Edit" action menu of the "Broken question" "table_row"
And the "Manage tags" item should exist in the "Edit" action menu of the "Broken question" "table_row"
And the "Delete" item should exist in the "Edit" action menu of the "Broken question" "table_row"
@@ -0,0 +1,30 @@
@core @core_question @javascript
Feature: The questions can be tagged
In order to tag questions
As a teacher
I want to see the standard tags in the tags field
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "tags" exist:
| name | isstandard |
| foo | 1 |
| bar | 1 |
Scenario: The tags autocomplete should include standard tags
When I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
And I press "Create a new question ..."
And I set the field "item_qtype_truefalse" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
And I expand all fieldsets
And I open the autocomplete suggestions list
Then "foo" "autocomplete_suggestions" should exist
And "bar" "autocomplete_suggestions" should exist
@@ -0,0 +1,45 @@
@core @core_question
Feature: The questions in the question bank can be filtered by tags
In order to find the questions I need
As a teacher
I want to filter the questions by tags
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | user | questiontext |
| Test questions | essay | question 1 name | admin | Question 1 text |
| Test questions | essay | question 2 name | teacher1 | Question 2 text |
And I am on the "question 1 name" "core_question > edit" page logged in as "teacher1"
And I set the following fields to these values:
| Tags | foo |
And I press "id_submitbutton"
And I am on the "question 2 name" "core_question > edit" page
And I set the following fields to these values:
| Tags | bar |
And I press "id_submitbutton"
@javascript
Scenario: The questions can be filtered by tag
When I apply question bank filter "Tag" with value "foo"
Then I should see "question 1 name" in the "categoryquestions" "table"
And I should not see "question 2 name" in the "categoryquestions" "table"
@javascript
Scenario: Empty condition should not result in exception
When I am on the "Course 1" "core_question > course question bank" page
And I set the field "Type or select..." in the "Filter 1" "fieldset" to "Test questions"
When I click on "Add condition" "button"
And I set the field "type" in the "Filter 2" "fieldset" to "Tag"
And I click on "Apply filters" "button"
@@ -0,0 +1,66 @@
@core @core_question
Feature: The questions in the question bank can be filtered by combine various conditions
In order to find the questions I need
As a teacher
I want to filter the questions by various conditions
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions 1|
| Course | C1 | Test questions 2|
And the following "questions" exist:
| questioncategory | qtype | name | user | questiontext |
| Test questions 1 | essay | question 1 name | teacher1 | Question 1 text |
| Test questions 1 | essay | question 2 name | teacher1 | Question 2 text |
| Test questions 2 | essay | question 3 name | teacher1 | Question 3 text |
| Test questions 2 | essay | question 4 name | teacher1 | Question 4 text |
And the following "core_question > Tags" exist:
| question | tag |
| question 1 name | foo |
| question 3 name | foo |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
@javascript
Scenario: The questions can be filtered by matching all conditions
When I apply question bank filter "Category" with value "Test questions 1"
And I apply question bank filter "Tag" with value "foo"
Then I should see "question 1 name" in the "categoryquestions" "table"
And I should not see "question 2 name" in the "categoryquestions" "table"
And I should not see "question 3 name" in the "categoryquestions" "table"
And I should not see "question 4 name" in the "categoryquestions" "table"
@javascript
Scenario: Filters persist when the page is reloaded
Given the following "questions" exist:
| questioncategory | qtype | name | user | questiontext | status |
| Test questions 1 | essay | hidden question name | teacher1 | Hidden text | hidden |
And the following "core_question > Tags" exist:
| question | tag |
| hidden question name | foo |
And I apply question bank filter "Category" with value "Test questions 1"
And I apply question bank filter "Tag" with value "foo"
And I apply question bank filter "Show hidden questions" with value "Yes"
And I should see "question 1 name" in the "categoryquestions" "table"
And I should see "hidden question name" in the "categoryquestions" "table"
And I should not see "question 2 name" in the "categoryquestions" "table"
And I should not see "question 3 name" in the "categoryquestions" "table"
And I should not see "question 4 name" in the "categoryquestions" "table"
When I reload the page
Then I should see "Test questions 1 (2)" in the "Filter 1" "fieldset"
And the field "Show hidden questions" matches value "Yes"
And I should see "foo" in the "Filter 3" "fieldset"
And I should see "question 1 name" in the "categoryquestions" "table"
And I should see "hidden question name" in the "categoryquestions" "table"
And I should not see "question 2 name" in the "categoryquestions" "table"
And I should not see "question 3 name" in the "categoryquestions" "table"
And I should not see "question 4 name" in the "categoryquestions" "table"
@@ -0,0 +1,39 @@
@core @core_question
Feature: A teacher can move questions between categories in the question bank
In order to organize my questions
As a teacher
I move questions between categories
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | questioncategory | name |
| Course | C1 | Top | top |
| Course | C1 | top | Default for C1 |
| Course | C1 | Default for C1 | Subcategory |
| Course | C1 | top | Used category |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Used category | essay | Test question to be moved | Write about whatever you want |
And I log in as "teacher1"
And I am on "Course 1" course homepage
@javascript
Scenario: Move a question between categories via the question page
When I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
And I apply question bank filter "Category" with value "Used category"
And I click on "Test question to be moved" "checkbox" in the "Test question to be moved" "table_row"
And I click on "With selected" "button"
And I click on question bulk action "move"
And I set the field "Question category" to "Subcategory"
And I press "Move to"
Then I should see "Test question to be moved"
And I should see "Subcategory (1)" in the ".form-autocomplete-selection" "css_element"
@@ -0,0 +1,86 @@
@core @core_question
Feature: A teacher can put questions with idnumbers in categories in the question bank
In order to organize my questions
As a teacher
I move questions between categories (now with idnumbers)
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I log in as "teacher1"
And I am on "Course 1" course homepage
Scenario: A question can only have a unique idnumber within a category
When the following "question categories" exist:
| contextlevel | reference | questioncategory | name | idnumber |
| Course | C1 | Top | top | |
| Course | C1 | top | Used category | c1used |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Used category | essay | Test question 1 | Write about whatever you want | q1 |
| Used category | essay | Test question 2 | Write about whatever you want | q2 |
And I am on the "Test question 2" "core_question > edit" page
And I set the field "ID number" to "q1"
And I press "submitbutton"
# This is the standard form warning reminding the user that the idnumber needs to be unique for a category.
Then I should see "This ID number is already in use"
Scenario: A question can be edited and saved without changing the idnumber
When the following "question categories" exist:
| contextlevel | reference | questioncategory | name | idnumber |
| Course | C1 | Top | top | |
| Course | C1 | top | Used category | c1used |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Used category | essay | Test question 1 | Write about whatever you want | q1 |
And I am on the "Test question 1" "core_question > edit" page
And I press "Save changes"
Then I should not see "This ID number is already in use"
Scenario: Question idnumber conflicts found when saving to the same category.
When the following "question categories" exist:
| contextlevel | reference | questioncategory | name |
| Course | C1 | Top | top |
| Course | C1 | top | Category 1 |
| Course | C1 | top | Category 2 |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Category 1 | essay | Question to edit | Write about whatever you want | q1 |
| Category 1 | essay | Other question | Write about whatever you want | q2 |
And I am on the "Question to edit" "core_question > edit" page
And I set the field "ID number" to "q2"
And I press "Save changes"
Then I should see "This ID number is already in use"
@javascript
Scenario: Moving a question between categories can force a change to the idnumber
And the following "question categories" exist:
| contextlevel | reference | questioncategory | name | idnumber |
| Course | C1 | Top | top | |
| Course | C1 | top | Subcategory | c1sub |
| Course | C1 | top | Used category | c1used |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext | idnumber |
| Used category | essay | Test question 1 | Write about whatever you want | q1 |
| Used category | essay | Test question 2 | Write about whatever you want | q2 |
| Subcategory | essay | Test question 3 | Write about whatever you want | q3 |
When I am on the "Test question 3" "core_question > edit" page
# The q1 idnumber is allowed for this question while it is in the Subcategory.
And I set the field "ID number" to "q1"
And I press "submitbutton"
# Javascript is required for the next step.
And I click on "Test question 3" "checkbox" in the "Test question 3" "table_row"
And I click on "With selected" "button"
And I click on question bulk action "move"
And I set the field "Question category" to "Subcategory"
And I press "Move to"
And I choose "Edit question" action for "Test question 3" in the question bank
# The question just moved into this category needs to have a unique idnumber, so a number is appended.
Then the field "ID number" matches value "q1_1"
@@ -0,0 +1,38 @@
@core @core_question @qbank_filter @javascript
Feature: A teacher can pagimate through question bank questions
In order to paginate questions
As a teacher
I must be able to paginate
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | questioncategory | name |
| Course | C1 | Top | Used category |
Given 100 "questions" exist with the following data:
| questioncategory | Used category |
| qtype | essay |
| name | Tests question [count] |
| questiontext | Write about whatever you want |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Used category | essay | Not on first page | Write about whatever you want |
Scenario: Questions can be paginated
When I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I apply question bank filter "Category" with value "Course 1"
And I follow "Sort by Question name ascending"
And I follow "Sort by Question name descending"
And I should see "Tests question 1"
And I should not see "Not on first page"
And I click on "2" "link" in the ".pagination" "css_element"
And I should not see "Tests question 1"
And I should see "Not on first page"
@@ -0,0 +1,35 @@
@core @core_question
Feature: A teacher can see highlighted questions in the question bank
In order to see my edited questions
As a teacher
I need to be able see the highlight of my edited question.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And 101 "questions" exist with the following data:
| questioncategory | Test questions |
| qtype | essay |
| name | essay [count] |
| questiontext | Write about whatever you want |
Scenario: Edited question highlight is retained when go to multiple pages.
Given I am on the "essay 1" "core_question > edit" page logged in as "teacher1"
And I set the following fields to these values:
| Question name | essay 1 edited |
And I press "id_submitbutton"
And I should see "essay 1 edited"
And ".highlight" "css_element" should exist in the "#categoryquestions" "css_element"
When I click on "2" "link" in the ".pagination" "css_element"
And I click on "1" "link" in the ".pagination" "css_element"
Then ".highlight" "css_element" should exist in the "#categoryquestions" "css_element"
@@ -0,0 +1,57 @@
@core @core_question
Feature: The questions in the question bank can be selected in various ways
In selected to do something for questions
As a teacher
I want to choose them to move, delete it.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | user | questiontext |
| Test questions | essay | A question 1 name | admin | Question 1 text |
| Test questions | essay | B question 2 name | teacher1 | Question 2 text |
| Test questions | numerical | C question 3 name | teacher1 | Question 3 text |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
@javascript
Scenario: The question text can be chosen all in the list of questions
Given the field "Select all" matches value ""
When I click on "Select all" "checkbox"
And the field "A question 1 name" matches value "1"
And the field "B question 2 name" matches value "1"
And the field "C question 3 name" matches value "1"
Then I click on "Deselect all" "checkbox"
And the field "A question 1 name" matches value ""
And the field "B question 2 name" matches value ""
And the field "C question 3 name" matches value ""
@javascript
Scenario: The question text can be chosen in the list of questions
Given the field "Select all" matches value ""
When I click on "A question 1 name" "checkbox"
Then the field "Select all" matches value ""
And I click on "B question 2 name" "checkbox"
And I click on "C question 3 name" "checkbox"
And the field "Deselect all" matches value "1"
@javascript
Scenario: The action button can be disabled when the question not be chosen in the list of questions
Given the field "Select all" matches value ""
When I click on "With selected" "button"
And I should not see "Delete"
And I should not see "Move to..."
And I click on "Select all" "checkbox"
And I click on "With selected" "button"
Then I should see question bulk action "move"
And I should see question bulk action "deleteselected"
@@ -0,0 +1,67 @@
@core @core_question
Feature: The questions in the question bank can be sorted in various ways
In order to see what questions I have
As a teacher
I want to view them in different orders
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | weeks |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | user | questiontext | idnumber |
| Test questions | essay | A question 1 name | admin | Question 1 text | numidnum</a |
| Test questions | essay | B question 2 name | teacher1 | Question 2 text | |
| Test questions | numerical | C question 3 name | teacher1 | Question 3 text | numidnum</c |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
Scenario: The questions are sorted by type by default
Then "A question 1 name" "checkbox" should appear before "C question 3 name" "checkbox"
Scenario: The questions can be sorted by idnumber
When I change the window size to "large"
And I follow "Sort by ID number ascending"
Then "C question 3 name" "checkbox" should appear after "A question 1 name" "checkbox"
And I should see "numidnum</c" in the "C question 3 name" "table_row"
And I follow "Sort by ID number descending"
And "C question 3 name" "checkbox" should appear before "A question 1 name" "checkbox"
Scenario: The questions can be sorted in reverse order by type
When I follow "Sort by Question type descending"
Then "C question 3 name" "checkbox" should appear before "A question 1 name" "checkbox"
Scenario: The questions can be sorted by name
When I follow "Sort by Question name ascending"
Then "A question 1 name" "checkbox" should appear before "B question 2 name" "checkbox"
And "B question 2 name" "checkbox" should appear before "C question 3 name" "checkbox"
Scenario: The questions can be sorted in reverse order by name
When I follow "Sort by Question name ascending"
And I follow "Sort by Question name descending"
Then "C question 3 name" "checkbox" should appear before "B question 2 name" "checkbox"
And "B question 2 name" "checkbox" should appear before "A question 1 name" "checkbox"
Scenario: The questions can be sorted by creator name
When I follow "Sort by First name ascending"
Then "A question 1 name" "checkbox" should appear before "B question 2 name" "checkbox"
Scenario: The questions can be sorted in reverse order by creator name
When I follow "Sort by First name ascending"
And I follow "Sort by First name descending"
Then "B question 2 name" "checkbox" should appear before "A question 1 name" "checkbox"
@javascript
Scenario: The question text can be shown in the list of questions
When I set the field "Show question text in the question list?" to "Yes"
Then I should see "Question 1 text"
And I should see "Question 2 text"
And I should see "Question 3 text"