first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,166 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign\backup;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/phpunit/classes/restore_date_testcase.php');
require_once($CFG->dirroot . '/mod/assign/tests/fixtures/testable_assign.php');
/**
* Restore date tests.
*
* @package mod_assign
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_date_test extends \restore_date_testcase {
/**
* Test restore dates.
*/
public function test_restore_dates(): void {
global $DB, $USER;
$record = ['cutoffdate' => 100, 'allowsubmissionsfromdate' => 100, 'duedate' => 100, 'timemodified' => 100];
list($course, $assign) = $this->create_course_and_module('assign', $record);
$cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $assign->id]);
$assignobj = new \mod_assign_testable_assign(\context_module::instance($cm->id), $cm, $course);
$submission = $assignobj->get_user_submission($USER->id, true);
$grade = $assignobj->get_user_grade($USER->id, true);
// User override.
$override = (object)[
'assignid' => $assign->id,
'groupid' => 0,
'userid' => $USER->id,
'sortorder' => 1,
'allowsubmissionsfromdate' => 100,
'duedate' => 200,
'cutoffdate' => 300
];
$DB->insert_record('assign_overrides', $override);
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course);
$newassign = $DB->get_record('assign', ['course' => $newcourseid]);
$this->assertFieldsNotRolledForward($assign, $newassign, ['timemodified']);
$props = ['allowsubmissionsfromdate', 'duedate', 'cutoffdate'];
$this->assertFieldsRolledForward($assign, $newassign, $props);
$newsubmission = $DB->get_record('assign_submission', ['assignment' => $newassign->id]);
$newoverride = $DB->get_record('assign_overrides', ['assignid' => $newassign->id]);
$newgrade = $DB->get_record('assign_grades', ['assignment' => $newassign->id]);
// Assign submission time checks.
$this->assertEquals($submission->timecreated, $newsubmission->timecreated);
$this->assertEquals($submission->timemodified, $newsubmission->timemodified);
// Assign override time checks.
$diff = $this->get_diff();
$this->assertEquals($override->duedate + $diff, $newoverride->duedate);
$this->assertEquals($override->cutoffdate + $diff, $newoverride->cutoffdate);
$this->assertEquals($override->allowsubmissionsfromdate + $diff, $newoverride->allowsubmissionsfromdate);
// Assign grade time checks.
$this->assertEquals($grade->timecreated, $newgrade->timecreated);
$this->assertEquals($grade->timemodified, $newgrade->timemodified);
}
/**
* Test backup and restore of an assignment with non-default settings.
*/
public function test_restore_settings(): void {
global $DB;
$generator = $this->getDataGenerator();
$course = $generator->create_course(['startdate' => $this->startdate]);
$record = [
'course' => $course->id,
'name' => random_string(),
'intro' => random_string(),
'introformat' => FORMAT_MARKDOWN,
'alwaysshowdescription' => 1,
'submissiondrafts' => 1,
'sendnotifications' => 1,
'sendlatenotifications' => 1,
'sendstudentnotifications' => 0,
'duedate' => time() + 1,
'cutoffdate' => time(),
'gradingduedate' => time() + 2,
'allowsubmissionsfromdate' => time() - 1,
'grade' => 10,
'timemodified' => 100,
'completionsubmit' => 1,
'requiresubmissionstatement' => 1,
'teamsubmission' => 1,
'requireallteammemberssubmit' => 1,
'teamsubmissiongroupingid' => $generator->create_grouping(['courseid' => $course->id])->id,
'blindmarking' => 1,
'hidegrader' => 1,
'revealidentities' => 1,
'attemptreopenmethod' => 'manual',
'maxattempts' => 2,
'markingworkflow' => 1,
'markingallocation' => 1,
'markinganonymous' => 1,
'preventsubmissionnotingroup' => 1,
'activityeditor' => [
'text' => random_string(),
'format' => FORMAT_MARKDOWN,
],
'timelimit' => DAYSECS,
'submissionattachments' => 1,
];
$assign = $this->getDataGenerator()->create_module('assign', $record);
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course, $this->startdate);
$newassign = $DB->get_record('assign', ['course' => $newcourseid]);
$newgrouping = $DB->get_record('groupings', ['courseid' => $newcourseid]);
// Verify that the settings of the restored assignment are correct.
foreach ($record as $setting => $value) {
$newsetting = $newassign->{$setting} ?? null;
switch ($setting) {
case 'course':
// Should match the new course.
$this->assertEquals($newcourseid, $newsetting);
break;
case 'teamsubmissiongroupingid':
// Should match the new grouping.
$this->assertEquals($newgrouping->id, $newsetting);
break;
case 'revealidentities':
// Reset to default for a restore without user data.
$this->assertEquals(0, $newsetting);
break;
case 'activityeditor':
$this->assertEquals($value['text'], $newassign->activity);
$this->assertEquals($value['format'], $newassign->activityformat);
break;
case 'timemodified':
$this->assertFieldsNotRolledForward($assign, $newassign, ['timemodified']);
break;
default:
// All other settings should match the original assignment.
$this->assertEquals($value, $newsetting, "Failed for '{$setting}'");
}
}
}
}
+219
View File
@@ -0,0 +1,219 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use mod_assign_testable_assign;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
require_once(__DIR__ . '/fixtures/testable_assign.php');
/**
* Unit tests for (some of) mod/assign/locallib.php.
*
* @package mod_assign
* @category test
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class base_test extends \advanced_testcase {
/** @var Default number of students to create */
const DEFAULT_STUDENT_COUNT = 3;
/** @var Default number of teachers to create */
const DEFAULT_TEACHER_COUNT = 2;
/** @var Default number of editing teachers to create */
const DEFAULT_EDITING_TEACHER_COUNT = 2;
/** @var Optional extra number of students to create */
const EXTRA_STUDENT_COUNT = 40;
/** @var Optional number of suspended students */
const EXTRA_SUSPENDED_COUNT = 10;
/** @var Optional extra number of teachers to create */
const EXTRA_TEACHER_COUNT = 5;
/** @var Optional extra number of editing teachers to create */
const EXTRA_EDITING_TEACHER_COUNT = 5;
/** @var Number of groups to create */
const GROUP_COUNT = 6;
/** @var \stdClass $course New course created to hold the assignments */
protected $course = null;
/** @var array $teachers List of DEFAULT_TEACHER_COUNT teachers in the course*/
protected $teachers = null;
/** @var array $editingteachers List of DEFAULT_EDITING_TEACHER_COUNT editing teachers in the course */
protected $editingteachers = null;
/** @var array $students List of DEFAULT_STUDENT_COUNT students in the course*/
protected $students = null;
/** @var array $extrateachers List of EXTRA_TEACHER_COUNT teachers in the course*/
protected $extrateachers = null;
/** @var array $extraeditingteachers List of EXTRA_EDITING_TEACHER_COUNT editing teachers in the course*/
protected $extraeditingteachers = null;
/** @var array $extrastudents List of EXTRA_STUDENT_COUNT students in the course*/
protected $extrastudents = null;
/** @var array $extrasuspendedstudents List of EXTRA_SUSPENDED_COUNT students in the course*/
protected $extrasuspendedstudents = null;
/** @var array $groups List of 10 groups in the course */
protected $groups = null;
/**
* Setup function - we will create a course and add an assign instance to it.
*/
protected function setUp(): void {
global $DB;
$this->resetAfterTest(true);
$this->course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$this->teachers = array();
for ($i = 0; $i < self::DEFAULT_TEACHER_COUNT; $i++) {
array_push($this->teachers, $this->getDataGenerator()->create_user());
}
$this->editingteachers = array();
for ($i = 0; $i < self::DEFAULT_EDITING_TEACHER_COUNT; $i++) {
array_push($this->editingteachers, $this->getDataGenerator()->create_user());
}
$this->students = array();
for ($i = 0; $i < self::DEFAULT_STUDENT_COUNT; $i++) {
array_push($this->students, $this->getDataGenerator()->create_user());
}
$this->groups = array();
for ($i = 0; $i < self::GROUP_COUNT; $i++) {
array_push($this->groups, $this->getDataGenerator()->create_group(array('courseid'=>$this->course->id)));
}
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
foreach ($this->teachers as $i => $teacher) {
$this->getDataGenerator()->enrol_user($teacher->id,
$this->course->id,
$teacherrole->id);
groups_add_member($this->groups[$i % self::GROUP_COUNT], $teacher);
}
$editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
foreach ($this->editingteachers as $i => $editingteacher) {
$this->getDataGenerator()->enrol_user($editingteacher->id,
$this->course->id,
$editingteacherrole->id);
groups_add_member($this->groups[$i % self::GROUP_COUNT], $editingteacher);
}
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
foreach ($this->students as $i => $student) {
$this->getDataGenerator()->enrol_user($student->id,
$this->course->id,
$studentrole->id);
groups_add_member($this->groups[$i % self::GROUP_COUNT], $student);
}
}
/*
* For tests that make sense to use alot of data, create extra students/teachers.
*/
protected function create_extra_users() {
global $DB;
$this->extrateachers = array();
for ($i = 0; $i < self::EXTRA_TEACHER_COUNT; $i++) {
array_push($this->extrateachers, $this->getDataGenerator()->create_user());
}
$this->extraeditingteachers = array();
for ($i = 0; $i < self::EXTRA_EDITING_TEACHER_COUNT; $i++) {
array_push($this->extraeditingteachers, $this->getDataGenerator()->create_user());
}
$this->extrastudents = array();
for ($i = 0; $i < self::EXTRA_STUDENT_COUNT; $i++) {
array_push($this->extrastudents, $this->getDataGenerator()->create_user());
}
$this->extrasuspendedstudents = array();
for ($i = 0; $i < self::EXTRA_SUSPENDED_COUNT; $i++) {
array_push($this->extrasuspendedstudents, $this->getDataGenerator()->create_user());
}
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
foreach ($this->extrateachers as $i => $teacher) {
$this->getDataGenerator()->enrol_user($teacher->id,
$this->course->id,
$teacherrole->id);
groups_add_member($this->groups[$i % self::GROUP_COUNT], $teacher);
}
$editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
foreach ($this->extraeditingteachers as $i => $editingteacher) {
$this->getDataGenerator()->enrol_user($editingteacher->id,
$this->course->id,
$editingteacherrole->id);
groups_add_member($this->groups[$i % self::GROUP_COUNT], $editingteacher);
}
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
foreach ($this->extrastudents as $i => $student) {
$this->getDataGenerator()->enrol_user($student->id,
$this->course->id,
$studentrole->id);
if ($i < (self::EXTRA_STUDENT_COUNT / 2)) {
groups_add_member($this->groups[$i % self::GROUP_COUNT], $student);
}
}
foreach ($this->extrasuspendedstudents as $i => $suspendedstudent) {
$this->getDataGenerator()->enrol_user($suspendedstudent->id,
$this->course->id,
$studentrole->id, 'manual', 0, 0, ENROL_USER_SUSPENDED);
if ($i < (self::EXTRA_SUSPENDED_COUNT / 2)) {
groups_add_member($this->groups[$i % self::GROUP_COUNT], $suspendedstudent);
}
}
}
/**
* Convenience function to create a testable instance of an assignment.
*
* @param array $params Array of parameters to pass to the generator
* @return testable_assign Testable wrapper around the assign class.
*/
protected function create_instance($params=array()) {
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
if (!isset($params['course'])) {
$params['course'] = $this->course->id;
}
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
return new mod_assign_testable_assign($context, $cm, $this->course);
}
public function test_create_instance(): void {
$this->assertNotEmpty($this->create_instance());
}
}
class_alias('mod_assign_testable_assign', 'testable_assign');
@@ -0,0 +1,150 @@
@mod @mod_assign
Feature: In an assignment, students start a new attempt based on their previous one
In order to improve my submission
As a student
I need to submit my assignment editing an online form, receive feedback, and then improve my submission.
@javascript
Scenario: Submit a text online and edit the submission
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| attemptreopenmethod | manual |
| hidegrader | 1 |
| submissiondrafts | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student first submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Allow another attempt | 1 |
And I press "Save changes"
And I click on "Edit settings" "link"
And I log out
When I am on the "Test assignment name" Activity page logged in as student1
Then I should not see "Teacher 1"
And I press "Add a new attempt based on previous submission"
And I press "Save changes"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should see "I'm the student first submission"
@javascript @_alert
Scenario: Allow new attempt does not display incorrect error message on group submission
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
| student4 | Student | 4 | student4@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
| student3 | G2 |
| student4 | G2 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| attemptreopenmethod | manual |
| submissiondrafts | 0 |
| groupmode | 1 |
| teamsubmission | 1 |
| hidegrader | 1 |
| maxattempts | 3 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student first submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
Then "Student 1" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 2" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 3" row "Status" column of "generaltable" table should contain "No submission"
And "Student 4" row "Status" column of "generaltable" table should contain "No submission"
And I click on "Quick grading" "checkbox"
And I click on "Student 1" "checkbox"
And I set the field "User grade" to "60.0"
And I press "Save all quick grading changes"
And I should see "The grade changes were saved"
And I press "Continue"
And I click on "Student 1" "checkbox"
And I set the following fields to these values:
| operation | Allow another attempt |
And I click on "Go" "button" confirming the dialogue
And I should not see "The grades were not saved because someone has modified one or more records more recently than when you loaded the page."
And I log out
And I am on the "Test assignment name" Activity page logged in as student3
And I should see "This is attempt 1 ( 3 attempts allowed )."
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student's 3 group 2 first attempt |
And I press "Save changes"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And "Student 1" row "Status" column of "generaltable" table should contain "Reopened"
And "Student 2" row "Status" column of "generaltable" table should contain "Reopened"
And "Student 3" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 4" row "Status" column of "generaltable" table should contain "Submitted for grading"
And I click on "Grade" "link" in the "Student 3" "table_row"
And I set the following fields to these values:
| Allow another attempt | 1 |
And I press "Save changes"
And I follow "Assignment: Test assignment name"
And I log out
And I am on the "Test assignment name" Activity page logged in as student4
And I should see "This is attempt 2 ( 3 attempts allowed )."
And I press "Add a new attempt"
And I set the following fields to these values:
| Online text | I'm the student's 4 group 2 second attempt |
And I press "Save changes"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I select "Group 2" from the "group" singleselect
And I click on "Grade" "link" in the ".tertiary-navigation" "css_element"
And I should see "2" in the "#id_attemptsettings" "css_element"
@@ -0,0 +1,158 @@
@mod @mod_assign @core_completion
Feature: View activity completion in the assignment activity
In order to have visibility of assignment completion requirements
As a student
I need to be able to view my assignment completion progress
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Vinnie | Student1 | student1@example.com |
| teacher1 | Darrell | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | enablecompletion | showcompletionconditions |
| Course 1 | C1 | 1 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| idnumber | mh1 |
| name | Music history |
| section | 1 |
| completion | 1 |
| grade[modgrade_type] | point |
| grade[modgrade_point] | 100 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| idnumber | mh2 |
| name | Music history 2 |
| section | 1 |
| assignsubmission_onlinetext_enabled | 1 |
| attemptreopenmethod | manual |
| maxattempts | -1 |
| completion | 2 |
| completionsubmit | 1 |
| grade[modgrade_type] | point |
| grade[modgrade_point] | 100 |
@javascript
Scenario: The manual completion button will be shown on the course page if the Show activity completion conditions is set to Yes
Given I am on the "Course 1" course page logged in as teacher1
# Teacher view.
And "Music history" should have the "Mark as done" completion condition
And I log out
# Student view.
When I log in as "student1"
And I am on "Course 1" course homepage
Then the manual completion button for "Music history" should exist
And the manual completion button of "Music history" is displayed as "Mark as done"
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
@javascript
Scenario: The manual completion button will not be shown on the course page if the Show activity completion conditions is set to No
Given I am on the "Course 1" course page logged in as teacher1
And I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Show activity completion conditions" to "No"
And I press "Save and display"
# Teacher view.
And "Completion" "button" should not exist in the "Music history" "activity"
And I log out
# Student view.
When I am on the "Course 1" course page logged in as "student1"
Then the manual completion button for "Music history" should not exist
And I am on the "Music history" "assign activity" page
And the manual completion button for "Music history" should exist
@javascript
Scenario: Use manual completion from the activity page
Given I am on the "Music history" "assign activity" page logged in as teacher1
# Teacher view.
And the manual completion button for "Music history" should be disabled
And I log out
# Student view.
And I am on the "Music history" "assign activity" page logged in as student1
Then the manual completion button of "Music history" is displayed as "Mark as done"
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
Scenario: View automatic completion items as a teacher
Given I am on the "Music history" "assign activity editing" page logged in as teacher1
And I expand all fieldsets
And I set the following fields to these values:
| Add requirements | 1 |
| View the activity | 1 |
| completionusegrade | 1 |
| completionsubmit | 1 |
And I press "Save and display"
Then "Music history" should have the "View" completion condition
And "Music history" should have the "Make a submission" completion condition
And "Music history" should have the "Receive a grade" completion condition
@javascript
Scenario: View automatic completion items as a student
Given I am on the "Music history" "assign activity editing" page logged in as teacher1
And I expand all fieldsets
And I set the following fields to these values:
| assignsubmission_onlinetext_enabled | 1 |
| Add requirements | 1 |
| View the activity | 1 |
| completionusegrade | 1 |
| completionsubmit | 1 |
And I press "Save and display"
And I log out
And I am on the "Music history" "assign activity" page logged in as student1
And the "View" completion condition of "Music history" is displayed as "done"
And the "Make a submission" completion condition of "Music history" is displayed as "todo"
And the "Receive a grade" completion condition of "Music history" is displayed as "todo"
And I am on the "Music history" "assign activity" page
And I press "Add submission"
And I set the field "Online text" to "History of playing with drumsticks reversed"
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And the "View" completion condition of "Music history" is displayed as "done"
And the "Make a submission" completion condition of "Music history" is displayed as "done"
And the "Receive a grade" completion condition of "Music history" is displayed as "todo"
And I log out
And I am on the "Music history" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Vinnie Student1" "table_row"
And I set the field "Grade out of 100" to "33"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I follow "View all submissions"
And I log out
When I am on the "Music history" "assign activity" page logged in as student1
Then the "View" completion condition of "Music history" is displayed as "done"
And the "Make a submission" completion condition of "Music history" is displayed as "done"
And the "Receive a grade" completion condition of "Music history" is displayed as "done"
@javascript
Scenario: Automatic completion items should reset when a new attempt is manually given.
Given I am on the "Music history 2" "assign activity" page logged in as student1
And the "Make a submission" completion condition of "Music history 2" is displayed as "todo"
And I press "Add submission"
And I set the field "Online text" to "History of playing with drumsticks reversed"
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And the "Make a submission" completion condition of "Music history 2" is displayed as "done"
And I log out
And I am on the "Music history 2" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Vinnie Student1" "table_row"
And I set the field "Grade out of 100" to "33"
And I set the field "Notify student" to "0"
And I set the field "Allow another attempt" to "Yes"
And I press "Save changes"
And I log out
When I am on the "Music history 2" "assign activity" page logged in as student1
And I should see "Reopened"
And "Add a new attempt based on previous submission" "button" should exist
Then the "Make a submission" completion condition of "Music history 2" is displayed as "todo"
@@ -0,0 +1,46 @@
@mod @mod_assign
Feature: Teacher can enable anonymous submissions for an assignment
In order to make an anonymous submission to an assignment
As a teacher
I should be able to enable anonymous submissions
Background:
Given the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | One | teacher1@example.com |
| student1 | Student | One | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled | blindmarking |
| assign | C1 | Assign 1 | 1 | 1 |
@javascript
Scenario: Teacher can enable anonymous submissions
# Submit an assignment as student1
Given the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Assign 1 | student1 | I'm the student's first submission |
When I am on the "Assign 1" "assign activity editing" page logged in as teacher1
# Confirm that anonymous submissions can't be changed to no anymore
Then "blindmarking" "select" should not exist
And I press "Cancel"
And I am on the "Assign 1" "assign activity" page
And I click on "View all submissions" "link"
# Confirm that Participant [n] is displayed instead of Student One - student name is hidden
And I should not see "Student One" in the "Participant" "table_row"
And I click on "Grade" "link" in the "Participant" "table_row"
And I set the field "Grade out of 100" to "70"
And I press "Save changes"
And I am on the "Assign 1" "assign activity" page
And I follow "Reveal student identities"
And I should see "Are you sure you want to reveal student identities for this assignment? This operation cannot be undone. Once the student identities have been revealed, the marks will be released to the gradebook."
And I press "Continue"
# Confirm that student identity is no longer hidden and grade is retained
And I should not see "Participant" in the "Student One" "table_row"
And I should see "70.00" in the "Student One" "table_row"
@@ -0,0 +1,29 @@
@mod @mod_assign
Feature: Switch role does not cause an error message in assignsubmission_comments
Scenario: I switch role to student and an error doesn't occur
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "users" exist:
| username |
| teacher1 |
And the following "course enrolments" exist:
| course | user | role |
| C1 | teacher1 | editingteacher |
And the following "activities" exist:
| activity | course | idnumber | name | intro | teamsubmission |
| assign | C1 | a1 | Test assignment one | This is the description text | 1 |
And the following "activity" exists:
| activity | assign |
| idnumber | ass1 |
| course | C1 |
| name | Test assignment |
| intro | This is the description text |
| teamsubmission | 1 |
| submissiondrafts | 0 |
And I am on the "C1" Course page logged in as teacher1
When I follow "Switch role to..." in the user menu
And I press "Student"
And I follow "Test assignment"
Then I should see "This is the description text"
@@ -0,0 +1,126 @@
@mod @mod_assign
Feature: Assign reset
In order to reuse past Assignss
As a teacher
I need to remove all previous data.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
| student2 | Sam2 | Student2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_onlinetext_wordlimit_enabled | 1 |
| assignsubmission_onlinetext_wordlimit | 10 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
Scenario: Use course reset to clear all attempt data
Given the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student first submission |
And I am on the "Test assignment name" Activity page logged in as student1
And I should see "Submitted for grading"
And I should see "I'm the student first submission"
And I should see "Not graded"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should see "Submitted for grading"
When I am on the "Course 1" "reset" page
And I set the following fields to these values:
| Delete all submissions | 1 |
And I press "Reset course"
And I press "Continue"
And I am on the "Test assignment name" Activity page
And I follow "View all submissions"
Then I should not see "Submitted for grading"
@javascript
Scenario: Use course reset to remove user overrides.
And I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Sam1 Student1"
When I am on the "Course 1" "reset" page
And I set the following fields to these values:
| Delete all user overrides | 1 |
And I press "Reset course"
And I press "Continue"
And I am on "Course 1" course homepage
And I click on "Test assignment name" "link" in the "region-main" "region"
And I navigate to "Overrides" in current page administration
Then I should not see "Sam1 Student1"
Scenario: Use course reset to remove group overrides.
When I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Group 1"
And I am on the "Course 1" "reset" page
And I set the following fields to these values:
| Delete all group overrides | 1 |
And I press "Reset course"
And I press "Continue"
And I am on the "Test assignment name" Activity page
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
Then I should not see "Group 1"
Scenario: Use course reset to reset blind marking assignment.
When I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| blindmarking | 1 |
And I press "Save"
When I am on the "Test assignment name" Activity page
And I follow "View all submissions"
And I select "Reveal student identities" from the "Grading action" singleselect
And I press "Continue"
And I should see "Sam1 Student1"
When I am on the "Course 1" "reset" page
And I set the following fields to these values:
| Delete all submissions | 1 |
And I press "Reset course"
And I press "Continue"
And I am on the "Test assignment name" Activity page
And I follow "View all submissions"
Then I should not see "Sam1 Student1"
@@ -0,0 +1,259 @@
@mod @mod_assign
Feature: Assign group override
In order to grant a group special access to an assignment
As a teacher
I need to create an override for that group.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
| student2 | Sam2 | Student2 | student2@example.com |
| student3 | Sam3 | Student3 | student3@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
Given the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
| student3 | G1 |
And the following "activities" exist:
| activity | name | intro | course | assignsubmission_onlinetext_enabled |
| assign | Test assignment name | Submit your online text | C1 | 1 |
Scenario: Add, modify then delete a group override
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Due date | ##1 Jan 2020 08:00## |
And I press "Save"
Then I should see "Wednesday, 1 January 2020, 8:00"
And I click on "Edit" "link" in the "Group 1" "table_row"
And I set the following fields to these values:
| Due date | ##1 Jan 2030 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I click on "Delete" "link"
And I press "Continue"
And I should not see "Group 1"
Scenario: Duplicate a user override
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Due date | ##1 Jan 2020 08:00## |
And I press "Save"
Then I should see "Wednesday, 1 January 2020, 8:00"
And I click on "copy" "link"
And I set the following fields to these values:
| Override group | Group 2 |
| Due date | ##1 Jan 2030 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I should see "Group 2"
Scenario: Allow a group to have a different due date
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Allow submissions from | disabled |
| Due date | ##1 Jan 2000 08:00## |
| Cut-off date | disabled |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Due date | ##1 Jan 2020 08:00## |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
Then the activity date in "Test assignment name" should contain "Due: Saturday, 1 January 2000, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And the activity date in "Test assignment name" should contain "Due: Wednesday, 1 January 2020, 8:00"
Scenario: Allow a group to have a different cut off date
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Due date | disabled |
| Allow submissions from | disabled |
| Cut-off date | ##1 Jan 2000 08:00## |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Cut-off date | ##1 Jan 2030 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
Then I should not see "You have not made a submission yet."
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should see "No submissions have been made yet"
Scenario: Allow a group to have a different start date
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Due date | disabled |
| Allow submissions from | ##1 January 2030 08:00## |
| Cut-off date | disabled |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Allow submissions from | ##1 Jan 2015 08:00## |
And I press "Save"
And I should see "Thursday, 1 January 2015, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
Then the activity date in "Test assignment name" should contain "Opens: Tuesday, 1 January 2030, 8:00"
And I should not see "Add submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should not see "Tuesday, 1 January 2030, 8:00"
@javascript
Scenario: Add both a user and group override and verify that both are applied correctly
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Due date | disabled |
| Allow submissions from | ##1 January 2040 08:00## |
| Cut-off date | disabled |
| Group mode | Visible groups |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Allow submissions from | ##1 January 2030 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I am on the "Test assignment name" Activity page
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Allow submissions from | ##1 January 2031 08:00## |
And I press "Save"
And I should see "Wednesday, 1 January 2031, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And the activity date in "Test assignment name" should contain "Opens: Wednesday, 1 January 2031, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And the activity date in "Test assignment name" should contain "Opens: Sunday, 1 January 2040, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student3
And the activity date in "Test assignment name" should contain "Opens: Tuesday, 1 January 2030, 8:00"
Scenario: Override a group when teacher is in no group, and does not have accessallgroups permission, and the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | groupmode |
| assign | Assignment 2 | Assignment 2 description | C1 | 1 |
And I am on the "Assignment 2" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
Then I should see "No groups you can access."
And the "Add group override" "button" should be disabled
Scenario: A teacher without accessallgroups permission should only be able to add group override for groups that he/she is a member of,
when the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | groupmode |
| assign | Assignment 2 | Assignment 2 description | C1 | 1 |
And the following "group members" exist:
| user | group |
| teacher1 | G1 |
And I am on the "Assignment 2" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
Then the "Override group" select box should contain "Group 1"
And the "Override group" select box should not contain "Group 2"
Scenario: A teacher without accessallgroups permission should only be able to see the group overrides for groups that he/she is a member of,
when the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | groupmode |
| assign | Assignment 2 | Assignment 2 description | C1 | 1 |
And the following "group members" exist:
| user | group |
| teacher1 | G1 |
And I am on the "Assignment 2" Activity page logged in as admin
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| Allow submissions from | ##1 January 2020 08:00## |
And I press "Save and enter another override"
And I set the following fields to these values:
| Override group | Group 2 |
| Allow submissions from | ##1 January 2020 08:00## |
And I press "Save"
And I log out
When I am on the "Assignment 2" Activity page logged in as teacher1
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
Then I should see "Group 1" in the ".generaltable" "css_element"
And I should not see "Group 2" in the ".generaltable" "css_element"
Scenario: "Not visible" groups should not be available for group overrides
Given the following "groups" exist:
| name | course | idnumber | visibility | participation |
| Visible to everyone/Participation | C1 | VP | 0 | 1 |
| Only visible to members/Participation | C1 | MP | 1 | 1 |
| Only see own membership | C1 | O | 2 | 0 |
| Not visible | C1 | N | 3 | 0 |
| Visible to everyone/Non-Participation | C1 | VN | 0 | 0 |
| Only visible to members/Non-Participation | C1 | MN | 1 | 0 |
When I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Overrides" in current page administration
And I select "Group overrides" from the "jump" singleselect
And I press "Add group override"
Then I should see "Visible to everyone/Participation" in the "Override group" "select"
And I should see "Visible to everyone/Non-Participation" in the "Override group" "select"
And I should see "Only visible to members" in the "Override group" "select"
And I should see "Only visible to members/Non-Participation" in the "Override group" "select"
And I should see "Only see own membership" in the "Override group" "select"
And I should not see "Not visible" in the "Override group" "select"
@@ -0,0 +1,39 @@
@mod @mod_assign
Feature: When a Teacher hides an assignment from view for students it should consistently indicate it is hidden.
Background: Grade multiple students on one page
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test hidden assignment |
| visible | 0 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test visible assignment |
Scenario: A teacher can view a hidden assignment
When I am on the "Test hidden assignment" Activity page logged in as teacher1
Then I should see "Test hidden assignment"
And I should see "Yes" in the "Hidden from students" "table_row"
Scenario: A teacher can view a visible assignment
Given I am on the "Test visible assignment" Activity page logged in as teacher1
Then I should see "Test visible assignment"
And I should see "No" in the "Hidden from students" "table_row"
Scenario: A student cannot view a hidden assignment
And I am on the "C1" Course page logged in as student1
And I should not see "Test hidden assignment"
And I should see "Test visible assignment"
@@ -0,0 +1,44 @@
@mod @mod_assign
Feature: Assignment with no calendar capabilites
In order to allow work effectively
As a teacher
I need to be able to create assignments even when I cannot edit calendar events
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I am on the "C1" "permissions" page logged in as admin
And I override the system permissions of "Teacher" role with:
| capability | permission |
| moodle/calendar:manageentries | Prohibit |
Scenario: Editing an assignment
Given the following "activities" exist:
| activity | name | intro | course | section |
| assign | Test assignment name | Test assignment description | C1 | 1 |
And I am on the "Test assignment name" Activity page
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Allow submissions from | ##1 January 2017## |
| Due date | ##1 February 2017## |
| Cut-off date | ##2 February 2017## |
| Remind me to grade by | ##1 March 2017## |
And I press "Save and return to course"
And I log out
When I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Allow submissions from | ##1 January 2018## |
| Due date | ##1 February 2018## |
| Cut-off date | ##2 February 2018## |
| Remind me to grade by | ##1 March 2018## |
And I press "Save and return to course"
Then I should see "Test assignment name"
@@ -0,0 +1,57 @@
@mod @mod_assign
Feature: In an assignment, teachers can use table preferences.
In order to improve grading process
As a teacher
I need to be able to filter students by first and last name.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | One | student1@example.com |
| student2 | Student | Two | student2@example.com |
| teacher1 | Darrell | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | enablecompletion | showcompletionconditions |
| Course 1 | C1 | 1 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| student2 | C1 | student |
| teacher1 | C1 | editingteacher |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment |
| assignsubmission_onlinetext_enabled | 1 |
And I log out
And I log in as "student1"
And I am on the "Test assignment" Activity page
And I press "Add submission"
And I set the following fields to these values:
| Online text | This is a submission for Student One |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And I log out
And I log in as "student2"
And I am on the "Test assignment" Activity page
And I press "Add submission"
And I set the following fields to these values:
| Online text | This is a submission for Student Two |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
@javascript
Scenario: As a teacher I can filter student submissions on the View all submission page
When I log in as "teacher1"
And I am on the "Test assignment" Activity page
And I follow "View all submissions"
And I click on "T" "link" in the ".lastinitial" "css_element"
And I click on "Grade" "link" in the "Student Two" "table_row"
And I should see "This is a submission for Student Two"
And I should see "1 of 1"
And I follow "Reset table preferences"
Then I should see "This is a submission for Student Two"
And I should see "2 of 2"
And I log out
@@ -0,0 +1,222 @@
@mod @mod_assign
Feature: Assign user override
In order to grant a student special access to an assignment
As a teacher
I need to create an override for that user.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
| student2 | Sam2 | Student2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activities" exist:
| activity | name | intro | course | assignsubmission_onlinetext_enabled |
| assign | Test assignment name | Submit your online text | C1 | 1 |
@javascript
Scenario: Add, modify then delete a user override
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Due date | ##first day of January 2020 08:00## |
And I press "Save"
Then I should see "Wednesday, 1 January 2020, 8:00"
And I click on "Edit" "link" in the "Sam1 Student1" "table_row"
And I set the following fields to these values:
| Due date | ##first day of January 2030 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I click on "Delete" "link"
And I press "Continue"
And I should not see "Sam1 Student1"
@javascript
Scenario: Duplicate a user override
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Due date | ##2020-01-01 08:00## |
And I press "Save"
Then I should see "Wednesday, 1 January 2020, 8:00"
And I click on "copy" "link"
And I set the following fields to these values:
| Override user | Student2 |
| Due date | ##2030-01-01 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I should see "Sam2 Student2"
@javascript
Scenario: Allow a user to have a different due date
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Allow submissions from | disabled |
| Due date | ##1 Jan 2000 08:00## |
| Cut-off date | disabled |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Due date | ##1 Jan 2020 08:00## |
And I press "Save"
Then I should see "Wednesday, 1 January 2020, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And the activity date in "Test assignment name" should contain "Due: Saturday, 1 January 2000, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And the activity date in "Test assignment name" should contain "Due: Wednesday, 1 January 2020, 8:00"
@javascript
Scenario: Allow a user to have a different cut off date
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Due date | disabled |
| Allow submissions from | disabled |
| Cut-off date | ##1 Jan 2000 08:00## |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Cut-off date | ##1 Jan 2030 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
Then I should not see "Add submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should see "Add submission"
@javascript
Scenario: Allow a user to have a different start date
Given I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Due date | disabled |
| Allow submissions from | ##1 January 2030 08:00## |
| Cut-off date | disabled |
And I press "Save and display"
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Allow submissions from | ##1 Jan 2015 08:00## |
And I press "Save"
And I should see "Thursday, 1 January 2015, 8:00"
And I log out
And I log in as "student2"
And I am on "Course 1" course homepage
And I click on "Test assignment name" "link" in the "region-main" "region"
Then the activity date in "Test assignment name" should contain "Opens: Tuesday, 1 January 2030, 8:00"
And I log out
And I log in as "student1"
And I am on "Course 1" course homepage
And I click on "Test assignment name" "link" in the "region-main" "region"
And I should not see "1 January 2030, 8:00"
Scenario: Override a user when teacher is in no group, and does not have accessallgroups permission, and the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | groupmode |
| assign | Assignment 2 | Assignment 2 description | C1 | 1 |
And I am on the "Assignment 2" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
Then I should see "No groups you can access."
And the "Add user override" "button" should be disabled
Scenario: A teacher without accessallgroups permission should only be able to add user override for users that he/she shares groups with,
when the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | groupmode |
| assign | Assignment 2 | Assignment 2 description | C1 | 1 |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "group members" exist:
| user | group |
| teacher1 | G1 |
| student1 | G1 |
| student2 | G2 |
And I am on the "Assignment 2" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
And I press "Add user override"
Then the "Override user" select box should contain "Sam1 Student1, student1@example.com"
And the "Override user" select box should not contain "Sam2 Student2, student2@example.com"
@javascript
Scenario: A teacher without accessallgroups permission should only be able to see the user override for users that he/she shares groups with,
when the activity's group mode is "separate groups"
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/site:accessallgroups | Prevent | editingteacher | Course | C1 |
And the following "activities" exist:
| activity | name | intro | course | groupmode |
| assign | Assignment 2 | Assignment 2 description | C1 | 1 |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "group members" exist:
| user | group |
| teacher1 | G1 |
| student1 | G1 |
| student2 | G2 |
And I am on the "Assignment 2" Activity page logged in as admin
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Allow submissions from | ##first day of January 2015 08:00## |
And I press "Save and enter another override"
And I set the following fields to these values:
| Override user | Student2 |
| Allow submissions from | ##first day of January 2015 08:00## |
And I press "Save"
And I log out
And I am on the "Assignment 2" Activity page logged in as teacher1
When I navigate to "Overrides" in current page administration
Then I should see "Student1" in the ".generaltable" "css_element"
But I should not see "Student2" in the ".generaltable" "css_element"
@javascript
Scenario: Create a user override when the assignment is not available to the student
Given I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Availability" to "Hide on course page"
And I click on "Save and display" "button"
When I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| Allow submissions from | ##1 Jan 2015 08:00## |
And I press "Save"
Then I should see "This override is inactive"
And "Edit" "icon" should exist in the "Sam1 Student1" "table_row"
And "copy" "icon" should exist in the "Sam1 Student1" "table_row"
And "Delete" "icon" should exist in the "Sam1 Student1" "table_row"
@@ -0,0 +1,74 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Behat custom steps and configuration for mod_bigbluebuttonbn.
*
* @package mod_assign
* @category test
* @copyright 2024 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
use Behat\Gherkin\Node\TableNode;
/**
* Behat custom steps and configuration for mod_assign.
*
* @package mod_assign
* @category test
* @copyright 2024 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_mod_assign extends behat_base {
/**
* Check that the marking guide information is displayed correctly.
*
* @Then /^I should see the marking guide information displayed as:$/
* @param TableNode $table The table of marking guide information to check.
*/
public function i_should_see_marking_guide_information(TableNode $table) {
if (!$table->getRowsHash()) {
return;
}
$criteriacheck = 1;
foreach ($table as $row) {
$locator = "//table[@id='guide0-criteria']/tbody/tr[$criteriacheck]/td";
$this->assertSession()->elementContains('xpath', "{$locator}[@class='descriptionreadonly']", $row['criteria']);
$this->assertSession()->elementContains('xpath', "{$locator}[@class='descriptionreadonly']", $row['description']);
if (!empty($row['remark'])) {
$this->assertSession()->elementContains('xpath', "{$locator}[@class='remark']", $row['remark']);
}
if (!empty($row['maxscore'])) {
$this->assertSession()->elementContains('xpath', "{$locator}[@class='descriptionreadonly']", $row['maxscore']);
}
if (!empty($row['criteriascore'])) {
$this->assertSession()->elementContains('xpath', "{$locator}[@class='score']", $row['criteriascore']);
}
$criteriacheck++;
}
}
}
@@ -0,0 +1,143 @@
@mod @mod_assign
Feature: Bulk released grades should not be sent to gradebook while submissions are anonymous.
In order to preserve student anonymity until identities are explicitly revealed
As a teacher
I should be able to bulk release grades for anonymous submissions via
marking workflow without the grades being pushed to the gradebook.
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
# Add the assignment.
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| markingworkflow | 1 |
| markinganonymous | 0 |
| blindmarking | 1 |
| assignfeedback_comments_enabled | 1 |
| assignfeedback_editpdf_enabled | 1 |
# Add a submission.
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm student1's submission |
| Test assignment name | student2 | I'm student2's submission |
# Mark the submissions.
And I am on the "Test assignment name" "assign activity" page logged in as "teacher1"
And I follow "View all submissions"
Then I should see "Not marked" in the "I'm student1's submission" "table_row"
And I click on "Grade" "link" in the "I'm student1's submission" "table_row"
And I set the field "Grade out of 100" to "50"
And I set the field "Marking workflow state" to "In review"
And I set the field "Feedback comments" to "Great job!"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Not marked" in the "I'm student2's submission" "table_row"
And I click on "Grade" "link" in the "I'm student2's submission" "table_row"
And I set the field "Grade out of 100" to "50"
And I set the field "Marking workflow state" to "In review"
And I set the field "Feedback comments" to "Great job!"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "In review" in the "I'm student1's submission" "table_row"
And I should see "In review" in the "I'm student2's submission" "table_row"
@javascript @_alert
Scenario: Grades are released in bulk before student identities are revealed.
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
Then I should not see "Student 1 (student1@example.com)"
And I should not see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"
And I set the field "Notify student" to "No"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Released" in the "I'm student1's submission" "table_row"
And I should see "Released" in the "I'm student2's submission" "table_row"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should not see "50"
And I should not see "Great job!"
And I am on the "Course 1" "grades > User report > View" page logged in as "student2"
Then I should not see "50"
And I should not see "Great job!"
And I am on the "Test assignment name" "assign activity" page logged in as "teacher1"
And I follow "View all submissions"
And I set the field "Grading action" to "Reveal student identities"
And I press "Continue"
Then I should see "Released" in the "Student 1" "table_row"
And I should see "Released" in the "Student 2" "table_row"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should see "50"
And I should see "Great job!"
And I am on the "Course 1" "grades > User report > View" page logged in as "student2"
Then I should see "50"
And I should see "Great job!"
@javascript @_alert
Scenario: Grades are released in bulk after student identities are revealed.
When I set the field "Grading action" to "Reveal student identities"
And I press "Continue"
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
Then I should see "Student 1 (student1@example.com)"
And I should see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"
And I set the field "Notify student" to "No"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Released" in the "Student 1" "table_row"
And I should see "Released" in the "Student 2" "table_row"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should see "50"
And I should see "Great job!"
And I am on the "Course 1" "grades > User report > View" page logged in as "student2"
Then I should see "50"
And I should see "Great job!"
@javascript @_alert
Scenario: Grades are released to the gradebook if markinganonymous is enabled
Given I follow "Settings"
And I expand all fieldsets
And I set the field "Allow partial release of grades while marking anonymously" to "Yes"
And I press "Save and display"
And I follow "View all submissions"
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
Then I should not see "Student 1 (student1@example.com)"
And I should not see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"
And I set the field "Notify student" to "No"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Released" in the "I'm student1's submission" "table_row"
And I should see "Released" in the "I'm student2's submission" "table_row"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should see "50"
And I should see "Great job!"
And I am on the "Course 1" "grades > User report > View" page logged in as "student2"
Then I should see "50"
And I should see "Great job!"
@@ -0,0 +1,154 @@
@mod @mod_assign
Feature: Bulk remove submissions
In order to reset the assignment submission of multiple students
As a teacher with the capability to edit submissions
I need to be able to remove student submissions by bulk
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
@javascript @skip_chrome_zerosize
Scenario: Bulk remove submissions should remove the data that was submitted
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
| Test assignment name | student2 | I'm the student2 submission |
And the following "role capability" exists:
| role | editingteacher |
| mod/assign:editothersubmission | allow |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should see "I'm the student1 submission"
And I should see "I'm the student2 submission"
And I set the field "selectall" to "1"
When I set the field "operation" to "Remove submission"
And I click on "Go" "button" confirming the dialogue
Then I should not see "I'm the student1 submission"
And I should not see "I'm the student2 submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should not see "I'm the student1 submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And I should not see "I'm the student2 submission1"
@javascript
Scenario: Bulk remove submissions should be unavailable if the user is missing the editing submission capability
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
| Test assignment name | student2 | I'm the student2 submission |
When I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should see "I'm the student1 submission"
And I should see "I'm the student2 submission"
And I set the field "selectall" to "1"
Then I should not see "Remove submission" in the "Choose operation" "select"
@javascript @skip_chrome_zerosize
Scenario: Bulk remove submission when shared group users are added to the bulk
removing submissions process in separate group mode without access all groups capability
Given the following "group members" exist:
| user | group |
| teacher1 | G1 |
| student1 | G1 |
| student2 | G1 |
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| groupmode | 1 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
| Test assignment name | student2 | I'm the student2 submission |
| Test assignment name | student3 | I'm the student3 submission |
And the following "role capability" exists:
| role | editingteacher |
| mod/assign:editothersubmission | allow |
| moodle/site:accessallgroups | prevent |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should see "I'm the student1 submission"
And I should see "I'm the student2 submission"
And I should not see "I'm the student3 submission"
And I set the field "selectall" to "1"
When I set the field "operation" to "Remove submission"
And I click on "Go" "button" confirming the dialogue
Then I should not see "I'm the student1 submission"
Then I should not see "I'm the student2 submission"
@javascript @skip_chrome_zerosize
Scenario: Bulk remove submission when group users and non-group users are added to the bulk
removing submissions process in separate group mode with access all groups capability
Given the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| groupmode | 1 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
| Test assignment name | student2 | I'm the student2 submission |
| Test assignment name | student3 | I'm the student3 submission |
And the following "role capability" exists:
| role | editingteacher |
| mod/assign:editothersubmission | allow |
| moodle/site:accessallgroups | allow |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should see "I'm the student1 submission"
And I should see "I'm the student2 submission"
And I should see "I'm the student3 submission"
And I set the field "selectall" to "1"
When I set the field "operation" to "Remove submission"
And I click on "Go" "button" confirming the dialogue
Then I should not see "I'm the student1 submission"
And I should not see "I'm the student2 submission"
And I should not see "I'm the student3 submission"
@@ -0,0 +1,56 @@
@mod @mod_assign
Feature: In an assignment, teachers can edit a students submission inline
In order to easily mark students assignments
As a teacher
I need to have a students submission text copied to the grading online form.
@javascript @_file_upload
Scenario: Submit a text online and edit the submission
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| assignfeedback_comments_enabled | 1 |
| assignfeedback_file_enabled | 1 |
| assignfeedback_comments_commentinline | 1 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student first submission |
When I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 50 |
| Feedback comments | I'm the teacher feedback |
And I upload "lib/tests/fixtures/empty.txt" file to "Feedback files" filemanager
And I press "Save changes"
And I follow "View all submissions"
Then I should see "50.00" in the "Student 1" "table_row"
And I should see "Submitted for grading" in the "Student 1" "table_row"
And I should see "Graded" in the "Student 1" "table_row"
And I should see "I'm the student first submission" in the "Student 1" "table_row"
And I should see "I'm the teacher feedback" in the "Student 1" "table_row"
And I should see "empty.txt" in the "Student 1" "table_row"
And I log out
When I am on the "Test assignment name" Activity page logged in as student1
And I should see "Submitted for grading" in the "Submission status" "table_row"
And I should see "Graded" in the "Grading status" "table_row"
And I should see "I'm the student first submission" in the "Online text" "table_row"
And I should see "I'm the teacher feedback" in the "Feedback comments" "table_row"
And I should see "empty.txt" in the "Feedback files" "table_row"
@@ -0,0 +1,65 @@
@mod @mod_assign
Feature: Check that the assignment grade can not be input in a wrong format.
In order to ensure that the grade is entered in the right format
As a teacher
I need to grade a student and ensure that the grade should be correctly entered
@javascript
Scenario: Error in the decimal separator ,
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student10@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Test assignment description |
| markingworkflow | 1 |
| submissiondrafts | 0 |
When I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Grade out of 100" to "50,,6"
And I press "Save changes"
Then I should see "The grade provided could not be understood: 50,,6"
@javascript
Scenario: Error in the decimal separator .
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student10@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Test assignment description |
| markingworkflow | 1 |
| submissiondrafts | 0 |
When I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Grade out of 100" to "50..6"
And I press "Save changes"
Then I should see "The grade provided could not be understood: 50..6"
@@ -0,0 +1,71 @@
@mod @mod_assign
Feature: Check that the assignment grade can be updated correctly
In order to ensure that the grade is shown correctly in the grading table
As a teacher
I need to grade a student and ensure the grade is shown correctly
@javascript
Scenario: Update the grade for an assignment
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student10@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Test assignment description |
| markingworkflow | 1 |
| submissiondrafts | 0 |
And I am on the "Test assignment name" Activity page logged in as teacher1
Then I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Grade out of 100" to "50"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I follow "View all submissions"
And "Student 1" row "Grade" column of "generaltable" table should contain "50.00"
@javascript
Scenario: Update the grade for a team assignment
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student10@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Test assignment description |
| markingworkflow | 1 |
| submissiondrafts | 0 |
| teamsubmission | 1 |
| groupmode | 0 |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Grade out of 100" to "50"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I follow "View all submissions"
Then "Student 1" row "Grade" column of "generaltable" table should contain "50.00"
@@ -0,0 +1,62 @@
@mod @mod_assign
Feature: Duplicate assign activity module with permissions
In order to ensure that locally assigned roles and permissions are correctly duplicated
As a teacher
I need to add the roles and permissions and ensure they are correctly duplicated
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student10@example.com |
| student2 | Student | 2 | student20@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Test assignment description |
| markingworkflow | 1 |
| submissiondrafts | 0 |
@javascript
Scenario: Add a locally assigned role and duplicate activity
Given I log in as "teacher 1"
And I am on "Course 1" course homepage with editing mode on
When I open "Test assignment name" actions menu
And I click on "Assign roles" "link" in the "Test assignment name" activity
And I click on "Non-editing teacher" "link"
And I click on "Student 2" "option"
And I click on "Add" "button"
And I am on "Course 1" course homepage with editing mode on
And I duplicate "Test assignment name" activity
Then I should see "Test assignment name (copy)"
And I open "Test assignment name (copy)" actions menu
And I click on "Assign roles" "link" in the "Test assignment name (copy)" activity
Then "Non-editing teacher" row "Users with role" column of "generaltable" table should contain "1"
@javascript
Scenario: Add a permission override to activity and duplicate
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| mod/assign:grade | Allow | student | 70 | Test assignment name |
And I log in as "admin"
When I am on "Course 1" course homepage with editing mode on
And I duplicate "Test assignment name" activity
Then I should see "Test assignment name (copy)"
And I open "Test assignment name (copy)" actions menu
And I click on "Edit settings" "link" in the "Test assignment name (copy)" activity
And I navigate to "Permissions" in current page administration
And I set the field "permissionscapabilitysearch" to "mod/assign:grade"
Then "Grade assignmentmod/assign:grade" row "Roles with permission" column of "permissions" table should contain "Student"
@@ -0,0 +1,66 @@
@mod @mod_assign
Feature: In an assignment, teachers can edit feedback for a students previous submission attempt
In order to correct feedback for a previous submission attempt
As a teacher
I need to be able to edit the feedback for a students previous submission attempt.
@javascript
Scenario: Edit feedback for a students previous attempt.
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignfeedback_comments_enabled | 1 |
| submissiondrafts | 0 |
| attemptreopenmethod | manual |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student2 | I'm the student first submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 2" "table_row"
And I set the following fields to these values:
| Grade | 49 |
| Feedback comments | I'm the teacher first feedback |
| Allow another attempt | Yes |
And I press "Save changes"
And I click on "Edit settings" "link"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And I should see "I'm the teacher first feedback" in the "Feedback comments" "table_row"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 2" "table_row"
And I click on "View a different attempt" "link"
And I click on "Attempt 1" "radio" in the "View a different attempt" "dialogue"
And I click on "View" "button" in the "View a different attempt" "dialogue"
And I set the following fields to these values:
| Grade | 50 |
| Feedback comments | I'm the teacher second feedback |
And I press "Save changes"
And I click on "Edit settings" "link"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
Then I should see "I'm the teacher second feedback" in the "Feedback comments" "table_row"
And I should see "50.00"
And I click on ".mod-assign-history-link" "css_element"
And I should not see "I'm the teacher second feedback" in the "Feedback comments" "table_row"
@@ -0,0 +1,41 @@
@mod @mod_assign @javascript
Feature: In an assignment, the administrator can edit students' submissions
In order to edit a student's submissions
As an administrator
I need to grade multiple students on one page
Scenario: Editing a student's submission
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
And I am on the "Test assignment name" Activity page logged in as admin
And I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
And I choose "Edit submission" in the open action menu
And I set the following fields to these values:
| Online text | Have you seen the movie Chef? |
And I press "Save changes"
Then I should see "Have you seen the movie Chef?"
And I open the action menu in "Student 1" "table_row"
And I choose "Edit submission" in the open action menu
And I set the following fields to these values:
| Online text | I have seen the movie chef. |
And I press "Save changes"
Then I should see "I have seen the movie chef."
@@ -0,0 +1,49 @@
@mod @mod_assign @_file_upload
Feature: In an assignment, students can upload files for assessment
In order to complete my assignments providing files
As a student
I need to upload files from my file system to be assessed
@javascript
Scenario: Submit a file and update the submission with another file
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 0 |
| assignsubmission_file_enabled | 1 |
| assignsubmission_file_maxfiles | 2 |
| assignsubmission_file_maxsizebytes | 1000000 |
And I am on the "Test assignment name" Activity page logged in as student1
When I press "Add submission"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
And I press "Save changes"
Then I should see "Submitted for grading"
And I should see "Not graded"
And "empty.txt" "link" should exist
And I press "Edit submission"
And I upload "lib/tests/fixtures/upload_users.csv" file to "File submissions" filemanager
And ".ffilemanager .fm-maxfiles .fp-btn-add" "css_element" should not be visible
And I press "Save changes"
And I should see "Submitted for grading"
And "empty.txt" "link" should exist
And "upload_users.csv" "link" should exist
And I press "Edit submission"
And ".ffilemanager .fm-maxfiles .fp-btn-add" "css_element" should not be visible
And I delete "empty.txt" from "File submissions" filemanager
And I press "Save changes"
And "empty.txt" "link" should not exist
And "upload_users.csv" "link" should exist
@@ -0,0 +1,52 @@
@mod @mod_assign
Feature: In an assignment, teachers can filter displayed submissions by assigned marker
In order to manage submissions more easily
As a teacher
I need to view submissions allocated to markers.
@javascript
Scenario: Allocate markers to submissions and filter by marker
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| marker1 | Marker | 1 | marker1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| marker1 | C1 | teacher |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| markingworkflow | 1 |
| markingallocation | 1 |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "allocatedmarker" to "Marker 1"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I click on "Edit settings" "link"
When I am on the "Test assignment name" Activity page
And I follow "View all submissions"
And I set the field "markerfilter" to "Marker 1"
Then I should see "Student 1"
And I should not see "Student 2"
And I set the field "markerfilter" to "No marker"
And I should not see "Student 1"
And I should see "Student 2"
And I set the field "markerfilter" to "No filter"
And I should see "Student 1"
And I should see "Student 2"
@@ -0,0 +1,64 @@
@mod @mod_assign
Feature: In an assignment, teachers can filter displayed submissions and see drafts
In order to manage submissions more easily
As a teacher
I need to view submissions with draft status.
Background:
Given the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
And the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled | submissiondrafts |
| assign | C1 | Test assignment | 1 | 1 |
And I am on the "Test assignment" Activity page logged in as student1
And I press "Add submission"
And I set the following fields to these values:
| Online text | This submission is submitted |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And I log out
And I am on the "Test assignment" Activity page logged in as student2
And I press "Add submission"
And I set the following fields to these values:
| Online text | This submission is NOT submitted |
And I press "Save changes"
And I log out
@javascript
Scenario: View assignments with draft status on the view all submissions page
Given I am on the "Test assignment" Activity page logged in as teacher1
And I follow "View all submissions"
When I set the field "Filter" to "Draft"
Then I should see "Student 2"
And I should not see "Student 1"
And I should not see "Student 3"
@javascript
Scenario: View assignments with draft status in the grader
Given I am on the "Test assignment" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
When I click on "[data-region=user-filters]" "css_element"
And I set the field "filter" to "Draft"
Then I should see "1 of 1"
And I should see "No users selected"
And I click on "[data-region=user-selector]" "css_element"
And I type "Student"
And I should see "Student 2"
And I should not see "Student 1"
And I should not see "Student 3"
@@ -0,0 +1,78 @@
@mod @mod_assign
Feature: In an assignment, teachers can change filters in the grading app
In order to manage submissions more easily
As a teacher
I need to preserve filter settings between the grader app and grading table.
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 & | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| marker1 | Marker | 1 | marker1@example.com |
| marker2 | Marker | 2 | marker2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| marker1 | C1 | teacher |
| marker2 | C1 | teacher |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name & |
| description | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| markingworkflow | 1 |
| markingallocation | 1 |
@javascript
Scenario: Set filters in the grading table and see them in the grading app
Given I am on the "Test assignment name &" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should not see "Course 1 &amp;"
And the "title" attribute of "a[title='Course: Course 1 &']" "css_element" should not contain "&amp;"
And I should not see "Test assignment name &amp;"
And I set the field "allocatedmarker" to "Marker 1"
And I set the field "workflowstate" to "In marking"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Test assignment name &" Activity page
And I follow "View all submissions"
And I set the field "filter" to "Not submitted"
And I set the field "markerfilter" to "Marker 1"
And I set the field "workflowfilter" to "In marking"
And I click on "Grade" "link" in the "Student 1" "table_row"
Then the field "filter" matches value "Not submitted"
And the field "markerfilter" matches value "Marker 1"
And the field "workflowfilter" matches value "In marking"
@javascript
Scenario: Set filters in the grading app and see them in the grading table
Given I am on the "Test assignment name &" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "allocatedmarker" to "Marker 1"
And I set the field "workflowstate" to "In marking"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Test assignment name &" Activity page
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I click on "[data-region=user-filters]" "css_element"
And I set the field "filter" to "Not submitted"
And I set the field "markerfilter" to "Marker 1"
And I set the field "workflowfilter" to "In marking"
And I click on "View all submissions" "link"
Then the field "filter" matches value "Not submitted"
And the field "markerfilter" matches value "Marker 1"
And the field "workflowfilter" matches value "In marking"
@@ -0,0 +1,158 @@
@mod @mod_assign
Feature: View the grading status of an assignment
In order to test the grading status for assignments is displaying correctly
As a student
I need to view my grading status
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
@javascript
Scenario: View the grading status for an assignment with marking workflow enabled
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| markingworkflow | 1 |
| assignfeedback_comments_enabled | 1 |
| assignsubmission_onlinetext_enabled | 1 |
# Add a submission.
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student first submission |
# Mark the submission.
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I should see "Not marked" in the "Student 1" "table_row"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should see "1 of 2"
And I click on "Change filters" "link"
And I set the field "Filter" to "submitted"
And I should see "1 of 1"
And I set the field "Grade out of 100" to "50"
And I set the field "Marking workflow state" to "In review"
And I set the field "Feedback comments" to "Great job! Lol, not really."
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I should see "In review" in the "Student 1" "table_row"
And I log out
# View the grading status as a student.
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I should see "In review" in the "Grading status" "table_row"
And I should not see "Great job! Lol, not really."
And I log out
# Mark the submission again but set the marking workflow to 'Released'.
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I should see "In review" in the "Student 1" "table_row"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should see "1 of 1"
And I set the field "Marking workflow state" to "Released"
And I press "Save changes"
And I follow "View all submissions"
And I should see "Released" in the "Student 1" "table_row"
And I log out
# View the grading status as a student.
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I should see "Released" in the "Grading status" "table_row"
And I should see "Great job! Lol, not really."
And I log out
# Now, change the status from 'Released' to 'In marking' (this will remove the grade from the gradebook).
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I should see "Released" in the "Student 1" "table_row"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should see "1 of 1"
And I set the field "Marking workflow state" to "In marking"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I should see "In marking" in the "Student 1" "table_row"
# The grade should also remain displayed as it's stored in the assign DB tables, but the final grade should be empty.
And "Student 1" row "Grade" column of "generaltable" table should contain "50.00"
And "Student 1" row "Final grade" column of "generaltable" table should contain "-"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I click on "Change filters" "link"
And I set the field "Workflow filter" to "In review"
And I should see "0 of 0"
@javascript
Scenario: View the grading status for an assignment with marking workflow disabled
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignfeedback_comments_enabled | 1 |
| markingworkflow | 0 |
| assignsubmission_onlinetext_enabled | 1 |
# Add a submission.
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student first submission |
# Mark the submission.
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I should not see "Graded" in the "Student 1" "table_row"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should see "1 of 2"
And I click on "Change filters" "link"
And I set the field "Filter" to "submitted"
And I should see "1 of 1"
And I set the field "Grade out of 100" to "50"
And I set the field "Feedback comments" to "Great job! Lol, not really."
And I press "Save changes"
And I click on "Edit settings" "link"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I should see "Graded" in the "Student 1" "table_row"
And I log out
# View the grading status as a student.
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I should see "Graded" in the "Grading status" "table_row"
And I should see "Great job! Lol, not really."
And I log out
# Student makes a subsequent submission.
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I press "Edit submission"
And I set the following fields to these values:
| Online text | I'm the student's second submission |
And I press "Save changes"
And I log out
# Teacher marks the submission again after noticing the 'Graded - resubmitted'.
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I should see "Graded - resubmitted" in the "Student 1" "table_row"
And I wait "10" seconds
And I click on "Grade" "link" in the "Student 1" "table_row"
And I should see "1 of 1"
And I set the field "Grade out of 100" to "99.99"
And I set the field "Feedback comments" to "Even better job! Really."
And I press "Save changes"
And I click on "Edit settings" "link"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I should see "Graded" in the "Student 1" "table_row"
And I log out
# View the grading status as a student again.
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I should see "Graded" in the "Grading status" "table_row"
And I should see "Even better job! Really."
@@ -0,0 +1,137 @@
@mod @mod_assign
Feature: Grant an extension to an offline student
In order to allow students to have an accurate due date
As a teacher
I need to grant students extensions at any time
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
| student4 | Student | 4 | student4@example.com |
| student5 | Student | 5 | student5@example.com |
| student6 | Student | 6 | student6@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
| student5 | C1 | student |
| student6 | C1 | student |
@javascript
Scenario: Granting an extension to an offline assignment
Given the following "activities" exist:
| activity | course | name | intro | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | duedate |
| assign | C1 | Test assignment name | Test assignment description | 0 | 0 | ## 2014-01-01 ## |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
And I follow "Grant extension"
And I should see "Student 1 (student1@example.com)"
And I should see "Wednesday, 1 January 2014, 12:00 AM" in the "fitem_id_duedate" "region"
And I should see "Current extension due date" in the "fitem_id_currentextension" "region"
And I should see "None" in the "fitem_id_currentextension" "region"
And I set the field "Extension due date" to "## 2014-02-02 ##"
And I press "Save changes"
Then I should see "Extension granted until:" in the "Student 1" "table_row"
And I open the action menu in "Student 1" "table_row"
And I follow "Grant extension"
And I should see "Student 1 (student1@example.com)"
And I should see "Wednesday, 1 January 2014, 12:00 AM" in the "fitem_id_duedate" "region"
And I should see "Sunday, 2 February 2014, 12:00 AM" in the "fitem_id_currentextension" "region"
And the field "id_extensionduedate_day" matches value "2"
And the field "id_extensionduedate_month" matches value "February"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should see "Extension due date"
@javascript
Scenario: Granting extensions to an offline assignment (batch action)
Given the following "activities" exist:
| activity | course | name | intro | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | duedate |
| assign | C1 | Test assignment name | Test assignment description | 0 | 0 | ## 2014-01-01 ## |
And the following "mod_assign > extensions" exist:
| assign | user | extensionduedate |
| Test assignment name | student2 | ## 2014-02-02 ## |
| Test assignment name | student3 | ## 2014-03-03 ## |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I set the field "selectall" to "1"
And I set the field "operation" to "Grant extension"
And I click on "Go" "button" confirming the dialogue
And I should see "Student 1 (student1@example.com)"
And I should see "Student 2 (student2@example.com)"
And I should see "Student 3 (student3@example.com)"
And I should see "Student 4 (student4@example.com)"
And I should see "Student 5 (student5@example.com)"
And I should see "1 more..."
And I should see "Wednesday, 1 January 2014, 12:00 AM" in the "fitem_id_duedate" "region"
And I should see "From Sunday, 2 February 2014, 12:00 AM" in the "fitem_id_currentextension" "region"
And I should see "To Monday, 3 March 2014, 12:00 AM" in the "fitem_id_currentextension" "region"
And I should see "Users without an extension: 4" in the "fitem_id_currentextension" "region"
And I set the field "Enable" to "1"
And I press "Save changes"
Then I should see "Extension granted until:" in the "Student 1" "table_row"
And I should see "Extension granted until:" in the "Student 2" "table_row"
And I should see "Extension granted until:" in the "Student 3" "table_row"
And I should see "Extension granted until:" in the "Student 4" "table_row"
And I should see "Extension granted until:" in the "Student 5" "table_row"
And I should see "Extension granted until:" in the "Student 6" "table_row"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should see "Extension due date"
@javascript
Scenario: Validating that extension date is after due date
Given the following "activities" exist:
| activity | course | name | intro | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | allowsubmissionsfromdate | duedate |
| assign | C1 | Test assignment name | Test assignment description | 0 | 0 | ## 2034-01-01 ## | ## 2034-01-02 ## |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
And I follow "Grant extension"
And I should see "Student 1 (student1@example.com)"
And I set the field "Enable" to "1"
And I set the following fields to these values:
| extensionduedate[day] | 1 |
And I press "Save changes"
Then I should see "Extension date must be after the due date"
And I set the following fields to these values:
| extensionduedate[year] | 2023 |
And I press "Save changes"
Then I should see "Extension date must be after the allow submissions from date"
@javascript
Scenario: Granting extensions to an offline assignment (batch action)
Given the following "activities" exist:
| activity | course | name | intro | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | allowsubmissionsfromdate | duedate |
| assign | C1 | Test assignment name | Test assignment description | 0 | 0 | ## 2034-01-01 ## | ## 2034-01-02 ## |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I set the field "selectall" to "1"
And I set the field "operation" to "Grant extension"
And I click on "Go" "button" confirming the dialogue
And I should see "Student 1 (student1@example.com)"
And I should see "Student 2 (student2@example.com)"
And I should see "Student 3 (student3@example.com)"
And I should see "Student 4 (student4@example.com)"
And I should see "Student 5 (student5@example.com)"
And I should see "1 more..."
And I set the field "Enable" to "1"
And I set the following fields to these values:
| extensionduedate[day] | 1 |
And I press "Save changes"
Then I should see "Extension date must be after the due date"
And I set the following fields to these values:
| extensionduedate[year] | 2023 |
And I press "Save changes"
Then I should see "Extension date must be after the allow submissions from date"
@@ -0,0 +1,344 @@
@mod @mod_assign
Feature: Group assignment submissions
In order to allow students to work collaboratively on an assignment
As a teacher
I need to group submissions in groups
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student0 | Student | 0 | student0@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
| student4 | Student | 4 | student4@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student0 | C1 | student |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
@javascript
Scenario: Confirm that group submissions are removed from the timeline
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| teamsubmission | 1 |
| duedate | ##tomorrow## |
| requiresubmissionstatement | 1 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
# Student1 checks the assignment is visible in the timeline
When I am on the "Homepage" page logged in as student1
Then I should see "Test assignment name" in the "Timeline" "block"
# Student2 checks the assignment is visible in the timeline
And I am on the "Homepage" page logged in as student2
And I should see "Test assignment name" in the "Timeline" "block"
# Student2 submits the assignment
And I am on the "Test assignment name" Activity page
And I press "Add submission"
And I set the field "Online text" to "Assignment submission text"
And I press "Save changes"
And I should see "Draft (not submitted)" in the "Submission status" "table_row"
And I press "Submit assignment"
And I should see "This submission is the work of my group, except where we have acknowledged the use of the works of other people."
And I press "Continue"
And I should see "Confirm submission"
And I should see "You are required to agree to this statement before you can submit."
And I set the field "submissionstatement" to "1"
And I press "Continue"
And I should see "Submitted for grading" in the "Submission status" "table_row"
# Student2 checks the timeline again
And I am on the "Homepage" page
And I should not see "Test assignment name" in the "Timeline" "block"
# Student1 checks the timeline again
And I am on the "Homepage" page logged in as student1
And I should not see "Test assignment name" in the "Timeline" "block"
@javascript
Scenario: Switch between group modes
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| teamsubmission | 1 |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
Then I should see "Default group" in the "Student 0" "table_row"
And I should see "Default group" in the "Student 1" "table_row"
And I should see "Default group" in the "Student 2" "table_row"
And I should see "Default group" in the "Student 3" "table_row"
And I am on the "Test assignment name" "assign activity editing" page
And I set the following fields to these values:
| Group mode | Separate groups |
And I press "Save and return to course"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Group mode | Separate groups |
And I press "Save and display"
And the following "group members" exist:
| user | group |
| student0 | G1 |
| student1 | G1 |
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I set the field "Separate groups" to "Group 1"
And I should see "Group 1" in the "Student 0" "table_row"
And I should see "Group 1" in the "Student 1" "table_row"
And I should not see "Student 2"
And I set the field "Separate groups" to "All participants"
And I should see "Group 1" in the "Student 0" "table_row"
And I should see "Group 1" in the "Student 1" "table_row"
And I should see "Default group" in the "Student 2" "table_row"
And I should see "Default group" in the "Student 3" "table_row"
Scenario: Confirm that the grading status changes for each group member
Given the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| teamsubmission | 1 |
| preventsubmissionnotingroup | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student's first submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
Then "Student 1" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 2" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 3" row "Status" column of "generaltable" table should not contain "Submitted for grading"
And "Student 4" row "Status" column of "generaltable" table should not contain "Submitted for grading"
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student3 | I'm the student's first submission |
And I am on the "Test assignment name" Activity page
And I follow "View all submissions"
And "Student 1" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 2" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 3" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 4" row "Status" column of "generaltable" table should contain "Submitted for grading"
@javascript
Scenario: Confirm that group submissions can be reopened
Given the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| teamsubmission | 1 |
| attemptreopenmethod | manual |
| requireallteammemberssubmit | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student's first submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 50.0 |
| Apply grades and feedback to entire group | 1 |
And I press "Save changes"
And I set the following fields to these values:
| Allow another attempt | 1 |
And I press "Save changes"
When I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then "Student 1" row "Status" column of "generaltable" table should contain "Reopened"
And "Student 2" row "Status" column of "generaltable" table should contain "Reopened"
Scenario: Confirm groups and submission counts are correct
Given the following "groups" exist:
| name | course | idnumber |
| Group 2 | C1 | G2 |
| Group 3 | C1 | G3 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
| student3 | G3 |
And the following "groupings" exist:
| name | course | idnumber |
| Grouping 1 | C1 | GG1 |
And the following "grouping groups" exist:
| grouping | group |
| GG1 | G1 |
| GG1 | G2 |
# Groupmode 1 = Separate Groups
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| teamsubmission | 1 |
| attemptreopenmethod | manual |
| requireallteammemberssubmit | 0 |
| groupmode | 1 |
| teamsubmissiongroupingid | GG1 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student's first submission |
| Test assignment name | student2 | I'm the student's first submission |
| Test assignment name | student3 | I'm the student's first submission |
And I am on the "Test assignment name" Activity page logged in as admin
And I should see "3" in the "Groups" "table_row"
And I should see "3" in the "Submitted" "table_row"
When I select "Group 1" from the "Separate groups" singleselect
Then I should see "1" in the "Groups" "table_row"
And I should see "1" in the "Submitted" "table_row"
And I select "Group 2" from the "Separate groups" singleselect
And I should see "1" in the "Groups" "table_row"
And I should see "1" in the "Submitted" "table_row"
And I select "Group 3" from the "Separate groups" singleselect
And I should see "1" in the "Groups" "table_row"
And I should see "1" in the "Submitted" "table_row"
Scenario: Confirm that the submission status changes for each group member
Given the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 1 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| teamsubmission | 1 |
| attemptreopenmethod | manual |
| requireallteammemberssubmit | 0 |
# Groupmode 0 = No Groups
| groupmode | 0 |
| preventsubmissionnotingroup | 0 |
| submissiondrafts | 0 |
| teamsubmission | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student's first submission |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| activity_modules | Course | C1 | course-view-* | side-pre |
And I am on the "C1" Course page logged in as student1
And I click on "Assignments" "link" in the "Activities" "block"
And I should see "Submitted for grading"
And I am on the "C1" Course page logged in as student2
And I click on "Assignments" "link" in the "Activities" "block"
And I should see "Submitted for grading"
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
Then "Student 1" row "Status" column of "generaltable" table should contain "Submitted for grading"
And "Student 2" row "Status" column of "generaltable" table should contain "Submitted for grading"
@javascript @_file_upload
Scenario: Student can submit or edit group assignment depending on 'requireallteammemberssubmit' setting
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 2 | C2 | 0 | 2 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C2 | editingteacher |
| student1 | C2 | student |
| student2 | C2 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C2 | CG1 |
And the following "group members" exist:
| user | group |
| student1 | CG1 |
| student2 | CG1 |
And the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | assignsubmission_file_maxfiles | assignsubmission_file_maxsizebytes | submissiondrafts | teamsubmission | requireallteammemberssubmit |
| assign | C2 | Assign 1 | 1 | 1 | 1 | 2097152 | 1 | 1 | 1 |
| assign | C2 | Assign 2 | 1 | 1 | 1 | 2097152 | 0 | 1 | 0 |
# Submit an assignment with 'requireallteammemberssubmit' setting enabled
When I am on the "Assign 1" "assign activity" page logged in as student1
Then I should see "Group 1"
And I should not see "Student 2"
And I press "Add submission"
And I set the field "Online text" to "student1 submission"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
And I press "Save changes"
# Confirm that Submission status remains as draft and all students appear because 'Submit assignment' was not yet clicked
And I should see "Draft (not submitted)" in the "Submission status" "table_row"
And I should see "Users who need to submit: Student 1, Student 2"
And I press "Submit assignment"
And I press "Continue"
# Confirm that Submission status remains as draft and only student2 appears because student2 has not yet submitted assignment
And I am on the "Assign 1" "assign activity" page logged in as student2
And I should see "Draft (not submitted)" in the "Submission status" "table_row"
And I should see "Users who need to submit: Student 2"
And I press "Edit submission"
And I set the field "Online text" to "student2 updated submission"
And I delete "empty.txt" from "File submissions" filemanager
And I upload "lib/tests/fixtures/tabfile.csv" file to "File submissions" filemanager
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
# Confirm that Submission status is now Submitted for grading and all changes made by student2 is reflected on assignment
And I am on the "Assign 1" "assign activity" page logged in as student1
And I should see "Submitted for grading" in the "Submission status" "table_row"
And I should see "student2 updated submission" in the "Online text" "table_row"
And I should see "tabfile.csv" in the "File submissions" "table_row"
And I should not see "student1 submission" in the "Online text" "table_row"
And I should not see "empty.txt" in the "File submissions" "table_row"
# Submit an assignment with 'requireallteammemberssubmit' disabled
And I am on the "Assign 2" "assign activity" page logged in as student1
And I should see "Group 1"
And I should not see "Student 2"
And I press "Add submission"
And I set the field "Online text" to "student1 submission"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
And I press "Save changes"
# Confirm that Submission status is immediately set to Submitted for grading for all students after student1 submits assignments
And I am on the "Assign 2" "assign activity" page logged in as student2
And I should see "Submitted for grading" in the "Submission status" "table_row"
And I should not see "Users who need to submit"
Scenario: Group submission does not use non-participation groups
Given the following "groups" exist:
| name | course | idnumber | participation |
| Group A | C1 | CG1 | 0 |
And the following "group members" exist:
| group | user |
| CG1 | student1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| teamsubmission | 1 |
| groupmode | 1 |
When I am on the "Test assignment name" Activity page logged in as student1
Then I should see "Default group"
And I should not see "Group A"
@@ -0,0 +1,81 @@
@mod @mod_assign @_file_upload
Feature: Hide grader identities identity from students
In order to keep the grader's identity a secret
As a moodle teacher
I need to enable Hide Grader in the assignment settings
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
# Set up the test assignment
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| teamsubmission | 1 |
| asignsubmission_onlinetext_enabled | 0 |
| assignsubmission_file_enabled | 1 |
| assignsubmission_file_maxfiles | 2 |
| assignsubmission_file_maxsizebytes | 1000000 |
| assignfeedback_comments_enabled | 1 |
| hidegrader | 0 |
And the following "mod_assign > submission" exists:
| assign | Test assignment name |
| user | student1 |
| file | lib/tests/fixtures/empty.txt |
# Grade the submission and leave feedback
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should not see "Graded" in the "Student 1" "table_row"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Grade out of 100" to "50"
And I set the field "Feedback comments" to "Catch for us the foxes."
And I press "Save changes"
And I follow "Test assignment name"
And I follow "View all submissions"
And I should see "Graded" in the "Student 1" "table_row"
And I log out
@javascript
Scenario: Hidden grading is disabled.
Given I am on the "Test assignment name" Activity page logged in as student1
Then I should see "Graded" in the "Grading status" "table_row"
And I should see "Catch for us the foxes."
And I should see "Teacher" in the "Graded by" "table_row"
@javascript
Scenario: Hidden grading is enabled.
# Enable the hidden grader option
Given I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
And I set the field "Hide grader identity from students" to "1"
And I press "Save and return to course"
And I log out
# Check the student doesn't see the grader's identity
When I am on the "Test assignment name" Activity page logged in as student1
Then I should see "Graded" in the "Grading status" "table_row"
And I should see "Catch for us the foxes."
And I should not see "Graded by"
@javascript
Scenario: Hidden grading is enabled, but students have the 'view' capability.
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| mod/assign:showhiddengrader | Allow | student | Course | C1 |
When I am on the "Test assignment name" Activity page logged in as student1
And I should see "Graded" in the "Grading status" "table_row"
And I should see "Catch for us the foxes."
And I should see "Teacher" in the "Graded by" "table_row"
@@ -0,0 +1,80 @@
@mod @mod_assign
Feature: In an assignment, students can add and edit text online
In order to complete my submissions online
As a student
I need to submit my assignment editing an online form
@javascript
Scenario: Submit a text online and edit the submission
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_onlinetext_wordlimit_enabled | 1 |
| assignsubmission_onlinetext_wordlimit | 10 |
| assignsubmission_file_enabled | 0 |
And I am on the "Test assignment name" Activity page logged in as student1
When I press "Add submission"
And I set the following fields to these values:
| Online text | This is more than 10 words. 1 2 3 4 5 6 7 8 9 10. |
And I press "Save changes"
Then I should see "Please review your submission and try again."
And I set the following fields to these values:
| Online text | I'm the student first submission |
And I press "Save changes"
Then I should see "Submitted for grading"
And I should see "I'm the student first submission"
And I should see "Not graded"
And I press "Edit submission"
And I set the following fields to these values:
| Online text | I'm the student second submission |
And I press "Save changes"
Then I should see "Submitted for grading"
And I should see "I'm the student second submission"
And I should not see "I'm the student first submission"
@javascript
Scenario: Auto-draft save online text submission
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
And I am on the "Test assignment name" Activity page logged in as student1
When I press "Add submission"
And I set the following fields to these values:
| Online text | text submission |
# Wait for the draft auto save.
And I wait "2" seconds
And I am on the "Test assignment name" Activity page
When I press "Add submission"
# Confirm draft was restored.
Then the field "Online text" matches value "text submission"
@@ -0,0 +1,113 @@
@mod @mod_assign @core_outcome
Feature: Outcome grading
In order to give an outcome to my student
As a teacher
I need to grade a submission
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student0 | Student | 0 | student0@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student0 | C1 | student |
| student1 | C1 | student |
And the following config values are set as admin:
| enableoutcomes | 1 |
And the following "scales" exist:
| name | scale |
| Test Scale | Disappointing, Excellent, Good, Very good, Excellent |
And the following "grade outcomes" exist:
| fullname | shortname | scale |
| Outcome Test | OT | Test Scale |
And I am on the "Course 1" "grades > outcomes" page logged in as admin
And I set the field "Available standard outcomes" to "Outcome Test"
And I click on "#add" "css_element"
And I log out
@javascript
Scenario: Giving an outcome to a student
Given I log in as "teacher1"
And I add a assign activity to course "Course 1" section "1" and I fill the form with:
| Assignment name | Test assignment name |
| ID number | Test assignment name |
| Description | Test assignment description |
| assignsubmission_onlinetext_enabled | 1 |
| Outcome Test | 1 |
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I press "Add submission"
And I set the following fields to these values:
| Online text | My online text |
And I press "Save changes"
When I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 0" "table_row"
And I set the following fields to these values:
| Outcome Test: | Excellent |
And I press "Save changes"
And I click on "Edit settings" "link"
When I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Outcome Test: Excellent" in the "Student 0" "table_row"
And I should not see "Outcome Test: Excellent" in the "Student 1" "table_row"
@javascript
Scenario: Giving an outcome to a group submission
Given the following "users" exist:
| username | firstname | lastname | email |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| student2 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "group members" exist:
| user | group |
| student0 | G1 |
| student1 | G1 |
And I log in as "teacher1"
And I add a assign activity to course "Course 1" section "1" and I fill the form with:
| Assignment name | Test assignment name |
| Description | Test assignment description |
| ID number | Test assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| Students submit in groups | Yes |
| Group mode | No groups |
| Outcome Test | 1 |
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I press "Add submission"
And I set the following fields to these values:
| Online text | My online text |
And I press "Save changes"
When I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 0" "table_row"
And I set the following fields to these values:
| Outcome Test: | Excellent |
| Apply grades and feedback to entire group | Yes |
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
Then I should see "Outcome Test: Excellent" in the "Student 0" "table_row"
And I should see "Outcome Test: Excellent" in the "Student 1" "table_row"
And I should not see "Outcome Test: Excellent" in the "Student 2" "table_row"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Outcome Test: | Disappointing |
| Apply grades and feedback to entire group | No |
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I should see "Outcome Test: Excellent" in the "Student 0" "table_row"
And I should see "Outcome Test: Disappointing" in the "Student 1" "table_row"
And I should not see "Outcome Test: Disappointing" in the "Student 0" "table_row"
And I should not see "Outcome Test: Excellent" in the "Student 1" "table_row"
And I should not see "Outcome Test: Disappointing" in the "Student 2" "table_row"
And I should not see "Outcome Test: Excellent" in the "Student 2" "table_row"
@@ -0,0 +1,34 @@
@mod @mod_assign
Feature: In an assignment, page titles are informative
In order to know I am viewing the correct page
The page titles need to reflect the current assignment and action
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activities" exist:
| activity | course | name | intro | assignsubmission_onlinetext_enabled |
| assign | C1 | History of ants | Tell me the history of ants | 1 |
Scenario: I view an assignment as a student and take an action
When I am on the "History of ants" Activity page logged in as student1
Then the page title should contain "C1: History of ants"
And I press "Add submission"
And the page title should contain "C1: History of ants - Edit submission"
Scenario: I view an assignment as a teacher and take an action
When I am on the "History of ants" Activity page logged in as teacher1
Then the page title should contain "C1: History of ants"
And I follow "View all submissions"
And the page title should contain "C1: History of ants - Grading"
And I click on "Grade" "link" in the "Student 1" "table_row"
And the page title should contain "C1: History of ants - Grading"
@@ -0,0 +1,105 @@
@mod @mod_assign
Feature: Prevent or allow assignment submission changes
In order to control when a student can change his/her submission
As a teacher
I need to prevent or allow student submission at any time
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
@javascript
Scenario: Preventing changes and allowing them again
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student submission |
And I am on the "Test assignment name" Activity page logged in as student1
And I press "Edit submission"
And I set the following fields to these values:
| Online text | I'm the student submission and he/she edited me |
And I press "Save changes"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
And I follow "Prevent submission changes"
Then I should see "Submission changes not allowed"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And "Edit submission" "button" should not exist
And I should see "This assignment is not accepting submissions"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
And I follow "Allow submission changes"
And I should not see "Submission changes not allowed"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should not see "This assignment is not accepting submissions"
And I press "Edit submission"
And I set the following fields to these values:
| Online text | I'm the student submission edited again |
And I press "Save changes"
And I should see "I'm the student submission edited again"
@javascript @_alert
Scenario: Preventing changes and allowing them again (batch action)
Given the following "activities" exist:
| activity | course | name | intro | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled |
| assign | C1 | Test assignment name | Test assignment description | 1 | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student submission |
| Test assignment name | student2 | I'm the student2 submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
When I follow "View all submissions"
And I set the field "selectall" to "1"
And I click on "Go" "button" confirming the dialogue
Then I should see "Submission changes not allowed" in the "Student 1" "table_row"
And I should see "Submission changes not allowed" in the "Student 2" "table_row"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And I should not see "Edit submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I set the field "selectall" to "1"
And I set the field "id_operation" to "Unlock submissions"
And I click on "Go" "button" confirming the dialogue
And I should not see "Submission changes not allowed" in the "Student 1" "table_row"
And I should not see "Submission changes not allowed" in the "Student 2" "table_row"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And I press "Edit submission"
And I set the following fields to these values:
| Online text | I'm the student2 submission and he/she edited me |
And I press "Save changes"
+142
View File
@@ -0,0 +1,142 @@
@mod @mod_assign @javascript
Feature: In an assignment, teachers grade multiple students on one page
In order to quickly give students grades and feedback
As a teacher
I need to grade multiple students on one page
Scenario: Saving but not grading a grade should
not indicate the grade is graded.
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| intro | Submit your online text |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
When I click on "Grade" "link" in the "Student 1" "table_row"
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page
Then I should see "1" in the "Needs grading" "table_row"
@skip_chrome_zerosize
Scenario: Grade multiple students on one page
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following config values are set as admin:
| enableoutcomes | 1 |
When I am on the "Course 1" "grades > outcomes" page logged in as teacher1
And I press "Manage outcomes"
And I press "Add a new outcome"
And I follow "Add a new scale"
And I set the following fields to these values:
| Name | 1337dom scale |
| Scale | Noob, Nub, 1337, HaXor |
And I press "Save changes"
And I am on the "Course 1" "grades > outcomes" page
And I press "Manage outcomes"
And I press "Add a new outcome"
And I set the following fields to these values:
| Full name | M8d skillZ! |
| Short name | skillZ! |
| Scale | 1337dom scale |
And I press "Save changes"
And I add a assign activity to course "Course 1" section "1" and I fill the form with:
| Assignment name | Test assignment name |
| Description | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| M8d skillZ! | 1 |
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student1 submission |
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page logged in as student2
When I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student2 submission |
And I press "Save changes"
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 50.0 |
| M8d skillZ! | 1337 |
| Feedback comments | I'm the teacher first feedback |
And I press "Save changes"
And I follow "View all submissions"
Then I click on "Quick grading" "checkbox"
And I set the field "User grade" to "60.0"
And I press "Save all quick grading changes"
And I should see "The grade changes were saved"
And I press "Continue"
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I should see "I'm the teacher first feedback"
And I should see "60.0"
And I follow "Grades" in the user menu
And I click on "Course 1" "link" in the "region-main" "region"
And I should see "1337"
And I am on the "Test assignment name" "assign activity" page logged in as student2
And I should not see "I'm the teacher first feedback"
And I should not see "60.0"
And I follow "Grades" in the user menu
And I click on "Course 1" "link" in the "region-main" "region"
And I should not see "1337"
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Hide User picture" "link"
And I click on "Hide Full name" "link"
And I click on "Hide Email address" "link"
And I click on "Hide Status" "link"
And I click on "Hide Grade" "link"
And I click on "Hide Edit" "link"
And I click on "Hide Last modified (submission)" "link"
And I click on "Hide Online text" "link"
And I click on "Hide Submission comments" "link"
And I click on "Hide Last modified (grade)" "link"
And I click on "Hide Feedback comments" "link"
And I click on "Hide Final grade" "link"
And I click on "Hide Outcomes" "link"
And I press "Save all quick grading changes"
And I should see "The grade changes were saved"
And I press "Continue"
And I am on the "Test assignment name" "assign activity" page logged in as student1
And I should see "I'm the teacher first feedback"
And I should see "60.0"
And I follow "Grades" in the user menu
And I click on "Course 1" "link" in the "region-main" "region"
And I should see "1337"
And I am on the "Test assignment name" "assign activity" page logged in as student2
And I should not see "I'm the teacher first feedback"
And I should not see "60.0"
And I follow "Grades" in the user menu
And I click on "Course 1" "link" in the "region-main" "region"
And I should not see "1337"
@@ -0,0 +1,87 @@
@mod @mod_assign
Feature: Relative assignment due dates
In order for students to be able to enter the course at any time and have a fixed period in which to submit the assignment
As a teacher in course with relative dates mode enabled
I should be able to create an assignment with a due date relative to the course start date
Scenario: As a student the due date for submitting my assignment is relative to my course start date
Given the following config values are set as admin:
| enablecourserelativedates | 1 |
And the following "courses" exist:
| fullname | shortname | category | groupmode | relativedatesmode | startdate |
| Course 1 | C1 | 0 | 1 | 1 | ##first day of -4 months## |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
# Two students, one started 4 months ago and one yesterday.
| user | course | role | timestart |
| teacher1 | C1 | editingteacher | ##first day of last month## |
| student1 | C1 | student | ##first day of -4 months## |
| student2 | C1 | student | ##yesterday## |
# One assignment, valid for 2 months.
And the following "activities" exist:
| activity | name | course | assignsubmission_onlinetext_enabled | timeopen | duedate |
| assign | Test assignment name | C1 | 1 | ##first day of -4 months## | ##last day of -3 months## |
When I am on the "Test assignment name" Activity page logged in as student1
Then I should see "Assignment is overdue by:" in the "Time remaining" "table_row"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And I should not see "Assignment is overdue by:" in the "Time remaining" "table_row"
Scenario: As a student the due date I see for submitting my assignment is relative to my course start date
Given the following config values are set as admin:
| enablecourserelativedates | 1 |
And the following "courses" exist:
# A course with start date set to 1 Jan 2021.
| fullname | shortname | category | groupmode | relativedatesmode | startdate |
| Course 1 | C1 | 0 | 1 | 1 | 1609459200 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
# User's enrolment starts from 5 Jan 2021.
| user | course | role | timestart |
| student1 | C1 | student | 1609804800 |
And the following "activities" exist:
# The assignment's due date is 3 Jan 2021.
| activity | name | course | assignsubmission_onlinetext_enabled | duedate |
| assign | Test assignment name | C1 | 1 | 1609632000 |
When I am on the "Test assignment name" Activity page logged in as student1
Then the activity date in "Test assignment name" should contain "Due: Thursday, 7 January 2021, 8:00"
Scenario: As a teacher, I should see the relative dates when reviewing assignment submissions
Given the following config values are set as admin:
| enablecourserelativedates | 1 |
And the following "courses" exist:
| fullname | shortname | category | groupmode | relativedatesmode | startdate |
| Course 1 | C1 | 0 | 1 | 1 | ##first day of 4 months ago## |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
# Two students, one started 4 months ago and one yesterday.
| user | course | role | timestart |
| teacher1 | C1 | editingteacher | ##first day of 4 months ago## |
| student1 | C1 | student | ##first day of 4 months ago## |
| student2 | C1 | student | ##yesterday## |
# One assignment, valid for 2 months.
And the following "activities" exist:
| activity | name | course | assignsubmission_onlinetext_enabled | timeopen | duedate |
| assign | Test assignment name | C1 | 1 | ##first day of 4 months ago## | ##last day of 3 months ago## |
And I am on the "Test assignment name" Activity page logged in as teacher1
And the activity date in "Test assignment name" should contain "after course start"
And I should see "Calculated for each student" in the "Time remaining" "table_row"
When I follow "View all submissions"
Then I should see "No submission" in the "Student 1" "table_row"
And I should see "Assignment is overdue by:" in the "Student 1" "table_row"
And I should see "No submission" in the "Student 2" "table_row"
And I should not see "Assignment is overdue by:" in the "Student 2" "table_row"
@@ -0,0 +1,153 @@
@mod @mod_assign
Feature: Remove a submission
In order to restart an assignment for a student
As a teacher
I need to remove a student submission at any time
Background:
Given the following config values are set as admin:
| enabletimelimit | 1 | assign |
And the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "role capability" exists:
| role | editingteacher |
| mod/assign:editothersubmission | allow |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
@javascript @skip_chrome_zerosize
Scenario: Remove a submission should remove the data that was submitted
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
When I follow "Remove submission"
And I click on "Continue" "button"
Then I should not see "I'm the student submission"
And "Student 1" row "Status" column of "generaltable" table should contain "No submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should not see "I'm the student submission"
And I should see "No submissions have been made yet" in the "Submission status" "table_row"
@javascript @skip_chrome_zerosize
Scenario: Remove a group submission should remove the data from all group members
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| teamsubmission | 1 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
When I follow "Remove submission"
And I click on "Continue" "button"
Then I should not see "I'm the student submission"
And "Student 1" row "Status" column of "generaltable" table should contain "No submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student2
And I should not see "I'm the student submission"
And I should see "Nothing has been submitted for this assignment" in the "Submission status" "table_row"
@javascript @skip_chrome_zerosize
Scenario: A student can remove their own submission
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student submission |
And I am on the "Test assignment name" Activity page logged in as student1
And I click on "Remove submission" "button"
And I click on "Continue" "button"
And I log out
When I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
Then I should not see "I'm the student submission"
And "Student 1" row "Status" column of "generaltable" table should contain "No submission"
And I log out
And I am on the "Test assignment name" Activity page logged in as student1
And I should not see "I'm the student submission"
And I should see "No submissions have been made yet" in the "Submission status" "table_row"
@javascript @skip_chrome_zerosize @_file_upload
Scenario: Submission removal with time limit setting
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment with time limit |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 1 |
| assignsubmission_file_maxfiles | 1 |
| assignsubmission_file_maxsizebytes | 1000000 |
| submissiondrafts | 0 |
| allowsubmissionsfromdate_enabled | 0 |
| duedate_enabled | 0 |
| cutoffdate_enabled | 0 |
| gradingduedate_enabled | 0 |
And I am on the "Test assignment with time limit" Activity page logged in as admin
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Time limit' to 5 seconds.
And I set the field "timelimit[enabled]" to "1"
And I set the field "timelimit[number]" to "5"
And I set the field "timelimit[timeunit]" to "seconds"
And I press "Save and return to course"
When I am on the "Test assignment with time limit" Activity page logged in as student1
And I click on "Begin assignment" "link"
And I click on "Begin assignment" "button"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
And I press "Save changes"
And I click on "Remove submission" "button"
Then I should see "Are you sure you want to remove your submission? Please note that this will not reset your time limit."
And I press "Cancel"
And I am on the "Test assignment with time limit" Activity page logged in as admin
And I click on "View all submissions" "link"
And I open the action menu in "Student 1" "table_row"
And I follow "Remove submission"
And I should see "Are you sure you want to remove the submission for Student 1? Please note that this will not reset the student's time limit. You can give more time by adding a time limit user override."
@@ -0,0 +1,69 @@
@mod @mod_assign
Feature: Submissions are unlocked when a new attempt is given
In order to allow students to reattempt a locked submission
As a teacher
I need to use quick grading to grant a new submission
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
@javascript
Scenario: A locked submission should unlock when a new attempt is automatically given.
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| attemptreopenmethod | untilpass |
| gradepass | 50 |
| submissiondrafts | 0 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I open the action menu in "Student 1" "table_row"
And I follow "Prevent submission changes"
And I should see "Submission changes not allowed"
And I click on "Quick grading" "checkbox"
And I set the field "User grade" to "49.0"
And I press "Save all quick grading changes"
And I should see "The grade changes were saved"
And I press "Continue"
Then I should see "Reopened"
And I should not see "Submission changes not allowed"
@javascript
Scenario: A locked submission should unlock when a new attempt is manually given.
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| attemptreopenmethod | manual |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student1 submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
When I open the action menu in "Student 1" "table_row"
And I follow "Prevent submission changes"
Then I should see "Submission changes not allowed"
And I open the action menu in "Student 1" "table_row"
And I follow "Allow another attempt"
And I should see "Reopened"
And I should not see "Submission changes not allowed"
@@ -0,0 +1,85 @@
@mod @mod_assign @javascript
Feature: Check that the assignment grade can be rescaled when the max grade is changed
In order to ensure that the percentages are not affected by changes to the max grade
As a teacher
I need to rescale all grades when updating the max grade
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student10@example.com |
| student2 | Student | 2 | student10@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Grade out of 100" to "40"
And I press "Save changes"
And I follow "View all submissions"
And "Student 1" row "Grade" column of "generaltable" table should contain "40.00"
And I am on the "Test assignment name" "assign activity" page
Scenario: Update the max grade for an assignment without rescaling existing grades
Given I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Rescale existing grades" to "No"
And I set the field "Maximum grade" to "80"
When I press "Save and display"
And I follow "View all submissions"
Then "Student 1" row "Grade" column of "generaltable" table should contain "40.00"
Scenario: Update an assignment without touching the max grades
Given I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Rescale existing grades" to "No"
And I set the field "Maximum grade" to "80"
And I press "Save and display"
And I navigate to "Settings" in current page administration
And I press "Save and display"
And I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Rescale existing grades" to "Yes"
And I set the field "Maximum grade" to "80"
When I press "Save and display"
And I follow "View all submissions"
Then "Student 1" row "Grade" column of "generaltable" table should contain "40.00"
Scenario: Update the max grade for an assignment rescaling existing grades
Given I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Rescale existing grades" to "Yes"
And I set the field "Maximum grade" to "50"
When I press "Save and display"
And I follow "View all submissions"
Then "Student 1" row "Grade" column of "generaltable" table should contain "20.00"
Scenario: Rescaling should not produce negative grades
Given I follow "View all submissions"
And I click on "Grade" "link" in the "Student 2" "table_row"
And I wait until the page is ready
And I am on the "Test assignment name" "assign activity" page
And I navigate to "Settings" in current page administration
And I expand all fieldsets
And I set the field "Rescale existing grades" to "Yes"
And I set the field "Maximum grade" to "50"
When I press "Save and display"
And I follow "View all submissions"
# Make sure the student did not receive a negative grade.
Then "Student 2" row "Grade" column of "generaltable" table should not contain "-0.50"
@@ -0,0 +1,238 @@
@mod @mod_assign @javascript
Feature: Set availability dates for an assignment
In order to control when a student can upload an assignment
As a teacher
I need be able to set availability dates for an assignment
Background:
Given I log in as "admin"
And I set the following administration settings values:
| Enable timed assignments | 1 |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Assignment name |
| description | Assignment description |
| assignsubmission_file_enabled | 1 |
| assignsubmission_file_maxfiles | 1 |
| assignsubmission_file_maxsizebytes | 0 |
| submissiondrafts | 0 |
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test late assignment with time limit |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 1 |
| assignsubmission_file_maxfiles | 1 |
| assignsubmission_file_maxsizebytes | 1000000 |
| submissiondrafts | 0 |
| allowsubmissionsfromdate_enabled | 0 |
| duedate_enabled | 0 |
| cutoffdate_enabled | 0 |
| gradingduedate_enabled | 0 |
Scenario: Student cannot submit an assignment prior to the 'allow submissions from' date
Given I am on the "Assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Allow submissions from' to tomorrow at noon.
And I set the field "Allow submissions from" to "##tomorrow noon##"
And I press "Save and return to course"
And I log out
When I am on the "Assignment name" Activity page logged in as student1
Then "Add submission" "button" should not exist
And the activity date in "Assignment name" should contain "Opens:"
And the activity date in "Assignment name" should contain "##tomorrow noon##%A, %d %B %Y, %I:%M##"
Scenario: Student can see the assignment's due date in the course calendar
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Assignment name |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
| allowsubmissionsfromdate | ##first day of this month noon## |
| duedate | ##first day of this month noon +24 hours## |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| calendar_month | Course | C1 | course-view-* | site-post |
When I am on the "C1" Course page logged in as student1
And I hover over day "2" of this month in the mini-calendar block
Then I should see "Assignment name is due"
@_file_upload
Scenario: Student can submit an assignment before the due date
Given I am on the "Assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Allow submissions from' to now.
And I set the field "Allow submissions from" to "##now##"
# Set 'Due date' to 2 days 5 hours 30 minutes in the future.
And I set the field "Due date" to "##+2 days 5 hours 30 minutes##"
And I press "Save and return to course"
And I log out
When I am on the "Assignment name" Activity page logged in as student1
And the activity date in "Assignment name" should contain "Due:"
And the activity date in "Assignment name" should contain "##+2 days 5 hours 30 minutes##%A, %d %B %Y##"
And I should see "2 days 5 hours" in the "Time remaining" "table_row"
And "Add submission" "button" should exist
And I press "Add submission"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
When I press "Save changes"
Then I should see "Submitted for grading" in the "Submission status" "table_row"
And I log out
And I am on the "Assignment name" Activity page logged in as teacher1
And I should see "1" in the "Submitted" "table_row"
And I follow "View all submissions"
And I should see "Submitted for grading" in the "Student 1" "table_row"
@_file_upload
Scenario: Student can submit an assignment after the due date and the submission is marked as late
Given I am on the "Assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Allow submissions from' to 3 days ago.
And I set the field "Allow submissions from" to "##3 days ago##"
# Set 'Due date' to 2 days 5 hours 30 minutes ago.
And I set the field "Due date" to "##2 days 5 hours 30 minutes ago##"
# Set 'Cut-off date' to tomorrow at noon.
And I set the field "Cut-off date" to "##tomorrow noon##"
And I press "Save and return to course"
And I log out
And I am on the "Assignment name" Activity page logged in as student1
And the activity date in "Assignment name" should contain "Due:"
And the activity date in "Assignment name" should contain "##2 days 5 hours 30 minutes ago##%A, %d %B %Y##"
And I should see "Assignment is overdue by: 2 days 5 hours" in the "Time remaining" "table_row"
And "Add submission" "button" should exist
And I press "Add submission"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
When I press "Save changes"
Then I should see "Submitted for grading" in the "Submission status" "table_row"
And I should see "Assignment was submitted 2 days 5 hours late" in the "Time remaining" "table_row"
And I log out
And I am on the "Assignment name" Activity page logged in as teacher1
And I should see "1" in the "Submitted" "table_row"
And I follow "View all submissions"
And I should see "Submitted for grading" in the "Student 1" "table_row"
And I should see "2 days 5 hours late" in the "Student 1" "table_row"
@_file_upload
Scenario: Student can submit an assignment before the time limit runs out
Given I log in as "admin"
And I change the window size to "large"
And I set the following administration settings values:
| Enable timed assignments | 1 |
And I log out
And I am on the "Assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Time limit' to 20 seconds.
And I set the field "timelimit[enabled]" to "1"
And I set the field "timelimit[number]" to "20"
And I set the field "timelimit[timeunit]" to "seconds"
And I press "Save and return to course"
And I log out
When I am on the "Assignment name" Activity page logged in as student1
And I should see "20 secs" in the "Time limit" "table_row"
And "Begin assignment" "link" should exist
And I follow "Begin assignment"
And I wait "1" seconds
And "Begin assignment" "button" should exist
And I press "Begin assignment"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
When I press "Save changes"
Then I should see "Submitted for grading" in the "Submission status" "table_row"
And I should see "secs under the time limit" in the "Time remaining" "table_row"
@_file_upload
Scenario: Assignment with time limit and due date shows how late assignment is submitted relative to due date
Given I log in as "admin"
And I change the window size to "large"
And I set the following administration settings values:
| Enable timed assignments | 1 |
And I log out
And I am on the "Assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Time limit' to 5 seconds.
And I set the field "timelimit[enabled]" to "1"
And I set the field "timelimit[number]" to "5"
And I set the field "timelimit[timeunit]" to "seconds"
# Set 'Due date' to 2 days 5 hours 30 minutes ago.
And I set the field "Due date" to "##2 days 5 hours 30 minutes ago##"
And I press "Save and display"
And I should see "5 secs" in the "Time limit" "table_row"
And I log out
When I am on the "Assignment name" Activity page logged in as student1
And "Begin assignment" "link" should exist
And I follow "Begin assignment"
And I wait "1" seconds
And "Begin assignment" "button" should exist
And I press "Begin assignment"
And I wait "5" seconds
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
When I press "Save changes"
Then I should see "Assignment was submitted 2 days 5 hours late" in the "Time remaining" "table_row"
Scenario: Student cannot submit an assignment after the cut-off date
Given I am on the "Assignment name" Activity page logged in as teacher1
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Allow submissions from' to 3 days ago.
And I set the field "Allow submissions from" to "##3 days ago##"
# Set 'Due date' to 2 days 5 hours 30 minutes ago.
And I set the field "Due date" to "##2 days 5 hours 30 minutes ago##"
# Set 'Cut-off date' to yesterday at noon.
And I set the field "Cut-off date" to "##yesterday noon##"
And I press "Save and return to course"
And I log out
When I am on the "Assignment name" Activity page logged in as student1
Then "Add submission" "button" should not exist
And I log out
And I am on the "Assignment name" Activity page logged in as teacher1
And I should see "0" in the "Submitted" "table_row"
And I follow "View all submissions"
And I should see "No submission" in the "Student 1" "table_row"
And I should see "Assignment is overdue by: 2 days 5 hours" in the "Student 1" "table_row"
@_file_upload
Scenario: Late submission will be calculated only when the student starts the assignment
Given I am on the "Test late assignment with time limit" Activity page logged in as admin
And I navigate to "Settings" in current page administration
And I click on "Expand all" "link" in the "region-main" "region"
# Set 'Time limit' to 5 seconds.
And I set the field "timelimit[enabled]" to "1"
And I set the field "timelimit[number]" to "5"
And I set the field "timelimit[timeunit]" to "seconds"
And I press "Save and return to course"
When I am on the "Test late assignment with time limit" Activity page logged in as student1
And I wait "6" seconds
And I click on "Begin assignment" "link"
And I click on "Begin assignment" "button"
And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager
And I press "Save changes"
Then I should see "Submitted for grading" in the "Submission status" "table_row"
And I should see "under the time limit" in the "Time remaining" "table_row"
@@ -0,0 +1,98 @@
@mod @mod_assign
Feature: Assignments correctly add feedback to the grade report when workflow and blind marking are enabled.
In order to give students feedback when blind marking
As a teacher
I should be able to reveal student identities at any time and have my feedback show
to the student in the gradebook when the grades are in a released state.
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
| submissiondrafts | 0 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| assignfeedback_comments_enabled | 1 |
| teamsubmission | 1 |
| markingworkflow | 1 |
| blindmarking | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student's first submission |
# Mark the submission.
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I should see "Not marked" in the "I'm the student's first submission" "table_row"
And I click on "Grade" "link" in the "I'm the student's first submission" "table_row"
And I set the field "Grade out of 100" to "50"
And I set the field "Marking workflow state" to "In review"
And I set the field "Feedback comments" to "Great job! Lol, not really."
And I set the field "Notify student" to "0"
And I press "Save changes"
And I follow "View all submissions"
And I should see "In review" in the "I'm the student's first submission" "table_row"
@javascript
Scenario: Student identities are revealed after releasing the grades.
When I click on "Grade" "link" in the "I'm the student's first submission" "table_row"
And I set the field "Marking workflow state" to "Ready for release"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I follow "View all submissions"
And I should see "Ready for release" in the "I'm the student's first submission" "table_row"
And I click on "Grade" "link" in the "I'm the student's first submission" "table_row"
And I set the field "Marking workflow state" to "Released"
And I press "Save changes"
And I follow "View all submissions"
And I should see "Released" in the "I'm the student's first submission" "table_row"
And I set the field "Grading action" to "Reveal student identities"
And I press "Continue"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should see "50"
And I should see "Great job! Lol, not really."
@javascript
Scenario: Student identities are revealed before releasing the grades.
When I click on "Grade" "link" in the "I'm the student's first submission" "table_row"
And I set the field "Marking workflow state" to "Ready for release"
And I set the field "Notify student" to "0"
And I press "Save changes"
And I follow "View all submissions"
And I should see "Ready for release" in the "I'm the student's first submission" "table_row"
And I set the field "Grading action" to "Reveal student identities"
And I press "Continue"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the field "Marking workflow state" to "Released"
And I press "Save changes"
And I follow "View all submissions"
And I should see "Released" in the "Student 1" "table_row"
And I am on the "Course 1" "grades > User report > View" page logged in as "student1"
Then I should see "50"
And I should see "Great job! Lol, not really."
@javascript
Scenario: Submissions table visible with overrides and blind marking
When I am on the "Test assignment name" "assign activity" page
And I navigate to "Overrides" in current page administration
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student |
| Due date | ##2030-01-01 08:00## |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I am on the "Test assignment name" "assign activity" page
And I follow "View all submissions"
And I should see "In review" in the "I'm the student's first submission" "table_row"
@@ -0,0 +1,115 @@
@mod @mod_assign @javascript
Feature: In an assignment, students can comment in their submissions
In order to refine assignment submissions
As a student
I need to add comments about submissions
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
Scenario: Student comments an assignment submission
Given the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled |
| assign | C1 | Test assignment name | 1 |
And I am on the "Test assignment name" Activity page logged in as student1
When I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student submission |
And I press "Save changes"
And I click on ".comment-link" "css_element"
And I set the field "content" to "First student comment"
And I follow "Save comment"
Then I should see "First student comment"
And the field "content" matches value "Add a comment..."
And I click on "Delete comment posted by Student 1" "link"
# Wait for the animation to finish.
And I wait "2" seconds
And I set the field "content" to "Second student comment"
And I follow "Save comment"
And I should see "Second student comment"
And I should not see "First student comment"
And I am on the "Test assignment name" "assign activity" page
And I click on ".comment-link" "css_element"
And I should see "Second student comment"
And I should not see "First student comment"
Scenario: Teacher updated the comment box and clicked the save changes to reflect the comment
Given the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled |
| assign | C1 | Test assignment name | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | student one submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I click on ".comment-link" "css_element"
When I set the field "content" to "Teacher feedback first comment"
And I press "Save changes"
And I should see "Comments (1)" in the ".comment-link" "css_element"
And I click on ".comment-link" "css_element"
Then I should see "Teacher feedback first comment" in the ".comment-list" "css_element"
Scenario: Teacher updated the comment box and clicked on save and show next to reflect the comment
Given the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled |
| assign | C1 | Test assignment name | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Test assignment name | student1 | I'm the student submission |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I click on ".comment-link" "css_element"
When I set the field "content" to "Teacher feedback first comment"
# click the save and show next twice as we have only 2 students
# so the second time you click we reach the same student who made
# the change
And I press "Save and show next"
And I press "Save and show next"
And I click on ".comment-link" "css_element"
Then I should see "Teacher feedback first comment" in the ".comment-list" "css_element"
Scenario: Teacher can comment on an offline assignment
Given the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled | assignmentsubmission_file_enabled | assignfeedback_comments_enabled |
| assign | C1 | Test assignment name | 0 | 0 | 1 |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
When I set the following fields to these values:
| Grade out of 100 | 50 |
| Feedback comments | I'm the teacher feedback |
And I press "Save changes"
And I follow "View all submissions"
Then I should see "50.00" in the "Student 1" "table_row"
And I should see "I'm the teacher feedback" in the "Student 1" "table_row"
Scenario: Teacher can comment on assignments with a zero grade
Given the following "activities" exist:
| activity | course | name | assignsubmission_onlinetext_enabled | assignmentsubmission_file_enabled | assignfeedback_comments_enabled |
| assign | C1 | Test assignment name | 0 | 0 | 1 |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 0 |
And I press "Save changes"
And I should see "The changes to the grade and feedback were saved"
And I set the following fields to these values:
| Feedback comments | I'm the teacher feedback |
And I press "Save changes"
Then I should see "The changes to the grade and feedback were saved"
@@ -0,0 +1,53 @@
@mod @mod_assign @javascript
Feature: Manage assignment submission web notifications
In order to receive assignment submission notifications
As a teacher
I need to be able to turn on web notifications for assignment submission
Background:
# Turn off the course welcome message, so we can easily test other messages.
Given the following config values are set as admin:
| sendcoursewelcomemessage | 0 | enrol_manual |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "user preferences" exist:
| user | preference | value |
| teacher1 | message_provider_mod_assign_assign_notification_enabled | none |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Assign 1 |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_file_enabled | 0 |
| submissiondrafts | 0 |
| sendnotifications | 1 |
And the following "mod_assign > submissions" exist:
| assign | user | onlinetext |
| Assign 1 | student1 | I'm the student1 submission |
Scenario: Teacher can choose to receive assignment notification submissions
Given I log in as "teacher1"
When I open the notification popover
Then I should see "You have no notifications"
# Update assignment submission to generate a notification
And I am on the "Assign 1" "assign activity" page logged in as student1
And the following "user preferences" exist:
| user | preference | value |
| teacher1 | message_provider_mod_assign_assign_notification_enabled | popup |
# This should generate a notification
And I press "Edit submission"
And I set the field "Online text" to "updated"
And I press "Save changes"
# Confirm that teacher received assignment submission notification
And I log in as "teacher1"
And I open the notification popover
Then I should see "Student 1 has updated their submission for assignment Assign 1"
@@ -0,0 +1,68 @@
@mod @mod_assign
Feature: In an assignment, teacher can require submission statements
In order to require students to accept an assignment submission statement
As a teacher
I need to enable "Require that students accept the submission statement"
Background:
Given the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Terry | Teacher | teacher1@example.com |
| student1 | Sam | Student | student1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assign |
| submissiondrafts | 1 |
| requiresubmissionstatement | 1 |
| assignsubmission_onlinetext_enabled | 1 |
Scenario: Student is required to accept assignment submission statement
Given I am on the "Test assign" "assign activity" page logged in as student1
And I press "Add submission"
And I set the field "Online text" to "My submission text."
And I press "Save changes"
And I should see "Draft (not submitted)" in the "Submission status" "table_row"
When I press "Submit assignment"
Then I should see "This submission is my own work, except where I have acknowledged the use of the works of other people."
And I press "Continue"
And I should see "Confirm submission"
And I should see "You are required to agree to this statement before you can submit."
And I set the field "submissionstatement" to "1"
And I press "Continue"
And I should see "Submitted for grading" in the "Submission status" "table_row"
Scenario: Student is not required to accept assignment submission statement when non exists
Given the following config values are set as admin:
| config | value | plugin |
| submissionstatement | | assign |
And I am on the "Test assign" "assign activity" page logged in as student1
When I press "Add submission"
And I set the field "Online text" to "My submission text."
And I press "Save changes"
And I should see "Draft (not submitted)" in the "Submission status" "table_row"
And I press "Submit assignment"
And I press "Continue"
Then I should see "Submitted for grading" in the "Submission status" "table_row"
Scenario: Student is not required to accept assignment submission statement
Given I am on the "Test assign" "assign activity editing" page logged in as teacher1
And I set the following fields to these values:
| Require that students accept the submission statement | No |
And I press "Save and display"
And I am on the "Test assign" "assign activity" page logged in as student1
And I press "Add submission"
And I set the field "Online text" to "My submission text."
And I press "Save changes"
And I should see "Draft (not submitted)" in the "Submission status" "table_row"
When I press "Submit assignment"
Then I should not see "This submission is my own work, except where I have acknowledged the use of the works of other people."
And I press "Continue"
And I should see "Submitted for grading" in the "Submission status" "table_row"
@@ -0,0 +1,203 @@
@mod @mod_assign
Feature: Submit assignment without group
As a teacher
I should be able to prevent students submitting team assignments as members of the default group
@javascript
Scenario: Switch between group modes
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
| Course 2 | C2 | 0 | 1 |
| Course 3 | C3 | 0 | 1 |
And the following "activities" exist:
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | preventsubmissionnotingroup | teamsubmission |
| assign | C1 | c1assign1 | Allow default group | Test assignment description | 1 | 0 | 1 |
| assign | C1 | c1assign2 | Require group membership | Test assignment description | 1 | 1 | 1 |
| assign | C2 | c2assign1 | Require group membership | Test assignment description | 1 | 1 | 1 |
| assign | C3 | c3assign1 | Require group membership | Test assignment description | 1 | 1 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C2 | GC21 |
| Group 1 | C3 | GC31 |
| Group 2 | C3 | GC32 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| teacher1 | C2 | editingteacher |
| student1 | C2 | student |
| student2 | C2 | student |
| teacher1 | C3 | editingteacher |
| student3 | C3 | student |
And the following "group members" exist:
| user | group |
| student1 | GC21 |
| student2 | GC21 |
| student3 | GC31 |
| student3 | GC32 |
# Student 1 can only submit assignment in course 2.
When I am on the "c1assign1" "assign activity" page logged in as student1
Then I should not see "Not a member of any group"
And I should not see "This assignment requires submission in groups. You are not a member of any group"
And I should see "Nothing has been submitted for this assignment"
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student submission |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And I should see "Submitted for grading"
And I am on the "c1assign2" "assign activity" page
And I should see "Not a member of any group"
And I should see "This assignment requires submission in groups. You are not a member of any group"
And I should see "Nothing has been submitted for this assignment"
And I should not see "Add submission"
And I am on the "c2assign1" "assign activity" page
And I should not see "Not a member of any group"
And I should see "Nothing has been submitted for this assignment"
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student submission |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And I should see "Submitted for grading"
And I log out
# Student 2 should see submitted for grading.
And I am on the "c1assign1" "assign activity" page logged in as student2
And I should see "Submitted for grading"
And I am on the "c2assign1" "assign activity" page
And I should see "Submitted for grading"
And I log out
# Teacher should see student 1 and student 2 has submitted assignment.
And I am on the "c1assign1" "assign activity" page logged in as teacher1
And I should see "1" in the "Groups" "table_row"
And I should not see "The setting 'Require group to make submission\' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I follow "View all submissions"
And I should see "Default group" in the "Student 1" "table_row"
And I should see "Default group" in the "Student 2" "table_row"
And I should see "Submitted for grading" in the "Student 1" "table_row"
And I should see "Submitted for grading" in the "Student 2" "table_row"
And I am on the "c1assign2" "assign activity" page
And I should see "0" in the "Groups" "table_row"
And I should see "The setting 'Require group to make submission' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I follow "View all submissions"
And I should see "Not a member of any group, so unable to make submissions." in the "Student 1" "table_row"
And I should see "Not a member of any group, so unable to make submissions." in the "Student 2" "table_row"
And I should not see "Submitted for grading" in the "Student 1" "table_row"
And I should not see "Submitted for grading" in the "Student 2" "table_row"
And I am on the "c2assign1" "assign activity" page
And I should see "1" in the "Groups" "table_row"
And I should not see "The setting 'Require group to make submission' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I follow "View all submissions"
And I should see "Group 1" in the "Student 1" "table_row"
And I should see "Group 1" in the "Student 2" "table_row"
And I should see "Submitted for grading" in the "Student 1" "table_row"
And I should see "Submitted for grading" in the "Student 2" "table_row"
And I log out
# Test student 3 (in multiple groups) should not be able to submit.
And I am on the "c3assign1" "assign activity" page logged in as student3
And I should see "Member of more than one group"
And I should see "The assignment requires submission in groups. You are a member of more than one group."
And I should see "Nothing has been submitted for this assignment"
And I should not see "Add submission"
And I log out
And I am on the "c3assign1" "assign activity" page logged in as teacher1
And I should see "The setting 'Require group to make submission' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I follow "View all submissions"
And I should see "Member of more than one group, so unable to make submissions." in the "Student 3" "table_row"
Scenario: All users are in groups, so no warning messages needed.
Given the following "courses" exist:
| fullname | shortname | groupmode |
| Course 1 | C1 | 0 |
And the following "activities" exist:
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | preventsubmissionnotingroup | teamsubmission |
| assign | C1 | assign1 | Allow default group | Test assignment description | 1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
When I am on the "Allow default group" "assign activity" page logged in as teacher1
Then I should not see "The setting 'Require group to make submission\' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I should not see "The setting 'Students submit in groups' is enabled and some users are either not a member of any group, or are a member of more than one group. Please be aware that these students will submit as members of the 'Default group'."
Scenario: One user is not in a group, so should see a warning about default group submission
Given the following "courses" exist:
| fullname | shortname | groupmode |
| Course 1 | C1 | 0 |
And the following "activities" exist:
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | preventsubmissionnotingroup | teamsubmission |
| assign | C1 | assign1 | Allow default group | Test assignment description | 1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "group members" exist:
| user | group |
| student1 | G1 |
When I am on the "Allow default group" "assign activity" page logged in as teacher1
Then I should not see "The setting 'Require group to make submission\' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I should see "The setting 'Students submit in groups' is enabled and some users are either not a member of any group, or are a member of more than one group. Please be aware that these students will submit as members of the 'Default group'."
Scenario: One user is a member of multiple groups, so should see a warning about default group submission
Given the following "courses" exist:
| fullname | shortname | groupmode |
| Course 1 | C1 | 0 |
And the following "activities" exist:
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | preventsubmissionnotingroup | teamsubmission |
| assign | C1 | assign1 | Allow default group | Test assignment description | 1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
| student2 | G2 |
When I am on the "Allow default group" "assign activity" page logged in as teacher1
Then I should not see "The setting 'Require group to make submission\' is enabled and some users are either not a member of any group, or are a member of more than one group, so are unable to make submissions."
And I should see "The setting 'Students submit in groups' is enabled and some users are either not a member of any group, or are a member of more than one group. Please be aware that these students will submit as members of the 'Default group'."
+239
View File
@@ -0,0 +1,239 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains unit tests for core_completion/activity_custom_completion.
*
* @package mod_assign
* @copyright Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
declare(strict_types=1);
namespace mod_assign;
use advanced_testcase;
use cm_info;
use coding_exception;
use mod_assign\completion\custom_completion;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/completionlib.php');
require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
/**
* Class for unit testing mod_assign/activity_custom_completion.
*
* @package mod_assign
* @copyright Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class custom_completion_test extends advanced_testcase {
// Use the generator helper.
use \mod_assign_test_generator;
/**
* Data provider for get_state().
*
* @return array[]
*/
public function get_state_provider(): array {
return [
'Undefined rule' => [
'somenonexistentrule', COMPLETION_DISABLED, false, null, coding_exception::class
],
'Rule not available' => [
'completionsubmit', COMPLETION_DISABLED, false, null, moodle_exception::class
],
'Rule available, user has not submitted' => [
'completionsubmit', COMPLETION_ENABLED, false, COMPLETION_INCOMPLETE, null
],
'Rule available, user has submitted' => [
'completionsubmit', COMPLETION_ENABLED, true, COMPLETION_COMPLETE, null
],
];
}
/**
* Test for get_state().
*
* @dataProvider get_state_provider
* @param string $rule The custom completion rule.
* @param int $available Whether this rule is available.
* @param bool $submitted
* @param int|null $status Expected status.
* @param string|null $exception Expected exception.
*/
public function test_get_state(string $rule, int $available, ?bool $submitted, ?int $status, ?string $exception): void {
if (!is_null($exception)) {
$this->expectException($exception);
}
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
$assign = $this->create_instance($course, ['completion' => COMPLETION_TRACKING_AUTOMATIC, $rule => $available]);
// Submit the assignment as the student.
$this->setUser($student);
if ($submitted == true) {
$this->add_submission($student, $assign);
$this->submit_for_grading($student, $assign);
}
$cm = cm_info::create($assign->get_course_module());
$customcompletion = new custom_completion($cm, (int)$student->id);
$this->assertEquals($status, $customcompletion->get_state($rule));
}
/**
* Test for get_state().
*
* @dataProvider get_state_provider
* @param string $rule The custom completion rule.
* @param int $available Whether this rule is available.
* @param bool $submitted
* @param int|null $status Expected status.
* @param string|null $exception Expected exception.
*/
public function test_get_state_group(string $rule, int $available, ?bool $submitted, ?int $status, ?string $exception): void {
if (!is_null($exception)) {
$this->expectException($exception);
}
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
$assign = $this->create_instance($course, ['completion' => COMPLETION_TRACKING_AUTOMATIC, $rule => $available,
'teamsubmission' => 1]);
// Submit the assignment as the student.
$this->setUser($student);
if ($submitted == true) {
$this->add_submission($student, $assign);
$this->submit_for_grading($student, $assign);
}
$cm = cm_info::create($assign->get_course_module());
$customcompletion = new custom_completion($cm, (int)$student->id);
$this->assertEquals($status, $customcompletion->get_state($rule));
}
/**
* Test for get_defined_custom_rules().
*/
public function test_get_defined_custom_rules(): void {
$rules = custom_completion::get_defined_custom_rules();
$this->assertCount(1, $rules);
$this->assertEquals('completionsubmit', reset($rules));
}
/**
* Test for get_defined_custom_rule_descriptions().
*/
public function test_get_custom_rule_descriptions(): void {
$this->resetAfterTest();
// Get defined custom rules.
$rules = custom_completion::get_defined_custom_rules();
// Get custom rule descriptions.
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
$assign = $this->create_instance($course, [
'submissiondrafts' => 0,
'completionusegrade' => 1
]);
$cm = cm_info::create($assign->get_course_module());
$customcompletion = new custom_completion($cm, 1);
$ruledescriptions = $customcompletion->get_custom_rule_descriptions();
// Confirm that defined rules and rule descriptions are consistent with each other.
$this->assertEquals(count($rules), count($ruledescriptions));
foreach ($rules as $rule) {
$this->assertArrayHasKey($rule, $ruledescriptions);
}
}
/**
* Test for is_defined().
*/
public function test_is_defined(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
$assign = $this->create_instance($course, [
'submissiondrafts' => 0,
'completionsubmit' => 1
]);
$cm = cm_info::create($assign->get_course_module());
$customcompletion = new custom_completion($cm, 1);
// Rule is defined.
$this->assertTrue($customcompletion->is_defined('completionsubmit'));
// Undefined rule.
$this->assertFalse($customcompletion->is_defined('somerandomrule'));
}
/**
* Data provider for test_get_available_custom_rules().
*
* @return array[]
*/
public function get_available_custom_rules_provider(): array {
return [
'Completion submit available' => [
COMPLETION_ENABLED, ['completionsubmit']
],
'Completion submit not available' => [
COMPLETION_DISABLED, []
],
];
}
/**
* Test for get_available_custom_rules().
*
* @dataProvider get_available_custom_rules_provider
* @param int $status
* @param array $expected
*/
public function test_get_available_custom_rules(int $status, array $expected): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course(['enablecompletion' => $status]);
$params = [];
if ($status == COMPLETION_ENABLED ) {
$params = [
'completion' => COMPLETION_TRACKING_AUTOMATIC,
'completionsubmit' => 1
];
}
$assign = $this->create_instance($course, $params);
$cm = cm_info::create($assign->get_course_module());
$customcompletion = new custom_completion($cm, 1);
$this->assertEquals($expected, $customcompletion->get_available_custom_rules());
}
}
+189
View File
@@ -0,0 +1,189 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains unit tests for mod_assign\dates.
*
* @package mod_assign
* @category test
* @copyright 2021 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
declare(strict_types=1);
namespace mod_assign;
use advanced_testcase;
use cm_info;
use core\activity_dates;
/**
* Class for unit testing mod_assign\dates.
*
* @copyright 2021 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dates_test extends advanced_testcase {
/**
* Data provider for get_dates_for_module().
* @return array[]
*/
public function get_dates_for_module_provider(): array {
$now = time();
$before = $now - DAYSECS;
$earlier = $before - DAYSECS;
$after = $now + DAYSECS;
$later = $after + DAYSECS;
return [
'without any dates' => [
null, null, null, null, null, null, []
],
'only with opening time' => [
$after, null, null, null, null, null, [
['label' => get_string('activitydate:submissionsopen', 'mod_assign'), 'timestamp' => $after,
'dataid' => 'allowsubmissionsfromdate'],
]
],
'only with closing time' => [
null, $after, null, null, null, null, [
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $after,
'dataid' => 'duedate'],
]
],
'with both times' => [
$after, $later, null, null, null, null, [
['label' => get_string('activitydate:submissionsopen', 'mod_assign'), 'timestamp' => $after,
'dataid' => 'allowsubmissionsfromdate'],
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $later,
'dataid' => 'duedate'],
]
],
'between the dates' => [
$before, $after, null, null, null, null, [
['label' => get_string('activitydate:submissionsopened', 'mod_assign'), 'timestamp' => $before,
'dataid' => 'allowsubmissionsfromdate'],
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $after,
'dataid' => 'duedate'],
]
],
'dates are past' => [
$earlier, $before, null, null, null, null, [
['label' => get_string('activitydate:submissionsopened', 'mod_assign'), 'timestamp' => $earlier,
'dataid' => 'allowsubmissionsfromdate'],
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $before,
'dataid' => 'duedate'],
]
],
'with user override' => [
$before, $after, $earlier, $later, null, null, [
['label' => get_string('activitydate:submissionsopened', 'mod_assign'), 'timestamp' => $earlier,
'dataid' => 'allowsubmissionsfromdate'],
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $later,
'dataid' => 'duedate'],
]
],
'with group override' => [
$before, $after, null, null, $earlier, $later, [
['label' => get_string('activitydate:submissionsopened', 'mod_assign'), 'timestamp' => $earlier,
'dataid' => 'allowsubmissionsfromdate'],
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $later,
'dataid' => 'duedate'],
]
],
'with both user and group overrides' => [
$before, $after, $earlier, $later, $earlier - DAYSECS, $later + DAYSECS, [
['label' => get_string('activitydate:submissionsopened', 'mod_assign'), 'timestamp' => $earlier,
'dataid' => 'allowsubmissionsfromdate'],
['label' => get_string('activitydate:submissionsdue', 'mod_assign'), 'timestamp' => $later,
'dataid' => 'duedate'],
]
],
];
}
/**
* Test for get_dates_for_module().
*
* @dataProvider get_dates_for_module_provider
* @param int|null $from Time of opening submissions in the assignment.
* @param int|null $due Assignment's due date.
* @param int|null $userfrom The user override for opening submissions.
* @param int|null $userdue The user override for due date.
* @param int|null $groupfrom The group override for opening submissions.
* @param int|null $groupdue The group override for due date.
* @param array $expected The expected value of calling get_dates_for_module()
*/
public function test_get_dates_for_module(?int $from, ?int $due,
?int $userfrom, ?int $userdue,
?int $groupfrom, ?int $groupdue,
array $expected): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
/** @var \mod_assign_generator $assigngenerator */
$assigngenerator = $generator->get_plugin_generator('mod_assign');
$course = $generator->create_course();
$user = $generator->create_user();
$generator->enrol_user($user->id, $course->id);
$data = ['course' => $course->id];
if ($from) {
$data['allowsubmissionsfromdate'] = $from;
}
if ($due) {
$data['duedate'] = $due;
}
$assign = $assigngenerator->create_instance($data);
if ($userfrom || $userdue || $groupfrom || $groupdue) {
$generator->enrol_user($user->id, $course->id);
$group = $generator->create_group(['courseid' => $course->id]);
$generator->create_group_member(['groupid' => $group->id, 'userid' => $user->id]);
if ($userfrom || $userdue) {
$assigngenerator->create_override([
'assignid' => $assign->id,
'userid' => $user->id,
'allowsubmissionsfromdate' => $userfrom,
'duedate' => $userdue,
]);
}
if ($groupfrom || $groupdue) {
$assigngenerator->create_override([
'assignid' => $assign->id,
'groupid' => $group->id,
'allowsubmissionsfromdate' => $groupfrom,
'duedate' => $groupdue,
]);
}
}
$this->setUser($user);
$cm = get_coursemodule_from_instance('assign', $assign->id);
// Make sure we're using a cm_info object.
$cm = cm_info::create($cm);
$dates = activity_dates::get_dates_for_module($cm, (int) $user->id);
$this->assertEquals($expected, $dates);
}
}
+446
View File
@@ -0,0 +1,446 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use context_module;
use assign;
/**
* Downloader tests class for mod_assign.
*
* @package mod_assign
* @category test
* @copyright 2022 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \mod_assign\downloader
*/
class downloader_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setupBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
}
/**
* Test for load_filelist method.
*
* @covers ::load_filelist
* @dataProvider load_filelist_provider
*
* @param bool $teamsubmission if the assign must have team submissions
* @param array $groupmembers the groups definition
* @param array|null $filterusers the filtered users (null for all users)
* @param bool $blindmarking if the assign has blind marking
* @param bool $downloadasfolder if the download as folder preference is set
* @param array $expected the expected file list
*/
public function test_load_filelist(
bool $teamsubmission,
array $groupmembers,
?array $filterusers,
bool $blindmarking,
bool $downloadasfolder,
array $expected
): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
if (!$downloadasfolder) {
set_user_preference('assign_downloadasfolders', 0);
}
// Create course and enrols.
$course = $this->getDataGenerator()->create_course();
$users = [
'student1' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student2' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student3' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student4' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student5' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
];
// Generate groups.
$groups = [];
foreach ($groupmembers as $groupname => $groupusers) {
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => $groupname]);
foreach ($groupusers as $user) {
groups_add_member($group, $users[$user]);
}
$groups[$groupname] = $group;
}
// Create activity.
$params = [
'course' => $course,
'assignsubmission_file_enabled' => 1,
'assignsubmission_file_maxfiles' => 12,
'assignsubmission_file_maxsizebytes' => 1024 * 1024,
];
if ($teamsubmission) {
$params['teamsubmission'] = 1;
$params['preventsubmissionnotingroup'] = false;
}
if ($blindmarking) {
$params['blindmarking'] = 1;
}
$activity = $this->getDataGenerator()->create_module('assign', $params);
$cm = get_coursemodule_from_id('assign', $activity->cmid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
// Generate submissions.
$datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$files = [
"mod/assign/tests/fixtures/submissionsample01.txt",
"mod/assign/tests/fixtures/submissionsample02.txt"
];
foreach ($users as $key => $user) {
if ($key == 'student5') {
continue;
}
$datagenerator->create_submission([
'userid' => $user->id,
'cmid' => $cm->id,
'file' => implode(',', $files),
]);
}
// Generate file list.
if ($filterusers) {
foreach ($filterusers as $key => $identifier) {
$filterusers[$key] = $users[$identifier]->id;
}
}
$manager = new assign($context, $cm, $course);
$downloader = new downloader($manager, $filterusers);
$hasfiles = $downloader->load_filelist();
// Expose protected filelist attribute.
$rc = new \ReflectionClass(downloader::class);
$rcp = $rc->getProperty('filesforzipping');
// Add some replacements.
$search = ['PARTICIPANT', 'DEFAULTTEAM'];
$replace = [get_string('participant', 'mod_assign'), get_string('defaultteam', 'mod_assign')];
foreach ($users as $identifier => $user) {
$search[] = strtoupper($identifier . '.ID');
$replace[] = $manager->get_uniqueid_for_user($user->id);
$search[] = strtoupper($identifier);
$replace[] = $this->prepare_filename_text(fullname($user));
}
foreach ($groups as $identifier => $group) {
$search[] = strtoupper($identifier . '.ID');
$replace[] = strtoupper($group->id);
$search[] = strtoupper($identifier);
$replace[] = $this->prepare_filename_text($group->name);
}
// Validate values.
$filelist = $rcp->getValue($downloader);
$result = array_keys($filelist);
$this->assertEquals($hasfiles, !empty($expected));
$this->assertCount(count($expected), $result);
foreach ($expected as $path) {
$value = str_replace($search, $replace, $path);
$this->assertTrue(in_array($value, $result));
}
}
/**
* Internal helper to clean a filename text.
*
* @param string $text the text to transform
* @return string the clean string
*/
private function prepare_filename_text(string $text): string {
return clean_filename(str_replace('_', ' ', $text));
}
/**
* Data provider for test_load_filelist().
*
* @return array of scenarios
*/
public function load_filelist_provider(): array {
$downloadasfoldertests = $this->load_filelist_downloadasfolder_scenarios();
$downloadasfilestests = $this->load_filelist_downloadasfiles_scenarios();
return array_merge(
$downloadasfoldertests,
$downloadasfilestests,
);
}
/**
* Generate the standard test scenarios for load_filelist with download as file.
*
* The scenarios are the same as download as folder but replacing the "/" of the files
* by a "_" and setting the downloadasfolder to false.
*
* @return array of scenarios
*/
private function load_filelist_downloadasfiles_scenarios(): array {
$result = $this->load_filelist_downloadasfolder_scenarios("Download as files:");
// Transform paths from files.
foreach ($result as $scenario => $info) {
$info['downloadasfolder'] = false;
foreach ($info['expected'] as $key => $path) {
$info['expected'][$key] = str_replace('/', '_', $path);
}
$result[$scenario] = $info;
}
return $result;
}
/**
* Generate the standard test scenarios for load_filelist with download as folder.
*
* @param string $prefix the scenarios prefix
* @return array of scenarios
*/
private function load_filelist_downloadasfolder_scenarios(string $prefix = "Download as folders:"): array {
return [
// Test without team submissions.
$prefix . ' All users without groups' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => null,
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT3_STUDENT3.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT3_STUDENT3.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT4_STUDENT4.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT4_STUDENT4.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users without submissions' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student1', 'student5'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Asking only for users without submissions' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student5'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [],
],
// Test with team submissions and no default team.
$prefix . ' All users with all users in groups' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => null,
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample01.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample02.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample01.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users with disjoined groups' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample01.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users with default teams who does not do a submission' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => ['student1', 'student5'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample01.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users without submission but member of a group' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => [
'student5'
],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample01.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample02.txt',
],
],
// Test with default team.
$prefix . ' All users with users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => null,
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users in groups with users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users without groups with users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => ['student3', 'student4'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users with some users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => ['student1', 'student3'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users with joined groups' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
'group2' => ['student2', 'student3'],
],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
// Tests with blind marking.
$prefix . ' All users without groups and blindmarking' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => null,
'blindmarking' => true,
'downloadasfolder' => true,
'expected' => [
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT3.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT3.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT4.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT4.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users without groups and blindmarking' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student1', 'student2'],
'blindmarking' => true,
'downloadasfolder' => true,
'expected' => [
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
],
],
];
}
}
File diff suppressed because it is too large Load Diff
+178
View File
@@ -0,0 +1,178 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign\external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/tests/externallib_advanced_testcase.php');
/**
* Test the start_submission external function.
*
* @package mod_assign
* @category test
* @covers \mod_assign\external\start_submission
* @author Andrew Madden <andrewmadden@catalyst-au.net>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class start_submission_test extends \mod_assign\externallib_advanced_testcase {
/** @var \stdClass $course New course created to hold the assignments */
protected $course = null;
/**
* Called before every test.
*/
protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
}
/**
* Test start_submission if assignment doesn't exist matching id.
*/
public function test_start_submission_with_invalid_assign_id(): void {
$this->expectException(\dml_exception::class);
start_submission::execute(123);
}
/**
* Test start_submission if user is not able to access activity or course.
*/
public function test_start_submission_when_user_has_no_capability_to_view_assignment(): void {
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$assign = $generator->create_instance(['course' => $this->course->id]);
$this->expectException(\require_login_exception::class);
start_submission::execute($assign->id);
}
/**
* Test start_submission if assignment cut off date has elapsed.
*/
public function test_start_submission_when_assignment_past_due_date(): void {
$fiveminago = time() - 300;
list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
false, ['cutoffdate' => $fiveminago]);
$result = start_submission::execute($instance->id);
$filteredwarnings = array_filter($result['warnings'], function($warning) {
return $warning['warningcode'] === 'submissionnotopen';
});
$this->assertCount(1, $filteredwarnings);
$this->assertEquals(0, $result['submissionid']);
$warning = array_pop($filteredwarnings);
$this->assertEquals($instance->id, $warning['itemid']);
$this->assertEquals('This assignment is not open for submissions', $warning['item']);
}
/**
* Test start_submission if time limit is disabled.
*/
public function test_start_submission_when_time_limit_disabled(): void {
list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status();
$result = start_submission::execute($instance->id);
$filteredwarnings = array_filter($result['warnings'], function($warning) {
return $warning['warningcode'] === 'timelimitnotenabled';
});
$this->assertCount(1, $filteredwarnings);
$this->assertEquals(0, $result['submissionid']);
$warning = array_pop($filteredwarnings);
$this->assertEquals($instance->id, $warning['itemid']);
$this->assertEquals('Time limit is not enabled for assignment.', $warning['item']);
}
/**
* Test start_submission if time limit is not set for assignment.
*/
public function test_start_submission_when_time_limit_not_set(): void {
set_config('enabletimelimit', '1', 'assign');
list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status();
$result = start_submission::execute($instance->id);
$filteredwarnings = array_filter($result['warnings'], function($warning) {
return $warning['warningcode'] === 'timelimitnotenabled';
});
$this->assertCount(1, $filteredwarnings);
$this->assertEquals(0, $result['submissionid']);
$warning = array_pop($filteredwarnings);
$this->assertEquals($instance->id, $warning['itemid']);
$this->assertEquals('Time limit is not enabled for assignment.', $warning['item']);
}
/**
* Test start_submission if user already has open submission.
*/
public function test_start_submission_when_submission_already_open(): void {
global $DB;
set_config('enabletimelimit', '1', 'assign');
list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
false, ['timelimit' => 300]);
$submission = $assign->get_user_submission($student1->id, true);
$submission->timestarted = time();
$DB->update_record('assign_submission', $submission);
$result = start_submission::execute($instance->id);
$filteredwarnings = array_filter($result['warnings'], function($warning) {
return $warning['warningcode'] === 'opensubmissionexists';
});
$this->assertCount(1, $filteredwarnings);
$this->assertEquals(0, $result['submissionid']);
$warning = array_pop($filteredwarnings);
$this->assertEquals($instance->id, $warning['itemid']);
$this->assertEquals('Open assignment submission already exists.', $warning['item']);
}
/**
* Test start_submission if user has already submitted with no additional attempts available.
*/
public function test_start_submission_with_no_attempts_available(): void {
global $DB;
set_config('enabletimelimit', '1', 'assign');
list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
false, ['timelimit' => 300]);
$submission = $assign->get_user_submission($student1->id, true);
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
$DB->update_record('assign_submission', $submission);
$result = start_submission::execute($instance->id);
$filteredwarnings = array_filter($result['warnings'], function($warning) {
return $warning['warningcode'] === 'submissionnotopen';
});
$this->assertCount(1, $filteredwarnings);
$this->assertEquals(0, $result['submissionid']);
$warning = array_pop($filteredwarnings);
$this->assertEquals($instance->id, $warning['itemid']);
$this->assertEquals('This assignment is not open for submissions', $warning['item']);
}
/**
* Test start_submission if user has no open submissions.
*/
public function test_start_submission_with_new_submission(): void {
global $DB;
set_config('enabletimelimit', '1', 'assign');
list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
false, ['timelimit' => 300]);
// Clear all current submissions.
$DB->delete_records('assign_submission', ['assignment' => $instance->id]);
$result = start_submission::execute($instance->id);
$this->assertCount(0, $result['warnings']);
$this->assertNotEmpty($result['submissionid']);
}
}
@@ -0,0 +1,172 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/mod/assign/externallib.php');
require_once(__DIR__ . '/fixtures/testable_assign.php');
/**
* Base class for unit tests for external functions in mod_assign.
*
* @package mod_assign
* @author Andrew Madden <andrewmadden@catalyst-au.net>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class externallib_advanced_testcase extends \externallib_advanced_testcase {
/**
* Create a submission for testing the get_submission_status function.
* @param bool $submitforgrading whether to submit for grading the submission
* @param array $params Optional params to use for creating assignment instance.
* @return array an array containing all the required data for testing
*/
protected function create_submission_for_testing_status(bool $submitforgrading = false, array $params = []): array {
global $DB;
// Create a course and assignment and users.
$course = self::getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1]);
$group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
$group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$params = array_merge([
'course' => $course->id,
'assignsubmission_file_maxfiles' => 1,
'assignsubmission_file_maxsizebytes' => 1024 * 1024,
'assignsubmission_onlinetext_enabled' => 1,
'assignsubmission_file_enabled' => 1,
'submissiondrafts' => 1,
'assignfeedback_file_enabled' => 1,
'assignfeedback_comments_enabled' => 1,
'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
'sendnotifications' => 0
], $params);
set_config('submissionreceipts', 0, 'assign');
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
$assign = new \mod_assign_testable_assign($context, $cm, $course);
$student1 = self::getDataGenerator()->create_user();
$student2 = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
$teacher = self::getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
$this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $student1->id]);
$this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $teacher->id]);
$this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $student2->id]);
$this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $teacher->id]);
$this->setUser($student1);
// Create a student1 with an online text submission.
// Simulate a submission.
$assign->get_user_submission($student1->id, true);
$data = new \stdClass();
$data->onlinetext_editor = [
'itemid' => file_get_unused_draft_itemid(),
'text' => 'Submission text with a <a href="@@PLUGINFILE@@/intro.txt">link</a>',
'format' => FORMAT_MOODLE,
];
$draftidfile = file_get_unused_draft_itemid();
$usercontext = \context_user::instance($student1->id);
$filerecord = [
'contextid' => $usercontext->id,
'component' => 'user',
'filearea' => 'draft',
'itemid' => $draftidfile,
'filepath' => '/',
'filename' => 't.txt',
];
$fs = get_file_storage();
$fs->create_file_from_string($filerecord, 'text contents');
$data->files_filemanager = $draftidfile;
$notices = [];
$assign->save_submission($data, $notices);
if ($submitforgrading) {
// Now, submit the draft for grading.
$notices = [];
$data = new \stdClass;
$data->userid = $student1->id;
$assign->submit_for_grading($data, $notices);
}
return [$assign, $instance, $student1, $student2, $teacher, $group1, $group2];
}
/**
* Create a course, assignment module instance, student and teacher and enrol them in
* the course.
*
* @param array $params parameters to be provided to the assignment module creation
* @return array containing the course, assignment module, student and teacher
*/
protected function create_assign_with_student_and_teacher(array $params = []): array {
global $DB;
$course = $this->getDataGenerator()->create_course();
$params = array_merge([
'course' => $course->id,
'name' => 'assignment',
'intro' => 'assignment intro text',
], $params);
// Create a course and assignment and users.
$assign = $this->getDataGenerator()->create_module('assign', $params);
$cm = get_coursemodule_from_instance('assign', $assign->id);
$context = \context_module::instance($cm->id);
$student = $this->getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
$teacher = $this->getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
assign_capability('mod/assign:view', CAP_ALLOW, $teacherrole->id, $context->id, true);
assign_capability('mod/assign:viewgrades', CAP_ALLOW, $teacherrole->id, $context->id, true);
assign_capability('mod/assign:grade', CAP_ALLOW, $teacherrole->id, $context->id, true);
accesslib_clear_all_caches_for_unit_testing();
return [
'course' => $course,
'assign' => $assign,
'student' => $student,
'teacher' => $teacher,
];
}
}
File diff suppressed because it is too large Load Diff
+156
View File
@@ -0,0 +1,156 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use assignfeedback_editpdf\document_services;
use assignfeedback_editpdf\combined_document;
use mod_assign_test_generator;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
/**
* Provides the unit tests for feedback.
*
* @package mod_assign
* @category test
* @copyright 2019 Ilya Tregubov ilyatregubov@catalyst-au.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class feedback_test extends \advanced_testcase {
// Use the generator helper.
use mod_assign_test_generator;
/**
* Helper to create a stored file object with the given supplied content.
*
* @param int $contextid context id for assigment
* @param int $itemid item id from assigment grade
* @param string $filearea File area
* @param int $timemodified Time modified
* @param string $filecontent The content of the mocked file
* @param string $filename The file name to use in the stored_file
* @param string $filerecord Any overrides to the filerecord
* @return stored_file
*/
protected function create_stored_file($contextid, $itemid, $filearea, $timemodified,
$filecontent = 'content', $filename = 'combined.pdf', $filerecord = []) {
$filerecord = array_merge([
'contextid' => $contextid,
'component' => 'assignfeedback_editpdf',
'filearea' => $filearea,
'itemid' => $itemid,
'filepath' => '/',
'filename' => $filename,
'timemodified' => $timemodified,
], $filerecord);
$fs = get_file_storage();
$file = $fs->create_file_from_string($filerecord, $filecontent);
return $file;
}
/**
* Convenience function to create an instance of an assignment.
*
* @param array $params Array of parameters to pass to the generator
* @return assign The assign class.
*/
protected function create_instance($params = array()) {
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
return new \assign($context, $cm, $params['course']);
}
/**
* Test fetching combined.pdf for state checking.
*/
public function test_get_combined_document_for_attempt(): void {
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
$assign = $this->create_instance([
'course' => $course,
'name' => 'Assign 1',
'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
'maxattempts' => 3,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true
]);
$submission = new \stdClass();
$submission->assignment = $assign->get_instance()->id;
$submission->userid = $user->id;
$submission->timecreated = time();
$submission->timemodified = time();
$submission->onlinetext_editor = ['text' => 'Submission text',
'format' => FORMAT_MOODLE];
$this->setUser($user);
$notices = [];
$assign->save_submission($submission, $notices);
$this->setUser($teacher);
$grade = '3.14';
$teachercommenttext = 'This is better. Thanks.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user->id, $data);
$grade = $assign->get_user_grade($user->id, true, -1);
$contextid = $assign->get_context()->id;
$itemid = $grade->id;
// Create combined document in combined area.
$this->create_stored_file($contextid, $itemid, 'combined', time());
$document = document_services::get_combined_document_for_attempt($assign, $user->id, -1);
$status = $document->get_status();
$this->assertEquals($status, combined_document::STATUS_COMPLETE);
// Create orphaned combined document in partial area.
$this->create_stored_file($contextid, $itemid, 'partial', time() - 3600);
$document = document_services::get_combined_document_for_attempt($assign, $user->id, -1);
$status = $document->get_status();
$this->assertEquals($status, combined_document::STATUS_FAILED);
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* mod_assign unit test events.
*
* @package mod_assign
* @copyright 2013 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign_unittests\event;
defined('MOODLE_INTERNAL') || die();
/**
* mod_assign submission_created unit test event class.
*
* @package mod_assign
* @copyright 2013 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class submission_created extends \mod_assign\event\submission_created {
}
/**
* mod_assign submission_updated unit test event class.
*
* @package mod_assign
* @copyright 2013 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class submission_updated extends \mod_assign\event\submission_updated {
}
/**
* mod_assign test class for event base.
*
* @package mod_assign
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class nothing_happened extends \mod_assign\event\base {
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
public static function get_name() {
return 'Nothing happened';
}
}
+1
View File
@@ -0,0 +1 @@
This is just a submission testing sample.
+1
View File
@@ -0,0 +1 @@
This is just a submission testing sample.
+172
View File
@@ -0,0 +1,172 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The testable assign class.
*
* @package mod_assign
* @copyright 2014 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
/**
* Test subclass that makes all the protected methods we want to test public.
*/
class mod_assign_testable_assign extends assign {
public function testable_show_intro() {
return parent::show_intro();
}
public function testable_delete_grades() {
return parent::delete_grades();
}
public function testable_apply_grade_to_user($formdata, $userid, $attemptnumber) {
return parent::apply_grade_to_user($formdata, $userid, $attemptnumber);
}
public function testable_get_grading_userid_list() {
return parent::get_grading_userid_list();
}
public function testable_is_graded($userid) {
return parent::is_graded($userid);
}
public function testable_update_submission(stdClass $submission, $userid, $updatetime, $teamsubmission) {
return parent::update_submission($submission, $userid, $updatetime, $teamsubmission);
}
public function testable_process_add_attempt($userid = 0) {
return parent::process_add_attempt($userid);
}
public function testable_process_save_quick_grades($postdata) {
// Ugly hack to get something into the method.
global $_POST;
$_POST = $postdata;
return parent::process_save_quick_grades();
}
public function testable_process_set_batch_marking_allocation($selectedusers, $markerid) {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/batchsetallocatedmarkerform.php');
// Simulate the form submission.
$data = array();
$data['id'] = $this->get_course_module()->id;
$data['selectedusers'] = $selectedusers;
$data['allocatedmarker'] = $markerid;
$data['action'] = 'setbatchmarkingallocation';
mod_assign_batch_set_allocatedmarker_form::mock_submit($data);
return parent::process_set_batch_marking_allocation();
}
public function testable_process_set_batch_marking_workflow_state($selectedusers, $state) {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/batchsetmarkingworkflowstateform.php');
// Simulate the form submission.
$data = array();
$data['id'] = $this->get_course_module()->id;
$data['selectedusers'] = $selectedusers;
$data['markingworkflowstate'] = $state;
$data['action'] = 'setbatchmarkingworkflowstate';
mod_assign_batch_set_marking_workflow_state_form::mock_submit($data);
return parent::process_set_batch_marking_workflow_state();
}
public function testable_submissions_open($userid = 0) {
return parent::submissions_open($userid);
}
public function testable_save_user_extension($userid, $extensionduedate) {
return parent::save_user_extension($userid, $extensionduedate);
}
public function testable_get_graders($userid) {
// Changed method from protected to public.
return parent::get_graders($userid);
}
public function testable_get_notifiable_users($userid) {
return parent::get_notifiable_users($userid);
}
public function testable_view_batch_set_workflow_state($selectedusers) {
global $PAGE;
$PAGE->set_url('/mod/assign/view.php');
$mform = $this->testable_grading_batch_operations_form('setmarkingworkflowstate', $selectedusers);
return parent::view_batch_set_workflow_state($mform);
}
public function testable_view_batch_markingallocation($selectedusers) {
global $PAGE;
$PAGE->set_url('/mod/assign/view.php');
$mform = $this->testable_grading_batch_operations_form('setmarkingallocation', $selectedusers);
return parent::view_batch_markingallocation($mform);
}
public function testable_grading_batch_operations_form($operation, $selectedusers) {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php');
// Mock submit the grading operations form.
$data = array();
$data['id'] = $this->get_course_module()->id;
$data['selectedusers'] = $selectedusers;
$data['returnaction'] = 'grading';
$data['operation'] = $operation;
mod_assign_grading_batch_operations_form::mock_submit($data);
// Set required variables in the form.
$formparams = array();
$formparams['submissiondrafts'] = 1;
$formparams['duedate'] = 1;
$formparams['attemptreopenmethod'] = ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL;
$formparams['feedbackplugins'] = array();
$formparams['markingworkflow'] = 1;
$formparams['markingallocation'] = 1;
$formparams['cm'] = $this->get_course_module()->id;
$formparams['context'] = $this->get_context();
$mform = new mod_assign_grading_batch_operations_form(null, $formparams);
return $mform;
}
public function testable_update_activity_completion_records($teamsubmission,
$requireallteammemberssubmit,
$submission,
$userid,
$complete,
$completion) {
return parent::update_activity_completion_records($teamsubmission,
$requireallteammemberssubmit,
$submission,
$userid,
$complete,
$completion);
}
}
+136
View File
@@ -0,0 +1,136 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Base class for unit tests for mod_assign.
*
* @package mod_assign
* @category phpunit
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
require_once(__DIR__ . '/fixtures/testable_assign.php');
/**
* Generator helper trait.
*
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
trait mod_assign_test_generator {
/**
* Convenience function to create a testable instance of an assignment.
*
* @param array $params Array of parameters to pass to the generator
* @return testable_assign Testable wrapper around the assign class.
*/
protected function create_instance($course, $params = [], $options = []) {
$params['course'] = $course->id;
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $generator->create_instance($params, $options);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
return new mod_assign_testable_assign($context, $cm, $course);
}
/**
* Add a user submission to the assignment.
*
* @param \stdClass $student The user to submit for
* @param \assign $assign The assignment to submit to
* @param string $onlinetext The text tobe submitted
* @param bool $changeuser Whether to switch user to the user being submitted as.
*/
protected function add_submission($student, $assign, $onlinetext = null, $changeuser = true) {
// Add a submission.
if ($changeuser) {
$this->setUser($student);
}
if ($onlinetext === null) {
$onlinetext = 'Submission text';
}
$data = (object) [
'userid' => $student->id,
'onlinetext_editor' => [
'itemid' => file_get_unused_draft_itemid(),
'text' => $onlinetext,
'format' => FORMAT_HTML,
]
];
$assign->save_submission($data, $notices);
}
/**
* Submit the assignemnt for grading.
*
* @param \stdClass $student The user to submit for
* @param \assign $assign The assignment to submit to
* @param array $data Additional data to set
* @param bool $changeuser Whether to switch user to the user being submitted as.
*/
public function submit_for_grading($student, $assign, $data = [], $changeuser = true) {
if ($changeuser) {
$this->setUser($student);
}
$data = (object) array_merge($data, [
'userid' => $student->id,
]);
$sink = $this->redirectMessages();
$assign->submit_for_grading($data, []);
$sink->close();
return $data;
}
/**
* Mark the submission.
*
* @param \stdClass $teacher The user to mark as
* @param \assign $assign The assignment to mark
* @param \stdClass $student The user to grade
* @param array $data Additional data to set
* @param bool $changeuser Whether to switch user to the user being submitted as.
*/
protected function mark_submission($teacher, $assign, $student, $grade = 50.0, $data = [], $attempt = 0) {
global $DB;
// Mark the submission.
$this->setUser($teacher);
$data = (object) array_merge($data, [
'grade' => $grade,
]);
// Bump all timecreated and timemodified for this user back.
$DB->execute('UPDATE {assign_submission} SET timecreated = timecreated - 1, timemodified = timemodified - 1 WHERE userid = :userid',
['userid' => $student->id]);
$assign->testable_apply_grade_to_user($data, $student->id, $attempt);
}
}
@@ -0,0 +1,37 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Online Text assignment submission subplugin data generator.
*
* @package mod_assign
* @category test
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class assignsubmission_subplugin_generator extends testing_module_generator {
/**
* Add submission data in the correct format for a call to `assign::save_submission()` from a table containing
* submission data for a single activity.
*
* Data should be added to the $submission object passed into the function.
*
* @param stdClass $submission The submission record to be modified
* @param assign $assign The assignment being submitted to
* @param array $data The data received
*/
abstract public function add_submission_data(stdClass $submission, assign $assign, array $data): void;
}
@@ -0,0 +1,58 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Behat data generator for mod_assign.
*
* @package mod_assign
* @category test
* @copyright 2021 Andrew Lyons
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_mod_assign_generator extends behat_generator_base {
/**
* Get a list of the entities that Behat can create using the generator step.
*
* @return array
*/
protected function get_creatable_entities(): array {
return [
'submissions' => [
'singular' => 'submission',
'datagenerator' => 'submission',
'required' => ['assign', 'user'],
'switchids' => ['assign' => 'assignid', 'user' => 'userid'],
],
'extensions' => [
'singular' => 'extension',
'datagenerator' => 'extension',
'required' => ['assign', 'user', 'extensionduedate'],
'switchids' => ['assign' => 'cmid', 'user' => 'userid'],
],
];
}
/**
* Get the assignment cmid using an activity name or idnumber.
*
* @param string $identifier activity name or idnumber
* @return int The cmid
*/
protected function get_assign_id(string $identifier): int {
return $this->get_cm_by_activity_name('assign', $identifier)->id;
}
}
+187
View File
@@ -0,0 +1,187 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
defined('MOODLE_INTERNAL') || die();
/**
* assign module data generator class
*
* @package mod_assign
* @category test
* @copyright 2012 Paul Charsley
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_assign_generator extends testing_module_generator {
/**
* Create a new instance of the assignment activity.
*
* @param array|stdClass|null $record
* @param array|null $options
* @return stdClass
*/
public function create_instance($record = null, array $options = null) {
$record = (object)(array)$record;
$defaultsettings = array(
'alwaysshowdescription' => 1,
'submissiondrafts' => 1,
'requiresubmissionstatement' => 0,
'sendnotifications' => 0,
'sendstudentnotifications' => 1,
'sendlatenotifications' => 0,
'duedate' => 0,
'allowsubmissionsfromdate' => 0,
'grade' => 100,
'cutoffdate' => 0,
'gradingduedate' => 0,
'teamsubmission' => 0,
'requireallteammemberssubmit' => 0,
'teamsubmissiongroupingid' => 0,
'blindmarking' => 0,
'attemptreopenmethod' => 'none',
'maxattempts' => -1,
'markingworkflow' => 0,
'markingallocation' => 0,
'markinganonymous' => 0,
'activityformat' => 0,
'timelimit' => 0,
'submissionattachments' => 0,
);
if (property_exists($record, 'teamsubmissiongroupingid')) {
$record->teamsubmissiongroupingid = $this->get_grouping_id($record->teamsubmissiongroupingid);
}
foreach ($defaultsettings as $name => $value) {
if (!isset($record->{$name})) {
$record->{$name} = $value;
}
}
return parent::create_instance($record, (array)$options);
}
/**
* Create an assignment submission.
*
* @param array $data with keys userid, cmid and
* then data for each assignsubmission plugin used.
* For backwards compatibility, you can pass cmid as 'assignid' but that generates a warning.
*/
public function create_submission(array $data): void {
global $USER;
if (array_key_exists('assignid', $data)) {
debugging(
'The cmid passed to create_submission should have array key cmid, not assignid.',
DEBUG_DEVELOPER,
);
$data['cmid'] = $data['assignid'];
unset($data['assignid']);
}
$currentuser = $USER;
$user = \core_user::get_user($data['userid']);
$this->set_user($user);
$submission = (object) [
'userid' => $user->id,
];
[$course, $cm] = get_course_and_cm_from_cmid($data['cmid'], 'assign');
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
foreach ($assign->get_submission_plugins() as $plugin) {
$pluginname = $plugin->get_type();
if (array_key_exists($pluginname, $data)) {
$plugingenerator = $this->datagenerator->get_plugin_generator("assignsubmission_{$pluginname}");
$plugingenerator->add_submission_data($submission, $assign, $data);
}
}
$assign->save_submission($submission, $notices);
$this->set_user($currentuser);
}
/**
* Create an assignment extension.
*
* @param array $data must have keys cmid, userid, extensionduedate.
*/
public function create_extension(array $data): void {
$user = \core_user::get_user($data['userid'], '*', MUST_EXIST);
[$course, $cm] = get_course_and_cm_from_cmid($data['cmid'], 'assign');
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
if (!$assign->save_user_extension($user->id, $data['extensionduedate'] ?: null)) {
throw new \core\exception\coding_exception('The requested extension could not be created.');
}
}
/**
* Gets the grouping id from it's idnumber.
*
* @throws Exception
* @param string $idnumber
* @return int
*/
protected function get_grouping_id(string $idnumber): int {
global $DB;
// Do not fetch grouping ID for empty grouping idnumber.
if (empty($idnumber)) {
throw new \core\exception\coding_exception('idnumber cannot be empty');
}
if (!$id = $DB->get_field('groupings', 'id', ['idnumber' => $idnumber])) {
if (is_numeric($idnumber)) {
return $idnumber;
}
throw new Exception('The specified grouping with idnumber "' . $idnumber . '" does not exist');
}
return $id;
}
/**
* Create an assign override (either user or group).
*
* @param array $data must specify assignid, and one of userid or groupid.
* @throws coding_exception
*/
public function create_override(array $data): void {
global $DB;
if (!isset($data['assignid'])) {
throw new coding_exception('Must specify assignid when creating an assign override.');
}
if (!isset($data['userid']) && !isset($data['groupid'])) {
throw new coding_exception('Must specify one of userid or groupid when creating an assign override.');
}
if (isset($data['userid']) && isset($data['groupid'])) {
throw new coding_exception('Cannot specify both userid and groupid when creating an assign override.');
}
$DB->insert_record('assign_overrides', (object) $data);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,178 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use mod_assign_test_generator;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once(__DIR__ . '/../locallib.php');
require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
/**
* Unit tests for (some of) mod/assign/locallib.php.
*
* @package mod_assign
* @category test
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class locallib_participants_test extends \advanced_testcase {
use mod_assign_test_generator;
public function test_list_participants_blind_marking(): void {
global $DB;
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$roles = $DB->get_records('role', null, '', 'shortname, id');
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($teacher->id,
$course->id,
$roles['teacher']->id);
$this->setUser($teacher);
// Enrol two students.
$students = [];
for ($i = 0; $i < 2; $i++) {
$student = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($student->id,
$course->id,
$roles['student']->id);
$students[$student->id] = $student;
}
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $generator->create_instance(['course' => $course->id, 'blindmarking' => 1]);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
$assign = new \assign($context, $cm, $course);
// Allocate IDs now.
// We're testing whether the IDs are correct after allocation.
\assign::allocate_unique_ids($assign->get_instance()->id);
$participants = $assign->list_participants(null, false);
// There should be exactly two participants and they should be the students.
$this->assertCount(2, $participants);
foreach ($participants as $participant) {
$this->assertArrayHasKey($participant->id, $students);
}
$keys = array_keys($participants);
// Create a grading table, and query the DB This should have the same order.
$table = new \assign_grading_table($assign, 10, '', 0, false);
$table->setup();
$table->query_db(10);
$this->assertEquals($keys, array_keys($table->rawdata));
// Submit a file for the second student.
$data = new \stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
'format'=>FORMAT_MOODLE);
static::helper_add_submission($assign, $participants[$keys[1]], $data, 'onlinetext');
// Assign has a private cache. The easiest way to clear this is to create a new instance.
$assign = new \assign($context, $cm, $course);
$newparticipants = $assign->list_participants(null, false);
// There should be exactly two participants and they should be the students.
$this->assertCount(2, $newparticipants);
foreach ($newparticipants as $participant) {
$this->assertArrayHasKey($participant->id, $students);
}
$newkeys = array_keys($newparticipants);
// The user who submitted first should now be listed first.
$this->assertEquals($participants[$keys[1]]->id, $newparticipants[$newkeys[0]]->id);
$this->assertEquals($participants[$keys[0]]->id, $newparticipants[$newkeys[1]]->id);
// Submit for the other student.
static::helper_add_submission($assign, $participants[$keys[0]], $data, 'onlinetext');
$assign = new \assign($context, $cm, $course);
$newparticipants = $assign->list_participants(null, false);
// The users should still be listed in order of the first submission
$this->assertEquals($participants[$keys[1]]->id, $newparticipants[$newkeys[0]]->id);
$this->assertEquals($participants[$keys[0]]->id, $newparticipants[$newkeys[1]]->id);
// The updated grading table should have the same order as the updated participant list.
$table->query_db(10);
$this->assertEquals($newkeys, array_keys($table->rawdata));
}
/**
* Tests that users who have a submission, but can no longer submit are listed.
*/
public function test_list_participants_can_no_longer_submit(): void {
global $DB;
$this->resetAfterTest(true);
// Create a role that will prevent users submitting.
$role = self::getDataGenerator()->create_role();
assign_capability('mod/assign:submit', CAP_PROHIBIT, $role, \context_system::instance());
// Create the test data.
$course = self::getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$assign = $this->create_instance($course);
self::getDataGenerator()->create_and_enrol($course, 'teacher');
$student1 = self::getDataGenerator()->create_and_enrol($course, 'student');
$student2 = self::getDataGenerator()->create_and_enrol($course, 'student');
$cannotsubmit1 = self::getDataGenerator()->create_and_enrol($course, 'student');
$cannotsubmit2 = self::getDataGenerator()->create_and_enrol($course, 'student');
// Create submissions for some users.
$this->add_submission($student1, $assign);
$this->submit_for_grading($student1, $assign);
$this->add_submission($cannotsubmit1, $assign);
$this->submit_for_grading($cannotsubmit1, $assign);
// Remove the capability to submit from some users.
role_assign($role, $cannotsubmit1->id, $coursecontext);
role_assign($role, $cannotsubmit2->id, $coursecontext);
// Everything is setup for the test now.
$participants = $assign->list_participants(null, true);
self::assertCount(3, $participants);
self::assertArrayHasKey($student1->id, $participants);
self::assertArrayHasKey($student2->id, $participants);
self::assertArrayHasKey($cannotsubmit1->id, $participants);
}
public function helper_add_submission($assign, $user, $data, $type) {
global $USER;
$previoususer = $USER;
$this->setUser($user);
$submission = $assign->get_user_submission($user->id, true);
$submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
$rc = new \ReflectionClass('assign');
$rcm = $rc->getMethod('update_submission');
$rcm->invokeArgs($assign, [$submission, $user->id, true, false]);
$plugin = $assign->get_submission_plugin_by_type($type);
$plugin->save($submission, $data);
$this->setUser($previoususer);
}
}
File diff suppressed because it is too large Load Diff
+145
View File
@@ -0,0 +1,145 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/accesslib.php');
require_once($CFG->dirroot . '/course/lib.php');
/**
* Unit tests for (some of) mod/assign/markerallocaion_test.php.
*
* @package mod_assign
* @category test
* @copyright 2017 Andrés Melo <andres.torres@blackboard.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class markerallocation_test extends \advanced_testcase {
/** @var \stdClass course record. */
private $course;
/**
* Create all the needed elements to test the difference between both functions.
*/
public function test_markerusers(): void {
$this->resetAfterTest();
global $DB;
// Create a course, by default it is created with 5 sections.
$this->course = $this->getDataGenerator()->create_course();
// Setting assing module, markingworkflow and markingallocation set to 1 to enable marker allocation.
$record = new \stdClass();
$record->course = $this->course;
$modulesettings = array(
'alwaysshowdescription' => 1,
'submissiondrafts' => 1,
'requiresubmissionstatement' => 0,
'sendnotifications' => 0,
'sendstudentnotifications' => 1,
'sendlatenotifications' => 0,
'duedate' => 0,
'allowsubmissionsfromdate' => 0,
'grade' => 100,
'cutoffdate' => 0,
'teamsubmission' => 0,
'requireallteammemberssubmit' => 0,
'teamsubmissiongroupingid' => 0,
'blindmarking' => 0,
'attemptreopenmethod' => 'none',
'maxattempts' => -1,
'markingworkflow' => 1,
'markingallocation' => 1,
);
$assignelement = $this->getDataGenerator()->create_module('assign', $record, $modulesettings);
$coursesectionid = course_add_cm_to_section($this->course->id, $assignelement->id, 1);
// Adding users to the course.
$userdata = array();
$userdata['firstname'] = 'teacher1';
$userdata['lasttname'] = 'lastname_teacher1';
$user1 = $this->getDataGenerator()->create_user($userdata);
$this->getDataGenerator()->enrol_user($user1->id, $this->course->id, 'teacher');
$userdata = array();
$userdata['firstname'] = 'teacher2';
$userdata['lasttname'] = 'lastname_teacher2';
$user2 = $this->getDataGenerator()->create_user($userdata);
$this->getDataGenerator()->enrol_user($user2->id, $this->course->id, 'teacher');
$userdata = array();
$userdata['firstname'] = 'student';
$userdata['lasttname'] = 'lastname_student';
$user3 = $this->getDataGenerator()->create_user($userdata);
$this->getDataGenerator()->enrol_user($user3->id, $this->course->id, 'student');
// Adding manager to the system.
$userdata = array();
$userdata['firstname'] = 'Manager';
$userdata['lasttname'] = 'lastname_Manager';
$user4 = $this->getDataGenerator()->create_user($userdata);
// Getting id of manager role.
$managerrole = $DB->get_record('role', array('shortname' => 'manager'));
if (!empty($managerrole)) {
// By default the context of the system is assigned.
$idassignment = $this->getDataGenerator()->role_assign($managerrole->id, $user4->id);
}
$oldusers = array($user1, $user2, $user4);
$newusers = array($user1, $user2);
list($sort, $params) = users_order_by_sql('u');
// Old code, it must return 3 users: teacher1, teacher2 and Manger.
$oldmarkers = get_users_by_capability(\context_course::instance($this->course->id), 'mod/assign:grade', '', $sort);
// New code, it must return 2 users: teacher1 and teacher2.
$newmarkers = get_enrolled_users(\context_course::instance($this->course->id), 'mod/assign:grade', 0, 'u.*', $sort);
// Test result quantity.
$this->assertEquals(count($oldusers), count($oldmarkers));
$this->assertEquals(count($newusers), count($newmarkers));
$this->assertEquals(count($oldmarkers) > count($newmarkers), true);
// Elements expected with new code.
foreach ($newmarkers as $key => $nm) {
$this->assertEquals($nm, $newusers[array_search($nm, $newusers)]);
}
// Elements expected with old code.
foreach ($oldusers as $key => $os) {
$this->assertEquals($os->id, $oldmarkers[$os->id]->id);
unset($oldmarkers[$os->id]);
}
$this->assertEquals(count($oldmarkers), 0);
}
}
+253
View File
@@ -0,0 +1,253 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use mod_assign_testable_assign;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
require_once($CFG->dirroot . '/mod/assign/tests/fixtures/testable_assign.php');
require_once($CFG->dirroot . '/group/lib.php');
/**
* Class mod_assign_portfolio_caller_testcase
*
* Tests behaviour of the assign_portfolio_caller class.
*
* @package mod_assign
* @category test
* @copyright Brendan Cox <brendan.cox@totaralearning.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class portfolio_caller_test extends \advanced_testcase {
/**
* Test an assignment file is loaded for a user who submitted it.
*/
public function test_user_submission_file_is_loaded(): void {
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
/* @var mod_assign_generator $assigngenerator */
$assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$activityrecord = $assigngenerator->create_instance(array('course' => $course->id));
$cm = get_coursemodule_from_instance('assign', $activityrecord->id);
$context = \context_module::instance($cm->id);
$assign = new mod_assign_testable_assign($context, $cm, $course);
$submission = $assign->get_user_submission($user->id, true);
$fs = get_file_storage();
$dummy = (object) array(
'contextid' => $context->id,
'component' => 'assignsubmission_file',
'filearea' => ASSIGNSUBMISSION_FILE_FILEAREA,
'itemid' => $submission->id,
'filepath' => '/',
'filename' => 'myassignmnent.pdf'
);
$file = $fs->create_file_from_string($dummy, 'Content of ' . $dummy->filename);
$caller = new \assign_portfolio_caller(array('cmid' => $cm->id, 'fileid' => $file->get_id()));
$caller->set('user', $user);
$caller->load_data();
$this->assertEquals($file->get_contenthash(), $caller->get_sha1_file());
// This processes the file either by fileid or by other fields in the file table.
// We should get the same outcome with either approach.
$caller = new \assign_portfolio_caller(
array(
'cmid' => $cm->id,
'sid' => $submission->id,
'area' => ASSIGNSUBMISSION_FILE_FILEAREA,
'component' => 'assignsubmission_file',
)
);
$caller->set('user', $user);
$caller->load_data();
$this->assertEquals($file->get_contenthash(), $caller->get_sha1_file());
}
/**
* Test an assignment file is not loaded for a user that did not submit it.
*/
public function test_different_user_submission_file_is_not_loaded(): void {
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
/* @var mod_assign_generator $assigngenerator */
$assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$activityrecord = $assigngenerator->create_instance(array('course' => $course->id));
$cm = get_coursemodule_from_instance('assign', $activityrecord->id);
$context = \context_module::instance($cm->id);
$assign = new mod_assign_testable_assign($context, $cm, $course);
$submission = $assign->get_user_submission($user->id, true);
$fs = get_file_storage();
$dummy = (object) array(
'contextid' => $context->id,
'component' => 'assignsubmission_file',
'filearea' => ASSIGNSUBMISSION_FILE_FILEAREA,
'itemid' => $submission->id,
'filepath' => '/',
'filename' => 'myassignmnent.pdf'
);
$file = $fs->create_file_from_string($dummy, 'Content of ' . $dummy->filename);
// Now add second user.
$wronguser = $this->getDataGenerator()->create_user();
$caller = new \assign_portfolio_caller(array('cmid' => $cm->id, 'fileid' => $file->get_id()));
$caller->set('user', $wronguser);
$this->expectException(\portfolio_caller_exception::class);
$this->expectExceptionMessage('Sorry, the requested file could not be found');
$caller->load_data();
}
/**
* Test an assignment file is loaded for a user who is part of a group that submitted it.
*/
public function test_group_submission_file_is_loaded(): void {
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$groupdata = new \stdClass();
$groupdata->courseid = $course->id;
$groupdata->name = 'group1';
$groupid = groups_create_group($groupdata);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
groups_add_member($groupid, $user);
/* @var mod_assign_generator $assigngenerator */
$assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$activityrecord = $assigngenerator->create_instance(array('course' => $course->id));
$cm = get_coursemodule_from_instance('assign', $activityrecord->id);
$context = \context_module::instance($cm->id);
$assign = new mod_assign_testable_assign($context, $cm, $course);
$submission = $assign->get_group_submission($user->id, $groupid, true);
$fs = get_file_storage();
$dummy = (object) array(
'contextid' => $context->id,
'component' => 'assignsubmission_file',
'filearea' => ASSIGNSUBMISSION_FILE_FILEAREA,
'itemid' => $submission->id,
'filepath' => '/',
'filename' => 'myassignmnent.pdf'
);
$file = $fs->create_file_from_string($dummy, 'Content of ' . $dummy->filename);
$caller = new \assign_portfolio_caller(array('cmid' => $cm->id, 'fileid' => $file->get_id()));
$caller->set('user', $user);
$caller->load_data();
$this->assertEquals($file->get_contenthash(), $caller->get_sha1_file());
// This processes the file either by fileid or by other fields in the file table.
// We should get the same outcome with either approach.
$caller = new \assign_portfolio_caller(
array(
'cmid' => $cm->id,
'sid' => $submission->id,
'area' => ASSIGNSUBMISSION_FILE_FILEAREA,
'component' => 'assignsubmission_file',
)
);
$caller->set('user', $user);
$caller->load_data();
$this->assertEquals($file->get_contenthash(), $caller->get_sha1_file());
}
/**
* Test an assignment file is not loaded for a user who is not part of a group that submitted it.
*/
public function test_different_group_submission_file_is_not_loaded(): void {
$this->resetAfterTest(true);
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$groupdata = new \stdClass();
$groupdata->courseid = $course->id;
$groupdata->name = 'group1';
$groupid = groups_create_group($groupdata);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
groups_add_member($groupid, $user);
/* @var mod_assign_generator $assigngenerator */
$assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$activityrecord = $assigngenerator->create_instance(array('course' => $course->id));
$cm = get_coursemodule_from_instance('assign', $activityrecord->id);
$context = \context_module::instance($cm->id);
$assign = new mod_assign_testable_assign($context, $cm, $course);
$submission = $assign->get_group_submission($user->id, $groupid,true);
$fs = get_file_storage();
$dummy = (object) array(
'contextid' => $context->id,
'component' => 'assignsubmission_file',
'filearea' => ASSIGNSUBMISSION_FILE_FILEAREA,
'itemid' => $submission->id,
'filepath' => '/',
'filename' => 'myassignmnent.pdf'
);
$file = $fs->create_file_from_string($dummy, 'Content of ' . $dummy->filename);
// Now add second user.
$wronguser = $this->getDataGenerator()->create_user();
// Create a new group for the wrong user.
$groupdata = new \stdClass();
$groupdata->courseid = $course->id;
$groupdata->name = 'group2';
$groupid = groups_create_group($groupdata);
$this->getDataGenerator()->enrol_user($wronguser->id, $course->id);
groups_add_member($groupid, $wronguser);
// In the negative test for the user, we loaded the caller via fileid. Switching to the other approach this time.
$caller = new \assign_portfolio_caller(
array(
'cmid' => $cm->id,
'sid' => $submission->id,
'area' => ASSIGNSUBMISSION_FILE_FILEAREA,
'component' => 'assignsubmission_file',
)
);
$caller->set('user', $wronguser);
$this->expectException(\portfolio_caller_exception::class);
$this->expectExceptionMessage('Sorry, the requested file could not be found');
$caller->load_data();
}
}
@@ -0,0 +1,230 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the privacy legacy polyfill for mod_assign.
*
* @package mod_assign
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\privacy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/feedbackplugin.php');
require_once($CFG->dirroot . '/mod/assign/feedback/comments/locallib.php');
/**
* Unit tests for the assignment feedback subplugins API's privacy legacy_polyfill.
*
* @package mod_assign
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class feedback_legacy_polyfill_test extends \advanced_testcase {
/**
* Convenience function to create an instance of an assignment.
*
* @param array $params Array of parameters to pass to the generator
* @return assign The assign class.
*/
protected function create_instance($params = array()) {
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
return new \assign($context, $cm, $params['course']);
}
/**
* Test the get_context_for_userid_within_feedback shim.
*/
public function test_get_context_for_userid_within_feedback(): void {
$userid = 21;
$contextlist = new \core_privacy\local\request\contextlist();
$mock = $this->createMock(test_assignfeedback_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_get_context_for_userid_within_feedback', [$userid, $contextlist]);
test_legacy_polyfill_feedback_provider::$mock = $mock;
test_legacy_polyfill_feedback_provider::get_context_for_userid_within_feedback($userid, $contextlist);
}
/**
* Test the get_student_user_ids shim.
*/
public function test_get_student_user_ids(): void {
$teacherid = 107;
$assignid = 15;
$useridlist = new \mod_assign\privacy\useridlist($teacherid, $assignid);
$mock = $this->createMock(test_assignfeedback_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_get_student_user_ids', [$useridlist]);
test_legacy_polyfill_feedback_provider::$mock = $mock;
test_legacy_polyfill_feedback_provider::get_student_user_ids($useridlist);
}
/**
* Test the export_feedback_user_data shim.
*/
public function test_export_feedback_user_data(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$assign = $this->create_instance(['course' => $course]);
$context = \context_system::instance();
$subplugin = new \assign_feedback_comments($assign, 'comments');
$requestdata = new \mod_assign\privacy\assign_plugin_request_data($context,$assign);
$mock = $this->createMock(test_assignfeedback_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_export_feedback_user_data', [$requestdata]);
test_legacy_polyfill_feedback_provider::$mock = $mock;
test_legacy_polyfill_feedback_provider::export_feedback_user_data($requestdata);
}
/**
* Test the delete_feedback_for_context shim.
*/
public function test_delete_feedback_for_context(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$assign = $this->create_instance(['course' => $course]);
$context = \context_system::instance();
$subplugin = new \assign_feedback_comments($assign, 'comments');
$requestdata = new \mod_assign\privacy\assign_plugin_request_data($context,$assign);
$mock = $this->createMock(test_assignfeedback_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_delete_feedback_for_context', [$requestdata]);
test_legacy_polyfill_feedback_provider::$mock = $mock;
test_legacy_polyfill_feedback_provider::delete_feedback_for_context($requestdata);
}
/**
* Test the delete feedback for grade shim.
*/
public function test_delete_feedback_for_grade(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$assign = $this->create_instance(['course' => $course]);
$context = \context_system::instance();
$subplugin = new \assign_feedback_comments($assign, 'comments');
$requestdata = new \mod_assign\privacy\assign_plugin_request_data($context,$assign);
$mock = $this->createMock(test_assignfeedback_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_delete_feedback_for_grade', [$requestdata]);
test_legacy_polyfill_feedback_provider::$mock = $mock;
test_legacy_polyfill_feedback_provider::delete_feedback_for_grade($requestdata);
}
}
/**
* Legacy polyfill test class for the assignfeedback_provider.
*
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_legacy_polyfill_feedback_provider implements \mod_assign\privacy\assignfeedback_provider {
use \mod_assign\privacy\feedback_legacy_polyfill;
/**
* @var test_legacy_polyfill_feedback_provider $mock.
*/
public static $mock = null;
/**
* Retrieves the contextids associated with the provided userid for this subplugin.
* NOTE if your subplugin must have an entry in the assign_grade table to work, then this
* method can be empty.
*
* @param int $userid The user ID to get context IDs for.
* @param contextlist $contextlist Use add_from_sql with this object to add your context IDs.
*/
public static function _get_context_for_userid_within_feedback(int $userid,
\core_privacy\local\request\contextlist $contextlist) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* Returns student user ids related to the provided teacher ID. If an entry must be present in the assign_grade table for
* your plugin to work then there is no need to fill in this method. If you filled in get_context_for_userid_within_feedback()
* then you probably have to fill this in as well.
*
* @param useridlist $useridlist A list of user IDs of students graded by this user.
*/
public static function _get_student_user_ids(\mod_assign\privacy\useridlist $useridlist) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* Export feedback data with the available grade and userid information provided.
* assign_plugin_request_data contains:
* - context
* - grade object
* - current path (subcontext)
* - user object
*
* @param assign_plugin_request_data $exportdata Contains data to help export the user information.
*/
public static function _export_feedback_user_data(\mod_assign\privacy\assign_plugin_request_data $exportdata) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* Any call to this method should delete all user data for the context defined in the deletion_criteria.
* assign_plugin_request_data contains:
* - context
* - assign object
*
* @param assign_plugin_request_data $requestdata Data useful for deleting user data from this sub-plugin.
*/
public static function _delete_feedback_for_context(\mod_assign\privacy\assign_plugin_request_data $requestdata) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* Calling this function should delete all user data associated with this grade.
* assign_plugin_request_data contains:
* - context
* - grade object
* - user object
* - assign object
*
* @param assign_plugin_request_data $requestdata Data useful for deleting user data.
*/
public static function _delete_feedback_for_grade(\mod_assign\privacy\assign_plugin_request_data $requestdata) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
}
/**
* Called inside the polyfill methods in the test polyfill provider, allowing us to ensure these are called with correct params.
*
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_assignfeedback_legacy_polyfill_mock_wrapper {
/**
* Get the return value for the specified item.
*/
public function get_return_value() {
}
}
+817
View File
@@ -0,0 +1,817 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Base class for unit tests for mod_assign.
*
* @package mod_assign
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\privacy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\writer;
use core_privacy\local\request\approved_contextlist;
use mod_assign\privacy\provider;
/**
* Unit tests for mod/assign/classes/privacy/
*
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
/**
* Convenience method for creating a submission.
*
* @param assign $assign The assign object
* @param stdClass $user The user object
* @param string $submissiontext Submission text
* @param integer $attemptnumber The attempt number
* @return object A submission object.
*/
protected function create_submission($assign, $user, $submissiontext, $attemptnumber = 0) {
$submission = $assign->get_user_submission($user->id, true, $attemptnumber);
$submission->onlinetext_editor = ['text' => $submissiontext,
'format' => FORMAT_MOODLE];
$this->setUser($user);
$notices = [];
$assign->save_submission($submission, $notices);
return $submission;
}
/**
* Convenience function to create an instance of an assignment.
*
* @param array $params Array of parameters to pass to the generator
* @return assign The assign class.
*/
protected function create_instance($params = array()) {
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
return new \assign($context, $cm, $params['course']);
}
/**
* Test that getting the contexts for a user works.
*/
public function test_get_contexts_for_userid(): void {
global $DB;
$this->resetAfterTest();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$user1 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
$this->getDataGenerator()->enrol_user($user1->id, $course3->id, 'student');
// Need a second user to create content in other assignments.
$user2 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user2->id, $course2->id, 'student');
// Create multiple assignments.
// Assignment with a text submission.
$assign1 = $this->create_instance(['course' => $course1]);
// Assignment two in a different course that the user is not enrolled in.
$assign2 = $this->create_instance(['course' => $course2]);
// Assignment three has an entry in the override table.
$assign3 = $this->create_instance(['course' => $course3, 'cutoffdate' => time()]);
// Assignment four - blind marking.
$assign4 = $this->create_instance(['course' => $course1, 'blindmarking' => 1]);
// Assignment five - user flags.
$assign5 = $this->create_instance(['course' => $course3]);
// Override has to be manually inserted into the DB.
$overridedata = new \stdClass();
$overridedata->assignid = $assign3->get_instance()->id;
$overridedata->userid = $user1->id;
$overridedata->duedate = time();
$DB->insert_record('assign_overrides', $overridedata);
// Assign unique id for blind marking in assignment four for user 1.
\assign::get_uniqueid_for_user_static($assign4->get_instance()->id, $user1->id);
// Create an entry in the user flags table.
$assign5->get_user_flags($user1->id, true);
// The user will be in these contexts.
$usercontextids = [
$assign1->get_context()->id,
$assign3->get_context()->id,
$assign4->get_context()->id,
$assign5->get_context()->id,
];
$submission = new \stdClass();
$submission->assignment = $assign1->get_instance()->id;
$submission->userid = $user1->id;
$submission->timecreated = time();
$submission->onlinetext_editor = ['text' => 'Submission text',
'format' => FORMAT_MOODLE];
$this->setUser($user1);
$notices = [];
$assign1->save_submission($submission, $notices);
// Create a submission for the second assignment.
$submission->assignment = $assign2->get_instance()->id;
$submission->userid = $user2->id;
$this->setUser($user2);
$assign2->save_submission($submission, $notices);
$contextlist = provider::get_contexts_for_userid($user1->id);
$this->assertEquals(count($usercontextids), count($contextlist->get_contextids()));
// There should be no difference between the contexts.
$this->assertEmpty(array_diff($usercontextids, $contextlist->get_contextids()));
}
/**
* Test returning a list of user IDs related to a context (assign).
*/
public function test_get_users_in_context(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
// Only made a comment on a submission.
$user1 = $this->getDataGenerator()->create_user();
// User 2 only has information about an activity override.
$user2 = $this->getDataGenerator()->create_user();
// User 3 made a submission.
$user3 = $this->getDataGenerator()->create_user();
// User 4 makes a submission and it is marked by the teacher.
$user4 = $this->getDataGenerator()->create_user();
// Grading and providing feedback as a teacher.
$user5 = $this->getDataGenerator()->create_user();
// This user has no entries and should not show up.
$user6 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user4->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user5->id, $course->id, 'editingteacher');
$this->getDataGenerator()->enrol_user($user6->id, $course->id, 'student');
$assign1 = $this->create_instance(['course' => $course,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true]);
$assign2 = $this->create_instance(['course' => $course]);
$context = $assign1->get_context();
// Jam an entry in the comments table for user 1.
$comment = (object) [
'contextid' => $context->id,
'component' => 'assignsubmission_comments',
'commentarea' => 'submission_comments',
'itemid' => 5,
'content' => 'A comment by user 1',
'format' => 0,
'userid' => $user1->id,
'timecreated' => time()
];
$DB->insert_record('comments', $comment);
$this->setUser($user5); // Set the user to the teacher.
$overridedata = new \stdClass();
$overridedata->assignid = $assign1->get_instance()->id;
$overridedata->userid = $user2->id;
$overridedata->duedate = time();
$overridedata->allowsubmissionsfromdate = time();
$overridedata->cutoffdate = time();
$DB->insert_record('assign_overrides', $overridedata);
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign1, $user3, $submissiontext);
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign1, $user4, $submissiontext);
$this->setUser($user5);
$grade = '72.00';
$teachercommenttext = 'This is better. Thanks.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign1->save_grade($user4->id, $data);
$userlist = new \core_privacy\local\request\userlist($context, 'assign');
provider::get_users_in_context($userlist);
$userids = $userlist->get_userids();
$this->assertTrue(in_array($user1->id, $userids));
$this->assertTrue(in_array($user2->id, $userids));
$this->assertTrue(in_array($user3->id, $userids));
$this->assertTrue(in_array($user4->id, $userids));
$this->assertTrue(in_array($user5->id, $userids));
$this->assertFalse(in_array($user6->id, $userids));
}
/**
* Test that a student with multiple submissions and grades is returned with the correct data.
*/
public function test_export_user_data_student(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$user = $this->getDataGenerator()->create_user();
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
$assign = $this->create_instance([
'course' => $course,
'name' => 'Assign 1',
'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
'maxattempts' => 3,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true
]);
$context = $assign->get_context();
// Create some submissions (multiple attempts) for a student.
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign, $user, $submissiontext);
$this->setUser($teacher);
$overridedata = new \stdClass();
$overridedata->assignid = $assign->get_instance()->id;
$overridedata->userid = $user->id;
$overridedata->duedate = time();
$overridedata->allowsubmissionsfromdate = time();
$overridedata->cutoffdate = time();
$DB->insert_record('assign_overrides', $overridedata);
$grade1 = '67.00';
$teachercommenttext = 'Please try again.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade1;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user->id, $data);
$submissiontext2 = 'My second submission';
$submission = $this->create_submission($assign, $user, $submissiontext2, 1);
$this->setUser($teacher);
$grade2 = '72.00';
$teachercommenttext2 = 'This is better. Thanks.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade2;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user->id, $data);
/** @var \core_privacy\tests\request\content_writer $writer */
$writer = writer::with_context($context);
$this->assertFalse($writer->has_any_data());
// The student should have some text submitted.
// Add the course context as well to make sure there is no error.
$approvedlist = new approved_contextlist($user, 'mod_assign', [$context->id, $coursecontext->id]);
provider::export_user_data($approvedlist);
// Check that we have general details about the assignment.
$this->assertEquals('Assign 1', $writer->get_data()->name);
// Check Submissions.
$this->assertEquals($submissiontext, $writer->get_data(['attempt 1', 'Submission Text'])->text);
$this->assertEquals($submissiontext2, $writer->get_data(['attempt 2', 'Submission Text'])->text);
$this->assertEquals(1, $writer->get_data(['attempt 1', 'submission'])->attemptnumber);
$this->assertEquals(2, $writer->get_data(['attempt 2', 'submission'])->attemptnumber);
// Check grades.
$this->assertEquals((float)$grade1, $writer->get_data(['attempt 1', 'grade'])->grade);
$this->assertEquals((float)$grade2, $writer->get_data(['attempt 2', 'grade'])->grade);
// Check feedback.
$this->assertStringContainsString($teachercommenttext, $writer->get_data(['attempt 1', 'Feedback comments'])->commenttext);
$this->assertStringContainsString($teachercommenttext2, $writer->get_data(['attempt 2', 'Feedback comments'])->commenttext);
// Check override data was exported correctly.
$overrideexport = $writer->get_data(['Overrides']);
$this->assertEquals(\core_privacy\local\request\transform::datetime($overridedata->duedate),
$overrideexport->duedate);
$this->assertEquals(\core_privacy\local\request\transform::datetime($overridedata->cutoffdate),
$overrideexport->cutoffdate);
$this->assertEquals(\core_privacy\local\request\transform::datetime($overridedata->allowsubmissionsfromdate),
$overrideexport->allowsubmissionsfromdate);
}
/**
* Tests the data returned for a teacher.
*/
public function test_export_user_data_teacher(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
$assign = $this->create_instance([
'course' => $course,
'name' => 'Assign 1',
'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
'maxattempts' => 3,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true
]);
$context = $assign->get_context();
// Create and grade some submissions from the students.
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign, $user1, $submissiontext);
$this->setUser($teacher);
$grade1 = '54.00';
$teachercommenttext = 'Comment on user 1 attempt 1.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade1;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user1->id, $data);
// Create and grade some submissions from the students.
$submissiontext2 = 'My first submission for user 2';
$submission = $this->create_submission($assign, $user2, $submissiontext2);
$this->setUser($teacher);
$grade2 = '56.00';
$teachercommenttext2 = 'Comment on user 2 first attempt.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade2;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user2->id, $data);
// Create and grade some submissions from the students.
$submissiontext3 = 'My second submission for user 2';
$submission = $this->create_submission($assign, $user2, $submissiontext3, 1);
$this->setUser($teacher);
$grade3 = '83.00';
$teachercommenttext3 = 'Comment on user 2 another attempt.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade3;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext3, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user2->id, $data);
// Set up some flags.
$duedate = time();
$flagdata = $assign->get_user_flags($teacher->id, true);
$flagdata->mailed = 1;
$flagdata->extensionduedate = $duedate;
$assign->update_user_flags($flagdata);
/** @var \core_privacy\tests\request\content_writer $writer */
$writer = writer::with_context($context);
$this->assertFalse($writer->has_any_data());
// The student should have some text submitted.
$approvedlist = new approved_contextlist($teacher, 'mod_assign', [$context->id, $coursecontext->id]);
provider::export_user_data($approvedlist);
// Check flag metadata.
$metadata = $writer->get_all_metadata();
$this->assertEquals(\core_privacy\local\request\transform::yesno(1), $metadata['mailed']->value);
$this->assertEquals(\core_privacy\local\request\transform::datetime($duedate), $metadata['extensionduedate']->value);
// Check for student grades given.
$student1grade = $writer->get_data(['studentsubmissions', $user1->id, 'attempt 1', 'grade']);
$this->assertEquals((float)$grade1, $student1grade->grade);
$student2grade1 = $writer->get_data(['studentsubmissions', $user2->id, 'attempt 1', 'grade']);
$this->assertEquals((float)$grade2, $student2grade1->grade);
$student2grade2 = $writer->get_data(['studentsubmissions', $user2->id, 'attempt 2', 'grade']);
$this->assertEquals((float)$grade3, $student2grade2->grade);
// Check for feedback given to students.
$this->assertStringContainsString($teachercommenttext, $writer->get_data(['studentsubmissions', $user1->id, 'attempt 1',
'Feedback comments'])->commenttext);
$this->assertStringContainsString($teachercommenttext2, $writer->get_data(['studentsubmissions', $user2->id, 'attempt 1',
'Feedback comments'])->commenttext);
$this->assertStringContainsString($teachercommenttext3, $writer->get_data(['studentsubmissions', $user2->id, 'attempt 2',
'Feedback comments'])->commenttext);
}
/**
* A test for deleting all user data for a given context.
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
$assign = $this->create_instance([
'course' => $course,
'name' => 'Assign 1',
'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
'maxattempts' => 3,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true
]);
$context = $assign->get_context();
// Create and grade some submissions from the students.
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign, $user1, $submissiontext);
$this->setUser($teacher);
// Overrides for both students.
$overridedata = new \stdClass();
$overridedata->assignid = $assign->get_instance()->id;
$overridedata->userid = $user1->id;
$overridedata->duedate = time();
$DB->insert_record('assign_overrides', $overridedata);
$overridedata->userid = $user2->id;
$DB->insert_record('assign_overrides', $overridedata);
assign_update_events($assign);
$grade1 = '54.00';
$teachercommenttext = 'Comment on user 1 attempt 1.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade1;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user1->id, $data);
// Create and grade some submissions from the students.
$submissiontext2 = 'My first submission for user 2';
$submission = $this->create_submission($assign, $user2, $submissiontext2);
$this->setUser($teacher);
$grade2 = '56.00';
$teachercommenttext2 = 'Comment on user 2 first attempt.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade2;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user2->id, $data);
// Create and grade some submissions from the students.
$submissiontext3 = 'My second submission for user 2';
$submission = $this->create_submission($assign, $user2, $submissiontext3, 1);
$this->setUser($teacher);
$grade3 = '83.00';
$teachercommenttext3 = 'Comment on user 2 another attempt.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade3;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext3, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user2->id, $data);
// Delete all user data for this assignment.
provider::delete_data_for_all_users_in_context($context);
// Check all relevant tables.
$records = $DB->get_records('assign_submission');
$this->assertEmpty($records);
$records = $DB->get_records('assign_grades');
$this->assertEmpty($records);
$records = $DB->get_records('assignsubmission_onlinetext');
$this->assertEmpty($records);
$records = $DB->get_records('assignfeedback_comments');
$this->assertEmpty($records);
// Check that overrides and the calendar events are deleted.
$records = $DB->get_records('event');
$this->assertEmpty($records);
$records = $DB->get_records('assign_overrides');
$this->assertEmpty($records);
}
/**
* A test for deleting all user data for one user.
*/
public function test_delete_data_for_user(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher');
$assign = $this->create_instance([
'course' => $course,
'name' => 'Assign 1',
'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL,
'maxattempts' => 3,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true
]);
$context = $assign->get_context();
// Create and grade some submissions from the students.
$submissiontext = 'My first submission';
$submission1 = $this->create_submission($assign, $user1, $submissiontext);
$this->setUser($teacher);
// Overrides for both students.
$overridedata = new \stdClass();
$overridedata->assignid = $assign->get_instance()->id;
$overridedata->userid = $user1->id;
$overridedata->duedate = time();
$DB->insert_record('assign_overrides', $overridedata);
$overridedata->userid = $user2->id;
$DB->insert_record('assign_overrides', $overridedata);
assign_update_events($assign);
$grade1 = '54.00';
$teachercommenttext = 'Comment on user 1 attempt 1.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade1;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user1->id, $data);
// Create and grade some submissions from the students.
$submissiontext2 = 'My first submission for user 2';
$submission2 = $this->create_submission($assign, $user2, $submissiontext2);
$this->setUser($teacher);
$grade2 = '56.00';
$teachercommenttext2 = 'Comment on user 2 first attempt.';
$data = new \stdClass();
$data->attemptnumber = 0;
$data->grade = $grade2;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user2->id, $data);
// Create and grade some submissions from the students.
$submissiontext3 = 'My second submission for user 2';
$submission3 = $this->create_submission($assign, $user2, $submissiontext3, 1);
$this->setUser($teacher);
$grade3 = '83.00';
$teachercommenttext3 = 'Comment on user 2 another attempt.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade3;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext3, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign->save_grade($user2->id, $data);
// Delete user 2's data.
$approvedlist = new approved_contextlist($user2, 'mod_assign', [$context->id, $coursecontext->id]);
provider::delete_data_for_user($approvedlist);
// Check all relevant tables.
$records = $DB->get_records('assign_submission');
foreach ($records as $record) {
$this->assertEquals($user1->id, $record->userid);
$this->assertNotEquals($user2->id, $record->userid);
}
$records = $DB->get_records('assign_grades');
foreach ($records as $record) {
$this->assertEquals($user1->id, $record->userid);
$this->assertNotEquals($user2->id, $record->userid);
}
$records = $DB->get_records('assignsubmission_onlinetext');
$this->assertCount(1, $records);
$record = array_shift($records);
// The only submission is for user 1.
$this->assertEquals($submission1->id, $record->submission);
$records = $DB->get_records('assignfeedback_comments');
$this->assertCount(1, $records);
$record = array_shift($records);
// The only record is the feedback comment for user 1.
$this->assertEquals($teachercommenttext, $record->commenttext);
// Check calendar events as well as assign overrides.
$records = $DB->get_records('event');
$this->assertCount(1, $records);
$record = array_shift($records);
// The remaining event should be for user 1.
$this->assertEquals($user1->id, $record->userid);
// Now for assign_overrides
$records = $DB->get_records('assign_overrides');
$this->assertCount(1, $records);
$record = array_shift($records);
// The remaining event should be for user 1.
$this->assertEquals($user1->id, $record->userid);
}
/**
* A test for deleting all user data for a bunch of users.
*/
public function test_delete_data_for_users(): void {
global $DB;
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
// Only made a comment on a submission.
$user1 = $this->getDataGenerator()->create_user();
// User 2 only has information about an activity override.
$user2 = $this->getDataGenerator()->create_user();
// User 3 made a submission.
$user3 = $this->getDataGenerator()->create_user();
// User 4 makes a submission and it is marked by the teacher.
$user4 = $this->getDataGenerator()->create_user();
// Grading and providing feedback as a teacher.
$user5 = $this->getDataGenerator()->create_user();
// This user has entries in assignment 2 and should not have their data deleted.
$user6 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user4->id, $course->id, 'student');
$this->getDataGenerator()->enrol_user($user5->id, $course->id, 'editingteacher');
$this->getDataGenerator()->enrol_user($user6->id, $course->id, 'student');
$assign1 = $this->create_instance(['course' => $course,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true]);
$assign2 = $this->create_instance(['course' => $course,
'assignsubmission_onlinetext_enabled' => true,
'assignfeedback_comments_enabled' => true]);
$context = $assign1->get_context();
// Jam an entry in the comments table for user 1.
$comment = (object) [
'contextid' => $context->id,
'component' => 'assignsubmission_comments',
'commentarea' => 'submission_comments',
'itemid' => 5,
'content' => 'A comment by user 1',
'format' => 0,
'userid' => $user1->id,
'timecreated' => time()
];
$DB->insert_record('comments', $comment);
$this->setUser($user5); // Set the user to the teacher.
$overridedata = new \stdClass();
$overridedata->assignid = $assign1->get_instance()->id;
$overridedata->userid = $user2->id;
$overridedata->duedate = time();
$overridedata->allowsubmissionsfromdate = time();
$overridedata->cutoffdate = time();
$DB->insert_record('assign_overrides', $overridedata);
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign1, $user3, $submissiontext);
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign1, $user4, $submissiontext);
$submissiontext = 'My first submission';
$submission = $this->create_submission($assign2, $user6, $submissiontext);
$this->setUser($user5);
$grade = '72.00';
$teachercommenttext = 'This is better. Thanks.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign1->save_grade($user4->id, $data);
$this->setUser($user5);
$grade = '81.00';
$teachercommenttext = 'This is nice.';
$data = new \stdClass();
$data->attemptnumber = 1;
$data->grade = $grade;
$data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE];
// Give the submission a grade.
$assign2->save_grade($user6->id, $data);
// Check data is in place.
$data = $DB->get_records('assign_submission');
// We should have one entry for user 3 and two entries each for user 4 and 6.
$this->assertCount(5, $data);
$usercounts = [
$user3->id => 0,
$user4->id => 0,
$user6->id => 0
];
foreach ($data as $datum) {
$usercounts[$datum->userid]++;
}
$this->assertEquals(1, $usercounts[$user3->id]);
$this->assertEquals(2, $usercounts[$user4->id]);
$this->assertEquals(2, $usercounts[$user6->id]);
$data = $DB->get_records('assign_grades');
// Two entries in assign_grades, one for each grade given.
$this->assertCount(2, $data);
$data = $DB->get_records('assign_overrides');
$this->assertCount(1, $data);
$data = $DB->get_records('comments');
$this->assertCount(1, $data);
$userlist = new \core_privacy\local\request\approved_userlist($context, 'assign', [$user1->id, $user2->id]);
provider::delete_data_for_users($userlist);
$data = $DB->get_records('assign_overrides');
$this->assertEmpty($data);
$data = $DB->get_records('comments');
$this->assertEmpty($data);
$data = $DB->get_records('assign_submission');
// No change here.
$this->assertCount(5, $data);
$userlist = new \core_privacy\local\request\approved_userlist($context, 'assign', [$user3->id, $user5->id]);
provider::delete_data_for_users($userlist);
$data = $DB->get_records('assign_submission');
// Only the record for user 3 has been deleted.
$this->assertCount(4, $data);
$data = $DB->get_records('assign_grades');
// Grades should be unchanged.
$this->assertCount(2, $data);
}
}
@@ -0,0 +1,231 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the privacy legacy polyfill for mod_assign.
*
* @package mod_assign
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\privacy;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/submissionplugin.php');
require_once($CFG->dirroot . '/mod/assign/submission/comments/locallib.php');
/**
* Unit tests for the assignment submission subplugins API's privacy legacy_polyfill.
*
* @package mod_assign
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class submission_legacy_polyfill_test extends \advanced_testcase {
/**
* Convenience function to create an instance of an assignment.
*
* @param array $params Array of parameters to pass to the generator
* @return assign The assign class.
*/
protected function create_instance($params = array()) {
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$instance = $generator->create_instance($params);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = \context_module::instance($cm->id);
return new \assign($context, $cm, $params['course']);
}
/**
* Test the get_context_for_userid_within_submission shim.
*/
public function test_get_context_for_userid_within_submission(): void {
$userid = 21;
$contextlist = new \core_privacy\local\request\contextlist();
$mock = $this->createMock(test_assignsubmission_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_get_context_for_userid_within_submission', [$userid, $contextlist]);
test_legacy_polyfill_submission_provider::$mock = $mock;
test_legacy_polyfill_submission_provider::get_context_for_userid_within_submission($userid, $contextlist);
}
/**
* Test the get_student_user_ids shim.
*/
public function test_get_student_user_ids(): void {
$teacherid = 107;
$assignid = 15;
$useridlist = new \mod_assign\privacy\useridlist($teacherid, $assignid);
$mock = $this->createMock(test_assignsubmission_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_get_student_user_ids', [$useridlist]);
test_legacy_polyfill_submission_provider::$mock = $mock;
test_legacy_polyfill_submission_provider::get_student_user_ids($useridlist);
}
/**
* Test the export_submission_user_data shim.
*/
public function test_export_submission_user_data(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$assign = $this->create_instance(['course' => $course]);
$context = \context_system::instance();
$subplugin = new \assign_submission_comments($assign, 'comment');
$requestdata = new \mod_assign\privacy\assign_plugin_request_data($context, $assign);
$mock = $this->createMock(test_assignsubmission_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_export_submission_user_data', [$requestdata]);
test_legacy_polyfill_submission_provider::$mock = $mock;
test_legacy_polyfill_submission_provider::export_submission_user_data($requestdata);
}
/**
* Test the delete_submission_for_context shim.
*/
public function test_delete_submission_for_context(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$assign = $this->create_instance(['course' => $course]);
$context = \context_system::instance();
$subplugin = new \assign_submission_comments($assign, 'comment');
$requestdata = new \mod_assign\privacy\assign_plugin_request_data($context, $assign);
$mock = $this->createMock(test_assignsubmission_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_delete_submission_for_context', [$requestdata]);
test_legacy_polyfill_submission_provider::$mock = $mock;
test_legacy_polyfill_submission_provider::delete_submission_for_context($requestdata);
}
/**
* Test the delete submission for grade shim.
*/
public function test_delete_submission_for_userid(): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course();
$assign = $this->create_instance(['course' => $course]);
$context = \context_system::instance();
$subplugin = new \assign_submission_comments($assign, 'comment');
$requestdata = new \mod_assign\privacy\assign_plugin_request_data($context, $assign);
$mock = $this->createMock(test_assignsubmission_legacy_polyfill_mock_wrapper::class);
$mock->expects($this->once())
->method('get_return_value')
->with('_delete_submission_for_userid', [$requestdata]);
test_legacy_polyfill_submission_provider::$mock = $mock;
test_legacy_polyfill_submission_provider::delete_submission_for_userid($requestdata);
}
}
/**
* Legacy polyfill test class for the assignsubmission_provider.
*
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_legacy_polyfill_submission_provider implements \mod_assign\privacy\assignsubmission_provider {
use \mod_assign\privacy\submission_legacy_polyfill;
/**
* @var test_legacy_polyfill_submission_provider $mock.
*/
public static $mock = null;
/**
* Retrieves the contextids associated with the provided userid for this subplugin.
* NOTE if your subplugin must have an entry in the assign_grade table to work, then this
* method can be empty.
*
* @param int $userid The user ID to get context IDs for.
* @param contextlist $contextlist Use add_from_sql with this object to add your context IDs.
*/
public static function _get_context_for_userid_within_submission(int $userid,
\core_privacy\local\request\contextlist $contextlist) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* Returns student user ids related to the provided teacher ID. If it is possible that a student ID will not be returned by
* the sql query in \mod_assign\privacy\provider::find_grader_info() Then you need to provide some sql to retrive those
* student IDs. This is highly likely if you had to fill in get_context_for_userid_within_submission above.
*
* @param useridlist $useridlist A list of user IDs of students graded by this user.
*/
public static function _get_student_user_ids(\mod_assign\privacy\useridlist $useridlist) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* This method is used to export any user data this sub-plugin has using the assign_plugin_request_data object to get the
* context and userid.
* assign_plugin_request_data contains:
* - context
* - grade object
* - current path (subcontext)
* - user object
*
* @param assign_plugin_request_data $exportdata Contains data to help export the user information.
*/
public static function _export_submission_user_data(\mod_assign\privacy\assign_plugin_request_data $exportdata) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* Any call to this method should delete all user data for the context defined in the deletion_criteria.
* assign_plugin_request_data contains:
* - context
* - assign object
*
* @param assign_plugin_request_data $requestdata Data useful for deleting user data from this sub-plugin.
*/
public static function _delete_submission_for_context(\mod_assign\privacy\assign_plugin_request_data $requestdata) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
/**
* A call to this method should delete user data (where practicle) from the userid and context.
* assign_plugin_request_data contains:
* - context
* - grade object
* - user object
* - assign object
*
* @param assign_plugin_request_data $requestdata Data useful for deleting user data.
*/
public static function _delete_submission_for_userid(\mod_assign\privacy\assign_plugin_request_data $requestdata) {
static::$mock->get_return_value(__FUNCTION__, func_get_args());
}
}
/**
* Called inside the polyfill methods in the test polyfill provider, allowing us to ensure these are called with correct params.
*
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_assignsubmission_legacy_polyfill_mock_wrapper {
/**
* Get the return value for the specified item.
*/
public function get_return_value() {
}
}
+126
View File
@@ -0,0 +1,126 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Assign search unit tests.
*
* @package mod_assign
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\search;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
require_once($CFG->dirroot . '/mod/assign/locallib.php');
/**
* Provides the unit tests for forum search.
*
* @package mod_assign
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class search_test extends \advanced_testcase {
/**
* Test for assign file attachments.
*
* @return void
*/
public function test_attach_files(): void {
global $USER;
$this->resetAfterTest(true);
set_config('enableglobalsearch', true);
$assignareaid = \core_search\manager::generate_areaid('mod_assign', 'activity');
// Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
$search = \testable_core_search::instance();
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$fs = get_file_storage();
$usercontext = \context_user::instance($USER->id);
$record = new \stdClass();
$record->course = $course->id;
$assign = $this->getDataGenerator()->create_module('assign', $record);
$context = \context_module::instance($assign->cmid);
// Attach the main file. We put them in the draft area, create_module will move them.
$filerecord = array(
'contextid' => $context->id,
'component' => 'mod_assign',
'filearea' => ASSIGN_INTROATTACHMENT_FILEAREA,
'itemid' => 0,
'filepath' => '/'
);
// Attach 4 files.
for ($i = 1; $i <= 4; $i++) {
$filerecord['filename'] = 'myfile'.$i;
$fs->create_file_from_string($filerecord, 'Test assign file '.$i);
}
// And a fifth in a sub-folder.
$filerecord['filename'] = 'myfile5';
$filerecord['filepath'] = '/subfolder/';
$fs->create_file_from_string($filerecord, 'Test assign file 5');
// Returns the instance as long as the area is supported.
$searcharea = \core_search\manager::get_search_area($assignareaid);
$this->assertInstanceOf('\mod_assign\search\activity', $searcharea);
$recordset = $searcharea->get_recordset_by_timestamp(0);
$nrecords = 0;
foreach ($recordset as $record) {
$doc = $searcharea->get_document($record);
$searcharea->attach_files($doc);
$files = $doc->get_files();
// Assign should return all files attached.
$this->assertCount(5, $files);
// We don't know the order, so get all the names, then sort, then check.
$filenames = array();
foreach ($files as $file) {
$filenames[] = $file->get_filename();
}
sort($filenames);
for ($i = 1; $i <= 5; $i++) {
$this->assertEquals('myfile'.$i, $filenames[($i - 1)]);
}
$nrecords++;
}
// If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
$recordset->close();
$this->assertEquals(1, $nrecords);
}
}