diff --git a/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php b/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php new file mode 100644 index 00000000000..18579cbf806 --- /dev/null +++ b/mod/workshop/allocation/manual/tests/behat/behat_workshopallocation_manual.php @@ -0,0 +1,114 @@ +. + +/** + * Steps definitions related to workshopallocation_manual. + * + * @package workshopallocation_manual + * @category test + * @copyright 2014 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. + +require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php'); +require_once(__DIR__ . '/../../../../../../lib/behat/behat_field_manager.php'); + +use Behat\Behat\Context\Step\Given as Given, + Behat\Gherkin\Node\TableNode as TableNode, + Behat\Mink\Exception\ElementTextException as ElementTextException; + +/** + * Steps definitions related to workshopallocation_manual. + * + * @package workshopallocation_manual + * @category test + * @copyright 2014 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_workshopallocation_manual extends behat_base { + /** + * Manually adds a reviewer for workshop participant. + * + * This step should start on manual allocation page. + * + * @When /^I add a reviewer "(?P(?:[^"]|\\")*)" for workshop participant "(?P(?:[^"]|\\")*)"$/ + * @param string $reviewername + * @param string $participantname + */ + public function i_add_a_reviewer_for_workshop_participant($reviewername, $participantname) { + $participantnameliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($participantname); + $xpathtd = "//table[contains(concat(' ', normalize-space(@class), ' '), ' allocations ')]/". + "tbody/tr[./td[contains(concat(' ', normalize-space(@class), ' '), ' peer ')]". + "[contains(.,$participantnameliteral)]]/". + "td[contains(concat(' ', normalize-space(@class), ' '), ' reviewedby ')]"; + $xpathselect = $xpathtd . "/descendant::select"; + try { + $selectnode = $this->find('xpath', $xpathselect); + } catch (Exception $ex) { + $this->find_button(get_string('showallparticipants', 'workshopallocation_manual'))->press(); + $selectnode = $this->find('xpath', $xpathselect); + } + $selectid = $selectnode->getAttribute('id'); + $selectformfield = behat_field_manager::get_form_field($selectnode, $this->getSession()); + $selectformfield->set_value($reviewername); + + if (!$this->running_javascript()) { + // Without Javascript we need to press the "Go" button. + $go = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('go')); + $this->find('xpath', $xpathtd."/descendant::input[@value=$go]")->click(); + } else { + // With Javascript we just wait for the page to reload and the success string to appear. + $allocatedtext = $this->getSession()->getSelectorsHandler()->xpathLiteral( + get_string('allocationadded', 'workshopallocation_manual')); + $this->find('xpath', "//*[contains(.,$allocatedtext)]"); + } + } + + /** + * Manually allocates multiple reviewers in workshop. + * + * @When /^I allocate submissions in workshop "(?P(?:[^"]|\\")*)" as:"$/ + * @param string $workshopname + * @param TableNode $table should have one column with title 'Reviewer' and another with title 'Participant' (or 'Reviewee') + */ + public function i_allocate_submissions_in_workshop_as($workshopname, TableNode $table) { + + $this->find_link($workshopname)->click(); + $this->find_link(get_string('allocate', 'workshop'))->click(); + $rows = $table->getRows(); + $reviewer = $participant = null; + for ($i = 0; $i < count($rows[0]); $i++) { + if (strtolower($rows[0][$i]) === 'reviewer') { + $reviewer = $i; + } else if (strtolower($rows[0][$i]) === 'reviewee' || strtolower($rows[0][$i]) === 'participant') { + $participant = $i; + } else { + throw new ElementTextException('Unrecognised column "'.$rows[0][$i].'"', $this->getSession()); + } + } + if ($reviewer === null) { + throw new ElementTextException('Column "Reviewer" could not be located', $this->getSession()); + } + if ($participant === null) { + throw new ElementTextException('Neither "Participant" nor "Reviewee" column could be located', $this->getSession()); + } + for ($i = 1; $i < count($rows); $i++) { + $this->i_add_a_reviewer_for_workshop_participant($rows[$i][$reviewer], $rows[$i][$participant]); + } + } +} diff --git a/mod/workshop/tests/behat/behat_mod_workshop.php b/mod/workshop/tests/behat/behat_mod_workshop.php new file mode 100644 index 00000000000..63c69976084 --- /dev/null +++ b/mod/workshop/tests/behat/behat_mod_workshop.php @@ -0,0 +1,155 @@ +. + +/** + * Steps definitions related to mod_workshop. + * + * @package mod_workshop + * @category test + * @copyright 2014 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. + +require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); + +use Behat\Behat\Context\Step\Given as Given, + Behat\Gherkin\Node\TableNode as TableNode; + +/** + * Steps definitions related to mod_workshop. + * + * @package mod_workshop + * @category test + * @copyright 2014 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_mod_workshop extends behat_base { + /** + * Changes the submission phase for the workshop. + * + * @When /^I change phase in workshop "(?P(?:[^"]|\\")*)" to "(?P(?:[^"]|\\")*)"$/ + * @param string $questiontype + * @param string $workshopname + */ + public function i_change_phase_in_workshop_to($workshopname, $phase) { + $workshopname = $this->escape($workshopname); + $phaseliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($phase); + $switchphase = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('switchphase', 'workshop')); + + $xpath = "//*[@class='userplan']/descendant::div[./span[contains(.,$phaseliteral)]]/". + "descendant-or-self::a[./img[@alt=$switchphase]]"; + $continue = $this->escape(get_string('continue')); + return array( + new Given("I follow \"$workshopname\""), + new Given("I click on \"$xpath\" \"xpath_element\""), + new Given("I press \"$continue\""), + ); + } + + /** + * Adds or edits a student workshop submission. + * + * @When /^I add a submission in workshop "(?P(?:[^"]|\\")*)" as:"$/ + * @param string $workshopname + * @param TableNode $table data to fill the submission form with, must contain 'Title' + */ + public function i_add_a_submission_in_workshop_as($workshopname, $table) { + $workshopname = $this->escape($workshopname); + $savechanges = $this->escape(get_string('savechanges')); + $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' ownsubmission ')]/descendant::input[@type='submit']"; + return array( + new Given("I follow \"$workshopname\""), + new Given("I click on \"$xpath\" \"xpath_element\""), + new Given("I fill the moodle form with:", $table), + new Given("I press \"$savechanges\""), + ); + } + + /** + * Sets the workshop assessment form. + * + * @When /^I edit assessment form in workshop "(?P(?:[^"]|\\")*)" as:"$/ + * @param string $workshopname + * @param TableNode $table data to fill the submission form with, must contain 'Title' + */ + public function i_edit_assessment_form_in_workshop_as($workshopname, $table) { + $workshopname = $this->escape($workshopname); + $editassessmentform = $this->escape(get_string('editassessmentform', 'workshop')); + $saveandclose = $this->escape(get_string('saveandclose', 'workshop')); + return array( + new Given("I follow \"$workshopname\""), + new Given("I follow \"$editassessmentform\""), + new Given("I fill the moodle form with:", $table), + new Given("I press \"$saveandclose\""), + ); + } + + /** + * Peer-assesses a workshop submission. + * + * @When /^I assess submission "(?P(?:[^"]|\\")*)" in workshop "(?P(?:[^"]|\\")*)" as:"$/ + * @param string $submission + * @param string $workshopname + * @param TableNode $table + */ + public function i_assess_submission_in_workshop_as($submission, $workshopname, TableNode $table) { + $workshopname = $this->escape($workshopname); + $submissionliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($submission); + $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' assessment-summary ') ". + "and contains(.,$submissionliteral)]"; + $assess = $this->escape(get_string('assess', 'workshop')); + $saveandclose = $this->escape(get_string('saveandclose', 'workshop')); + return array( + new Given("I follow \"$workshopname\""), + new Given("I click on \"$assess\" \"button\" in the \"$xpath\" \"xpath_element\""), + new Given("I fill the moodle form with:", $table), + new Given("I press \"$saveandclose\""), + ); + } + + /** + * Checks that the user has particular grade set by his reviewing peer in workshop + * + * @Then /^I should see grade "(?P[^"]*)" for workshop participant "(?P(?:[^"]|\\")*)" set by peer "(?P(?:[^"]|\\")*)"$/ + * @param string $grade + * @param string $participant + * @param string $reviewer + */ + public function i_should_see_grade_for_workshop_participant_set_by_peer($grade, $participant, $reviewer) { + $participantliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($participant); + $reviewerliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($reviewer); + $gradeliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($grade); + $participantselector = "contains(concat(' ', normalize-space(@class), ' '), ' participant ') ". + "and contains(.,$participantliteral)"; + $trxpath = "//table/tbody/tr[td[$participantselector]]"; + $tdparticipantxpath = "//table/tbody/tr/td[$participantselector]"; + $tdxpath = "/td[contains(concat(' ', normalize-space(@class), ' '), ' receivedgrade ') and contains(.,$reviewerliteral)]/". + "descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' grade ') and .=$gradeliteral]"; + + $tr = $this->find('xpath', $trxpath); + $rowspan = $this->find('xpath', $tdparticipantxpath)->getAttribute('rowspan'); + + $xpath = $trxpath.$tdxpath; + if (!empty($rowspan)) { + for ($i = 1; $i < $rowspan; $i++) { + $xpath .= ' | '.$trxpath."/following-sibling::tr[$i]".$tdxpath; + } + } + $this->find('xpath', $xpath); + } +} diff --git a/mod/workshop/tests/behat/workshop_assessment.feature b/mod/workshop/tests/behat/workshop_assessment.feature new file mode 100644 index 00000000000..55b1c8d6228 --- /dev/null +++ b/mod/workshop/tests/behat/workshop_assessment.feature @@ -0,0 +1,154 @@ +@mod @mod_workshop +Feature: Workshop submission and assessment + In order to use workshop activity + As a student + I need to be able to add a submission and assess those of my peers + + Background: + Given the following "users" exists: + | username | firstname | lastname | email | + | student1 | Sam1 | Student1 | student1@asd.com | + | student2 | Sam2 | Student2 | student2@asd.com | + | student3 | Sam3 | Student3 | student3@asd.com | + | student4 | Sam4 | Student4 | student3@asd.com | + | teacher1 | Terry1 | Teacher1 | teacher1@asd.com | + And the following "courses" exists: + | fullname | shortname | + | Course1 | c1 | + And the following "course enrolments" exists: + | user | course | role | + | student1 | c1 | student | + | student2 | c1 | student | + | student3 | c1 | student | + | student4 | c1 | student | + | teacher1 | c1 | editingteacher | + And the following "activities" exists: + | activity | name | intro | course | idnumber | + | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | +# teacher1 sets up assessment form and changes the phase to submission + When I log in as "teacher1" + And I follow "Course1" + And I edit assessment form in workshop "TestWorkshop" as:" + | id_description__idx_0_editor | Aspect1 | + | id_description__idx_1_editor | Aspect2 | + | id_description__idx_2_editor | | + And I change phase in workshop "TestWorkshop" to "Submission phase" + And I log out +# student1 submits + And I log in as "student1" + And I follow "Course1" + And I follow "TestWorkshop" + Then I should see "Submit your work" + And I add a submission in workshop "TestWorkshop" as:" + | Title | Submission1 | + | Submission content | Some content | + And "//div[@class='submission-full' and contains(.,'Submission1') and contains(.,'submitted on')]" "xpath_element" should exists + And I log out +# student2 submits + And I log in as "student2" + And I follow "Course1" + And I add a submission in workshop "TestWorkshop" as:" + | Title | Submission2 | + | Submission content | Some content | + And I log out +# student3 submits + And I log in as "student3" + And I follow "Course1" + And I add a submission in workshop "TestWorkshop" as:" + | Title | Submission3 | + | Submission content | Some content | + And I log out +# teacher1 allocates reviewers and changes the phase to assessment + And I log in as "teacher1" + And I follow "Course1" + And I follow "TestWorkshop" + And I should see "to allocate: 3" + And I should see "There is at least one author who has not yet submitted their work" + And I should see "All submissions (3)" + And I should see "Submission1" + And I should see "Submission2" + And I should see "Submission3" + And I allocate submissions in workshop "TestWorkshop" as:" + | Participant | Reviewer | + | Sam1 Student1 | Sam2 Student2 | + | Sam2 Student2 | Sam1 Student1 | + | Sam3 Student3 | Sam1 Student1 | + | Sam2 Student2 | Sam4 Student4 | + And I follow "TestWorkshop" + And I should see "to allocate: 0" + And I change phase in workshop "TestWorkshop" to "Assessment phase" + And I log out +# student1 assesses work of student2 and student3 + And I log in as "student1" + And I follow "Course1" + And I follow "TestWorkshop" + And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 2') and contains(.,'total: 2')]" "xpath_element" should exists + And I assess submission "Sam2" in workshop "TestWorkshop" as:" + | grade__idx_0 | 5 / 10 | + | peercomment__idx_0 | You can do better | + | grade__idx_1 | 10 / 10 | + | peercomment__idx_1 | Amazing | + | Feedback for the author | Good work | + And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 1') and contains(.,'total: 2')]" "xpath_element" should exists + And I follow "Course1" + And I assess submission "Sam3" in workshop "TestWorkshop" as:" + | grade__idx_0 | 9 / 10 | + | peercomment__idx_0 | Well done | + | grade__idx_1 | 8 / 10 | + | peercomment__idx_1 | Very good | + | Feedback for the author | No comments | + And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 0') and contains(.,'total: 2')]" "xpath_element" should exists + And I log out +# student2 assesses work of student1 + And I log in as "student2" + And I follow "Course1" + And I follow "TestWorkshop" + And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 1') and contains(.,'total: 1')]" "xpath_element" should exists + And I assess submission "Sam1" in workshop "TestWorkshop" as:" + | grade__idx_0 | 6 / 10 | + | peercomment__idx_0 | | + | grade__idx_1 | 7 / 10 | + | peercomment__idx_1 | | + | Feedback for the author | Keep it up | + And "//ul[@class='tasks']/li[div[@class='title' and contains(.,'Assess peers')]]/div[@class='details' and contains(.,'pending: 0') and contains(.,'total: 1')]" "xpath_element" should exists + And I log out +# teacher1 makes sure he can see all peer grades + And I log in as "teacher1" + And I follow "Course1" + And I follow "TestWorkshop" + And I should see grade "52" for workshop participant "Sam1" set by peer "Sam2" + And I should see grade "60" for workshop participant "Sam2" set by peer "Sam1" + And I should see grade "-" for workshop participant "Sam2" set by peer "Sam4" + And I should see "No submission found for this user" in the "//table/tbody/tr[td[contains(concat(' ', normalize-space(@class), ' '), ' participant ') and contains(.,'Sam4')]]" "xpath_element" + And I should see grade "68" for workshop participant "Sam3" set by peer "Sam1" + And I click on "//table/tbody/tr[td[contains(concat(' ', normalize-space(@class), ' '), ' participant ') and contains(.,'Sam2')]]/td[contains(concat(' ', normalize-space(@class), ' '), ' receivedgrade ') and contains(.,'Sam1')]/descendant::a[@class='grade']" "xpath_element" + And I should see "5 / 10" in the "//fieldset[contains(.,'Aspect1')]" "xpath_element" + And I should see "You can do better" in the "//fieldset[contains(.,'Aspect1')]" "xpath_element" + And I should see "10 / 10" in the "//fieldset[contains(.,'Aspect2')]" "xpath_element" + And I should see "Amazing" in the "//fieldset[contains(.,'Aspect2')]" "xpath_element" + And I should see "Good work" in the ".overallfeedback" "css_element" +# teacher1 assesses the work on submission1 and assesses the assessment of peer + And I fill the moodle form with: + | Override grade for assessment | 11 | + | Feedback for the reviewer | | + And I press "Save and close" + And I change phase in workshop "TestWorkshop" to "Grading evaluation phase" + And I follow "Submission1" + And I should see "Grade: 52 of 80" in the "//div[contains(concat(' ', normalize-space(@class), ' '), ' assessment-full ') and contains(.,'Sam2')]" "xpath_element" + And I press "Assess" + And I fill the moodle form with: + | grade__idx_0 | 1 / 10 | + | peercomment__idx_0 | Extremely bad | + | grade__idx_1 | 2 / 10 | + | peercomment__idx_1 | Very bad | + | Feedback for the author | Your peers overestimate you | + And I press "Save and close" + And I press "Re-calculate grades" + And I should see "32" in the "//table/tbody/tr[td[contains(concat(' ', normalize-space(@class), ' '), ' participant ') and contains(.,'Sam1')]]/td[contains(concat(' ', normalize-space(@class), ' '), ' submissiongrade ')]" "xpath_element" + And I should see "16" in the "//table/tbody/tr[td[contains(concat(' ', normalize-space(@class), ' '), ' participant ') and contains(.,'Sam1')]]/td[contains(concat(' ', normalize-space(@class), ' '), ' gradinggrade ')]" "xpath_element" + And I log out + + @javascript + Scenario: Add and assess submissions in workshop with javascript enabled + + Scenario: Add and assess submissions in workshop with javascript disabled