first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+810
View File
@@ -0,0 +1,810 @@
<?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 tool_policy;
use tool_policy\test\helper;
/**
* Unit tests for the {@link \tool_policy\api} class.
*
* @package tool_policy
* @category test
* @copyright 2018 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class api_test extends \advanced_testcase {
/**
* Test the common operations with a policy document and its versions.
*/
public function test_policy_document_life_cycle(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Prepare the form data for adding a new policy document.
$formdata = api::form_policydoc_data(new policy_version(0));
$this->assertObjectHasProperty('name', $formdata);
$this->assertArrayHasKey('text', $formdata->summary_editor);
$this->assertArrayHasKey('format', $formdata->content_editor);
// Save the form.
$formdata->name = 'Test terms & conditions';
$formdata->type = policy_version::TYPE_OTHER;
$policy = api::form_policydoc_add($formdata);
$record = $policy->to_record();
$this->assertNotEmpty($record->id);
$this->assertNotEmpty($record->policyid);
$this->assertNotEmpty($record->timecreated);
$this->assertNotEmpty($record->timemodified);
$this->assertNotNull($record->name);
$this->assertNotNull($record->summary);
$this->assertNotNull($record->summaryformat);
$this->assertNotNull($record->content);
$this->assertNotNull($record->contentformat);
// Update the policy document version.
$formdata = api::form_policydoc_data($policy);
$formdata->revision = '*** Unit test ***';
$formdata->summary_editor['text'] = '__Just a summary__';
$formdata->summary_editor['format'] = FORMAT_MARKDOWN;
$formdata->content_editor['text'] = '### Just a test ###';
$formdata->content_editor['format'] = FORMAT_MARKDOWN;
$updated = api::form_policydoc_update_overwrite($formdata);
$this->assertEquals($policy->get('id'), $updated->get('id'));
$this->assertEquals($policy->get('policyid'), $updated->get('policyid'));
// Save form as a new version.
$formdata = api::form_policydoc_data($policy);
$formdata->name = 'New terms & conditions';
$formdata->revision = '*** Unit test 2 ***';
$formdata->summary_editor['text'] = '<strong>Yet another summary</strong>';
$formdata->summary_editor['format'] = FORMAT_MOODLE;
$formdata->content_editor['text'] = '<h3>Yet another test</h3>';
$formdata->content_editor['format'] = FORMAT_HTML;
$new = api::form_policydoc_update_new($formdata);
$this->assertNotEquals($policy->get('id'), $new->get('id'));
$this->assertEquals($policy->get('policyid'), $new->get('policyid'));
// Add yet another policy document.
$formdata = api::form_policydoc_data(new policy_version(0));
$formdata->name = 'Privacy terms';
$formdata->type = policy_version::TYPE_PRIVACY;
$another = api::form_policydoc_add($formdata);
// Get the list of all policies and their versions.
$docs = api::list_policies();
$this->assertEquals(2, count($docs));
// Get just one policy and all its versions.
$docs = api::list_policies($another->get('policyid'));
$this->assertEquals(1, count($docs));
// Activate a policy.
$this->assertEquals(0, count(api::list_current_versions()));
api::make_current($updated->get('id'));
$current = api::list_current_versions();
$this->assertEquals(1, count($current));
$first = reset($current);
$this->assertEquals('Test terms &amp; conditions', $first->name);
// Activate another policy version.
api::make_current($new->get('id'));
$current = api::list_current_versions();
$this->assertEquals(1, count($current));
$first = reset($current);
$this->assertEquals('New terms &amp; conditions', $first->name);
// Inactivate the policy.
api::inactivate($new->get('policyid'));
$this->assertEmpty(api::list_current_versions());
$archived = api::get_policy_version($new->get('id'));
$this->assertEquals(policy_version::STATUS_ARCHIVED, $archived->status);
// Create a new draft from an archived version.
$draft = api::revert_to_draft($archived->id);
$draft = api::get_policy_version($draft->get('id'));
$archived = api::get_policy_version($archived->id);
$this->assertEmpty(api::list_current_versions());
$this->assertNotEquals($draft->id, $archived->id);
$this->assertEquals(policy_version::STATUS_DRAFT, $draft->status);
$this->assertEquals(policy_version::STATUS_ARCHIVED, $archived->status);
// An active policy can't be set to draft.
api::make_current($draft->id);
$this->expectException('coding_exception');
$this->expectExceptionMessage('Version not found or is not archived');
api::revert_to_draft($draft->id);
}
/**
* Test changing the sort order of the policy documents.
*/
public function test_policy_sortorder(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$formdata = api::form_policydoc_data(new policy_version(0));
$formdata->name = 'Policy1';
$formdata->summary_editor = ['text' => 'P1 summary', 'format' => FORMAT_HTML, 'itemid' => 0];
$formdata->content_editor = ['text' => 'P1 content', 'format' => FORMAT_HTML, 'itemid' => 0];
$policy1 = api::form_policydoc_add($formdata);
$policy1sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy1->get('policyid')]);
$formdata = api::form_policydoc_data(new policy_version(0));
$formdata->name = 'Policy2';
$formdata->summary_editor = ['text' => 'P2 summary', 'format' => FORMAT_HTML, 'itemid' => 0];
$formdata->content_editor = ['text' => 'P2 content', 'format' => FORMAT_HTML, 'itemid' => 0];
$policy2 = api::form_policydoc_add($formdata);
$policy2sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy2->get('policyid')]);
$this->assertTrue($policy1sortorder < $policy2sortorder);
$formdata = api::form_policydoc_data(new policy_version(0));
$formdata->name = 'Policy3';
$formdata->summary_editor = ['text' => 'P3 summary', 'format' => FORMAT_HTML, 'itemid' => 0];
$formdata->content_editor = ['text' => 'P3 content', 'format' => FORMAT_HTML, 'itemid' => 0];
$policy3 = api::form_policydoc_add($formdata);
$policy3sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy3->get('policyid')]);
$this->assertTrue($policy1sortorder < $policy2sortorder);
$this->assertTrue($policy2sortorder < $policy3sortorder);
api::move_up($policy3->get('policyid'));
$policy1sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy1->get('policyid')]);
$policy2sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy2->get('policyid')]);
$policy3sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy3->get('policyid')]);
$this->assertTrue($policy1sortorder < $policy3sortorder);
$this->assertTrue($policy3sortorder < $policy2sortorder);
api::move_down($policy1->get('policyid'));
$policy1sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy1->get('policyid')]);
$policy2sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy2->get('policyid')]);
$policy3sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy3->get('policyid')]);
$this->assertTrue($policy3sortorder < $policy1sortorder);
$this->assertTrue($policy1sortorder < $policy2sortorder);
$orderedlist = [];
foreach (api::list_policies() as $policy) {
$orderedlist[] = $policy->id;
}
$this->assertEquals([$policy3->get('policyid'), $policy1->get('policyid'), $policy2->get('policyid')], $orderedlist);
}
/**
* Test that list of policies can be filtered by audience
*/
public function test_list_policies_audience(): void {
$this->resetAfterTest();
$this->setAdminUser();
$policy1 = helper::add_policy(['audience' => policy_version::AUDIENCE_LOGGEDIN]);
$policy2 = helper::add_policy(['audience' => policy_version::AUDIENCE_GUESTS]);
$policy3 = helper::add_policy();
api::make_current($policy1->get('id'));
api::make_current($policy2->get('id'));
api::make_current($policy3->get('id'));
$list = array_map(function ($version) {
return $version->policyid;
}, api::list_current_versions());
$this->assertEquals([$policy1->get('policyid'), $policy2->get('policyid'), $policy3->get('policyid')],
array_values($list));
$ids = api::get_current_versions_ids();
$this->assertEquals([$policy1->get('policyid') => $policy1->get('id'),
$policy2->get('policyid') => $policy2->get('id'),
$policy3->get('policyid') => $policy3->get('id')], $ids);
$list = array_map(function ($version) {
return $version->policyid;
}, api::list_current_versions(policy_version::AUDIENCE_LOGGEDIN));
$this->assertEquals([$policy1->get('policyid'), $policy3->get('policyid')], array_values($list));
$ids = api::get_current_versions_ids(policy_version::AUDIENCE_LOGGEDIN);
$this->assertEquals([$policy1->get('policyid') => $policy1->get('id'),
$policy3->get('policyid') => $policy3->get('id')], $ids);
$list = array_map(function ($version) {
return $version->policyid;
}, api::list_current_versions(policy_version::AUDIENCE_GUESTS));
$this->assertEquals([$policy2->get('policyid'), $policy3->get('policyid')], array_values($list));
$ids = api::get_current_versions_ids(policy_version::AUDIENCE_GUESTS);
$this->assertEquals([$policy2->get('policyid') => $policy2->get('id'),
$policy3->get('policyid') => $policy3->get('id')], $ids);
}
/**
* Test behaviour of the {@link api::can_user_view_policy_version()} method.
*/
public function test_can_user_view_policy_version(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$child = $this->getDataGenerator()->create_user();
$parent = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->create_user();
$officer = $this->getDataGenerator()->create_user();
$manager = $this->getDataGenerator()->create_user();
$syscontext = \context_system::instance();
$childcontext = \context_user::instance($child->id);
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
$roleofficerid = create_role('Policy officer', 'policyofficer', 'Can see all acceptances but can\'t edit policy documents');
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
assign_capability('tool/policy:viewacceptances', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
role_assign($roleminorid, $child->id, $syscontext->id);
// Becoming a parent is easy. Being a good one is difficult.
role_assign($roleparentid, $parent->id, $childcontext->id);
role_assign($roleofficerid, $officer->id, $syscontext->id);
role_assign($rolemanagerid, $manager->id, $syscontext->id);
accesslib_clear_all_caches_for_unit_testing();
// Prepare a policy document with some versions.
list($policy1, $policy2, $policy3) = helper::create_versions(3);
// Normally users do not have access to policy drafts.
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $child->id));
$this->assertFalse(api::can_user_view_policy_version($policy2, null, $parent->id));
$this->assertFalse(api::can_user_view_policy_version($policy3, null, $CFG->siteguest));
// Officers and managers have access even to drafts.
$this->assertTrue(api::can_user_view_policy_version($policy1, null, $officer->id));
$this->assertTrue(api::can_user_view_policy_version($policy3, null, $manager->id));
// Current versions are public so that users can decide whether to even register on such a site.
api::make_current($policy2->id);
$policy1 = api::get_policy_version($policy1->id);
$policy2 = api::get_policy_version($policy2->id);
$policy3 = api::get_policy_version($policy3->id);
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $child->id));
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $child->id));
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $CFG->siteguest));
$this->assertFalse(api::can_user_view_policy_version($policy3, null, $child->id));
// Let the parent accept the policy on behalf of her child.
$this->setUser($parent);
api::accept_policies($policy2->id, $child->id);
// Release a new version of the policy.
api::make_current($policy3->id);
$policy1 = api::get_policy_version($policy1->id);
$policy2 = api::get_policy_version($policy2->id);
$policy3 = api::get_policy_version($policy3->id);
api::get_user_minors($parent->id);
// They should now have access to the archived version (because they agreed) and the current one.
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $child->id));
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $parent->id));
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $child->id));
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $parent->id));
$this->assertTrue(api::can_user_view_policy_version($policy3, null, $child->id));
$this->assertTrue(api::can_user_view_policy_version($policy3, null, $parent->id));
}
/**
* Test behaviour of the {@link api::can_accept_policies()} method.
*/
public function test_can_accept_policies(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$child = $this->getDataGenerator()->create_user();
$parent = $this->getDataGenerator()->create_user();
$officer = $this->getDataGenerator()->create_user();
$manager = $this->getDataGenerator()->create_user();
$syscontext = \context_system::instance();
$childcontext = \context_user::instance($child->id);
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
$roleofficerid = create_role('Policy officer', 'policyofficer', 'Can see all acceptances but can\'t edit policy documents');
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:viewacceptances', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $syscontext->id);
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
role_assign($roleminorid, $child->id, $syscontext->id);
role_assign($roleparentid, $parent->id, $childcontext->id);
role_assign($roleofficerid, $officer->id, $syscontext->id);
role_assign($rolemanagerid, $manager->id, $syscontext->id);
accesslib_clear_all_caches_for_unit_testing();
$policy1 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
$policy2 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
$policy3 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
$policy4 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
$mixed = [$policy1->id, $policy2->id, $policy3->id, $policy4->id];
$compulsory = [$policy1->id, $policy2->id];
$optional = [$policy3->id, $policy4->id];
// Normally users can accept all policies.
$this->setUser($user);
$this->assertTrue(api::can_accept_policies($mixed));
$this->assertTrue(api::can_accept_policies($compulsory));
$this->assertTrue(api::can_accept_policies($optional));
// Digital minors can be set to not be able to accept policies themselves.
$this->setUser($child);
$this->assertFalse(api::can_accept_policies($mixed));
$this->assertFalse(api::can_accept_policies($compulsory));
$this->assertFalse(api::can_accept_policies($optional));
// The parent can accept optional policies on child's behalf.
$this->setUser($parent);
$this->assertTrue(api::can_accept_policies($mixed, $child->id));
$this->assertTrue(api::can_accept_policies($compulsory, $child->id));
$this->assertTrue(api::can_accept_policies($optional, $child->id));
// Officers and managers can accept on other user's behalf.
$this->setUser($officer);
$this->assertTrue(api::can_accept_policies($mixed, $parent->id));
$this->assertTrue(api::can_accept_policies($compulsory, $parent->id));
$this->assertTrue(api::can_accept_policies($optional, $parent->id));
$this->setUser($manager);
$this->assertTrue(api::can_accept_policies($mixed, $parent->id));
$this->assertTrue(api::can_accept_policies($compulsory, $parent->id));
$this->assertTrue(api::can_accept_policies($optional, $parent->id));
}
/**
* Test behaviour of the {@link api::can_decline_policies()} method.
*/
public function test_can_decline_policies(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$child = $this->getDataGenerator()->create_user();
$parent = $this->getDataGenerator()->create_user();
$officer = $this->getDataGenerator()->create_user();
$manager = $this->getDataGenerator()->create_user();
$syscontext = \context_system::instance();
$childcontext = \context_user::instance($child->id);
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
$roleofficerid = create_role('Policy officer', 'policyofficer', 'Can see all acceptances but can\'t edit policy documents');
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:viewacceptances', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $syscontext->id);
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
role_assign($roleminorid, $child->id, $syscontext->id);
role_assign($roleparentid, $parent->id, $childcontext->id);
role_assign($roleofficerid, $officer->id, $syscontext->id);
role_assign($rolemanagerid, $manager->id, $syscontext->id);
accesslib_clear_all_caches_for_unit_testing();
$policy1 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
$policy2 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
$policy3 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
$policy4 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
$mixed = [$policy1->id, $policy2->id, $policy3->id, $policy4->id];
$compulsory = [$policy1->id, $policy2->id];
$optional = [$policy3->id, $policy4->id];
// Normally users can decline only optional policies.
$this->setUser($user);
$this->assertFalse(api::can_decline_policies($mixed));
$this->assertFalse(api::can_decline_policies($compulsory));
$this->assertTrue(api::can_decline_policies($optional));
// If they can't accept them, they can't decline them too.
$this->setUser($child);
$this->assertFalse(api::can_decline_policies($mixed));
$this->assertFalse(api::can_decline_policies($compulsory));
$this->assertFalse(api::can_decline_policies($optional));
// The parent can decline optional policies on child's behalf.
$this->setUser($parent);
$this->assertFalse(api::can_decline_policies($mixed, $child->id));
$this->assertFalse(api::can_decline_policies($compulsory, $child->id));
$this->assertTrue(api::can_decline_policies($optional, $child->id));
// Even officers or managers cannot decline compulsory policies.
$this->setUser($officer);
$this->assertFalse(api::can_decline_policies($mixed));
$this->assertFalse(api::can_decline_policies($compulsory));
$this->assertTrue(api::can_decline_policies($optional));
$this->assertFalse(api::can_decline_policies($mixed, $child->id));
$this->assertFalse(api::can_decline_policies($compulsory, $child->id));
$this->assertTrue(api::can_decline_policies($optional, $child->id));
$this->setUser($manager);
$this->assertFalse(api::can_decline_policies($mixed));
$this->assertFalse(api::can_decline_policies($compulsory));
$this->assertTrue(api::can_decline_policies($optional));
$this->assertFalse(api::can_decline_policies($mixed, $child->id));
$this->assertFalse(api::can_decline_policies($compulsory, $child->id));
$this->assertTrue(api::can_decline_policies($optional, $child->id));
}
/**
* Test behaviour of the {@link api::can_revoke_policies()} method.
*/
public function test_can_revoke_policies(): void {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$child = $this->getDataGenerator()->create_user();
$parent = $this->getDataGenerator()->create_user();
$officer = $this->getDataGenerator()->create_user();
$manager = $this->getDataGenerator()->create_user();
$syscontext = \context_system::instance();
$childcontext = \context_user::instance($child->id);
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
$roleofficerid = create_role('Policy officer', 'policyofficer', 'Can see all acceptances but can\'t edit policy documents');
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:viewacceptances', CAP_ALLOW, $roleofficerid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $syscontext->id);
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
role_assign($roleminorid, $child->id, $syscontext->id);
// Becoming a parent is easy. Being a good one is difficult.
role_assign($roleparentid, $parent->id, $childcontext->id);
role_assign($roleofficerid, $officer->id, $syscontext->id);
role_assign($rolemanagerid, $manager->id, $syscontext->id);
accesslib_clear_all_caches_for_unit_testing();
$policy1 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
$policy2 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
$versionids = [$policy1->id, $policy2->id];
// Guests cannot revoke anything.
$this->setGuestUser();
$this->assertFalse(api::can_revoke_policies($versionids));
// Normally users do not have access to revoke policies.
$this->setUser($user);
$this->assertFalse(api::can_revoke_policies($versionids, $user->id));
$this->setUser($child);
$this->assertFalse(api::can_revoke_policies($versionids, $child->id));
// Optional policies can be revoked if the user can accept them.
$this->setUser($user);
$this->assertTrue(api::can_revoke_policies([$policy2->id]));
$this->assertTrue(api::can_revoke_policies([$policy2->id], $user->id));
$this->setUser($child);
$this->assertFalse(api::can_revoke_policies([$policy2->id]));
$this->assertFalse(api::can_revoke_policies([$policy2->id], $child->id));
// The parent can revoke the policy on behalf of her child (but not her own policies, unless they are optional).
$this->setUser($parent);
$this->assertFalse(api::can_revoke_policies($versionids, $parent->id));
$this->assertTrue(api::can_revoke_policies($versionids, $child->id));
$this->assertTrue(api::can_revoke_policies([$policy2->id]));
$this->assertTrue(api::can_revoke_policies([$policy2->id], $child->id));
// Officers and managers can revoke everything.
$this->setUser($officer);
$this->assertTrue(api::can_revoke_policies($versionids, $officer->id));
$this->assertTrue(api::can_revoke_policies($versionids, $child->id));
$this->assertTrue(api::can_revoke_policies($versionids, $parent->id));
$this->assertTrue(api::can_revoke_policies($versionids, $manager->id));
$this->setUser($manager);
$this->assertTrue(api::can_revoke_policies($versionids, $manager->id));
$this->assertTrue(api::can_revoke_policies($versionids, $child->id));
$this->assertTrue(api::can_revoke_policies($versionids, $parent->id));
$this->assertTrue(api::can_revoke_policies($versionids, $officer->id));
}
/**
* Test {@link api::fix_revision_values()} behaviour.
*/
public function test_fix_revision_values(): void {
$this->resetAfterTest();
$this->setAdminUser();
$versions = [
(object) ['id' => 80, 'timecreated' => mktime(1, 1, 1, 12, 28, 2018), 'revision' => '', 'e' => '28 December 2018'],
(object) ['id' => 70, 'timecreated' => mktime(1, 1, 1, 12, 27, 2018), 'revision' => '', 'e' => '27 December 2018 - v2'],
(object) ['id' => 60, 'timecreated' => mktime(1, 1, 1, 12, 27, 2018), 'revision' => '', 'e' => '27 December 2018 - v1'],
(object) ['id' => 50, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '0', 'e' => '0'],
(object) ['id' => 40, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '1.1', 'e' => '1.1 - v2'],
(object) ['id' => 30, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '1.1', 'e' => '1.1 - v1'],
(object) ['id' => 20, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '', 'e' => '26 December 2018'],
(object) ['id' => 10, 'timecreated' => mktime(17, 57, 00, 12, 25, 2018), 'revision' => '1.0', 'e' => '1.0'],
];
api::fix_revision_values($versions);
foreach ($versions as $version) {
$this->assertSame($version->revision, $version->e);
}
}
/**
* Test that accepting policy updates 'policyagreed'
*/
public function test_accept_policies(): void {
global $DB, $USER;
$this->resetAfterTest();
$this->setAdminUser();
$policy1 = helper::add_policy()->to_record();
api::make_current($policy1->id);
$policy2 = helper::add_policy()->to_record();
api::make_current($policy2->id);
$policy3 = helper::add_policy(['optional' => true])->to_record();
api::make_current($policy3->id);
// Accept policy on behalf of somebody else.
$user1 = $this->getDataGenerator()->create_user();
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Accepting just compulsory policies is not enough, we want to hear explicitly about the optional one, too.
api::accept_policies([$policy1->id, $policy2->id], $user1->id);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Optional policy does not need to be accepted, but it must be answered explicitly.
api::decline_policies([$policy3->id], $user1->id);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Revoke previous agreement to a compulsory policy.
api::revoke_acceptance($policy1->id, $user1->id);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Accept policies for oneself.
$user2 = $this->getDataGenerator()->create_user();
$this->setUser($user2);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
api::accept_policies([$policy1->id]);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
api::accept_policies([$policy2->id]);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
api::decline_policies([$policy3->id]);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
api::accept_policies([$policy3->id]);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
// Ensure policies are always accepted when all are responded regardless the $USER->policyagreed value.
$USER->policyagreed = 1;
$DB->set_field('user', 'policyagreed', 0, ['id' => $user2->id]);
api::accept_policies([$policy3->id]);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
}
/**
* Test that activating a new policy resets everybody's policyagreed flag in the database.
*/
public function test_reset_policyagreed(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$user1 = $this->getDataGenerator()->create_user();
// Introducing a new policy.
list($policy1v1, $policy1v2) = helper::create_versions(2);
api::make_current($policy1v1->id);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
api::accept_policies([$policy1v1->id], $user1->id);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Introducing another policy.
$policy2v1 = helper::add_policy()->to_record();
api::make_current($policy2v1->id);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
api::accept_policies([$policy2v1->id], $user1->id);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Updating an existing policy (major update).
api::make_current($policy1v2->id);
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
api::accept_policies([$policy1v2->id], $user1->id);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Do not touch the flag if there is no new version (e.g. a minor update).
api::make_current($policy2v1->id);
api::make_current($policy1v2->id);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Do not touch the flag if inactivating a policy.
api::inactivate($policy1v2->policyid);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
// Do not touch the flag if setting to draft a policy.
api::revert_to_draft($policy1v2->id);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
}
/**
* Test behaviour of the {@link api::get_user_minors()} method.
*/
public function test_get_user_minors(): void {
$this->resetAfterTest();
// A mother having two children, each child having own father.
$mother1 = $this->getDataGenerator()->create_user();
$father1 = $this->getDataGenerator()->create_user();
$father2 = $this->getDataGenerator()->create_user();
$child1 = $this->getDataGenerator()->create_user();
$child2 = $this->getDataGenerator()->create_user();
$syscontext = \context_system::instance();
$child1context = \context_user::instance($child1->id);
$child2context = \context_user::instance($child2->id);
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
role_assign($roleparentid, $mother1->id, $child1context->id);
role_assign($roleparentid, $mother1->id, $child2context->id);
role_assign($roleparentid, $father1->id, $child1context->id);
role_assign($roleparentid, $father2->id, $child2context->id);
accesslib_clear_all_caches_for_unit_testing();
$mother1minors = api::get_user_minors($mother1->id);
$this->assertEquals(2, count($mother1minors));
$father1minors = api::get_user_minors($father1->id);
$this->assertEquals(1, count($father1minors));
$this->assertEquals($child1->id, $father1minors[$child1->id]->id);
$father2minors = api::get_user_minors($father2->id);
$this->assertEquals(1, count($father2minors));
$this->assertEquals($child2->id, $father2minors[$child2->id]->id);
$this->assertEmpty(api::get_user_minors($child1->id));
$this->assertEmpty(api::get_user_minors($child2->id));
$extradata = api::get_user_minors($mother1->id, ['policyagreed', 'deleted']);
$this->assertTrue(property_exists($extradata[$child1->id], 'policyagreed'));
$this->assertTrue(property_exists($extradata[$child1->id], 'deleted'));
$this->assertTrue(property_exists($extradata[$child2->id], 'policyagreed'));
$this->assertTrue(property_exists($extradata[$child2->id], 'deleted'));
}
/**
* Test behaviour of the {@link api::create_acceptances_user_created()} method.
*/
public function test_create_acceptances_user_created(): void {
global $CFG, $DB;
$this->resetAfterTest();
$this->setAdminUser();
$CFG->sitepolicyhandler = 'tool_policy';
$policy = helper::add_policy()->to_record();
api::make_current($policy->id);
// User has not accepted any policies.
$user1 = $this->getDataGenerator()->create_user();
\core\event\user_created::create_from_userid($user1->id)->trigger();
$this->assertEquals(0, $DB->count_records('tool_policy_acceptances',
['userid' => $user1->id, 'policyversionid' => $policy->id]));
// User has accepted policies.
$user2 = $this->getDataGenerator()->create_user();
$DB->set_field('user', 'policyagreed', 1, ['id' => $user2->id]);
\core\event\user_created::create_from_userid($user2->id)->trigger();
$this->assertEquals(1, $DB->count_records('tool_policy_acceptances',
['userid' => $user2->id, 'policyversionid' => $policy->id]));
}
/**
* Test that user can login if sitepolicyhandler is set but there are no policies.
*/
public function test_login_with_handler_without_policies(): void {
global $CFG;
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$CFG->sitepolicyhandler = 'tool_policy';
require_login(null, false, null, false, true);
}
/**
* Test the three-state logic of the value returned by {@link api::is_user_version_accepted()}.
*/
public function test_is_user_version_accepted(): void {
$preloadedacceptances = [
4 => (object) [
'policyversionid' => 4,
'mainuserid' => 13,
'status' => 1,
],
6 => (object) [
'policyversionid' => 6,
'mainuserid' => 13,
'status' => 0,
],
];
$this->assertTrue(api::is_user_version_accepted(13, 4, $preloadedacceptances));
$this->assertFalse(api::is_user_version_accepted(13, 6, $preloadedacceptances));
$this->assertNull(api::is_user_version_accepted(13, 5, $preloadedacceptances));
}
/**
* Test the functionality of {@link api::get_agreement_optional()}.
*/
public function test_get_agreement_optional(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$policy1 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
api::make_current($policy1->id);
$policy2 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
api::make_current($policy2->id);
$this->assertEquals(api::get_agreement_optional($policy1->id), policy_version::AGREEMENT_OPTIONAL);
$this->assertEquals(api::get_agreement_optional($policy2->id), policy_version::AGREEMENT_COMPULSORY);
}
}
@@ -0,0 +1,306 @@
@tool @tool_policy
Feature: Viewing acceptances reports and accepting on behalf of other users
In order to manage user acceptances
As a manager
I need to be able to view acceptances and accept on behalf of other users
Background:
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
# This is required for now to prevent the overflow region affecting the action menus.
And I change window size to "large"
And the following policies exist:
| Name | Revision | Content | Summary | Status |
| This site policy | | full text2 | short text2 | active |
| This privacy policy | | full text3 | short text3 | draft |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | one@example.com |
| user2 | User | Two | two@example.com |
| manager | Max | Manager | man@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| manager | manager | System | |
And the following "courses" exist:
| fullname | shortname |
| Course1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| user1 | C1 | student |
| user2 | C1 | student |
Scenario: View acceptances made by users on their own, single policy
When I log in as "user1"
Then I should see "This site policy"
And I should not see "Course overview"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should see "Calendar"
And I log out
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And "Accepted" "text" should exist in the "User One" "table_row"
And "Accepted" "text" should exist in the "Max Manager" "table_row"
And "Pending" "text" should exist in the "User Two" "table_row"
Scenario: Agree on behalf of another user as a manager, single policy, javascript off
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
When I log in as "manager"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Accepting policy"
And I should see "User One"
And I should see "This site policy"
And I should see "I acknowledge that I have received a request to give consent on behalf of the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Max Manager" "link" should exist in the "User One" "table_row"
And "Consent received from a parent" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User Two" "table_row"
@javascript
Scenario: Agree on behalf of another user as a manager, single policy, javascript on
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
When I log in as "manager"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should see "Calendar"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Give consent"
And I should see "User One"
And I should see "This site policy"
And I should see "I acknowledge that I have received a request to give consent on behalf of the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Max Manager" "link" should exist in the "User One" "table_row"
And "Consent received from a parent" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User Two" "table_row"
Scenario: View acceptances made by users on their own, multiple policies
Given I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I press "Continue"
And I log out
When I log in as "user1"
Then I should see "This site policy"
And I press "Next"
And I should see "This privacy policy"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I should see "Calendar"
And I log out
And I log in as "manager"
And I press "Next"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And "Accepted" "text" should exist in the "User One" "table_row"
And "Pending" "text" should not exist in the "User One" "table_row"
And "Accepted" "text" should exist in the "Max Manager" "table_row"
And "Pending" "text" should exist in the "User Two" "table_row"
And "Accepted" "text" should not exist in the "User Two" "table_row"
And I click on "Details" "link" in the "User One" "table_row"
And "Accepted" "text" should exist in the "This site policy" "table_row"
And "Accepted" "text" should exist in the "This privacy policy" "table_row"
And I am on site homepage
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And I click on "Details" "link" in the "User Two" "table_row"
And "Pending" "text" should exist in the "This site policy" "table_row"
And "Pending" "text" should exist in the "This privacy policy" "table_row"
Scenario: Agree on behalf of another user as a manager, multiple policies, javascript off
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I press "Continue"
And I log out
When I log in as "manager"
And I press "Next"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Accepting policy"
And I should see "User One"
And I should see "This site policy"
And I should see "I acknowledge that I have received a request to give consent on behalf of the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User One" "table_row"
And I click on "Details" "link" in the "User One" "table_row"
And "Accepted on user's behalf" "text" should exist in the "This site policy" "table_row"
And "Max Manager" "link" should exist in the "This site policy" "table_row"
And "Consent received from a parent" "text" should exist in the "This site policy" "table_row"
And "Pending" "text" should exist in the "This privacy policy" "table_row"
@javascript
Scenario: Agree on behalf of another user as a manager, multiple policies, javascript on
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I wait until "Activate" "button" exists
And I press "Activate"
And I log out
When I log in as "manager"
And I press "Next"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Give consent"
And I should see "User One"
And I should see "This site policy"
And I should see "I acknowledge that I have received a request to give consent on behalf of the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User One" "table_row"
And I click on "Details" "link" in the "User One" "table_row"
And "Accepted on user's behalf" "text" should exist in the "This site policy" "table_row"
And "Max Manager" "link" should exist in the "This site policy" "table_row"
And "Consent received from a parent" "text" should exist in the "This site policy" "table_row"
And "Pending" "text" should exist in the "This privacy policy" "table_row"
Scenario: Policies and agreements profile link visible for current user
Given I log in as "user1"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
When I follow "Profile" in the user menu
# User can see his own agreements link in the profile.
Then I should see "Policies and agreements"
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "This site policy" "table_row"
# User can't see agreements link in other user profiles.
And I am on "Course1" course homepage
And I navigate to course participants
And I follow "User Two"
And I should not see "Policies and agreements"
Scenario: Policies and agreements profile link visible also for users who can access on behalf of others
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
# User can see agreements link in other user profiles because has the capability for accepting on behalf of them.
When I am on "Course1" course homepage
And I navigate to course participants
And I follow "User Two"
Then I should see "Policies and agreements"
Scenario: Agree on behalf of another user as an admin who is logged in as a manager
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
When I log in as "manager"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I log out
And I am on the "manager" "user > profile" page logged in as "admin"
And I follow "Log in as"
And I press "Continue"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Accepting policy"
And I should see "User One"
And I should see "This site policy"
And I should see "I acknowledge that I have received a request to give consent on behalf of the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Max Manager" "link" should not exist in the "User One" "table_row"
And "Admin User" "link" should exist in the "User One" "table_row"
And "Consent received from a parent" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User Two" "table_row"
@javascript
Scenario: Bulk agree on behalf of another users as a manager, multiple policies, javascript on
Given the following "role capability" exists:
| role | manager |
| tool/policy:acceptbehalf | allow |
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I wait until "Activate" "button" exists
And I press "Activate"
And I log out
When I log in as "manager"
And I press "Next"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And I click on "Select" "checkbox" in the "User One" "table_row"
And I press "Consent"
And I should see "Accepting policy"
And I should see "One"
And I click on "Cancel" "button" in the "Accepting policy" "dialogue"
And I should not see "Accepting policy"
And I click on "Select" "checkbox" in the "User Two" "table_row"
And I press "Consent"
And I should see "Accepting policy"
And I should see "User One, User Two"
When I press "Give consent"
Then "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Accepted on user's behalf" "text" should exist in the "User Two" "table_row"
Scenario: View acceptances made by users on their own after inactivating a policy
Given I log in as "user1"
And I should see "This site policy"
And I should not see "Course overview"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should see "Calendar"
And I log out
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I press "Continue"
And I click on "Set status to \"Inactive\"" "link" in the "This privacy policy" "table_row"
And I press "Continue"
And I log out
When I log in as "user1"
Then I should see "Calendar"
@@ -0,0 +1,125 @@
<?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/>.
/**
* Step definition for tool_policy
*
* @package tool_policy
* @category test
* @copyright 2018 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
use Behat\Gherkin\Node\TableNode as TableNode;
/**
* Step definition for tool_policy
*
* @package tool_policy
* @category test
* @copyright 2018 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_tool_policy extends behat_base {
/**
* Click on an entry in the edit menu.
*
* @Given /^the following policies exist:$/
*
* Supported table fields:
*
* - Name: Policy name (required).
* - Revision: Revision name (policy version).
* - Status: Policy version status - 'draft', 'active' or 'archived'. Defaults to 'active'.
* - Audience: Target users - 'guest', 'all' or 'loggedin'. Default to 'all'.
* - Type: 0 - site policy, 1 - privacy policy, 2 - third party policy, 99 - other.
* - Summary: Policy summary text.
* - Content: Policy full text.
* - Agreement style (agreementstyle): 0 - On the consent page, 1 - On its own page
* - Agreement optional (optional): 0 - Compulsory policy, 1 - Optional policy
*
* @param TableNode $data
*/
public function the_following_policies_exist(TableNode $data) {
global $CFG;
if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') {
throw new Exception('Site policy handler is not set to "tool_policy"');
}
$fields = [
'name',
'revision',
'policy',
'status',
'audience',
'type',
'content',
'summary',
'agreementstyle',
'optional',
];
// Associative array "policy identifier" => id in the database .
$policies = [];
foreach ($data->getHash() as $elementdata) {
$data = (object)[
'audience' => \tool_policy\policy_version::AUDIENCE_ALL,
'archived' => 0,
'type' => 0
];
$elementdata = array_change_key_case($elementdata, CASE_LOWER);
foreach ($elementdata as $key => $value) {
if ($key === 'policy') {
if (array_key_exists($value, $policies)) {
$data->policyid = $policies[$value];
}
} else if ($key === 'status') {
$data->archived = ($value === 'archived');
} else if ($key === 'audience') {
if ($value === 'guest') {
$data->audience = \tool_policy\policy_version::AUDIENCE_GUESTS;
} else if ($value === 'loggedin') {
$data->audience = \tool_policy\policy_version::AUDIENCE_LOGGEDIN;
}
} else if (($key === 'summary' || $key === 'content') && !empty($value)) {
$data->{$key.'_editor'} = ['text' => $value, 'format' => FORMAT_MOODLE];
} else if (in_array($key, $fields) && $value !== '') {
$data->$key = $value;
}
}
if (empty($data->name) || empty($data->content_editor) || empty($data->summary_editor)) {
throw new Exception('Policy is missing at least one of the required fields: name, content, summary');
}
if (!empty($data->policyid)) {
$version = tool_policy\api::form_policydoc_update_new($data);
} else {
$version = \tool_policy\api::form_policydoc_add($data);
}
if (!empty($elementdata['policy'])) {
$policies[$elementdata['policy']] = $version->get('policyid');
}
if (empty($elementdata['status']) || $elementdata['status'] === 'active') {
\tool_policy\api::make_current($version->get('id'));
}
}
}
}
@@ -0,0 +1,877 @@
@tool @tool_policy
Feature: User must accept policy managed by this plugin when logging in and signing up
In order to record user agreement to use the site
As a user
I need to be able to accept site policy during sign up
Scenario: Accept policy on sign up, no site policy
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
Then I should not see "I understand and agree"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site (edit their profile).
And I log in as "user1"
And I open my profile in edit mode
And the field "First name" matches value "User1"
Scenario: Accept policy on sign up, only draft policy
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Policy | Name | Revision | Content | Summary | Status |
| P1 | This site policy | | full text1 | short text1 | draft |
| P1 | This privacy policy | | full text2 | short text2 | draft |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
Then I should not see "I understand and agree"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site (edit their profile).
And I log in as "user1"
And I open my profile in edit mode
And the field "First name" matches value "User1"
Scenario: Accept policy on sign up, one policy
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
Given the following policies exist:
| Policy | Name | Revision | Content | Summary | Status |
| P1 | This site policy | | full text1 | short text1 | archived |
| P1 | This site policy | | full text2 | short text2 | active |
| P1 | This site policy | | full text3 | short text3 | draft |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
Then I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should see "full text2"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should not see "full text2"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should not see "I understand and agree"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site.
And I log in as "user1"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "This site policy" "table_row"
And I log out
Scenario: Accept policy on sign up, multiple policies
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
Given the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
| This guests policy | 0 | | full text4 | short text4 | active | guest |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
Then I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should see "full text2"
And I press "Next"
And I should see "This privacy policy" in the "region-main" "region"
And I should see "short text3"
And I should see "full text3"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should not see "full text2"
And I should see "This privacy policy" in the "region-main" "region"
And I should see "short text3"
And I should not see "full text3"
And I should not see "This guests policy" in the "region-main" "region"
And I should not see "short text4"
And I should not see "full text4"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I should not see "I understand and agree"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site.
And I log in as "user1"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "This site policy" "table_row"
And "Accepted" "text" should exist in the "This privacy policy" "table_row"
And I should not see "This guests policy"
And I log out
Scenario: Accept policy on sign up and age verification
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
| agedigitalconsentverification | 1 |
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| This site policy | | full text2 | short text2 | active |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
Then I should see "Age and location verification"
And I set the field "What is your age?" to "16"
And I set the field "In which country do you live?" to "DZ"
And I press "Proceed"
And I should see "This site policy"
And I should see "short text2"
And I should see "full text2"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
And I should see "short text2"
And I should not see "full text2"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should not see "I understand and agree"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site.
And I log in as "user1"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "This site policy" "table_row"
And I log out
Scenario: Accept policy on sign up, do not accept all policies
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And I am on site homepage
And I follow "Log in"
And I click on "Create new account" "link"
And I should see "This site policy"
And I press "Next"
And I should see "This privacy policy"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
And I should see "This privacy policy"
# Confirm that a notification is displayed if none of the policies are accepted.
When I set the field "I agree to the This site policy" to "0"
And I set the field "I agree to the This privacy policy" to "0"
And I press "Next"
Then I should see "Please agree to the following policies"
And I should see "Before continuing you need to acknowledge all these policies."
# Confirm that a notification is displayed if only some policies are accepted.
When I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "0"
Then I should see "Please agree to the following policies"
And I should see "Before continuing you need to acknowledge all these policies."
Scenario: Accept policy on login, do not accept all policies
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
And I log in as "user1"
And I should see "This site policy"
And I press "Next"
And I should see "This privacy policy"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
And I should see "This privacy policy"
# Confirm that a notification is displayed if none of the policies are accepted.
When I set the field "I agree to the This site policy" to "0"
And I set the field "I agree to the This privacy policy" to "0"
And I press "Next"
Then I should see "Please agree to the following policies"
And I should see "Before continuing you need to acknowledge all these policies."
# Confirm that a notification is displayed if only some policies are accepted.
When I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "0"
Then I should see "Please agree to the following policies"
And I should see "Before continuing you need to acknowledge all these policies."
# Confirm that user can not browse the site (edit their profile).
When I follow "Profile" in the user menu
Then I should see "Please agree to the following policies"
Scenario: Accept policy on login, accept all policies
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
And I log in as "user1"
And I should see "This site policy"
And I press "Next"
And I should see "This privacy policy"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
And I should see "This privacy policy"
# User accepts all policies.
When I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
Then I should not see "Please agree to the following policies"
And I should not see "Before continuing you need to acknowledge all these policies."
# Confirm that user can login and browse the site (edit their profile).
When I open my profile in edit mode
Then the field "First name" matches value "User"
And I log out
# Confirm when logging again as user, the policies are not displayed.
When I log in as "user1"
Then I should not see "This site policy"
And I should not see "This privacy policy"
And I should not see "Please agree to the following policies"
# Confirm that user can login and browse the site (edit their profile).
When I open my profile in edit mode
Then the field "First name" matches value "User"
Scenario: Accept policy on login, accept new policy documents
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
And I log in as "user1"
And I should see "This site policy"
And I press "Next"
And I should see "This privacy policy"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
And I should see "This privacy policy"
# User accepts all policies.
When I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
Then I should not see "Please agree to the following policies"
# Confirm that user can login and browse the site (edit their profile).
When I open my profile in edit mode
Then the field "First name" matches value "User"
And I log out
# Create new policy document.
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I should see "Policies and agreements"
And I should see "New policy"
And I follow "New policy"
And I set the following fields to these values:
| Name | This third parties policy |
| Type | Third parties policy |
| User consent | All users |
| Summary | short text4 |
| Full policy | full text4 |
| Active | 1 |
When I press "Save"
Then I should see "Policies and agreements"
And I should see "This third parties policy"
And I log out
# Confirm when logging again as user, the new policies are displayed.
When I log in as "user1"
And I should not see "This site policy"
And I should not see "This privacy policy"
Then I should see "This third parties policy"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This third parties policy"
And I set the field "This third parties policy" to "1"
And I press "Next"
# Confirm that user can login and browse the site (edit their profile).
When I open my profile in edit mode
Then the field "First name" matches value "User"
Scenario: Accept policy on login, accept new policy version
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
And I log in as "user1"
And I should see "This site policy"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
# User accepts policy.
When I set the field "I agree to the This site policy" to "1"
And I press "Next"
Then I should not see "Please agree to the following policies"
# Confirm that user can login and browse the site (edit their profile).
When I open my profile in edit mode
Then the field "First name" matches value "User"
And I log out
# Create new version of the policy document.
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
# Menu is already open because javascript is disabled.
Then I should see "View"
And I should see "Edit"
And I should see "Set status to \"Inactive\""
When I follow "Edit"
Then I should see "Editing policy"
And I set the field "Name" to "This site policy new version"
And I set the field "Summary" to "short text2 new version"
And I set the field "Full policy" to "full text2 new version"
And I press "Save"
And I log out
# Confirm that the user has to agree to the new version of the policy.
When I log in as "user1"
Then I should see "This site policy new version"
And I should see "short text2 new version"
And I should see "full text2 new version"
When I press "Next"
Then I should see "Please agree to the following policies"
And I should see "This site policy new version"
And I should see "short text2 new version"
# User accepts policy.
And I set the field "I agree to the This site policy new version" to "1"
When I press "Next"
Then I should not see "Please agree to the following policies"
# Confirm that user can login and browse the site (edit their profile).
When I open my profile in edit mode
Then the field "First name" matches value "User"
@javascript
Scenario: Accept policy on login as guest
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
| This guests policy | 0 | | full text4 | short text4 | active | guest |
And I am on site homepage
And I change window size to "large"
And I follow "Log in"
When I press "Access as a guest"
Then I should see "If you continue browsing this website, you agree to our policies"
# Confirm when navigating, the pop-up policies are displayed.
When I am on the "My courses" page
Then I should see "If you continue browsing this website, you agree to our policies"
And I should see "This site policy"
And I should see "This guests policy"
And I should not see "This privacy policy"
# Confirm when clicking on the policy links, the policy content is displayed.
When I click on "This site policy" "link"
Then I should see "full text2"
And I click on "Close" "button" in the "This site policy" "dialogue"
And I should not see "full text2"
When I click on "This guests policy" "link"
Then I should see "full text4"
And I click on "Close" "button" in the "This guests policy" "dialogue"
And I should not see "full text4"
# Confirm when agreeing to policies the pop-up is no longer displayed.
When I follow "Continue"
Then I should not see "If you continue browsing this website, you agree to our policies"
Scenario: Accept policy on sign up, after completing sign up attempt to create another account
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
Given the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
| This guests policy | 0 | | full text4 | short text4 | active | guest |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
Then I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should see "full text2"
When I press "Next"
Then I should see "This privacy policy" in the "region-main" "region"
And I should see "short text3"
And I should see "full text3"
When I press "Next"
Then I should see "Please agree to the following policies"
And I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should see "This privacy policy" in the "region-main" "region"
And I should see "short text3"
And I should not see "This guests policy" in the "region-main" "region"
And I should not see "short text4"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
When I press "Next"
Then I should not see "I understand and agree"
And I should see "New account"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
When I press "Create my new account"
Then I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I follow "Log in"
When I click on "Create new account" "link"
# Confirm that the user can view and accept policies when attempting to create another account.
Then I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should see "full text2"
When I press "Next"
Then I should see "This privacy policy" in the "region-main" "region"
And I should see "short text3"
And I should see "full text3"
When I press "Next"
Then I should see "Please agree to the following policies"
And I should see "This site policy" in the "region-main" "region"
And I should see "short text2"
And I should not see "full text2"
And I should see "This privacy policy" in the "region-main" "region"
And I should see "short text3"
And I should not see "full text3"
And I should not see "This guests policy" in the "region-main" "region"
And I should not see "short text4"
And I should not see "full text4"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
When I press "Next"
Then I should not see "I understand and agree"
And I should see "New account"
Scenario: Accept policy while being logged in as another user
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
When I am on the "user1" "user > profile" page logged in as "admin"
And I follow "Log in as"
Then I should see "You are logged in as User 1"
And I press "Continue"
And I should see "Please read our This site policy"
And I press "Next"
And I should see "Please read our This privacy policy"
And I press "Next"
And I should see "Viewing this page on behalf of User 1"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I log out
And I log in as "user1"
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Admin User" "link" should exist in the "This site policy" "table_row"
And "Admin User" "link" should exist in the "This privacy policy" "table_row"
Scenario: Log in as another user without capability to accept policies on their behalf
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following policies exist:
| Name | Type | Revision | Content | Summary | Status | Audience |
| This site policy | 0 | | full text2 | short text2 | active | all |
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
| manager | Max | Manager | man@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| manager | manager | System | |
When I log in as "manager"
And I press "Next"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
And I am on the "user1" "user > profile" page
And I follow "Log in as"
Then I should see "You are logged in as User 1"
And I press "Continue"
And I should see "Policies and agreements"
And I should see "No permission to agree to the policies on behalf of this user"
And I should see "Sorry, you do not have the required permission to agree to the following policies on behalf of User 1"
Scenario: Accept policy on sign up as a guest, one policy
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
Given the following policies exist:
| Policy | Name | Revision | Content | Summary | Status |
| P1 | This site policy | | full text1 | short text1 | archived |
| P1 | This site policy | | full text2 | short text2 | active |
| P1 | This site policy | | full text3 | short text3 | draft |
And I am on site homepage
And I follow "Log in"
# First log in as a guest
And I press "Access as a guest"
# Now sign up
And I follow "Log in"
When I click on "Create new account" "link"
Then I should see "This site policy"
And I should see "short text2"
And I should see "full text2"
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "This site policy"
And I should see "short text2"
And I should not see "full text2"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should not see "I understand and agree"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site.
And I log in as "user1"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "This site policy" "table_row"
And I log out
Scenario: Accepting policies on sign up, multiple policies with different style of giving ageement.
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| name | summary | content | agreementstyle |
| Privacy policy | We scan your thoughts | Here goes content. | 0 |
| Digital maturity declaration | You declare be old enough | Here goes content. | 1 |
| Cookies policy | We eat cookies, srsly | Here goes content. | 0 |
| Terms of Service | We teach, you learn | Here goes content. | 1 |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
# The first policy with the agreement style "on its own page" must be accepted first.
Then I should see "Digital maturity declaration" in the "region-main" "region"
And I should see "You declare be old enough"
And I should see "Here goes content."
And I press "I agree to the Digital maturity declaration"
# The second policy with the agreement style "on its own page" must be accepted now.
And I should see "Terms of Service" in the "region-main" "region"
And I should see "We teach, you learn"
And I should see "Here goes content."
And I press "I agree to the Terms of Service"
# Only now we see the remaining consent page policies.
And I should see "Policy 1 out of 2"
And I should see "Privacy policy" in the "region-main" "region"
And I should see "We scan your thoughts"
And I should see "Here goes content."
And I press "Next"
And I should see "Policy 2 out of 2"
And I should see "Cookies policy" in the "region-main" "region"
And I should see "We eat cookies, srsly"
And I should see "Here goes content."
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "Privacy policy"
And I should see "Cookies policy"
And I should not see "Digital maturity declaration" in the "region-main" "region"
And I should not see "Terms of Service" in the "region-main" "region"
And I should not see "Here goes content."
And I set the field "I agree to the Privacy policy" to "1"
And I set the field "I agree to the Cookies policy" to "1"
And I press "Next"
And I should see "New account"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site.
And I log in as "user1"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "Privacy policy" "table_row"
And "Accepted" "text" should exist in the "Cookies policy" "table_row"
And "Accepted" "text" should exist in the "Terms of Service" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And I log out
Scenario: Accepting policies on login, multiple policies with different style of giving ageement.
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following policies exist:
| name | summary | content | agreementstyle |
| Digital maturity declaration | You declare be old enough | Here goes content. | 1 |
| Privacy policy | We scan your thoughts | Here goes content. | 0 |
| Terms of Service | We teach, you learn | Here goes content. | 1 |
| Cookies policy | We eat cookies, srsly | Here goes content. | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | user1@example.com |
And I log in as "user1"
# The first policy with the agreement style "on its own page" must be accepted first.
Then I should see "Digital maturity declaration" in the "region-main" "region"
And I should see "You declare be old enough"
And I should see "Here goes content."
And I press "I agree to the Digital maturity declaration"
# The second policy with the agreement style "on its own page" must be accepted now.
And I should see "Terms of Service" in the "region-main" "region"
And I should see "We teach, you learn"
And I should see "Here goes content."
# If the user logs out now, only the first policy is accepted and we return to the same page.
And I log out
And I log in as "user1"
And I should see "Terms of Service" in the "region-main" "region"
And I should see "We teach, you learn"
And I should see "Here goes content."
And I press "I agree to the Terms of Service"
# Only now we see the remaining consent page policies.
And I should see "Policy 1 out of 2"
And I should see "Privacy policy" in the "region-main" "region"
And I should see "We scan your thoughts"
And I should see "Here goes content."
And I press "Next"
And I should see "Policy 2 out of 2"
And I should see "Cookies policy" in the "region-main" "region"
And I should see "We eat cookies, srsly"
And I should see "Here goes content."
And I press "Next"
And I should see "Please agree to the following policies"
And I should see "Privacy policy"
And I should see "Cookies policy"
And I should not see "Digital maturity declaration" in the "region-main" "region"
And I should not see "Terms of Service" in the "region-main" "region"
And I should not see "Here goes content."
And I set the field "I agree to the Privacy policy" to "1"
And I set the field "I agree to the Cookies policy" to "1"
And I press "Next"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "Privacy policy" "table_row"
And "Accepted" "text" should exist in the "Cookies policy" "table_row"
And "Accepted" "text" should exist in the "Terms of Service" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And I log out
Scenario: Accepting policies on login, all and loggedin policies to be accepted on their own page.
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following policies exist:
| name | summary | content | agreementstyle | audience |
| Privacy policy | We scan your thoughts | Here goes content. | 1 | all |
| Digital maturity declaration | You declare be old enough | Here goes content. | 1 | loggedin |
| Cookies policy | We eat cookies, srsly | Here goes content. | 1 | guest |
| Terms of Service | We teach, you learn | Here goes content. | 1 | all |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | user1@example.com |
And I log in as "user1"
# All the policies to be displayed one by one with a button to accept each of them prior seeing the next.
Then I should see "Privacy policy" in the "region-main" "region"
And I should see "We scan your thoughts"
And I should see "Here goes content."
And I press "I agree to the Privacy policy"
And I should see "Digital maturity declaration" in the "region-main" "region"
And I should see "You declare be old enough"
And I should see "Here goes content."
And I press "I agree to the Digital maturity declaration"
And I should see "Terms of Service" in the "region-main" "region"
And I should see "We teach, you learn"
And I should see "Here goes content."
And I press "I agree to the Terms of Service"
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "Privacy policy" "table_row"
And "Accepted" "text" should exist in the "Terms of Service" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And "Cookies policy" "table_row" should not exist
And I log out
Scenario: Accepting policies on sign up, policies to be accepted on their own page.
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
| sitepolicyhandler | tool_policy |
And the following policies exist:
| name | summary | content | agreementstyle | audience |
| Privacy policy | We scan your thoughts | Here goes content. | 1 | guest |
| Digital maturity declaration | You declare be old enough | Here goes content. | 1 | all |
| Cookies policy | We eat cookies, srsly | Here goes content. | 1 | loggedin |
| Terms of Service | We teach, you learn | Here goes content. | 1 | guest |
And I am on site homepage
And I follow "Log in"
When I click on "Create new account" "link"
# All the policies to be displayed one by one with a button to accept each of them prior seeing the next.
Then I should see "Digital maturity declaration" in the "region-main" "region"
And I should see "You declare be old enough"
And I should see "Here goes content."
And I press "I agree to the Digital maturity declaration"
And I should see "Cookies policy" in the "region-main" "region"
And I should see "We eat cookies, srsly"
And I press "I agree to the Cookies policy"
And I should see "New account"
And I set the following fields to these values:
| Username | user1 |
| Password | user1 |
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
And I confirm email for "user1"
And I should see "Thanks, User1 L1"
And I should see "Your registration has been confirmed"
And I open my profile in edit mode
And the field "First name" matches value "User1"
And I log out
# Confirm that user can login and browse the site.
And I log in as "user1"
And I follow "Profile" in the user menu
# User can see his own agreements in the profile.
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And "Accepted" "text" should exist in the "Cookies policy" "table_row"
And "Privacy policy" "table_row" should not exist
And "Terms of Service" "table_row" should not exist
And I log out
@@ -0,0 +1,260 @@
@tool @tool_policy
Feature: Manage policies
In order to manage policies
As a manager
I need to be able to create and edit site policies
Background:
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | one@example.com |
| user2 | User | Two | two@example.com |
| manager | Max | Manager | man@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| manager | manager | System | |
Scenario: Create new policy and save as draft
When I log in as "manager"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I follow "New policy"
And I set the following fields to these values:
| Name | Policy1 |
| Version | v1 |
| Summary | Policy summary |
| Full policy | Full text |
And the field "Type" matches value "Site policy"
And the field "User consent" matches value "All users"
And the field "status" matches value "0"
And "Draft" "field" should exist
And "Active" "field" should exist
And "Minor change" "field" should not exist
And I should not see "Minor change"
And "Save as draft" "button" should not exist
And I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Draft | v1 | N/A |
And I log out
Scenario: Create new policy and save as active
When I log in as "manager"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I follow "New policy"
And I set the following fields to these values:
| Name | Policy1 |
| Version | v1 |
| Summary | Policy summary |
| Full policy | Full text |
| Active | 1 |
And I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Active | v1 | 0 of 4 (0%) |
And I log out
Scenario: Edit active policy and save as minor change
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | active |
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the Policy1" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Edit" "link" in the "Policy1" "table_row"
And "Draft" "field" should not exist
And "Active" "field" should not exist
And "Minor change" "field" should exist
And "Save as draft" "button" should exist
And I set the field "Version" to "v1 amended"
And I set the field "Minor change" to "1"
And I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Active | v1 amended | 1 of 4 (25%) |
And I log out
Scenario: Edit active policy and save as draft
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | active |
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the Policy1" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Edit" "link" in the "Policy1" "table_row"
And I set the field "Version" to "v2"
And I press "Save as draft"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Active | v1 | 1 of 4 (25%) |
| Policy1 Site policy, All users, Compulsory | Draft | v2 | N/A |
And I log out
Scenario: Edit active policy and save as new active version
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | active |
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the Policy1" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Edit" "link" in the "Policy1" "table_row"
And I set the field "Name" to "Policy2"
And I set the field "Version" to "v2"
And I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy2 Site policy, All users, Compulsory | Active | v2 | 0 of 4 (0%) |
And I should not see "Policy1"
And I should not see "v1"
And I click on "View previous versions" "link" in the "Policy2" "table_row"
And I should see "Policy2 previous versions"
And I should not see "v2"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Inactive | v1 | 1 of 4 (25%) |
And I log out
Scenario: Edit draft policy and save as draft
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | draft |
And I log in as "manager"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Edit" "link" in the "Policy1" "table_row"
And I set the field "Version" to "v2"
And "Draft" "field" should exist
And "Active" "field" should exist
And "Minor change" "field" should not exist
And I should not see "Minor change"
And "Save as draft" "button" should not exist
And I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Draft | v2 | N/A |
And I should not see "v1"
And "View previous versions" "link" should not exist
And I log out
Scenario: Edit draft policy and save as active
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | draft |
And I log in as "manager"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Edit" "link" in the "Policy1" "table_row"
And I set the field "Version" to "v2"
And I set the field "Active" to "1"
And I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Active | v2 | 0 of 4 (0%) |
And I should not see "v1"
And "View previous versions" "link" should not exist
And I log out
Scenario: Activate draft policy
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | draft |
And I log in as "manager"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Set status to \"Active\"" "link" in the "Policy1" "table_row"
Then I should see "All users will be required to agree to this new policy version to be able to use the site."
And I press "Continue"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Active | v1 | 0 of 4 (0%) |
And "View previous versions" "link" should not exist
And I log out
Scenario: Edit archived policy and save as draft
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | active |
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the Policy1" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Set status to \"Inactive\"" "link" in the "Policy1" "table_row"
Then I should see "You are about to inactivate policy"
And I press "Continue"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Inactive | v1 | 1 of 4 (25%) |
And I click on "Create a new draft" "link" in the "Policy1" "table_row"
And I set the field "Version" to "v2"
And I set the field "Name" to "Policy2"
And the field "status" matches value "0"
And "Draft" "field" should exist
And "Active" "field" should exist
And "Minor change" "field" should not exist
And I should not see "Minor change"
And "Save as draft" "button" should not exist
And I press "Save"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy2 Site policy, All users, Compulsory | Draft | v2 | N/A |
And I should not see "v1"
And I should not see "Policy1"
And I click on "View previous versions" "link" in the "Policy2" "table_row"
And I should see "Policy2 previous versions"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Inactive | v1 | 1 of 4 (25%) |
And I should not see "v2"
And I log out
Scenario: Edit archived policy and save as active
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | active |
And I log in as "manager"
And I press "Next"
And I set the field "I agree to the Policy1" to "1"
And I press "Next"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Set status to \"Inactive\"" "link" in the "Policy1" "table_row"
And I press "Continue"
And I click on "Create a new draft" "link" in the "Policy1" "table_row"
And I set the field "Version" to "v2"
And I set the field "Name" to "Policy2"
And I set the field "Active" to "1"
And I press "Save"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy2 Site policy, All users, Compulsory | Active | v2 | 0 of 4 (0%) |
And I should not see "v1"
And I should not see "Policy1"
And I click on "View previous versions" "link" in the "Policy2" "table_row"
And I should see "Policy2 previous versions"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version | Agreements |
| Policy1 Site policy, All users, Compulsory | Inactive | v1 | 1 of 4 (25%) |
And I should not see "v2"
And I log out
Scenario: Current user can go back to previous page in List of active policies page
Given the following policies exist:
| Name | Revision | Content | Summary | Status |
| Policy1 | v1 | full text2 | short text2 | active |
And I log in as "user1"
And I press "Next"
And I set the field "I agree to the Policy1" to "1"
And I press "Next"
And I follow "Preferences" in the user menu
And I should see "Preferences"
And I should see "Policies"
# User should see a redirect back to previous page link.
And I click on "Policies" "link"
And I should see "List of active policies"
And I should see "Go back to previous page"
When I click on "Go back to previous page" "link"
Then I should see "Preferences"
@@ -0,0 +1,264 @@
@tool @tool_policy
Feature: Optional policies
In order to exercise my privacy rights
As a user
I should be able to decline policy statements and withdraw my previously given consent to them
Background:
Given the following config values are set as admin:
| sitepolicyhandler | tool_policy |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | one@example.com |
| user2 | User | Two | two@example.com |
| manager | Max | Manager | man@example.com |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| manager | manager | System | |
And the following "courses" exist:
| fullname | shortname |
| Course1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| user1 | C1 | student |
| user2 | C1 | student |
Scenario: Configuring a policy as optional
Given I log in as "manager"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I follow "New policy"
# Policies are compulsory by default.
And the field "Agreement optional" matches value "No"
# Optional status can be set when creating a new policy.
And I set the following fields to these values:
| Name | ConsentPageOptional1 |
| Version | v1 |
| Summary | Policy summary |
| Full policy | Full text |
| Active | 1 |
| Show policy before showing other policies | No |
| Agreement optional | Yes |
When I press "Save"
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version |
| ConsentPageOptional1 Site policy, All users, Optional | Active | v1 |
# Optional status can be edited.
And I open the action menu in "ConsentPageOptional1" "table_row"
And I click on "Edit" "link" in the "ConsentPageOptional1" "table_row"
And I set the field "Agreement optional" to "No"
And I set the field "Minor change" to "1"
And I press "Save"
And the following should exist in the "tool-policy-managedocs-wrapper" table:
| Name | Policy status | Version |
| ConsentPageOptional1 Site policy, All users, Compulsory | Active | v1 |
Scenario: Compulsory policies must be accepted prior signup, optional policies just after it
Given the following config values are set as admin:
| registerauth | email |
| passwordpolicy | 0 |
And the following policies exist:
| Name | Content | Summary | Agreementstyle | Optional |
| ConsentPageOptional1 | full text1 | short text1 | 0 | 1 |
| ConsentPageOptional2 | full text2 | short text2 | 0 | 1 |
| ConsentPageCompulsory1 | full text3 | short text3 | 0 | 0 |
| OwnPageCompulsory1 | full text4 | short text4 | 1 | 0 |
| OwnPageOptional1 | full text5 | short text5 | 1 | 1 |
And I am on site homepage
And I follow "Log in"
And I click on "Create new account" "link"
# Compulsory policies displayed on own page are shown first and must be agreed.
And I should see "OwnPageCompulsory1" in the "region-main" "region"
And I should see "short text4" in the "region-main" "region"
And I should see "full text4" in the "region-main" "region"
And I press "I agree to the OwnPageCompulsory1"
# Compulsory policies displayed on the consent page are shown next and must be agreed.
And I should see "ConsentPageCompulsory1"
And I should see "short text3" in the "region-main" "region"
And I should see "full text3" in the "region-main" "region"
And I press "Next"
And I should see "Please agree to the following policies"
And I set the field "I agree to the ConsentPageCompulsory1" to "1"
And I press "Next"
# The signup form can be submitted and a new account created.
And I set the following fields to these values:
| Username | user3 |
| Password | user3 |
| Email address | user3@address.invalid |
| Email (again) | user3@address.invalid |
| First name | User3 |
| Last name | L3 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user3@address.invalid"
And I confirm email for "user3"
And I should see "Thanks, User3 L3"
And I should see "Your registration has been confirmed"
When I press "Continue"
# After confirming the new account, the user is logged in and asked to accept or decline the optional policies.
# First come policies displayed on their own page.
Then I should see "OwnPageOptional1"
And I should see "short text5" in the "region-main" "region"
And I should see "full text5" in the "region-main" "region"
And I press "No thanks, I decline OwnPageOptional1"
# Then come policies displayed on the consent page.
And I should see "ConsentPageOptional1" in the "region-main" "region"
And I should see "short text1" in the "region-main" "region"
And I should see "full text1" in the "region-main" "region"
And I press "Next"
And I should see "ConsentPageOptional2" in the "region-main" "region"
And I should see "short text2" in the "region-main" "region"
And I should see "full text2" in the "region-main" "region"
And I press "Next"
And I should see "Please agree to the following policies"
And I set the field "I agree to the ConsentPageOptional1" to "1"
And I set the field "No thanks, I decline ConsentPageOptional2" to "0"
And I press "Next"
# Accepted and declined policies are shown in the profile.
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "ConsentPageCompulsory1" "table_row"
And "Accepted" "text" should exist in the "ConsentPageOptional1" "table_row"
And "Accepted" "text" should exist in the "OwnPageCompulsory1" "table_row"
And "Declined" "text" should exist in the "OwnPageOptional1" "table_row"
And "Declined" "text" should exist in the "ConsentPageOptional2" "table_row"
Scenario: When a new optional policy is added, users are asked to accept/decline it on their next login
Given the following policies exist:
| Name | Content | Summary | Agreementstyle | Optional |
| ConsentPageOptional1 | full text1 | short text1 | 0 | 1 |
| OwnPageOptional1 | full text5 | short text5 | 1 | 1 |
When I log in as "user1"
# First come policies displayed on their own page.
Then I should see "OwnPageOptional1"
And I should see "short text5" in the "region-main" "region"
And I should see "full text5" in the "region-main" "region"
And I press "I agree to the OwnPageOptional1"
# Then come policies displayed on the consent page.
And I should see "ConsentPageOptional1" in the "region-main" "region"
And I should see "short text1" in the "region-main" "region"
And I should see "full text1" in the "region-main" "region"
And I press "Next"
And I should see "Please agree to the following policies"
And I set the field "No thanks, I decline ConsentPageOptional1" to "0"
And I press "Next"
# Accepted and declined policies are shown in the profile.
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "OwnPageOptional1" "table_row"
And "Declined" "text" should exist in the "ConsentPageOptional1" "table_row"
Scenario: Users can withdraw an accepted optional policy and re-accept it again (js off)
Given the following policies exist:
| Name | Content | Summary | Agreementstyle | Optional |
| OwnPageOptional1 | full text1 | short text1 | 1 | 1 |
And I log in as "user1"
And I press "I agree to the OwnPageOptional1"
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "OwnPageOptional1" "table_row"
And "Withdraw" "link" should exist in the "OwnPageOptional1" "table_row"
When I click on "Withdraw acceptance of OwnPageOptional1" "link" in the "OwnPageOptional1" "table_row"
Then I should see "Withdrawing policy"
And I should see "User One"
And I should see "OwnPageOptional1"
And I press "Withdraw user consent"
And "Declined" "text" should exist in the "OwnPageOptional1" "table_row"
And "Accept" "link" should exist in the "OwnPageOptional1" "table_row"
And I click on "Accept OwnPageOptional1" "link" in the "OwnPageOptional1" "table_row"
And I should see "Accepting policy"
And I should see "User One"
And I should see "OwnPageOptional1"
And I press "Give consent"
And "Accepted" "text" should exist in the "OwnPageOptional1" "table_row"
@javascript
Scenario: Users can withdraw an accepted optional policy and re-accept it again (js on)
Given the following policies exist:
| Name | Content | Summary | Agreementstyle | Optional |
| OwnPageOptional1 | full text1 | short text1 | 1 | 1 |
And I log in as "user1"
And I press "I agree to the OwnPageOptional1"
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Accepted" "text" should exist in the "OwnPageOptional1" "table_row"
And "Withdraw" "link" should exist in the "OwnPageOptional1" "table_row"
When I click on "Withdraw acceptance of OwnPageOptional1" "link" in the "OwnPageOptional1" "table_row"
Then I should see "Withdrawing policy"
And I should see "User One"
And I should see "OwnPageOptional1"
And I press "Withdraw user consent"
And "Declined" "text" should exist in the "OwnPageOptional1" "table_row"
And "Accept" "link" should exist in the "OwnPageOptional1" "table_row"
And I click on "Accept OwnPageOptional1" "link" in the "OwnPageOptional1" "table_row"
And I should see "Accepting policy"
And I should see "User One"
And I should see "OwnPageOptional1"
And I press "Give consent"
And "Accepted" "text" should exist in the "OwnPageOptional1" "table_row"
Scenario: Managers can see accepted, declined and pending acceptances of optional policies
Given the following policies exist:
| Name | Content | Summary | Agreementstyle | Optional |
| OwnPageOptional1 | full text1 | short text1 | 1 | 1 |
| OwnPageOptional2 | full text2 | short text2 | 1 | 1 |
And I log in as "user1"
And I press "I agree to the OwnPageOptional1"
And I press "No thanks, I decline OwnPageOptional2"
And I log out
And I log in as "manager"
And I press "I agree to the OwnPageOptional1"
And I press "I agree to the OwnPageOptional2"
When I navigate to "Users > Privacy and policies > User agreements" in site administration
# User One has accepted just some policies.
Then "Partially accepted" "text" should exist in the "User One" "table_row"
And "Details" "link" should exist in the "User One" "table_row"
# User Two did not have a chance to respond to the new policies yet.
And "Pending" "text" should exist in the "User Two" "table_row"
And "Details" "link" should exist in the "User Two" "table_row"
# Max Manager accepted all and can also change status of own acceptances.
And "Accepted" "text" should exist in the "Max Manager" "table_row"
And "Details" "link" should exist in the "Max Manager" "table_row"
And "Withdraw accepted policies" "link" should exist in the "Max Manager" "table_row"
And "Withdraw acceptance of OwnPageOptional1" "link" should exist in the "Max Manager" "table_row"
And "Withdraw acceptance of OwnPageOptional2" "link" should exist in the "Max Manager" "table_row"
Scenario: Administrators can see accepted, declined and pending acceptances of optional policies and also change them on behalf of other users
Given the following policies exist:
| Name | Content | Summary | Agreementstyle | Optional |
| OwnPageOptional1 | full text1 | short text1 | 1 | 1 |
| OwnPageOptional2 | full text2 | short text2 | 1 | 1 |
And I log in as "user1"
And I press "I agree to the OwnPageOptional1"
And I press "No thanks, I decline OwnPageOptional2"
And I log out
And I log in as "admin"
When I navigate to "Users > Privacy and policies > User agreements" in site administration
# User One has accepted just some policies.
Then "Partially accepted" "text" should exist in the "User One" "table_row"
And "Details" "link" should exist in the "User One" "table_row"
And "Withdraw acceptance of OwnPageOptional1" "link" should exist in the "User One" "table_row"
And "Accept OwnPageOptional2" "link" should exist in the "User One" "table_row"
# User Two did not have a chance to respond to the new policies yet.
And "Pending" "text" should exist in the "User Two" "table_row"
And "Accept pending policies" "link" should exist in the "User Two" "table_row"
And "Decline pending policies" "link" should exist in the "User Two" "table_row"
And "Accept OwnPageOptional1" "link" should exist in the "User Two" "table_row"
And "Decline OwnPageOptional1" "link" should exist in the "User Two" "table_row"
And "Accept OwnPageOptional2" "link" should exist in the "User Two" "table_row"
And "Decline OwnPageOptional2" "link" should exist in the "User Two" "table_row"
# Accept all policies on Max Manager's behalf.
And I click on "Accept pending policies" "link" in the "Max Manager" "table_row"
And I press "Give consent"
And "Accepted" "text" should exist in the "Max Manager" "table_row"
# Decline all policies on User Two's behalf.
And I click on "Decline pending policies" "link" in the "User Two" "table_row"
And I press "Decline user consent"
And "Declined on user's behalf" "text" should exist in the "User Two" "table_row"
And "Accepted" "text" should not exist in the "User Two" "table_row"
And "Pending" "text" should not exist in the "User Two" "table_row"
# Accept policy on User One's behalf.
And I click on "Accept OwnPageOptional2" "link" in the "User One" "table_row"
And I press "Give consent"
And "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Declined" "text" should not exist in the "User One" "table_row"
And "Pending" "text" should not exist in the "User One" "table_row"
@@ -0,0 +1,447 @@
<?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 tool_policy;
use externallib_advanced_testcase;
use tool_mobile\external as external_mobile;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/user/externallib.php');
/**
* External policy webservice API tests.
*
* @package tool_policy
* @copyright 2018 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class externallib_test extends externallib_advanced_testcase {
/** @var \tool_policy\policy_version $policy1 Policy document 1. */
protected $policy1;
/** @var \tool_policy\policy_version $policy2 Policy document 2. */
protected $policy2;
/** @var \tool_policy\policy_version $policy3 Policy document 3. */
protected $policy3;
/** @var \stdClass $child user record. */
protected $child;
/** @var \stdClass $parent user record. */
protected $parent;
/** @var \stdClass $adult user record. */
protected $adult;
/**
* Setup function- we will create some policy docs.
*/
public function setUp(): void {
$this->resetAfterTest(true);
$this->setAdminUser();
// Prepare a policy document with some versions.
$formdata = api::form_policydoc_data(new \tool_policy\policy_version(0));
$formdata->name = 'Test policy';
$formdata->revision = 'v1';
$formdata->summary_editor = ['text' => 'summary', 'format' => FORMAT_HTML, 'itemid' => 0];
$formdata->content_editor = ['text' => 'content', 'format' => FORMAT_HTML, 'itemid' => 0];
$this->policy1 = api::form_policydoc_add($formdata);
$formdata = api::form_policydoc_data($this->policy1);
$formdata->revision = 'v2';
$this->policy2 = api::form_policydoc_update_new($formdata);
$formdata = api::form_policydoc_data($this->policy1);
$formdata->revision = 'v3';
$this->policy3 = api::form_policydoc_update_new($formdata);
api::make_current($this->policy2->get('id'));
// Create users.
$this->child = $this->getDataGenerator()->create_user();
$this->parent = $this->getDataGenerator()->create_user();
$this->adult = $this->getDataGenerator()->create_user();
$syscontext = \context_system::instance();
$childcontext = \context_user::instance($this->child->id);
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
role_assign($roleminorid, $this->child->id, $syscontext->id);
role_assign($roleparentid, $this->parent->id, $childcontext->id);
}
/**
* Test for the get_policy_version() function.
*/
public function test_get_policy_version(): void {
$this->setUser($this->adult);
// View current policy version.
$result = external::get_policy_version($this->policy2->get('id'));
$result = \core_external\external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
$this->assertCount(1, $result['result']);
$this->assertEquals($this->policy1->get('name'), $result['result']['policy']['name']);
$this->assertEquals($this->policy1->get('content'), $result['result']['policy']['content']);
// View draft policy version.
$result = external::get_policy_version($this->policy3->get('id'));
$result = \core_external\external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
$this->assertCount(0, $result['result']);
$this->assertCount(1, $result['warnings']);
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorusercantviewpolicyversion');
// Add test for non existing versionid.
$result = external::get_policy_version(999);
$result = \core_external\external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
$this->assertCount(0, $result['result']);
$this->assertCount(1, $result['warnings']);
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorpolicyversionnotfound');
// View previous non-accepted version in behalf of a child.
$this->setUser($this->parent);
$result = external::get_policy_version($this->policy1->get('id'), $this->child->id);
$result = \core_external\external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
$this->assertCount(0, $result['result']);
$this->assertCount(1, $result['warnings']);
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorusercantviewpolicyversion');
// Let the parent accept the policy on behalf of her child and view it again.
api::accept_policies($this->policy1->get('id'), $this->child->id);
$result = external::get_policy_version($this->policy1->get('id'), $this->child->id);
$result = \core_external\external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
$this->assertCount(1, $result['result']);
$this->assertEquals($this->policy1->get('name'), $result['result']['policy']['name']);
$this->assertEquals($this->policy1->get('content'), $result['result']['policy']['content']);
// Only parent is able to view the child policy version accepted by her child.
$this->setUser($this->adult);
$result = external::get_policy_version($this->policy1->get('id'), $this->child->id);
$result = \core_external\external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
$this->assertCount(0, $result['result']);
$this->assertCount(1, $result['warnings']);
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorusercantviewpolicyversion');
}
/**
* Test tool_mobile\external callback to site_policy_handler.
*/
public function test_get_config_with_site_policy_handler(): void {
global $CFG;
$this->resetAfterTest(true);
// Set the handler for the site policy, make sure it substitutes link to the sitepolicy.
$CFG->sitepolicyhandler = 'tool_policy';
$sitepolicymanager = new \core_privacy\local\sitepolicy\manager();
$result = external_mobile::get_config();
$result = \core_external\external_api::clean_returnvalue(external_mobile::get_config_returns(), $result);
$toolsitepolicy = $sitepolicymanager->get_embed_url();
foreach (array_values($result['settings']) as $r) {
if ($r['name'] == 'sitepolicy') {
$configsitepolicy = $r['value'];
}
}
$this->assertEquals($toolsitepolicy, $configsitepolicy);
}
/**
* Test for core_privacy\sitepolicy\manager::accept() when site policy handler is set.
*/
public function test_agree_site_policy_with_handler(): void {
global $CFG, $DB, $USER;
$this->resetAfterTest(true);
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
// Set mock site policy handler. See function tool_phpunit_site_policy_handler() below.
$CFG->sitepolicyhandler = 'tool_policy';
$this->assertEquals(0, $USER->policyagreed);
$sitepolicymanager = new \core_privacy\local\sitepolicy\manager();
// Make sure user can not login.
$toolconsentpage = $sitepolicymanager->get_redirect_url();
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('sitepolicynotagreed', 'error', $toolconsentpage->out()));
\core_user_external::validate_context(\context_system::instance());
// Call WS to agree to the site policy. It will call tool_policy handler.
$result = \core_user_external::agree_site_policy();
$result = \core_external\external_api::clean_returnvalue(\core_user_external::agree_site_policy_returns(), $result);
$this->assertTrue($result['status']);
$this->assertCount(0, $result['warnings']);
$this->assertEquals(1, $USER->policyagreed);
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', array('id' => $USER->id)));
// Try again, we should get a warning.
$result = \core_user_external::agree_site_policy();
$result = \core_external\external_api::clean_returnvalue(\core_user_external::agree_site_policy_returns(), $result);
$this->assertFalse($result['status']);
$this->assertCount(1, $result['warnings']);
$this->assertEquals('alreadyagreed', $result['warnings'][0]['warningcode']);
}
/**
* Test for core_privacy\sitepolicy\manager::accept() when site policy handler is set.
*/
public function test_checkcanaccept_with_handler(): void {
global $CFG;
$this->resetAfterTest(true);
$CFG->sitepolicyhandler = 'tool_policy';
$syscontext = \context_system::instance();
$sitepolicymanager = new \core_privacy\local\sitepolicy\manager();
$adult = $this->getDataGenerator()->create_user();
$child = $this->getDataGenerator()->create_user();
$rolechildid = create_role('Child', 'child', 'Not old enough to accept site policies themselves');
assign_capability('tool/policy:accept', CAP_PROHIBIT, $rolechildid, $syscontext->id);
role_assign($rolechildid, $child->id, $syscontext->id);
// Default user can accept policies.
$this->setUser($adult);
$result = external_mobile::get_config();
$result = \core_external\external_api::clean_returnvalue(external_mobile::get_config_returns(), $result);
$toolsitepolicy = $sitepolicymanager->accept();
$this->assertTrue($toolsitepolicy);
// Child user can not accept policies.
$this->setUser($child);
$result = external_mobile::get_config();
$result = \core_external\external_api::clean_returnvalue(external_mobile::get_config_returns(), $result);
$this->expectException(\required_capability_exception::class);
$sitepolicymanager->accept();
}
/**
* Test for external function get_user_acceptances().
*/
public function test_external_get_user_acceptances(): void {
global $CFG;
$this->resetAfterTest(true);
$CFG->sitepolicyhandler = 'tool_policy';
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Create optional policy.
$formdata = api::form_policydoc_data(new \tool_policy\policy_version(0));
$formdata->name = 'Test optional policy';
$formdata->revision = 'v1';
$formdata->optional = 1;
$formdata->summary_editor = ['text' => 'summary', 'format' => FORMAT_HTML, 'itemid' => 0];
$formdata->content_editor = ['text' => 'content', 'format' => FORMAT_HTML, 'itemid' => 0];
$optionalpolicy = api::form_policydoc_add($formdata);
api::make_current($optionalpolicy->get('id'));
// Accept this version.
api::accept_policies([$optionalpolicy->get('id')], $user->id, null);
// Generate new version.
$formdata = api::form_policydoc_data($optionalpolicy);
$formdata->revision = 'v2';
$optionalpolicynew = api::form_policydoc_update_new($formdata);
api::make_current($optionalpolicynew->get('id'));
// Now return all policies the user should be able to see, including previous versions of existing policies, if accepted/declined.
$policies = \tool_policy\external\get_user_acceptances::execute();
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\get_user_acceptances::execute_returns(), $policies);
$this->assertCount(3, $policies['policies']);
$this->assertCount(0, $policies['warnings']);
foreach ($policies['policies'] as $policy) {
if ($policy['versionid'] == $this->policy2->get('id')) {
$this->assertEquals($this->policy2->get('name'), $policy['name']);
$this->assertEquals(0, $policy['optional']);
$this->assertTrue($policy['canaccept']);
$this->assertFalse($policy['candecline']); // Cannot decline or revoke mandatory for myself.
$this->assertFalse($policy['canrevoke']);
} else {
$this->assertEquals($optionalpolicy->get('name'), $policy['name']);
$this->assertEquals(1, $policy['optional']);
$this->assertTrue($policy['canaccept']);
$this->assertTrue($policy['candecline']); // Can decline or revoke optional for myself.
$this->assertTrue($policy['canrevoke']);
}
$this->assertNotContains('acceptance', $policy); // Nothing accepted yet.
}
// Get other user acceptances.
$this->parent->policyagreed = 1;
$this->setUser($this->parent);
$policies = \tool_policy\external\get_user_acceptances::execute($this->child->id);
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\get_user_acceptances::execute_returns(), $policies);
$this->assertCount(2, $policies['policies']);
foreach ($policies['policies'] as $policy) {
if ($policy['versionid'] == $this->policy2->get('id')) {
$this->assertTrue($policy['canaccept']);
$this->assertFalse($policy['candecline']); // Cannot decline mandatory in general.
$this->assertTrue($policy['canrevoke']);
} else {
$this->assertTrue($policy['canaccept']);
$this->assertTrue($policy['candecline']);
$this->assertTrue($policy['canrevoke']);
}
$this->assertNotContains('acceptance', $policy); // Nothing accepted yet.
}
// Get other user acceptances without permission.
$this->expectException(\required_capability_exception::class);
$policies = \tool_policy\external\get_user_acceptances::execute($user->id);
}
/**
* Test for external function set_acceptances_status().
*/
public function test_external_set_acceptances_status(): void {
global $CFG;
$this->resetAfterTest(true);
$CFG->sitepolicyhandler = 'tool_policy';
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Create optional policy.
$formdata = api::form_policydoc_data(new \tool_policy\policy_version(0));
$formdata->name = 'Test optional policy';
$formdata->revision = 'v1';
$formdata->optional = 1;
$formdata->summary_editor = ['text' => 'summary', 'format' => FORMAT_HTML, 'itemid' => 0];
$formdata->content_editor = ['text' => 'content', 'format' => FORMAT_HTML, 'itemid' => 0];
$optionalpolicy = api::form_policydoc_add($formdata);
api::make_current($optionalpolicy->get('id'));
// Decline this version.
api::decline_policies([$optionalpolicy->get('id')], $user->id, null);
// Generate new version and make it current.
$formdata = api::form_policydoc_data($optionalpolicy);
$formdata->revision = 'v2';
$optionalpolicynew = api::form_policydoc_update_new($formdata);
api::make_current($optionalpolicynew->get('id'));
// Accept all the current policies.
$ids = [
['versionid' => $this->policy2->get('id'), 'status' => 1],
['versionid' => $optionalpolicynew->get('id'), 'status' => 1],
];
$policies = \tool_policy\external\set_acceptances_status::execute($ids);
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\set_acceptances_status::execute_returns(), $policies);
$this->assertEquals(1, $policies['policyagreed']);
$this->assertCount(0, $policies['warnings']);
// And now accept and old one.
$ids = [['versionid' => $optionalpolicy->get('id'), 'status' => 1, 'note' => 'I accept for me.']]; // The note will be ignored.
$policies = \tool_policy\external\set_acceptances_status::execute($ids);
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\set_acceptances_status::execute_returns(), $policies);
// Retrieve and check all are accepted now.
$policies = \tool_policy\external\get_user_acceptances::execute();
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\get_user_acceptances::execute_returns(), $policies);
$this->assertCount(3, $policies['policies']);
foreach ($policies['policies'] as $policy) {
$this->assertEquals(1, $policy['acceptance']['status']); // Check all accepted.
$this->assertEmpty($policy['acceptance']['note']); // The note was not recorded because it was for itself.
}
// Decline optional only.
$policies = \tool_policy\external\set_acceptances_status::execute([['versionid' => $optionalpolicynew->get('id'), 'status' => 0]]);
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\set_acceptances_status::execute_returns(), $policies);
$this->assertEquals(1, $policies['policyagreed']);
$this->assertCount(0, $policies['warnings']);
$policies = \tool_policy\external\get_user_acceptances::execute();
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\get_user_acceptances::execute_returns(), $policies);
$this->assertCount(3, $policies['policies']);
foreach ($policies['policies'] as $policy) {
if ($policy['versionid'] == $optionalpolicynew->get('id')) {
$this->assertEquals(0, $policy['acceptance']['status']); // Not accepted.
} else {
$this->assertEquals(1, $policy['acceptance']['status']); // Accepted.
}
}
// Parent & child case now. Accept the optional ONLY on behalf of someone else.
$this->parent->policyagreed = 1;
$this->setUser($this->parent);
$notetext = 'I accept this on behalf of my child Santiago.';
$policies = \tool_policy\external\set_acceptances_status::execute(
[['versionid' => $optionalpolicynew->get('id'), 'status' => 1, 'note' => $notetext]], $this->child->id);
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\set_acceptances_status::execute_returns(), $policies);
$this->assertEquals(0, $policies['policyagreed']); // Mandatory missing.
$this->assertCount(0, $policies['warnings']);
$policies = \tool_policy\external\get_user_acceptances::execute($this->child->id);
$policies = \core_external\external_api::clean_returnvalue(
\tool_policy\external\get_user_acceptances::execute_returns(), $policies);
$this->assertCount(2, $policies['policies']);
foreach ($policies['policies'] as $policy) {
if ($policy['versionid'] == $this->policy2->get('id')) {
$this->assertNotContains('acceptance', $policy); // Not yet accepted.
$this->assertArrayNotHasKey('acceptance', $policy);
} else {
$this->assertEquals(1, $policy['acceptance']['status']); // Accepted.
$this->assertEquals($notetext, $policy['acceptance']['note']);
}
}
// Try to accept on behalf of other user with no permissions.
$this->expectException(\required_capability_exception::class);
$policies = \tool_policy\external\set_acceptances_status::execute([['versionid' => $optionalpolicynew->get('id'), 'status' => 1]], $user->id);
}
/**
* Test for external function set_acceptances_status decline mandatory.
*/
public function test_external_set_acceptances_status_decline_mandatory(): void {
global $CFG;
$this->resetAfterTest(true);
$CFG->sitepolicyhandler = 'tool_policy';
$this->parent->policyagreed = 1;
$this->setUser($this->parent);
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('errorpolicyversioncompulsory', 'tool_policy'));
$ids = [['versionid' => $this->policy2->get('id'), 'status' => 0]];
$policies = \tool_policy\external\set_acceptances_status::execute($ids, $this->child->id);
}
}
@@ -0,0 +1,395 @@
<?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/>.
/**
* Privacy provider tests.
*
* @package tool_policy
* @category test
* @copyright 2018 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_policy\privacy;
use core_privacy\local\metadata\collection;
use tool_policy\privacy\provider;
use tool_policy\api;
use tool_policy\policy_version;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\writer;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy provider tests class.
*
* @copyright 2018 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends \core_privacy\tests\provider_testcase {
/** @var stdClass The user object. */
protected $user;
/** @var stdClass The manager user object. */
protected $manager;
/** @var context_system The system context instance. */
protected $syscontext;
/**
* Setup function. Will create a user.
*/
protected function setUp(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$this->user = $generator->create_user();
// Create manager user.
$this->manager = $generator->create_user();
$this->syscontext = \context_system::instance();
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $this->syscontext->id);
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $this->syscontext->id);
role_assign($rolemanagerid, $this->manager->id, $this->syscontext->id);
accesslib_clear_all_caches_for_unit_testing();
}
/**
* Test getting the context for the user ID related to this plugin.
*/
public function test_get_contexts_for_userid(): void {
global $CFG;
// When there are no policies or agreements context list is empty.
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->manager->id);
$this->assertEmpty($contextlist);
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
$this->assertEmpty($contextlist);
// Create a policy.
$this->setUser($this->manager);
$CFG->sitepolicyhandler = 'tool_policy';
$policy = $this->add_policy();
api::make_current($policy->get('id'));
// After creating a policy, there should be manager context.
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->manager->id);
$this->assertEquals(1, $contextlist->count());
// But when there are no agreements, user context list is empty.
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
$this->assertEmpty($contextlist);
// Agree to the policy.
$this->setUser($this->user);
api::accept_policies([$policy->get('id')]);
// There should be user context.
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
$this->assertEquals(1, $contextlist->count());
}
/**
* Test getting the user IDs within the context related to this plugin.
*/
public function test_get_users_in_context(): void {
global $CFG;
$component = 'tool_policy';
// System context should have nothing before a policy is added.
$userlist = new \core_privacy\local\request\userlist($this->syscontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
// Create parent and child users.
$generator = $this->getDataGenerator();
$parentuser = $generator->create_user();
$childuser = $generator->create_user();
// Fetch relevant contexts.
$managercontext = \context_user::instance($this->manager->id);
$usercontext = $managercontext = \context_user::instance($this->user->id);
$parentcontext = $managercontext = \context_user::instance($parentuser->id);
$childcontext = $managercontext = \context_user::instance($childuser->id);
// Assign parent to accept on behalf of the child.
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $this->syscontext->id);
role_assign($roleparentid, $parentuser->id, $childcontext->id);
// Create a policy.
$this->setUser($this->manager);
$CFG->sitepolicyhandler = 'tool_policy';
$policy = $this->add_policy();
api::make_current($policy->get('id'));
// Manager should exist in system context now they have created a policy.
$userlist = new \core_privacy\local\request\userlist($this->syscontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(1, $userlist);
$this->assertEquals([$this->manager->id], $userlist->get_userids());
// User contexts should be empty before policy acceptances.
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
$userlist = new \core_privacy\local\request\userlist($parentcontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
$userlist = new \core_privacy\local\request\userlist($childcontext, $component);
provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
// User accepts policy, parent accepts on behalf of child only.
$this->setUser($this->user);
api::accept_policies([$policy->get('id')]);
$this->setUser($parentuser);
api::accept_policies([$policy->get('id')], $childuser->id);
// Ensure user is fetched within its user context.
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(1, $userlist);
$this->assertEquals([$this->user->id], $userlist->get_userids());
// Ensure parent and child are both found within child's user context.
$userlist = new \core_privacy\local\request\userlist($childcontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(2, $userlist);
$expected = [$parentuser->id, $childuser->id];
$actual = $userlist->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);
// Parent has not accepted for itself, so should not be found within its user context.
$userlist = new \core_privacy\local\request\userlist($parentcontext, $component);
provider::get_users_in_context($userlist);
$this->assertCount(0, $userlist);
}
public function test_export_agreements(): void {
global $CFG;
$otheruser = $this->getDataGenerator()->create_user();
$otherusercontext = \context_user::instance($otheruser->id);
// Create policies and agree to them as manager.
$this->setUser($this->manager);
$managercontext = \context_user::instance($this->manager->id);
$systemcontext = \context_system::instance();
$agreementsubcontext = [
get_string('privacyandpolicies', 'admin'),
get_string('useracceptances', 'tool_policy')
];
$versionsubcontext = [
get_string('policydocuments', 'tool_policy')
];
$CFG->sitepolicyhandler = 'tool_policy';
$policy1 = $this->add_policy();
api::make_current($policy1->get('id'));
$policy2 = $this->add_policy();
api::make_current($policy2->get('id'));
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
// Agree to the policies for oneself.
$this->setUser($this->user);
$usercontext = \context_user::instance($this->user->id);
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
// Request export for this user.
$contextlist = provider::get_contexts_for_userid($this->user->id);
$this->assertCount(1, $contextlist);
$this->assertEquals([$usercontext->id], $contextlist->get_contextids());
$approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
provider::export_user_data($approvedcontextlist);
// User can not see manager's agreements but can see his own.
$writer = writer::with_context($managercontext);
$this->assertFalse($writer->has_any_data());
$writer = writer::with_context($usercontext);
$this->assertTrue($writer->has_any_data());
// Test policy 1.
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
$datauser = $writer->get_data($subcontext);
$this->assertEquals($policy1->get('name'), $datauser->name);
$this->assertEquals($this->user->id, $datauser->agreedby);
$this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
$this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
// Test policy 2.
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
$datauser = $writer->get_data($subcontext);
$this->assertEquals($policy2->get('name'), $datauser->name);
$this->assertEquals($this->user->id, $datauser->agreedby);
$this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
$this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
}
public function test_export_agreements_for_other(): void {
global $CFG;
$managercontext = \context_user::instance($this->manager->id);
$systemcontext = \context_system::instance();
$usercontext = \context_user::instance($this->user->id);
// Create policies and agree to them as manager.
$this->setUser($this->manager);
$agreementsubcontext = [
get_string('privacyandpolicies', 'admin'),
get_string('useracceptances', 'tool_policy')
];
$versionsubcontext = [
get_string('policydocuments', 'tool_policy')
];
$CFG->sitepolicyhandler = 'tool_policy';
$policy1 = $this->add_policy();
api::make_current($policy1->get('id'));
$policy2 = $this->add_policy();
api::make_current($policy2->get('id'));
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
// Agree to the other user's policies.
api::accept_policies([$policy1->get('id'), $policy2->get('id')], $this->user->id, 'My note');
// Request export for the manager.
$contextlist = provider::get_contexts_for_userid($this->manager->id);
$this->assertCount(3, $contextlist);
$this->assertEqualsCanonicalizing(
[$managercontext->id, $usercontext->id, $systemcontext->id],
$contextlist->get_contextids()
);
$approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
provider::export_user_data($approvedcontextlist);
// The user context has data.
$writer = writer::with_context($usercontext);
$this->assertTrue($writer->has_any_data());
// Test policy 1.
$writer = writer::with_context($usercontext);
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
$datauser = $writer->get_data($subcontext);
$this->assertEquals($policy1->get('name'), $datauser->name);
$this->assertEquals($this->manager->id, $datauser->agreedby);
$this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
$this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
// Test policy 2.
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
$datauser = $writer->get_data($subcontext);
$this->assertEquals($policy2->get('name'), $datauser->name);
$this->assertEquals($this->manager->id, $datauser->agreedby);
$this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
$this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
}
public function test_export_created_policies(): void {
global $CFG;
// Create policies and agree to them as manager.
$this->setUser($this->manager);
$managercontext = \context_user::instance($this->manager->id);
$systemcontext = \context_system::instance();
$agreementsubcontext = [
get_string('privacyandpolicies', 'admin'),
get_string('useracceptances', 'tool_policy')
];
$versionsubcontext = [
get_string('policydocuments', 'tool_policy')
];
$CFG->sitepolicyhandler = 'tool_policy';
$policy1 = $this->add_policy();
api::make_current($policy1->get('id'));
$policy2 = $this->add_policy();
api::make_current($policy2->get('id'));
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
// Agree to the policies for oneself.
$contextlist = provider::get_contexts_for_userid($this->manager->id);
$this->assertCount(2, $contextlist);
$this->assertEqualsCanonicalizing([$managercontext->id, $systemcontext->id], $contextlist->get_contextids());
$approvedcontextlist = new approved_contextlist($this->manager, 'tool_policy', $contextlist->get_contextids());
provider::export_user_data($approvedcontextlist);
// User has agreed to policies.
$writer = writer::with_context($managercontext);
$this->assertTrue($writer->has_any_data());
// Test policy 1.
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
$datauser = $writer->get_data($subcontext);
$this->assertEquals($policy1->get('name'), $datauser->name);
$this->assertEquals($this->manager->id, $datauser->agreedby);
$this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
$this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
// Test policy 2.
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
$datauser = $writer->get_data($subcontext);
$this->assertEquals($policy2->get('name'), $datauser->name);
$this->assertEquals($this->manager->id, $datauser->agreedby);
$this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
$this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
// User can see policy documents.
$writer = writer::with_context($systemcontext);
$this->assertTrue($writer->has_any_data());
$subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
$dataversion = $writer->get_data($subcontext);
$this->assertEquals($policy1->get('name'), $dataversion->name);
$this->assertEquals(get_string('yes'), $dataversion->createdbyme);
$subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
$dataversion = $writer->get_data($subcontext);
$this->assertEquals($policy2->get('name'), $dataversion->name);
$this->assertEquals(get_string('yes'), $dataversion->createdbyme);
}
/**
* Helper method that creates a new policy for testing
*
* @param array $params
* @return policy_version
*/
protected function add_policy($params = []) {
static $counter = 0;
$counter++;
$defaults = [
'name' => 'Policy '.$counter,
'summary_editor' => ['text' => "P$counter summary", 'format' => FORMAT_HTML, 'itemid' => 0],
'content_editor' => ['text' => "P$counter content", 'format' => FORMAT_HTML, 'itemid' => 0],
];
$params = (array)$params + $defaults;
$formdata = \tool_policy\api::form_policydoc_data(new policy_version(0));
foreach ($params as $key => $value) {
$formdata->$key = $value;
}
return api::form_policydoc_add($formdata);
}
}
@@ -0,0 +1,126 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_policy;
use tool_policy\privacy\local\sitepolicy\handler;
use tool_policy\test\helper;
/**
* Unit tests for the {@link \tool_policy\privacy\local\sitepolicy\handler} class.
*
* @package tool_policy
* @category test
* @copyright 2018 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sitepolicy_handler_test extends \advanced_testcase {
/**
* Test behaviour of the {@link \tool_policy\privacy\local\sitepolicy\handler::get_redirect_url()} method.
*/
public function test_get_redirect_url(): void {
$this->resetAfterTest();
$this->setAdminUser();
// No redirect for guests.
$this->assertNull(handler::get_redirect_url(true));
// No redirect if there is no policy.
$this->assertNull(handler::get_redirect_url());
// No redirect if no policy for logged in users.
$policy1 = helper::add_policy(['audience' => policy_version::AUDIENCE_GUESTS])->to_record();
api::make_current($policy1->id);
$this->assertNull(handler::get_redirect_url());
// URL only when there is actually some policy to show.
$policy2 = helper::add_policy(['audience' => policy_version::AUDIENCE_LOGGEDIN])->to_record();
api::make_current($policy2->id);
$this->assertInstanceOf('moodle_url', handler::get_redirect_url());
}
/**
* Test behaviour of the {@link \tool_policy\privacy\local\sitepolicy\handler::get_embed_url()} method.
*/
public function test_get_embed_url(): void {
$this->resetAfterTest();
$this->setAdminUser();
// No embed if there is no policy.
$this->assertNull(handler::get_embed_url());
$this->assertNull(handler::get_embed_url(true));
$policy1 = helper::add_policy(['audience' => policy_version::AUDIENCE_GUESTS])->to_record();
api::make_current($policy1->id);
// Policy exists for guests only.
$this->assertNull(handler::get_embed_url());
$this->assertInstanceOf('moodle_url', handler::get_embed_url(true));
$policy2 = helper::add_policy(['audience' => policy_version::AUDIENCE_LOGGEDIN])->to_record();
api::make_current($policy2->id);
// Some policy exists for all users.
$this->assertInstanceOf('moodle_url', handler::get_embed_url());
$this->assertInstanceOf('moodle_url', handler::get_embed_url(true));
}
/**
* Test behaviour of the {@link \tool_policy\privacy\local\sitepolicy\handler::accept()} method.
*/
public function test_accept(): void {
global $DB, $USER;
$this->resetAfterTest();
// False if not logged in.
$this->setUser(0);
$this->assertFalse(handler::accept());
// Guests accept policies implicitly by continuing to use the site.
$this->setGuestUser();
$this->assertTrue(handler::accept());
// Create one compulsory and one optional policy.
$this->setAdminUser();
$policy1 = helper::add_policy(['optional' => policy_version::AGREEMENT_COMPULSORY])->to_record();
api::make_current($policy1->id);
$policy2 = helper::add_policy(['optional' => policy_version::AGREEMENT_OPTIONAL])->to_record();
api::make_current($policy2->id);
$user1 = $this->getDataGenerator()->create_user();
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
$this->assertEmpty($DB->get_records('tool_policy_acceptances', ['userid' => $user1->id]));
$this->setUser($user1->id);
$this->assertEquals(0, $USER->policyagreed);
// Only the compulsory policy is marked as accepted when accepting via the handler.
$this->assertTrue(handler::accept());
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
$this->assertEquals(1, $USER->policyagreed);
$this->assertEquals(1, $DB->count_records('tool_policy_acceptances', ['userid' => $user1->id]));
$this->assertTrue($DB->record_exists('tool_policy_acceptances', ['userid' => $user1->id,
'policyversionid' => $policy1->id]));
}
/**
* Test presence of the {@link \tool_policy\privacy\local\sitepolicy\handler::signup_form()} method.
*/
public function test_signup_form(): void {
$this->assertTrue(method_exists('\tool_policy\privacy\local\sitepolicy\handler', 'signup_form'));
}
}