MDL-87708 core: Remove MoodleNet outbound sharing tests

Part of MDL-87350
This commit is contained in:
Muhammad Arnaldo
2026-03-11 09:08:42 +07:00
committed by Huong Nguyen
parent 32c0db31e1
commit 146fda5681
19 changed files with 26 additions and 2789 deletions
@@ -1,56 +0,0 @@
<?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/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
use Moodle\BehatExtension\Exception\SkippedException;
require_once(__DIR__ . '/../../behat/behat_base.php');
/**
* Steps definitions related to MoodleNet.
*
* @package core
* @category test
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_moodlenet extends behat_base {
/**
* Check that the TEST_MOODLENET_MOCK_SERVER is defined, so we can connect to the mock server.
*
* @Given /^a MoodleNet mock server is configured$/
*/
public function mock_is_configured(): void {
if (!defined('TEST_MOODLENET_MOCK_SERVER')) {
throw new SkippedException(
'The TEST_MOODLENET_MOCK_SERVER constant must be defined to run MoodleNet tests'
);
}
}
/**
* Change the service base url to the TEST_MOODLENET_MOCK_SERVER url.
*
* @Given /^I change the MoodleNet field "(?P<field_string>(?:[^"]|\\")*)" to mock server$/
* @param string $field Field name
*/
public function change_service_base_url_to_mock_url(string $field): void {
$field = behat_field_manager::get_form_field_from_label($field, $this);
$field->set_value(TEST_MOODLENET_MOCK_SERVER);
}
}
@@ -1,94 +0,0 @@
@core
Feature: MoodleNet outbound send activity
In order to send activity to MoodleNet server
As a teacher
I need to be able package the activity and share to MoodleNet
Background:
Given I log in as "admin"
And a MoodleNet mock server is configured
And the following config values are set as admin:
| enablesharingtomoodlenet | 1 |
And I navigate to "Server > OAuth 2 services" in site administration
And I press "MoodleNet"
And I should see "Create new service: MoodleNet"
And I change the MoodleNet field "Service base URL" to mock server
And I press "Save changes"
And I navigate to "MoodleNet > MoodleNet outbound settings" in site administration
And I set the field "Auth 2 service" to "MoodleNet"
And I press "Save changes"
And the following course exists:
| name | Test course |
| shortname | C1 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
| manager1 | Manager | 1 | manager1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| manager1 | C1 | manager |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following "activities" exist:
| activity | course | idnumber | name | intro |
| assign | C1 | assign1 | Test Assignment 1 | Test Assignment 1 |
Scenario: Share to MoodleNet menu only be available for teachers and managers
Given I am on the "Test Assignment 1" "assign activity" page logged in as student1
Then "Share to MoodleNet" "link" should not exist in current page administration
And I am on the "Test Assignment 1" "assign activity" page logged in as teacher1
And "Share to MoodleNet" "link" should exist in current page administration
And I am on the "Test Assignment 1" "assign activity" page logged in as manager1
And "Share to MoodleNet" "link" should exist in current page administration
Scenario: Share to MoodleNet menu only be available for user that has capability only
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/moodlenet:shareactivity | Prohibit | editingteacher | Course | C1 |
When I am on the "Test Assignment 1" "assign activity" page logged in as teacher1
Then "Share to MoodleNet" "link" should not exist in current page administration
And I am on the "Test Assignment 1" "assign activity" page logged in as manager1
And "Share to MoodleNet" "link" should exist in current page administration
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/moodlenet:shareactivity | Prohibit | manager | Course | C1 |
And I am on the "Test Assignment 1" "assign activity" page logged in as manager1
And "Share to MoodleNet" "link" should not exist in current page administration
@javascript
Scenario: User can share activity to MoodleNet
Given I am on the "Test Assignment 1" "assign activity" page logged in as teacher1
When I navigate to "Share to MoodleNet" in current page administration
Then I should see "Assignment" in the "Share to MoodleNet" "dialogue"
And I should see "Test Assignment 1" in the "Share to MoodleNet" "dialogue"
And I should see "This activity is being shared with MoodleNet as a resource." in the "Share to MoodleNet" "dialogue"
And I click on "Share" "button" in the "Share to MoodleNet" "dialogue"
And I switch to "moodlenet_auth" window
And I press "Allow" and switch to main window
And I should see "Saved to MoodleNet drafts"
And "Go to MoodleNet drafts" "link" should exist in the "Share to MoodleNet" "dialogue"
@javascript
Scenario: User can see their shared resources on the MoodleNet share progress page
Given I am on the "C1" course page logged in as teacher1
When I navigate to "MoodleNet share progress" in current page administration
And I should see "There are no shared resources to display at this time."
And I am on "C1" course homepage
And I navigate to "Share to MoodleNet" in current page administration
And I click on "Share" "button" in the "Share to MoodleNet" "dialogue"
And I switch to "moodlenet_auth" window
And I press "Allow" and switch to main window
And I click on "Close" "button" in the "Share to MoodleNet" "dialogue"
And I am on the "Test Assignment 1" "assign activity" page
And I navigate to "Share to MoodleNet" in current page administration
And I click on "Share" "button" in the "Share to MoodleNet" "dialogue"
And I click on "Close" "button" in the "Share to MoodleNet" "dialogue"
And I am on "C1" course homepage
And I navigate to "MoodleNet share progress" in current page administration
Then "Test course 1" row "Name" column of "generaltable" table should contain "Test course 1"
And "Test course 1" row "Type" column of "generaltable" table should contain "Course"
And "Test course 1" row "Send status" column of "generaltable" table should contain "Sent"
And "Test Assignment 1" row "Name" column of "generaltable" table should contain "Test Assignment 1"
And "Test Assignment 1" row "Type" column of "generaltable" table should contain "Assignment"
And "Test Assignment 1" row "Send status" column of "generaltable" table should contain "Sent"
@@ -1,67 +0,0 @@
@core
Feature: MoodleNet outbound share course
In order to send a course to MoodleNet server
As a teacher
I need to be able to backup the course and share to MoodleNet
Background:
Given the following course exists:
| name | Test course |
| shortname | C1 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
| manager1 | Manager | 1 | manager1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| manager1 | C1 | manager |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And I log in as "admin"
And a MoodleNet mock server is configured
And the following config values are set as admin:
| enablesharingtomoodlenet | 1 |
And I navigate to "Server > OAuth 2 services" in site administration
And I press "MoodleNet"
And I should see "Create new service: MoodleNet"
And I change the MoodleNet field "Service base URL" to mock server
And I press "Save changes"
And I navigate to "MoodleNet > MoodleNet outbound settings" in site administration
And I set the field "Auth 2 service" to "MoodleNet"
And I press "Save changes"
Scenario: Share course to MoodleNet option only be available for teachers and managers
Given I am on the "C1" "course" page logged in as student1
And "Share to MoodleNet" "link" should not exist in current page administration
When I am on the "C1" "course" page logged in as teacher1
And "Share to MoodleNet" "link" should exist in current page administration
Then I am on the "C1" "course" page logged in as manager1
And "Share to MoodleNet" "link" should exist in current page administration
Scenario: Share course to MoodleNet option only be available for user that has capability only
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/moodlenet:sharecourse | Prohibit | editingteacher | Course | C1 |
When I am on the "C1" "course" page logged in as teacher1
Then "Share to MoodleNet" "link" should not exist in current page administration
And I am on the "C1" "course" page logged in as manager1
And "Share to MoodleNet" "link" should exist in current page administration
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/moodlenet:sharecourse | Prohibit | manager | Course | C1 |
And I am on the "C1" "course" page logged in as manager1
And "Share to MoodleNet" "link" should not exist in current page administration
@javascript
Scenario: User can share course to MoodleNet
Given I am on the "C1" "course" page logged in as teacher1
When I navigate to "Share to MoodleNet" in current page administration
Then I should see "Course" in the "Share to MoodleNet" "dialogue"
And I should see "Test course 1" in the "Share to MoodleNet" "dialogue"
And I should see "This course is being shared with MoodleNet as a resource." in the "Share to MoodleNet" "dialogue"
And I click on "Share" "button" in the "Share to MoodleNet" "dialogue"
And I switch to "moodlenet_auth" window
And I press "Allow" and switch to main window
And I should see "Saved to MoodleNet drafts"
And "Go to MoodleNet drafts" "link" should exist in the "Share to MoodleNet" "dialogue"
@@ -1,97 +0,0 @@
@core
Feature: MoodleNet outbound share selected activities in a course
In order to send a number of selected activities in a course to MoodleNet server
As a teacher
I need to be able to backup the selected activities in a course and share to MoodleNet
Background:
Given the following course exists:
| name | Test course |
| shortname | C1 |
And the following "activities" exist:
| activity | course | idnumber | name | intro |
| assign | C1 | assign1 | Test Assignment 1 | Test Assignment 1 |
| assign | C1 | assign2 | Test Assignment 2 | Test Assignment 2 |
| assign | C1 | assign3 | Test Assignment 3 | Test Assignment 3 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
| manager1 | Manager | 1 | manager1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| manager1 | C1 | manager |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And I log in as "admin"
And a MoodleNet mock server is configured
And the following config values are set as admin:
| enablesharingtomoodlenet | 1 |
And I navigate to "Server > OAuth 2 services" in site administration
And I press "MoodleNet"
And I should see "Create new service: MoodleNet"
And I change the MoodleNet field "Service base URL" to mock server
And I press "Save changes"
And I navigate to "MoodleNet > MoodleNet outbound settings" in site administration
And I set the field "Auth 2 service" to "MoodleNet"
And I press "Save changes"
@javascript
Scenario: Share to MoodleNet bulk option should only be available for users with the capability
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/moodlenet:sharecourse | Prohibit | editingteacher | Course | C1 |
When I am on the "C1" "course" page logged in as teacher1
And I turn editing mode on
And I click on "Bulk actions" "button"
And I click on "Select activity Test Assignment 1" "checkbox"
Then "Share to MoodleNet" "button" should not exist in the "sticky-footer" "region"
And I am on the "C1" "course" page logged in as manager1
And I turn editing mode on
And I click on "Bulk actions" "button"
And I click on "Select activity Test Assignment 1" "checkbox"
And "Share to MoodleNet" "button" should exist in the "sticky-footer" "region"
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/moodlenet:sharecourse | Prohibit | manager | Course | C1 |
And I am on the "C1" "course" page logged in as manager1
And I turn editing mode on
And I click on "Bulk actions" "button"
And I click on "Select activity Test Assignment 1" "checkbox"
And "Share to MoodleNet" "button" should not exist in the "sticky-footer" "region"
@javascript
Scenario: User can share selected activities in a course to MoodleNet
Given I am on the "C1" "course" page logged in as teacher1
And I turn editing mode on
And I click on "Bulk actions" "button"
When I click on "Share to MoodleNet" "button" in the "sticky-footer" "region"
Then "Share to MoodleNet" "dialogue" should not exist
And I click on "Select activity Test Assignment 1" "checkbox"
And I click on "Select activity Test Assignment 2" "checkbox"
And I click on "Share to MoodleNet" "button" in the "sticky-footer" "region"
And "Share to MoodleNet" "dialogue" should exist
And I should see "Test course 1" in the "Share to MoodleNet" "dialogue"
And I should see "The selected activities are being shared with MoodleNet as a resource." in the "Share to MoodleNet" "dialogue"
And I should see "2 activities will be included in the course." in the "Share to MoodleNet" "dialogue"
And I click on "Share" "button" in the "Share to MoodleNet" "dialogue"
And I switch to "moodlenet_auth" window
And I press "Allow" and switch to main window
And I should see "Saved to MoodleNet drafts"
And "Go to MoodleNet drafts" "link" should exist in the "Share to MoodleNet" "dialogue"
@javascript
Scenario: User can share activity directly in a course bulk mode to MoodleNet
Given I am on the "C1" "course" page logged in as teacher1
And I turn editing mode on
And I click on "Bulk actions" "button"
And I click on "Select activity Test Assignment 1" "checkbox"
When I click on "Share to MoodleNet" "button" in the "sticky-footer" "region"
Then I should see "Test Assignment 1" in the "Share to MoodleNet" "dialogue"
And I should see "This activity is being shared with MoodleNet as a resource." in the "Share to MoodleNet" "dialogue"
And I should not see "1 activities will be included in the course." in the "Share to MoodleNet" "dialogue"
And I click on "Share" "button" in the "Share to MoodleNet" "dialogue"
And I switch to "moodlenet_auth" window
And I press "Allow" and switch to main window
And I should see "Saved to MoodleNet drafts"
And "Go to MoodleNet drafts" "link" should exist in the "Share to MoodleNet" "dialogue"
-84
View File
@@ -1,84 +0,0 @@
<?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\external;
defined('MOODLE_INTERNAL') || die();
use core\oauth2\api;
use core_external\external_api;
global $CFG;
require_once($CFG->dirroot . '/lib/tests/moodlenet/helpers.php');
/**
* External functions test for moodlenet_auth_check.
*
* @package core
* @category test
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\external\moodlenet_auth_check
*/
final class moodlenet_auth_check_test extends \core_external\tests\externallib_testcase {
/**
* Test the behaviour of moodlenet_auth_check().
*
* @covers ::execute
*/
public function test_moodlenet_auth_check(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->enablesharingtomoodlenet = true;
// Generate data.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$user = $generator->create_user();
$generator->enrol_user($user->id, $course->id, 'student');
// Create dummy issuer.
$issuer = \core\moodlenet\helpers::get_mock_issuer(0);
// Test with the user does not have permission.
$this->setUser($user);
$result = moodlenet_auth_check::execute($issuer->get('id'), $course->id);
$result = external_api::clean_returnvalue(moodlenet_auth_check::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorpermission', $result['warnings'][0]['warningcode']);
// Test with the issuer is not enabled.
$this->setAdminUser();
$result = moodlenet_auth_check::execute($issuer->get('id'), $course->id);
$result = external_api::clean_returnvalue(moodlenet_auth_check::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
// Test with the issuer is enabled and not logged in.
$issuer->set('enabled', 1);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
set_config('oauthservice', $issuer->get('id'), 'moodlenet');
$result = moodlenet_auth_check::execute($issuer->get('id'), $course->id);
$result = external_api::clean_returnvalue(moodlenet_auth_check::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['loginurl']);
}
}
@@ -1,137 +0,0 @@
<?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\external;
use core\oauth2\api;
use core_external\external_api;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/tests/moodlenet/helpers.php');
/**
* External functions test for moodlenet_get_share_info_activity.
*
* @package core
* @category test
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\external\moodlenet_get_share_info_activity
*/
final class moodlenet_get_share_info_activity_test extends \core_external\tests\externallib_testcase {
/**
* Test the behaviour of moodlenet_get_share_info_activity().
* @covers ::execute
*/
public function test_moodlenet_get_share_info_activity(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->enablesharingtomoodlenet = true;
// Generate course and activities.
$course = $this->getDataGenerator()->create_course();
$activity1 = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Page activity']);
$activity2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'name' => 'Assign activity']);
$activity3 = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id, 'name' => 'Quiz activity']);
// Create dummy enabled issuer.
$issuer = \core\moodlenet\helpers::get_mock_issuer(1);
// Test the 1st activity with no OAuth2 setup yet.
$result = moodlenet_get_share_info_activity::execute($activity1->cmid);
$result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertEmpty($result['name']);
$this->assertEmpty($result['type']);
$this->assertEmpty($result['server']);
$this->assertEmpty($result['supportpageurl']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals(0, $result['warnings'][0]['item']);
$this->assertEquals('errorissuernotset', $result['warnings'][0]['warningcode']);
$this->assertEquals(get_string('moodlenet:issuerisnotset', 'moodle'), $result['warnings'][0]['message']);
// Test the 1st activity with OAuth2 disabled.
set_config('oauthservice', $issuer->get('id'), 'moodlenet');
$issuer->set('enabled', 0);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
$result = moodlenet_get_share_info_activity::execute($activity1->cmid);
$result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertEmpty($result['name']);
$this->assertEmpty($result['type']);
$this->assertEmpty($result['server']);
$this->assertEmpty($result['supportpageurl']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($issuer->get('id'), $result['warnings'][0]['item']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
$this->assertEquals(get_string('moodlenet:issuerisnotenabled', 'moodle'), $result['warnings'][0]['message']);
// Test the 1st activity with support url is set to the internal contact site support page.
$issuer->set('enabled', 1);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
$expectedsupporturl = $CFG->wwwroot . '/user/contactsitesupport.php';
$result = moodlenet_get_share_info_activity::execute($activity1->cmid);
$result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result);
$this->assertTrue($result['status']);
$this->assertEquals($activity1->name, $result['name']);
$this->assertEquals(get_string('modulename', 'mod_page'), $result['type']);
$this->assertEquals($issuer->get_display_name(), $result['server']);
$this->assertEquals($expectedsupporturl, $result['supportpageurl']);
// Test the 2nd activity with support url is set to the external contact site support page.
$expectedsupporturl = 'https://moodle.org/';
$CFG->supportpage = $expectedsupporturl;
$result = moodlenet_get_share_info_activity::execute($activity2->cmid);
$result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result);
$this->assertTrue($result['status']);
$this->assertEquals($activity2->name, $result['name']);
$this->assertEquals(get_string('modulename', 'mod_assign'), $result['type']);
$this->assertEquals($expectedsupporturl, $result['supportpageurl']);
// Test the 3rd activity with contact site support is disabled.
$CFG->supportavailability = CONTACT_SUPPORT_DISABLED;
$result = moodlenet_get_share_info_activity::execute($activity3->cmid);
$result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result);
$this->assertTrue($result['status']);
$this->assertEquals($activity3->name, $result['name']);
$this->assertEquals(get_string('modulename', 'mod_quiz'), $result['type']);
$this->assertEmpty($result['supportpageurl']);
// Test with an invalid activity.
// Get a random cmid that not in the created activity list.
$cmids = [$activity1->cmid, $activity2->cmid, $activity3->cmid];
do {
$randomcmid = random_int(5, 25);
} while (in_array($randomcmid, $cmids));
$result = moodlenet_get_share_info_activity::execute($randomcmid);
$result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertEmpty($result['name']);
$this->assertEmpty($result['type']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($randomcmid, $result['warnings'][0]['item']);
$this->assertEquals('errorgettingactivityinformation', $result['warnings'][0]['warningcode']);
$this->assertEquals(get_string('invalidcoursemodule', 'error'), $result['warnings'][0]['message']);
}
}
@@ -1,100 +0,0 @@
<?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\external;
use core\oauth2\api;
use core_external\external_api;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/tests/moodlenet/helpers.php');
/**
* External functions test for moodlenet_get_shared_course_info.
*
* @package core
* @category test
* @copyright 2023 Safat Shahin <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\external\moodlenet_get_shared_course_info
*/
final class moodlenet_get_shared_course_info_test extends \core_external\tests\externallib_testcase {
/**
* Test the behaviour of moodlenet_get_shared_course_info().
*
* @covers ::execute
*/
public function test_moodlenet_get_shared_course_info(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->enablesharingtomoodlenet = true;
// Generate course and activities.
$course = $this->getDataGenerator()->create_course();
// Create dummy enabled issuer.
$issuer = \core\moodlenet\helpers::get_mock_issuer(1);
// Test the course with no OAuth2 setup yet.
$result = moodlenet_get_shared_course_info::execute($course->id);
$result = external_api::clean_returnvalue(moodlenet_get_shared_course_info::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertEmpty($result['name']);
$this->assertEmpty($result['type']);
$this->assertEmpty($result['server']);
$this->assertEmpty($result['supportpageurl']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals(0, $result['warnings'][0]['item']);
$this->assertEquals('errorissuernotset', $result['warnings'][0]['warningcode']);
$this->assertEquals(get_string('moodlenet:issuerisnotset', 'moodle'), $result['warnings'][0]['message']);
// Test the course with OAuth2 disabled.
set_config('oauthservice', $issuer->get('id'), 'moodlenet');
$issuer->set('enabled', 0);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
$result = moodlenet_get_shared_course_info::execute($course->id);
$result = external_api::clean_returnvalue(moodlenet_get_shared_course_info::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertEmpty($result['name']);
$this->assertEmpty($result['type']);
$this->assertEmpty($result['server']);
$this->assertEmpty($result['supportpageurl']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($issuer->get('id'), $result['warnings'][0]['item']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
$this->assertEquals(get_string('moodlenet:issuerisnotenabled', 'moodle'), $result['warnings'][0]['message']);
// Test the course with support url is set to the internal contact site support page.
$issuer->set('enabled', 1);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
$expectedsupporturl = $CFG->wwwroot . '/user/contactsitesupport.php';
$result = moodlenet_get_shared_course_info::execute($course->id);
$result = external_api::clean_returnvalue(moodlenet_get_shared_course_info::execute_returns(), $result);
$this->assertTrue($result['status']);
$this->assertEquals($course->fullname, $result['name']);
$this->assertEquals(get_string('course'), $result['type']);
$this->assertEquals($issuer->get_display_name(), $result['server']);
$this->assertEquals($expectedsupporturl, $result['supportpageurl']);
}
}
@@ -1,168 +0,0 @@
<?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\external;
use core\oauth2\api;
use core_external\external_api;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/tests/moodlenet/helpers.php');
/**
* External functions test for moodlenet_send_activity.
*
* @package core
* @category test
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\external\moodlenet_send_activity
*/
final class moodlenet_send_activity_test extends \core_external\tests\externallib_testcase {
/**
* Test the behaviour of moodlenet_send_activity().
*
* @covers ::execute
*/
public function test_moodlenet_send_activity(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
// Generate data.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$moduleinstance = $generator->create_module('assign', ['course' => $course->id]);
$user = $generator->create_user();
$generator->enrol_user($user->id, $course->id, 'student');
// Create dummy issuer.
$issuer = \core\moodlenet\helpers::get_mock_issuer(0);
// Test with the experimental flag off.
$result = moodlenet_send_activity::execute($issuer->get('id'), $moduleinstance->cmid, 0);
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
$CFG->enablesharingtomoodlenet = true;
// Test with invalid format.
$result = moodlenet_send_activity::execute($issuer->get('id'), $moduleinstance->cmid, 5);
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorinvalidformat', $result['warnings'][0]['warningcode']);
// Test with the user does not have permission.
$this->setUser($user);
$result = moodlenet_send_activity::execute($issuer->get('id'), $moduleinstance->cmid, 0);
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorpermission', $result['warnings'][0]['warningcode']);
$this->setAdminUser();
// Test with the issuer is not enabled.
$result = moodlenet_send_activity::execute($issuer->get('id'), $moduleinstance->cmid, 0);
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
// Test with the issuer is enabled but not set in the MN Outbound setting.
$issuer->set('enabled', 1);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
$result = moodlenet_send_activity::execute($issuer->get('id'), $moduleinstance->cmid, 0);
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
set_config('oauthservice', $issuer->get('id'), 'moodlenet');
// Test with the issuer not yet authorized.
$result = moodlenet_send_activity::execute($issuer->get('id'), $moduleinstance->cmid, 0);
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('erroroauthclient', $result['warnings'][0]['warningcode']);
$this->assertEquals($issuer->get('id'), $result['warnings'][0]['item']);
$this->assertEquals(get_string('moodlenet:issuerisnotauthorized', 'moodle'), $result['warnings'][0]['message']);
}
/**
* Test execute_returns() method.
*
* @dataProvider return_resource_url_provider
* @covers ::execute_returns
*/
public function test_moodlenet_send_activity_return_resource_url(bool $state, string $resourceurl): void {
$this->resetAfterTest();
// Create dummy result with the resourceurl.
$result = [
'status' => true,
'resourceurl' => $resourceurl,
'warnings' => [],
];
if (!$state) {
$this->expectException(\invalid_response_exception::class);
}
$result = external_api::clean_returnvalue(moodlenet_send_activity::execute_returns(), $result);
if ($state) {
$this->assertEquals($resourceurl, $result['resourceurl']);
}
}
/**
* Provider for test_moodlenet_send_activity_return_resource_url().
*
* @return array Test data.
*/
public static function return_resource_url_provider(): array {
return [
'Success 1' => [
true,
'https://moodlenet.example.com/drafts/view/testactivity_backup.mbz',
],
'Success 2' => [
true,
'https://moodlenet.example.com/drafts/view/testactivity_backup with spaces.mbz',
],
'Success 3' => [
true,
'https://moodlenet.example.com/drafts/view/testactivity_backup with " character.mbz',
],
'Success 4' => [
true,
"https://moodlenet.example.com/drafts/view/testactivity_backup with ' character.mbz",
],
'Success 5' => [
true,
'https://moodlenet.example.com/drafts/view/testactivity_backup with < and > characters.mbz',
],
'Fail 1' => [
false,
'https://moodlenet.example.com/drafts/view/testactivity_backupwith<lang lang="en">a<a</lang>html.mbz',
],
];
}
}
-174
View File
@@ -1,174 +0,0 @@
<?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\external;
use core\oauth2\api;
use core_external\external_api;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/tests/moodlenet/helpers.php');
/**
* External functions test for moodlenet_send_course.
*
* @package core
* @category test
* @copyright 2023 Safat Shahin <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\external\moodlenet_send_course
*/
final class moodlenet_send_course_test extends \core_external\tests\externallib_testcase {
/**
* Test the behaviour of moodlenet_send_course().
*
* @covers ::execute
*/
public function test_moodlenet_send_course(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
// Generate data.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$user = $generator->create_user();
$generator->enrol_user($user->id, $course->id, 'student');
// Create dummy issuer.
$issuer = \core\moodlenet\helpers::get_mock_issuer(0);
// Test with the experimental flag off.
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 0);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
$CFG->enablesharingtomoodlenet = true;
// Test with invalid format.
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 5);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorinvalidformat', $result['warnings'][0]['warningcode']);
// Test with invalid course module id.
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 0, [random_int(5, 30)]);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorinvalidcmids', $result['warnings'][0]['warningcode']);
// Test with the user does not have permission.
$this->setUser($user);
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 0);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorpermission', $result['warnings'][0]['warningcode']);
$this->setAdminUser();
// Test with the issuer is not enabled.
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 0);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
// Test with the issuer is enabled but not set in the MN Outbound setting.
$issuer->set('enabled', 1);
$irecord = $issuer->to_record();
api::update_issuer($irecord);
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 0);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('errorissuernotenabled', $result['warnings'][0]['warningcode']);
set_config('oauthservice', $issuer->get('id'), 'moodlenet');
// Test with the issuer not yet authorized.
$result = moodlenet_send_course::execute($issuer->get('id'), $course->id, 0);
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
$this->assertFalse($result['status']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals('erroroauthclient', $result['warnings'][0]['warningcode']);
$this->assertEquals($issuer->get('id'), $result['warnings'][0]['item']);
$this->assertEquals(get_string('moodlenet:issuerisnotauthorized', 'moodle'), $result['warnings'][0]['message']);
}
/**
* Test execute_returns() method.
*
* @dataProvider return_resource_url_provider
* @covers ::execute_returns
*/
public function test_moodlenet_send_course_return_resource_url(bool $state, string $resourceurl): void {
$this->resetAfterTest();
// Create dummy result with the resourceurl.
$result = [
'status' => true,
'resourceurl' => $resourceurl,
'warnings' => [],
];
if (!$state) {
$this->expectException(\invalid_response_exception::class);
}
$result = external_api::clean_returnvalue(moodlenet_send_course::execute_returns(), $result);
if ($state) {
$this->assertEquals($resourceurl, $result['resourceurl']);
}
}
/**
* Provider for test_moodlenet_send_course_return_resource_url().
*
* @return array Test data.
*/
public static function return_resource_url_provider(): array {
return [
'Success 1' => [
true,
'https://moodlenet.example.com/drafts/view/testcourse_backup.mbz',
],
'Success 2' => [
true,
'https://moodlenet.example.com/drafts/view/testcourse_backup with spaces.mbz',
],
'Success 3' => [
true,
'https://moodlenet.example.com/drafts/view/testcourse_backup with " character.mbz',
],
'Success 4' => [
true,
"https://moodlenet.example.com/drafts/view/testcourse_backup with ' character.mbz",
],
'Success 5' => [
true,
'https://moodlenet.example.com/drafts/view/testcourse_backup with < and > characters.mbz',
],
'Fail 1' => [
false,
'https://moodlenet.example.com/drafts/view/testcourse_backupwith<lang lang="en">a<a</lang>html.mbz',
],
];
}
}
@@ -1,139 +0,0 @@
<?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\moodlenet;
use core\context\user;
/**
* Unit tests for {@see activity_packager}.
*
* @coversDefaultClass \core\moodlenet\activity_packager
* @package core
* @copyright 2023 Michael Hawkins <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class activity_packager_test extends \advanced_testcase {
/**
* Test fetching and overriding a backup task setting.
*
* @covers ::override_task_setting
* @covers ::get_all_task_settings
* @covers ::get_backup_controller
*/
public function test_override_task_setting(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$assigndata = [
'course' => $course->id,
'name' => 'Extremely interesting assignment',
'intro' => 'A great assignment to share',
];
$assign = $generator->create_module('assign', $assigndata);
$cminfo = get_fast_modinfo($course->id)->get_cm($assign->cmid);
$packager = new activity_packager($cminfo, $USER->id);
// Fetch all backup task settings.
$rc = new \ReflectionClass(activity_packager::class);
$rcmgetbackup = $rc->getMethod('get_backup_controller');
$controller = $rcmgetbackup->invoke($packager);
$rcmgetall = $rc->getMethod('get_all_task_settings');
$tasksettings = $rcmgetall->invoke($packager, $controller);
// Fetch the default settings and grab an example value (setting_root_users).
$rootsettings = $tasksettings[\backup_root_task::class];
$testsettingname = 'setting_root_users';
$oldvalue = 99;
foreach ($rootsettings as $setting) {
$name = $setting->get_ui_name();
if ($name == $testsettingname) {
$oldvalue = $setting->get_value();
break;
}
}
// Check we found the setting value (either 0 or 1 are valid).
$this->assertNotEquals(99, $oldvalue);
$this->assertLessThanOrEqual(1, $oldvalue);
// Override the setting_root_users value, then re-fetch the settings to check the change is reflected.
$overridevalue = ($oldvalue == 1) ? 0 : 1;
$rcmoverridesetting = $rc->getMethod('override_task_setting');
$rcmoverridesetting->invoke($packager, $tasksettings, $testsettingname, $overridevalue);
$tasksettings = $rcmgetall->invoke($packager, $controller);
$rootsettings = $tasksettings[\backup_root_task::class];
$newvalue = 99;
foreach ($rootsettings as $setting) {
$name = $setting->get_ui_name();
if ($name == $testsettingname) {
$newvalue = $setting->get_value();
break;
}
}
$this->assertEquals($overridevalue, $newvalue);
// We have finished with the backup controller, so destroy it.
$controller->destroy();
}
/**
* Test overriding a backup task setting.
*
* @covers ::get_package
* @covers ::package
*/
public function test_get_package(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$currenttime = time();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$assigndata = [
'course' => $course->id,
'name' => 'Extremely interesting assignment',
'intro' => 'A great assignment to share',
];
$assign = $generator->create_module('assign', $assigndata);
$cminfo = get_fast_modinfo($course->id)->get_cm($assign->cmid);
$packager = new activity_packager($cminfo, $USER->id);
$package = $packager->get_package();
// Confirm the expected stored_file object is returned.
$this->assertInstanceOf(\stored_file::class, $package);
// Check some known values in the returned stored_file object to confirm they match the file we have packaged.
$this->assertNotEmpty($package->get_contenthash());
$this->assertEquals(user::instance($USER->id)->id, $package->get_contextid());
$this->assertEquals('user', $package->get_component());
$this->assertEquals('draft', $package->get_filearea());
$this->assertEquals('assign_backup.mbz', $package->get_filename());
$this->assertGreaterThan(0, $package->get_filesize());
$timecreated = $package->get_timecreated();
$this->assertGreaterThanOrEqual($currenttime, $timecreated);
$this->assertEquals($timecreated, $package->get_timemodified());
}
}
@@ -1,312 +0,0 @@
<?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\moodlenet;
use context_course;
use core\http_client;
use core\oauth2\issuer;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Http\Message\ResponseInterface;
use ReflectionMethod;
use stdClass;
use testing_data_generator;
/**
* Unit tests for {@see activity_sender}.
*
* @coversDefaultClass \core\moodlenet\activity_sender
* @package core
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class activity_sender_test extends \advanced_testcase {
/** @var testing_data_generator Data generator. */
private testing_data_generator $generator;
/** @var stdClass Course object. */
private stdClass $course;
/** @var stdClass Activity object, */
private stdClass $moduleinstance;
/** @var context_course Course context instance. */
private context_course $coursecontext;
/** @var issuer $issuer Dummy issuer. */
private issuer $issuer;
/** @var MockObject $mockoauthclient Mock OAuth client. */
private MockObject $mockoauthclient;
public static function setUpBeforeClass(): void {
parent::setUpBeforeClass();
require_once(__DIR__ . '/helpers.php');
}
/**
* Set up function for tests.
*/
protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
// Get data generator.
$this->generator = $this->getDataGenerator();
// Create course.
$this->course = $this->generator->create_course();
$this->moduleinstance = $this->generator->create_module('assign', ['course' => $this->course->id]);
$this->coursecontext = context_course::instance($this->course->id);
// Create mock issuer.
$this->issuer = helpers::get_mock_issuer(1);
// Create mock builder for OAuth2 client.
$mockbuilder = $this->getMockBuilder('core\oauth2\client');
$mockbuilder->onlyMethods(['get_issuer', 'is_logged_in', 'get_accesstoken']);
$mockbuilder->setConstructorArgs([$this->issuer, '', '']);
// Get the OAuth2 client mock.
$this->mockoauthclient = $mockbuilder->getMock();
}
/**
* Test prepare_share_contents method.
*
* @covers ::prepare_share_contents
*/
public function test_prepare_share_contents(): void {
global $USER;
$this->setAdminUser();
$httpclient = new http_client();
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
// Set get_file method accessibility.
$method = new ReflectionMethod(activity_sender::class, 'prepare_share_contents');
// Test with invalid share format.
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('moodlenet:invalidshareformat', 'error'));
$package = $method->invoke(new activity_sender(
$this->moduleinstance->cmid,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
random_int(5, 30)
));
// Test with valid share format and invalid course module.
$package = $method->invoke(new activity_sender(
random_int(5, 30),
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
));
$this->assertEmpty($package);
// Test with valid share format and valid course module.
$package = $method->invoke(new activity_sender(
$this->moduleinstance->cmid,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
));
$this->assertNotEmpty($package);
// Confirm the expected stored_file object is returned.
$this->assertInstanceOf(\stored_file::class, $package);
}
/**
* Test get_resource_description method.
*
* @covers ::get_resource_description
*/
public function test_get_resource_description(): void {
global $USER;
$this->setAdminUser();
$activity = $this->generator->create_module('assign', [
'course' => $this->course->id,
'intro' => '<p>This is an example Moodle activity description.</p>
<p>&nbsp;</p>
<p>This is a formatted intro</p>
<p>&nbsp;</p>
<p>This thing has many lines.</p>
<p>&nbsp;</p>
<p>The last word of this sentence is in <strong>bold</strong></p>'
]);
$httpclient = new http_client();
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
// Set get_resource_description method accessibility.
$method = new ReflectionMethod(activity_sender::class, 'get_resource_description');
// Test the processed description.
$processeddescription = $method->invoke(new activity_sender(
$activity->cmid,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
), $this->coursecontext);
$this->assertEquals('This is an example Moodle activity description.
 
This is a formatted intro
 
This thing has many lines.
 
The last word of this sentence is in bold', $processeddescription);
}
/**
* Test share_resource() method.
*
* @dataProvider share_resource_provider
* @covers ::share_resource
* @covers ::log_event
* @covers \core\moodlenet\moodlenet_client::create_resource_from_stored_file
* @covers \core\moodlenet\moodlenet_client::prepare_file_share_request_data
* @param ResponseInterface $httpresponse
* @param array $expected
*/
public function test_share_resource(ResponseInterface $httpresponse, array $expected): void {
global $CFG, $USER;
$this->setAdminUser();
// Enable the experimental flag.
$CFG->enablesharingtomoodlenet = true;
// Set OAuth 2 service in the outbound setting to the dummy issuer.
set_config('oauthservice', $this->issuer->get('id'), 'moodlenet');
// Generate access token for the mock.
$accesstoken = new stdClass();
$accesstoken->token = random_string(64);
// Get the OAuth2 client mock and set the return value for necessary methods.
$this->mockoauthclient->method('get_issuer')->will($this->returnValue($this->issuer));
$this->mockoauthclient->method('is_logged_in')->will($this->returnValue(true));
$this->mockoauthclient->method('get_accesstoken')->will($this->returnValue($accesstoken));
// Create Guzzle mock.
$mockguzzlehandler = new MockHandler([$httpresponse]);
$handlerstack = HandlerStack::create($mockguzzlehandler);
$httpclient = new http_client(['handler' => $handlerstack]);
// Create events sink.
$sink = $this->redirectEvents();
// Create activity sender.
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$activitysender = new activity_sender(
$this->moduleinstance->cmid,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
);
if (isset($expected['exception'])) {
$this->expectException(ClientException::class);
$this->expectExceptionMessage($expected['exception']);
}
// Call the API.
$result = $activitysender->share_resource();
// Verify the result.
$this->assertEquals($expected['response_code'], $result['responsecode']);
$this->assertEquals($expected['resource_url'], $result['drafturl']);
// Verify the events.
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\moodlenet_resource_exported', $event);
$this->assertEquals($USER->id, $event->userid);
if ($result['responsecode'] == 201) {
$description = "The user with id '{$USER->id}' successfully shared activities to MoodleNet with the " .
"following course module ids, from context with id '{$this->coursecontext->id}': '{$this->moduleinstance->cmid}'.";
} else {
$description = "The user with id '{$USER->id}' failed to share activities to MoodleNet with the " .
"following course module ids, from context with id '{$this->coursecontext->id}': '{$this->moduleinstance->cmid}'.";
}
$this->assertEquals($description, $event->get_description());
}
/**
* Provider for test share_resource().
*
* @return array Test data.
*/
public static function share_resource_provider(): array {
return [
'Success' => [
'httpresponse' => new Response(
201,
['Content-Type' => 'application/json'],
json_encode([
'homepage' => 'https://moodlenet.example.com/drafts/view/activity_backup_1.mbz',
]),
),
'expected' => [
'response_code' => 201,
'resource_url' => 'https://moodlenet.example.com/drafts/view/activity_backup_1.mbz',
],
],
'Fail with 200 status code' => [
'httpresponse' => new Response(
200,
['Content-Type' => 'application/json'],
json_encode([
'homepage' => 'https://moodlenet.example.com/drafts/view/activity_backup_2.mbz',
]),
),
'expected' => [
'response_code' => 200,
'resource_url' => 'https://moodlenet.example.com/drafts/view/activity_backup_2.mbz',
],
],
'Fail with 401 status code' => [
'httpresponse' => new Response(
401,
),
'expected' => [
'response_code' => 401,
'resource_url' => '',
'exception' => 'Client error: ' .
'`POST https://moodlenet.example.com/.pkg/@moodlenet/ed-resource/basic/v1/create` ' .
'resulted in a `401 Unauthorized` response',
],
],
'Fail with 404 status code' => [
'httpresponse' => new Response(
404,
),
'expected' => [
'response_code' => 404,
'resource_url' => '',
'exception' => 'Client error: '.
'`POST https://moodlenet.example.com/.pkg/@moodlenet/ed-resource/basic/v1/create` ' .
'resulted in a `404 Not Found` response',
],
],
];
}
}
@@ -1,128 +0,0 @@
<?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\moodlenet;
use core\context\user;
/**
* Test coverage for moodlenet course packager.
*
* @package core
* @copyright 2023 Safat Shahin <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\moodlenet\course_packager
*/
final class course_packager_test extends \advanced_testcase {
/**
* Test fetching and overriding a backup task setting.
*
* @covers ::override_task_setting
* @covers ::get_all_task_settings
* @covers ::get_backup_controller
*/
public function test_override_task_setting(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
// Load the course packager.
$packager = new course_packager($course, $USER->id);
// Fetch all backup task settings.
$rc = new \ReflectionClass(course_packager::class);
$rcmgetbackup = $rc->getMethod('get_backup_controller');
$controller = $rcmgetbackup->invoke($packager);
$rcmgetall = $rc->getMethod('get_all_task_settings');
$tasksettings = $rcmgetall->invoke($packager, $controller);
// Fetch the default settings and grab an example value (setting_root_users).
$rootsettings = $tasksettings[\backup_root_task::class];
$testsettingname = 'setting_root_users';
$oldvalue = 99;
foreach ($rootsettings as $setting) {
$name = $setting->get_ui_name();
if ($name == $testsettingname) {
$oldvalue = $setting->get_value();
break;
}
}
// Check we found the setting value (either 0 or 1 are valid).
$this->assertNotEquals(99, $oldvalue);
$this->assertLessThanOrEqual(1, $oldvalue);
// Override the setting_root_users value, then re-fetch the settings to check the change is reflected.
$overridevalue = ($oldvalue == 1) ? 0 : 1;
$rcmoverridesetting = $rc->getMethod('override_task_setting');
$rcmoverridesetting->invoke($packager, $tasksettings, $testsettingname, $overridevalue);
$tasksettings = $rcmgetall->invoke($packager, $controller);
$rootsettings = $tasksettings[\backup_root_task::class];
$newvalue = 99;
foreach ($rootsettings as $setting) {
$name = $setting->get_ui_name();
if ($name == $testsettingname) {
$newvalue = $setting->get_value();
break;
}
}
$this->assertEquals($overridevalue, $newvalue);
// We have finished with the backup controller, so destroy it.
$controller->destroy();
}
/**
* Test the course package file.
*
* @covers ::get_package
* @covers ::package
*/
public function test_get_package(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$currenttime = time();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
// Load the course packager.
$packager = new course_packager($course, $USER->id);
$package = $packager->get_package();
// Confirm the expected stored_file object is returned.
$this->assertInstanceOf(\stored_file::class, $package);
// Check some known values in the returned stored_file object to confirm they match the file we have packaged.
$this->assertNotEmpty($package->get_contenthash());
$this->assertEquals(user::instance($USER->id)->id, $package->get_contextid());
$this->assertEquals('user', $package->get_component());
$this->assertEquals('draft', $package->get_filearea());
$this->assertEquals($course->shortname . '_backup.mbz', $package->get_filename());
$this->assertGreaterThan(0, $package->get_filesize());
$timecreated = $package->get_timecreated();
$this->assertGreaterThanOrEqual($currenttime, $timecreated);
$this->assertEquals($timecreated, $package->get_timemodified());
}
}
@@ -1,92 +0,0 @@
<?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\moodlenet;
use backup_activity_task;
/**
* Unit tests for {@see \core\moodlenet\course_partial_packager}.
*
* @coversDefaultClass \core\moodlenet\course_partial_packager
* @package core
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class course_partial_packager_test extends \advanced_testcase {
/**
* Test fetching task settings.
*
* @covers ::remove_unselected_activities
* @covers ::get_all_activity_tasks
* @covers ::get_backup_controller
*/
public function test_remove_unselected_activities(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$page1 = $generator->create_module('page', ['course' => $course->id]);
$page2 = $generator->create_module('page', ['course' => $course->id]);
// Load the course packager.
$packager = new course_partial_packager($course, [$page1->cmid], $USER->id);
// Fetch all backup task settings.
$rc = new \ReflectionClass(course_partial_packager::class);
$rcmgetbackup = $rc->getMethod('get_backup_controller');
$controller = $rcmgetbackup->invoke($packager);
$rcmremove = $rc->getMethod('remove_unselected_activities');
$rcmremove->invoke($packager, $controller);
// Fetch all backup task settings for asserting them.
$finalsetting = [];
foreach ($controller->get_plan()->get_tasks() as $task) {
if (! $task instanceof backup_activity_task) { // Only for activity tasks.
continue;
}
$tasksettings = $task->get_settings();
foreach ($tasksettings as $setting) {
if (in_array($task->get_moduleid(), [$page1->cmid, $page2->cmid]) &&
strpos($setting->get_name(), '_included') !== false) {
$finalsetting[$task->get_moduleid()] = [
'name' => $setting->get_name(),
'value' => $setting->get_value(),
];
}
}
}
// Check the number of partial sharing tasks.
// Expected 2, Page 1 and Page 2.
$this->assertCount(2, $finalsetting);
// Check the value of the task of Page 1. 1 mean enabled, the backup will include the Page 1 activity.
$this->assertEquals('page_' . $page1->cmid . '_included', $finalsetting[$page1->cmid]['name']);
$this->assertEquals(1, $finalsetting[$page1->cmid]['value']);
// Check the value of the task of Page 2. 0 mean disabled, the backup will not include the Page 2 activity.
$this->assertEquals('page_' . $page2->cmid . '_included', $finalsetting[$page2->cmid]['name']);
$this->assertEquals(0, $finalsetting[$page2->cmid]['value']);
// We have finished with the backup controller, so destroy it.
$controller->destroy();
}
}
@@ -1,313 +0,0 @@
<?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\moodlenet;
use context_course;
use core\http_client;
use core\oauth2\issuer;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use moodle_exception;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Http\Message\ResponseInterface;
use ReflectionMethod;
use stdClass;
use testing_data_generator;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/tests/moodlenet/helpers.php');
/**
* Unit tests for {@see \core\moodlenet\course_partial_sender}.
*
* @coversDefaultClass \core\moodlenet\course_partial_sender
* @package core
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class course_partial_sender_test extends \advanced_testcase {
/** @var testing_data_generator Data generator. */
private testing_data_generator $generator;
/** @var stdClass Course object. */
private stdClass $course;
/** @var context_course Course context instance. */
private context_course $coursecontext;
/** @var array List of activities. */
private array $activities;
/** @var issuer $issuer Dummy issuer. */
private issuer $issuer;
/** @var MockObject $mockoauthclient Mock OAuth client. */
private MockObject $mockoauthclient;
/**
* Set up function for tests.
*/
protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
// Get data generator.
$this->generator = $this->getDataGenerator();
// Create course.
$this->course = $this->generator->create_course(['shortname' => 'testcourse']);
$this->coursecontext = context_course::instance($this->course->id);
// Create activities.
$this->activities[1] = $this->generator->create_module('page', ['course' => $this->course->id]);
$this->activities[2] = $this->generator->create_module('page', ['course' => $this->course->id]);
// Create mock issuer.
$this->issuer = helpers::get_mock_issuer(1);
// Create mock builder for OAuth2 client.
$mockbuilder = $this->getMockBuilder('core\oauth2\client');
$mockbuilder->onlyMethods(['get_issuer', 'is_logged_in', 'get_accesstoken']);
$mockbuilder->setConstructorArgs([$this->issuer, '', '']);
// Get the OAuth2 client mock.
$this->mockoauthclient = $mockbuilder->getMock();
}
/**
* Test prepare_share_contents method.
*
* @covers ::prepare_share_contents
*/
public function test_prepare_share_contents(): void {
global $USER;
$this->setAdminUser();
// Set get_file method accessibility.
$method = new ReflectionMethod(course_partial_sender::class, 'prepare_share_contents');
$httpclient = new http_client();
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$this->expectException(moodle_exception::class);
$this->expectExceptionMessage(get_string('invalidcoursemodule', 'error'));
// Test with valid share format and invalid course module id.
$package = $method->invoke(new course_partial_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
[random_int(5, 30)],
resource_sender::SHARE_FORMAT_BACKUP
));
$this->assertEmpty($package);
// Test with valid share format and valid course module ids.
$package = $method->invoke(new course_partial_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
[$this->activities[1]->cmid, $this->activities[2]->cmid],
resource_sender::SHARE_FORMAT_BACKUP
));
$this->assertNotEmpty($package);
// Confirm the expected stored_file object is returned.
$this->assertInstanceOf(\stored_file::class, $package);
}
/**
* Test get_resource_description method.
*
* @covers ::get_resource_description
*/
public function test_get_resource_description(): void {
global $USER;
$this->setAdminUser();
$course = $this->generator->create_course([
'summary' => '<p>This is an example Moodle course description.</p>
<p>&nbsp;</p>
<p>This is a formatted intro</p>
<p>&nbsp;</p>
<p>This thing has many lines.</p>
<p>&nbsp;</p>
<p>The last word of this sentence is in <strong>bold</strong></p>'
]);
$page = $this->generator->create_module('page', ['course' => $course->id]);
// Set get_resource_description method accessibility.
$method = new ReflectionMethod(course_partial_sender::class, 'get_resource_description');
// Test the processed description.
$httpclient = new http_client();
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$processeddescription = $method->invoke(new course_partial_sender(
$course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
[$page->cmid],
resource_sender::SHARE_FORMAT_BACKUP
), $this->coursecontext);
$this->assertEquals('This is an example Moodle course description.
 
This is a formatted intro
 
This thing has many lines.
 
The last word of this sentence is in bold', $processeddescription);
}
/**
* Test share_resource() method.
*
* @dataProvider share_resource_provider
* @covers ::share_resource
* @covers ::log_event
* @covers \core\moodlenet\moodlenet_client::create_resource_from_stored_file
* @covers \core\moodlenet\moodlenet_client::prepare_file_share_request_data
* @param ResponseInterface $httpresponse
* @param array $expected
*/
public function test_share_resource(ResponseInterface $httpresponse, array $expected): void {
global $CFG, $USER;
$this->setAdminUser();
// Enable the experimental flag.
$CFG->enablesharingtomoodlenet = true;
// Set OAuth 2 service in the outbound setting to the dummy issuer.
set_config('oauthservice', $this->issuer->get('id'), 'moodlenet');
// Generate access token for the mock.
$accesstoken = new stdClass();
$accesstoken->token = random_string(64);
// Get the OAuth2 client mock and set the return value for necessary methods.
$this->mockoauthclient->method('get_issuer')->will($this->returnValue($this->issuer));
$this->mockoauthclient->method('is_logged_in')->will($this->returnValue(true));
$this->mockoauthclient->method('get_accesstoken')->will($this->returnValue($accesstoken));
// Create Guzzle mock.
$mockguzzlehandler = new MockHandler([$httpresponse]);
$handlerstack = HandlerStack::create($mockguzzlehandler);
$httpclient = new http_client(['handler' => $handlerstack]);
// Create events sink.
$sink = $this->redirectEvents();
// Create sender.
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$coursepartialsender = new course_partial_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
[$this->activities[1]->cmid, $this->activities[2]->cmid],
resource_sender::SHARE_FORMAT_BACKUP
);
if (isset($expected['exception'])) {
$this->expectException(ClientException::class);
$this->expectExceptionMessage($expected['exception']);
}
// Call the API.
$result = $coursepartialsender->share_resource();
// Verify the result.
$this->assertEquals($expected['response_code'], $result['responsecode']);
$this->assertEquals($expected['resource_url'], $result['drafturl']);
// Verify the events.
$events = $sink->get_events();
$event = end($events);
$this->assertInstanceOf('\core\event\moodlenet_resource_exported', $event);
$this->assertEquals($USER->id, $event->userid);
$cmidslist = implode("', '", [$this->activities[1]->cmid, $this->activities[2]->cmid]);
if ($result['responsecode'] == 201) {
$description = "The user with id '{$USER->id}' successfully shared activities to MoodleNet with the " .
"following course module ids, from context with id '{$this->coursecontext->id}': '{$cmidslist}'.";
} else {
$description = "The user with id '{$USER->id}' failed to share activities to MoodleNet with the " .
"following course module ids, from context with id '{$this->coursecontext->id}': '{$cmidslist}'.";
}
$this->assertEquals($description, $event->get_description());
}
/**
* Provider for test share_resource().
*
* @return array Test data.
*/
public static function share_resource_provider(): array {
return [
'Success' => [
'httpresponse' => new Response(
201,
['Content-Type' => 'application/json'],
json_encode([
'homepage' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_1.mbz',
]),
),
'expected' => [
'response_code' => 201,
'resource_url' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_1.mbz',
],
],
'Fail with 200 status code' => [
'httpresponse' => new Response(
200,
['Content-Type' => 'application/json'],
json_encode([
'homepage' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_2.mbz',
]),
),
'expected' => [
'response_code' => 200,
'resource_url' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_2.mbz',
],
],
'Fail with 401 status code' => [
'httpresponse' => new Response(
401,
),
'expected' => [
'response_code' => 401,
'resource_url' => '',
'exception' => 'Client error: ' .
'`POST https://moodlenet.example.com/.pkg/@moodlenet/ed-resource/basic/v1/create` ' .
'resulted in a `401 Unauthorized` response',
],
],
'Fail with 404 status code' => [
'httpresponse' => new Response(
404,
),
'expected' => [
'response_code' => 404,
'resource_url' => '',
'exception' => 'Client error: '.
'`POST https://moodlenet.example.com/.pkg/@moodlenet/ed-resource/basic/v1/create` ' .
'resulted in a `404 Not Found` response',
],
],
];
}
}
@@ -1,318 +0,0 @@
<?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\moodlenet;
use context_course;
use core\http_client;
use core\oauth2\issuer;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Http\Message\ResponseInterface;
use ReflectionMethod;
use stdClass;
use testing_data_generator;
/**
* Test coverage for moodlenet course sender.
*
* @package core
* @copyright 2023 Safat Shahin <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\moodlenet\course_sender
*/
final class course_sender_test extends \advanced_testcase {
/** @var testing_data_generator Data generator. */
private testing_data_generator $generator;
/** @var stdClass Course object. */
private stdClass $course;
/** @var context_course Course context instance. */
private context_course $coursecontext;
/** @var issuer $issuer Dummy issuer. */
private issuer $issuer;
/** @var MockObject $mockoauthclient Mock OAuth client. */
private MockObject $mockoauthclient;
public static function setUpBeforeClass(): void {
parent::setUpBeforeClass();
require_once(__DIR__ . '/helpers.php');
}
/**
* Set up function for tests.
*/
protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
// Get data generator.
$this->generator = $this->getDataGenerator();
// Create course.
$this->course = $this->generator->create_course(['shortname' => 'testcourse']);
$this->coursecontext = context_course::instance($this->course->id);
// Create mock issuer.
$this->issuer = helpers::get_mock_issuer(1);
// Create mock builder for OAuth2 client.
$mockbuilder = $this->getMockBuilder('core\oauth2\client');
$mockbuilder->onlyMethods(['get_issuer', 'is_logged_in', 'get_accesstoken']);
$mockbuilder->setConstructorArgs([$this->issuer, '', '']);
// Get the OAuth2 client mock.
$this->mockoauthclient = $mockbuilder->getMock();
}
/**
* Test prepare_share_contents method.
*
* @covers ::prepare_share_contents
*/
public function test_prepare_share_contents(): void {
global $USER;
$this->setAdminUser();
// Set get_file method accessibility.
$method = new ReflectionMethod(course_sender::class, 'prepare_share_contents');
// Test with invalid share format.
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('moodlenet:invalidshareformat', 'error'));
$httpclient = new http_client();
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$coursesender = new course_sender(
random_int(5, 30),
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
random_int(5, 30)
);
$coursesender = $method->invoke(new course_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
));
// Test with valid share format and invalid course module.
$package = $method->invoke(new course_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
));
$this->assertEmpty($package);
// Test with valid share format and valid course module.
$package = $method->invoke(new course_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
));
$this->assertNotEmpty($package);
// Confirm the expected stored_file object is returned.
$this->assertInstanceOf(\stored_file::class, $package);
}
/**
* Test get_resource_description method.
*
* @covers ::get_resource_description
*/
public function test_get_resource_description(): void {
global $USER;
$this->setAdminUser();
$course = $this->generator->create_course([
'summary' => '<p>This is an example Moodle course description.</p>
<p>&nbsp;</p>
<p>This is a formatted intro</p>
<p>&nbsp;</p>
<p>This thing has many lines.</p>
<p>&nbsp;</p>
<p>The last word of this sentence is in <strong>bold</strong></p>'
]);
// Set get_resource_description method accessibility.
$method = new ReflectionMethod(course_sender::class, 'get_resource_description');
// Test the processed description.
$httpclient = new http_client();
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$processeddescription = $method->invoke(new course_sender(
$course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
), $this->coursecontext);
$this->assertEquals('This is an example Moodle course description.
 
This is a formatted intro
 
This thing has many lines.
 
The last word of this sentence is in bold', $processeddescription);
}
/**
* Test share_resource() method.
*
* @dataProvider share_resource_provider
* @covers ::share_resource
* @covers ::log_event
* @covers \core\moodlenet\moodlenet_client::create_resource_from_stored_file
* @covers \core\moodlenet\moodlenet_client::prepare_file_share_request_data
* @param ResponseInterface $httpresponse
* @param array $expected
*/
public function test_share_resource(ResponseInterface $httpresponse, array $expected): void {
global $CFG, $USER;
$this->setAdminUser();
// Enable the experimental flag.
$CFG->enablesharingtomoodlenet = true;
// Set OAuth 2 service in the outbound setting to the dummy issuer.
set_config('oauthservice', $this->issuer->get('id'), 'moodlenet');
// Generate access token for the mock.
$accesstoken = new stdClass();
$accesstoken->token = random_string(64);
// Get the OAuth2 client mock and set the return value for necessary methods.
$this->mockoauthclient->method('get_issuer')->will($this->returnValue($this->issuer));
$this->mockoauthclient->method('is_logged_in')->will($this->returnValue(true));
$this->mockoauthclient->method('get_accesstoken')->will($this->returnValue($accesstoken));
// Create Guzzle mock.
$mockguzzlehandler = new MockHandler([$httpresponse]);
$handlerstack = HandlerStack::create($mockguzzlehandler);
$httpclient = new http_client(['handler' => $handlerstack]);
// Create events sink.
$sink = $this->redirectEvents();
// Create sender.
$moodlenetclient = new moodlenet_client($httpclient, $this->mockoauthclient);
$coursesender = new course_sender(
$this->course->id,
$USER->id,
$moodlenetclient,
$this->mockoauthclient,
resource_sender::SHARE_FORMAT_BACKUP
);
if (isset($expected['exception'])) {
$this->expectException(ClientException::class);
$this->expectExceptionMessage($expected['exception']);
}
// Call the API.
$result = $coursesender->share_resource();
// Verify the result.
$this->assertEquals($expected['response_code'], $result['responsecode']);
$this->assertEquals($expected['resource_url'], $result['drafturl']);
// Verify the events.
$events = $sink->get_events();
$event = end($events);
$this->assertInstanceOf('\core\event\moodlenet_resource_exported', $event);
$this->assertEquals($USER->id, $event->userid);
if ($result['responsecode'] == 201) {
$description = "The user with id '{$USER->id}' successfully shared course to MoodleNet with the " .
"following course id, from context with id '{$this->coursecontext->id}': '{$this->course->id}'.";
} else {
$description = "The user with id '{$USER->id}' failed to share course to MoodleNet with the " .
"following course id, from context with id '{$this->coursecontext->id}': '{$this->course->id}'.";
}
$this->assertEquals($description, $event->get_description());
}
/**
* Provider for test share_resource().
*
* @return array Test data.
*/
public static function share_resource_provider(): array {
return [
'Success' => [
'httpresponse' => new Response(
201,
['Content-Type' => 'application/json'],
json_encode([
'homepage' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_1.mbz',
]),
),
'expected' => [
'response_code' => 201,
'resource_url' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_1.mbz',
],
],
'Fail with 200 status code' => [
'httpresponse' => new Response(
200,
['Content-Type' => 'application/json'],
json_encode([
'homepage' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_2.mbz',
]),
),
'expected' => [
'response_code' => 200,
'resource_url' => 'https://moodlenet.example.com/drafts/view/testcourse_backup_2.mbz',
],
],
'Fail with 401 status code' => [
'httpresponse' => new Response(
401,
),
'expected' => [
'response_code' => 401,
'resource_url' => '',
'exception' => 'Client error: ' .
'`POST https://moodlenet.example.com/.pkg/@moodlenet/ed-resource/basic/v1/create` ' .
'resulted in a `401 Unauthorized` response',
],
],
'Fail with 404 status code' => [
'httpresponse' => new Response(
404,
),
'expected' => [
'response_code' => 404,
'resource_url' => '',
'exception' => 'Client error: '.
'`POST https://moodlenet.example.com/.pkg/@moodlenet/ed-resource/basic/v1/create` ' .
'resulted in a `404 Not Found` response',
],
],
];
}
}
-52
View File
@@ -1,52 +0,0 @@
<?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\moodlenet;
use core\oauth2\issuer;
/**
* Helper for tests related to MoodleNet integration.
*
* @package core
* @copyright 2023 Michael Hawkins <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helpers {
/**
* Create and return a mock MoodleNet issuer.
*
* @param int $enabled Whether the issuer is enabled.
* @return issuer The issuer that has been created.
*/
public static function get_mock_issuer(int $enabled): issuer {
$record = (object) [
'name' => 'MoodleNet',
'image' => 'https://moodle.net/favicon.ico',
'baseurl' => 'https://moodlenet.example.com',
'loginscopes' => '',
'loginscopesoffline' => '',
'loginparamsoffline' => '',
'showonloginpage' => issuer::SERVICEONLY,
'servicetype' => 'moodlenet',
'enabled' => $enabled,
];
$issuer = new issuer(0, $record);
$issuer->create();
return $issuer;
}
}
@@ -1,134 +0,0 @@
<?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\moodlenet;
use core\moodlenet\share_recorder;
/**
* Test coverage for moodlenet share recorder.
*
* @package core
* @copyright 2023 David Woloszyn <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \core\moodlenet\share_recorder
*/
final class share_recorder_test extends \advanced_testcase {
/**
* Test inserting and updating an activity share progress to MoodleNet.
*
* @covers ::insert_share_progress
* @covers ::update_share_progress
*/
public function test_activity_share_progress(): void {
global $DB, $USER;
$this->resetAfterTest();
$courseid = 10;
$cmid = 20;
$resourceurl = 'https://moodlenet.test/files/testresource.mbz';
// Insert the activity share progress and test the returned id.
$shareid = share_recorder::insert_share_progress(share_recorder::TYPE_ACTIVITY, $USER->id, $courseid, $cmid);
$this->assertNotNull($shareid);
// Test we have set the fields correctly.
$record = $DB->get_record('moodlenet_share_progress', ['id' => $shareid]);
$this->assertEquals(share_recorder::TYPE_ACTIVITY, $record->type);
$this->assertEquals(share_recorder::STATUS_IN_PROGRESS, $record->status);
$this->assertEquals($courseid, $record->courseid);
$this->assertEquals($cmid, $record->cmid);
$this->assertTimeCurrent($record->timecreated);
$this->assertEquals($USER->id, $record->userid);
// Update the record with the returned data from MoodleNet.
share_recorder::update_share_progress($shareid, share_recorder::STATUS_SENT, $resourceurl);
// Test we have set the fields correctly.
$record = $DB->get_record('moodlenet_share_progress', ['id' => $shareid]);
$this->assertEquals($resourceurl, $record->resourceurl);
$this->assertEquals(share_recorder::STATUS_SENT, $record->status);
}
/**
* Test inserting and updating a course share progress to MoodleNet.
* We will also force an error status and test that too.
*
* @covers ::insert_share_progress
* @covers ::update_share_progress
*/
public function test_course_share_progress(): void {
global $DB, $USER;
$this->resetAfterTest();
$courseid = 10;
// Insert the course share progress and test the returned id.
$shareid = share_recorder::insert_share_progress(share_recorder::TYPE_COURSE, $USER->id, $courseid);
$this->assertNotNull($shareid);
// Test we have set the fields correctly (we expect cmid to be null for course shares).
$record = $DB->get_record('moodlenet_share_progress', ['id' => $shareid]);
$this->assertEquals(share_recorder::TYPE_COURSE, $record->type);
$this->assertEquals(share_recorder::STATUS_IN_PROGRESS, $record->status);
$this->assertEquals($courseid, $record->courseid);
$this->assertNull($record->cmid);
$this->assertTimeCurrent($record->timecreated);
$this->assertEquals($USER->id, $record->userid);
// Update the record, but let's test with an error status.
share_recorder::update_share_progress($shareid, share_recorder::STATUS_ERROR);
// Test we have set the field correctly.
$record = $DB->get_record('moodlenet_share_progress', ['id' => $shareid]);
$this->assertEquals(share_recorder::STATUS_ERROR, $record->status);
}
/**
* Tests the share type is one of the allowed values.
*
* @covers ::get_allowed_share_types
*/
public function test_invalid_share_type(): void {
global $USER;
$this->resetAfterTest();
$courseid = 10;
$invalidsharetype = 99;
$this->expectException(\moodle_exception::class);
share_recorder::insert_share_progress($invalidsharetype, $USER->id, $courseid);
}
/**
* Tests the share status is one of the allowed values.
*
* @covers ::get_allowed_share_statuses
*/
public function test_invalid_share_status(): void {
global $USER;
$this->resetAfterTest();
$courseid = 10;
$invalidsharestatus = 66;
$recordid = share_recorder::insert_share_progress(share_recorder::TYPE_COURSE, $USER->id, $courseid);
$this->expectException(\moodle_exception::class);
share_recorder::update_share_progress($recordid, $invalidsharestatus);
}
}
@@ -1,193 +0,0 @@
<?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\moodlenet;
use context_course;
use stdClass;
use testing_data_generator;
/**
* Unit tests for {@see utilities}.
*
* @coversDefaultClass \core\moodlenet\utilities
* @package core
* @copyright 2023 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class utilities_test extends \advanced_testcase {
/** @var testing_data_generator Data generator. */
private testing_data_generator $generator;
/** @var stdClass Activity object, */
private stdClass $course;
/** @var context_course Course context instance. */
private context_course $coursecontext;
/**
* Set up function for tests.
*/
protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->generator = $this->getDataGenerator();
$this->course = $this->generator->create_course();
$this->coursecontext = context_course::instance($this->course->id);
}
/**
* Test is_valid_instance method.
*
* @covers ::is_valid_instance
* @return void
*/
public function test_is_valid_instance(): void {
global $CFG;
$this->setAdminUser();
// Create dummy issuer.
$issuer = new \core\oauth2\issuer(0);
$issuer->set('enabled', 0);
$issuer->set('servicetype', 'google');
// Can not share if the experimental flag it set to false.
$CFG->enablesharingtomoodlenet = false;
$this->assertFalse(utilities::is_valid_instance($issuer));
// Enable the experimental flag.
$CFG->enablesharingtomoodlenet = true;
// Can not share if the OAuth 2 service in the outbound setting is not matched the given one.
set_config('oauthservice', random_int(1, 30), 'moodlenet');
$this->assertFalse(utilities::is_valid_instance($issuer));
// Can not share if the OAuth 2 service in the outbound setting is not enabled.
set_config('oauthservice', $issuer->get('id'), 'moodlenet');
$this->assertFalse(utilities::is_valid_instance($issuer));
// Can not share if the OAuth 2 service type is not moodlenet.
$issuer->set('enabled', 1);
$this->assertFalse(utilities::is_valid_instance($issuer));
// All good now.
$issuer->set('servicetype', 'moodlenet');
$this->assertTrue(utilities::is_valid_instance($issuer));
}
/**
* Test can_user_share method.
*
* @covers ::can_user_share
* @return void
*/
public function test_can_user_share(): void {
global $DB;
// Generate data.
$student1 = $this->generator->create_user();
$teacher1 = $this->generator->create_user();
$teacher2 = $this->generator->create_user();
$manager1 = $this->generator->create_user();
// Enrol users.
$this->generator->enrol_user($student1->id, $this->course->id, 'student');
$this->generator->enrol_user($teacher1->id, $this->course->id, 'teacher');
$this->generator->enrol_user($teacher2->id, $this->course->id, 'editingteacher');
$this->generator->enrol_user($manager1->id, $this->course->id, 'manager');
// Get roles.
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher'], 'id', MUST_EXIST);
$editingteacherrole = $DB->get_record('role', ['shortname' => 'editingteacher'], 'id', MUST_EXIST);
// Test with default settings.
// Student and Teacher cannot share the activity.
$this->assertFalse(utilities::can_user_share($this->coursecontext, $student1->id));
$this->assertFalse(utilities::can_user_share($this->coursecontext, $teacher1->id));
// Editing-teacher and Manager can share the activity.
$this->assertTrue(utilities::can_user_share($this->coursecontext, $teacher2->id));
$this->assertTrue(utilities::can_user_share($this->coursecontext, $manager1->id));
// Teacher who has the capabilities can share the activity.
assign_capability('moodle/moodlenet:shareactivity', CAP_ALLOW, $teacherrole->id, $this->coursecontext);
assign_capability('moodle/backup:backupactivity', CAP_ALLOW, $teacherrole->id, $this->coursecontext);
$this->assertTrue(utilities::can_user_share($this->coursecontext, $teacher1->id));
// Editing-teacher who does not have the capabilities can not share the activity.
assign_capability('moodle/moodlenet:shareactivity', CAP_PROHIBIT, $editingteacherrole->id, $this->coursecontext);
$this->assertFalse(utilities::can_user_share($this->coursecontext, $teacher2->id));
// Test with default settings for course.
// Student and Teacher cannot share the course.
$this->assertFalse(utilities::can_user_share($this->coursecontext, $student1->id, 'course'));
$this->assertFalse(utilities::can_user_share($this->coursecontext, $teacher1->id, 'course'));
// Editing-teacher and Manager can share the course.
$this->assertTrue(utilities::can_user_share($this->coursecontext, $teacher2->id, 'course'));
$this->assertTrue(utilities::can_user_share($this->coursecontext, $manager1->id, 'course'));
// Teacher who has the capabilities can share the course.
assign_capability('moodle/moodlenet:sharecourse', CAP_ALLOW, $teacherrole->id, $this->coursecontext);
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $teacherrole->id, $this->coursecontext);
$this->assertTrue(utilities::can_user_share($this->coursecontext, $teacher1->id, 'course'));
// Editing-teacher who does not have the capabilities can not share the course.
assign_capability('moodle/moodlenet:sharecourse', CAP_PROHIBIT, $editingteacherrole->id, $this->coursecontext);
$this->assertFalse(utilities::can_user_share($this->coursecontext, $teacher2->id, 'course'));
}
/**
* Test does_user_have_capability_in_any_course method.
*
* @covers ::does_user_have_capability_in_any_course
* @return void
*/
public function test_does_user_have_capability_in_any_course(): void {
global $DB;
// Prepare data.
$teacher1 = $this->generator->create_user();
$student1 = $this->generator->create_user();
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher'], 'id', MUST_EXIST);
$studentrole = $DB->get_record('role', ['shortname' => 'student'], 'id', MUST_EXIST);
// Enrol users,
$this->generator->enrol_user($teacher1->id, $this->course->id, $teacherrole->id);
$this->generator->enrol_user($student1->id, $this->course->id, $studentrole->id);
// Assign a valid capability to the teacher.
assign_capability('moodle/moodlenet:shareactivity', CAP_ALLOW, $teacherrole->id, $this->coursecontext);
// Check the method's results are as expected (this is cached).
$this->assertSame('yes', utilities::does_user_have_capability_in_any_course($teacher1->id));
$this->assertSame('no', utilities::does_user_have_capability_in_any_course($student1->id));
// Compare to cache.
$teachercachedvalue = \cache::make('core', 'moodlenet_usercanshare')->get($teacher1->id);
$this->assertSame('yes', $teachercachedvalue);
$studentcachedvalue = \cache::make('core', 'moodlenet_usercanshare')->get($student1->id);
$this->assertSame('no', $studentcachedvalue);
// Change the teacher's role and check the moodlenet_usercanshare cache is invalidated for everyone.
$this->generator->role_assign($studentrole->id, $teacher1->id, $this->coursecontext->id);
$teachercachedvalue = \cache::make('core', 'moodlenet_usercanshare')->get($teacher1->id);
$this->assertFalse($teachercachedvalue);
$studentcachedvalue = \cache::make('core', 'moodlenet_usercanshare')->get($student1->id);
$this->assertFalse($studentcachedvalue);
}
}
+26 -131
View File
@@ -20,7 +20,6 @@ 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;
use core\moodlenet\share_recorder;
/**
* Privacy provider tests class.
@@ -40,30 +39,17 @@ final class provider_test extends provider_testcase {
*/
public function test_get_contexts_for_userid(): void {
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
// Check that there are no contexts used for the user yet.
$this->assertEmpty(provider::get_contexts_for_userid($user1->id));
$user = $this->getDataGenerator()->create_user();
// Insert a record.
$this->insert_dummy_moodlenet_share_progress_record($user1->id);
$this->insert_dummy_shortlink_record($user2->id);
$this->insert_dummy_shortlink_record($user->id);
// Check that we only get back one context for user1.
$contextlist = provider::get_contexts_for_userid($user1->id);
// Check that we only get back one context for user.
$contextlist = provider::get_contexts_for_userid($user->id);
$this->assertCount(1, $contextlist);
// Check that the context returned is the expected one.
$usercontext = \context_user::instance($user1->id);
$this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]);
// Check that we only get back one context for user2.
$contextlist = provider::get_contexts_for_userid($user2->id);
$this->assertCount(1, $contextlist);
// Check that the context returned is the expected one.
$usercontext = \context_user::instance($user2->id);
$usercontext = \context_user::instance($user->id);
$this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]);
}
@@ -76,46 +62,22 @@ final class provider_test extends provider_testcase {
$this->resetAfterTest();
// Create some users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$usercontext1 = \context_user::instance($user1->id);
$usercontext2 = \context_user::instance($user2->id);
$usercontext3 = \context_user::instance($user3->id);
$user = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
// Get userlists and check they are empty for now.
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, 'core');
provider::get_users_in_context($userlist1);
$this->assertCount(0, $userlist1);
$userlist = new \core_privacy\local\request\userlist($usercontext, 'core');
provider::get_users_in_context($userlist);
$this->assertCount(0, $userlist);
$userlist2 = new \core_privacy\local\request\userlist($usercontext2, 'core');
provider::get_users_in_context($userlist2);
$this->assertCount(0, $userlist2);
$userlist3 = new \core_privacy\local\request\userlist($usercontext3, 'core');
provider::get_users_in_context($userlist3);
$this->assertCount(0, $userlist3);
// Insert records for both users.
$this->insert_dummy_moodlenet_share_progress_record($user1->id);
$this->insert_dummy_moodlenet_share_progress_record($user2->id);
$this->insert_dummy_shortlink_record($user3->id);
// Insert records for the user.
$this->insert_dummy_shortlink_record($user->id);
// Check the userlists contain the correct users.
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, 'core');
provider::get_users_in_context($userlist1);
$this->assertCount(1, $userlist1);
$this->assertEquals($user1->id, $userlist1->get_userids()[0]);
$userlist2 = new \core_privacy\local\request\userlist($usercontext2, 'core');
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
$this->assertEquals($user2->id, $userlist2->get_userids()[0]);
$userlist3 = new \core_privacy\local\request\userlist($usercontext3, 'core');
provider::get_users_in_context($userlist3);
$this->assertCount(1, $userlist3);
$this->assertEquals($user3->id, $userlist3->get_userids()[0]);
$userlist = new \core_privacy\local\request\userlist($usercontext, 'core');
provider::get_users_in_context($userlist);
$this->assertCount(1, $userlist);
$this->assertEquals($user->id, $userlist->get_userids()[0]);
}
/**
@@ -127,61 +89,29 @@ final class provider_test extends provider_testcase {
global $DB;
$this->resetAfterTest();
// Create some users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
// Create user.
$user = $this->getDataGenerator()->create_user();
// Insert a record for each user.
$this->insert_dummy_moodlenet_share_progress_record($user1->id);
$this->insert_dummy_moodlenet_share_progress_record($user2->id);
$this->insert_dummy_shortlink_record($user3->id);
$subcontexts = [
get_string('privacy:metadata:moodlenet_share_progress', 'moodle')
];
// Check if user1 has any exported data yet.
$usercontext1 = \context_user::instance($user1->id);
$writer = writer::with_context($usercontext1);
$this->assertFalse($writer->has_any_data());
// Export user1's data and check the count.
$approvedlist = new approved_contextlist($user1, 'core', [$usercontext1->id]);
provider::export_user_data($approvedlist);
$data = (array)$writer->get_data($subcontexts);
$this->assertCount(1, $data);
// Get the inserted data.
$userdata = $DB->get_record('moodlenet_share_progress', ['userid' => $user1->id]);
// Check exported data against the inserted data.
$this->assertEquals($userdata->id, reset($data)->id);
$this->assertEquals($userdata->type, reset($data)->type);
$this->assertEquals($userdata->courseid, reset($data)->courseid);
$this->assertEquals($userdata->cmid, reset($data)->cmid);
$this->assertEquals($userdata->userid, reset($data)->userid);
$this->assertEquals($userdata->timecreated, reset($data)->timecreated);
$this->assertEquals($userdata->resourceurl, reset($data)->resourceurl);
$this->assertEquals($userdata->status, reset($data)->status);
// Insert a record for the user.
$this->insert_dummy_shortlink_record($user->id);
$subcontexts = [
get_string('privacy:metadata:shortlink', 'moodle')
];
// Check if user3 has any exported data yet.
$usercontext3 = \context_user::instance($user3->id);
$writer = writer::with_context($usercontext3);
// Check if user has any exported data yet.
$usercontext = \context_user::instance($user->id);
$writer = writer::with_context($usercontext);
$this->assertFalse($writer->has_any_data());
// Export user3's data and check the count.
$approvedlist = new approved_contextlist($user3, 'core', [$usercontext3->id]);
// Export user's data and check the count.
$approvedlist = new approved_contextlist($user, 'core', [$usercontext->id]);
provider::export_user_data($approvedlist);
$data = (array)$writer->get_data($subcontexts);
$this->assertCount(1, $data);
// Get the inserted data.
$userdata = $DB->get_record('shortlink', ['userid' => $user3->id]);
$userdata = $DB->get_record('shortlink', ['userid' => $user->id]);
// Check exported data against the inserted data.
$this->assertEquals($userdata->id, reset($data)->id);
@@ -206,14 +136,10 @@ final class provider_test extends provider_testcase {
$user2 = $this->getDataGenerator()->create_user();
// Insert a record for each user.
$this->insert_dummy_moodlenet_share_progress_record($user1->id);
$this->insert_dummy_moodlenet_share_progress_record($user2->id);
$this->insert_dummy_shortlink_record($user1->id);
$this->insert_dummy_shortlink_record($user2->id);
// Get all users' data.
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(2, $usersdata);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(2, $usersdata);
@@ -222,9 +148,6 @@ final class provider_test extends provider_testcase {
provider::delete_data_for_all_users_in_context($usercontext1);
// Check what is remaining belongs to user2.
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(1, $usersdata);
$this->assertEquals($user2->id, reset($usersdata)->userid);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(1, $usersdata);
$this->assertEquals($user2->id, reset($usersdata)->userid);
@@ -244,14 +167,10 @@ final class provider_test extends provider_testcase {
$user2 = $this->getDataGenerator()->create_user();
// Insert a record for each user.
$this->insert_dummy_moodlenet_share_progress_record($user1->id);
$this->insert_dummy_moodlenet_share_progress_record($user2->id);
$this->insert_dummy_shortlink_record($user1->id);
$this->insert_dummy_shortlink_record($user2->id);
// Get all users' data.
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(2, $usersdata);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(2, $usersdata);
@@ -261,9 +180,6 @@ final class provider_test extends provider_testcase {
provider::delete_data_for_user($approvedlist);
// Check what is remaining belongs to user2.
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(1, $usersdata);
$this->assertEquals($user2->id, reset($usersdata)->userid);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(1, $usersdata);
$this->assertEquals($user2->id, reset($usersdata)->userid);
@@ -285,22 +201,16 @@ final class provider_test extends provider_testcase {
$usercontext2 = \context_user::instance($user2->id);
// Insert a record for each user.
$this->insert_dummy_moodlenet_share_progress_record($user1->id);
$this->insert_dummy_moodlenet_share_progress_record($user2->id);
$this->insert_dummy_shortlink_record($user1->id);
$this->insert_dummy_shortlink_record($user2->id);
// Check the count on all user's data.
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(2, $usersdata);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(2, $usersdata);
// Attempt to delete data for user1 using user2's context (should have no effect).
$approvedlist = new approved_userlist($usercontext2, 'core', [$user1->id]);
provider::delete_data_for_users($approvedlist);
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(2, $usersdata);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(2, $usersdata);
@@ -309,26 +219,11 @@ final class provider_test extends provider_testcase {
provider::delete_data_for_users($approvedlist);
// Check what is remaining belongs to user2.
$usersdata = $DB->get_records('moodlenet_share_progress', []);
$this->assertCount(1, $usersdata);
$this->assertEquals($user2->id, reset($usersdata)->userid);
$usersdata = $DB->get_records('shortlink', []);
$this->assertCount(1, $usersdata);
$this->assertEquals($user2->id, reset($usersdata)->userid);
}
/**
* Helper function to insert a MoodleNet share progress record for use in the tests.
*
* @param int $userid The ID of the user to link the record to.
*/
protected function insert_dummy_moodlenet_share_progress_record(int $userid): void {
$sharetype = share_recorder::TYPE_ACTIVITY;
$courseid = 123;
$cmid = 456;
share_recorder::insert_share_progress($sharetype, $userid, $courseid, $cmid);
}
/**
* Helper function to insert a shortlink record for use in the tests.
*