Merge branch 'MDL-39635_master' of git://github.com/dmonllao/moodle

This commit is contained in:
Eloy Lafuente (stronk7)
2013-07-23 00:45:13 +02:00
37 changed files with 295 additions and 237 deletions
+7 -3
View File
@@ -62,7 +62,7 @@ class behat_admin extends behat_base {
}
// Search by label.
$searchbox = $this->find_field('Search in settings');
$searchbox = $this->find_field(get_string('searchinsettings', 'admin'));
$searchbox->setValue($label);
$submitsearch = $this->find('css', 'form.adminsearchform input[type=submit]');
$submitsearch->press();
@@ -72,8 +72,12 @@ class behat_admin extends behat_base {
// Admin settings does not use the same DOM structure than other moodle forms
// but we also need to use lib/behat/form_field/* to deal with the different moodle form elements.
$exception = new ElementNotFoundException($this->getSession(), '"' . $label . '" administration setting ');
// The argument should be converted to an xpath literal.
$label = $this->getSession()->getSelectorsHandler()->xpathLiteral($label);
$fieldxpath = "//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]" .
"[@id=//label[contains(normalize-space(string(.)), '" . $label . "')]/@for]";
"[@id=//label[contains(normalize-space(.), $label)]/@for]";
$fieldnode = $this->find('xpath', $fieldxpath, $exception);
$formfieldtypenode = $this->find('xpath', $fieldxpath . "/ancestor::div[@class='form-setting']" .
"/child::div[contains(concat(' ', @class, ' '), ' form-')]/child::*/parent::div");
@@ -90,7 +94,7 @@ class behat_admin extends behat_base {
$field = behat_field_manager::get_field_instance($type, $fieldnode, $this->getSession());
$field->set_value($value);
$this->find_button('Save changes')->press();
$this->find_button(get_string('savechanges'))->press();
}
}
@@ -15,7 +15,7 @@ Feature: Display extended course names
And I should not see "C_shortname Course fullname"
Scenario: Courses list with extended course names
Given I click on "Courses" "link" in the "//div[@id='settingsnav']//descendant::li[contains(concat(' ', @class, ' '), ' type_setting ')][not(contains(., 'Site administration'))][contains(., 'Appearance')]" "xpath_element"
Given I click on "Courses" "link" in the "//div[@id='settingsnav']/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' type_setting ')][not(contains(., 'Site administration'))][contains(., 'Appearance')]" "xpath_element"
And I check "Display extended course names"
When I press "Save changes"
And I am on homepage
@@ -37,7 +37,7 @@ Feature: Page contents assertions
And I follow "Course 1"
When I click on "Move this to the dock" "button" in the ".block_settings" "css_element"
Then I should not see "Question bank"
And I click on "//div[@id='dock']/descendant::*[contains(., 'Administration')]/h2" "xpath_element"
And I click on "//div[@id='dock']/descendant::h2[normalize-space(.)='Administration']" "xpath_element"
@javascript
Scenario: Locators inside specific DOM nodes using XPath
@@ -45,5 +45,5 @@ Feature: Page contents assertions
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And I log in as "admin"
When I click on "Move this to the dock" "button" in the "//*[contains(concat(' ', normalize-space(@class), ' '), ' block_settings ')]" "xpath_element"
When I click on "Move this to the dock" "button" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' block_settings ')]" "xpath_element"
Then I should not see "Turn editing on"
@@ -30,17 +30,17 @@ Feature: Set up contextual data for tests
Then I should see "Course 1"
And I should see "Course 2"
And I should see "Course 3"
When I go to the courses management page
And I go to the courses management page
And I follow "Cat 1"
Then I should see "Cat 2"
And I should see "Cat 2"
And I should see "Cat 3"
When I follow "Cat 3"
Then I should see "Course 1"
And I follow "Cat 3"
And I should see "Course 1"
And I should see "Course 2"
When I select "Cat 2" from "Course categories:"
Then I should see "No courses in this category"
When I select "Miscellaneous" from "Course categories:"
Then I should see "Course 3"
And I select "Cat 1 / Cat 2" from "Course categories:"
And I should see "No courses in this category"
And I select "Miscellaneous" from "Course categories:"
And I should see "Course 3"
@javascript
Scenario: Add a bunch of groups and groupings
+5 -5
View File
@@ -49,10 +49,10 @@ class behat_auth extends behat_base {
public function i_log_in_as($username) {
return array(new Given('I am on homepage'),
new Given('I follow "Log in"'),
new Given('I fill in "Username" with "'.$username.'"'),
new Given('I fill in "Password" with "'.$username.'"'),
new Given('I press "Log in"')
new Given('I follow "' . get_string('login') . '"'),
new Given('I fill in "' . get_string('username') . '" with "' . $this->escape($username) . '"'),
new Given('I fill in "' . get_string('password') . '" with "'. $this->escape($username) . '"'),
new Given('I press "' . get_string('login') . '"')
);
}
@@ -62,7 +62,7 @@ class behat_auth extends behat_base {
* @Given /^I log out$/
*/
public function i_log_out() {
return new When('I follow "Log out"');
return new When('I follow "' . get_string('logout') . '"');
}
}
@@ -31,7 +31,7 @@ Feature: Backup Moodle courses
And I should not see "Section 3"
And I press "Continue"
And I click on "Continue" "button" in the ".bcs-current-course" "css_element"
And I click on "//div[contains(concat(' ', @class, ' '), ' fitem ')][contains(., 'Include calendar events')]/descendant::img" "xpath_element"
And I click on "setting_root_logs" "checkbox" in the "//div[contains(@class, 'fitem')][contains(., 'Include course logs')]" "xpath_element"
And "//div[contains(concat(' ', normalize-space(@class), ' '), ' fitem ')][contains(., 'Include calendar events')]/descendant::img" "xpath_element" should exists
And I check "Include course logs"
And I press "Cancel"
And I click on "Cancel" "button" in the ".confirmation-dialogue" "css_element"
+46 -33
View File
@@ -61,25 +61,25 @@ class behat_backup extends behat_base {
$this->find_link($backupcourse)->click();
// Click the backup link.
$this->find_link('Backup')->click();
$this->find_link(get_string('backup'))->click();
// Initial settings.
$this->fill_backup_restore_form($options);
$this->find_button('Next')->press();
$this->find_button(get_string('backupstage1action', 'backup'))->press();
// Schema settings.
$this->fill_backup_restore_form($options);
$this->find_button('Next')->press();
$this->find_button(get_string('backupstage2action', 'backup'))->press();
// Confirmation and review, backup filename can also be specified.
$this->fill_backup_restore_form($options);
$this->find_button('Perform backup')->press();
$this->find_button(get_string('backupstage4action', 'backup'))->press();
// Waiting for it to finish.
$this->wait(10);
// Last backup continue button.
$this->find_button('Continue')->press();
$this->find_button(get_string('backupstage16action', 'backup'))->press();
}
/**
@@ -105,36 +105,37 @@ class behat_backup extends behat_base {
// Click the course link.
$this->find_link($tocourse)->click();
// Click the backup link.
$this->find_link('Import')->click();
// Click the import link.
$this->find_link(get_string('import'))->click();
// Select the course.
$exception = new ExpectationException('"' . $fromcourse . '" course not found in the list of courses to import from', $this->getSession());
$fromcourse = str_replace("'", "\'", $fromcourse);
$xpath = "//div[contains(concat(' ', @class, ' '), ' ics-results ')]" .
"/descendant::tr[contains(., '" . $fromcourse . "')]" .
// The argument should be converted to an xpath literal.
$fromcourse = $this->getSession()->getSelectorsHandler()->xpathLiteral($fromcourse);
$xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' ics-results ')]" .
"/descendant::tr[contains(., $fromcourse)]" .
"/descendant::input[@type='radio']";
$radionode = $this->find('xpath', $xpath, $exception);
$radionode->check();
$radionode->click();
$this->find_button('Continue')->press();
$this->find_button(get_string('continue'))->press();
// Initial settings.
$this->fill_backup_restore_form($options);
$this->find_button('Next')->press();
$this->find_button(get_string('importbackupstage1action', 'backup'))->press();
// Schema settings.
$this->fill_backup_restore_form($options);
$this->find_button('Next')->press();
$this->find_button(get_string('importbackupstage2action', 'backup'))->press();
// Run it.
$this->find_button('Perform import')->press();
$this->find_button(get_string('importbackupstage4action', 'backup'))->press();
$this->wait();
// Continue and redirect to 'to' course.
$this->find_button('Continue')->press();
$this->find_button(get_string('continue'))->press();
}
/**
@@ -150,17 +151,20 @@ class behat_backup extends behat_base {
// Confirm restore.
$this->select_backup($backupfilename);
// The argument should be converted to an xpath literal.
$existingcourse = $this->getSession()->getSelectorsHandler()->xpathLiteral($existingcourse);
// Selecting the specified course (we can not call behat_forms::select_radio here as is in another behat subcontext).
$existingcourse = str_replace("'", "\'", $existingcourse);
$radionode = $this->find('xpath', "//div[contains(@class, 'bcs-existing-course')]" .
$radionode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-existing-course ')]" .
"/descendant::div[@class='restore-course-search']" .
"/descendant::tr[contains(., '" . $existingcourse . "')]" .
"/descendant::tr[contains(., $existingcourse)]" .
"/descendant::input[@type='radio']");
$radionode->check();
$radionode->click();
// Pressing the continue button of the restore into an existing course section.
$continuenode = $this->find('xpath', "//div[contains(@class, 'bcs-existing-course')]/descendant::input[@type='submit'][@value='Continue']");
$continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-existing-course ')]" .
"/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
$continuenode->click();
$this->wait();
@@ -181,14 +185,15 @@ class behat_backup extends behat_base {
$this->select_backup($backupfilename);
// The first category in the list.
$radionode = $this->find('xpath', "//div[contains(@class, 'bcs-new-course')]" .
$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.
$continuenode = $this->find('xpath', "//div[contains(@class, 'bcs-new-course')]/descendant::input[@type='submit'][@value='Continue']");
$continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' bcs-new-course ')]" .
"/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
$continuenode->click();
$this->wait();
@@ -209,14 +214,14 @@ class behat_backup extends behat_base {
$this->select_backup($backupfilename);
// Merge without deleting radio option.
$radionode = $this->find('xpath', "//div[contains(@class, 'bcs-current-course')]" .
$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.
$continuenode = $this->find('xpath', "//div[contains(@class, 'bcs-current-course')]" .
"/descendant::input[@type='submit'][@value='Continue']");
$continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" .
"/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
$continuenode->click();
$this->wait();
@@ -237,14 +242,14 @@ class behat_backup extends behat_base {
$this->select_backup($backupfilename);
// Delete contents radio option.
$radionode = $this->find('xpath', "//div[contains(@class, 'bcs-current-course')]" .
$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.
$continuenode = $this->find('xpath', "//div[contains(@class, 'bcs-current-course')]" .
"/descendant::input[@type='submit'][@value='Continue']");
$continuenode = $this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), 'bcs-current-course')]" .
"/descendant::input[@type='submit'][@value='" . get_string('continue') . "']");
$continuenode->click();
$this->wait();
@@ -263,12 +268,16 @@ class behat_backup extends behat_base {
// Using xpath as there are other restore links before this one.
$exception = new ExpectationException('The "' . $backupfilename . '" backup file can not be found in this page', $this->getSession());
$xpath = "//tr[contains(., '" . $backupfilename . "')]/descendant::a[contains(., 'Restore')]";
// The argument should be converted to an xpath literal.
$backupfilename = $this->getSession()->getSelectorsHandler()->xpathLiteral($backupfilename);
$xpath = "//tr[contains(., $backupfilename)]/descendant::a[contains(., '" . get_string('restore') . "')]";
$restorelink = $this->find('xpath', $xpath, $exception);
$restorelink->click();
// Confirm the backup contents.
$restore = $this->find_button('Continue')->press();
$restore = $this->find_button(get_string('continue'))->press();
}
/**
@@ -284,18 +293,18 @@ class behat_backup extends behat_base {
// Settings.
$this->fill_backup_restore_form($options);
$this->find_button('Next')->press();
$this->find_button(get_string('restorestage4action', 'backup'))->press();
// Schema.
$this->fill_backup_restore_form($options);
$this->find_button('Next')->press();
$this->find_button(get_string('restorestage8action', 'backup'))->press();
// Review, no options here.
$this->find_button('Perform restore')->press();
$this->find_button(get_string('restorestage16action', 'backup'))->press();
$this->wait(10);
// Last restore continue button, redirected to restore course after this.
$this->find_button('Continue')->press();
$this->find_button(get_string('restorestage32action', 'backup'))->press();
}
/**
@@ -339,6 +348,10 @@ class behat_backup extends behat_base {
*/
protected function wait($timeout = false) {
if (!$this->running_javascript()) {
return;
}
if (!$timeout) {
$timeout = self::TIMEOUT;
}
@@ -63,7 +63,7 @@ class behat_block_comments extends behat_base {
$commentstextarea = $this->find('css', '.comment-area textarea', $exception);
$commentstextarea->setValue($comment);
$this->find_link('Save comment')->click();
$this->find_link(get_string('savecomment'))->click();
// Wait for the AJAX request.
$this->getSession()->wait(4 * 1000, false);
@@ -91,8 +91,11 @@ class behat_block_comments extends behat_base {
$exception = new ElementNotFoundException($this->getSession(), '"' . $comment . '" comment ');
$commentxpath = "//div[contains(concat(' ', @class, ' '), ' block_comments ')]" .
"/descendant::div[@class='comment-message'][contains(., '" . $comment . "')]";
// Using xpath liternal to avoid possible problems with comments containing quotes.
$commentliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($comment);
$commentxpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' block_comments ')]" .
"/descendant::div[@class='comment-message'][contains(., $commentliteral)]";
$commentnode = $this->find('xpath', $commentxpath, $exception);
// Click on delete icon.
@@ -101,7 +104,7 @@ class behat_block_comments extends behat_base {
$deleteicon->click();
// Yes confirm.
$confirmnode = $this->find('xpath', "//div[@class='comment-delete-confirm']/descendant::a[contains(., 'Yes')]");
$confirmnode = $this->find('xpath', "//div[@class='comment-delete-confirm']/descendant::a[contains(., '" . get_string('yes') . "')]");
$confirmnode->click();
// Wait for the AJAX request.
+2 -2
View File
@@ -46,13 +46,13 @@ class behat_blocks extends behat_base {
* @param string $blockname
*/
public function i_add_the_block($blockname) {
$steps = new Given('I select "' . $blockname . '" from "bui_addblock"');
$steps = new Given('I select "' . $this->escape($blockname) . '" from "bui_addblock"');
// If we are running without javascript we need to submit the form.
if (!$this->running_javascript()) {
$steps = array(
$steps,
new Given('I click on "Go" "button" in the "#add_block" "css_element"')
new Given('I click on "' . get_string('go') . '" "button" in the "#add_block" "css_element"')
);
}
return $steps;
@@ -32,4 +32,4 @@ Feature: Add and configure blocks throughout the site
And I press "Save changes"
And I follow "Course 1"
# The first block matching the pattern should be top-left block
And I should see "Comments" in the "//*[@id='region-pre']/descendant::div[contains(concat(' ', @class, ' '), ' block ')]" "xpath_element"
And I should see "Comments" in the "//*[@id='region-pre']/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' block ')]" "xpath_element"
+9 -9
View File
@@ -54,10 +54,10 @@ class behat_cohort extends behat_base {
$userid = $DB->get_field('user', 'id', array('username' => $username));
$steps = array(
new Given('I click on "Assign" "link" in the "//table[@id=\'cohorts\']//tr[contains(., \'' . $cohortidnumber . '\')]" "xpath_element"'),
new Given('I select "' . $userid . '" from "Potential users"'),
new Given('I press "Add"'),
new Given('I press "Back to cohorts"')
new Given('I click on "' . get_string('assign', 'cohort') . '" "link" in the "' . $this->escape($cohortidnumber) . '" table row'),
new Given('I select "' . $userid . '" from "' . get_string('potusers', 'cohort') . '"'),
new Given('I press "' . get_string('add') . '"'),
new Given('I press "' . get_string('backtocohorts', 'cohort') . '"')
);
// If we are not in the cohorts management we should move there before anything else.
@@ -65,11 +65,11 @@ class behat_cohort extends behat_base {
$steps = array_merge(
array(
new Given('I am on homepage'),
new Given('I collapse "Front page settings" node'),
new Given('I expand "Site administration" node'),
new Given('I expand "Users" node'),
new Given('I expand "Accounts" node'),
new Given('I follow "Cohorts"')
new Given('I collapse "' . get_string('frontpagesettings', 'admin') . '" node'),
new Given('I expand "' . get_string('administrationsite') . '" node'),
new Given('I expand "' . get_string('users', 'admin') . '" node'),
new Given('I expand "' . get_string('accounts', 'admin') . '" node'),
new Given('I follow "' . get_string('cohorts', 'cohort') . '"')
),
$steps
);
@@ -32,11 +32,11 @@ Feature: Upload users to a cohort
And I press "Upload users"
And I press "Continue"
And I follow "Cohorts"
And I click on "Assign" "link" in the "//table[@id='cohorts']//tr[contains(., 'Cohort 1')]" "xpath_element"
And I click on "Assign" "link" in the "Cohort 1" table row
Then the "Current users" select box should contain "Tom Jones (tomjones@example.com)"
And the "Current users" select box should contain "Bob Jones (bobjones@example.com)"
And I press "Back to cohorts"
And I click on "Assign" "link" in the "//table[@id='cohorts']//tr[contains(., 'Cohort 2')]" "xpath_element"
And I click on "Assign" "link" in the "Cohort 2" table row
And the "Current users" select box should contain "Mary Smith (marysmith@example.com)"
And the "Current users" select box should contain "Alice Smith (alicesmith@example.com)"
And I am on homepage
+12 -9
View File
@@ -50,12 +50,13 @@ class behat_completion extends behat_base {
public function user_has_completed_activity($userfullname, $activityname) {
// Will throw an exception if the element can not be hovered.
$titleliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($userfullname . ", " . $activityname . ": Completed");
$xpath = "//table[@id='completion-progress']" .
"/descendant::img[contains(@title, '" . $userfullname . ", " . $activityname . ": Completed')]";
"/descendant::img[contains(@title, $titleliteral)]";
return array(
new Given('I go to the current course activity completion report'),
new Given('I hover "' . $xpath . '" "xpath_element"')
new Given('I hover "' . $this->escape($xpath) . '" "xpath_element"')
);
}
@@ -68,11 +69,13 @@ class behat_completion extends behat_base {
*/
public function user_has_not_completed_activity($userfullname, $activityname) {
// Will throw an exception if the element can not be hovered.
$titleliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($userfullname . ", " . $activityname . ": Not completed");
$xpath = "//table[@id='completion-progress']" .
"/descendant::img[contains(@title, '" . $userfullname . ", " . $activityname . ": Not completed')]";
"/descendant::img[contains(@title, $titleliteral)]";
return array(
new Given('I go to the current course activity completion report'),
new Given('I hover "' . $xpath . '" "xpath_element"')
new Given('I hover "' . $this->escape($xpath) . '" "xpath_element"')
);
return $steps;
@@ -89,15 +92,15 @@ class behat_completion extends behat_base {
// Expand reports node if we can't see the link.
try {
$this->find('xpath', "//*[@id='settingsnav']" .
$this->find('xpath', "//div[@id='settingsnav']" .
"/descendant::li" .
"/descendant::li[not(contains(@class,'collapsed'))]" .
"/descendant::p[contains(., 'Activity completion')]");
"/descendant::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed '))]" .
"/descendant::p[contains(., '" . get_string('pluginname', 'report_progress') . "')]");
} catch (ElementNotFoundException $e) {
$steps[] = new Given('I expand "Reports" node');
$steps[] = new Given('I expand "' . get_string('reports') . '" node');
}
$steps[] = new Given('I follow "Activity completion"');
$steps[] = new Given('I follow "' . get_string('pluginname', 'report_progress') . '"');
return $steps;
}
@@ -27,21 +27,21 @@ Feature: Toggle activities groups mode from the course page
| Force group mode | No |
When I press "Save changes"
Then "No groups (Click to change)" "link" should exists
And ".//a//img[contains(@src, 'groupn')]" "xpath_element" should exists
And "//a/child::img[contains(@src, 'groupn')]" "xpath_element" should exists
And I click on "No groups (Click to change)" "link" in the "Test forum name" activity
And I wait "3" seconds
And "Separate groups (Click to change)" "link" should exists
And ".//a//img[contains(@src, 'groups')]" "xpath_element" should exists
And "//a/child::img[contains(@src, 'groups')]" "xpath_element" should exists
And I reload the page
And "Separate groups (Click to change)" "link" should exists
And ".//a//img[contains(@src, 'groups')]" "xpath_element" should exists
And "//a/child::img[contains(@src, 'groups')]" "xpath_element" should exists
And I click on "Separate groups (Click to change)" "link" in the "Test forum name" activity
And I wait "3" seconds
And "Visible groups (Click to change)" "link" should exists
And ".//a//img[contains(@src, 'groupv')]" "xpath_element" should exists
And "//a/child::img[contains(@src, 'groupv')]" "xpath_element" should exists
And I reload the page
And "Visible groups (Click to change)" "link" should exists
And ".//a//img[contains(@src, 'groupv')]" "xpath_element" should exists
And "//a/child::img[contains(@src, 'groupv')]" "xpath_element" should exists
And I click on "Visible groups (Click to change)" "link" in the "Test forum name" activity
And "No groups (Click to change)" "link" should exists
And ".//a//img[contains(@src, 'groupn')]" "xpath_element" should exists
And "//a/child::img[contains(@src, 'groupn')]" "xpath_element" should exists
@@ -26,7 +26,7 @@ Feature: Indent items on the course page
When I indent right "Test glossary name" activity
Then "#section-1 li.glossary div.mod-indent-1" "css_element" should exists
And I indent right "Test glossary name" activity
And "//*[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[@title='Move left']" "xpath_element" should exists
And "//li[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[@title='Move left']" "xpath_element" should exists
And "#section-1 li.glossary div.mod-indent-2" "css_element" should exists
And I reload the page
And "#section-1 li.glossary div.mod-indent-2" "css_element" should exists
@@ -34,4 +34,4 @@ Feature: Indent items on the course page
And I indent left "Test glossary name" activity
And "#section-1 li.glossary div.mod-indent-2" "css_element" should not exists
And "#section-1 li.glossary div.mod-indent-1" "css_element" should not exists
And "//*[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[@title='Move left']" "xpath_element" should not exists
And "//li[@id='section-1']/descendant::li[contains(concat(' ', @class, ' '), ' glossary ')]/descendant::a[@title='Move left']" "xpath_element" should not exists
+46 -42
View File
@@ -48,7 +48,7 @@ class behat_course extends behat_base {
* @Given /^I turn editing mode on$/
*/
public function i_turn_editing_mode_on() {
return new Given('I press "Turn editing on"');
return new Given('I press "' . get_string('turneditingon') . '"');
}
/**
@@ -56,7 +56,7 @@ class behat_course extends behat_base {
* @Given /^I turn editing mode off$/
*/
public function i_turn_editing_mode_off() {
return new Given('I press "Turn editing off"');
return new Given('I press "' . get_string('turneditingoff') . '"');
}
/**
@@ -68,9 +68,9 @@ class behat_course extends behat_base {
public function i_create_a_course_with(TableNode $table) {
return array(
new Given('I go to the courses management page'),
new Given('I press "Add a new course"'),
new Given('I press "' . get_string('addnewcourse') . '"'),
new Given('I fill the moodle form with:', $table),
new Given('I press "Save changes"')
new Given('I press "' . get_string('savechanges') . '"')
);
}
@@ -83,9 +83,9 @@ class behat_course extends behat_base {
return array(
new Given('I am on homepage'),
new Given('I expand "Site administration" node'),
new Given('I expand "Courses" node'),
new Given('I follow "Add/edit courses"'),
new Given('I expand "' . get_string('administrationsite') . '" node'),
new Given('I expand "' . get_string('courses', 'admin') . '" node'),
new Given('I follow "' . get_string('coursemgmt', 'admin') . '"'),
);
}
@@ -100,9 +100,9 @@ class behat_course extends behat_base {
public function i_add_to_section_and_i_fill_the_form_with($activity, $section, TableNode $data) {
return array(
new Given('I add a "'.$activity.'" to section "'.$section.'"'),
new Given('I add a "' . $this->escape($activity) . '" to section "' . $this->escape($section) . '"'),
new Given('I fill the moodle form with:', $data),
new Given('I press "Save and return to course"')
new Given('I press "' . get_string('savechangesandreturntocourse') . '"')
);
}
@@ -116,7 +116,9 @@ class behat_course extends behat_base {
*/
public function i_add_to_section($activity, $section) {
$sectionxpath = "//*[@id='section-" . $section . "']";
$sectionxpath = "//li[@id='section-" . $section . "']";
$activityliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral(ucfirst($activity));
if ($this->running_javascript()) {
@@ -126,9 +128,9 @@ class behat_course extends behat_base {
$sectionnode->click();
// Clicks the selected activity if it exists.
$activity = ucfirst($activity);
$activityxpath = "//div[@id='chooseform']/descendant::label" .
"/descendant::span[contains(concat(' ', @class, ' '), ' typename ')][contains(.,'" . $activity . "')]" .
"/descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' typename ')]" .
"[contains(., $activityliteral)]" .
"/parent::label/child::input";
$activitynode = $this->find('xpath', $activityxpath);
$activitynode->doubleClick();
@@ -137,8 +139,8 @@ class behat_course extends behat_base {
// Without Javascript.
// Selecting the option from the select box which contains the option.
$selectxpath = $sectionxpath . "/descendant::div[contains(concat(' ', @class, ' '), ' section_add_menus ')]" .
"/descendant::select[contains(., '" . $activity . "')]";
$selectxpath = $sectionxpath . "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' section_add_menus ')]" .
"/descendant::select[contains(., $activityliteral)]";
$selectnode = $this->find('xpath', $selectxpath);
$selectnode->selectOption($activity);
@@ -162,7 +164,7 @@ class behat_course extends behat_base {
$xpath = $this->section_exists($sectionnumber);
return array(
new Given('I click on "' . get_string('markthistopic') . '" "link" in the "' . $xpath . '" "xpath_element"'),
new Given('I click on "' . get_string('markthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"'),
new Given('I wait "2" seconds')
);
}
@@ -179,7 +181,7 @@ class behat_course extends behat_base {
$xpath = $this->section_exists($sectionnumber);
return array(
new Given('I click on "' . get_string('markedthistopic') . '" "link" in the "' . $xpath . '" "xpath_element"'),
new Given('I click on "' . get_string('markedthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"'),
new Given('I wait "2" seconds')
);
}
@@ -268,7 +270,7 @@ class behat_course extends behat_base {
// Section should be hidden.
$exception = new ExpectationException('The section is not hidden', $this->getSession());
$this->find('xpath', $sectionxpath . "[contains(concat(' ', @class, ' '), ' hidden ')]", $exception);
$this->find('xpath', $sectionxpath . "[contains(concat(' ', normalize-space(@class), ' '), ' hidden ')]", $exception);
// The checking are different depending on user permissions.
if ($this->is_course_editor()) {
@@ -284,8 +286,8 @@ class behat_course extends behat_base {
foreach ($activities as $activity) {
// Dimmed.
$this->find('xpath', "//div[contains(concat(' ', @class, ' '), ' activityinstance ')]" .
"/a[contains(concat(' ', @class, ' '), ' dimmed ')]", $dimmedexception, $activity);
$this->find('xpath', "//div[contains(concat(' ', normalize-space(@class), ' '), ' activityinstance ')]" .
"/a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')]", $dimmedexception, $activity);
// Non-JS browsers can not click on img elements.
if ($this->running_javascript()) {
@@ -319,7 +321,8 @@ class behat_course extends behat_base {
$sectionxpath = $this->section_exists($sectionnumber);
// Section should not be hidden.
if (!$this->getSession()->getPage()->find('xpath', $sectionxpath . "[not(contains(concat(' ', @class, ' '), ' hidden '))]")) {
$xpath = $sectionxpath . "[not(contains(concat(' ', normalize-space(@class), ' '), ' hidden '))]";
if (!$this->getSession()->getPage()->find('xpath', $xpath)) {
throw new ExpectationException('The section is hidden', $this->getSession());
}
@@ -449,10 +452,11 @@ class behat_course extends behat_base {
// JS enabled.
if ($this->running_javascript()) {
$destinationxpath = $sectionxpath . "/descendant::ul[contains(@class, 'yui3-dd-drop')]";
$destinationxpath = $sectionxpath . "/descendant::ul[contains(concat(' ', normalize-space(@class), ' '), ' yui3-dd-drop ')]";
return array(
new Given('I drag "' . $activitynode->getXpath() . '" "xpath_element" and I drop it in "' . $destinationxpath . '" "xpath_element"'),
new Given('I drag "' . $this->escape($activitynode->getXpath()) . '" "xpath_element" ' .
'and I drop it in "' . $this->escape($destinationxpath) . '" "xpath_element"'),
);
} else {
@@ -460,8 +464,8 @@ class behat_course extends behat_base {
// Moving to the fist spot of the section (before all other section's activities).
return array(
new Given('I click on "a.editing_move" "css_element" in the "' . $activityname . '" activity'),
new Given('I click on "li.movehere a" "css_element" in the "' . $sectionxpath . '" "xpath_element"'),
new Given('I click on "a.editing_move" "css_element" in the "' . $this->escape($activityname) . '" activity'),
new Given('I click on "li.movehere a" "css_element" in the "' . $this->escape($sectionxpath) . '" "xpath_element"'),
);
}
}
@@ -482,8 +486,8 @@ class behat_course extends behat_base {
// Adding chr(10) to save changes.
return array(
new Given('I click on "' . get_string('edittitle') . '" "link" in the "' . $activityname .'" activity'),
new Given('I fill in "title" with "' . $newactivityname . chr(10) . '"'),
new Given('I click on "' . get_string('edittitle') . '" "link" in the "' . $this->escape($activityname) .'" activity'),
new Given('I fill in "title" with "' . $this->escape($newactivityname) . chr(10) . '"'),
new Given('I wait "2" seconds')
);
}
@@ -497,7 +501,7 @@ class behat_course extends behat_base {
public function i_indent_right_activity($activityname) {
$steps = array(
new Given('I click on "' . get_string('moveright') . '" "link" in the "' . $activityname . '" activity')
new Given('I click on "' . get_string('moveright') . '" "link" in the "' . $this->escape($activityname) . '" activity')
);
if ($this->running_javascript()) {
@@ -516,7 +520,7 @@ class behat_course extends behat_base {
public function i_indent_left_activity($activityname) {
$steps = array(
new Given('I click on "' . get_string('moveleft') . '" "link" in the "' . $activityname . '" activity')
new Given('I click on "' . get_string('moveleft') . '" "link" in the "' . $this->escape($activityname) . '" activity')
);
if ($this->running_javascript()) {
@@ -553,7 +557,7 @@ class behat_course extends behat_base {
// With JS disabled.
$steps = array(
new Given('I click on "' . $deletestring . '" "link" in the "' . $activityname . '" activity'),
new Given('I click on "' . $this->escape($deletestring) . '" "link" in the "' . $this->escape($activityname) . '" activity'),
new Given('I press "' . get_string('yes') . '"')
);
@@ -569,7 +573,7 @@ class behat_course extends behat_base {
*/
public function i_duplicate_activity($activityname) {
return array(
new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $activityname . '" activity'),
new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $this->escape($activityname) . '" activity'),
new Given('I press "' . get_string('continue') .'"'),
new Given('I press "' . get_string('duplicatecontcourse') .'"')
);
@@ -584,7 +588,7 @@ class behat_course extends behat_base {
*/
public function i_duplicate_activity_editing_the_new_copy_with($activityname, TableNode $data) {
return array(
new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $activityname . '" activity'),
new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $this->escape($activityname) . '" activity'),
new Given('I press "' . get_string('continue') .'"'),
new Given('I press "' . get_string('duplicatecontedit') . '"'),
new Given('I fill the moodle form with:', $data),
@@ -657,9 +661,9 @@ class behat_course extends behat_base {
$courseformat = $this->get_course_format();
// Checking the show button alt text and show icon.
$showtext = get_string('showfromothers', $courseformat);
$linkxpath = $xpath . "/descendant::a[@title='". $showtext ."']";
$imgxpath = $linkxpath . "/descendant::img[@alt='". $showtext ."'][contains(@src, 'show')]";
$showtext = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('showfromothers', $courseformat));
$linkxpath = $xpath . "/descendant::a[@title=$showtext]";
$imgxpath = $linkxpath . "/descendant::img[@alt=$showtext][contains(@src, 'show')]";
$exception = new ElementNotFoundException($this->getSession(), 'Show section icon ');
$this->find('xpath', $imgxpath, $exception);
@@ -684,9 +688,9 @@ class behat_course extends behat_base {
$courseformat = $this->get_course_format();
// Checking the hide button alt text and hide icon.
$hidetext = get_string('hidefromothers', $courseformat);
$linkxpath = $xpath . "/descendant::a[@title='" . $hidetext . "']";
$imgxpath = $linkxpath . "/descendant::img[@alt='" . $hidetext ."'][contains(@src, 'hide')]";
$hidetext = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('hidefromothers', $courseformat));
$linkxpath = $xpath . "/descendant::a[@title=$hidetext]";
$imgxpath = $linkxpath . "/descendant::img[@alt=$hidetext][contains(@src, 'hide')]";
$exception = new ElementNotFoundException($this->getSession(), 'Hide section icon ');
$this->find('xpath', $imgxpath, $exception);
@@ -730,7 +734,7 @@ class behat_course extends behat_base {
*/
protected function get_section_activities($sectionxpath) {
$xpath = $sectionxpath . "/descendant::li[contains(concat(' ', @class, ' '), ' activity ')]";
$xpath = $sectionxpath . "/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')]";
// We spin here, as activities usually require a lot of time to load.
try {
@@ -751,8 +755,8 @@ class behat_course extends behat_base {
*/
protected function get_activity_node($activityname) {
$activityname = str_replace("'", "\'", $activityname);
$xpath = "//li[contains(concat(' ', @class, ' '), ' activity ')][contains(., '" .$activityname. "')]";
$activityname = $this->getSession()->getSelectorsHandler()->xpathLiteral($activityname);
$xpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][contains(., $activityname)]";
return $this->find('xpath', $xpath);
}
@@ -765,8 +769,8 @@ class behat_course extends behat_base {
protected function is_course_editor() {
// We don't need to behat_base::spin() here as all is already loaded.
if (!$this->getSession()->getPage()->findButton('Turn editing off') &&
!$this->getSession()->getPage()->findButton('Turn editing on')) {
if (!$this->getSession()->getPage()->findButton(get_string('turneditingoff')) &&
!$this->getSession()->getPage()->findButton(get_string('turneditingon'))) {
return false;
}
+15 -15
View File
@@ -28,11 +28,11 @@ Feature: Force group mode in a course
| Group mode | Separate groups |
| Force group mode | Yes |
When I press "Save changes"
Then ".//a//img[contains(./@alt, 'Separate groups (forced mode)')]" "xpath_element" should not exists
And ".//img[contains(./@alt, 'Separate groups (forced mode)')]" "xpath_element" should exists
And I click on "//img[contains(./@alt, 'Separate groups (forced mode)')]" "xpath_element" in the "li.activity.chat" "css_element"
And ".//a//img[contains(./@alt, 'Separate groups (forced mode)')]" "xpath_element" should not exists
And ".//img[contains(./@alt, 'Separate groups (forced mode)')]" "xpath_element" should exists
Then "//a/child::img[contains(@alt, 'Separate groups (forced mode)')]" "xpath_element" should not exists
And "//img[contains(@alt, 'Separate groups (forced mode)')]" "xpath_element" should exists
And I click on "//img[contains(@alt, 'Separate groups (forced mode)')]" "xpath_element" in the "li.activity.chat" "css_element"
And "//a/child::img[contains(@alt, 'Separate groups (forced mode)')]" "xpath_element" should not exists
And "//img[contains(@alt, 'Separate groups (forced mode)')]" "xpath_element" should exists
@javascript
Scenario: Forced group mode using visible groups
@@ -40,11 +40,11 @@ Feature: Force group mode in a course
| Group mode | Visible groups |
| Force group mode | Yes |
And I press "Save changes"
Then ".//a//img[contains(./@alt, 'Visible groups (forced mode)')]" "xpath_element" should not exists
And ".//img[contains(./@alt, 'Visible groups (forced mode)')]" "xpath_element" should exists
And I click on "//img[contains(./@alt, 'Visible groups (forced mode)')]" "xpath_element" in the "li.activity.chat" "css_element"
And ".//a//img[contains(./@alt, 'Visible groups (forced mode)')]" "xpath_element" should not exists
And ".//img[contains(./@alt, 'Visible groups (forced mode)')]" "xpath_element" should exists
Then "//a/child::img[contains(@alt, 'Visible groups (forced mode)')]" "xpath_element" should not exists
And "//img[contains(@alt, 'Visible groups (forced mode)')]" "xpath_element" should exists
And I click on "//img[contains(@alt, 'Visible groups (forced mode)')]" "xpath_element" in the "li.activity.chat" "css_element"
And "//a/child::img[contains(@alt, 'Visible groups (forced mode)')]" "xpath_element" should not exists
And "//img[contains(@alt, 'Visible groups (forced mode)')]" "xpath_element" should exists
@javascript
Scenario: Forced group mode without groups
@@ -52,9 +52,9 @@ Feature: Force group mode in a course
| Group mode | No groups |
| Force group mode | Yes |
And I press "Save changes"
Then ".//a//img[contains(./@alt, 'No groups (forced mode)')]" "xpath_element" should not exists
And ".//img[contains(./@alt, 'No groups (forced mode)')]" "xpath_element" should exists
And I click on "//img[contains(./@alt, 'No groups (forced mode)')]" "xpath_element" in the "li.activity.chat" "css_element"
And ".//a//img[contains(./@alt, 'No groups (forced mode)')]" "xpath_element" should not exists
And ".//img[contains(./@alt, 'No groups (forced mode)')]" "xpath_element" should exists
Then "//a/child::img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" should not exists
And "//img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" should exists
And I click on "//img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" in the "li.activity.chat" "css_element"
And "//a/child::img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" should not exists
And "//img[contains(@alt, 'No groups (forced mode)')]" "xpath_element" should exists
+4 -4
View File
@@ -50,11 +50,11 @@ class behat_enrol extends behat_base {
public function i_add_enrolment_method_with($enrolmethod, TableNode $table) {
return array(
new Given('I expand "Users" node'),
new Given('I follow "Enrolment methods"'),
new Given('I select "' . $enrolmethod . '" from "Add method"'),
new Given('I expand "' . get_string('users', 'admin') . '" node'),
new Given('I follow "' . get_string('type_enrol_plural', 'plugin') . '"'),
new Given('I select "' . $this->escape($enrolmethod) . '" from "' . get_string('addinstance', 'enrol') . '"'),
new Given('I fill the moodle form with:', $table),
new Given('I press "Add method"')
new Given('I press "' . get_string('addinstance', 'enrol') . '"')
);
}
+9 -6
View File
@@ -51,36 +51,39 @@ class behat_groups extends behat_base {
global $DB;
$user = $DB->get_record('user', array('username' => $username));
$userfullname = fullname($user);
$userfullname = $this->getSession()->getSelectorsHandler()->xpathLiteral(fullname($user));
// Using a xpath liternal to avoid problems with quotes and double quotes.
$groupname = $this->getSession()->getSelectorsHandler()->xpathLiteral($groupname);
// We don't know the option text as it contains the number of users in the group.
$select = $this->find_field('groups');
$xpath = "//select[@id='groups']/descendant::option[contains(., '" . $groupname . "')]";
$xpath = "//select[@id='groups']/descendant::option[contains(., $groupname)]";
$groupoption = $this->find('xpath', $xpath);
$fulloption = $groupoption->getText();
$select->selectOption($fulloption);
// Here we don't need to wait for the AJAX response.
$this->find_button('Add/remove users')->click();
$this->find_button(get_string('adduserstogroup', 'group'))->click();
// Wait for add/remove members page to be loaded.
$this->getSession()->wait(self::TIMEOUT, '(document.readyState === "complete")');
// Getting the option and selecting it.
$select = $this->find_field('addselect');
$xpath = "//select[@id='addselect']/descendant::option[contains(., '" . $userfullname . "')]";
$xpath = "//select[@id='addselect']/descendant::option[contains(., $userfullname)]";
$memberoption = $this->find('xpath', $xpath);
$fulloption = $memberoption->getText();
$select->selectOption($fulloption);
// Click add button.
$this->find_button('Add')->click();
$this->find_button(get_string('add'))->click();
// Wait for the page to load.
$this->getSession()->wait(self::TIMEOUT, '(document.readyState === "complete")');
// Returning to the main groups page.
$this->find_button('Back to groups')->click();
$this->find_button(get_string('backtogroups', 'group'))->click();
}
}
+25 -17
View File
@@ -64,10 +64,12 @@ class behat_files extends behat_base {
$exception = new ExpectationException('"' . $filepickerelement . '" filepicker can not be found', $this->getSession());
// Gets the ffilemanager node specified by the locator which contains the filepicker container.
$filepickerelement = $this->getSession()->getSelectorsHandler()->xpathLiteral($filepickerelement);
$filepickercontainer = $this->find(
'xpath',
"//input[./@id = //label[contains(normalize-space(string(.)), '" . $filepickerelement . "')]/@for]
//ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' ffilemanager ') or contains(concat(' ', normalize-space(@class), ' '), ' ffilepicker ')]",
"//input[./@id = //label[normalize-space(.)=$filepickerelement]/@for]" .
"//ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' ffilemanager ') or " .
"contains(concat(' ', normalize-space(@class), ' '), ' ffilepicker ')]",
$exception
);
@@ -117,17 +119,20 @@ class behat_files extends behat_base {
$exception = new ExpectationException($exceptionmsg, $this->getSession());
// Avoid quote-related problems.
$name = $this->getSession()->getSelectorsHandler()->xpathLiteral($name);
// Get a filepicker element (folder or file).
try {
// First we look at the folder as we need to click on the contextual menu otherwise it would be opened.
$node = $this->find(
'xpath',
"//div[@class='fp-content']
//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]
[contains(concat(' ', normalize-space(@class), ' '), ' fp-folder ')][contains(normalize-space(string(.)), '" . $name . "')]
//descendant::a[contains(concat(' ', normalize-space(@class), ' '), ' fp-contextmenu ')]
",
"//div[@class='fp-content']" .
"//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]" .
"[contains(concat(' ', normalize-space(@class), ' '), ' fp-folder ')]" .
"[normalize-space(.)=$name]" .
"//descendant::a[contains(concat(' ', normalize-space(@class), ' '), ' fp-contextmenu ')]",
$exception,
$containernode
);
@@ -137,10 +142,10 @@ class behat_files extends behat_base {
// Here the contextual menu is hidden, we click on the thumbnail.
$node = $this->find(
'xpath',
"//div[@class='fp-content']
//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')][contains(normalize-space(string(.)), '" . $name . "')]
//descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-thumbnail ')]
",
"//div[@class='fp-content']" .
"//descendant::*[self::div | self::a][contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')]" .
"[normalize-space(.)=$name]" .
"//descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-thumbnail ')]",
false,
$containernode
);
@@ -176,12 +181,15 @@ class behat_files extends behat_base {
// Getting the repository link and opening it.
$repoexception = new ExpectationException('The "' . $repositoryname . '" repository has not been found', $this->getSession());
// Avoid problems with both double and single quotes in the same string.
$repositoryname = $this->getSession()->getSelectorsHandler()->xpathLiteral($repositoryname);
// Here we don't need to look inside the selected filepicker because there can only be one modal window.
$repositorylink = $this->find(
'xpath',
"//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')]
//descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-name ')]
[contains(normalize-space(string(.)), '" . $repositoryname . "')]",
"//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')]" .
"//descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-name ')]" .
"[normalize-space(.)=$repositoryname]",
$repoexception
);
@@ -226,10 +234,10 @@ class behat_files extends behat_base {
// only used when accessing the filepicker, there is no filemanager-loading after selecting the file.
$this->find(
'xpath',
"//div[contains(concat(' ', @class, ' '), ' filemanager ')]" .
"[not(contains(concat(' ', @class, ' '), ' fm-updating '))]" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' filemanager ')]" .
"[not(contains(concat(' ', normalize-space(@class), ' '), ' fm-updating '))]" .
"|" .
"//div[contains(concat(' ', @class, ' '), ' filemanager-loading ')]" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' filemanager-loading ')]" .
"[contains(@style, 'display: none;')]",
$exception,
$filepickernode
+4 -1
View File
@@ -58,10 +58,13 @@ class behat_form_select extends behat_form_field {
// Single select needs an extra click in the option.
if (!$this->field->hasAttribute('multiple')) {
$value = $this->session->getSelectorsHandler()->xpathLiteral($value);
// Using the driver direcly because Element methods are messy when dealing
// with elements inside containers.
$optionxpath = $this->field->getXpath() .
"/descendant::option[(./@value = '" . $value . "' or contains(normalize-space(string(.)), '" . $value . "'))]";
"/descendant::option[(./@value=$value or normalize-space(.)=$value)]";
$optionnodes = $this->session->getDriver()->find($optionxpath);
if ($optionnodes) {
current($optionnodes)->click();
+7 -4
View File
@@ -132,8 +132,8 @@ class behat_forms extends behat_base {
// Show all fields.
$showmorestr = get_string('showmore', 'form');
$showmores = $this->find_all('xpath', "//a[contains(concat(' ', normalize-space(.), ' '), '" . $showmorestr . "')]" .
"[contains(concat(' ', normalize-space(@class), ' '), ' moreless-toggler')]");
$showmores = $this->find_all('xpath', "//a[normalize-space(.)='" . $showmorestr . "']" .
"[contains(concat(' ', normalize-space(@class), ' '), ' moreless-toggler ')]");
// We are supposed to have 'show more's here, otherwise exception.
@@ -186,9 +186,12 @@ class behat_forms extends behat_base {
return;
}
// Single select needs an extra click in the option.
if (!$selectnode->hasAttribute('multiple')) {
// Single select needs an extra click in the option.
$xpath = ".//option[(./@value = '" . $option . "' or contains(normalize-space(string(.)), '" . $option . "'))]";
// Avoid quotes problems.
$option = $this->getSession()->getSelectorsHandler()->xpathLiteral($option);
$xpath = "//option[(./@value=$option or normalize-space(.)=$option)]";
$optionnode = $this->find('xpath', $xpath, false, $selectnode);
$optionnode->click();
} else {
+4 -4
View File
@@ -242,8 +242,8 @@ class behat_general extends behat_base {
// The table row container.
$nocontainerexception = new ElementNotFoundException($this->getSession(), '"' . $tablerowtext . '" row text ');
$tablerowtext = str_replace("'", "\'", $tablerowtext);
$rownode = $this->find('xpath', "//tr[contains(., '" . $tablerowtext . "')]", $nocontainerexception);
$tablerowtext = $this->getSession()->getSelectorsHandler()->xpathLiteral($tablerowtext);
$rownode = $this->find('xpath', "//tr[contains(., $tablerowtext)]", $nocontainerexception);
// Looking for the element DOM node inside the specified row.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
@@ -285,7 +285,7 @@ class behat_general extends behat_base {
public function assert_page_contains_text($text) {
$xpathliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($text);
$xpath = "/descendant::*[contains(., " . $xpathliteral. ")]";
$xpath = "/descendant::*[contains(., $xpathliteral)]";
// Wait until it finds the text, otherwise custom exception.
try {
@@ -305,7 +305,7 @@ class behat_general extends behat_base {
public function assert_page_not_contains_text($text) {
$xpathliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($text);
$xpath = "/descendant::*[not(contains(., " . $xpathliteral. "))]";
$xpath = "/descendant::*[not(contains(., $xpathliteral))]";
// Wait until it finds the text, otherwise custom exception.
try {
+17 -11
View File
@@ -56,16 +56,19 @@ class behat_navigation extends behat_base {
return false;
}
// Avoid problems with quotes.
$nodetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($nodetext);
$xpath = "//ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/child::li[contains(concat(' ', normalize-space(@class), ' '), ' collapsed ')]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]" .
"/child::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/child::span[normalize-space(.)=$nodetextliteral]" .
"|" .
"//ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/descendant::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed'))]" .
"/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' collapsed')]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]" .
"/child::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]";
"/descendant::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed '))]" .
"/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' collapsed ')]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/child::span[normalize-space(.)=$nodetextliteral]";
$exception = new ExpectationException('The "' . $nodetext . '" node can not be expanded', $this->getSession());
$node = $this->find('xpath', $xpath, $exception);
@@ -86,15 +89,18 @@ class behat_navigation extends behat_base {
return false;
}
// Avoid problems with quotes.
$nodetextliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($nodetext);
$xpath = "//ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/child::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed '))]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]" .
"/child::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/child::span[normalize-space(.)=$nodetextliteral]" .
"|" .
"//ul[contains(concat(' ', normalize-space(@class), ' '), ' block_tree ')]" .
"/descendant::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed'))]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch')]" .
"/child::span[contains(concat(' ', normalize-space(.), ' '), '" . $nodetext . "')]";
"/descendant::li[not(contains(concat(' ', normalize-space(@class), ' '), ' collapsed '))]" .
"/child::p[contains(concat(' ', normalize-space(@class), ' '), ' branch ')]" .
"/child::span[normalize-space(.)=$nodetextliteral]";
$exception = new ExpectationException('The "' . $nodetext . '" node can not be collapsed', $this->getSession());
$node = $this->find('xpath', $xpath, $exception);
+11 -11
View File
@@ -52,14 +52,14 @@ class behat_permissions extends behat_base {
return array(
new Given('I am on homepage'),
new Given('I collapse "Front page settings" node'),
new Given('I expand "Site administration" node'),
new Given('I expand "Users" node'),
new Given('I expand "Permissions" node'),
new Given('I follow "Define roles"'),
new Given('I collapse "' . get_string('frontpagesettings', 'admin') . '" node'),
new Given('I expand "' . get_string('administrationsite') . '" node'),
new Given('I expand "' . get_string('users', 'admin') . '" node'),
new Given('I expand "' . get_string('permissions', 'role') . '" node'),
new Given('I follow "' . get_string('defineroles', 'role') . '"'),
new Given('I follow "Edit ' . $this->escape($rolename) . ' role"'),
new Given('I fill the capabilities form with the following permissions:', $table),
new Given('I press "Save changes"')
new Given('I press "' . get_string('savechanges') . '"')
);
}
@@ -73,12 +73,12 @@ class behat_permissions extends behat_base {
public function i_override_the_system_permissions_of_role_with($rolename, $table) {
// We don't know the number of overrides so we have to get it to match the option contents.
$roleoption = $this->find('xpath', '//select[@name="roleid"]/option[contains(text(),"' . $this->escape($rolename) . '")]');
$roleoption = $this->find('xpath', '//select[@name="roleid"]/option[contains(.,"' . $this->escape($rolename) . '")]');
return array(
new Given('I select "' . $this->escape($roleoption->getText()) . '" from "Advanced role override"'),
new Given('I select "' . $this->escape($roleoption->getText()) . '" from "' . get_string('advancedoverride', 'role') . '"'),
new Given('I fill the capabilities form with the following permissions:', $table),
new Given('I press "Save changes"')
new Given('I press "' . get_string('savechanges') . '"')
);
}
@@ -93,9 +93,9 @@ class behat_permissions extends behat_base {
// Ensure we are using the advanced view.
// Wrapped in a try/catch to capture the exception and continue execution, we don't know if advanced mode was already enabled.
try {
$advancedtoggle = $this->find_button('Show advanced');
$advancedtoggle = $this->find_button(get_string('showadvanced', 'form'));
if ($advancedtoggle) {
$this->getSession()->getPage()->pressButton('Show advanced');
$this->getSession()->getPage()->pressButton(get_string('showadvanced', 'form'));
}
} catch (Exception $e) {
// We already are in advanced mode.
+5 -5
View File
@@ -63,14 +63,14 @@ class behat_message extends behat_base {
$steps[] = new Given('I am on homepage');
if ($this->running_javascript()) {
$steps[] = new Given('I expand "My profile" node');
$steps[] = new Given('I expand "' . get_string('myprofile') . '" node');
}
$steps[] = new Given('I follow "Messages"');
$steps[] = new Given('I fill in "' . get_string('searchcombined', 'message') . '" with "' . $tofullname . '"');
$steps[] = new Given('I follow "' . get_string('messages', 'message') . '"');
$steps[] = new Given('I fill in "' . get_string('searchcombined', 'message') . '" with "' . $this->escape($tofullname) . '"');
$steps[] = new Given('I press "' . get_string('searchcombined', 'message') . '"');
$steps[] = new Given('I follow "' . get_string('sendmessageto', 'message', $tofullname) . '"');
$steps[] = new Given('I fill in "id_message" with "' . $messagecontent . '"');
$steps[] = new Given('I follow "' . $this->escape(get_string('sendmessageto', 'message', $tofullname)) . '"');
$steps[] = new Given('I fill in "id_message" with "' . $this->escape($messagecontent) . '"');
$steps[] = new Given('I press "' . get_string('sendmessage', 'message') . '"');
return $steps;
+1 -1
View File
@@ -52,7 +52,7 @@ class behat_mod_choice extends behat_base {
return array(
new Given('I follow "' . $this->escape($choiceactivity) . '"'),
new Given('I select "' . $this->escape($option) . '" radio button'),
new Given('I press "Save my choice"')
new Given('I press "' . get_string('savemychoice', 'choice') . '"')
);
}
+4 -4
View File
@@ -51,9 +51,9 @@ class behat_mod_forum extends behat_base {
// Escaping $forumname as it has been stripped automatically by the transformer.
return array(
new Given('I follow "' . $this->escape($forumname) . '"'),
new Given('I press "' . get_string('addanewdiscussion', 'mod_forum') . '"'),
new Given('I press "' . get_string('addanewdiscussion', 'forum') . '"'),
new Given('I fill the moodle form with:', $table),
new Given('I press "' . get_string('posttoforum', 'mod_forum') . '"'),
new Given('I press "' . get_string('posttoforum', 'forum') . '"'),
new Given('I wait to be redirected')
);
}
@@ -71,9 +71,9 @@ class behat_mod_forum extends behat_base {
return array(
new Given('I follow "' . $this->escape($forumname) . '"'),
new Given('I follow "' . $this->escape($postsubject) . '"'),
new Given('I follow "' . get_string('reply', 'mod_forum') . '"'),
new Given('I follow "' . get_string('reply', 'forum') . '"'),
new Given('I fill the moodle form with:', $table),
new Given('I press "' . get_string('posttoforum', 'mod_forum') . '"'),
new Given('I press "' . get_string('posttoforum', 'forum') . '"'),
new Given('I wait to be redirected')
);
@@ -38,7 +38,7 @@ Feature: Set a certain number of discussions as a completion condition for a for
And I log out
And I log in as "student1"
And I follow "Course 1"
Then I hover "//li[contains(concat(' ', @class, ' '), ' modtype_forum ')]/descendant::img[@alt='Not completed: Test forum name']" "xpath_element"
Then I hover "//li[contains(concat(' ', normalize-space(@class), ' '), ' modtype_forum ')]/descendant::img[@alt='Not completed: Test forum name']" "xpath_element"
And I add a new discussion to "Test forum name" forum with:
| Subject | Post 1 subject |
| Message | Body 1 content |
@@ -46,7 +46,7 @@ Feature: Set a certain number of discussions as a completion condition for a for
| Subject | Post 2 subject |
| Message | Body 2 content |
And I follow "Course 1"
And I hover "//li[contains(concat(' ', @class, ' '), ' modtype_forum ')]/descendant::img[contains(@alt, 'Completed: Test forum name')]" "xpath_element"
And I hover "//li[contains(concat(' ', normalize-space(@class), ' '), ' modtype_forum ')]/descendant::img[contains(@alt, 'Completed: Test forum name')]" "xpath_element"
And I log out
And I log in as "teacher1"
And I follow "Course 1"
@@ -50,7 +50,7 @@ class behat_mod_glossary extends behat_base {
return array(
new Given('I press "' . get_string('addentry', 'mod_glossary') . '"'),
new Given('I fill the moodle form with:', $data),
new Given('I press "Save changes"')
new Given('I press "' . get_string('savechanges') . '"')
);
}
@@ -65,8 +65,8 @@ class behat_mod_glossary extends behat_base {
return array(
new Given('I follow "' . get_string('categoryview', 'mod_glossary') . '"'),
new Given('I press "' . get_string('editcategories', 'mod_glossary') . '"'),
new Given('I press "Add Category"'),
new Given('I fill in "name" with "' . $categoryname . '"'),
new Given('I press "' . get_string('add').' '.get_string('category', 'glossary') . '"'),
new Given('I fill in "name" with "' . $this->escape($categoryname) . '"'),
new Given('I press "' . get_string('savechanges') . '"'),
new Given('I press "' . get_string('back', 'mod_glossary') . '"')
);
@@ -34,7 +34,7 @@ Feature: A teacher can choose whether to provide a printer-friendly glossary ent
| Concept | Just a test concept |
| Definition | Concept definition |
Then "Printer-friendly version" "link" should exists
And "//*[contains(concat(' ', @class, ' '), ' printicon ')][contains(@href, 'print.php')]" "xpath_element" should exists
And "//*[contains(concat(' ', normalize-space(@class), ' '), ' printicon ')][contains(@href, 'print.php')]" "xpath_element" should exists
And I follow "Printer-friendly version"
And I should see "Just a test concept"
@@ -51,4 +51,4 @@ Feature: A teacher can choose whether to provide a printer-friendly glossary ent
| Concept | Just a test concept |
| Definition | Concept definition |
Then "Printer-friendly version" "link" should not exists
And "//*[contains(concat(' ', @class, ' '), ' printicon ')][contains(@href, 'print.php')]" "xpath_element" should not exists
And "//*[contains(concat(' ', normalize-space(@class), ' '), ' printicon ')][contains(@href, 'print.php')]" "xpath_element" should not exists
@@ -40,7 +40,7 @@ Feature: In a lesson activity, students can navigate through a series of pages i
| id_jumpto_1 | Next page |
And I press "Save page"
And I follow "Expanded"
And I click on "Add a question page here" "link" in the "//div[contains(concat(' ', @class, ' '), ' addlinks ')][3]" "xpath_element"
And I click on "Add a question page here" "link" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' addlinks ')][3]" "xpath_element"
And I select "Numerical" from "Select a question type"
And I press "Add a question page"
And I fill the moodle form with:
+12 -6
View File
@@ -51,16 +51,18 @@ class behat_question extends behat_base {
*/
public function i_add_a_question_filling_the_form_with($questiontypename, TableNode $questiondata) {
$questiontypexpath = "//span[@class='qtypename'][.='" . $questiontypename . "']" .
// Using xpath literal to avoid quotes problems.
$questiontypename = $this->getSession()->getSelectorsHandler()->xpathLiteral($questiontypename);
$questiontypexpath = "//span[@class='qtypename'][normalize-space(.)=$questiontypename]" .
"/ancestor::div[@class='qtypeoption']/descendant::input";
return array(
new Given('I follow "' . get_string('questionbank', 'question') . '"'),
new Given('I press "' . get_string('createnewquestion', 'question') . '"'),
new Given('I click on "' . $questiontypexpath . '" "xpath_element"'),
new Given('I click on "' . $this->escape($questiontypexpath) . '" "xpath_element"'),
new Given('I click on "Next" "button" in the "#qtypechoicecontainer" "css_element"'),
new Given('I fill the moodle form with:', $questiondata),
new Given('I press "Save changes"')
new Given('I press "' . get_string('savechanges') . '"')
);
}
@@ -75,14 +77,18 @@ class behat_question extends behat_base {
*/
public function the_state_of_question_is_shown_as($questiondescription, $state) {
// Using xpath literal to avoid quotes problems.
$questiondescriptionliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($questiondescription);
$stateliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($state);
// Split in two checkings to give more feedback in case of exception.
$exception = new ElementNotFoundException($this->getSession(), 'Question "' . $questiondescription . '" ');
$questionxpath = "//div[contains(concat(' ', @class, ' '), ' qtext ')][contains(., '" . $questiondescription . "')]";
$questionxpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' qtext ')][contains(., $questiondescriptionliteral)]";
$this->find('xpath', $questionxpath, $exception);
$exception = new ExpectationException('Question "' . $questiondescription . '" state is not "' . $state . '"', $this->getSession());
$xpath = $questionxpath . "/ancestor::div[contains(concat(' ', @class, ' '), ' que ')]" .
"/descendant::div[@class='state'][contains(., '" . $state . "')]";
$xpath = $questionxpath . "/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' que ')]" .
"/descendant::div[@class='state'][contains(., $stateliteral)]";
$this->find('xpath', $xpath, $exception);
}
@@ -56,7 +56,7 @@ class behat_repository_recent extends behat_files {
// Opening the specified file contextual menu from the modal window.
$this->open_element_contextual_menu($filename);
$this->find_button('Select this file')->click();
$this->find_button(get_string('getfile', 'repository'))->click();
// Ensure the file has been selected and we returned to the form page.
$this->wait_until_return_to_form();
+6 -4
View File
@@ -63,7 +63,7 @@ class behat_filepicker extends behat_files {
$dialoginput = $this->find('css', '.fp-mkdir-dlg-text input');
$dialoginput->setValue($foldername);
$this->getSession()->getPage()->pressButton('Create folder');
$this->getSession()->getPage()->pressButton(get_string('makeafolder'));
// Wait until the process finished and modal windows are hidden.
$this->wait_until_return_to_form();
@@ -92,6 +92,8 @@ class behat_filepicker extends behat_files {
// Just in case there is any contents refresh in progress.
$this->wait_until_contents_are_updated($fieldnode);
$folderliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($foldername);
// We look both in the pathbar and in the contents.
try {
@@ -99,8 +101,8 @@ class behat_filepicker extends behat_files {
$folder = $this->find(
'xpath',
"//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-folder ')]" .
"/descendant::div[contains(concat(' ', @class, ' '), ' fp-filename ')]" .
"[normalize-space(.)='" . $foldername . "']",
"/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-filename ')]" .
"[normalize-space(.)=$folderliteral]",
$exception,
$fieldnode
);
@@ -110,7 +112,7 @@ class behat_filepicker extends behat_files {
$folder = $this->find(
'xpath',
"//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-path-folder-name ')]" .
"[normalize-space(.)='" . $foldername . "']",
"[normalize-space(.)=$folderliteral]",
$exception,
$fieldnode
);
@@ -24,7 +24,7 @@ Feature: A selected file can be cancelled
And I upload "lib/tests/fixtures/upload_users.csv" file to "Files" filepicker
And I click on "#fitem_id_files .fp-btn-add a" "css_element"
And I click on "Recent files" "link" in the ".fp-repo-area" "css_element"
And I click on "//a[contains(concat(' ', @class, ' '), ' fp-file ')][contains(., 'empty.txt')]" "xpath_element"
And I click on "//a[contains(concat(' ', normalize-space(@class), ' '), ' fp-file ')][normalize-space(.)='empty.txt']" "xpath_element"
And I click on ".yui3-panel-focused .fp-select .fp-select-cancel" "css_element"
And I click on ".yui3-panel-focused .file-picker button.yui3-button-close" "css_element"
And I press "Save and display"
@@ -65,10 +65,10 @@ class behat_repository_upload extends behat_files {
$noformexception = new ExpectationException('The upload file form is not ready', $this->getSession());
$this->find(
'xpath',
"//div[contains(concat(' ', @class, ' '), ' file-picker ')]" .
"[contains(concat(' ', @class, ' '), ' repository_upload ')]" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" .
"[contains(concat(' ', normalize-space(@class), ' '), ' repository_upload ')]" .
"/descendant::div[@class='fp-content']" .
"/descendant::div[contains(concat(' ', @class, ' '), ' fp-upload-form ')]" .
"/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-upload-form ')]" .
"/descendant::form",
$noformexception
);