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,126 @@
@core @core_cohort @enrol_cohort
Feature: Access visible and hidden cohorts
In order to enrol users from cohorts
As an manager or teacher
I need to be able to view the list of cohorts defined above the course
Background:
Given the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
| Cat 2 | 0 | CAT2 |
And the following "cohorts" exist:
| name | idnumber | visible |
| System cohort | CV0 | 1 |
| System hidden cohort | CH0 | 0 |
| System empty cohort | CVE0 | 1 |
And the following "cohorts" exist:
| name | idnumber | contextlevel | reference | visible |
| Cohort in category 1 | CV1 | Category | CAT1 | 1 |
| Cohort in category 2 | CV2 | Category | CAT2 | 1 |
| Cohort hidden in category 1 | CH1 | Category | CAT1 | 0 |
| Cohort empty in category 1 | CVE1 | Category | CAT1 | 1 |
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | First | User | first@example.com |
| user2 | Second | User | second@example.com |
| student | Sam | User | student@example.com |
| teacher | Terry | User | teacher@example.com |
And the following "cohort members" exist:
| user | cohort |
| student | CV0 |
| student | CV1 |
| student | CV2 |
| student | CH0 |
| student | CH1 |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user1 | manager | System | |
| user2 | manager | Category | CAT1 |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | CAT1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher | C1 | editingteacher |
@javascript @skip_chrome_zerosize
Scenario: Teacher can see visible cohorts defined in the above contexts
When I log in as "teacher"
And I am on the "Course 1" "enrolment methods" page
And I select "Cohort sync" from the "Add method" singleselect
And I open the autocomplete suggestions list
Then "Cohort in category 1" "autocomplete_suggestions" should exist
And "System cohort" "autocomplete_suggestions" should exist
And "Cohort hidden in category 1" "autocomplete_suggestions" should not exist
And "System hidden cohort" "autocomplete_suggestions" should not exist
And "Cohort in category 2" "autocomplete_suggestions" should not exist
And "Cohort empty in category 1" "autocomplete_suggestions" should exist
And "System empty cohort" "autocomplete_suggestions" should exist
And I set the field "Cohort" to "System cohort"
And I press "Add method"
And I am on the "Course 1" "enrolled users" page
And I should see "student@example.com"
And I am on the "Course 1" "groups" page
And I press "Auto-create groups"
And the "Select members from cohort" select box should contain "Cohort in category 1"
And the "Select members from cohort" select box should contain "System cohort"
And the "Select members from cohort" select box should not contain "Cohort hidden in category 1"
And the "Select members from cohort" select box should not contain "System hidden cohort"
And the "Select members from cohort" select box should not contain "Cohort in category 2"
And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
And the "Select members from cohort" select box should not contain "System empty cohort"
@javascript @skip_chrome_zerosize
Scenario: System manager can see all cohorts defined in the above contexts
When I log in as "user1"
And I am on the "Course 1" "enrolment methods" page
And I select "Cohort sync" from the "Add method" singleselect
And I open the autocomplete suggestions list
Then "Cohort in category 1" "autocomplete_suggestions" should exist
And "System cohort" "autocomplete_suggestions" should exist
And "Cohort hidden in category 1" "autocomplete_suggestions" should exist
And "System hidden cohort" "autocomplete_suggestions" should exist
And "Cohort in category 2" "autocomplete_suggestions" should not exist
And "Cohort empty in category 1" "autocomplete_suggestions" should exist
And "System empty cohort" "autocomplete_suggestions" should exist
And I set the field "Cohort" to "System cohort"
And I press "Add method"
And I am on the "Course 1" "enrolled users" page
And I should see "student@example.com"
And I am on the "Course 1" "groups" page
And I press "Auto-create groups"
And the "Select members from cohort" select box should contain "Cohort in category 1"
And the "Select members from cohort" select box should contain "System cohort"
And the "Select members from cohort" select box should contain "Cohort hidden in category 1"
And the "Select members from cohort" select box should contain "System hidden cohort"
And the "Select members from cohort" select box should not contain "Cohort in category 2"
And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
And the "Select members from cohort" select box should not contain "System empty cohort"
@javascript @skip_chrome_zerosize
Scenario: Category manager can see all cohorts defined in his category and visible cohorts defined above
When I log in as "user2"
And I am on the "Course 1" "enrolment methods" page
And I select "Cohort sync" from the "Add method" singleselect
And I open the autocomplete suggestions list
Then "Cohort in category 1" "autocomplete_suggestions" should exist
And "System cohort" "autocomplete_suggestions" should exist
And "Cohort hidden in category 1" "autocomplete_suggestions" should exist
And "System hidden cohort" "autocomplete_suggestions" should not exist
And "Cohort in category 2" "autocomplete_suggestions" should not exist
And "Cohort empty in category 1" "autocomplete_suggestions" should exist
And "System empty cohort" "autocomplete_suggestions" should exist
And I set the field "Cohort" to "System cohort"
And I press "Add method"
And I am on the "Course 1" "enrolled users" page
And I should see "student@example.com"
And I am on the "Course 1" "groups" page
And I press "Auto-create groups"
And the "Select members from cohort" select box should contain "Cohort in category 1"
And the "Select members from cohort" select box should contain "System cohort"
And the "Select members from cohort" select box should contain "Cohort hidden in category 1"
And the "Select members from cohort" select box should not contain "System hidden cohort"
And the "Select members from cohort" select box should not contain "Cohort in category 2"
And the "Select members from cohort" select box should not contain "Cohort empty in category 1"
And the "Select members from cohort" select box should not contain "System empty cohort"
+128
View File
@@ -0,0 +1,128 @@
@core @core_cohort
Feature: Add cohorts of users
In order to create site-wide groups
As an admin
I need to create cohorts and add users on them
Background:
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | fruit | Fruit |
And the following "users" exist:
| username | firstname | lastname | email | profile_field_fruit |
| user1 | First | User | first@example.com | Apple |
| user2 | Second | User | second@example.com | Banana |
| user3 | Third | User | third@example.com | Apple |
| user4 | Forth | User | forth@example.com | Pear |
And the following "cohort" exists:
| name | Test cohort name |
| idnumber | 333 |
| description | Test cohort description |
And I log in as "admin"
And I navigate to "Users > Accounts > Cohorts" in site administration
@javascript
Scenario: Add a cohort
When I follow "Add new cohort"
And I set the following fields to these values:
| Name | My new cohort |
| Context | System |
| Cohort ID | mynewcohort |
| Description | My new cohort is cool |
And I press "Save changes"
Then the following should exist in the "generaltable" table:
| Name | Cohort ID | Description |
| My new cohort | mynewcohort | My new cohort is cool |
And I should see "Test cohort name"
And I should see "333"
And I should see "Test cohort description"
And I should see "Created manually"
@javascript
Scenario: Add users to a cohort selecting them from the system users list
When I add "First User (first@example.com)" user to "333" cohort members
And I add "Second User (second@example.com)" user to "333" cohort members
Then the following should exist in the "reportbuilder-table" table:
| Name | Cohort size |
| Test cohort name | 2 |
And I press "Assign" action in the "Test cohort name" report row
And the "Current users" select box should contain "First User (first@example.com)"
And the "Current users" select box should contain "Second User (second@example.com)"
And the "Current users" select box should not contain "Forth User (forth@example.com)"
@javascript
Scenario: Add user to cohort using custom user field search
Given the following config values are set as admin:
| showuseridentity | email,profile_field_fruit |
When I press "Assign" action in the "Test cohort name" report row
And I set the field "addselect_searchtext" to "Apple"
And I wait "1" seconds
Then the "Potential users" select box should contain "First User (first@example.com\, Apple)"
And the "Potential users" select box should not contain "Second User (second@example.com\, Banana)"
And the "Potential users" select box should not contain "Forth User (forth@example.com\, Pear)"
And I set the field "Potential users" to "Third User (third@example.com\, Apple)"
And I press "Add"
And the "Current users" select box should contain "Third User (third@example.com\, Apple)"
@javascript
Scenario: Remove user from cohort using custom user field search
Given the following config values are set as admin:
| showuseridentity | email,profile_field_fruit |
And the following "cohort members" exist:
| cohort | user |
| 333 | user1 |
| 333 | user2 |
When I press "Assign" action in the "Test cohort name" report row
And I set the field "removeselect_searchtext" to "Apple"
And I wait "1" seconds
Then the "Current users" select box should not contain "Second User (second@example.com\, Banana)"
And I set the field "Current users" to "First User (first@example.com\, Apple)"
And I press "Remove"
And the "Potential users" select box should contain "First User (first@example.com\, Apple)"
@javascript
Scenario: Add users to a cohort using a bulk user action
When I navigate to "Users > Accounts > Bulk user actions" in site administration
And I set the field "Available" to "Third User"
And I press "Add to selection"
And I set the field "Available" to "Forth User"
And I press "Add to selection"
And I set the field "id_action" to "Add to cohort"
And I press "Go"
And I set the field "Cohort" to "Test cohort name [333]"
And I press "Add to cohort"
And I navigate to "Users > Accounts > Cohorts" in site administration
Then the following should exist in the "reportbuilder-table" table:
| Name | Cohort size |
| Test cohort name | 2 |
And I press "Assign" action in the "Test cohort name" report row
And the "Current users" select box should contain "Third User (third@example.com)"
And the "Current users" select box should contain "Forth User (forth@example.com)"
And the "Current users" select box should not contain "First User (first@example.com)"
@javascript
Scenario: Add users to a cohort using a user list bulk action
When I navigate to "Users > Accounts > Browse list of users" in site administration
And I click on "Third User" "checkbox"
And I click on "Forth User" "checkbox"
And I set the field "Bulk user actions" to "Add to cohort"
And I set the field "Cohort" to "Test cohort name [333]"
And I press "Add to cohort"
And I should see "Browse list of users"
And I navigate to "Users > Accounts > Cohorts" in site administration
Then the following should exist in the "reportbuilder-table" table:
| Name | Cohort size |
| Test cohort name | 2 |
And I press "Assign" action in the "Test cohort name" report row
And the "Current users" select box should contain "Third User (third@example.com)"
And the "Current users" select box should contain "Forth User (forth@example.com)"
And the "Current users" select box should not contain "First User (first@example.com)"
@javascript
Scenario: Edit cohort name in-place
When I navigate to "Users > Accounts > Cohorts" in site administration
And I set the field "Edit cohort name" to "Students cohort"
Then I should not see "Test cohort name"
And I should see "Students cohort"
And I navigate to "Users > Accounts > Cohorts" in site administration
And I should see "Students cohort"
+73
View File
@@ -0,0 +1,73 @@
<?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/>.
/**
* Cohorts steps definitions.
*
* @package core_cohort
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
/**
* Steps definitions for cohort actions.
*
* @package core_cohort
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_cohort extends behat_base {
/**
* Adds the user to the specified cohort. The user should be specified like "Firstname Lastname (user@example.com)".
*
* @Given /^I add "(?P<user_fullname_string>(?:[^"]|\\")*)" user to "(?P<cohort_idnumber_string>(?:[^"]|\\")*)" cohort members$/
* @param string $user
* @param string $cohortidnumber
*/
public function i_add_user_to_cohort_members($user, $cohortidnumber) {
// If we are not in the cohorts management we should move there before anything else.
$cohortsurl = new moodle_url('/cohort/index.php');
if (strpos($this->getSession()->getCurrentUrl(), $cohortsurl->out(false)) !== 0) {
// With JS enabled we should expand a few tree nodes.
$parentnodes = get_string('users', 'admin') . ' > ' .
get_string('accounts', 'admin');
$this->execute("behat_general::i_am_on_homepage");
$this->execute("behat_navigation::i_navigate_to_in_site_administration",
$parentnodes . ' > ' . get_string('cohorts', 'cohort')
);
}
$this->execute('behat_reportbuilder::i_press_action_in_the_report_row',
[get_string('assign', 'cohort'), $this->escape($cohortidnumber)]);
$this->execute("behat_forms::i_set_the_field_to",
array(get_string('potusers', 'cohort'), $this->escape($user))
);
$this->execute("behat_forms::press_button", get_string('add'));
$this->execute("behat_forms::press_button", get_string('backtocohorts', 'cohort'));
}
}
+39
View File
@@ -0,0 +1,39 @@
@core @core_cohort @core_customfield @javascript
Feature: Add and use cohort custom fields
In order to store an extra information about cohorts
As an admin
I need to create cohort customs fields and be able to populate them on cohort creation
Background:
Given the following "custom field categories" exist:
| name | component | area | itemid |
| Category for test | core_cohort | cohort | 0 |
Scenario: Create a new cohort custom field and use the field for a new cohort
When I log in as "admin"
And I navigate to "Users > Accounts > Cohort custom fields" in site administration
And I click on "Add a new custom field" "link"
And I click on "Short text" "link"
And I set the following fields to these values:
| Name | Test field |
| Short name | testfield |
And I click on "Save changes" "button" in the "Adding a new Short text" "dialogue"
Then the following should exist in the "generaltable" table:
| Custom field | Short name | Type |
| Test field | testfield | Short text |
And I navigate to "Users > Accounts > Cohorts" in site administration
And I follow "Add new cohort"
Then I should see "Category for test"
And I should see "Test field"
And I set the following fields to these values:
| Name | My new cohort |
| Context | System |
| Cohort ID | mynewcohort |
| Description | My new cohort description |
| Test field | Custom field text |
And I press "Save changes"
Then the following should exist in the "generaltable" table:
| Name | Cohort ID | Description |
| My new cohort | mynewcohort | My new cohort description |
And I press "Edit" action in the "My new cohort" report row
And the field "Test field" matches value "Custom field text"
@@ -0,0 +1,44 @@
@core @core_cohort @_file_upload
Feature: Upload users to a cohort
In order to quickly fill site-wide groups with users
As an admin
I need to upload a file with users data containing cohort assigns
@javascript @skip_chrome_zerosize
Scenario: Upload users and assign them to a course with cohort enrolment method enabled
Given the following "cohorts" exist:
| name | idnumber |
| Cohort 1 | ASD |
| Cohort 2 | DSA |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
| Course 2 | C2 | 0 |
And I log in as "admin"
And I add "Cohort sync" enrolment method in "Course 1" with:
| Cohort | Cohort 1 |
And I should see "Cohort sync (Cohort 1 - Student)"
And I add "Cohort sync" enrolment method in "Course 2" with:
| Cohort | Cohort 2 |
And I should see "Cohort sync (Cohort 2 - Student)"
When I navigate to "Users > Accounts > Upload users" in site administration
And I upload "lib/tests/fixtures/upload_users_cohorts.csv" file to "File" filemanager
And I press "Upload users"
And I press "Upload users"
And I press "Continue"
And I navigate to "Users > Accounts > Cohorts" in site administration
And I press "Assign" action in the "Cohort 1" report row
Then the "Current users" select box should contain "Tom Jones (tomjones@example.com)"
And the "Current users" select box should contain "Bob Jones (bobjones@example.com)"
And I press "Back to cohorts"
And I press "Assign" action in the "Cohort 2" report row
And the "Current users" select box should contain "Mary Smith (marysmith@example.com)"
And the "Current users" select box should contain "Alice Smith (alicesmith@example.com)"
And I am on the "Course 1" "enrolled users" page
And I should see "Tom Jones"
And I should see "Bob Jones"
And I should not see "Mary Smith"
And I am on the "Course 2" "enrolled users" page
And I should see "Mary Smith"
And I should see "Alice Smith"
And I should not see "Tom Jones"
+195
View File
@@ -0,0 +1,195 @@
@core @core_cohort @_file_upload
Feature: A privileged user can create cohorts using a CSV file
In order to create cohorts using a CSV file
As an admin
I need to be able to upload a CSV file and navigate through the upload process
Background:
Given the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
| Cat 2 | 0 | CAT2 |
| Cat 3 | CAT1 | CAT3 |
@javascript
Scenario: Upload cohorts with default System context as admin
When I log in as "admin"
And I navigate to "Users > Accounts >Cohorts" in site administration
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts1.csv" file to "File" filemanager
And I click on "Preview" "button"
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | visible | Status |
| cohort name 1 | cohortid1 | first description | System | 1 | |
| cohort name 2 | cohortid2 | | System | 1 | |
| cohort name 3 | cohortid3 | | Category 1 | 0 | |
| cohort name 4 | cohortid4 | | Cat 1 | 1 | |
| cohort name 5 | cohortid5 | | Cat 2 | 0 | |
| cohort name 6 | cohortid6 | | Cat 3 | 1 | |
And I press "Upload cohorts"
And I should see "Uploaded 6 cohorts"
And I press "Continue"
And the following should exist in the "reportbuilder-table" table:
| Name | Cohort ID | Description | Cohort size | Source |
| cohort name 1 | cohortid1 | first description | 0 | Created manually |
| cohort name 2 | cohortid2 | | 0 | Created manually |
And I follow "All cohorts"
And the following should exist in the "reportbuilder-table" table:
| Category | Name | Cohort ID | Description | Cohort size | Source |
| System | cohort name 1 | cohortid1 | first description | 0 | Created manually |
| System | cohort name 2 | cohortid2 | | 0 | Created manually |
| Category 1 | cohort name 3 | cohortid3 | | 0 | Created manually |
| Cat 1 | cohort name 4 | cohortid4 | | 0 | Created manually |
| Cat 2 | cohort name 5 | cohortid5 | | 0 | Created manually |
| Cat 3 | cohort name 6 | cohortid6 | | 0 | Created manually |
And ".text-muted" "css_element" should not exist in the "cohort name 1" "table_row"
And ".text-muted" "css_element" should not exist in the "cohort name 2" "table_row"
And ".text-muted" "css_element" should exist in the "cohort name 3" "table_row"
And the "class" attribute of "cohort name 3" "table_row" should contain "text-muted"
And ".text-muted" "css_element" should not exist in the "cohort name 4" "table_row"
And the "class" attribute of "cohort name 5" "table_row" should contain "text-muted"
And ".text-muted" "css_element" should not exist in the "cohort name 6" "table_row"
@javascript @_file_upload
Scenario: Upload cohorts with default category context as admin
When I log in as "admin"
And I navigate to "Users > Accounts >Cohorts" in site administration
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts1.csv" file to "File" filemanager
And I set the field "Default context" to "Cat 1 / Cat 3"
And I click on "Preview" "button"
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | Status |
| cohort name 1 | cohortid1 | first description | Cat 3 | |
| cohort name 2 | cohortid2 | | Cat 3 | |
| cohort name 3 | cohortid3 | | Category 1 | |
| cohort name 4 | cohortid4 | | Cat 1 | |
| cohort name 5 | cohortid5 | | Cat 2 | |
| cohort name 6 | cohortid6 | | Cat 3 | |
And I press "Upload cohorts"
And I should see "Uploaded 6 cohorts"
And I press "Continue"
And I should see "Cat 3"
And I navigate to "Users > Accounts >Cohorts" in site administration
And I follow "All cohorts"
And the following should exist in the "reportbuilder-table" table:
| Category | Name | Cohort ID | Description | Cohort size | Source |
| Cat 3 | cohort name 1 | cohortid1 | first description | 0 | Created manually |
| Cat 3 | cohort name 2 | cohortid2 | | 0 | Created manually |
| Category 1 | cohort name 3 | cohortid3 | | 0 | Created manually |
| Cat 1 | cohort name 4 | cohortid4 | | 0 | Created manually |
| Cat 2 | cohort name 5 | cohortid5 | | 0 | Created manually |
| Cat 3 | cohort name 6 | cohortid6 | | 0 | Created manually |
@javascript @_file_upload
Scenario: Upload cohorts with default category context as manager
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user1 | manager | Category | CAT1 |
When I log in as "user1"
And I am on course index
And I follow "Cat 1"
And I navigate to "Cohorts" in current page administration
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts1.csv" file to "File" filemanager
And I click on "Preview" "button"
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | Status |
| cohort name 1 | cohortid1 | first description | Cat 1 | |
| cohort name 2 | cohortid2 | | Cat 1 | |
| cohort name 3 | cohortid3 | | Cat 1 | Category Category 1 not found or you don't have permission to create a cohort there. The default context will be used. |
| cohort name 4 | cohortid4 | | Cat 1 | |
| cohort name 5 | cohortid5 | | Cat 1 | Category CAT2 not found or you don't have permission to create a cohort there. The default context will be used. |
| cohort name 6 | cohortid6 | | Cat 3 | |
And I press "Upload cohorts"
And I should see "Uploaded 6 cohorts"
@javascript @_file_upload
Scenario: Upload cohorts with conflicting id number
Given the following "cohorts" exist:
| name | idnumber |
| Cohort | cohortid2 |
When I log in as "admin"
And I navigate to "Users > Accounts >Cohorts" in site administration
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts1.csv" file to "File" filemanager
And I click on "Preview" "button"
Then I should see "Errors were found in CSV data. See details below."
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | Status |
| cohort name 1 | cohortid1 | first description | System | |
| cohort name 2 | cohortid2 | | System | Cohort with the same ID number already exists |
| cohort name 3 | cohortid3 | | Category 1 | |
| cohort name 4 | cohortid4 | | Cat 1 | |
| cohort name 5 | cohortid5 | | Cat 2 | |
| cohort name 6 | cohortid6 | | Cat 3 | |
And "Upload cohorts" "button" should not exist
@javascript @_file_upload
Scenario: Upload cohorts with different ways of specifying context
When I log in as "admin"
And I navigate to "Users > Accounts >Cohorts" in site administration
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts2.csv" file to "File" filemanager
And I click on "Preview" "button"
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | Status |
| Specify category as name | cohortid1 | | Category 1 | |
| Specify category as idnumber | cohortid2 | | Cat 1 | |
| Specify category as id | cohortid3 | | Category 1 | |
| Specify category as path | cohortid4 | | Cat 3 | |
| Specify category_id | cohortid5 | | Category 1 | |
| Specify category_idnumber | cohortid6 | | Cat 1 | |
| Specify category_path | cohortid7 | | Cat 3 | |
And I should not see "not found or you"
And I press "Upload cohorts"
And I should see "Uploaded 7 cohorts"
And I press "Continue"
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts3.csv" file to "File" filemanager
And I click on "Preview" "button"
And the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | Status |
| Specify context as id (system) | cohortid8 | | System | |
| Specify context as name (system) | cohortid9 | | System | |
| Specify context as category name only | cohortid10 | | Cat 1 | |
| Specify context as category path | cohortid12 | | Cat 3 | |
| Specify context as category idnumber | cohortid13 | | Cat 2 | |
And I should not see "not found or you"
And I press "Upload cohorts"
And I should see "Uploaded 5 cohorts"
@javascript @_file_upload
Scenario: Upload cohorts with theme
When I log in as "admin"
And I navigate to "Users > Accounts >Cohorts" in site administration
And I follow "Upload cohorts"
And I upload "cohort/tests/fixtures/uploadcohorts4.csv" file to "File" filemanager
And I click on "Preview" "button"
Then the following should exist in the "previewuploadedcohorts" table:
| name | idnumber | description | Context | visible | theme | Status |
| cohort name 1 | cohortid1 | first description | System | 1 | boost | |
| cohort name 2 | cohortid2 | | System | 1 | | |
| cohort name 3 | cohortid3 | | Category 1 | 0 | boost | |
| cohort name 4 | cohortid4 | | Cat 1 | 1 | classic | |
| cohort name 5 | cohortid5 | | Cat 2 | 0 | | |
| cohort name 6 | cohortid6 | | Cat 3 | 1 | classic | |
And I press "Upload cohorts"
And I should see "Uploaded 6 cohorts"
And I press "Continue"
And the following should exist in the "reportbuilder-table" table:
| Name | Cohort ID | Description | Cohort size | Source |
| cohort name 1 | cohortid1 | first description | 0 | Created manually |
| cohort name 2 | cohortid2 | | 0 | Created manually |
And I follow "All cohorts"
And the following should exist in the "reportbuilder-table" table:
| Category | Name | Cohort ID | Description | Cohort size | Source |
| System | cohort name 1 | cohortid1 | first description | 0 | Created manually |
| System | cohort name 2 | cohortid2 | | 0 | Created manually |
| Category 1 | cohort name 3 | cohortid3 | | 0 | Created manually |
| Cat 1 | cohort name 4 | cohortid4 | | 0 | Created manually |
| Cat 2 | cohort name 5 | cohortid5 | | 0 | Created manually |
| Cat 3 | cohort name 6 | cohortid6 | | 0 | Created manually |
+83
View File
@@ -0,0 +1,83 @@
@core @core_cohort
Feature: View cohort list
In order to operate with cohorts
As an admin or manager
I need to be able to view the list of cohorts in the system
Background:
Given the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
| Cat 2 | 0 | CAT2 |
| Cat 3 | CAT1 | CAT3 |
And the following "cohorts" exist:
| name | idnumber |
| System cohort | CH0 |
And the following "cohorts" exist:
| name | idnumber | contextlevel | reference |
| Cohort in category 1 | CH1 | Category | CAT1 |
| Cohort in category 2 | CH2 | Category | CAT2 |
| Cohort in category 3 | CH3 | Category | CAT3 |
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | First | User | first@example.com |
| user2 | Second | User | second@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user1 | manager | System | |
| user2 | manager | Category | CAT1 |
Scenario: Admin can see system cohorts and all cohorts
When I log in as "admin"
And I navigate to "Users > Accounts >Cohorts" in site administration
Then I should see "System cohort"
And I should not see "Cohort in category"
And I follow "All cohorts"
And I should see "System cohort"
And I should see "Cohort in category 1"
And I should see "Cohort in category 2"
And I should see "Cohort in category 3"
And I log out
Scenario: Manager can see system cohorts and all cohorts
When I log in as "user1"
And I navigate to "Users > Accounts >Cohorts" in site administration
Then I should see "System cohort"
And I should not see "Cohort in category"
And I follow "All cohorts"
And I should see "System cohort"
And I should see "Cohort in category 1"
And I should see "Cohort in category 2"
And I should see "Cohort in category 3"
And I log out
Scenario: Manager in category can see cohorts in the category
When I log in as "user2"
And I am on course index
And I follow "Cat 1"
And I follow "Cohorts"
And I should not see "All cohorts"
And I should not see "System cohort"
And I should see "Cohort in category 1"
And I should not see "Cohort in category 2"
And I should not see "Cohort in category 3"
And I log out
@javascript
Scenario: Cohorts list can be filtered
When I log in as "admin"
And I navigate to "Users > Accounts > Cohorts" in site administration
And I follow "All cohorts"
And I click on "Filters" "button"
And I set the following fields in the "Name" "core_reportbuilder > Filter" to these values:
| Name operator | Contains |
| Name value | category 1 |
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
Then the following should exist in the "reportbuilder-table" table:
| Category | Name |
| Cat 1 | Cohort in category 1 |
And the following should not exist in the "reportbuilder-table" table:
| Category | Name |
| Cat 2 | Cohort in category 2 |
| Cat 3 | Cohort in category 3 |
| System | System cohort |
@@ -0,0 +1,182 @@
<?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 core_cohort\customfield;
use advanced_testcase;
use context_system;
use context_coursecat;
use moodle_url;
use core_customfield\field_controller;
/**
* Unit tests for cohort custom field handler.
*
* @package core_cohort
* @covers \core_cohort\customfield\cohort_handler
* @copyright 2022 Dmitrii Metelkin <dmitriim@catalys-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cohort_handler_test extends advanced_testcase {
/**
* Test custom field handler.
* @var \core_customfield\handler
*/
protected $handler;
/**
* Setup.
*/
public function setUp(): void {
$this->handler = cohort_handler::create();
}
/**
* Create Cohort custom field for testing.
*
* @return field_controller
*/
protected function create_cohort_custom_field(): field_controller {
$fieldcategory = self::getDataGenerator()->create_custom_field_category([
'component' => 'core_cohort',
'area' => 'cohort',
]);
return self::getDataGenerator()->create_custom_field([
'shortname' => 'testfield1',
'type' => 'text',
'categoryid' => $fieldcategory->get('id'),
]);
}
/**
* Test configuration context.
*/
public function test_get_configuration_context(): void {
$this->assertInstanceOf(context_system::class, $this->handler->get_configuration_context());
}
/**
* Test getting config URL.
*/
public function test_get_configuration_url(): void {
$this->assertInstanceOf(moodle_url::class, $this->handler->get_configuration_url());
$this->assertEquals('/cohort/customfield.php', $this->handler->get_configuration_url()->out_as_local_url());
}
/**
* Test can configure check.
*/
public function test_can_configure(): void {
$this->resetAfterTest();
$user = self::getDataGenerator()->create_user();
self::setUser($user);
$this->assertFalse($this->handler->can_configure());
$roleid = self::getDataGenerator()->create_role();
assign_capability('moodle/cohort:configurecustomfields', CAP_ALLOW, $roleid, context_system::instance()->id, true);
role_assign($roleid, $user->id, context_system::instance()->id);
$this->assertTrue($this->handler->can_configure());
}
/**
* Test getting instance context.
*/
public function test_get_instance_context(): void {
$this->resetAfterTest();
$category = self::getDataGenerator()->create_category();
$catcontext = context_coursecat::instance($category->id);
$systemcontext = context_system::instance();
$cohortsystem = self::getDataGenerator()->create_cohort();
$cohortcategory = self::getDataGenerator()->create_cohort(['contextid' => $catcontext->id]);
$this->assertInstanceOf(context_system::class, $this->handler->get_instance_context($cohortsystem->id));
$this->assertSame($systemcontext, $this->handler->get_instance_context($cohortsystem->id));
$this->assertInstanceOf(context_coursecat::class, $this->handler->get_instance_context($cohortcategory->id));
$this->assertSame($catcontext, $this->handler->get_instance_context($cohortcategory->id));
}
/**
* Test can edit functionality.
*/
public function test_can_edit(): void {
$this->resetAfterTest();
$roleid = self::getDataGenerator()->create_role();
assign_capability('moodle/cohort:manage', CAP_ALLOW, $roleid, context_system::instance()->id, true);
$field = $this->create_cohort_custom_field();
$user = self::getDataGenerator()->create_user();
self::setUser($user);
$this->assertFalse($this->handler->can_edit($field, 0));
role_assign($roleid, $user->id, context_system::instance()->id);
$this->assertTrue($this->handler->can_edit($field, 0));
}
/**
* Test can view functionality.
*/
public function test_can_view(): void {
$this->resetAfterTest();
$manageroleid = self::getDataGenerator()->create_role();
assign_capability('moodle/cohort:manage', CAP_ALLOW, $manageroleid, context_system::instance()->id, true);
$viewroleid = self::getDataGenerator()->create_role();
assign_capability('moodle/cohort:view', CAP_ALLOW, $viewroleid, context_system::instance()->id, true);
$viewandmanageroleid = self::getDataGenerator()->create_role();
assign_capability('moodle/cohort:manage', CAP_ALLOW, $viewandmanageroleid, context_system::instance()->id, true);
assign_capability('moodle/cohort:view', CAP_ALLOW, $viewandmanageroleid, context_system::instance()->id, true);
$field = $this->create_cohort_custom_field();
$cohort = self::getDataGenerator()->create_cohort();
$user1 = self::getDataGenerator()->create_user();
$user2 = self::getDataGenerator()->create_user();
$user3 = self::getDataGenerator()->create_user();
self::setUser($user1);
$this->assertFalse($this->handler->can_view($field, $cohort->id));
self::setUser($user2);
$this->assertFalse($this->handler->can_view($field, $cohort->id));
self::setUser($user3);
$this->assertFalse($this->handler->can_view($field, $cohort->id));
role_assign($manageroleid, $user1->id, context_system::instance()->id);
role_assign($viewroleid, $user2->id, context_system::instance()->id);
role_assign($viewandmanageroleid, $user3->id, context_system::instance()->id);
self::setUser($user1);
$this->assertTrue($this->handler->can_view($field, $cohort->id));
self::setUser($user2);
$this->assertTrue($this->handler->can_view($field, $cohort->id));
self::setUser($user3);
$this->assertTrue($this->handler->can_view($field, $cohort->id));
}
}
+775
View File
@@ -0,0 +1,775 @@
<?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 core_cohort;
use core_cohort_external;
use core_external\external_api;
use externallib_advanced_testcase;
use core_cohort\customfield\cohort_handler;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/cohort/externallib.php');
/**
* External cohort API
*
* @package core_cohort
* @category external
* @copyright MediaTouch 2000 srl
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class externallib_test extends externallib_advanced_testcase {
/**
* Create cohort custom fields for testing.
*/
protected function create_custom_fields(): void {
$fieldcategory = self::getDataGenerator()->create_custom_field_category([
'component' => 'core_cohort',
'area' => 'cohort',
'name' => 'Other fields',
]);
self::getDataGenerator()->create_custom_field([
'shortname' => 'testfield1',
'name' => 'Custom field',
'type' => 'text',
'categoryid' => $fieldcategory->get('id'),
]);
self::getDataGenerator()->create_custom_field([
'shortname' => 'testfield2',
'name' => 'Custom field',
'type' => 'text',
'categoryid' => $fieldcategory->get('id'),
]);
}
/**
* Test create_cohorts
*/
public function test_create_cohorts(): void {
global $DB;
$this->resetAfterTest(true);
set_config('allowcohortthemes', 1);
$contextid = \context_system::instance()->id;
$category = $this->getDataGenerator()->create_category();
// Custom fields.
$this->create_custom_fields();
$cohort1 = array(
'categorytype' => array('type' => 'id', 'value' => $category->id),
'name' => 'cohort test 1',
'idnumber' => 'cohorttest1',
'description' => 'This is a description for cohorttest1',
'theme' => 'classic'
);
$cohort2 = array(
'categorytype' => array('type' => 'system', 'value' => ''),
'name' => 'cohort test 2',
'idnumber' => 'cohorttest2',
'description' => 'This is a description for cohorttest2',
'visible' => 0
);
$cohort3 = array(
'categorytype' => array('type' => 'id', 'value' => $category->id),
'name' => 'cohort test 3',
'idnumber' => 'cohorttest3',
'description' => 'This is a description for cohorttest3'
);
$roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid);
$cohort4 = array(
'categorytype' => array('type' => 'id', 'value' => $category->id),
'name' => 'cohort test 4',
'idnumber' => 'cohorttest4',
'description' => 'This is a description for cohorttest4',
'theme' => 'classic'
);
$cohort5 = array(
'categorytype' => array('type' => 'id', 'value' => $category->id),
'name' => 'cohort test 5 (with custom fields)',
'idnumber' => 'cohorttest5',
'description' => 'This is a description for cohorttest5',
'customfields' => array(
array(
'shortname' => 'testfield1',
'value' => 'Test value 1',
),
array(
'shortname' => 'testfield2',
'value' => 'Test value 2',
),
),
);
// Call the external function.
$this->setCurrentTimeStart();
$createdcohorts = core_cohort_external::create_cohorts(array($cohort1, $cohort2));
$createdcohorts = external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts);
// Check we retrieve the good total number of created cohorts + no error on capability.
$this->assertEquals(2, count($createdcohorts));
foreach ($createdcohorts as $createdcohort) {
$dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
if ($createdcohort['idnumber'] == $cohort1['idnumber']) {
$conid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'],
'contextlevel' => CONTEXT_COURSECAT));
$this->assertEquals($dbcohort->contextid, $conid);
$this->assertEquals($dbcohort->name, $cohort1['name']);
$this->assertEquals($dbcohort->description, $cohort1['description']);
$this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default.
// As $CFG->allowcohortthemes is enabled, theme must be initialised.
$this->assertEquals($dbcohort->theme, $cohort1['theme']);
} else if ($createdcohort['idnumber'] == $cohort2['idnumber']) {
$this->assertEquals($dbcohort->contextid, \context_system::instance()->id);
$this->assertEquals($dbcohort->name, $cohort2['name']);
$this->assertEquals($dbcohort->description, $cohort2['description']);
$this->assertEquals($dbcohort->visible, $cohort2['visible']);
// Although $CFG->allowcohortthemes is enabled, no theme is defined for this cohort.
$this->assertEquals($dbcohort->theme, '');
} else {
$this->fail('Unrecognised cohort found');
}
$this->assertTimeCurrent($dbcohort->timecreated);
$this->assertTimeCurrent($dbcohort->timemodified);
}
$createdcohorts = core_cohort_external::create_cohorts(array($cohort5));
$createdcohorts = external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts);
$this->assertCount(1, $createdcohorts);
$createdcohort = reset($createdcohorts);
$dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
$this->assertEquals($cohort5['name'], $dbcohort->name);
$this->assertEquals($cohort5['description'], $dbcohort->description);
$this->assertEquals(1, $dbcohort->visible);
$this->assertEquals('', $dbcohort->theme);
$data = cohort_handler::create()->export_instance_data_object($createdcohort['id'], true);
$this->assertEquals('Test value 1', $data->testfield1);
$this->assertEquals('Test value 2', $data->testfield2);
// Call when $CFG->allowcohortthemes is disabled.
set_config('allowcohortthemes', 0);
$createdcohorts = core_cohort_external::create_cohorts(array($cohort4));
$createdcohorts = external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts);
foreach ($createdcohorts as $createdcohort) {
$dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
if ($createdcohort['idnumber'] == $cohort4['idnumber']) {
$conid = $DB->get_field('context', 'id', array('instanceid' => $cohort4['categorytype']['value'],
'contextlevel' => CONTEXT_COURSECAT));
$this->assertEquals($dbcohort->contextid, $conid);
$this->assertEquals($dbcohort->name, $cohort4['name']);
$this->assertEquals($dbcohort->description, $cohort4['description']);
$this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default.
$this->assertEquals($dbcohort->theme, ''); // As $CFG->allowcohortthemes is disabled, theme must be empty.
}
}
// Call without required capability.
$this->unassignUserCapability('moodle/cohort:manage', $contextid, $roleid);
$this->expectException(\required_capability_exception::class);
$createdcohorts = core_cohort_external::create_cohorts(array($cohort3));
}
/**
* Test delete_cohorts
*/
public function test_delete_cohorts(): void {
global $USER, $CFG, $DB;
$this->resetAfterTest(true);
$cohort1 = self::getDataGenerator()->create_cohort();
$cohort2 = self::getDataGenerator()->create_cohort();
// Check the cohorts were correctly created.
$this->assertEquals(2, $DB->count_records_select('cohort', ' (id = :cohortid1 OR id = :cohortid2)',
array('cohortid1' => $cohort1->id, 'cohortid2' => $cohort2->id)));
$contextid = $cohort1->contextid;
$roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid);
// Call the external function.
core_cohort_external::delete_cohorts(array($cohort1->id, $cohort2->id));
// Check we retrieve no cohorts + no error on capability.
$this->assertEquals(0, $DB->count_records_select('cohort', ' (id = :cohortid1 OR id = :cohortid2)',
array('cohortid1' => $cohort1->id, 'cohortid2' => $cohort2->id)));
// Call without required capability.
$cohort1 = self::getDataGenerator()->create_cohort();
$cohort2 = self::getDataGenerator()->create_cohort();
$this->unassignUserCapability('moodle/cohort:manage', $contextid, $roleid);
$this->expectException(\required_capability_exception::class);
core_cohort_external::delete_cohorts(array($cohort1->id, $cohort2->id));
}
/**
* Test get_cohorts
*/
public function test_get_cohorts(): void {
$this->resetAfterTest(true);
// Custom fields.
$this->create_custom_fields();
set_config('allowcohortthemes', 1);
$cohort1 = array(
'contextid' => 1,
'name' => 'cohortnametest1',
'idnumber' => 'idnumbertest1',
'description' => 'This is a description for cohort 1',
'theme' => 'classic',
'customfield_testfield1' => 'Test value 1',
'customfield_testfield2' => 'Test value 2',
);
// We need a site admin to be able to populate cohorts custom fields.
$this->setAdminUser();
$cohort1 = self::getDataGenerator()->create_cohort($cohort1);
$cohort2 = self::getDataGenerator()->create_cohort();
$context = \context_system::instance();
$roleid = $this->assignUserCapability('moodle/cohort:view', $context->id);
// Call the external function.
$returnedcohorts = core_cohort_external::get_cohorts(array(
$cohort1->id, $cohort2->id));
$returnedcohorts = external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts);
// Check we retrieve the good total number of enrolled cohorts + no error on capability.
$this->assertEquals(2, count($returnedcohorts));
foreach ($returnedcohorts as $enrolledcohort) {
if ($enrolledcohort['idnumber'] == $cohort1->idnumber) {
$this->assertEquals($cohort1->name, $enrolledcohort['name']);
$this->assertEquals($cohort1->description, $enrolledcohort['description']);
$this->assertEquals($cohort1->visible, $enrolledcohort['visible']);
$this->assertEquals($cohort1->theme, $enrolledcohort['theme']);
$this->assertIsArray($enrolledcohort['customfields']);
$this->assertCount(2, $enrolledcohort['customfields']);
$actual = [];
foreach ($enrolledcohort['customfields'] as $customfield) {
$this->assertArrayHasKey('name', $customfield);
$this->assertArrayHasKey('shortname', $customfield);
$this->assertArrayHasKey('type', $customfield);
$this->assertArrayHasKey('valueraw', $customfield);
$this->assertArrayHasKey('value', $customfield);
$actual[$customfield['shortname']] = $customfield;
}
$this->assertEquals('Test value 1', $actual['testfield1']['value']);
$this->assertEquals('Test value 2', $actual['testfield2']['value']);
}
}
// Check that a user with cohort:manage can see the cohort.
$this->unassignUserCapability('moodle/cohort:view', $context->id, $roleid);
$roleid = $this->assignUserCapability('moodle/cohort:manage', $context->id, $roleid);
// Call the external function.
$returnedcohorts = core_cohort_external::get_cohorts(array(
$cohort1->id, $cohort2->id));
$returnedcohorts = external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts);
// Check we retrieve the good total number of enrolled cohorts + no error on capability.
$this->assertEquals(2, count($returnedcohorts));
// Check when allowcohortstheme is disabled, theme is not returned.
set_config('allowcohortthemes', 0);
$returnedcohorts = core_cohort_external::get_cohorts(array(
$cohort1->id));
$returnedcohorts = external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts);
foreach ($returnedcohorts as $enrolledcohort) {
if ($enrolledcohort['idnumber'] == $cohort1->idnumber) {
$this->assertNull($enrolledcohort['theme']);
}
}
}
/**
* Test update_cohorts
*/
public function test_update_cohorts(): void {
global $DB;
$this->resetAfterTest(true);
// Custom fields.
$this->create_custom_fields();
set_config('allowcohortthemes', 0);
$cohort1 = self::getDataGenerator()->create_cohort(array('visible' => 0));
$data = cohort_handler::create()->export_instance_data_object($cohort1->id, true);
$this->assertNull($data->testfield1);
$this->assertNull($data->testfield2);
$cohort1 = array(
'id' => $cohort1->id,
'categorytype' => array('type' => 'id', 'value' => '1'),
'name' => 'cohortnametest1',
'idnumber' => 'idnumbertest1',
'description' => 'This is a description for cohort 1',
'theme' => 'classic',
'customfields' => array(
array(
'shortname' => 'testfield1',
'value' => 'Test value 1',
),
array(
'shortname' => 'testfield2',
'value' => 'Test value 2',
),
),
);
$context = \context_system::instance();
$roleid = $this->assignUserCapability('moodle/cohort:manage', $context->id);
// Call the external function.
core_cohort_external::update_cohorts(array($cohort1));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$contextid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'],
'contextlevel' => CONTEXT_COURSECAT));
$this->assertEquals($dbcohort->contextid, $contextid);
$this->assertEquals($dbcohort->name, $cohort1['name']);
$this->assertEquals($dbcohort->idnumber, $cohort1['idnumber']);
$this->assertEquals($dbcohort->description, $cohort1['description']);
$this->assertEquals($dbcohort->visible, 0);
$this->assertEmpty($dbcohort->theme);
$data = cohort_handler::create()->export_instance_data_object($cohort1['id'], true);
$this->assertEquals('Test value 1', $data->testfield1);
$this->assertEquals('Test value 2', $data->testfield2);
// Since field 'visible' was added in 2.8, make sure that update works correctly with and without this parameter.
core_cohort_external::update_cohorts(array($cohort1 + array('visible' => 1)));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$this->assertEquals(1, $dbcohort->visible);
core_cohort_external::update_cohorts(array($cohort1));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$this->assertEquals(1, $dbcohort->visible);
// Call when $CFG->allowcohortthemes is enabled.
set_config('allowcohortthemes', 1);
core_cohort_external::update_cohorts(array($cohort1 + array('theme' => 'classic')));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$this->assertEquals('classic', $dbcohort->theme);
// Call when $CFG->allowcohortthemes is disabled.
set_config('allowcohortthemes', 0);
core_cohort_external::update_cohorts(array($cohort1 + array('theme' => 'boost')));
$dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
$this->assertEquals('classic', $dbcohort->theme);
// Updating custom fields.
$cohort1['customfields'] = array(
array(
'shortname' => 'testfield1',
'value' => 'Test value 1 updated',
),
array(
'shortname' => 'testfield2',
'value' => 'Test value 2 updated',
),
);
core_cohort_external::update_cohorts(array($cohort1));
$data = cohort_handler::create()->export_instance_data_object($cohort1['id'], true);
$this->assertEquals('Test value 1 updated', $data->testfield1);
$this->assertEquals('Test value 2 updated', $data->testfield2);
// Call without required capability.
$this->unassignUserCapability('moodle/cohort:manage', $context->id, $roleid);
$this->expectException(\required_capability_exception::class);
core_cohort_external::update_cohorts(array($cohort1));
}
/**
* Verify handling of 'id' param.
*/
public function test_update_cohorts_invalid_id_param(): void {
$this->resetAfterTest(true);
$cohort = self::getDataGenerator()->create_cohort();
$cohort1 = array(
'id' => 'THIS IS NOT AN ID',
'name' => 'Changed cohort name',
'categorytype' => array('type' => 'id', 'value' => '1'),
'idnumber' => $cohort->idnumber,
);
try {
core_cohort_external::update_cohorts(array($cohort1));
$this->fail('Expecting invalid_parameter_exception exception, none occured');
} catch (\invalid_parameter_exception $e1) {
$this->assertStringContainsString('Invalid external api parameter: the value is "THIS IS NOT AN ID"', $e1->debuginfo);
}
$cohort1['id'] = 9.999; // Also not a valid id of a cohort.
try {
core_cohort_external::update_cohorts(array($cohort1));
$this->fail('Expecting invalid_parameter_exception exception, none occured');
} catch (\invalid_parameter_exception $e2) {
$this->assertStringContainsString('Invalid external api parameter: the value is "9.999"', $e2->debuginfo);
}
}
/**
* Test update_cohorts without permission on the dest category.
*/
public function test_update_cohorts_missing_dest(): void {
global $USER, $CFG, $DB;
$this->resetAfterTest(true);
$category1 = self::getDataGenerator()->create_category(array(
'name' => 'Test category 1'
));
$category2 = self::getDataGenerator()->create_category(array(
'name' => 'Test category 2'
));
$context1 = \context_coursecat::instance($category1->id);
$context2 = \context_coursecat::instance($category2->id);
$cohort = array(
'contextid' => $context1->id,
'name' => 'cohortnametest1',
'idnumber' => 'idnumbertest1',
'description' => 'This is a description for cohort 1'
);
$cohort1 = self::getDataGenerator()->create_cohort($cohort);
$roleid = $this->assignUserCapability('moodle/cohort:manage', $context1->id);
$cohortupdate = array(
'id' => $cohort1->id,
'categorytype' => array('type' => 'id', 'value' => $category2->id),
'name' => 'cohort update',
'idnumber' => 'idnumber update',
'description' => 'This is a description update'
);
// Call the external function.
// Should fail because we don't have permission on the dest category
$this->expectException(\required_capability_exception::class);
core_cohort_external::update_cohorts(array($cohortupdate));
}
/**
* Test update_cohorts without permission on the src category.
*/
public function test_update_cohorts_missing_src(): void {
global $USER, $CFG, $DB;
$this->resetAfterTest(true);
$category1 = self::getDataGenerator()->create_category(array(
'name' => 'Test category 1'
));
$category2 = self::getDataGenerator()->create_category(array(
'name' => 'Test category 2'
));
$context1 = \context_coursecat::instance($category1->id);
$context2 = \context_coursecat::instance($category2->id);
$cohort = array(
'contextid' => $context1->id,
'name' => 'cohortnametest1',
'idnumber' => 'idnumbertest1',
'description' => 'This is a description for cohort 1'
);
$cohort1 = self::getDataGenerator()->create_cohort($cohort);
$roleid = $this->assignUserCapability('moodle/cohort:manage', $context2->id);
$cohortupdate = array(
'id' => $cohort1->id,
'categorytype' => array('type' => 'id', 'value' => $category2->id),
'name' => 'cohort update',
'idnumber' => 'idnumber update',
'description' => 'This is a description update'
);
// Call the external function.
// Should fail because we don't have permission on the src category
$this->expectException(\required_capability_exception::class);
core_cohort_external::update_cohorts(array($cohortupdate));
}
/**
* Test add_cohort_members
*/
public function test_add_cohort_members(): void {
global $DB;
$this->resetAfterTest(true); // Reset all changes automatically after this test.
$contextid = \context_system::instance()->id;
$cohort = array(
'contextid' => $contextid,
'name' => 'cohortnametest1',
'idnumber' => 'idnumbertest1',
'description' => 'This is a description for cohort 1'
);
$cohort0 = self::getDataGenerator()->create_cohort($cohort);
// Check the cohorts were correctly created.
$this->assertEquals(1, $DB->count_records_select('cohort', ' (id = :cohortid0)',
array('cohortid0' => $cohort0->id)));
$cohort1 = array(
'cohorttype' => array('type' => 'id', 'value' => $cohort0->id),
'usertype' => array('type' => 'id', 'value' => '1')
);
$roleid = $this->assignUserCapability('moodle/cohort:assign', $contextid);
// Call the external function.
$addcohortmembers = core_cohort_external::add_cohort_members(array($cohort1));
$addcohortmembers = external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $addcohortmembers);
// Check we retrieve the good total number of created cohorts + no error on capability.
$this->assertEquals(1, count($addcohortmembers));
foreach ($addcohortmembers as $addcohortmember) {
$dbcohort = $DB->get_record('cohort_members', array('cohortid' => $cohort0->id));
$this->assertEquals($dbcohort->cohortid, $cohort1['cohorttype']['value']);
$this->assertEquals($dbcohort->userid, $cohort1['usertype']['value']);
}
// Call without required capability.
$cohort2 = array(
'cohorttype' => array('type' => 'id', 'value' => $cohort0->id),
'usertype' => array('type' => 'id', 'value' => '2')
);
$this->unassignUserCapability('moodle/cohort:assign', $contextid, $roleid);
$this->expectException(\required_capability_exception::class);
$addcohortmembers = core_cohort_external::add_cohort_members(array($cohort2));
}
/**
* Test delete_cohort_members
*/
public function test_delete_cohort_members(): void {
global $DB;
$this->resetAfterTest(true); // Reset all changes automatically after this test.
$cohort1 = self::getDataGenerator()->create_cohort();
$user1 = self::getDataGenerator()->create_user();
$cohort2 = self::getDataGenerator()->create_cohort();
$user2 = self::getDataGenerator()->create_user();
$context = \context_system::instance();
$roleid = $this->assignUserCapability('moodle/cohort:assign', $context->id);
$cohortaddmember1 = array(
'cohorttype' => array('type' => 'id', 'value' => $cohort1->id),
'usertype' => array('type' => 'id', 'value' => $user1->id)
);
$cohortmembers1 = core_cohort_external::add_cohort_members(array($cohortaddmember1));
$cohortmembers1 = external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $cohortmembers1);
$cohortaddmember2 = array(
'cohorttype' => array('type' => 'id', 'value' => $cohort2->id),
'usertype' => array('type' => 'id', 'value' => $user2->id)
);
$cohortmembers2 = core_cohort_external::add_cohort_members(array($cohortaddmember2));
$cohortmembers2 = external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $cohortmembers2);
// Check we retrieve no cohorts + no error on capability.
$this->assertEquals(2, $DB->count_records_select('cohort_members', ' ((cohortid = :idcohort1 AND userid = :iduser1)
OR (cohortid = :idcohort2 AND userid = :iduser2))',
array('idcohort1' => $cohort1->id, 'iduser1' => $user1->id, 'idcohort2' => $cohort2->id, 'iduser2' => $user2->id)));
// Call the external function.
$cohortdel1 = array(
'cohortid' => $cohort1->id,
'userid' => $user1->id
);
$cohortdel2 = array(
'cohortid' => $cohort2->id,
'userid' => $user2->id
);
core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2));
// Check we retrieve no cohorts + no error on capability.
$this->assertEquals(0, $DB->count_records_select('cohort_members', ' ((cohortid = :idcohort1 AND userid = :iduser1)
OR (cohortid = :idcohort2 AND userid = :iduser2))',
array('idcohort1' => $cohort1->id, 'iduser1' => $user1->id, 'idcohort2' => $cohort2->id, 'iduser2' => $user2->id)));
// Call without required capability.
$this->unassignUserCapability('moodle/cohort:assign', $context->id, $roleid);
$this->expectException(\required_capability_exception::class);
core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2));
}
/**
* Search cohorts.
*/
public function test_search_cohorts(): void {
global $DB, $CFG;
$this->resetAfterTest(true);
$this->create_custom_fields();
$creator = $this->getDataGenerator()->create_user();
$user = $this->getDataGenerator()->create_user();
$catuser = $this->getDataGenerator()->create_user();
$catcreator = $this->getDataGenerator()->create_user();
$courseuser = $this->getDataGenerator()->create_user();
$category = $this->getDataGenerator()->create_category();
$othercategory = $this->getDataGenerator()->create_category();
$course = $this->getDataGenerator()->create_course();
$syscontext = \context_system::instance();
$catcontext = \context_coursecat::instance($category->id);
$coursecontext = \context_course::instance($course->id);
// Fetching default authenticated user role.
$authrole = $DB->get_record('role', array('id' => $CFG->defaultuserroleid));
// Reset all default authenticated users permissions.
unassign_capability('moodle/cohort:manage', $authrole->id);
// Creating specific roles.
$creatorrole = create_role('Creator role', 'creatorrole', 'creator role description');
$userrole = create_role('User role', 'userrole', 'user role description');
$courserole = create_role('Course user role', 'courserole', 'course user role description');
assign_capability('moodle/cohort:manage', CAP_ALLOW, $creatorrole, $syscontext->id);
assign_capability('moodle/cohort:view', CAP_ALLOW, $courserole, $syscontext->id);
// Check for parameter $includes = 'parents'.
role_assign($creatorrole, $creator->id, $syscontext->id);
role_assign($creatorrole, $catcreator->id, $catcontext->id);
role_assign($userrole, $user->id, $syscontext->id);
role_assign($userrole, $catuser->id, $catcontext->id);
// Enrol user in the course.
$this->getDataGenerator()->enrol_user($courseuser->id, $course->id, 'courserole');
$syscontext = array('contextid' => \context_system::instance()->id);
$catcontext = array('contextid' => \context_coursecat::instance($category->id)->id);
$othercatcontext = array('contextid' => \context_coursecat::instance($othercategory->id)->id);
$coursecontext = array('contextid' => \context_course::instance($course->id)->id);
$customfields = array(
'contextid' => \context_system::instance()->id,
'customfield_testfield1' => 'Test value 1',
'customfield_testfield2' => 'Test value 2',
);
// We need a site admin to be able to populate cohorts custom fields.
$this->setAdminUser();
$cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1')));
$cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2')));
$cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3')));
$cohort4 = $this->getDataGenerator()->create_cohort(array_merge($customfields, array('name' => 'Cohortsearch 4')));
// A user without permission in the system.
$this->setUser($user);
try {
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
$this->fail('Invalid permissions in system');
} catch (\required_capability_exception $e) {
// All good.
}
// A user without permission in a category.
$this->setUser($catuser);
try {
$result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
$this->fail('Invalid permissions in category');
} catch (\required_capability_exception $e) {
// All good.
}
// A user with permissions in the system.
$this->setUser($creator);
$result = core_cohort_external::search_cohorts("Cohortsearch 4", $syscontext, 'parents');
$this->assertCount(1, $result['cohorts']);
$this->assertEquals('Cohortsearch 4', $result['cohorts'][$cohort4->id]->name);
// A user with permissions in the system, searching category context.
$result = core_cohort_external::search_cohorts("Cohortsearch 4", $catcontext, 'parents');
$this->assertCount(1, $result['cohorts']);
$this->assertEquals('Cohortsearch 4', $result['cohorts'][$cohort4->id]->name);
$this->assertEqualsCanonicalizing([
'Test value 1',
'Test value 2',
], array_column($result['cohorts'][$cohort4->id]->customfields, 'value'));
$actual = [];
foreach ($result['cohorts'][$cohort4->id]->customfields as $customfield) {
$this->assertArrayHasKey('name', $customfield);
$this->assertArrayHasKey('shortname', $customfield);
$this->assertArrayHasKey('type', $customfield);
$this->assertArrayHasKey('valueraw', $customfield);
$this->assertArrayHasKey('value', $customfield);
$actual[$customfield['shortname']] = $customfield;
}
// A user with permissions in the category.
$this->setUser($catcreator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
$this->assertCount(3, $result['cohorts']);
$cohorts = array();
foreach ($result['cohorts'] as $cohort) {
$cohorts[] = $cohort->name;
}
$this->assertTrue(in_array('Cohortsearch 1', $cohorts));
// Check for parameter $includes = 'self'.
$this->setUser($creator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $othercatcontext, 'self');
$this->assertCount(1, $result['cohorts']);
$this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name);
// Check for parameter $includes = 'all'.
$this->setUser($creator);
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'all');
$this->assertCount(4, $result['cohorts']);
// A user in the course context with the system cohort:view capability. Check that all the system cohorts are returned.
$this->setUser($courseuser);
$result = core_cohort_external::search_cohorts("Cohortsearch", $coursecontext, 'all');
$this->assertCount(2, $result['cohorts']);
$this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
// Detect invalid parameter $includes.
$this->setUser($creator);
try {
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'invalid');
$this->fail('Invalid parameter includes');
} catch (\coding_exception $e) {
// All good.
}
}
}
+7
View File
@@ -0,0 +1,7 @@
name,idnumber,description,category,visible
cohort name 1,cohortid1,first description,,
cohort name 2,cohortid2,,,
cohort name 3,cohortid3,,Category 1,no
cohort name 4,cohortid4,,CAT1,yes
cohort name 5,cohortid5,,CAT2,0
cohort name 6,cohortid6,,CAT3,1
1 name idnumber description category visible
2 cohort name 1 cohortid1 first description
3 cohort name 2 cohortid2
4 cohort name 3 cohortid3 Category 1 no
5 cohort name 4 cohortid4 CAT1 yes
6 cohort name 5 cohortid5 CAT2 0
7 cohort name 6 cohortid6 CAT3 1
+8
View File
@@ -0,0 +1,8 @@
name,idnumber,description,category,category_id,category_idnumber,category_path
Specify category as name,cohortid1,,Category 1,,,
Specify category as idnumber,cohortid2,,CAT1,,,
Specify category as id,cohortid3,,1,,,
Specify category as path,cohortid4,,Cat 1 / Cat 3,,,
Specify category_id,cohortid5,,,1,,
Specify category_idnumber,cohortid6,,,,CAT1,
Specify category_path,cohortid7,,,,,Cat 1 / Cat 3
1 name idnumber description category category_id category_idnumber category_path
2 Specify category as name cohortid1 Category 1
3 Specify category as idnumber cohortid2 CAT1
4 Specify category as id cohortid3 1
5 Specify category as path cohortid4 Cat 1 / Cat 3
6 Specify category_id cohortid5 1
7 Specify category_idnumber cohortid6 CAT1
8 Specify category_path cohortid7 Cat 1 / Cat 3
+6
View File
@@ -0,0 +1,6 @@
name,idnumber,description,context
Specify context as id (system),cohortid8,,1
Specify context as name (system),cohortid9,,System
Specify context as category name only,cohortid10,,Cat 1
Specify context as category path,cohortid12,,Cat 1 / Cat 3
Specify context as category idnumber,cohortid13,,CAT2
1 name idnumber description context
2 Specify context as id (system) cohortid8 1
3 Specify context as name (system) cohortid9 System
4 Specify context as category name only cohortid10 Cat 1
5 Specify context as category path cohortid12 Cat 1 / Cat 3
6 Specify context as category idnumber cohortid13 CAT2
+7
View File
@@ -0,0 +1,7 @@
name,idnumber,description,category,visible,theme
cohort name 1,cohortid1,first description,,,boost
cohort name 2,cohortid2,,,,
cohort name 3,cohortid3,,Category 1,no,boost
cohort name 4,cohortid4,,CAT1,yes,classic
cohort name 5,cohortid5,,CAT2,0,
cohort name 6,cohortid6,,CAT3,1,classic
1 name idnumber description category visible theme
2 cohort name 1 cohortid1 first description boost
3 cohort name 2 cohortid2
4 cohort name 3 cohortid3 Category 1 no boost
5 cohort name 4 cohortid4 CAT1 yes classic
6 cohort name 5 cohortid5 CAT2 0
7 cohort name 6 cohortid6 CAT3 1 classic
+13
View File
@@ -0,0 +1,13 @@
name,idnumber,description,category
cohort name 1,cid1,first description,
cohort name 2,cid2,,
cohort name 3,cid3,,Category 1
cohort name 4,cid4,,CAT1
cohort name 5,cid5,,CAT2
cohort name 6,cid6,,CAT3
cohort name 7,cid7,,CAT1
cohort name 8,cid8,,CAT2
cohort name 9,cid9,,CAT3
cohort name 10,cid10,,CAT1
cohort name 11,cid11,,CAT2
cohort name 12,cid1,,CAT3
1 name idnumber description category
2 cohort name 1 cid1 first description
3 cohort name 2 cid2
4 cohort name 3 cid3 Category 1
5 cohort name 4 cid4 CAT1
6 cohort name 5 cid5 CAT2
7 cohort name 6 cid6 CAT3
8 cohort name 7 cid7 CAT1
9 cohort name 8 cid8 CAT2
10 cohort name 9 cid9 CAT3
11 cohort name 10 cid10 CAT1
12 cohort name 11 cid11 CAT2
13 cohort name 12 cid1 CAT3
+973
View File
@@ -0,0 +1,973 @@
<?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 core_cohort;
use core_cohort\customfield\cohort_handler;
use core_customfield\data_controller;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once("$CFG->dirroot/cohort/lib.php");
/**
* Cohort library tests.
*
* @package core_cohort
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class lib_test extends \advanced_testcase {
/**
* Create Cohort custom field for testing.
*
* @return \core_customfield\field_controller
*/
protected function create_cohort_custom_field(): \core_customfield\field_controller {
$fieldcategory = self::getDataGenerator()->create_custom_field_category([
'component' => 'core_cohort',
'area' => 'cohort',
'name' => 'Other fields',
]);
return self::getDataGenerator()->create_custom_field([
'shortname' => 'testfield1',
'name' => 'Custom field',
'type' => 'text',
'categoryid' => $fieldcategory->get('id'),
]);
}
public function test_cohort_add_cohort(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$this->create_cohort_custom_field();
$cohort = new \stdClass();
$cohort->contextid = \context_system::instance()->id;
$cohort->name = 'test cohort';
$cohort->idnumber = 'testid';
$cohort->description = 'test cohort desc';
$cohort->descriptionformat = FORMAT_HTML;
$cohort->customfield_testfield1 = 'Test value 1';
$id = cohort_add_cohort($cohort);
$this->assertNotEmpty($id);
$newcohort = $DB->get_record('cohort', array('id'=>$id));
$this->assertEquals($cohort->contextid, $newcohort->contextid);
$this->assertSame($cohort->name, $newcohort->name);
$this->assertSame($cohort->description, $newcohort->description);
$this->assertEquals($cohort->descriptionformat, $newcohort->descriptionformat);
$this->assertNotEmpty($newcohort->timecreated);
$this->assertSame($newcohort->component, '');
$this->assertSame($newcohort->theme, '');
$this->assertSame($newcohort->timecreated, $newcohort->timemodified);
$handler = cohort_handler::create();
$customfieldsdata = $handler->export_instance_data_object($id);
$this->assertEquals('Test value 1', $customfieldsdata->testfield1);
}
public function test_cohort_add_cohort_missing_name(): void {
$cohort = new \stdClass();
$cohort->contextid = \context_system::instance()->id;
$cohort->name = null;
$cohort->idnumber = 'testid';
$cohort->description = 'test cohort desc';
$cohort->descriptionformat = FORMAT_HTML;
$this->expectException(\coding_exception::class);
$this->expectExceptionMessage('Missing cohort name in cohort_add_cohort()');
cohort_add_cohort($cohort);
}
public function test_cohort_add_cohort_event(): void {
$this->resetAfterTest();
// Setup cohort data structure.
$cohort = new \stdClass();
$cohort->contextid = \context_system::instance()->id;
$cohort->name = 'test cohort';
$cohort->idnumber = 'testid';
$cohort->description = 'test cohort desc';
$cohort->descriptionformat = FORMAT_HTML;
// Catch Events.
$sink = $this->redirectEvents();
// Perform the add operation.
$id = cohort_add_cohort($cohort);
// Capture the event.
$events = $sink->get_events();
$sink->close();
// Validate the event.
$this->assertCount(1, $events);
$event = $events[0];
$this->assertInstanceOf('\core\event\cohort_created', $event);
$this->assertEquals('cohort', $event->objecttable);
$this->assertEquals($id, $event->objectid);
$this->assertEquals($cohort->contextid, $event->contextid);
$url = new \moodle_url('/cohort/index.php', array('contextid' => $event->contextid));
$this->assertEquals($url, $event->get_url());
$this->assertEquals($cohort, $event->get_record_snapshot('cohort', $id));
$this->assertEventContextNotUsed($event);
}
public function test_cohort_update_cohort(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$this->create_cohort_custom_field();
$cohort = new \stdClass();
$cohort->contextid = \context_system::instance()->id;
$cohort->name = 'test cohort';
$cohort->idnumber = 'testid';
$cohort->description = 'test cohort desc';
$cohort->descriptionformat = FORMAT_HTML;
$cohort->customfield_testfield1 = 'Test value 1';
$id = cohort_add_cohort($cohort);
$this->assertNotEmpty($id);
$DB->set_field('cohort', 'timecreated', $cohort->timecreated - 10, array('id'=>$id));
$DB->set_field('cohort', 'timemodified', $cohort->timemodified - 10, array('id'=>$id));
$cohort = $DB->get_record('cohort', array('id'=>$id));
$cohort->name = 'test cohort 2';
$cohort->customfield_testfield1 = 'Test value updated';
cohort_update_cohort($cohort);
$newcohort = $DB->get_record('cohort', array('id'=>$id));
$this->assertSame($cohort->contextid, $newcohort->contextid);
$this->assertSame($cohort->name, $newcohort->name);
$this->assertSame($cohort->description, $newcohort->description);
$this->assertSame($cohort->descriptionformat, $newcohort->descriptionformat);
$this->assertSame($cohort->timecreated, $newcohort->timecreated);
$this->assertSame($cohort->component, $newcohort->component);
$this->assertSame($newcohort->theme, '');
$this->assertGreaterThan($newcohort->timecreated, $newcohort->timemodified);
$this->assertLessThanOrEqual(time(), $newcohort->timemodified);
$handler = cohort_handler::create();
$customfieldsdata = $handler->export_instance_data_object($id);
$this->assertEquals('Test value updated', $customfieldsdata->testfield1);
}
public function test_cohort_update_cohort_event(): void {
global $DB;
$this->resetAfterTest();
// Setup the cohort data structure.
$cohort = new \stdClass();
$cohort->contextid = \context_system::instance()->id;
$cohort->name = 'test cohort';
$cohort->idnumber = 'testid';
$cohort->description = 'test cohort desc';
$cohort->descriptionformat = FORMAT_HTML;
$cohort->theme = '';
$id = cohort_add_cohort($cohort);
$this->assertNotEmpty($id);
$cohort->name = 'test cohort 2';
// Catch Events.
$sink = $this->redirectEvents();
// Peform the update.
cohort_update_cohort($cohort);
// Add again theme property to the cohort object for comparing it to the event snapshop.
$cohort->theme = '';
$events = $sink->get_events();
$sink->close();
// Validate the event.
$this->assertCount(1, $events);
$event = $events[0];
$updatedcohort = $DB->get_record('cohort', array('id'=>$id));
$this->assertInstanceOf('\core\event\cohort_updated', $event);
$this->assertEquals('cohort', $event->objecttable);
$this->assertEquals($updatedcohort->id, $event->objectid);
$this->assertEquals($updatedcohort->contextid, $event->contextid);
$url = new \moodle_url('/cohort/edit.php', array('id' => $event->objectid));
$this->assertEquals($url, $event->get_url());
$this->assertEquals($cohort, $event->get_record_snapshot('cohort', $id));
$this->assertEventContextNotUsed($event);
}
public function test_cohort_delete_cohort(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$field = $this->create_cohort_custom_field();
$cohort = $this->getDataGenerator()->create_cohort(['customfield_testfield1' => 'Test value 1']);
$this->assertTrue($DB->record_exists('customfield_data', ['instanceid' => $cohort->id, 'fieldid' => $field->get('id')]));
cohort_delete_cohort($cohort);
$this->assertFalse($DB->record_exists('cohort', array('id'=>$cohort->id)));
$this->assertFalse($DB->record_exists('customfield_data', ['instanceid' => $cohort->id, 'fieldid' => $field->get('id')]));
}
public function test_cohort_delete_cohort_event(): void {
$this->resetAfterTest();
$cohort = $this->getDataGenerator()->create_cohort();
// Capture the events.
$sink = $this->redirectEvents();
// Perform the delete.
cohort_delete_cohort($cohort);
$events = $sink->get_events();
$sink->close();
// Validate the event structure.
$this->assertCount(1, $events);
$event = $events[0];
$this->assertInstanceOf('\core\event\cohort_deleted', $event);
$this->assertEquals('cohort', $event->objecttable);
$this->assertEquals($cohort->id, $event->objectid);
$url = new \moodle_url('/cohort/index.php', array('contextid' => $event->contextid));
$this->assertEquals($url, $event->get_url());
$this->assertEquals($cohort, $event->get_record_snapshot('cohort', $cohort->id));
$this->assertEventContextNotUsed($event);
}
public function test_cohort_delete_category(): void {
global $DB;
$this->resetAfterTest();
$category = $this->getDataGenerator()->create_category();
$cohort = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category->id)->id));
cohort_delete_category($category);
$this->assertTrue($DB->record_exists('cohort', array('id'=>$cohort->id)));
$newcohort = $DB->get_record('cohort', array('id'=>$cohort->id));
$this->assertEquals(\context_system::instance()->id, $newcohort->contextid);
}
public function test_cohort_add_member(): void {
global $DB;
$this->resetAfterTest();
$cohort = $this->getDataGenerator()->create_cohort();
$user = $this->getDataGenerator()->create_user();
$this->assertFalse($DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$user->id)));
cohort_add_member($cohort->id, $user->id);
$this->assertTrue($DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$user->id)));
}
public function test_cohort_add_member_event(): void {
global $USER;
$this->resetAfterTest();
// Setup the data.
$cohort = $this->getDataGenerator()->create_cohort();
$user = $this->getDataGenerator()->create_user();
// Capture the events.
$sink = $this->redirectEvents();
// Peform the add member operation.
cohort_add_member($cohort->id, $user->id);
$events = $sink->get_events();
$sink->close();
// Validate the event.
$this->assertCount(1, $events);
$event = $events[0];
$this->assertInstanceOf('\core\event\cohort_member_added', $event);
$this->assertEquals('cohort', $event->objecttable);
$this->assertEquals($cohort->id, $event->objectid);
$this->assertEquals($user->id, $event->relateduserid);
$this->assertEquals($USER->id, $event->userid);
$url = new \moodle_url('/cohort/assign.php', array('id' => $event->objectid));
$this->assertEquals($url, $event->get_url());
$this->assertEventContextNotUsed($event);
}
public function test_cohort_remove_member(): void {
global $DB;
$this->resetAfterTest();
$cohort = $this->getDataGenerator()->create_cohort();
$user = $this->getDataGenerator()->create_user();
cohort_add_member($cohort->id, $user->id);
$this->assertTrue($DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$user->id)));
cohort_remove_member($cohort->id, $user->id);
$this->assertFalse($DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$user->id)));
}
public function test_cohort_remove_member_event(): void {
global $USER;
$this->resetAfterTest();
// Setup the data.
$cohort = $this->getDataGenerator()->create_cohort();
$user = $this->getDataGenerator()->create_user();
cohort_add_member($cohort->id, $user->id);
// Capture the events.
$sink = $this->redirectEvents();
// Peform the remove operation.
cohort_remove_member($cohort->id, $user->id);
$events = $sink->get_events();
$sink->close();
// Validate the event.
$this->assertCount(1, $events);
$event = $events[0];
$this->assertInstanceOf('\core\event\cohort_member_removed', $event);
$this->assertEquals('cohort', $event->objecttable);
$this->assertEquals($cohort->id, $event->objectid);
$this->assertEquals($user->id, $event->relateduserid);
$this->assertEquals($USER->id, $event->userid);
$url = new \moodle_url('/cohort/assign.php', array('id' => $event->objectid));
$this->assertEquals($url, $event->get_url());
$this->assertEventContextNotUsed($event);
}
public function test_cohort_is_member(): void {
global $DB;
$this->resetAfterTest();
$cohort = $this->getDataGenerator()->create_cohort();
$user = $this->getDataGenerator()->create_user();
$this->assertFalse(cohort_is_member($cohort->id, $user->id));
cohort_add_member($cohort->id, $user->id);
$this->assertTrue(cohort_is_member($cohort->id, $user->id));
}
public function test_cohort_get_cohorts(): void {
global $DB;
$this->resetAfterTest();
$category1 = $this->getDataGenerator()->create_category();
$category2 = $this->getDataGenerator()->create_category();
$cohort1 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category1->id)->id, 'name'=>'aaagrrryyy', 'idnumber'=>'','description'=>''));
$cohort2 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category1->id)->id, 'name'=>'bbb', 'idnumber'=>'', 'description'=>'yyybrrr'));
$cohort3 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category1->id)->id, 'name'=>'ccc', 'idnumber'=>'xxarrrghyyy', 'description'=>'po_us'));
$cohort4 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_system::instance()->id));
$result = cohort_get_cohorts(\context_coursecat::instance($category2->id)->id);
$this->assertEquals(0, $result['totalcohorts']);
$this->assertEquals(0, count($result['cohorts']));
$this->assertEquals(0, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id);
$this->assertEquals(3, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1, $cohort2->id=>$cohort2, $cohort3->id=>$cohort3), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 0, 100, 'arrrgh');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort3->id=>$cohort3), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 0, 100, 'brrr');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort2->id=>$cohort2), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 0, 100, 'grrr');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 1, 1, 'yyy');
$this->assertEquals(3, $result['totalcohorts']);
$this->assertEquals(array($cohort2->id=>$cohort2), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 0, 100, 'po_us');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort3->id=>$cohort3), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 0, 100, 'pokus');
$this->assertEquals(0, $result['totalcohorts']);
$this->assertEquals(array(), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_system::instance()->id);
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort4->id=>$cohort4), $result['cohorts']);
$this->assertEquals(1, $result['allcohorts']);
}
public function test_cohort_get_all_cohorts(): void {
global $DB;
$this->resetAfterTest();
$category1 = $this->getDataGenerator()->create_category();
$category2 = $this->getDataGenerator()->create_category();
$cohort1 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category1->id)->id, 'name'=>'aaagrrryyy', 'idnumber'=>'','description'=>''));
$cohort2 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category1->id)->id, 'name'=>'bbb', 'idnumber'=>'', 'description'=>'yyybrrr'));
$cohort3 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_coursecat::instance($category2->id)->id, 'name'=>'ccc', 'idnumber'=>'xxarrrghyyy', 'description'=>'po_us'));
$cohort4 = $this->getDataGenerator()->create_cohort(array('contextid'=>\context_system::instance()->id));
// Get list of all cohorts as admin.
$this->setAdminUser();
$result = cohort_get_all_cohorts(0, 100, '');
$this->assertEquals(4, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1, $cohort2->id=>$cohort2, $cohort3->id=>$cohort3, $cohort4->id=>$cohort4), $result['cohorts']);
$this->assertEquals(4, $result['allcohorts']);
$result = cohort_get_all_cohorts(0, 100, 'grrr');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1), $result['cohorts']);
$this->assertEquals(4, $result['allcohorts']);
// Get list of all cohorts as manager who has capability everywhere.
$user = $this->getDataGenerator()->create_user();
$managerrole = $DB->get_record('role', array('shortname' => 'manager'));
role_assign($managerrole->id, $user->id, \context_system::instance()->id);
$this->setUser($user);
$result = cohort_get_all_cohorts(0, 100, '');
$this->assertEquals(4, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1, $cohort2->id=>$cohort2, $cohort3->id=>$cohort3, $cohort4->id=>$cohort4), $result['cohorts']);
$this->assertEquals(4, $result['allcohorts']);
$result = cohort_get_all_cohorts(0, 100, 'grrr');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1), $result['cohorts']);
$this->assertEquals(4, $result['allcohorts']);
// Get list of all cohorts as manager who has capability everywhere except category2.
$context2 = \context_coursecat::instance($category2->id);
role_change_permission($managerrole->id, $context2, 'moodle/cohort:view', CAP_PROHIBIT);
role_change_permission($managerrole->id, $context2, 'moodle/cohort:manage', CAP_PROHIBIT);
$this->assertFalse(has_any_capability(array('moodle/cohort:view', 'moodle/cohort:manage'), $context2));
$result = cohort_get_all_cohorts(0, 100, '');
$this->assertEquals(3, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1, $cohort2->id=>$cohort2, $cohort4->id=>$cohort4), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_all_cohorts(0, 100, 'grrr');
$this->assertEquals(1, $result['totalcohorts']);
$this->assertEquals(array($cohort1->id=>$cohort1), $result['cohorts']);
$this->assertEquals(3, $result['allcohorts']);
$result = cohort_get_cohorts(\context_coursecat::instance($category1->id)->id, 1, 1, 'yyy');
$this->assertEquals(2, $result['totalcohorts']);
$this->assertEquals(array($cohort2->id=>$cohort2), $result['cohorts']);
$this->assertEquals(2, $result['allcohorts']);
}
public function test_cohort_get_available_cohorts(): void {
global $DB;
$this->resetAfterTest();
$category1 = $this->getDataGenerator()->create_category();
$category2 = $this->getDataGenerator()->create_category();
$course1 = $this->getDataGenerator()->create_course(array('category' => $category1->id));
$course2 = $this->getDataGenerator()->create_course(array('category' => $category2->id));
$category1ctx = \context_coursecat::instance($category1->id);
$category2ctx = \context_coursecat::instance($category2->id);
$course1ctx = \context_course::instance(($course1->id));
$course2ctx = \context_course::instance(($course2->id));
$systemctx = \context_system::instance();
$cohort1 = $this->getDataGenerator()->create_cohort(array('contextid'=>$category1ctx->id, 'name'=>'aaagrrryyy', 'idnumber'=>'','description'=>''));
$cohort2 = $this->getDataGenerator()->create_cohort(array('contextid'=>$category1ctx->id, 'name'=>'bbb', 'idnumber'=>'', 'description'=>'yyybrrr', 'visible'=>0));
$cohort3 = $this->getDataGenerator()->create_cohort(array('contextid'=>$category2ctx->id, 'name'=>'ccc', 'idnumber'=>'xxarrrghyyy', 'description'=>'po_us'));
$cohort4 = $this->getDataGenerator()->create_cohort(array('contextid'=>$systemctx->id, 'name' => 'ddd'));
$cohort5 = $this->getDataGenerator()->create_cohort(array('contextid'=>$systemctx->id, 'visible'=>0, 'name' => 'eee'));
/*
Structure of generated course categories, courses and cohort:
system
-cohort4 (visible, has 3 members)
-cohort5 (not visible, no members)
category1
-cohort1 (visible, no members)
-cohort2 (not visible, has 1 member)
course1
category2
-cohort3 (visible, has 2 member)
course2
In this test we call cohort_get_available_cohorts() for users with different roles
and with different paramteres ($withmembers, $search, $offset, $limit) to make sure we go
through all possible options of SQL query.
*/
// Admin can see visible and invisible cohorts defined in above contexts.
$this->setAdminUser();
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort1->id, $cohort2->id, $cohort4->id, $cohort5->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 2, '');
$this->assertEquals(array($cohort1->id, $cohort2->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 1, 2, '');
$this->assertEquals(array($cohort2->id, $cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 100, 'yyy');
$this->assertEquals(array($cohort1->id, $cohort2->id), array_keys($result));
$result = cohort_get_available_cohorts($course2ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id, $cohort5->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY);
$this->assertEmpty($result);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_MEMBERS_ONLY);
$this->assertEmpty($result);
// Get list of available cohorts as a teacher in the course.
$user1 = $this->getDataGenerator()->create_user();
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
role_assign($teacherrole->id, $user1->id, $course1ctx->id);
role_assign($teacherrole->id, $user1->id, $course2ctx->id);
$this->setUser($user1);
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort1->id, $cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 1, '');
$this->assertEquals(array($cohort1->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 1, 1, '');
$this->assertEquals(array($cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 100, 'yyy');
$this->assertEquals(array($cohort1->id), array_keys($result));
$result = cohort_get_available_cohorts($course2ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY);
$this->assertEmpty($result);
// Now add members to cohorts.
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$user5 = $this->getDataGenerator()->create_user();
$user6 = $this->getDataGenerator()->create_user();
cohort_add_member($cohort2->id, $user3->id);
cohort_add_member($cohort3->id, $user2->id);
cohort_add_member($cohort3->id, $user3->id);
cohort_add_member($cohort4->id, $user4->id);
cohort_add_member($cohort4->id, $user5->id);
cohort_add_member($cohort4->id, $user6->id);
// Check filtering non-empty cohorts as admin.
$this->setAdminUser();
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort2->id, $cohort4->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$this->assertEquals(2, $result[$cohort3->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, 'yyy');
$this->assertEquals(array($cohort2->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
// Check filtering non-empty cohorts as teacher.
$this->setUser($user1);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort4->id), array_keys($result));
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$this->assertEquals(2, $result[$cohort3->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_MEMBERS_ONLY, 0, 0, 'yyy');
$this->assertEmpty($result);
// Enrol users.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user2->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user3->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user5->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user6->id, $course1->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user3->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user4->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user5->id, $course2->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($user6->id, $course2->id, $studentrole->id);
// Check cohorts with enrolments as admin.
$this->setAdminUser();
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort2->id, $cohort4->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->enrolledcnt);
$this->assertEquals(2, $result[$cohort4->id]->enrolledcnt);
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course2ctx, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort3->id, $cohort4->id), array_keys($result));
$this->assertEquals(1, $result[$cohort3->id]->enrolledcnt);
$this->assertEquals(3, $result[$cohort4->id]->enrolledcnt);
$this->assertEquals(2, $result[$cohort3->id]->memberscnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0, 'yyy');
$this->assertEquals(array($cohort2->id), array_keys($result));
$this->assertEquals(1, $result[$cohort2->id]->enrolledcnt);
$this->assertEquals(1, $result[$cohort2->id]->memberscnt);
$result = cohort_get_available_cohorts($course1ctx, COHORT_WITH_NOTENROLLED_MEMBERS_ONLY, 0, 0, '');
$this->assertEquals(array($cohort4->id), array_keys($result));
$this->assertEquals(2, $result[$cohort4->id]->enrolledcnt);
$this->assertEquals(3, $result[$cohort4->id]->memberscnt);
// Assign user1 additional 'manager' role in the category context. He can now see hidden cohort in category1
// but still can not see hidden category in system.
$managerrole = $DB->get_record('role', array('shortname' => 'manager'));
role_assign($managerrole->id, $user1->id, \context_coursecat::instance($category1->id));
$this->setUser($user1);
$result = cohort_get_available_cohorts($course1ctx, COHORT_ALL, 0, 0, '');
$this->assertEquals(array($cohort1->id, $cohort2->id, $cohort4->id), array_keys($result));
}
/**
* Test that all get functions return custom fields data.
*
* @covers \cohort_get_cohort, \cohort_get_cohorts, \cohort_get_all_cohorts
* @covers \cohort_get_available_cohorts, \cohort_get_user_cohorts
*/
public function test_get_functions_return_custom_fields(): void {
$this->resetAfterTest();
$this->setAdminUser();
$user = self::getDataGenerator()->create_user();
$course = self::getDataGenerator()->create_course();
$coursectx = \context_course::instance(($course->id));
$this->create_cohort_custom_field();
$cohort1 = $this->getDataGenerator()->create_cohort(['customfield_testfield1' => 'Test value 1']);
$cohort2 = $this->getDataGenerator()->create_cohort();
// Test cohort_get_cohort.
$result = cohort_get_cohort($cohort1->id, $coursectx, true);
$this->assertObjectHasProperty('customfields', $result);
$this->assertCount(1, $result->customfields);
$field = reset($result->customfields);
$this->assertInstanceOf(data_controller::class, $field);
$this->assertEquals('testfield1', $field->get_field()->get('shortname'));
$this->assertEquals('Test value 1', $field->get_value());
// Test custom fields are not returned if not needed.
$result = cohort_get_cohort($cohort1->id, $coursectx);
$this->assertObjectNotHasProperty('customfields', $result);
// Test cohort_get_cohorts.
$result = cohort_get_cohorts(\context_system::instance()->id, 0, 25, '', true);
$this->assertEquals(2, $result['totalcohorts']);
$this->assertEquals(2, $result['allcohorts']);
foreach ($result['cohorts'] as $cohort) {
$this->assertObjectHasProperty('customfields', $cohort);
$this->assertCount(1, $cohort->customfields);
$field = reset($cohort->customfields);
$this->assertInstanceOf(data_controller::class, $field);
$this->assertEquals('testfield1', $field->get_field()->get('shortname'));
if ($cohort->id == $cohort1->id ) {
$this->assertEquals('Test value 1', $field->get_value());
} else {
$this->assertEquals('', $field->get_value());
}
}
// Test custom fields are not returned if not needed.
$result = cohort_get_cohorts(\context_system::instance()->id, 0, 25, '');
$this->assertEquals(2, $result['totalcohorts']);
$this->assertEquals(2, $result['allcohorts']);
foreach ($result['cohorts'] as $cohort) {
$this->assertObjectNotHasProperty('customfields', $cohort);
}
// Test test_cohort_get_all_cohorts.
$result = cohort_get_all_cohorts(0, 100, '', true);
$this->assertEquals(2, $result['totalcohorts']);
$this->assertEquals(2, $result['allcohorts']);
foreach ($result['cohorts'] as $cohort) {
$this->assertObjectHasProperty('customfields', $cohort);
$this->assertCount(1, $cohort->customfields);
$field = reset($cohort->customfields);
$this->assertInstanceOf(data_controller::class, $field);
$this->assertEquals('testfield1', $field->get_field()->get('shortname'));
if ($cohort->id == $cohort1->id ) {
$this->assertEquals('Test value 1', $field->get_value());
} else {
$this->assertEquals('', $field->get_value());
}
}
// Test custom fields are not returned if not needed.
$result = cohort_get_all_cohorts(0, 100, '');
$this->assertEquals(2, $result['totalcohorts']);
$this->assertEquals(2, $result['allcohorts']);
foreach ($result['cohorts'] as $cohort) {
$this->assertObjectNotHasProperty('customfields', $cohort);
}
// Test cohort_get_available_cohorts.
$result = cohort_get_available_cohorts($coursectx, COHORT_ALL, 0, 25, '', true);
$this->assertCount(2, $result);
foreach ($result as $cohort) {
$this->assertObjectHasProperty('customfields', $cohort);
$this->assertCount(1, $cohort->customfields);
$field = reset($cohort->customfields);
$this->assertInstanceOf(data_controller::class, $field);
$this->assertEquals('testfield1', $field->get_field()->get('shortname'));
if ($cohort->id == $cohort1->id ) {
$this->assertEquals('Test value 1', $field->get_value());
} else {
$this->assertEquals('', $field->get_value());
}
}
// Test custom fields are not returned if not needed.
$result = cohort_get_available_cohorts($coursectx, COHORT_ALL, 0, 25, '');
$this->assertCount(2, $result);
foreach ($result as $cohort) {
$this->assertObjectNotHasProperty('customfields', $cohort);
}
// Test cohort_get_user_cohorts.
cohort_add_member($cohort1->id, $user->id);
cohort_add_member($cohort2->id, $user->id);
$result = cohort_get_user_cohorts($user->id, true);
$this->assertCount(2, $result);
foreach ($result as $cohort) {
$this->assertObjectHasProperty('customfields', $cohort);
$this->assertCount(1, $cohort->customfields);
$field = reset($cohort->customfields);
$this->assertInstanceOf(data_controller::class, $field);
$this->assertEquals('testfield1', $field->get_field()->get('shortname'));
if ($cohort->id == $cohort1->id ) {
$this->assertEquals('Test value 1', $field->get_value());
} else {
$this->assertEquals('', $field->get_value());
}
}
// Test that there is no custom fields returned if not required.
$result = cohort_get_user_cohorts($user->id);
$this->assertCount(2, $result);
foreach ($result as $cohort) {
$this->assertObjectNotHasProperty('customfields', $cohort);
}
}
/**
* Create a cohort with allowcohortthemes enabled/disabled.
*/
public function test_cohort_add_theme_cohort(): void {
global $DB;
$this->resetAfterTest();
// Theme is added when allowcohortthemes is enabled.
set_config('allowcohortthemes', 1);
set_config('theme', 'boost');
$systemctx = \context_system::instance();
$cohort1 = $this->getDataGenerator()->create_cohort(array('contextid' => $systemctx->id, 'name' => 'test cohort 1',
'idnumber' => 'testid1', 'description' => 'test cohort desc', 'descriptionformat' => FORMAT_HTML, 'theme' => 'classic'));
$id = cohort_add_cohort($cohort1);
$this->assertNotEmpty($id);
$newcohort = $DB->get_record('cohort', array('id' => $id));
$this->assertEquals($cohort1->contextid, $newcohort->contextid);
$this->assertSame($cohort1->name, $newcohort->name);
$this->assertSame($cohort1->description, $newcohort->description);
$this->assertEquals($cohort1->descriptionformat, $newcohort->descriptionformat);
$this->assertNotEmpty($newcohort->theme);
$this->assertSame($cohort1->theme, $newcohort->theme);
$this->assertNotEmpty($newcohort->timecreated);
$this->assertSame($newcohort->component, '');
$this->assertSame($newcohort->timecreated, $newcohort->timemodified);
// Theme is not added when allowcohortthemes is disabled.
set_config('allowcohortthemes', 0);
$cohort2 = $this->getDataGenerator()->create_cohort(array('contextid' => $systemctx->id, 'name' => 'test cohort 2',
'idnumber' => 'testid2', 'description' => 'test cohort desc', 'descriptionformat' => FORMAT_HTML, 'theme' => 'classic'));
$id = cohort_add_cohort($cohort2);
$this->assertNotEmpty($id);
$newcohort = $DB->get_record('cohort', array('id' => $id));
$this->assertSame($cohort2->name, $newcohort->name);
$this->assertEmpty($newcohort->theme);
}
/**
* Update a cohort with allowcohortthemes enabled/disabled.
*/
public function test_cohort_update_theme_cohort(): void {
global $DB;
$this->resetAfterTest();
// Enable cohort themes.
set_config('allowcohortthemes', 1);
set_config('theme', 'boost');
$systemctx = \context_system::instance();
$cohort1 = $this->getDataGenerator()->create_cohort(array('contextid' => $systemctx->id, 'name' => 'test cohort 1',
'idnumber' => 'testid1', 'description' => 'test cohort desc', 'descriptionformat' => FORMAT_HTML, 'theme' => 'classic'));
$id = cohort_add_cohort($cohort1);
$this->assertNotEmpty($id);
// Theme is updated when allowcohortthemes is enabled.
$cohort1 = $DB->get_record('cohort', array('id' => $id));
$cohort1->name = 'test cohort 1 updated';
$cohort1->theme = 'classic';
cohort_update_cohort($cohort1);
$updatedcohort = $DB->get_record('cohort', array('id' => $id));
$this->assertEquals($cohort1->contextid, $updatedcohort->contextid);
$this->assertSame($cohort1->name, $updatedcohort->name);
$this->assertSame($cohort1->description, $updatedcohort->description);
$this->assertNotEmpty($updatedcohort->theme);
$this->assertSame($cohort1->theme, $updatedcohort->theme);
// Theme is not updated neither overwritten when allowcohortthemes is disabled.
set_config('allowcohortthemes', 0);
$cohort2 = $DB->get_record('cohort', array('id' => $id));
$cohort2->theme = 'classic';
cohort_update_cohort($cohort2);
$updatedcohort = $DB->get_record('cohort', array('id' => $id));
$this->assertEquals($cohort2->contextid, $updatedcohort->contextid);
$this->assertNotEmpty($updatedcohort->theme);
$this->assertSame($cohort1->theme, $updatedcohort->theme);
}
/**
* Test that lib function returns custom field data for a cohorts.
*
* @covers \cohort_get_custom_fields_data
*/
public function test_cohort_get_custom_fields_data(): void {
$this->resetAfterTest();
$this->setAdminUser();
$this->create_cohort_custom_field();
$cohort1 = $this->getDataGenerator()->create_cohort(['customfield_testfield1' => 'Test value 1']);
$cohort2 = $this->getDataGenerator()->create_cohort();
$result = cohort_get_custom_fields_data([$cohort1->id, $cohort2->id, 777]);
$this->assertArrayHasKey($cohort1->id, $result);
$this->assertArrayHasKey($cohort2->id, $result);
$this->assertArrayHasKey(777, $result);
foreach ($result as $cohortid => $fieldcontrollers) {
foreach ($fieldcontrollers as $fieldcontroller) {
$this->assertInstanceOf(data_controller::class, $fieldcontroller);
if ($cohortid == $cohort1->id) {
$this->assertSame('Test value 1', $fieldcontroller->export_value());
} else {
$this->assertNull($fieldcontroller->export_value());
}
}
}
}
/**
* Test the behaviour of cohort_get_cohort().
*
* @covers ::cohort_get_cohort
*/
public function test_cohort_get_cohort(): void {
$this->resetAfterTest();
$cat = $this->getDataGenerator()->create_category();
$cat1 = $this->getDataGenerator()->create_category(['parent' => $cat->id]);
$cat2 = $this->getDataGenerator()->create_category(['parent' => $cat->id]);
$course1 = $this->getDataGenerator()->create_course(['category' => $cat1->id, 'shortname' => 'ANON1']);
$course2 = $this->getDataGenerator()->create_course(['category' => $cat2->id, 'shortname' => 'ANON2']);
$cohort1 = $this->getDataGenerator()->create_cohort(['contextid' => \context_coursecat::instance($cat1->id)->id]);
$result = cohort_get_cohort($cohort1->id, \context_course::instance($course2->id));
$this->assertFalse($result);
$result = cohort_get_cohort($cohort1->id, \context_course::instance($course2->id), true);
$this->assertFalse($result);
$result = cohort_get_cohort($cohort1->id, \context_course::instance($course1->id));
$this->assertEquals($cohort1->id, $result->id);
$result = cohort_get_cohort($cohort1->id, \context_course::instance($course1->id), true);
$this->assertEquals($cohort1->id, $result->id);
}
}
+343
View File
@@ -0,0 +1,343 @@
<?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 core_cohort.
*
* @package core_cohort
* @category test
* @copyright 2018 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_cohort\privacy;
defined('MOODLE_INTERNAL') || die();
use core_cohort\privacy\provider;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\writer;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\approved_userlist;
/**
* Unit tests for cohort\classes\privacy\provider.php
*
* @copyright 2018 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends provider_testcase {
/**
* Basic setup for these tests.
*/
public function setUp(): void {
$this->resetAfterTest(true);
}
/**
* Test getting the context for the user ID related to this plugin.
*/
public function test_get_contexts_for_userid(): void {
// Create system cohort and category cohort.
$coursecategory = $this->getDataGenerator()->create_category();
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
$systemctx = \context_system::instance();
$categorycohort = $this->getDataGenerator()->create_cohort([
'contextid' => $coursecategoryctx->id,
'name' => 'Category cohort 1',
]);
$systemcohort = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 1'
]);
// Create user and add to the system and category cohorts.
$user = $this->getDataGenerator()->create_user();
cohort_add_member($categorycohort->id, $user->id);
cohort_add_member($systemcohort->id, $user->id);
// User is member of 2 cohorts.
$contextlist = provider::get_contexts_for_userid($user->id);
$this->assertCount(2, (array) $contextlist->get_contextids());
$this->assertContainsEquals($coursecategoryctx->id, $contextlist->get_contextids());
$this->assertContainsEquals($systemctx->id, $contextlist->get_contextids());
}
/**
* Test that data is exported correctly for this plugin.
*/
public function test_export_user_data(): void {
// Create system cohort and category cohort.
$coursecategory = $this->getDataGenerator()->create_category();
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
$systemctx = \context_system::instance();
$categorycohort = $this->getDataGenerator()->create_cohort([
'contextid' => $coursecategoryctx->id,
'name' => 'Category cohort 1',
]);
$systemcohort1 = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 1'
]);
$systemcohort2 = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 2'
]);
// Create user and add to the system and category cohorts.
$user = $this->getDataGenerator()->create_user();
cohort_add_member($categorycohort->id, $user->id);
cohort_add_member($systemcohort1->id, $user->id);
cohort_add_member($systemcohort2->id, $user->id);
// Validate system cohort exported data.
$writer = writer::with_context($systemctx);
$this->assertFalse($writer->has_any_data());
$this->export_context_data_for_user($user->id, $systemctx, 'core_cohort');
$data = $writer->get_related_data([], 'cohort');
$this->assertCount(2, $data);
// Validate category cohort exported data.
$writer = writer::with_context($coursecategoryctx);
$this->assertFalse($writer->has_any_data());
$this->export_context_data_for_user($user->id, $coursecategoryctx, 'core_cohort');
$data = $writer->get_related_data([], 'cohort');
$this->assertCount(1, $data);
$this->assertEquals($categorycohort->name, reset($data)->name);
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
// Create system cohort and category cohort.
$coursecategory = $this->getDataGenerator()->create_category();
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
$systemctx = \context_system::instance();
$categorycohort = $this->getDataGenerator()->create_cohort([
'contextid' => $coursecategoryctx->id,
'name' => 'Category cohort 1',
'idnumber' => '',
'description' => ''
]);
$systemcohort = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 1'
]);
// Create user and add to the system and category cohorts.
$user = $this->getDataGenerator()->create_user();
cohort_add_member($categorycohort->id, $user->id);
cohort_add_member($systemcohort->id, $user->id);
// Before deletion, we should have 2 entries in the cohort_members table.
$count = $DB->count_records('cohort_members');
$this->assertEquals(2, $count);
// Delete data based on system context.
provider::delete_data_for_all_users_in_context($systemctx);
// After deletion, the cohort_members entries should have been deleted.
$count = $DB->count_records('cohort_members');
$this->assertEquals(1, $count);
// Delete data based on category context.
provider::delete_data_for_all_users_in_context($coursecategoryctx);
// After deletion, the cohort_members entries should have been deleted.
$count = $DB->count_records('cohort_members');
$this->assertEquals(0, $count);
}
/**
* Test for provider::delete_data_for_user().
*/
public function test_delete_data_for_user(): void {
global $DB;
// Create system cohort and category cohort.
$coursecategory = $this->getDataGenerator()->create_category();
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
$systemctx = \context_system::instance();
$categorycohort = $this->getDataGenerator()->create_cohort([
'contextid' => $coursecategoryctx->id,
'name' => 'Category cohort 1',
'idnumber' => '',
'description' => ''
]);
$systemcohort = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 1'
]);
// Create user and add to the system and category cohorts.
$user1 = $this->getDataGenerator()->create_user();
cohort_add_member($categorycohort->id, $user1->id);
cohort_add_member($systemcohort->id, $user1->id);
// Create another user and add to the system and category cohorts.
$user2 = $this->getDataGenerator()->create_user();
cohort_add_member($categorycohort->id, $user2->id);
cohort_add_member($systemcohort->id, $user2->id);
// Create another user and add to the system cohort.
$user3 = $this->getDataGenerator()->create_user();
cohort_add_member($systemcohort->id, $user3->id);
// Before deletion, we should have 5 entries in the cohort_members table.
$count = $DB->count_records('cohort_members');
$this->assertEquals(5, $count);
$contextlist = provider::get_contexts_for_userid($user1->id);
$contexts = [];
$contexts[] = \context_user::instance($user1->id)->id;
$contexts = array_merge($contexts, $contextlist->get_contextids());
$approvedcontextlist = new approved_contextlist($user1, 'cohort', $contexts);
provider::delete_data_for_user($approvedcontextlist);
// After deletion, the cohort_members entries for the first student should have been deleted.
$count = $DB->count_records('cohort_members', ['userid' => $user1->id]);
$this->assertEquals(0, $count);
$count = $DB->count_records('cohort_members');
$this->assertEquals(3, $count);
// Confirm that the cohorts hasn't been removed.
$cohortscount = $DB->get_records('cohort');
$this->assertCount(2, (array) $cohortscount);
}
/**
* Test that only users within a course context are fetched.
*/
public function test_get_users_in_context(): void {
$component = 'core_cohort';
// Create system cohort and category cohort.
$coursecategory = $this->getDataGenerator()->create_category();
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
$systemctx = \context_system::instance();
$categorycohort = $this->getDataGenerator()->create_cohort([
'contextid' => $coursecategoryctx->id,
'name' => 'Category cohort 1',
]);
// Create user.
$user = $this->getDataGenerator()->create_user();
$userctx = \context_user::instance($user->id);
$userlist1 = new \core_privacy\local\request\userlist($coursecategoryctx, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(0, $userlist1);
$userlist2 = new \core_privacy\local\request\userlist($systemctx, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(0, $userlist2);
$systemcohort = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 1'
]);
// Create user and add to the system and category cohorts.
cohort_add_member($categorycohort->id, $user->id);
cohort_add_member($systemcohort->id, $user->id);
// The list of users within the coursecat context should contain user.
$userlist1 = new \core_privacy\local\request\userlist($coursecategoryctx, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(1, $userlist1);
$expected = [$user->id];
$actual = $userlist1->get_userids();
$this->assertEquals($expected, $actual);
// The list of users within the system context should contain user.
$userlist2 = new \core_privacy\local\request\userlist($systemctx, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
$expected = [$user->id];
$actual = $userlist2->get_userids();
$this->assertEquals($expected, $actual);
// The list of users within the user context should be empty.
$userlist3 = new \core_privacy\local\request\userlist($userctx, $component);
provider::get_users_in_context($userlist3);
$this->assertCount(0, $userlist3);
}
/**
* Test that data for users in approved userlist is deleted.
*/
public function test_delete_data_for_users(): void {
$component = 'core_cohort';
// Create system cohort and category cohort.
$coursecategory = $this->getDataGenerator()->create_category();
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
$systemctx = \context_system::instance();
$categorycohort = $this->getDataGenerator()->create_cohort([
'contextid' => $coursecategoryctx->id,
'name' => 'Category cohort 1',
]);
// Create user1.
$user1 = $this->getDataGenerator()->create_user();
$userctx1 = \context_user::instance($user1->id);
// Create user2.
$user2 = $this->getDataGenerator()->create_user();
$systemcohort = $this->getDataGenerator()->create_cohort([
'contextid' => $systemctx->id,
'name' => 'System cohort 1'
]);
// Create user and add to the system and category cohorts.
cohort_add_member($categorycohort->id, $user1->id);
cohort_add_member($systemcohort->id, $user1->id);
cohort_add_member($categorycohort->id, $user2->id);
$userlist1 = new \core_privacy\local\request\userlist($coursecategoryctx, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(2, $userlist1);
$userlist2 = new \core_privacy\local\request\userlist($systemctx, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
// Convert $userlist1 into an approved_contextlist.
$approvedlist1 = new approved_userlist($coursecategoryctx, $component, $userlist1->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist1);
// Re-fetch users in coursecategoryctx.
$userlist1 = new \core_privacy\local\request\userlist($coursecategoryctx, $component);
provider::get_users_in_context($userlist1);
// The user data in coursecategoryctx should be deleted.
$this->assertCount(0, $userlist1);
// Re-fetch users in coursecategoryctx.
$userlist2 = new \core_privacy\local\request\userlist($systemctx, $component);
provider::get_users_in_context($userlist2);
// The user data in coursecontext2 should be still present.
$this->assertCount(1, $userlist2);
// Convert $userlist2 into an approved_contextlist in the user context.
$approvedlist3 = new approved_userlist($userctx1, $component, $userlist2->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist3);
// Re-fetch users in coursecontext1.
$userlist3 = new \core_privacy\local\request\userlist($systemctx, $component);
provider::get_users_in_context($userlist3);
// The user data in systemcontext should not be deleted.
$this->assertCount(1, $userlist3);
}
}
@@ -0,0 +1,193 @@
<?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/>.
declare(strict_types=1);
namespace core_cohort\reportbuilder\audience;
use advanced_testcase;
use context;
use core_reportbuilder_generator;
use core_user\reportbuilder\datasource\users;
/**
* Unit tests for cohort member report audience type
*
* @package core_reportbuilder
* @covers \core_cohort\reportbuilder\audience\cohortmember
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cohortmember_test extends advanced_testcase {
/**
* Test that this audience type description is generated correctly
*/
public function test_get_description(): void {
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$cohort = self::getDataGenerator()->create_cohort();
$audience = cohortmember::create($report->get('id'), ['cohorts' => [$cohort->id]]);
$this->assertEquals($cohort->name, $audience->get_description());
}
/**
* Test if user can add this audience type to the report
*/
public function test_user_can_add(): void {
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
// Admin user.
self::setAdminUser();
$cohort = self::getDataGenerator()->create_cohort();
$context = context::instance_by_id($cohort->contextid);
$audience = cohortmember::create($report->get('id'), ['cohorts' => [$cohort->id]]);
$this->assertTrue($audience->user_can_add());
// Non-priveleged user.
$user = self::getDataGenerator()->create_user();
self::setUser($user);
$this->assertFalse($audience->user_can_add());
// Grant priveleges to user (moodle/cohort:view).
$roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
assign_capability('moodle/cohort:view', CAP_ALLOW, $roleid, $context->id);
role_assign($roleid, $user->id, $context->id);
$this->assertTrue($audience->user_can_add());
}
/**
* Test if user can edit this audience type
*/
public function test_user_can_edit(): void {
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$cohort = self::getDataGenerator()->create_cohort();
$context = context::instance_by_id($cohort->contextid);
$audience = cohortmember::create($report->get('id'), ['cohorts' => [$cohort->id]]);
// Admin user.
self::setAdminUser();
$this->assertTrue($audience->user_can_edit());
// Non-priveleged user.
$user = self::getDataGenerator()->create_user();
self::setUser($user);
$this->assertFalse($audience->user_can_edit());
// Grant priveleges to user (moodle/cohort:view).
$roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
assign_capability('moodle/cohort:view', CAP_ALLOW, $roleid, $context->id);
role_assign($roleid, $user->id, $context->id);
$this->assertTrue($audience->user_can_edit());
}
/**
* Test that sql generated is correct
*/
public function test_get_sql(): void {
global $DB;
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$cohort = self::getDataGenerator()->create_cohort();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
// Add user1 into cohort.
cohort_add_member($cohort->id, $user1->id);
// Add user3 into cohort.
cohort_add_member($cohort->id, $user3->id);
$audience = cohortmember::create($report->get('id'), ['cohorts' => [$cohort->id]]);
[$join, $where, $params] = $audience->get_sql('u');
$query = 'SELECT u.* FROM {user} u ' . $join . ' WHERE ' . $where;
$records = $DB->get_records_sql($query, $params);
$this->assertEqualsCanonicalizing([$user1->id, $user3->id], array_column($records, 'id'));
}
/**
* Test if this audience type is available to use
*/
public function test_is_available(): void {
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
self::setAdminUser();
// Check with no cohorts available in the system.
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$audience = cohortmember::create($report->get('id'), ['cohorts' => []]);
$this->assertFalse($audience->is_available());
// Check with cohorts available in the system.
self::getDataGenerator()->create_cohort();
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$audience2 = cohortmember::create($report->get('id'), ['cohorts' => []]);
$this->assertTrue($audience2->is_available());
}
}
@@ -0,0 +1,294 @@
<?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/>.
declare(strict_types=1);
namespace core_cohort\reportbuilder\datasource;
use context_coursecat;
use context_system;
use core_customfield_generator;
use core_reportbuilder_generator;
use core_reportbuilder_testcase;
use core_reportbuilder\local\filters\{boolean_select, date, select, text};
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php");
/**
* Unit tests for cohorts datasource
*
* @package core_cohort
* @covers \core_cohort\reportbuilder\datasource\cohorts
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cohorts_test extends core_reportbuilder_testcase {
/**
* Test default datasource
*/
public function test_datasource_default(): void {
$this->resetAfterTest();
// Test subject.
$contextsystem = context_system::instance();
$cohortone = $this->getDataGenerator()->create_cohort([
'contextid' => $contextsystem->id,
'name' => 'Legends',
'idnumber' => 'C101',
'description' => 'Cohort for the legends',
]);
$category = $this->getDataGenerator()->create_category();
$contextcategory = context_coursecat::instance($category->id);
$cohorttwo = $this->getDataGenerator()->create_cohort([
'contextid' => $contextcategory->id,
'name' => 'Category cohort',
'description' => 'This is my category cohort',
]);
// Non-visible cohort (excluded by default).
$cohortnonvisible = $this->getDataGenerator()->create_cohort([
'contextid' => $contextsystem->id,
'name' => 'Non-visible',
'visible' => false,
]);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report(['name' => 'Cohorts', 'source' => cohorts::class, 'default' => 1]);
$content = $this->get_custom_report_content($report->get('id'));
// Default columns are name, context, idnumber, description. Sorted by name.
$this->assertEquals([
[$cohorttwo->name, $contextcategory->get_context_name(false), $cohorttwo->idnumber,
format_text($cohorttwo->description)],
[$cohortone->name, $contextsystem->get_context_name(false), $cohortone->idnumber,
format_text($cohortone->description)],
], array_map('array_values', $content));
}
/**
* Test datasource columns that aren't added by default
*/
public function test_datasource_non_default_columns(): void {
$this->resetAfterTest();
$this->setAdminUser();
set_config('allowcohortthemes', true);
/** @var core_customfield_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
$fieldcategory = $generator->create_category(['component' => 'core_cohort', 'area' => 'cohort']);
$field = $generator->create_field(['categoryid' => $fieldcategory->get('id'), 'shortname' => 'hi']);
// Test subject.
$cohort = $this->getDataGenerator()->create_cohort([
'name' => 'Legends',
'idnumber' => 'C101',
'description' => 'Cohort for the legends',
'theme' => 'boost',
'customfield_hi' => 'Hello',
]);
$user = $this->getDataGenerator()->create_user(['firstname' => 'Lionel', 'lastname' => 'Richards']);
cohort_add_member($cohort->id, $user->id);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report(['name' => 'Cohorts', 'source' => cohorts::class, 'default' => 0]);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:visible']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:timecreated']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:timemodified']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:component']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:theme']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:customfield_hi']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort_member:timeadded']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullname']);
$content = $this->get_custom_report_content($report->get('id'));
$this->assertCount(1, $content);
[$visible, $timecreated, $timemodified, $component, $theme, $custom, $timeadded, $fullname] = array_values($content[0]);
$this->assertEquals('Yes', $visible);
$this->assertNotEmpty($timecreated);
$this->assertNotEmpty($timemodified);
$this->assertEquals('Created manually', $component);
$this->assertEquals('Boost', $theme);
$this->assertEquals('Hello', $custom);
$this->assertNotEmpty($timeadded);
$this->assertEquals(fullname($user), $fullname);
}
/**
* Data provider for {@see test_datasource_filters}
*
* @return array[]
*/
public function datasource_filters_provider(): array {
return [
// Cohort.
'Filter cohort' => ['cohort:cohortselect', [
'cohort:cohortselect_values' => [-1],
], false],
'Filter context' => ['cohort:context', [
'cohort:context_operator' => select::EQUAL_TO,
'cohort:context_value' => context_system::instance()->id,
], true],
'Filter content (no match)' => ['cohort:context', [
'cohort:context_operator' => select::EQUAL_TO,
'cohort:context_value' => -1,
], false],
'Filter name' => ['cohort:name', [
'cohort:name_operator' => text::IS_EQUAL_TO,
'cohort:name_value' => 'Legends',
], true],
'Filter name (no match)' => ['cohort:name', [
'cohort:name_operator' => text::IS_EQUAL_TO,
'cohort:name_value' => 'Dancing',
], false],
'Filter idnumber' => ['cohort:idnumber', [
'cohort:idnumber_operator' => text::IS_EQUAL_TO,
'cohort:idnumber_value' => 'C101',
], true],
'Filter idnumber (no match)' => ['cohort:idnumber', [
'cohort:idnumber_operator' => text::IS_EQUAL_TO,
'cohort:idnumber_value' => 'C102',
], false],
'Filter time created' => ['cohort:timecreated', [
'cohort:timecreated_operator' => date::DATE_RANGE,
'cohort:timecreated_from' => 1622502000,
], true],
'Filter time created (no match)' => ['cohort:timecreated', [
'cohort:timecreated_operator' => date::DATE_RANGE,
'cohort:timecreated_to' => 1622502000,
], false],
'Filter description' => ['cohort:description', [
'cohort:description_operator' => text::CONTAINS,
'cohort:description_value' => 'legends',
], true],
'Filter description (no match)' => ['cohort:description', [
'cohort:description_operator' => text::IS_EMPTY,
], false],
'Filter theme' => ['cohort:theme', [
'cohort:theme_operator' => select::EQUAL_TO,
'cohort:theme_value' => 'boost',
], true],
'Filter theme (no match)' => ['cohort:theme', [
'cohort:theme_operator' => select::EQUAL_TO,
'cohort:theme_value' => 'classic',
], false],
'Filter visible' => ['cohort:visible', [
'cohort:visible_operator' => boolean_select::CHECKED,
], true],
'Filter visible (no match)' => ['cohort:visible', [
'cohort:visible_operator' => boolean_select::NOT_CHECKED,
], false],
// Cohort member.
'Filter time added' => ['cohort_member:timeadded', [
'cohort_member:timeadded_operator' => date::DATE_RANGE,
'cohort_member:timeadded_from' => 1622502000,
], true],
'Filter time added (no match)' => ['cohort_member:timeadded', [
'cohort_member:timeadded_operator' => date::DATE_RANGE,
'cohort_member:timeadded_to' => 1622502000,
], false],
// User.
'Filter user' => ['user:username', [
'user:username_operator' => text::IS_EQUAL_TO,
'user:username_value' => 'lionel',
], true],
'Filter user (no match)' => ['user:username', [
'user:username_operator' => text::IS_EQUAL_TO,
'user:username_value' => 'rick',
], false],
];
}
/**
* Test datasource filters
*
* @param string $filtername
* @param array $filtervalues
* @param bool $expectmatch
*
* @dataProvider datasource_filters_provider
*/
public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
$this->resetAfterTest();
set_config('allowcohortthemes', true);
// Test subject.
$cohort = $this->getDataGenerator()->create_cohort([
'name' => 'Legends',
'idnumber' => 'C101',
'description' => 'Cohort for the legends',
'theme' => 'boost',
]);
$user = $this->getDataGenerator()->create_user(['username' => 'lionel']);
cohort_add_member($cohort->id, $user->id);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
// Create report containing single column, and given filter.
$report = $generator->create_report(['name' => 'Cohorts', 'source' => cohorts::class, 'default' => 0]);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'cohort:name']);
// Add filter, set it's values.
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
if ($expectmatch) {
$this->assertCount(1, $content);
$this->assertEquals('Legends', reset($content[0]));
} else {
$this->assertEmpty($content);
}
}
/**
* Stress test datasource
*
* In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php
*/
public function test_stress_datasource(): void {
if (!PHPUNIT_LONGTEST) {
$this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
}
$this->resetAfterTest();
$cohort = $this->getDataGenerator()->create_cohort();
$user = $this->getDataGenerator()->create_user();
cohort_add_member($cohort->id, $user->id);
$this->datasource_stress_test_columns(cohorts::class);
$this->datasource_stress_test_columns_aggregation(cohorts::class);
$this->datasource_stress_test_conditions(cohorts::class, 'cohort:name');
}
}