From 42ad096fdb0184c2a7fbed82ac8c91583ae3b48d Mon Sep 17 00:00:00 2001 From: Rajesh Taneja Date: Tue, 9 Dec 2014 17:00:58 +0800 Subject: [PATCH] MDL-46891 Behat: Added support for behat 3 --- admin/tests/behat/behat_admin.php | 3 +- admin/tool/behat/tests/manager_test.php | 3 +- .../tests/behat/manage_langpacks.feature | 14 +- auth/tests/behat/behat_auth.php | 4 +- backup/util/ui/tests/behat/behat_backup.php | 9 +- behat.yml.dist | 15 +- blocks/tests/behat/behat_blocks.php | 2 +- calendar/tests/behat/behat_calendar.php | 2 +- cohort/tests/behat/behat_cohort.php | 2 +- completion/tests/behat/behat_completion.php | 4 +- config-dist.php | 11 +- course/tests/behat/behat_course.php | 8 +- course/tests/behat/category_resort.feature | 1 - course/tests/behat/course_resort.feature | 1 - enrol/tests/behat/behat_enrol.php | 2 +- .../tests/behat/behat_gradingform_guide.php | 6 +- .../tests/behat/behat_gradingform_rubric.php | 13 +- grade/grading/tests/behat/behat_grading.php | 6 +- .../tests/behat/behat_gradereport_grader.php | 4 +- grade/tests/behat/behat_grade.php | 2 +- group/tests/behat/behat_groups.php | 2 +- lib/behat/behat_base.php | 18 +- lib/behat/classes/behat_config_manager.php | 33 ++- lib/behat/classes/behat_selectors.php | 4 +- lib/behat/form_field/behat_form_checkbox.php | 19 +- lib/behat/form_field/behat_form_radio.php | 19 +- lib/behat/form_field/behat_form_select.php | 200 +++--------------- lib/tests/behat/behat_deprecated.php | 4 +- lib/tests/behat/behat_forms.php | 9 +- lib/tests/behat/behat_general.php | 6 +- lib/tests/behat/behat_hooks.php | 145 +++++++------ lib/tests/behat/behat_navigation.php | 7 +- lib/tests/behat/behat_permissions.php | 2 +- lib/tests/behat/behat_transformations.php | 21 +- message/tests/behat/behat_message.php | 2 +- .../behat/behat_assignfeedback_editpdf.php | 2 - mod/choice/tests/behat/behat_mod_choice.php | 2 +- mod/data/tests/behat/behat_mod_data.php | 4 +- .../tests/behat/behat_mod_feedback.php | 6 +- mod/forum/tests/behat/behat_mod_forum.php | 2 +- .../tests/behat/behat_mod_glossary.php | 2 +- mod/quiz/tests/behat/behat_mod_quiz.php | 9 +- .../behat/behat_workshopallocation_manual.php | 3 +- .../tests/behat/behat_mod_workshop.php | 2 +- question/tests/behat/behat_question.php | 2 +- question/tests/behat/behat_question_base.php | 2 +- repository/tests/behat/behat_filepicker.php | 4 +- .../tests/behat/behat_repository_upload.php | 4 +- 48 files changed, 266 insertions(+), 381 deletions(-) diff --git a/admin/tests/behat/behat_admin.php b/admin/tests/behat/behat_admin.php index 8c56f7ae55239..8f69e31299fb9 100644 --- a/admin/tests/behat/behat_admin.php +++ b/admin/tests/behat/behat_admin.php @@ -28,8 +28,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php'); -use Behat\Behat\Context\Step\Given as Given, - Behat\Gherkin\Node\TableNode as TableNode, +use Behat\Gherkin\Node\TableNode as TableNode, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; /** diff --git a/admin/tool/behat/tests/manager_test.php b/admin/tool/behat/tests/manager_test.php index 1dc44eff76a48..0f24f38621dd3 100644 --- a/admin/tool/behat/tests/manager_test.php +++ b/admin/tool/behat/tests/manager_test.php @@ -142,11 +142,10 @@ public function test_config_file_contents() { // YAML decides when is is necessary to wrap strings between single quotes, so not controlled // values like paths should not be asserted including the key name as they would depend on the // directories values. - $this->assertContains($CFG->dirroot . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR . 'features', $contents); + $this->assertContains($CFG->dirroot, $contents); // Not quoted strings. $this->assertContains('micarro: /me/lo/robaron', $contents); - $this->assertContains('class: behat_init_context', $contents); // YAML uses single quotes to wrap URL strings. $this->assertContains("base_url: '" . $CFG->behat_wwwroot . "'", $contents); diff --git a/admin/tool/langimport/tests/behat/manage_langpacks.feature b/admin/tool/langimport/tests/behat/manage_langpacks.feature index 4d518de55e9af..6d6f0f0e394d6 100644 --- a/admin/tool/langimport/tests/behat/manage_langpacks.feature +++ b/admin/tool/langimport/tests/behat/manage_langpacks.feature @@ -13,10 +13,10 @@ Feature: Manage language packs Scenario: Install language pack Given I log in as "admin" And I navigate to "Language packs" node in "Site administration > Language" - When I set the field "Available language packs" to "English - Pirate (en_ar)" + When I set the field "Available language packs" to "en_ar" And I press "Install selected language pack(s)" Then I should see "Language pack 'en_ar' was successfully installed" - And the "Installed language packs" select box should contain "English - Pirate (en_ar)" + And the "Installed language packs" select box should contain "en_ar" And I navigate to "Live logs" node in "Site administration > Reports" And I should see "The language pack 'en_ar' was installed." And I log out @@ -35,14 +35,14 @@ Feature: Manage language packs Scenario: Try to uninstall language pack Given I log in as "admin" And I navigate to "Language packs" node in "Site administration > Language" - And I set the field "Available language packs" to "English - Pirate (en_ar)" + And I set the field "Available language packs" to "en_ar" And I press "Install selected language pack(s)" - When I set the field "Installed language packs" to "English - Pirate (en_ar)" + When I set the field "Installed language packs" to "en_ar" And I press "Uninstall selected language pack(s)" And I press "Continue" Then I should see "Language pack 'en_ar' was uninstalled" - And the "Installed language packs" select box should not contain "English - Pirate (en_ar)" - And the "Available language packs" select box should contain "English - Pirate (en_ar)" + And the "Installed language packs" select box should not contain "en_ar" + And the "Available language packs" select box should contain "en_ar" And I navigate to "Live logs" node in "Site administration > Reports" And I should see "The language pack 'en_ar' was removed." And I should see "Language pack uninstalled" @@ -51,7 +51,7 @@ Feature: Manage language packs Scenario: Try to uninstall English language pack Given I log in as "admin" And I navigate to "Language packs" node in "Site administration > Language" - When I set the field "Installed language packs" to "English (en)" + When I set the field "Installed language packs" to "en" And I press "Uninstall selected language pack(s)" Then I should see "The English language pack cannot be uninstalled." And I navigate to "Live logs" node in "Site administration > Reports" diff --git a/auth/tests/behat/behat_auth.php b/auth/tests/behat/behat_auth.php index 959c2fb043ddf..806aa09eba20f 100644 --- a/auth/tests/behat/behat_auth.php +++ b/auth/tests/behat/behat_auth.php @@ -28,8 +28,8 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; -use Behat\Behat\Context\Step\When as When; +use Moodle\BehatExtension\Context\Step\Given as Given; +use Moodle\BehatExtension\Context\Step\When as When; /** * Log in log out steps definitions. diff --git a/backup/util/ui/tests/behat/behat_backup.php b/backup/util/ui/tests/behat/behat_backup.php index bd0f777881b63..410cdef918483 100644 --- a/backup/util/ui/tests/behat/behat_backup.php +++ b/backup/util/ui/tests/behat/behat_backup.php @@ -219,7 +219,6 @@ public function i_restore_backup_into_course_using_this_options($backupfilename, "/descendant::div[@class='restore-course-search']" . "/descendant::tr[contains(., $existingcourse)]" . "/descendant::input[@type='radio']"); - $radionode->check(); $radionode->click(); // Pressing the continue button of the restore into an existing course section. @@ -250,7 +249,6 @@ public function i_restore_backup_into_a_new_course_using_this_options($backupfil $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-new-course ')]" . "/descendant::div[@class='restore-course-search']" . "/descendant::input[@type='radio']"); - $radionode->check(); $radionode->click(); // Pressing the continue button of the restore into an existing course section. @@ -280,7 +278,6 @@ public function i_merge_backup_into_the_current_course($backupfilename, $options // Merge without deleting radio option. $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" . "/descendant::input[@type='radio'][@name='target'][@value='1']"); - $radionode->check(); $radionode->click(); // Pressing the continue button of the restore merging section. @@ -310,7 +307,6 @@ public function i_merge_backup_into_current_course_deleting_its_contents($backup // Delete contents radio option. $radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" . "/descendant::input[@type='radio'][@name='target'][@value='0']"); - $radionode->check(); $radionode->click(); // Pressing the continue button of the restore merging section. @@ -419,8 +415,6 @@ protected function get_step_options($options, $step) { return; } - $pageoptions = clone $options; - $rows = $options->getRows(); $newrows = array(); foreach ($rows as $k => $data) { @@ -433,7 +427,8 @@ protected function get_step_options($options, $step) { $newrows[] = $data; } } - $pageoptions->setRows($newrows); + $pageoptions = new TableNode($newrows); + return $pageoptions; } diff --git a/behat.yml.dist b/behat.yml.dist index 60cf8071e6489..8c7e910002d19 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -1,14 +1,13 @@ default: - paths: - features: lib/behat/features - bootstrap: lib/behat/features/bootstrap - context: - class: behat_init_context + suites: + default: + paths: { } + contexts: { } extensions: - Behat\MinkExtension\Extension: + Behat\MinkExtension: base_url: 'http://localhost:8000' goutte: null selenium2: null - Moodle\BehatExtension\Extension: - features: { } + Moodle\BehatExtension: + moodledirroot: /Should/Change/To/Moodle/www/dir steps_definitions: { } diff --git a/blocks/tests/behat/behat_blocks.php b/blocks/tests/behat/behat_blocks.php index a10250dcae647..2d8143ca38c10 100644 --- a/blocks/tests/behat/behat_blocks.php +++ b/blocks/tests/behat/behat_blocks.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; +use Moodle\BehatExtension\Context\Step\Given as Given; /** * Blocks management steps definitions. diff --git a/calendar/tests/behat/behat_calendar.php b/calendar/tests/behat/behat_calendar.php index 70e57b227309b..9dc24a251e690 100644 --- a/calendar/tests/behat/behat_calendar.php +++ b/calendar/tests/behat/behat_calendar.php @@ -26,7 +26,7 @@ // NOTE: no MOODLE_INTERNAL used, this file may be required by behat before including /config.php. require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; +use Moodle\BehatExtension\Context\Step\Given as Given; use Behat\Gherkin\Node\TableNode as TableNode; /** diff --git a/cohort/tests/behat/behat_cohort.php b/cohort/tests/behat/behat_cohort.php index 8c860b561fbff..e1fd62192c898 100644 --- a/cohort/tests/behat/behat_cohort.php +++ b/cohort/tests/behat/behat_cohort.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; +use Moodle\BehatExtension\Context\Step\Given as Given; /** * Steps definitions for cohort actions. diff --git a/completion/tests/behat/behat_completion.php b/completion/tests/behat/behat_completion.php index f1b4215a9ee7a..0bd4e809f0548 100644 --- a/completion/tests/behat/behat_completion.php +++ b/completion/tests/behat/behat_completion.php @@ -27,8 +27,8 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given, - Behat\Behat\Context\Step\Then, +use Moodle\BehatExtension\Context\Step\Given, + Moodle\BehatExtension\Context\Step\Then, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; /** diff --git a/config-dist.php b/config-dist.php index 8d8d481e1a07e..bb1bc60562c75 100644 --- a/config-dist.php +++ b/config-dist.php @@ -683,8 +683,15 @@ // ) // ), // 'Mac-Firefox' => array( +// 'suites' => array ( +// 'default' => array( +// 'filters' => array( +// 'tags' => '~@_file_upload' +// ), +// ), +// ), // 'extensions' => array( -// 'Behat\MinkExtension\Extension' => array( +// 'Behat\MinkExtension' => array( // 'selenium2' => array( // 'browser' => 'firefox', // 'capabilities' => array( @@ -697,7 +704,7 @@ // ), // 'Mac-Safari' => array( // 'extensions' => array( -// 'Behat\MinkExtension\Extension' => array( +// 'Behat\MinkExtension' => array( // 'selenium2' => array( // 'browser' => 'safari', // 'capabilities' => array( diff --git a/course/tests/behat/behat_course.php b/course/tests/behat/behat_course.php index 344a208c3dfeb..09ee8d4f78137 100644 --- a/course/tests/behat/behat_course.php +++ b/course/tests/behat/behat_course.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode, Behat\Mink\Exception\ExpectationException as ExpectationException, Behat\Mink\Exception\DriverException as DriverException, @@ -97,7 +97,7 @@ public function i_create_a_course_with(TableNode $table) { unset($rows[$key]); } } - $table->setRows($rows); + $table = new TableNode($rows); // Adding a forced wait until editors are loaded as otherwise selenium sometimes tries clicks on the // format field when the editor is being rendered and the click misses the field coordinates. @@ -585,7 +585,7 @@ public function activity_should_be_visible($activityname) { // The 'Hide' button should be available. $nohideexception = new ExpectationException('"' . $activityname . '" don\'t have a "' . get_string('hide') . '" icon', $this->getSession()); - $this->find('named', array('link', get_string('hide')), $nohideexception, $activitynode); + $this->find('named_partial', array('link', get_string('hide')), $nohideexception, $activitynode); } } @@ -611,7 +611,7 @@ public function activity_should_be_hidden($activityname) { // Also 'Show' icon. $noshowexception = new ExpectationException('"' . $activityname . '" don\'t have a "' . get_string('show') . '" icon', $this->getSession()); - $this->find('named', array('link', get_string('show')), $noshowexception, $activitynode); + $this->find('named_partial', array('link', get_string('show')), $noshowexception, $activitynode); } else { diff --git a/course/tests/behat/category_resort.feature b/course/tests/behat/category_resort.feature index dc35898d0dfad..42dacac5fa69a 100644 --- a/course/tests/behat/category_resort.feature +++ b/course/tests/behat/category_resort.feature @@ -105,7 +105,6 @@ Feature: Test we can resort categories in the management interface. And I should see the "Course categories and courses" management page And I click on action for "Master cat" in management category listing And a new page should have loaded since I started watching - And I start watching to see if a new page loads And I should see the "Course categories and courses" management page And I should see category listing before And I should see category listing before diff --git a/course/tests/behat/course_resort.feature b/course/tests/behat/course_resort.feature index cee3ccd72a2c2..f117146cad03d 100644 --- a/course/tests/behat/course_resort.feature +++ b/course/tests/behat/course_resort.feature @@ -86,7 +86,6 @@ Feature: Test we can resort course in the management interface. And I should see "Sort by Course time created descending" in the ".course-listing-actions" "css_element" And I click on "link" in the ".course-listing-actions" "css_element" And a new page should have loaded since I started watching - And I start watching to see if a new page loads And I should see the "Course categories and courses" management page And I should see course listing before And I should see course listing before diff --git a/enrol/tests/behat/behat_enrol.php b/enrol/tests/behat/behat_enrol.php index 116e0a24fdd58..034898ce4497b 100644 --- a/enrol/tests/behat/behat_enrol.php +++ b/enrol/tests/behat/behat_enrol.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode; /** diff --git a/grade/grading/form/guide/tests/behat/behat_gradingform_guide.php b/grade/grading/form/guide/tests/behat/behat_gradingform_guide.php index 7ce443c64ad10..e63fc5dd4d150 100644 --- a/grade/grading/form/guide/tests/behat/behat_gradingform_guide.php +++ b/grade/grading/form/guide/tests/behat/behat_gradingform_guide.php @@ -26,9 +26,9 @@ require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php'); use Behat\Gherkin\Node\TableNode as TableNode, - Behat\Behat\Context\Step\Given as Given, - Behat\Behat\Context\Step\When as When, - Behat\Behat\Context\Step\Then as Then, + Moodle\BehatExtension\Context\Step\Given as Given, + Moodle\BehatExtension\Context\Step\When as When, + Moodle\BehatExtension\Context\Step\Then as Then, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException, Behat\Mink\Exception\ExpectationException as ExpectationException; diff --git a/grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php b/grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php index e01387b16a566..778c7ff1b0398 100644 --- a/grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php +++ b/grade/grading/form/rubric/tests/behat/behat_gradingform_rubric.php @@ -28,9 +28,7 @@ require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php'); use Behat\Gherkin\Node\TableNode as TableNode, - Behat\Behat\Context\Step\Given as Given, - Behat\Behat\Context\Step\When as When, - Behat\Behat\Context\Step\Then as Then, + Moodle\BehatExtension\Context\Step\Given as Given, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException, Behat\Mink\Exception\ExpectationException as ExpectationException; @@ -107,6 +105,15 @@ public function i_define_the_following_rubric(TableNode $rubric) { } } + // Remove empty criterion, as TableNode might contain them to make table rows equal size. + $newcriterion = array(); + foreach ($criterion as $k => $c) { + if (!empty($c)) { + $newcriterion[$k] = $c; + } + } + $criterion = $newcriterion; + // Checking the number of cells. if (count($criterion) % 2 === 0) { throw new ExpectationException( diff --git a/grade/grading/tests/behat/behat_grading.php b/grade/grading/tests/behat/behat_grading.php index 0a0bf07862ad4..f76117cb978c5 100644 --- a/grade/grading/tests/behat/behat_grading.php +++ b/grade/grading/tests/behat/behat_grading.php @@ -28,8 +28,8 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); use Behat\Gherkin\Node\TableNode as TableNode, - Behat\Behat\Context\Step\Given as Given, - Behat\Behat\Context\Step\When as When; + Moodle\BehatExtension\Context\Step\Given as Given, + Moodle\BehatExtension\Context\Step\When as When; /** * Generic grading methods step definitions. @@ -93,7 +93,7 @@ public function i_go_to_activity_advanced_grading_page($userfullname, $activityn // Shortcut in case we already are in the grading page. $usergradetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($usergradetext); - if ($this->getSession()->getPage()->find('named', array('link', $usergradetextliteral))) { + if ($this->getSession()->getPage()->find('named_partial', array('link', $usergradetextliteral))) { return $gradeuserstep; } diff --git a/grade/report/grader/tests/behat/behat_gradereport_grader.php b/grade/report/grader/tests/behat/behat_gradereport_grader.php index ee12feba93c9d..3e2bcd1bef6dd 100644 --- a/grade/report/grader/tests/behat/behat_gradereport_grader.php +++ b/grade/report/grader/tests/behat/behat_gradereport_grader.php @@ -27,8 +27,8 @@ require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given, - Behat\Behat\Context\Step\Then, +use Moodle\BehatExtension\Context\Step\Given, + Moodle\BehatExtension\Context\Step\Then, Behat\Mink\Exception\ExpectationException as ExpectationException, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; diff --git a/grade/tests/behat/behat_grade.php b/grade/tests/behat/behat_grade.php index 6ee26bf25017b..76ef7f6a85732 100644 --- a/grade/tests/behat/behat_grade.php +++ b/grade/tests/behat/behat_grade.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode; class behat_grade extends behat_base { diff --git a/group/tests/behat/behat_groups.php b/group/tests/behat/behat_groups.php index 54aea96310de5..6ab66d8209f8b 100644 --- a/group/tests/behat/behat_groups.php +++ b/group/tests/behat/behat_groups.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Then; +use Moodle\BehatExtension\Context\Step\Then; use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; /** diff --git a/lib/behat/behat_base.php b/lib/behat/behat_base.php index efe954b3893b4..de3b87e52795e 100644 --- a/lib/behat/behat_base.php +++ b/lib/behat/behat_base.php @@ -102,6 +102,13 @@ protected function locate_path($path) { */ protected function find($selector, $locator, $exception = false, $node = false, $timeout = false) { + // Throw exception, so dev knows it is not supported. + if ($selector === 'named') { + $exception = 'Using the "named" selector is deprecated as of 3.1. ' + .' Use the "named_partial" or use the "named_exact" selector instead.'; + throw new ExpectationException($exception, $this->getSession()); + } + // Returns the first match. $items = $this->find_all($selector, $locator, $exception, $node, $timeout); return count($items) ? reset($items) : null; @@ -122,11 +129,18 @@ protected function find($selector, $locator, $exception = false, $node = false, */ protected function find_all($selector, $locator, $exception = false, $node = false, $timeout = false) { + // Throw exception, so dev knows it is not supported. + if ($selector === 'named') { + $exception = 'Using the "named" selector is deprecated as of 3.1. ' + .' Use the "named_partial" or use the "named_exact" selector instead.'; + throw new ExpectationException($exception, $this->getSession()); + } + // Generic info. if (!$exception) { // With named selectors we can be more specific. - if ($selector == 'named') { + if (($selector == 'named_exact') || ($selector == 'named_partial')){ $exceptiontype = $locator[0]; $exceptionlocator = $locator[1]; @@ -236,7 +250,7 @@ public function __call($name, $arguments) { // Redirecting execution to the find method with the specified selector. // It will detect if it's pointing to an unexisting named selector. - return $this->find('named', + return $this->find('named_partial', array( $cleanname, $this->getSession()->getSelectorsHandler()->xpathLiteral($arguments[0]) diff --git a/lib/behat/classes/behat_config_manager.php b/lib/behat/classes/behat_config_manager.php index 0108064633ec0..a0e2c88602464 100644 --- a/lib/behat/classes/behat_config_manager.php +++ b/lib/behat/classes/behat_config_manager.php @@ -397,35 +397,32 @@ protected static function get_config_file_contents($features, $stepsdefinitions) $CFG->behat_wwwroot = 'http://itwillnotbeused.com'; } - $basedir = $CFG->dirroot . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'behat'; - + // Comments use black color, so failure path is not visible. Using color other then black/white is safer. + // https://github.com/Behat/Behat/pull/628. $config = array( 'default' => array( - 'paths' => array( - 'features' => $basedir . DIRECTORY_SEPARATOR . 'features', - 'bootstrap' => $basedir . DIRECTORY_SEPARATOR . 'features' . DIRECTORY_SEPARATOR . 'bootstrap', + 'formatters' => array( + 'moodle_progress' => array( + 'output_styles' => array( + 'comment' => array('magenta')) + ) ), - 'context' => array( - 'class' => 'behat_init_context' + 'suites' => array( + 'default' => array( + 'paths' => $features, + 'contexts' => array_keys($stepsdefinitions) + ) ), 'extensions' => array( - 'Behat\MinkExtension\Extension' => array( + 'Behat\MinkExtension' => array( 'base_url' => $CFG->behat_wwwroot, 'goutte' => null, 'selenium2' => $selenium2wdhost ), - 'Moodle\BehatExtension\Extension' => array( - 'formatters' => array( - 'moodle_progress' => 'Moodle\BehatExtension\Formatter\MoodleProgressFormatter', - 'moodle_list' => 'Moodle\BehatExtension\Formatter\MoodleListFormatter', - 'moodle_step_count' => 'Moodle\BehatExtension\Formatter\MoodleStepCountFormatter' - ), - 'features' => $features, + 'Moodle\BehatExtension' => array( + 'moodledirroot' => $CFG->dirroot, 'steps_definitions' => $stepsdefinitions ) - ), - 'formatter' => array( - 'name' => 'moodle_progress' ) ) ); diff --git a/lib/behat/classes/behat_selectors.php b/lib/behat/classes/behat_selectors.php index 76921aa1ca1f5..c328f5d627ba4 100644 --- a/lib/behat/classes/behat_selectors.php +++ b/lib/behat/classes/behat_selectors.php @@ -158,7 +158,7 @@ public static function get_behat_selector($selectortype, $element, Behat\Mink\Se } else { // Named selectors uses arrays as locators including the type of named selector. $locator = array($selectortype, $session->getSelectorsHandler()->xpathLiteral($element)); - $selector = 'named'; + $selector = 'named_partial'; } return array($selector, $locator); @@ -173,7 +173,7 @@ public static function get_behat_selector($selectortype, $element, Behat\Mink\Se public static function register_moodle_selectors(Behat\Mink\Session $session) { foreach (self::get_moodle_selectors() as $name => $xpath) { - $session->getSelectorsHandler()->getSelector('named')->registerNamedXpath($name, $xpath); + $session->getSelectorsHandler()->getSelector('named_partial')->registerNamedXpath($name, $xpath); } } diff --git a/lib/behat/form_field/behat_form_checkbox.php b/lib/behat/form_field/behat_form_checkbox.php index 69a9cbc8b3415..dc568b08e1b2a 100644 --- a/lib/behat/form_field/behat_form_checkbox.php +++ b/lib/behat/form_field/behat_form_checkbox.php @@ -58,10 +58,7 @@ public function set_value($value) { $this->field->click(); // Trigger the onchange event as triggered when 'checking' the checkbox. - $this->session->getDriver()->triggerSynScript( - $this->field->getXPath(), - "Syn.trigger('change', {}, {{ELEMENT}})" - ); + $this->trigger_on_change(); } else if (empty($value) && $this->field->isChecked()) { @@ -74,10 +71,7 @@ public function set_value($value) { $this->field->click(); // Trigger the onchange event as triggered when 'checking' the checkbox. - $this->session->getDriver()->triggerSynScript( - $this->field->getXPath(), - "Syn.trigger('change', {}, {{ELEMENT}})" - ); + $this->trigger_on_change(); } } @@ -110,4 +104,13 @@ public function matches($expectedvalue = false) { return false; } + /** + * Trigger on change event. + */ + protected function trigger_on_change() { + $this->session->getDriver()->triggerSynScript( + $this->field->getXPath(), + "Syn.trigger('change', {}, {{ELEMENT}})" + ); + } } diff --git a/lib/behat/form_field/behat_form_radio.php b/lib/behat/form_field/behat_form_radio.php index 8304133dae63f..22e064c17c5f2 100644 --- a/lib/behat/form_field/behat_form_radio.php +++ b/lib/behat/form_field/behat_form_radio.php @@ -59,7 +59,7 @@ class behat_form_radio extends behat_form_checkbox { * @return string The value attribute */ public function get_value() { - return (bool)$this->field->getAttribute('checked'); + return $this->field->isSelected(); } /** @@ -75,20 +75,17 @@ public function get_value() { public function set_value($value) { if ($this->running_javascript()) { - parent::set_value($value); + // Check on radio button. + $this->field->click(); + + // Trigger the onchange event as triggered when 'selecting' the radio. + if (!empty($value) && !$this->field->isSelected()) { + $this->trigger_on_change(); + } } else { // Goutte does not accept a check nor a click in an input[type=radio]. $this->field->setValue($this->field->getAttribute('value')); } } - /** - * Returns whether the provided value matches the current value or not. - * - * @param string $expectedvalue - * @return bool - */ - public function matches($expectedvalue = false) { - return $this->text_matches($expectedvalue); - } } diff --git a/lib/behat/form_field/behat_form_select.php b/lib/behat/form_field/behat_form_select.php index 6bc66a83cb02e..880d061ebd55d 100644 --- a/lib/behat/form_field/behat_form_select.php +++ b/lib/behat/form_field/behat_form_select.php @@ -49,28 +49,14 @@ class behat_form_select extends behat_form_field { */ public function set_value($value) { - // In some browsers we select an option and it triggers all the - // autosubmits and works as expected but not in all of them, so we - // try to catch all the possibilities to make this function work as - // expected. - - // Get the internal id of the element we are going to click. - // This kind of internal IDs are only available in the selenium wire - // protocol, so only available using selenium drivers, phantomjs and family. - if ($this->running_javascript()) { - $currentelementid = $this->get_internal_field_id(); - } - // Is the select multiple? $multiple = $this->field->hasAttribute('multiple'); - - // By default, assume the passed value is a non-multiple option. - $options = array(trim($value)); + $singleselect = ($this->field->hasClass('singleselect') || $this->field->hasClass('urlselect')); // Here we select the option(s). if ($multiple) { // Split and decode values. Comma separated list of values allowed. With valuable commas escaped with backslash. - $options = preg_replace('/\\\,/', ',', preg_split('/(?field->getValue() == $value) { - return; - } else { - $opt = $this->field->find('named', array( - 'option', $this->field->getSession()->getSelectorsHandler()->xpathLiteral($value) - )); - if ($opt && ($this->field->getValue() == $opt->getValue())) { - return; - } - } - - // If not running JS or not a singleselect then use selectOption. - // For singleselect only click event is enough. - if (!$this->running_javascript() || - !($this->field->hasClass('singleselect') || $this->field->hasClass('urlselect'))) { - - // This is a single select, let's pass the last one specified. - $this->field->selectOption(end($options)); - } - } - - // With JS disabled this is enough and we finish here. - if (!$this->running_javascript()) { - return; - } - - // With JS enabled we add more clicks as some selenium - // drivers requires it to fire JS events. - - // In some browsers the selectOption actions can perform a form submit or reload page - // so we need to ensure the element is still available to continue interacting - // with it. We don't wait here. - // getXpath() does not send a query to selenium, so we don't need to wrap it in a try & catch. - $selectxpath = $this->field->getXpath(); - if (!$this->session->getDriver()->find($selectxpath)) { - return; - } - - // We also check the selenium internal element id, if it have changed - // we are dealing with an autosubmit that was already executed, and we don't to - // execute anything else as the action we wanted was already performed. - if ($currentelementid != $this->get_internal_field_id()) { - return; - } + // By default, assume the passed value is a non-multiple option. + $this->field->selectOption(trim($value)); + } // Wait for all the possible AJAX requests that have been // already triggered by selectOption() to be finished. - $this->session->wait(behat_base::TIMEOUT * 1000, behat_base::PAGE_READY_JS); - - // Wrapped in try & catch as the element may disappear if an AJAX request was submitted. - try { - $multiple = $this->field->hasAttribute('multiple'); - } catch (Exception $e) { - // We do not specify any specific Exception type as there are - // different exceptions that can be thrown by the driver and - // we can not control them all, also depending on the selenium - // version the exception type can change. - return; - } - - // Single select sometimes needs an extra click in the option. - if (!$multiple) { - - // Var $options only contains 1 option. - $optionxpath = $this->get_option_xpath(end($options), $selectxpath); - - // Using the driver direcly because Element methods are messy when dealing - // with elements inside containers. - if ($optionnodes = $this->session->getDriver()->find($optionxpath)) { - - // Wrapped in a try & catch as we can fall into race conditions - // and the element may not be there. - try { - current($optionnodes)->click(); - } catch (Exception $e) { - // We continue and return as this means that the element is not there or it is not the same. - return; - } - } - - } else { - - // Wrapped in a try & catch as we can fall into race conditions - // and the element may not be there. - try { - // Multiple ones needs the click in the select. - $this->field->click(); - } catch (Exception $e) { - // We continue and return as this means that the element is not there or it is not the same. - return; - } - - // We also check that the option(s) are still there. We neither wait. - foreach ($options as $option) { - $optionxpath = $this->get_option_xpath($option, $selectxpath); - if (!$this->session->getDriver()->find($optionxpath)) { - return; - } + if ($this->running_javascript()) { + // Trigger change event as this is needed by some drivers (Phantomjs). Don't do it for + // Singleselect as this will cause multiple event fire and lead to race-around condition. + $browser = \Moodle\BehatExtension\Driver\MoodleSelenium2Driver::getBrowser(); + if (!$singleselect && ($browser == 'phantomjs')) { + $script = "Syn.trigger('change', {}, {{ELEMENT}})"; + $this->session->getDriver()->triggerSynScript($this->field->getXpath(), $script); } - - // Wait for all the possible AJAX requests that have been - // already triggered by clicking on the field to be finished. $this->session->wait(behat_base::TIMEOUT * 1000, behat_base::PAGE_READY_JS); - - // Wrapped in a try & catch as we can fall into race conditions - // and the element may not be there. - try { - - // Repeating the select(s) as some drivers (chrome that I know) are moving - // to another option after the general select field click above. - $afterfirstoption = false; - foreach ($options as $option) { - $this->field->selectOption(trim($option), $afterfirstoption); - $afterfirstoption = true; - } - } catch (Exception $e) { - // We continue and return as this means that the element is not there or it is not the same. - return; - } } } @@ -233,9 +114,6 @@ public function matches($expectedvalue) { // We are dealing with a multi-select. - // Can pass multiple comma separated, with valuable commas escaped with backslash. - $expectedarr = array(); // Array of passed text options to test. - // Unescape + trim all options and flip it to have the expected values as keys. $expectedoptions = $this->get_unescaped_options($expectedvalue); @@ -306,45 +184,23 @@ protected function get_selected_options($returntexts = true) { $selectedoptions = array(); // To accumulate found selected options. - // Selenium getValue() implementation breaks - separates - values having - // commas within them, so we'll be looking for options with the 'selected' attribute instead. - if ($this->running_javascript()) { - // Get all the options in the select and extract their value/text pairs. - $alloptions = $this->field->findAll('xpath', '//option'); - foreach ($alloptions as $option) { - // Is it selected? - if ($option->hasAttribute('selected')) { - if ($multiple) { - // If the select is multiple, text commas must be encoded. - $selectedoptions[] = trim(str_replace(',', '\,', $option->{$method}())); - } else { - $selectedoptions[] = trim($option->{$method}()); - } - } - } - - } else { - // Goutte does not keep the 'selected' attribute updated, but its getValue() returns - // the selected elements correctly, also those having commas within them. - - // Goutte returns the values as an array or as a string depending - // on whether multiple options are selected or not. - $values = $this->field->getValue(); - if (!is_array($values)) { - $values = array($values); - } + // Driver returns the values as an array or as a string depending + // on whether multiple options are selected or not. + $values = $this->field->getValue(); + if (!is_array($values)) { + $values = array($values); + } - // Get all the options in the select and extract their value/text pairs. - $alloptions = $this->field->findAll('xpath', '//option'); - foreach ($alloptions as $option) { - // Is it selected? - if (in_array($option->getValue(), $values)) { - if ($multiple) { - // If the select is multiple, text commas must be encoded. - $selectedoptions[] = trim(str_replace(',', '\,', $option->{$method}())); - } else { - $selectedoptions[] = trim($option->{$method}()); - } + // Get all the options in the select and extract their value/text pairs. + $alloptions = $this->field->findAll('xpath', '//option'); + foreach ($alloptions as $option) { + // Is it selected? + if (in_array($option->getValue(), $values)) { + if ($multiple) { + // If the select is multiple, text commas must be encoded. + $selectedoptions[] = trim(str_replace(',', '\,', $option->{$method}())); + } else { + $selectedoptions[] = trim($option->{$method}()); } } } diff --git a/lib/tests/behat/behat_deprecated.php b/lib/tests/behat/behat_deprecated.php index 495a4864eef00..1cc0672505144 100644 --- a/lib/tests/behat/behat_deprecated.php +++ b/lib/tests/behat/behat_deprecated.php @@ -28,8 +28,8 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); use Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException, - Behat\Behat\Context\Step\Given as Given, - Behat\Behat\Context\Step\Then as Then, + Moodle\BehatExtension\Context\Step\Given as Given, + Moodle\BehatExtension\Context\Step\Then as Then, Behat\Gherkin\Node\TableNode as TableNode; /** diff --git a/lib/tests/behat/behat_forms.php b/lib/tests/behat/behat_forms.php index f36571d81a9ff..d750a8f0ba170 100644 --- a/lib/tests/behat/behat_forms.php +++ b/lib/tests/behat/behat_forms.php @@ -28,12 +28,11 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php'); -use Behat\Behat\Context\Step\Given as Given, - Behat\Behat\Context\Step\When as When, - Behat\Behat\Context\Step\Then as Then, - Behat\Gherkin\Node\TableNode as TableNode, +use Behat\Gherkin\Node\TableNode as TableNode, + Moodle\BehatExtension\Context\Step\Given as Given, + Moodle\BehatExtension\Context\Step\When as When, + Moodle\BehatExtension\Context\Step\Then as Then, Behat\Gherkin\Node\PyStringNode as PyStringNode, - Behat\Mink\Element\NodeElement as NodeElement, Behat\Mink\Exception\ExpectationException as ExpectationException, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; diff --git a/lib/tests/behat/behat_general.php b/lib/tests/behat/behat_general.php index 57c63553e090a..c301b0a0c1c7a 100644 --- a/lib/tests/behat/behat_general.php +++ b/lib/tests/behat/behat_general.php @@ -33,7 +33,7 @@ WebDriver\Exception\NoSuchElement as NoSuchElement, WebDriver\Exception\StaleElementReference as StaleElementReference, Behat\Gherkin\Node\TableNode as TableNode, - Behat\Behat\Context\Step\Given as Given; + Moodle\BehatExtension\Context\Step\Given as Given; /** * Cross component steps definitions. @@ -192,7 +192,7 @@ public function switch_to_window($windowname) { // unnamed window (presumably the main window) to some other named // window, then we first set the main window name to a conventional // value that we can later use this name to switch back. - $this->getSession()->evaluateScript( + $this->getSession()->executeScript( 'if (window.name == "") window.name = "' . self::MAIN_WINDOW_NAME . '"'); $this->getSession()->switchToWindow($windowname); @@ -1383,7 +1383,7 @@ public function i_start_watching_to_see_if_a_new_page_loads() { $this->pageloaddetectionrunning = true; - $session->evaluateScript( + $session->executeScript( 'var span = document.createElement("span"); span.setAttribute("data-rel", "' . self::PAGE_LOAD_DETECTION_STRING . '"); span.setAttribute("style", "display: none;"); diff --git a/lib/tests/behat/behat_hooks.php b/lib/tests/behat/behat_hooks.php index cddbe93c96fbd..f761429968e9f 100644 --- a/lib/tests/behat/behat_hooks.php +++ b/lib/tests/behat/behat_hooks.php @@ -29,11 +29,14 @@ require_once(__DIR__ . '/../../behat/behat_base.php'); -use Behat\Behat\Event\SuiteEvent as SuiteEvent, - Behat\Behat\Event\ScenarioEvent as ScenarioEvent, - Behat\Behat\Event\FeatureEvent as FeatureEvent, - Behat\Behat\Event\OutlineExampleEvent as OutlineExampleEvent, - Behat\Behat\Event\StepEvent as StepEvent, +use Behat\Testwork\Hook\Scope\BeforeSuiteScope, + Behat\Testwork\Hook\Scope\AfterSuiteScope, + Behat\Behat\Hook\Scope\BeforeFeatureScope, + Behat\Behat\Hook\Scope\AfterFeatureScope, + Behat\Behat\Hook\Scope\BeforeScenarioScope, + Behat\Behat\Hook\Scope\AfterScenarioScope, + Behat\Behat\Hook\Scope\BeforeStepScope, + Behat\Behat\Hook\Scope\AfterStepScope, Behat\Mink\Exception\DriverException as DriverException, WebDriver\Exception\NoSuchWindow as NoSuchWindow, WebDriver\Exception\UnexpectedAlertOpen as UnexpectedAlertOpen, @@ -104,7 +107,7 @@ class behat_hooks extends behat_base { * @throws Exception * @BeforeSuite */ - public static function before_suite(SuiteEvent $event) { + public static function before_suite(BeforeSuiteScope $scope) { global $CFG; // Defined only when the behat CLI command is running, the moodle init setup process will @@ -113,7 +116,6 @@ public static function before_suite(SuiteEvent $event) { define('BEHAT_TEST', 1); define('CLI_SCRIPT', 1); - // With BEHAT_TEST we will be using $CFG->behat_* instead of $CFG->dataroot, $CFG->prefix and $CFG->wwwroot. require_once(__DIR__ . '/../../../config.php'); @@ -169,7 +171,7 @@ public static function before_suite(SuiteEvent $event) { * @param FeatureEvent $event event fired before feature. * @BeforeFeature */ - public static function before_feature(FeatureEvent $event) { + public static function before_feature(BeforeFeatureScope $event) { if (!defined('BEHAT_FEATURE_TIMING_FILE')) { return; } @@ -183,7 +185,7 @@ public static function before_feature(FeatureEvent $event) { * @param FeatureEvent $event event fired after feature. * @AfterFeature */ - public static function after_feature(FeatureEvent $event) { + public static function after_feature(AfterFeatureScope $event) { if (!defined('BEHAT_FEATURE_TIMING_FILE')) { return; } @@ -201,7 +203,7 @@ public static function after_feature(FeatureEvent $event) { * @param SuiteEvent $event event fired after suite. * @AfterSuite */ - public static function after_suite(SuiteEvent $event) { + public static function after_suite(AfterSuiteScope $event) { if (!defined('BEHAT_FEATURE_TIMING_FILE')) { return; } @@ -225,7 +227,7 @@ public static function after_suite(SuiteEvent $event) { * @throws coding_exception If here we are not using the test database it should be because of a coding error * @BeforeScenario */ - public function before_scenario($event) { + public function before_scenario(BeforeScenarioScope $scope) { global $DB, $SESSION, $CFG; // As many checks as we can. @@ -310,16 +312,18 @@ public function before_scenario($event) { * default would be at framework level, which will stop the execution of * the run. * - * @param StepEvent $event event fired before step. - * @BeforeStep @javascript + * @BeforeStep */ - public function before_step_javascript(StepEvent $event) { + public function before_step_javascript(BeforeStepScope $scope) { + self::$currentstepexception = null; - try { - $this->wait_for_pending_js(); - self::$currentstepexception = null; - } catch (Exception $e) { - self::$currentstepexception = $e; + // Only run if JS. + if ($this->running_javascript()) { + try { + $this->wait_for_pending_js(); + } catch (Exception $e) { + self::$currentstepexception = $e; + } } } @@ -335,16 +339,36 @@ public function before_step_javascript(StepEvent $event) { * default would be at framework level, which will stop the execution of * the run. * - * @param StepEvent $event event fired after step. - * @AfterStep @javascript + * @AfterStep */ - public function after_step_javascript(StepEvent $event) { - global $CFG; + public function after_step_javascript(AfterStepScope $scope) { + global $CFG, $DB; + + // Save the page content if the step failed. + if (!empty($CFG->behat_faildump_path) && + $scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED) { + $this->take_contentdump($scope); + } + + // Abort any open transactions to prevent subsequent tests hanging. + // This does the same as abort_all_db_transactions(), but doesn't call error_log() as we don't + // want to see a message in the behat output. + if (($scope->getTestResult() instanceof \Behat\Behat\Tester\Result\ExecutedStepResult) && + $scope->getTestResult()->hasException()) { + if ($DB && $DB->is_transaction_started()) { + $DB->force_transaction_rollback(); + } + } + + // Only run if JS. + if (!$this->running_javascript()) { + return; + } // Save a screenshot if the step failed. if (!empty($CFG->behat_faildump_path) && - $event->getResult() === StepEvent::FAILED) { - $this->take_screenshot($event); + $scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED) { + $this->take_screenshot($scope); } try { @@ -366,42 +390,15 @@ public function after_step_javascript(StepEvent $event) { } } - /** - * Execute any steps required after the step has finished. - * - * This includes creating an HTML dump of the content if there was a failure. - * - * @param StepEvent $event event fired after step. - * @AfterStep - */ - public function after_step(StepEvent $event) { - global $CFG, $DB; - - // Save the page content if the step failed. - if (!empty($CFG->behat_faildump_path) && - $event->getResult() === StepEvent::FAILED) { - $this->take_contentdump($event); - } - - // Abort any open transactions to prevent subsequent tests hanging. - // This does the same as abort_all_db_transactions(), but doesn't call error_log() as we don't - // want to see a message in the behat output. - if ($event->hasException()) { - if ($DB && $DB->is_transaction_started()) { - $DB->force_transaction_rollback(); - } - } - } - /** * Executed after scenario having switch window to restart session. * This is needed to close all extra browser windows and starting * one browser window. * - * @param ScenarioEvent $event event fired after scenario. + * @param AfterScenarioScope $event event fired after scenario. * @AfterScenario @_switch_window */ - public function after_scenario_switchwindow(ScenarioEvent $event) { + public function after_scenario_switchwindow(AfterScenarioScope $event) { for ($count = 0; $count < self::EXTENDED_TIMEOUT; $count) { try { $this->getSession()->restart(); @@ -428,15 +425,15 @@ protected function get_run_faildump_dir() { * Take screenshot when a step fails. * * @throws Exception - * @param StepEvent $event + * @param AfterStepScope $scope */ - protected function take_screenshot(StepEvent $event) { + protected function take_screenshot(AfterStepScope $scope) { // Goutte can't save screenshots. if (!$this->running_javascript()) { return false; } - list ($dir, $filename) = $this->get_faildump_filename($event, 'png'); + list ($dir, $filename) = $this->get_faildump_filename($scope, 'png'); $this->saveScreenshot($filename, $dir); } @@ -444,10 +441,10 @@ protected function take_screenshot(StepEvent $event) { * Take a dump of the page content when a step fails. * * @throws Exception - * @param StepEvent $event + * @param AfterStepScope $scope */ - protected function take_contentdump(StepEvent $event) { - list ($dir, $filename) = $this->get_faildump_filename($event, 'html'); + protected function take_contentdump(AfterStepScope $scope) { + list ($dir, $filename) = $this->get_faildump_filename($scope, 'html'); $fh = fopen($dir . DIRECTORY_SEPARATOR . $filename, 'w'); fwrite($fh, $this->getSession()->getPage()->getContent()); @@ -459,10 +456,10 @@ protected function take_contentdump(StepEvent $event) { * * This is used for content such as the DOM, and screenshots. * - * @param StepEvent $event + * @param AfterStepScope $scope * @param String $filetype The file suffix to use. Limited to 4 chars. */ - protected function get_faildump_filename(StepEvent $event, $filetype) { + protected function get_faildump_filename(AfterStepScope $scope, $filetype) { global $CFG; // All the contentdumps should be in the same parent dir. @@ -482,12 +479,12 @@ protected function get_faildump_filename(StepEvent $event, $filetype) { // The scenario title + the failed step text. // We want a i-am-the-scenario-title_i-am-the-failed-step.$filetype format. - $filename = $event->getStep()->getParent()->getTitle() . '_' . $event->getStep()->getText(); + $filename = $scope->getFeature()->getTitle() . '_' . $scope->getStep()->getText(); $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename); - // File name limited to 255 characters. Leaving 4 chars for the file + // File name limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file. // extension as we allow .png for images and .html for DOM contents. - $filename = substr($filename, 0, 250) . '.' . $filetype; + $filename = substr($filename, 0, 245) . '_' . $scope->getStep()->getLine() . '.' . $filetype; return array($dir, $filename); } @@ -508,17 +505,19 @@ protected function wait_for_pending_js() { $pending = ''; try { $jscode = - 'if (typeof M === "undefined") { - if (document.readyState === "complete") { + 'return function() { + if (typeof M === "undefined") { + if (document.readyState === "complete") { + return ""; + } else { + return "incomplete"; + } + } else if (' . self::PAGE_READY_JS . ') { return ""; } else { - return "incomplete"; + return M.util.pending_js.join(":"); } - } else if (' . self::PAGE_READY_JS . ') { - return ""; - } else { - return M.util.pending_js.join(":"); - }'; + }();'; $pending = $this->getSession()->evaluateScript($jscode); } catch (NoSuchWindow $nsw) { // We catch an exception here, in case we just closed the window we were interacting with. diff --git a/lib/tests/behat/behat_navigation.php b/lib/tests/behat/behat_navigation.php index 81392ea9be577..2fc25937e29ab 100644 --- a/lib/tests/behat/behat_navigation.php +++ b/lib/tests/behat/behat_navigation.php @@ -27,10 +27,10 @@ require_once(__DIR__ . '/../../behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; +use Moodle\BehatExtension\Context\Step\Given; +use Moodle\BehatExtension\Context\Step\When; use Behat\Mink\Exception\ExpectationException as ExpectationException; use Behat\Mink\Exception\DriverException as DriverException; -use Behat\Behat\Context\Step\When as When; /** * Steps definitions to navigate through the navigation tree nodes. @@ -245,7 +245,8 @@ public function i_navigate_to_node_in($nodetext, $parentnodes) { if ($parentnodes[0] === $siteadminstr) { // We don't know if there if Site admin is already expanded so // don't wait, it is non-JS and we already waited for the DOM. - if ($siteadminlink = $this->getSession()->getPage()->find('named', array('link', "'" . $siteadminstr . "'"))) { + $siteadminlink = $this->getSession()->getPage()->find('named_exact', array('link', "'" . $siteadminstr . "'")); + if ($siteadminlink) { $siteadminlink->click(); } } diff --git a/lib/tests/behat/behat_permissions.php b/lib/tests/behat/behat_permissions.php index 4b932b6cd7db0..a9f05e44b76e4 100644 --- a/lib/tests/behat/behat_permissions.php +++ b/lib/tests/behat/behat_permissions.php @@ -28,7 +28,7 @@ require_once(__DIR__ . '/../../behat/behat_base.php'); use Behat\Mink\Exception\ExpectationException as ExpectationException, - Behat\Behat\Context\Step\Given as Given, + Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode; /** diff --git a/lib/tests/behat/behat_transformations.php b/lib/tests/behat/behat_transformations.php index 738b8298d8126..a8f745411cb7f 100644 --- a/lib/tests/behat/behat_transformations.php +++ b/lib/tests/behat/behat_transformations.php @@ -82,12 +82,25 @@ public function arg_replace_nasty_strings($argument) { * Transformations applicable to TableNode arguments should also * be applied, adding them in a different method for Behat API restrictions. * - * @Transform /^table:(.*)/ + * @Transform table:Surname,My Surname $NASTYSTRING2 * @param TableNode $tablenode * @return TableNode The transformed table */ - public function tablenode_transformations(TableNode $tablenode) { + public function prefixed_tablenode_transformations(TableNode $tablenode) { + return $this->tablenode_transformations($tablenode); + } + /** + * Transformations for TableNode arguments. + * + * Transformations applicable to TableNode arguments should also + * be applied, adding them in a different method for Behat API restrictions. + * + * @Transform table:Surname,$NASTYSTRING1 + * @param TableNode $tablenode + * @return TableNode The transformed table + */ + public function tablenode_transformations(TableNode $tablenode) { // Walk through all values including the optional headers. $rows = $tablenode->getRows(); foreach ($rows as $rowkey => $row) { @@ -101,7 +114,9 @@ public function tablenode_transformations(TableNode $tablenode) { } // Return the transformed TableNode. - $tablenode->setRows($rows); + unset($tablenode); + $tablenode = new TableNode($rows); + return $tablenode; } diff --git a/message/tests/behat/behat_message.php b/message/tests/behat/behat_message.php index 144983ad049a8..56c2573520832 100644 --- a/message/tests/behat/behat_message.php +++ b/message/tests/behat/behat_message.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; /** diff --git a/mod/assign/feedback/editpdf/tests/behat/behat_assignfeedback_editpdf.php b/mod/assign/feedback/editpdf/tests/behat/behat_assignfeedback_editpdf.php index 41fab07cb300d..a35c867e3fa28 100644 --- a/mod/assign/feedback/editpdf/tests/behat/behat_assignfeedback_editpdf.php +++ b/mod/assign/feedback/editpdf/tests/behat/behat_assignfeedback_editpdf.php @@ -27,8 +27,6 @@ require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; - /** * Steps definitions related with the editpdf. * diff --git a/mod/choice/tests/behat/behat_mod_choice.php b/mod/choice/tests/behat/behat_mod_choice.php index ba012aaae68c1..6af5c5e9551cf 100644 --- a/mod/choice/tests/behat/behat_mod_choice.php +++ b/mod/choice/tests/behat/behat_mod_choice.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given; +use Moodle\BehatExtension\Context\Step\Given as Given; /** * Choice activity definitions. diff --git a/mod/data/tests/behat/behat_mod_data.php b/mod/data/tests/behat/behat_mod_data.php index 3dc04c2803f68..3fcc8d09e8d37 100644 --- a/mod/data/tests/behat/behat_mod_data.php +++ b/mod/data/tests/behat/behat_mod_data.php @@ -27,8 +27,8 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, - Behat\Behat\Context\Step\When as When, +use Moodle\BehatExtension\Context\Step\Given as Given, + Moodle\BehatExtension\Context\Step\When as When, Behat\Gherkin\Node\TableNode as TableNode; /** * Database-related steps definitions. diff --git a/mod/feedback/tests/behat/behat_mod_feedback.php b/mod/feedback/tests/behat/behat_mod_feedback.php index d6c4b528cbbcc..abf47affbd79d 100644 --- a/mod/feedback/tests/behat/behat_mod_feedback.php +++ b/mod/feedback/tests/behat/behat_mod_feedback.php @@ -54,14 +54,16 @@ public function i_add_question_to_the_feedback_with($questiontype, TableNode $qu $additem = $this->escape(get_string('add_item', 'feedback')); $rv[] = new Given("I select \"{$questiontype}\" from the \"{$additem}\" singleselect"); - $newdata = new TableNode(); $rows = $questiondata->getRows(); + $modifiedrows = array(); foreach ($rows as $row) { foreach ($row as $key => $value) { $row[$key] = preg_replace('|\\\\n|', "\n", $value); } - $newdata->addRow($row); + $modifiedrows[] = $row; } + $newdata = new TableNode($modifiedrows); + $rv[] = new Given('I set the following fields to these values:', $newdata); $saveitem = $this->escape(get_string('save_item', 'feedback')); diff --git a/mod/forum/tests/behat/behat_mod_forum.php b/mod/forum/tests/behat/behat_mod_forum.php index bb56542c9ca3d..f132e1f48a408 100644 --- a/mod/forum/tests/behat/behat_mod_forum.php +++ b/mod/forum/tests/behat/behat_mod_forum.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode; /** * Forum-related steps definitions. diff --git a/mod/glossary/tests/behat/behat_mod_glossary.php b/mod/glossary/tests/behat/behat_mod_glossary.php index a4b904c09f5a9..51c8eae0d0264 100644 --- a/mod/glossary/tests/behat/behat_mod_glossary.php +++ b/mod/glossary/tests/behat/behat_mod_glossary.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode; /** diff --git a/mod/quiz/tests/behat/behat_mod_quiz.php b/mod/quiz/tests/behat/behat_mod_quiz.php index ac23865daca55..4f4e7f80895d6 100644 --- a/mod/quiz/tests/behat/behat_mod_quiz.php +++ b/mod/quiz/tests/behat/behat_mod_quiz.php @@ -28,9 +28,10 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); require_once(__DIR__ . '/../../../../question/tests/behat/behat_question_base.php'); -use Behat\Behat\Context\Step\Given as Given, - Behat\Gherkin\Node\TableNode as TableNode, - Behat\Mink\Exception\ExpectationException as ExpectationException; +use Moodle\BehatExtension\Context\Step\Given as Given, + Behat\Gherkin\Node\TableNode as TableNode; + +use Behat\Mink\Exception\ExpectationException as ExpectationException; /** * Steps definitions related to mod_quiz. @@ -83,7 +84,7 @@ public function quiz_contains_the_following_questions($quizname, TableNode $data } $rows = $data->getRows(); array_unshift($rows, $headings); - $data->setRows($rows); + $data = new TableNode($rows); } // Add the questions. diff --git a/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php b/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php index 9d86bd4b7a00c..bc40ab8de108d 100644 --- a/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php +++ b/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php @@ -28,8 +28,7 @@ require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php'); require_once(__DIR__ . '/../../../../../../lib/behat/behat_field_manager.php'); -use Behat\Behat\Context\Step\Given as Given, - Behat\Gherkin\Node\TableNode as TableNode, +use Behat\Gherkin\Node\TableNode as TableNode, Behat\Mink\Exception\ElementTextException as ElementTextException; /** diff --git a/mod/workshop/tests/behat/behat_mod_workshop.php b/mod/workshop/tests/behat/behat_mod_workshop.php index 4ff5d28b4cfe1..3c1c7b4bae5c5 100644 --- a/mod/workshop/tests/behat/behat_mod_workshop.php +++ b/mod/workshop/tests/behat/behat_mod_workshop.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode; /** diff --git a/question/tests/behat/behat_question.php b/question/tests/behat/behat_question.php index 069d98256fc46..2c5e60c325004 100644 --- a/question/tests/behat/behat_question.php +++ b/question/tests/behat/behat_question.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/behat_question_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode, Behat\Mink\Exception\ExpectationException as ExpectationException, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; diff --git a/question/tests/behat/behat_question_base.php b/question/tests/behat/behat_question_base.php index 9c7fdb429a8be..b45b6aeb4b7a1 100644 --- a/question/tests/behat/behat_question_base.php +++ b/question/tests/behat/behat_question_base.php @@ -27,7 +27,7 @@ require_once(__DIR__ . '/../../../lib/behat/behat_base.php'); -use Behat\Behat\Context\Step\Given as Given, +use Moodle\BehatExtension\Context\Step\Given as Given, Behat\Gherkin\Node\TableNode as TableNode, Behat\Mink\Exception\ExpectationException as ExpectationException, Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException; diff --git a/repository/tests/behat/behat_filepicker.php b/repository/tests/behat/behat_filepicker.php index 2e763b9f5b721..34758fbc1cdd2 100644 --- a/repository/tests/behat/behat_filepicker.php +++ b/repository/tests/behat/behat_filepicker.php @@ -210,7 +210,7 @@ public function i_should_see_elements_in_filemanager($elementscount, $filemanage * @param string $filemanagerelement */ public function i_add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement) { - $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, new TableNode(), false); + $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, new TableNode(array()), false); } /** @@ -223,7 +223,7 @@ public function i_add_file_from_repository_to_filemanager($filepath, $repository * @param string $filemanagerelement */ public function i_add_and_overwrite_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement) { - $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, new TableNode(), + $this->add_file_from_repository_to_filemanager($filepath, $repository, $filemanagerelement, new TableNode(array()), get_string('overwrite', 'repository')); } diff --git a/repository/upload/tests/behat/behat_repository_upload.php b/repository/upload/tests/behat/behat_repository_upload.php index 366e5290fd363..693814dfc8019 100644 --- a/repository/upload/tests/behat/behat_repository_upload.php +++ b/repository/upload/tests/behat/behat_repository_upload.php @@ -51,7 +51,7 @@ class behat_repository_upload extends behat_files { * @param string $filemanagerelement */ public function i_upload_file_to_filemanager($filepath, $filemanagerelement) { - $this->upload_file_to_filemanager($filepath, $filemanagerelement, new TableNode(), false); + $this->upload_file_to_filemanager($filepath, $filemanagerelement, new TableNode(array()), false); } /** @@ -63,7 +63,7 @@ public function i_upload_file_to_filemanager($filepath, $filemanagerelement) { * @param string $filemanagerelement */ public function i_upload_and_overwrite_file_to_filemanager($filepath, $filemanagerelement) { - $this->upload_file_to_filemanager($filepath, $filemanagerelement, new TableNode(), + $this->upload_file_to_filemanager($filepath, $filemanagerelement, new TableNode(array()), get_string('overwrite', 'repository')); }