diff --git a/admin/tool/behat/tests/behat_form_text_test.php b/admin/tool/behat/tests/behat_form_text_test.php new file mode 100644 index 00000000000..0823cbac758 --- /dev/null +++ b/admin/tool/behat/tests/behat_form_text_test.php @@ -0,0 +1,191 @@ +. + +/** + * Tests for behat_form_text class + * + * @copyright 2022 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com} + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_behat; + +use behat_form_text; +use Behat\Mink\Session; +use Behat\Mink\Element\NodeElement; +use core_string_manager_standard; + +defined('MOODLE_INTERNAL') || die; + +global $CFG; +require_once($CFG->libdir . '/behat/classes/behat_session_interface.php'); +require_once($CFG->libdir . '/behat/classes/behat_session_trait.php'); +require_once($CFG->libdir . '/behat/form_field/behat_form_text.php'); + +/** + * Tests for the behat_form_text class + * + * @package tool_behat + * @category test + * @copyright 2022 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com} + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \behat_form_text + * @covers \behat_form_field + */ +class behat_form_text_test extends \basic_testcase { + + /** + * Data provider for the test_set_get_value() method. + * + * @return array of value and expectation pairs to be tested. + */ + public function provider_test_set_get_value() { + return [ + 'null' => [null, null], + 'int' => [3, 3], + 'float' => [3.14, 3.14], + 'string' => ['hello', 'hello'], + 'utf8' => ['你好', '你好'], + ]; + } + + /** + * Test the set_value() and get_value() methods. + * + * @param mixed $value value to be set. + * @param mixed $expectation value to be checked. + * @dataProvider provider_test_set_get_value() + */ + public function test_set_get_value($value, $expectation) { + $session = $this->createMock(Session::class); + $node = $this->createMock(NodeElement::class); + $node->method('getValue')->willReturn($value); + $field = new behat_form_text($session, $node); + + $field->set_value($value); + $this->assertEquals($expectation, $field->get_value()); + } + + /** + * Data provider for the test_text_matches() method. + * + * @return array of decsep, value, match and result pairs to be tested. + */ + public function provider_test_matches() { + return [ + 'lazy true' => ['.', 'hello', 'hello', true], + 'lazy false' => ['.', 'hello', 'bye', false], + 'float true' => ['.', '3.14', '3.1400', true], + 'float false' => ['.', '3.14', '3.1401', false], + 'float and float string true' => ['.', 3.14, '3.1400', true], + 'float and unrelated string false' => ['.', 3.14, 'hello', false], + 'float hash decsep true' => ['#', '3#14', '3#1400', true], + 'float hash decsep false' => ['#', '3#14', '3#1401', false], + 'float and float string hash decsep true' => ['#', 3.14, '3.1400', true], + 'float and unrelated string hash decsep false' => ['#', 3.14, 'hello', false], + 'float custom-default decsep mix1 true' => ['#', '3#14', '3.1400', true], + 'float custom-default decsep mix2 true' => ['#', '3.14', '3#1400', true], + 'float 2-custom decsep mix1 false' => ['#', '3#14', '3,1400', false], + 'float 2-custom decsep mix2 false' => [',', '3#14', '3,1400', false], + 'float default-custom decsep mix1 false' => ['.', '3#14', '3.1400', false], + 'float default-custom decsep mix2 false' => ['.', '3.14', '3#1400', false], + ]; + } + + /** + * Test the matches() method. + * + * @param string $decsep decimal separator to use. + * @param mixed $value value to be set. + * @param mixed $match value to be matched. + * @param bool $result expected return status of the function. + * @dataProvider provider_test_matches() + */ + public function test_matches($decsep, $value, $match, $result) { + global $CFG; + + // Switch of string manager to avoid having to (slow) customise the lang file. + $origcustom = $CFG->config_php_settings['customstringmanager'] ?? null; + $CFG->config_php_settings['customstringmanager'] = '\tool_behat\phpunit_string_manager'; + $manager = get_string_manager(true); + $manager->set_string('decsep', 'langconfig', $decsep); + + $session = $this->createMock(Session::class); + $node = $this->createMock(NodeElement::class); + $node->method('getValue')->willReturn($value); + + $field = new behat_form_text($session, $node); + + $field->set_value($value); + $this->assertSame($result, $field->matches($match)); + + // Switch back to the original string manager. + if (is_null($origcustom)) { + unset($CFG->config_php_settings['customstringmanager']); + } else { + $CFG->config_php_settings['customstringmanager'] = $origcustom; + } + $manager = get_string_manager(true); + } +} + +/** + * Customised values that will be used instead of standard manager one. + * + * If an existing component/identifier is found, return it instead of the real + * one from language files. Note this doesn't support place holders or another niceties. + * + * @package tool_behat + * @category test + * @copyright 2022 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com} + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class phpunit_string_manager extends core_string_manager_standard { + + /** @var array language customisations provided by the manager without asking for real contents */ + protected $customstrings = []; + + /** + * Get String returns a requested string + * + * @param string $identifier The identifier of the string to search for + * @param string $component The module the string is associated with + * @param string|object|array $a An object, string or number that can be used + * within translation strings + * @param string $lang moodle translation language, null means use current + * @return string The String ! + */ + public function get_string($identifier, $component = '', $a = null, $lang = null) { + $key = trim($component) . '/' . trim($identifier); + if (isset($this->customstrings[$key])) { + return $this->customstrings[$key]; + } + return parent::get_string($identifier, $component, $a, $lang); + } + + /** + * Sets a custom string to be returned by the string manager instead of the language file one. + * + * @param string $identifier The identifier of the string to search for + * @param string $component The module the string is associated with + * @param string $value the contents of the language string to be returned by get_string() + */ + public function set_string($identifier, $component, $value) { + $key = trim($component) . '/' . trim($identifier); + $this->customstrings[$key] = $value; + } +} diff --git a/grade/report/singleview/tests/behat/singleview.feature b/grade/report/singleview/tests/behat/singleview.feature index d266c61f07a..a4388a58a4b 100644 --- a/grade/report/singleview/tests/behat/singleview.feature +++ b/grade/report/singleview/tests/behat/singleview.feature @@ -117,6 +117,24 @@ Feature: We can use Single view And I press "Save" Then I should see "Grades were set for 6 items" + Scenario: I can bulk update grades with custom decimal separator + Given the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + And I follow "Single view for Ann, Jill, Grainne, Beauchamp" + And I should see "Gronya,Beecham" + When I set the field "For" to "All grades" + And I set the field "Insert value" to "1#25" + And I set the field "Perform bulk insert" to "1" + And I press "Save" + Then I should see "Grades were set for 6 items" + # Custome scale, cast to int + And the field "Grade for new grade item 1" matches value "Disappointing" + # Value grade, float with custom decsep. + And the field "Grade for Test assignment one" matches value "1#25" + # Numerical scale, cast to int, showing as float with custom decsep. + And the field "Grade for Test grade item" matches value "1#00" + Scenario: Navigation works in the Single view. Given I follow "Single view for Ann, Jill, Grainne, Beauchamp" Then I should see "Gronya,Beecham" diff --git a/grade/tests/behat/grade_category_validation.feature b/grade/tests/behat/grade_category_validation.feature index b7da9640ed9..b11e533b862 100644 --- a/grade/tests/behat/grade_category_validation.feature +++ b/grade/tests/behat/grade_category_validation.feature @@ -101,3 +101,21 @@ Feature: Editing a grade item And I set the field "Maximum grade" to "50" When I press "Save changes" Then I should see "You must choose whether to rescale existing grades or not." + + Scenario: Perform changes to a grade category with custom decimal separator + Given the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + And I navigate to "View > Grader report" in the course gradebook + And I turn editing mode on + And I give the grade "20#00" to the user "Student 1" for the grade item "EN Cat 1 total" + And I press "Save changes" + And I navigate to "Setup > Gradebook setup" in the course gradebook + And I click on "Edit settings" "link" in the "EN Cat 1" "table_row" + And I set the field "Rescale overridden grades" to "Yes" + And I set the field "Maximum grade" to "87#50" + When I press "Save changes" + And I navigate to "View > Grader report" in the course gradebook + And I follow "Single view for Student 1" + Then I should see "Student 1" + And the field "Grade for Category total" matches value "17#50" diff --git a/grade/tests/behat/grade_override_letter.feature b/grade/tests/behat/grade_override_letter.feature index 55a91c9e3d8..d21ae91edb6 100644 --- a/grade/tests/behat/grade_override_letter.feature +++ b/grade/tests/behat/grade_override_letter.feature @@ -69,6 +69,47 @@ Feature: Grade letters can be overridden | | | | | | | A | 95.25 | B | 76.75 | C | 50.01 | D | 40 | F | 0.01 | F- | 0 | 100.00 % | 95.25 % | A | 95.24 % | 76.75 % | B | 76.74 % | 50.01 % | C | 50.00 % | 40.00 % | D | 39.99 % | 0.01 % | F | 0.00 % | 0.00 % | F- | | | | A | 95.25 | B | 76.75 | C | 50.01 | | | | | D | 40 | F | 0.01 | F- | 0 | 100.00 % | 95.25 % | A | 95.24 % | 76.75 % | B | 76.74 % | 50.01 % | C | 50.00 % | 40.00 % | D | 39.99 % | 0.01 % | F | 0.00 % | 0.00 % | F- | + Scenario Outline: Define grade letters with custom decimal separator + Given the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | | + When I set the following fields to these values: + | override | 1 | + | Grade letter 1 | | + | gradeboundary1 | | + | Grade letter 2 | | + | gradeboundary2 | | + | Grade letter 3 | | + | gradeboundary3 | | + | Grade letter 4 | | + | gradeboundary4 | | + | Grade letter 5 | | + | gradeboundary5 | | + | Grade letter 6 | | + | gradeboundary6 | | + | Grade letter 7 | | + | gradeboundary7 | | + | Grade letter 8 | | + | gradeboundary8 | | + | Grade letter 9 | | + | gradeboundary9 | | + | Grade letter 10 | | + | gradeboundary10 | | + | Grade letter 11 | | + | gradeboundary11 | | + And I press "Save changes" + Then I should see "The default grade letters are currently overridden." + And the following should exist in the "grade-letters-view" table: + | Highest | Lowest | Letter | + | | | | + | | | | + | | | | + + Examples: + | decsep | l1 | b1 | l2 | b2 | l3 | b3 | high1 | low1 | high2 | low2 | high3 | low3 | + | . | A | 88.88 | B | 50.00 | C | 0.00 | 100.00 % | 88.88 % | 88.87 % | 50.00 % | 49.99 % | 0.00 % | + | # | A | 88#88 | B | 50#00 | C | 0#00 | 100#00 % | 88#88 % | 88#87 % | 50#00 % | 49#99 % | 0#00 % | + Scenario: I delete a grade letter Given I set the following fields to these values: | override | 1 | diff --git a/grade/tests/behat/grade_to_pass.feature b/grade/tests/behat/grade_to_pass.feature index 79acf830ced..46d8f65d0aa 100644 --- a/grade/tests/behat/grade_to_pass.feature +++ b/grade/tests/behat/grade_to_pass.feature @@ -199,6 +199,30 @@ Feature: We can set the grade to pass value And I follow "Settings" And the field "Grade to pass" matches value "80" + Scenario: Set a valid grade to pass for lesson activity with custom decimal separator + Given the following "activities" exist: + | activity | name | intro | course | section | idnumber | + | lesson | Test Lesson 1 | Test | C1 | 1 | lesson1 | + And the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + And I am on "Course 1" course homepage with editing mode on + And I follow "Test Lesson 1" + And I navigate to "Settings" in current page administration + And I set the following fields to these values: + | Grade to pass | 90#50 | + And I press "Save and return to course" + And I navigate to "View > Grader report" in the course gradebook + And I click on "Edit lesson Test Lesson 1" "link" + And I expand all fieldsets + Then the field "Grade to pass" matches value "90#50" + And I set the field "Grade to pass" to "80" + And I press "Save changes" + And I am on "Course 1" course homepage + And I follow "Test Lesson 1" + And I follow "Settings" + And the field "Grade to pass" matches value "80#00" + Scenario: Set a valid grade to pass for database activity Given the following "activities" exist: | activity | name | intro | course | section | idnumber | diff --git a/mod/lesson/tests/behat/lesson_informations_at_end.feature b/mod/lesson/tests/behat/lesson_informations_at_end.feature index cdbcfb3e773..abc5e7effd8 100644 --- a/mod/lesson/tests/behat/lesson_informations_at_end.feature +++ b/mod/lesson/tests/behat/lesson_informations_at_end.feature @@ -2,7 +2,7 @@ Feature: In a lesson activity, if custom scoring is not enabled, student should see some informations at the end of lesson: questions answered, correct answers, grade, score - Scenario: Informations at end of lesson if custom scoring not enabled + Background: Given the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@example.com | @@ -18,11 +18,10 @@ Feature: In a lesson activity, if custom scoring is not enabled, student should | activity | name | intro | course | section | idnumber | | lesson | Test lesson name | Test lesson description | C1 | 1 | lesson1 | And I log in as "teacher1" - And I am on "Course 1" course homepage - And I follow "Test lesson name" - And I navigate to "Settings" in current page administration + And I am on the "Test lesson name" "lesson activity editing" page And I set the following fields to these values: - | Custom scoring | No | + | Maximum grade | 75 | + | Custom scoring | No | And I press "Save and return to course" And I follow "Test lesson name" And I follow "Add a content page" @@ -47,18 +46,40 @@ Feature: In a lesson activity, if custom scoring is not enabled, student should And I press "Save page" And I log out And I log in as "student1" - And I am on "Course 1" course homepage - When I follow "Test lesson name" - Then I should see "First page contents" - And I press "Next page" + + Scenario: Informations at end of lesson if custom scoring not enabled + Given I am on "Course 1" course homepage + And I follow "Test lesson name" + And I should see "First page contents" + When I press "Next page" And I should see "1 + 1?" And I set the following fields to these values: | Your answer | 1 | And I press "Submit" And I should see "Incorrect answer" And I press "Continue" - And I should see "Congratulations - end of lesson reached" + Then I should see "Congratulations - end of lesson reached" And I should see "Number of questions answered: 1" And I should see "Number of correct answers: 0" And I should see "Your score is 0 (out of 1)." - And I should see "Your current grade is 0.0 out of 100" + And I should see "Your current grade is 0.0 out of 75" + + Scenario: Informations at end of lesson if custom scoring not enabled with custom decimal separator + Given the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + And I am on "Course 1" course homepage + And I follow "Test lesson name" + And I should see "First page contents" + When I press "Next page" + And I should see "1 + 1?" + And I set the following fields to these values: + | Your answer | 1 | + And I press "Submit" + And I should see "Incorrect answer" + And I press "Continue" + Then I should see "Congratulations - end of lesson reached" + And I should see "Number of questions answered: 1" + And I should see "Number of correct answers: 0" + And I should see "Your score is 0 (out of 1)." + And I should see "Your current grade is 0#0 out of 75" diff --git a/mod/quiz/tests/behat/info_page.feature b/mod/quiz/tests/behat/info_page.feature index 96c34611c29..318f7768d99 100644 --- a/mod/quiz/tests/behat/info_page.feature +++ b/mod/quiz/tests/behat/info_page.feature @@ -31,6 +31,19 @@ Feature: Display of information before starting a quiz When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" Then I should see "Grade to pass: 60.00 out of 100.00" + Scenario: Check the pass grade is displayed with custom decimal separator + Given the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + And the following "activities" exist: + | activity | name | intro | course | idnumber | gradepass | + | quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | 60#00 | + And quiz "Quiz 1" contains the following questions: + | question | page | + | TF1 | 1 | + When I am on the "Quiz 1" "mod_quiz > View" page logged in as "student" + Then I should see "Grade to pass: 60#00 out of 100#00" + Scenario: Check the pass grade is not displayed if not set Given the following "activities" exist: | activity | name | intro | course | idnumber | gradepass | diff --git a/mod/quiz/tests/behat/preview.feature b/mod/quiz/tests/behat/preview.feature index f853ec91bf6..dde7286d05a 100644 --- a/mod/quiz/tests/behat/preview.feature +++ b/mod/quiz/tests/behat/preview.feature @@ -41,6 +41,19 @@ Feature: Preview a quiz as a teacher And I follow "Finish review" And "Review" "link" in the "Preview" "table_row" should be visible + @javascript + Scenario: Review the quiz attempt with custom decimal separator + Given the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + When I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher" + And I follow "Review" + Then I should see "1#00/4#00" + And I should see "25#00 out of 100#00" + And I should see "Mark 1#00 out of 1#00" + And I follow "Finish review" + And "Review" "link" in the "Preview" "table_row" should be visible + @javascript Scenario: Preview the quiz Given I am on the "Quiz 1" "mod_quiz > View" page logged in as "teacher" diff --git a/question/type/ddimageortext/tests/behat/edit.feature b/question/type/ddimageortext/tests/behat/edit.feature index 7fecbcfe477..9bb97d495ef 100644 --- a/question/type/ddimageortext/tests/behat/edit.feature +++ b/question/type/ddimageortext/tests/behat/edit.feature @@ -31,3 +31,20 @@ Feature: Test editing a drag and drop onto image questions | Question name | Edited question name | And I press "id_submitbutton" Then I should see "Edited question name" + + Scenario: Edit a drag and drop onto image question and verify penalty works as expected + When I choose "Edit question" action for "Drag onto image" in the question bank + Then the following fields match these values: + | Question name | Drag onto image | + | Penalty for each incorrect try | 33.33333% | + | Penalty for each incorrect try | 0.3333333 | + + Scenario: Edit a drag and drop onto image question and verify penalty works as expected with custom decimal separator + When the following "language customisations" exist: + | component | stringid | value | + | core_langconfig | decsep | # | + And I choose "Edit question" action for "Drag onto image" in the question bank + Then the following fields match these values: + | Question name | Drag onto image | + | Penalty for each incorrect try | 33#33333% | + | Penalty for each incorrect try | 0.3333333 |