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

This commit is contained in:
Eloy Lafuente (stronk7) 2013-12-10 23:29:06 +01:00
commit ebc77165a4
51 changed files with 991 additions and 335 deletions

View file

@ -29,14 +29,12 @@ Feature: Toggle activities groups mode from the course page
Then "No groups (Click to change)" "link" 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/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/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/child::img[contains(@src, 'groupv')]" "xpath_element" should exists
And I reload the page

View file

@ -40,8 +40,10 @@ Feature: Add activities to courses
Scenario: Add an activity without the required fields
When I add a "Database" to section "3" and I fill the form with:
| Name | Test name |
And I press "Save and return to course"
Then I should see "Adding a new"
And I should see "Required"
And I press "Cancel"
Scenario: Add an activity to a course with Javascript disabled
Then I should see "Add a resource to section 'Topic 1'"

View file

@ -67,15 +67,50 @@ class behat_course extends behat_base {
* @return Given[]
*/
public function i_create_a_course_with(TableNode $table) {
return array(
$steps = array(
new Given('I go to the courses management page'),
new Given('I should see the "'.get_string('categories').'" management page'),
new Given('I click on category "'.get_string('miscellaneous').'" in the management interface'),
new Given('I should see the "'.get_string('categoriesandcoures').'" management page'),
new Given('I click on "'.get_string('createnewcourse').'" "link" in the "#course-listing" "css_element"'),
new Given('I fill the moodle form with:', $table),
new Given('I press "' . get_string('savechanges') . '"')
new Given('I click on "'.get_string('createnewcourse').'" "link" in the "#course-listing" "css_element"')
);
// If the course format is one of the fields we change how we
// fill the form as we need to wait for the form to be set.
$rowshash = $table->getRowsHash();
$formatfieldrefs = array(get_string('format'), 'format', 'id_format');
foreach ($formatfieldrefs as $fieldref) {
if (!empty($rowshash[$fieldref])) {
$formatfield = $fieldref;
}
}
// Setting the format separately.
if (!empty($formatfield)) {
// Removing the format field from the TableNode.
$rows = $table->getRows();
$formatvalue = $rowshash[$formatfield];
foreach ($rows as $key => $row) {
if ($row[0] == $formatfield) {
unset($rows[$key]);
}
}
$table->setRows($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.
$steps[] = new Given('I wait until the editors are loaded');
$steps[] = new Given('I select "' . $formatvalue . '" from "' . $formatfield . '"');
$steps[] = new Given('I fill the moodle form with:', $table);
} else {
$steps[] = new Given('I fill the moodle form with:', $table);
}
$steps[] = new Given('I press "' . get_string('savechanges') . '"');
return $steps;
}
/**
@ -181,10 +216,7 @@ class behat_course extends behat_base {
// Ensures the section exists.
$xpath = $this->section_exists($sectionnumber);
return array(
new Given('I click on "' . get_string('markthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"'),
new Given('I wait "2" seconds')
);
return new Given('I click on "' . get_string('markthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"');
}
/**
@ -199,10 +231,7 @@ class behat_course extends behat_base {
// Ensures the section exists.
$xpath = $this->section_exists($sectionnumber);
return array(
new Given('I click on "' . get_string('markedthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"'),
new Given('I wait "2" seconds')
);
return new Given('I click on "' . get_string('markedthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"');
}
/**
@ -215,9 +244,9 @@ class behat_course extends behat_base {
$showlink = $this->show_section_icon_exists($sectionnumber);
$showlink->click();
// It requires time.
if ($this->running_javascript()) {
$this->getSession()->wait(5000, false);
$this->getSession()->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
$this->i_wait_until_section_is_available($sectionnumber);
}
}
@ -231,9 +260,9 @@ class behat_course extends behat_base {
$hidelink = $this->hide_section_icon_exists($sectionnumber);
$hidelink->click();
// It requires time.
if ($this->running_javascript()) {
$this->getSession()->wait(5000, false);
$this->getSession()->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
$this->i_wait_until_section_is_available($sectionnumber);
}
}
@ -314,6 +343,11 @@ class behat_course extends behat_base {
$sectionxpath = $this->section_exists($sectionnumber);
// Preventive in case there is any action in progress.
// Adding it here because we are interacting (click) with
// the elements, not necessary when we just find().
$this->i_wait_until_section_is_available($sectionnumber);
// Section should be hidden.
$exception = new ExpectationException('The section is not hidden', $this->getSession());
$this->find('xpath', $sectionxpath . "[contains(concat(' ', normalize-space(@class), ' '), ' hidden ')]", $exception);
@ -338,9 +372,12 @@ class behat_course extends behat_base {
// Non-JS browsers can not click on img elements.
if ($this->running_javascript()) {
// Expanding the actions menu.
$actionsmenu = $this->find('css', "a[role='menuitem']", false, $activity);
$actionsmenu->click();
// Expanding the actions menu if it is not shown.
$classes = array_flip(explode(' ', $activity->getAttribute('class')));
if (empty($classes['action-menu-shown'])) {
$actionsmenu = $this->find('css', "a[role='menuitem']", false, $activity);
$actionsmenu->click();
}
// To check that the visibility is not clickable we check the funcionality rather than the applied style.
$visibilityiconnode = $this->find('css', 'a.editing_show img', false, $activity);
@ -349,6 +386,17 @@ class behat_course extends behat_base {
// We ensure that we still see the show icon.
$visibilityiconnode = $this->find('css', 'a.editing_show img', $visibilityexception, $activity);
// It is there only when running JS scenarios.
if ($this->running_javascript()) {
// Collapse the actions menu if it is displayed.
$classes = array_flip(explode(' ', $activity->getAttribute('class')));
if (!empty($classes['action-menu-shown'])) {
$actionsmenu = $this->find('css', "a[role='menuitem']", false, $activity);
$actionsmenu->click();
}
}
}
}
@ -543,8 +591,7 @@ class behat_course extends behat_base {
$activity = $this->escape($activityname);
return array(
new Given('I click on "' . get_string('edittitle') . '" "link" in the "' . $activity .'" activity'),
new Given('I fill in "title" with "' . $this->escape($newactivityname) . chr(10) . '"'),
new Given('I wait "2" seconds')
new Given('I fill in "title" with "' . $this->escape($newactivityname) . chr(10) . '"')
);
}
@ -572,6 +619,30 @@ class behat_course extends behat_base {
return new Given('I click on "a[role=\'menuitem\']" "css_element" in the "' . $this->escape($activityname) . '" activity');
}
/**
* Closes an activity actions menu if it is not already closed.
*
* @Given /^I close "(?P<activity_name_string>(?:[^"]|\\")*)" actions menu$/
* @throws DriverException The step is not available when Javascript is disabled
* @param string $activityname
* @return Given
*/
public function i_close_actions_menu($activityname) {
if (!$this->running_javascript()) {
throw new DriverException('Activities actions menu not available when Javascript is disabled');
}
// If it is already closed we do nothing.
$activitynode = $this->get_activity_node($activityname);
$classes = array_flip(explode(' ', $activitynode->getAttribute('class')));
if (empty($classes['action-menu-shown'])) {
return;
}
return new Given('I click on "a[role=\'menuitem\']" "css_element" in the "' . $this->escape($activityname) . '" activity');
}
/**
* Indents to the right the activity or resource specified by it's name. Editing mode should be on.
*
@ -588,10 +659,6 @@ class behat_course extends behat_base {
}
$steps[] = new Given('I click on "' . get_string('moveright') . '" "link" in the "' . $activity . '" activity');
if ($this->running_javascript()) {
$steps[] = new Given('I wait "2" seconds');
}
return $steps;
}
@ -611,10 +678,6 @@ class behat_course extends behat_base {
}
$steps[] = new Given('I click on "' . get_string('moveleft') . '" "link" in the "' . $activity . '" activity');
if ($this->running_javascript()) {
$steps[] = new Given('I wait "2" seconds');
}
return $steps;
}
@ -640,8 +703,6 @@ class behat_course extends behat_base {
$this->getSession()->getDriver()->getWebDriverSession()->accept_alert();
$this->getSession()->wait(2 * 1000, false);
} else {
// With JS disabled.
@ -668,10 +729,7 @@ class behat_course extends behat_base {
$steps[] = new Given('I open "' . $activity . '" actions menu');
}
$steps[] = new Given('I click on "' . get_string('duplicate') . '" "link" in the "' . $activity . '" activity');
if ($this->running_javascript()) {
// Temporary wait until MDL-41030 lands.
$steps[] = new Given('I wait "4" seconds');
} else {
if (!$this->running_javascript()) {
$steps[] = new Given('I press "' . get_string('continue') .'"');
$steps[] = new Given('I press "' . get_string('duplicatecontcourse') .'"');
}
@ -691,12 +749,22 @@ class behat_course extends behat_base {
$steps = array();
$activity = $this->escape($activityname);
$activityliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($activityname);
if ($this->running_javascript()) {
$steps[] = new Given('I duplicate "' . $activity . '" activity');
// We wait until the AJAX request finishes and the section is visible again.
$hiddenlightboxxpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][contains(., $activityliteral)]" .
"/ancestor::li[contains(concat(' ', normalize-space(@class), ' '), ' section ')]" .
"/descendant::div[contains(concat(' ', @class, ' '), ' lightbox ')][contains(@style, 'display: none')]";
$steps[] = new Given('I wait until the page is ready');
$steps[] = new Given('I wait until "' . $this->escape($hiddenlightboxxpath) .'" "xpath_element" exists');
// Close the original activity actions menu.
$steps[] = new Given('I close "' . $activity . '" actions menu');
// Determine the future new activity xpath from the former one.
$activityliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($activityname);
$duplicatedxpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][contains(., $activityliteral)]" .
"/following-sibling::li";
$duplicatedactionsmenuxpath = $duplicatedxpath . "/descendant::a[@role='menuitem']";
@ -717,6 +785,32 @@ class behat_course extends behat_base {
return $steps;
}
/**
* Waits until the section is available to interact with it. Useful when the section is performing an action and the section is overlayed with a loading layout.
*
* Using the protected method as this method will be usually
* called by other methods which are not returning a set of
* steps and performs the actions directly, so it would not
* be executed if it returns another step.
*
* Hopefully we would not require test writers to use this step
* and we will manage it from other step definitions.
*
* @Given /^I wait until section "(?P<section_number>\d+)" is available$/
* @param int $sectionnumber
* @return void
*/
public function i_wait_until_section_is_available($sectionnumber) {
// Looks for a hidden lightbox or a non-existent lightbox in that section.
$sectionxpath = $this->section_exists($sectionnumber);
$hiddenlightboxxpath = $sectionxpath . "/descendant::div[contains(concat(' ', @class, ' '), ' lightbox ')][contains(@style, 'display: none')]" .
" | " .
$sectionxpath . "[count(child::div[contains(@class, 'lightbox')]) = 0]";
$this->ensure_element_exists($hiddenlightboxxpath, 'xpath_element');
}
/**
* Clicks on the specified element of the activity. You should be in the course page with editing mode turned on.
*
@ -882,6 +976,18 @@ class behat_course extends behat_base {
return $this->find('xpath', $xpath);
}
/**
* Gets the activity instance name from the activity node.
*
* @throws ElementNotFoundException
* @param NodeElement $activitynode
* @return string
*/
protected function get_activity_name($activitynode) {
$instancenamenode = $this->find('xpath', "//span[contains(concat(' ', normalize-space(@class), ' '), ' instancename ')]", false, $activitynode);
return $instancenamenode->getText();
}
/**
* Returns whether the user can edit the course contents or not.
*

View file

@ -1,4 +1,4 @@
@core @core_course @test
@core @core_course
Feature: Course category management interface performs as expected
In order to test JS enhanced display of categories and subcategories.
As a moodle admin

View file

@ -1,4 +1,4 @@
@core @core_course
@core @core_course @_alerts
Feature: Course activity controls works as expected
In order to manage my course's activities
As a teacher
@ -59,11 +59,16 @@ Feature: Course activity controls works as expected
And I click on "Edit settings" "link" in the "Test forum name 1" activity
And I should see "Updating Forum"
And I should see "Display description on course page"
And I press "Save and return to course"
And I fill the moodle form with:
| Forum name | Just to check that I can edit the name |
| Description | Just to check that I can edit the description |
| Display description on course page | 1 |
And I click on "Cancel" "button"
And "#section-2" "css_element" <should_see_other_sections> exists
And I open "Test forum name 1" actions menu
And I click on "Hide" "link" in the "Test forum name 1" activity
And "#section-2" "css_element" <should_see_other_sections> exists
And I close "Test forum name 1" actions menu
And I duplicate "Test forum name 2" activity editing the new copy with:
| Forum name | Edited test forum name 2 |
And "#section-2" "css_element" <should_see_other_sections> exists