MDL-83468 phpunit: Fix various tests after phpunit 10

This commit is contained in:
Andrew Nicols 2024-10-16 11:58:29 +08:00 committed by Sara Arjona
parent b95a8c6ecc
commit bc75ef8bbc
No known key found for this signature in database
51 changed files with 717 additions and 659 deletions

1
.gitignore vendored
View file

@ -59,3 +59,4 @@ moodle-plugin-ci.phar
phpcs.xml
jsconfig.json
UPGRADING-CURRENT.md
.phpunit.cache

View file

@ -468,7 +468,7 @@ final class manager_util_test extends \advanced_testcase {
$CFG->dirroot = $oldroot;
}
public function clean_features_path_list() {
public static function clean_features_path_list() {
return array(
['/home/test/this/that/test/behat/mod_assign.feature', 'mod_assign_behat_test_that_this_test', '/home/test/this/that/test/behat/mod_assign.feature'],
['/home/this/that/test/behat/mod_assign.feature', 'mod_assign_behat_test_that_this_home', '/home/this/that/test/behat/mod_assign.feature'],

View file

@ -89,13 +89,13 @@ final class data_request_test extends data_privacy_testcase {
* Test the pseudo states of a data request with an export request.
*
* @dataProvider status_state_provider
* @param int $status
* @param int $state
* @param bool $resettable
* @param bool $active
*/
public function test_pseudo_states_export(int $status, bool $resettable, bool $active): void {
public function test_pseudo_states_export(int $state, bool $resettable, bool $active): void {
$uut = new \tool_dataprivacy\data_request();
$uut->set('status', $status);
$uut->set('status', $state);
$uut->set('type', api::DATAREQUEST_TYPE_EXPORT);
$this->assertEquals($resettable, $uut->is_resettable());
@ -106,13 +106,13 @@ final class data_request_test extends data_privacy_testcase {
* Test the pseudo states of a data request with a delete request.
*
* @dataProvider status_state_provider
* @param int $status
* @param int $state
* @param bool $resettable
* @param bool $active
*/
public function test_pseudo_states_delete(int $status, bool $resettable, bool $active): void {
public function test_pseudo_states_delete(int $state, bool $resettable, bool $active): void {
$uut = new \tool_dataprivacy\data_request();
$uut->set('status', $status);
$uut->set('status', $state);
$uut->set('type', api::DATAREQUEST_TYPE_DELETE);
$this->assertEquals($resettable, $uut->is_resettable());
@ -123,11 +123,11 @@ final class data_request_test extends data_privacy_testcase {
* Test the pseudo states of a data request.
*
* @dataProvider status_state_provider
* @param int $status
* @param int $state
*/
public function test_can_reset_others($status): void {
public function test_can_reset_others(int $state, bool $resettable, bool $active): void {
$uut = new \tool_dataprivacy\data_request();
$uut->set('status', $status);
$uut->set('status', $state);
$uut->set('type', api::DATAREQUEST_TYPE_OTHERS);
$this->assertFalse($uut->is_resettable());
@ -142,7 +142,7 @@ final class data_request_test extends data_privacy_testcase {
$states = [];
foreach (self::status_state_provider() as $thisstatus) {
if (!$thisstatus['resettable']) {
$states[] = $thisstatus;
$states[] = ['state' => $thisstatus['state']];
}
}
@ -153,11 +153,11 @@ final class data_request_test extends data_privacy_testcase {
* Ensure that requests which are not resettable cause an exception to be thrown.
*
* @dataProvider non_resettable_provider
* @param int $status
* @param int $state
*/
public function test_non_resubmit_request($status): void {
public function test_non_resubmit_request($state): void {
$uut = new \tool_dataprivacy\data_request();
$uut->set('status', $status);
$uut->set('status', $state);
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('cannotreset', 'tool_dataprivacy'));

View file

@ -61,28 +61,28 @@ final class filtered_userlist_test extends \advanced_testcase {
return [
// Entire list should be preserved.
'No overrides' => [
'users' => [1, 2, 3, 4, 5],
'initial' => [1, 2, 3, 4, 5],
'expired' => [],
'unexpired' => [],
[1, 2, 3, 4, 5],
'expected' => [1, 2, 3, 4, 5],
],
// The list should be filtered to only keep the expired users.
'Expired only' => [
'users' => [1, 2, 3, 4, 5],
'initial' => [1, 2, 3, 4, 5],
'expired' => [2, 3, 4],
'unexpired' => [],
'expected' => [2, 3, 4],
],
// The list should be filtered to remove any unexpired users.
'Unexpired only' => [
'users' => [1, 2, 3, 4, 5],
'initial' => [1, 2, 3, 4, 5],
'expired' => [],
'unexpired' => [1, 5],
'expected' => [2, 3, 4],
],
// The list should be filtered to only keep expired users who are not on the unexpired list.
'Combination of expired and unexpired' => [
'users' => [1, 2, 3, 4, 5],
'initial' => [1, 2, 3, 4, 5],
'expired' => [1, 2, 3],
'unexpired' => [1, 5],
'expected' => [2, 3],

View file

@ -134,15 +134,15 @@ final class httpsreplace_test extends \advanced_testcase {
/**
* Test upgrade_http_links
* @param string $content Example content that we'll attempt to replace.
* @param string $ouputregex Regex for what output we expect.
* @param string $outputregex Regex for what output we expect.
* @param string $expectedcontent What content we are expecting afterwards.
* @dataProvider upgrade_http_links_provider
*/
public function test_upgrade_http_links($content, $ouputregex, $expectedcontent): void {
public function test_upgrade_http_links($content, $outputregex, $expectedcontent): void {
global $DB;
$this->resetAfterTest();
$this->expectOutputRegex($ouputregex);
$this->expectOutputRegex($outputregex);
$finder = new tool_httpreplace_url_finder_mock();

View file

@ -32,7 +32,7 @@ final class url_test extends \advanced_testcase {
* Test the parsing to host + path components.
*
* @dataProvider url_provider
* @param string $urlstring The full URL string
* @param string $url The full URL string
* @param string $host the expected host component of the URL.
* @param string $path the expected path component of the URL.
* @param bool $exception whether or not an exception is expected during construction.
@ -58,37 +58,37 @@ final class url_test extends \advanced_testcase {
public static function url_provider(): array {
return [
'No path' => [
'url' => 'https://example.moodle.net',
'urlstring' => 'https://example.moodle.net',
'host' => 'example.moodle.net',
'path' => null,
'exception' => false,
],
'Slash path' => [
'url' => 'https://example.moodle.net/',
'urlstring' => 'https://example.moodle.net/',
'host' => 'example.moodle.net',
'path' => '/',
'exception' => false,
],
'Path includes file and extension' => [
'url' => 'https://example.moodle.net/uploads/123456789/pic.png',
'urlstring' => 'https://example.moodle.net/uploads/123456789/pic.png',
'host' => 'example.moodle.net',
'path' => '/uploads/123456789/pic.png',
'exception' => false,
],
'Path includes file, extension and params' => [
'url' => 'https://example.moodle.net/uploads/123456789/pic.png?option=1&option2=test',
'urlstring' => 'https://example.moodle.net/uploads/123456789/pic.png?option=1&option2=test',
'host' => 'example.moodle.net',
'path' => '/uploads/123456789/pic.png',
'exception' => false,
],
'Malformed - invalid' => [
'url' => 'invalid',
'urlstring' => 'invalid',
'host' => null,
'path' => null,
'exception' => true,
],
'Direct, non-encoded utf8 - invalid' => [
'url' => 'http://москва.рф/services/',
'urlstring' => 'http://москва.рф/services/',
'host' => 'москва.рф',
'path' => '/services/',
'exception' => true,

View file

@ -379,8 +379,8 @@ final class event_factory_test extends \advanced_testcase {
'bailoutcheck' => function() {
return false;
},
event_interface::class,
'Hello'
'expectedclass' => event_interface::class,
'expectedattributevalue' => 'Hello'
],
'Sample event record with event hidden' => [
'dbrow' => (object)[
@ -413,8 +413,8 @@ final class event_factory_test extends \advanced_testcase {
'bailoutcheck' => function() {
return false;
},
null,
null
'expectedclass' => null,
'expectedattributevalue' => null
],
'Sample event record with early bail' => [
'dbrow' => (object)[
@ -447,8 +447,8 @@ final class event_factory_test extends \advanced_testcase {
'bailoutcheck' => function() {
return true;
},
null,
null
'expectedclass' => null,
'expectedattributevalue' => null
]
];
}

View file

@ -20,6 +20,10 @@
"autoload-dev": {
"psr-0": {
"Moodle\\BehatExtension": "lib/behat/extension/"
},
"psr-4": {
"core_testing\\": "lib/testing/classes/",
"core_phpunit\\": "lib/phpunit/classes/"
}
},
"minimum-stability": "dev",

View file

@ -194,27 +194,27 @@ final class stateactions_test extends \advanced_testcase {
public static function basic_role_provider(): array {
return [
'admin' => [
'role' => 'admin',
'rolename' => 'admin',
'expectedexception' => false,
],
'editingteacher' => [
'role' => 'editingteacher',
'rolename' => 'editingteacher',
'expectedexception' => false,
],
'teacher' => [
'role' => 'teacher',
'rolename' => 'teacher',
'expectedexception' => true,
],
'student' => [
'role' => 'student',
'rolename' => 'student',
'expectedexception' => true,
],
'guest' => [
'role' => 'guest',
'rolename' => 'guest',
'expectedexception' => true,
],
'unenroled' => [
'role' => 'unenroled',
'rolename' => 'unenroled',
'expectedexception' => true,
],
];

View file

@ -49,7 +49,7 @@ final class migration_claim_test extends \advanced_testcase {
* Test instantiation and getters of the migration_claim.
*
* @dataProvider migration_claim_provider
* @param array $migrationclaimdata the lti1p1 migration claim.
* @param array $lti1p1migrationclaim the lti1p1 migration claim.
* @param string $deploymentid string id of the tool deployment.
* @param string $platform string url of the issuer.
* @param string $clientid string id of the client.
@ -60,7 +60,7 @@ final class migration_claim_test extends \advanced_testcase {
* @covers ::__construct
*/
public function test_migration_claim(
array $migrationclaimdata,
array $lti1p1migrationclaim,
string $deploymentid,
string $platform,
string $clientid,
@ -79,7 +79,7 @@ final class migration_claim_test extends \advanced_testcase {
$this->expectException($expected['exception']);
$this->expectExceptionMessage($expected['exceptionmessage']);
new migration_claim(
$migrationclaimdata,
$lti1p1migrationclaim,
$deploymentid,
$platform,
$clientid,
@ -89,7 +89,7 @@ final class migration_claim_test extends \advanced_testcase {
);
} else {
$migrationclaim = new migration_claim(
$migrationclaimdata,
$lti1p1migrationclaim,
$deploymentid,
$platform,
$clientid,

View file

@ -98,28 +98,28 @@ final class application_registration_repository_test extends \advanced_testcase
*
* @dataProvider save_data_provider
* @covers ::save
* @param array $regdata the registration data
* @param array $registrationdata the registration data
*/
public function test_save_new(array $regdata): void {
public function test_save_new(array $registrationdata): void {
$this->resetAfterTest();
$reg = application_registration::create_draft($regdata['name'], $regdata['uniqueid']);
if (isset($regdata['platformid'])) {
$reg->set_platformid($regdata['platformid']);
$reg = application_registration::create_draft($registrationdata['name'], $registrationdata['uniqueid']);
if (isset($registrationdata['platformid'])) {
$reg->set_platformid($registrationdata['platformid']);
}
if (isset($regdata['clientid'])) {
$reg->set_clientid($regdata['clientid']);
if (isset($registrationdata['clientid'])) {
$reg->set_clientid($registrationdata['clientid']);
}
if (isset($regdata['authenticationrequesturl'])) {
$reg->set_authenticationrequesturl($regdata['authenticationrequesturl']);
if (isset($registrationdata['authenticationrequesturl'])) {
$reg->set_authenticationrequesturl($registrationdata['authenticationrequesturl']);
}
if (isset($regdata['jwksurl'])) {
$reg->set_jwksurl($regdata['jwksurl']);
if (isset($registrationdata['jwksurl'])) {
$reg->set_jwksurl($registrationdata['jwksurl']);
}
if (isset($regdata['accesstokenurl'])) {
$reg->set_accesstokenurl($regdata['accesstokenurl']);
if (isset($registrationdata['accesstokenurl'])) {
$reg->set_accesstokenurl($registrationdata['accesstokenurl']);
}
if (!empty($regdata['setcomplete'])) {
if (!empty($registrationdata['setcomplete'])) {
$reg->complete_registration();
}
$repository = new application_registration_repository();

View file

@ -126,8 +126,8 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
public static function user_launch_provider(): array {
return [
'New tool: no legacy data, no migration claim sent' => [
'legacy_data' => null,
'launch_data' => [
'legacydata' => null,
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
@ -136,14 +136,14 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
]
],
'Migrated tool: Legacy data exists, no change in user_id so omitted from claim' => [
'legacy_data' => [
'legacydata' => [
'consumer_key' => 'CONSUMER_1',
'tools' => [
['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'],
]
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -159,14 +159,14 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
],
'Migrated tool: Legacy data exists, platform signs with different valid secret' => [
'legacy_data' => [
'legacydata' => [
'consumer_key' => 'CONSUMER_1',
'tools' => [
['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'],
]
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -181,14 +181,14 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
]
],
'Migrated tool: Legacy data exists, no migration claim sent' => [
'legacy_data' => [
'legacydata' => [
'consumer_key' => 'CONSUMER_1',
'tools' => [
['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'],
]
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
@ -197,14 +197,14 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
]
],
'Migrated tool: Legacy data exists, migration claim signature generated using invalid secret' => [
'legacy_data' => [
'legacydata' => [
'consumer_key' => 'CONSUMER_1',
'tools' => [
['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'],
]
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -221,14 +221,14 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
]
],
'Migrated tool: Legacy data exists, migration claim signature omitted' => [
'legacy_data' => [
'legacydata' => [
'consumer_key' => 'CONSUMER_1',
'tools' => [
['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'],
]
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -244,14 +244,14 @@ final class tool_launch_service_test extends \lti_advantage_testcase {
]
],
'Migrated tool: Legacy data exists, migration claim missing oauth_consumer_key' => [
'legacy_data' => [
'legacydata' => [
'consumer_key' => 'CONSUMER_1',
'tools' => [
['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'],
]
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [
'user_id' => 'user-id-123',

View file

@ -800,7 +800,7 @@ final class sync_members_test extends \lti_advantage_testcase {
require_once($CFG->dirroot . '/auth/lti/auth.php');
return [
'Migrated tool, user ids changed, new and existing users present in sync' => [
'legacy_data' => [
'legacydata' => [
'users' => [
['user_id' => '1'],
['user_id' => '2'],
@ -811,8 +811,8 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'],
]
],
'resource_config' => null,
'launch_data' => [
'resourceconfig' => null,
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -823,7 +823,7 @@ final class sync_members_test extends \lti_advantage_testcase {
'resource_link_id' => '4b6fa'
],
],
'sync_members_data' => [
'syncmembers' => [
self::get_mock_members_with_ids(['1p3_1'], ['1'])[0],
self::get_mock_members_with_ids(['1p3_2'], ['2'])[0],
self::get_mock_members_with_ids(['1p3_3'], ['3'])[0],
@ -851,7 +851,7 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'Migrated tool, no change in user ids, new and existing users present in sync' => [
'legacy_data' => [
'legacydata' => [
'users' => [
['user_id' => '1'],
['user_id' => '2'],
@ -862,8 +862,8 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'],
]
],
'resource_config' => null,
'launch_data' => [
'resourceconfig' => null,
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -873,7 +873,7 @@ final class sync_members_test extends \lti_advantage_testcase {
'resource_link_id' => '4b6fa'
],
],
'sync_members_data' => [
'syncmembers' => [
self::get_mock_members_with_ids(['1'], null)[0],
self::get_mock_members_with_ids(['2'], null)[0],
self::get_mock_members_with_ids(['3'], null)[0],
@ -901,7 +901,7 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'New tool, no launch migration claim, change in user ids, new and existing users present in sync' => [
'legacy_data' => [
'legacydata' => [
'users' => [
['user_id' => '1'],
['user_id' => '2'],
@ -912,12 +912,12 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'],
]
],
'resource_config' => null,
'launch_data' => [
'resourceconfig' => null,
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
'sync_members_data' => [
'syncmembers' => [
self::get_mock_members_with_ids(['1p3_1'], null)[0],
self::get_mock_members_with_ids(['1p3_2'], null)[0],
self::get_mock_members_with_ids(['1p3_3'], null)[0],
@ -945,7 +945,7 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'New tool, no launch migration claim, no change in user ids, new and existing users present in sync' => [
'legacy_data' => [
'legacydata' => [
'users' => [
['user_id' => '1'],
['user_id' => '2'],
@ -956,12 +956,12 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'],
]
],
'resource_config' => null,
'launch_data' => [
'resourceconfig' => null,
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1'])[0],
'launch_migration_claim' => null,
],
'sync_members_data' => [
'syncmembers' => [
self::get_mock_members_with_ids(['1'], null)[0],
self::get_mock_members_with_ids(['2'], null)[0],
self::get_mock_members_with_ids(['3'], null)[0],
@ -989,7 +989,7 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'New tool, migration only via member sync, no launch claim, new and existing users present in sync' => [
'legacy_data' => [
'legacydata' => [
'users' => [
['user_id' => '1'],
['user_id' => '2'],
@ -1000,12 +1000,12 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'],
]
],
'resource_config' => null,
'launch_data' => [
'resourceconfig' => null,
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
'sync_members_data' => [
'syncmembers' => [
self::get_mock_members_with_ids(['1p3_1'], ['1'])[0],
self::get_mock_members_with_ids(['1p3_2'], ['2'])[0],
self::get_mock_members_with_ids(['1p3_3'], ['3'])[0],
@ -1033,16 +1033,16 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'Default provisioning modes, mixed bag of users and roles' => [
'legacy_data' => null,
'resource_config' => [
'legacydata' => null,
'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY,
'provisioningmodeinstructor' => \auth_plugin_lti::PROVISIONING_MODE_PROMPT_NEW_EXISTING
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
'sync_members_data' => [
'syncmembers' => [
// This user is just an instructor but is also the user who is already linked, via the launch above.
self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
@ -1083,16 +1083,16 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'All automatic provisioning, mixed bag of users and roles' => [
'legacy_data' => null,
'resource_config' => [
'legacydata' => null,
'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY,
'provisioningmodeinstructor' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
'sync_members_data' => [
'syncmembers' => [
// This user is just an instructor but is also the user who is already linked, via the launch above.
self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
@ -1133,16 +1133,16 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'All prompt provisioning, mixed bag of users and roles' => [
'legacy_data' => null,
'resource_config' => [
'legacydata' => null,
'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_PROMPT_NEW_EXISTING,
'provisioningmodeinstructor' => \auth_plugin_lti::PROVISIONING_MODE_PROMPT_NEW_EXISTING
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null,
],
'sync_members_data' => [
'syncmembers' => [
// This user is just an instructor but is also the user who is already linked, via the launch above.
self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
@ -1183,7 +1183,7 @@ final class sync_members_test extends \lti_advantage_testcase {
]
],
'All automatic provisioning, with legacy data and migration claim, mixed bag of users and roles' => [
'legacy_data' => [
'legacydata' => [
'users' => [
['user_id' => '2'],
['user_id' => '3'],
@ -1196,11 +1196,11 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'],
]
],
'resource_config' => [
'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY,
'provisioningmodeinstructor' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY
],
'launch_data' => [
'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1',
@ -1210,7 +1210,7 @@ final class sync_members_test extends \lti_advantage_testcase {
'resource_link_id' => '4b6fa'
],
],
'sync_members_data' => [
'syncmembers' => [
// This user is just an instructor but is also the user who is already linked, via the launch above.
self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',

View file

@ -603,7 +603,7 @@ final class lib_test extends \advanced_testcase {
'notifyall' => 0,
'expirythreshold' => 12 * HOURSECS,
],
'global settings' => (object) [
'globalsettings' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 0,
@ -620,7 +620,7 @@ final class lib_test extends \advanced_testcase {
'notifyall' => 0,
'expirythreshold' => DAYSECS,
],
'global settings' => (object) [
'globalsettings' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 72 * HOURSECS,
@ -637,7 +637,7 @@ final class lib_test extends \advanced_testcase {
'notifyall' => 1,
'expirythreshold' => 0
],
'global settings' => (object) [
'globalsettings' => (object) [
'status' => ENROL_INSTANCE_DISABLED,
'roleid' => $teacherrole->id,
'enrolperiod' => 0,
@ -717,7 +717,7 @@ final class lib_test extends \advanced_testcase {
'notifyall' => 0,
'expirythreshold' => 2 * DAYSECS,
],
'update data' => (object) [
'updatedata' => (object) [
'status' => ENROL_INSTANCE_DISABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 30 * DAYSECS,
@ -734,7 +734,7 @@ final class lib_test extends \advanced_testcase {
'notifyall' => 0,
'expirythreshold' => 0,
],
'update data' => (object) [
'updatedata' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $teacherrole->id,
'enrolperiod' => 0,
@ -751,7 +751,7 @@ final class lib_test extends \advanced_testcase {
'notifyall' => 1,
'expirythreshold' => 2 * DAYSECS,
],
'update data' => (object) [
'updatedata' => (object) [
'status' => ENROL_INSTANCE_ENABLED,
'roleid' => $studentrole->id,
'enrolperiod' => 30 * DAYSECS,

View file

@ -153,7 +153,7 @@ class core_date {
// Is server timezone usable?
if (isset($CFG->timezone) and !is_numeric($CFG->timezone)) {
$result = @timezone_open($CFG->timezone); // Hide notices if invalid.
$result = timezone_open($CFG->timezone); // Hide notices if invalid.
if ($result !== false) {
return $result->getName();
}
@ -319,7 +319,7 @@ class core_date {
if (!defined('PHPUNIT_TEST')) {
throw new coding_exception('core_date::phpunit_override_default_php_timezone() must be used only from unit tests');
}
$result = timezone_open($tz ?? ''); // This triggers error if $tz invalid.
$result = @timezone_open($tz ?? ''); // This triggers error if $tz invalid.
if ($result !== false) {
self::$defaultphptimezone = $tz;
} else {

View file

@ -280,6 +280,9 @@ final class dml_pgsql_read_replica_test extends \advanced_testcase {
];
$this->resetDebugging();
set_error_handler(function ($errno, $errstr) {
$this->assertStringContainsString('could not connect to server', $errstr);
}, E_ALL);
$db2 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary);
$db2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions);
$this->assertNotEmpty($db2->get_records('user'));
@ -301,5 +304,7 @@ final class dml_pgsql_read_replica_test extends \advanced_testcase {
);
// Attempt to connect to the existing DB host will succeed.
$this->assertEquals("Readwrite db connection succeeded for host {$cfg->dbhost}", $debugging[1]);
$this->assertTrue(count($db2->get_records('user')) > 0);
restore_error_handler();
}
}

View file

@ -45,7 +45,7 @@ final class dml_table_test extends \database_driver_testcase {
'primarykey' => 'id',
'fieldprefix' => 'ban',
'tablealias' => 'banana',
'banana.id AS banid',
'expected' => 'banana.id AS banid',
],
'multiple fields' => [
'tablename' => 'test_table_multiple',
@ -57,7 +57,7 @@ final class dml_table_test extends \database_driver_testcase {
'primarykey' => 'id',
'fieldprefix' => 'ban',
'tablealias' => 'banana',
'banana.id AS banid, banana.course AS bancourse, banana.name AS banname',
'expected' => 'banana.id AS banid, banana.course AS bancourse, banana.name AS banname',
],
];
}

View file

@ -487,7 +487,8 @@ final class dml_test extends \database_driver_testcase {
$DB = $this->tdb;
require_once($CFG->dirroot . '/lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php');
$fixture = new \test_dml_sql_debugging_fixture($this);
$databasemock = $this->getMockBuilder(\moodle_database::class)->getMock();
$fixture = new \test_dml_sql_debugging_fixture($databasemock);
$sql = "SELECT * FROM {users}";
@ -499,31 +500,31 @@ final class dml_test extends \database_driver_testcase {
$CFG->debugsqltrace = 1;
$out = $fixture->four($sql);
$expected = <<<EOD
SELECT * FROM {users}
-- line 64 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to ReflectionMethod->invoke()
SELECT \* FROM {users}
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to ReflectionMethod->invoke\(\)
EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out);
$this->assertMatchesRegularExpression('@' . $this->unix_to_os_dirsep($expected) . '@', $out);
$CFG->debugsqltrace = 2;
$out = $fixture->four($sql);
$expected = <<<EOD
SELECT * FROM {users}
-- line 64 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to ReflectionMethod->invoke()
-- line 73 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->one()
SELECT \* FROM {users}
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to ReflectionMethod->invoke\(\)
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->one\(\)
EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out);
$this->assertMatchesRegularExpression('@' . $this->unix_to_os_dirsep($expected) . '@', $out);
$CFG->debugsqltrace = 5;
$out = $fixture->four($sql);
$expected = <<<EOD
SELECT * FROM {users}
-- line 64 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to ReflectionMethod->invoke()
-- line 73 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->one()
-- line 82 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->two()
-- line 91 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->three()
-- line 517 of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four()
SELECT \* FROM {users}
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to ReflectionMethod->invoke\(\)
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->one\(\)
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->two\(\)
-- line \d+ of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->three\(\)
-- line \d+ of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four\(\)
EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out);
$this->assertMatchesRegularExpression('@' . $this->unix_to_os_dirsep($expected) . '@', $out);
$CFG->debugsqltrace = 0;
}
@ -4666,7 +4667,7 @@ EOD;
'name' => 'Bob',
'falias' => 'Dan, Grace',
],
], $DB->get_records_sql($sql));
], array_values($DB->get_records_sql($sql)));
}
/**

View file

@ -34,16 +34,14 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_dml_sql_debugging_fixture {
/** @var db handle */
private $db;
/**
* constructor
* @param testcase $testcase test object
* Constructor
* @param \moodle_database $db The database handle to use for this fixture
*/
public function __construct($testcase) {
$this->db = $testcase->getMockBuilder(\moodle_database::class)
->getMockForAbstractClass();
public function __construct(
/** @var \moodle_database The database handle to use for this fixture */
private \moodle_database $db,
) {
}
/**

View file

@ -29,6 +29,7 @@ use stdClass, ReflectionClass;
use moodle_database, pgsql_native_moodle_database;
use xmldb_table;
use moodle_exception;
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
/**
* Test specific features of the Postgres dml.
@ -396,6 +397,7 @@ final class pgsql_native_moodle_database_test extends \advanced_testcase {
/**
* Test SSL connection.
*/
#[WithoutErrorHandler]
public function test_ssl_connection(): void {
$pgconnerr = 'pg_connect(): Unable to connect to PostgreSQL server:';

View file

@ -536,24 +536,14 @@ final class zip_packer_test extends \advanced_testcase implements file_progress
unlink($textfile);
// Behavior is different between old PHP versions and new ones. Let's detect it.
$result = false;
try {
// Old PHP versions were not printing any warning.
$result = $zip_archive->close();
} catch (\Exception $e) {
// New PHP versions print PHP Warning.
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e);
$this->assertStringContainsString('ZipArchive::close', $e->getMessage());
}
// This is crazy, but it shows how some PHP versions do return true.
try {
// And some PHP versions do return correctly false (5.4.25, 5.6.14...)
$this->assertFalse($result);
} catch (\Exception $e) {
// But others do insist into returning true (5.6.13...). Only can accept them.
$this->assertInstanceOf('PHPUnit\Framework\ExpectationFailedException', $e);
$this->assertTrue($result);
}
set_error_handler(function ($errno, $errstr) use (&$result) {
$result = $errstr;
$this->assertStringContainsString('ZipArchive::close', $errstr);
}, E_WARNING);
$this->assertFalse($zip_archive->close());
$this->assertFileDoesNotExist($archive);
restore_error_handler();
}
/**

View file

@ -20,6 +20,8 @@ use core\http_client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
/**
* Advanced PHPUnit test case customised for Moodle.
@ -46,21 +48,16 @@ abstract class advanced_testcase extends base_testcase {
* Note: use setUp() or setUpBeforeClass() in your test cases.
*
* @param string $name
* @param array $data
* @param string $dataName
*/
final public function __construct($name = null, array $data = [], $dataname = '') {
parent::__construct($name, $data, $dataname);
final public function __construct(string $name = null) {
parent::__construct($name);
$this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setPreserveGlobalState(false);
}
/**
* Runs the bare test sequence.
*/
final public function runBare(): void {
#[Before]
final public function setup_test_environment(): void {
global $CFG, $DB;
if (phpunit_util::$lastdbwrites != $DB->perf_get_writes()) {
@ -71,28 +68,18 @@ abstract class advanced_testcase extends base_testcase {
$this->testdbtransaction = $DB->start_delegated_transaction();
}
try {
$this->setCurrentTimeStart();
parent::runBare();
} catch (Exception $ex) {
$e = $ex;
} catch (Throwable $ex) {
// Engine errors in PHP7 throw exceptions of type Throwable (this "catch" will be ignored in PHP5).
$e = $ex;
} finally {
}
#[After]
final public function teardown_test_environment(): void {
global $CFG, $DB;
// Reset global state after test and test failure.
$CFG = phpunit_util::get_global_backup('CFG');
$DB = phpunit_util::get_global_backup('DB');
// We need to reset the autoloader.
\core_component::reset();
}
if (isset($e)) {
// Cleanup after failed expectation.
self::resetAllData();
throw $e;
}
// Deal with any debugging messages.
$debugerror = phpunit_util::display_debugging_messages(true);

View file

@ -1,5 +1,4 @@
<?php
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@ -25,6 +24,7 @@ use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
/**
* Base class for PHPUnit test cases customised for Moodle
@ -605,7 +605,42 @@ abstract class base_testcase extends PHPUnit\Framework\TestCase {
* @return int
*/
protected static function getInvocationCount(InvocationOrder $counter): int {
if (method_exists($counter, 'numberOfInvocations')) {
return $counter->numberOfInvocations();
}
return $counter->getInvocationCount();
}
// phpcs:enable
/**
* Get an invokable object for testing.
*
* This is a helper method to create an invokable object for testing which can be used to
* track invocations, including arguments provided.
*
* This can be useful for modifications to the error handler.
*
* @return object
*/
protected static function get_invokable() {
return new class {
private array $invocations = [];
public function __invoke(...$args) {
$this->invocations[] = $args;
}
public function get_invocations(): array {
return $this->invocations;
}
public function get_invocation_count(): int {
return count($this->invocations);
}
public function reset(): void {
$this->invocations = [];
}
};
}
}

View file

@ -1,4 +1,5 @@
<?php
use PHPUnit\Framework\Attributes\After;
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@ -14,16 +15,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Basic test case.
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* The simplest PHPUnit test case customised for Moodle
*
@ -35,50 +26,26 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class basic_testcase extends base_testcase {
/**
* Constructs a test case with the given name.
*
* Note: use setUp() or setUpBeforeClass() in your test cases.
*
* @param string $name
* @param array $data
* @param string $dataName
*/
final public function __construct($name = null, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
final public function __construct($name = null) {
parent::__construct($name);
$this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false);
}
/**
* Runs the bare test sequence and log any changes in global state or database.
* @return void
*/
final public function runBare(): void {
#[After]
final public function test_teardown(): void {
global $DB;
try {
parent::runBare();
} catch (Exception $ex) {
$e = $ex;
} catch (Throwable $ex) {
// Engine errors in PHP7 throw exceptions of type Throwable (this "catch" will be ignored in PHP5).
$e = $ex;
}
if (isset($e)) {
// cleanup after failed expectation
phpunit_util::reset_all_data();
throw $e;
}
if ($DB->is_transaction_started()) {
phpunit_util::reset_all_data();
throw new coding_exception('basic_testcase '.$this->getName().' is not supposed to use database transactions!');
throw new coding_exception('basic_testcase ' . $this->getName() . ' is not supposed to use database transactions!');
}
phpunit_util::reset_all_data(true);

View file

@ -1,4 +1,6 @@
<?php
use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@ -56,14 +58,11 @@ abstract class database_driver_testcase extends base_testcase {
* Constructs a test case with the given name.
*
* @param string $name
* @param array $data
* @param string $dataName
*/
final public function __construct($name = null, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
final public function __construct($name = null) {
parent::__construct($name);
$this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false);
}
@ -101,9 +100,9 @@ abstract class database_driver_testcase extends base_testcase {
self::$extradb = $d;
}
protected function setUp(): void {
#[Before]
protected function setup_extradb(): void {
global $DB;
parent::setUp();
if (self::$extradb) {
$this->tdb = self::$extradb;
@ -112,7 +111,8 @@ abstract class database_driver_testcase extends base_testcase {
}
}
protected function tearDown(): void {
#[After]
protected function teardown_extradb(): void {
// delete all test tables
$dbman = $this->tdb->get_manager();
$tables = $this->tdb->get_tables(false);
@ -122,7 +122,6 @@ abstract class database_driver_testcase extends base_testcase {
$dbman->drop_table($table);
}
}
parent::tearDown();
}
public static function tearDownAfterClass(): void {
@ -134,35 +133,14 @@ abstract class database_driver_testcase extends base_testcase {
parent::tearDownAfterClass();
}
/**
* Runs the bare test sequence.
* @return void
*/
public function runBare(): void {
try {
parent::runBare();
#[After]
public function check_debugging(): void {
// Deal with any debugging messages.
$debugerror = phpunit_util::display_debugging_messages(true);
$this->resetDebugging();
if (!empty($debugerror)) {
trigger_error('Unexpected debugging() call detected.' . "\n" . $debugerror, E_USER_NOTICE);
}
} catch (Exception $ex) {
$e = $ex;
} catch (Throwable $ex) {
// Engine errors in PHP7 throw exceptions of type Throwable (this "catch" will be ignored in PHP5).
$e = $ex;
}
if (isset($e)) {
if ($this->tdb->is_transaction_started()) {
$this->tdb->force_transaction_rollback();
}
$this->tearDown();
throw $e;
}
}
/**

View file

@ -0,0 +1,27 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_phpunit\exception;
/**
* An exception thrown when an error is encountered in the setup, teardown, or other non-test parts of a unit test.
*
* @package core_testing
* @copyright Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_exception extends \core\exception\coding_exception {
}

View file

@ -314,7 +314,7 @@ class phpunit_util extends testing_util {
if ($warnings) {
$warnings = implode("\n", $warnings);
trigger_error($warnings, E_USER_WARNING);
throw new \core_phpunit\exception\test_exception($warnings);
}
}

View file

@ -2,7 +2,7 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation>
<xs:documentation source="https://phpunit.de/documentation.html">
This Schema file defines the rules by which the XML configuration file of PHPUnit 9.5 may be structured.
This Schema file defines the rules by which the XML configuration file of PHPUnit 10.0 may be structured.
</xs:documentation>
<xs:appinfo source="https://phpunit.de/documentation.html"/>
</xs:annotation>
@ -32,7 +32,6 @@
<xs:attribute name="cacheDirectory" type="xs:anyURI"/>
<xs:attribute name="pathCoverage" type="xs:boolean" default="false"/>
<xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/>
<xs:attribute name="processUncoveredFiles" type="xs:boolean" default="false"/>
<xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/>
<xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/>
</xs:complexType>
@ -57,62 +56,19 @@
</xs:complexType>
<xs:complexType name="extensionsType">
<xs:sequence>
<xs:element name="extension" type="objectType" maxOccurs="unbounded"/>
<xs:element name="bootstrap" type="bootstrapType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="listenersType">
<xs:complexType name="bootstrapType">
<xs:sequence>
<xs:element name="listener" type="objectType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="objectType">
<xs:sequence>
<xs:element name="arguments" minOccurs="0">
<xs:complexType>
<xs:group ref="argumentsGroup"/>
</xs:complexType>
</xs:element>
<xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="class" type="xs:string" use="required"/>
<xs:attribute name="file" type="xs:anyURI"/>
</xs:complexType>
<xs:complexType name="arrayType">
<xs:sequence>
<xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:complexType name="parameterType">
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="value" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="argumentType">
<xs:group ref="argumentChoice"/>
<xs:attribute name="key" use="required"/>
</xs:complexType>
<xs:group name="argumentsGroup">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="array" type="arrayType" />
<xs:element name="integer" type="xs:integer" />
<xs:element name="string" type="xs:string" />
<xs:element name="double" type="xs:double" />
<xs:element name="null" />
<xs:element name="object" type="objectType" />
<xs:element name="file" type="xs:anyURI" />
<xs:element name="directory" type="xs:anyURI" />
<xs:element name="boolean" type="xs:boolean" />
</xs:choice>
</xs:sequence>
</xs:group>
<xs:group name="argumentChoice">
<xs:choice>
<xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:group>
<xs:simpleType name="columnsType">
<xs:union>
<xs:simpleType>
@ -135,7 +91,7 @@
</xs:group>
<xs:complexType name="directoryFilterType">
<xs:simpleContent>
<xs:extension base="xs:anyURI">
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="prefix" default=""/>
<xs:attribute type="xs:string" name="suffix" default="Test.php"/>
<xs:attributeGroup ref="phpVersionGroup"/>
@ -207,19 +163,14 @@
</xs:complexType>
<xs:attributeGroup name="configAttributeGroup">
<xs:attribute name="backupGlobals" type="xs:boolean" default="false"/>
<xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/>
<xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/>
<xs:attribute name="bootstrap" type="xs:anyURI"/>
<xs:attribute name="cacheDirectory" type="xs:anyURI"/>
<xs:attribute name="cacheResult" type="xs:boolean" default="true"/>
<xs:attribute name="cacheResultFile" type="xs:anyURI"/>
<xs:attribute name="colors" type="xs:boolean" default="false"/>
<xs:attribute name="columns" type="columnsType" default="80"/>
<xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/>
<xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/>
<xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/>
<xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/>
<xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/>
<xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\DefaultResultPrinter"/>
<xs:attribute name="printerFile" type="xs:anyURI"/>
<xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/>
<xs:attribute name="processIsolation" type="xs:boolean" default="false"/>
<xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/>
<xs:attribute name="stopOnError" type="xs:boolean" default="false"/>
@ -235,37 +186,36 @@
<xs:attribute name="failOnWarning" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/>
<xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/>
<xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/>
<xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/>
<xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
<xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
<xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/>
<xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/>
<xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/>
<xs:attribute name="defaultTestSuite" type="xs:string" default=""/>
<xs:attribute name="verbose" type="xs:boolean" default="false"/>
<xs:attribute name="testdox" type="xs:boolean" default="false"/>
<xs:attribute name="stderr" type="xs:boolean" default="false"/>
<xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/>
<xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/>
<xs:attribute name="extensionsDirectory" type="xs:string"/>
<xs:attribute name="extensionsDirectory" type="xs:anyURI"/>
<xs:attribute name="executionOrder" type="executionOrderType" default="default"/>
<xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/>
<xs:attribute name="noInteraction" type="xs:boolean" default="false"/>
<xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/>
<xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/>
<xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/>
<xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/>
<xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/>
<xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/>
</xs:attributeGroup>
<xs:group name="configGroup">
<xs:all>
<xs:element ref="testSuiteFacet" minOccurs="0"/>
<xs:element name="groups" type="groupsType" minOccurs="0"/>
<xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/>
<xs:element name="coverage" type="coverageType" minOccurs="0"/>
<xs:element name="logging" type="loggingType" minOccurs="0"/>
<xs:element name="extensions" type="extensionsType" minOccurs="0"/>
<xs:element name="listeners" type="listenersType" minOccurs="0"/>
<xs:element name="php" type="phpType" minOccurs="0"/>
</xs:all>
</xs:group>
@ -279,8 +229,10 @@
</xs:complexType>
<xs:complexType name="testSuiteType">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="pathGroup"/>
<xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="exclude" type="xs:string"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
@ -301,8 +253,6 @@
<xs:element name="teamcity" type="logToFileType" minOccurs="0" />
<xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" />
<xs:element name="testdoxText" type="logToFileType" minOccurs="0" />
<xs:element name="testdoxXml" type="logToFileType" minOccurs="0" />
<xs:element name="text" type="logToFileType" minOccurs="0"/>
</xs:all>
</xs:group>
<xs:complexType name="logToFileType">
@ -319,6 +269,12 @@
<xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/>
<xs:attribute name="lowUpperBound" type="xs:integer" default="50"/>
<xs:attribute name="highLowerBound" type="xs:integer" default="90"/>
<xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/>
<xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/>
<xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/>
<xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/>
<xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/>
<xs:attribute name="customCssFile" type="xs:string"/>
</xs:complexType>
<xs:complexType name="coverageReportTextType">
<xs:attribute name="outputFile" type="xs:anyURI" use="required"/>

View file

@ -16,6 +16,8 @@
namespace core;
use core_phpunit\exception\test_exception;
/**
* Test advanced_testcase extra features.
*
@ -216,28 +218,29 @@ final class advanced_test extends \advanced_testcase {
// Database change.
$this->assertEquals(1, $DB->get_field('user', 'confirmed', array('id'=>2)));
$DB->set_field('user', 'confirmed', 0, array('id'=>2));
try {
self::resetAllData(true);
} catch (\Exception $e) {
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e);
} catch (test_exception $e) {
$this->assertStringContainsString('unexpected database modification', $e->getMessage());
}
$this->assertEquals(1, $DB->get_field('user', 'confirmed', array('id'=>2)));
$this->assertEquals(1, $DB->get_field('user', 'confirmed', array('id'=>2)));
// Config change.
$CFG->xx = 'yy';
unset($CFG->admin);
$CFG->rolesactive = 0;
try {
self::resetAllData(true);
} catch (\Exception $e) {
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e);
} catch (test_exception $e) {
$this->assertStringContainsString('xx', $e->getMessage());
$this->assertStringContainsString('admin', $e->getMessage());
$this->assertStringContainsString('rolesactive', $e->getMessage());
}
$this->assertFalse(isset($CFG->xx));
$this->assertTrue(isset($CFG->admin));
$this->assertEquals(1, $CFG->rolesactive);
}
// _GET change.
$_GET['__somethingthatwillnotnormallybepresent__'] = 'yy';
@ -269,23 +272,28 @@ final class advanced_test extends \advanced_testcase {
$SITE->id = 10;
$COURSE = new \stdClass();
$COURSE->id = 7;
try {
self::resetAllData(true);
} catch (\Exception $e) {
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e);
} catch (test_exception $e) {
$this->assertStringContainsString('unexpected change of $COURSE', $e->getMessage());
}
$this->assertEquals(1, $SITE->id);
$this->assertSame($SITE, $COURSE);
$this->assertSame($SITE, $COURSE);
}
// USER change.
$this->setUser(2);
try {
self::resetAllData(true);
} catch (\Exception $e) {
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e);
$this->assertEquals(0, $USER->id);
} catch (test_exception $e) {
$this->assertStringContainsString('unexpected change of $USER', $e->getMessage());
}
$this->assertEquals(0, $USER->id);
}
public function test_getDataGenerator(): void {
@ -642,8 +650,8 @@ final class advanced_test extends \advanced_testcase {
try {
self::resetAllData(true);
} catch (\Exception $e) {
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e);
} catch (test_exception $e) {
$this->assertStringContainsString('unexpected change of locale', $e->getMessage());
}
if ($CFG->ostype === 'WINDOWS') {

View file

@ -16,6 +16,7 @@
namespace core;
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
use phpunit_util;
/**
@ -235,16 +236,7 @@ STRING;
global $DB;
$DB->set_field('user', 'confirmed', 1, ['id' => -1]);
// Let's convert the user warnings into an assert-able exception.
set_error_handler(
static function ($errno, $errstr) {
restore_error_handler();
throw new \Exception($errstr, $errno);
},
E_USER_WARNING // Or any other specific E_ that we want to assert.
);
$this->expectException(\Exception::class);
$this->expectException(\core_phpunit\exception\test_exception::class);
$this->expectExceptionMessage('Warning: unexpected database modification');
phpunit_util::reset_all_data(true);
}
@ -261,15 +253,6 @@ STRING;
unset($CFG->admin);
$CFG->rolesactive = 0;
// Let's convert the user warnings into an assert-able exception.
set_error_handler(
static function ($errno, $errstr) {
restore_error_handler();
throw new \Exception($errstr, $errno);
},
E_USER_WARNING // Or any other specific E_ that we want to assert.
);
$this->expectException(\Exception::class);
$this->expectExceptionMessageMatches('/rolesactive.*xx value.*removal.*admin/ms'); // 3 messages matched.
phpunit_util::reset_all_data(true);
@ -285,15 +268,6 @@ STRING;
global $USER;
$USER->id = 10;
// Let's convert the user warnings into an assert-able exception.
set_error_handler(
static function ($errno, $errstr) {
restore_error_handler();
throw new \Exception($errstr, $errno);
},
E_USER_WARNING // Or any other specific E_ that we want to assert.
);
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Warning: unexpected change of $USER');
phpunit_util::reset_all_data(true);
@ -309,15 +283,6 @@ STRING;
global $COURSE;
$COURSE->id = 10;
// Let's convert the user warnings into an assert-able exception.
set_error_handler(
static function ($errno, $errstr) {
restore_error_handler();
throw new \Exception($errstr, $errno);
},
E_USER_WARNING // Or any other specific E_ that we want to assert.
);
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Warning: unexpected change of $COURSE');
phpunit_util::reset_all_data(true);
@ -338,15 +303,6 @@ STRING;
$USER->id = 10;
$COURSE->id = 10;
// Let's convert the user warnings into an assert-able exception.
set_error_handler(
static function ($errno, $errstr) {
restore_error_handler();
throw new \Exception($errstr, $errno);
},
E_USER_WARNING // Or any other specific E_ that we want to assert.
);
$this->expectException(\Exception::class);
$this->expectExceptionMessageMatches('/resetting.*rolesactive.*new.*removal.*USER.*COURSE/ms'); // 6 messages matched.
phpunit_util::reset_all_data(true);

View file

@ -0,0 +1,65 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for core_cache.
*
* @package core_cache
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_cache\privacy;
use core_privacy\local\metadata\collection;
/**
* Privacy Subsystem implementation for core_cache.
*
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
// Caches store data.
\core_privacy\local\metadata\provider,
// The cache subsystem stores data on behalf of other components.
\core_privacy\local\request\subsystem\plugin_provider,
\core_privacy\local\request\shared_userlist_provider
{
/**
* Returns meta data about this system.
*
* Note, although this plugin does store user data, it is not able to
* identify it, and that user data is typically very short lived.
*
* Therefore it is not realistically possible to export any of this
* data as it is only identifiable by the plugin storing it, and that
* plugin should already be exporting the data as part of it's own
* implementation.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection): collection {
// Data is stored in cache stores.
$collection->add_plugintype_link('cachestore', [], 'privacy:metadata:cachestore');
// Cache locks do not store any personal user data.
return $collection;
}
}

View file

@ -76,7 +76,7 @@ final class completionlib_test extends advanced_testcase {
* @param boolean $canonicalize
* @param boolean $ignoreCase
*/
public static function assertEquals($expected, $actual, string $message = '', float $delta = 0, int $maxDepth = 10,
public static function assertCompletionEquals($expected, $actual, string $message = '', float $delta = 0, int $maxDepth = 10,
bool $canonicalize = false, bool $ignoreCase = false): void {
// Nasty cheating hack: prevent random failures on timemodified field.
if (is_array($actual) && (is_object($expected) || is_array($expected))) {
@ -104,33 +104,33 @@ final class completionlib_test extends advanced_testcase {
// Config alone.
$CFG->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, completion_info::is_enabled_for_site());
$this->assertCompletionEquals(COMPLETION_DISABLED, completion_info::is_enabled_for_site());
$CFG->enablecompletion = COMPLETION_ENABLED;
$this->assertEquals(COMPLETION_ENABLED, completion_info::is_enabled_for_site());
$this->assertCompletionEquals(COMPLETION_ENABLED, completion_info::is_enabled_for_site());
// Course.
$course = (object)array('id' => 13);
$c = new completion_info($course);
$course->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled());
$this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled());
$course->enablecompletion = COMPLETION_ENABLED;
$this->assertEquals(COMPLETION_ENABLED, $c->is_enabled());
$this->assertCompletionEquals(COMPLETION_ENABLED, $c->is_enabled());
$CFG->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled());
$this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled());
// Course and CM.
$cm = new stdClass();
$cm->completion = COMPLETION_TRACKING_MANUAL;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled($cm));
$this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled($cm));
$CFG->enablecompletion = COMPLETION_ENABLED;
$course->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled($cm));
$this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled($cm));
$course->enablecompletion = COMPLETION_ENABLED;
$this->assertEquals(COMPLETION_TRACKING_MANUAL, $c->is_enabled($cm));
$this->assertCompletionEquals(COMPLETION_TRACKING_MANUAL, $c->is_enabled($cm));
$cm->completion = COMPLETION_TRACKING_NONE;
$this->assertEquals(COMPLETION_TRACKING_NONE, $c->is_enabled($cm));
$this->assertCompletionEquals(COMPLETION_TRACKING_NONE, $c->is_enabled($cm));
$cm->completion = COMPLETION_TRACKING_AUTOMATIC;
$this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $c->is_enabled($cm));
$this->assertCompletionEquals(COMPLETION_TRACKING_AUTOMATIC, $c->is_enabled($cm));
}
/**
@ -281,11 +281,11 @@ final class completionlib_test extends advanced_testcase {
): void {
switch (self::getInvocationCount($setinvocations)) {
case 1:
$this->assertEquals($cm, $comparecm);
$this->assertCompletionEquals($cm, $comparecm);
$comparewith1->evaluate($comparewith);
break;
case 2:
$this->assertEquals($cm, $comparecm);
$this->assertCompletionEquals($cm, $comparecm);
$comparewith2->evaluate($comparewith);
break;
default:
@ -407,7 +407,7 @@ final class completionlib_test extends advanced_testcase {
$current = (object)['viewed' => COMPLETION_NOT_VIEWED];
$completioninfo = new completion_info($this->course);
$this->assertEquals($expectedstate, $completioninfo->internal_get_state($cm, $userid, $current));
$this->assertCompletionEquals($expectedstate, $completioninfo->internal_get_state($cm, $userid, $current));
}
/**
@ -503,7 +503,7 @@ final class completionlib_test extends advanced_testcase {
// The target user already received a grade, so internal_get_state should be already complete.
$completioninfo = new completion_info($this->course);
$this->assertEquals($expectedstate, $completioninfo->internal_get_state($cm, $userid, null));
$this->assertCompletionEquals($expectedstate, $completioninfo->internal_get_state($cm, $userid, null));
}
/**
@ -544,10 +544,10 @@ final class completionlib_test extends advanced_testcase {
// The target user already received a grade, so internal_get_state should be already complete.
$completioninfo = new completion_info($this->course);
$this->assertEquals(COMPLETION_COMPLETE, $completioninfo->internal_get_state($cm, $userid, null));
$this->assertCompletionEquals(COMPLETION_COMPLETE, $completioninfo->internal_get_state($cm, $userid, null));
// As the teacher which does not have a grade in this cm, internal_get_state should return incomplete.
$this->assertEquals(COMPLETION_INCOMPLETE, $completioninfo->internal_get_state($cm, $teacher->id, null));
$this->assertCompletionEquals(COMPLETION_INCOMPLETE, $completioninfo->internal_get_state($cm, $teacher->id, null));
}
/**
@ -570,14 +570,14 @@ final class completionlib_test extends advanced_testcase {
// Fetch completion for the user who hasn't made a choice yet.
$completion = $completioninfo->internal_get_state($cminfo, $this->user->id, COMPLETION_INCOMPLETE);
$this->assertEquals(COMPLETION_INCOMPLETE, $completion);
$this->assertCompletionEquals(COMPLETION_INCOMPLETE, $completion);
// Have the user make a choice.
$choicewithoptions = choice_get_choice($choice->id);
$optionids = array_keys($choicewithoptions->option);
choice_user_submit_response($optionids[0], $choice, $this->user->id, $this->course, $cminfo);
$completion = $completioninfo->internal_get_state($cminfo, $this->user->id, COMPLETION_INCOMPLETE);
$this->assertEquals(COMPLETION_COMPLETE, $completion);
$this->assertCompletionEquals(COMPLETION_COMPLETE, $completion);
}
/**
@ -654,7 +654,7 @@ final class completionlib_test extends advanced_testcase {
->will($this->returnValue(666));
$c = new completion_info($course);
$this->assertEquals(666, $c->count_user_data($cm));
$this->assertCompletionEquals(666, $c->count_user_data($cm));
}
/**
@ -712,17 +712,17 @@ final class completionlib_test extends advanced_testcase {
$c->expects($updateinvocations)
->method('update_state')
->willReturnCallback(function ($comparecm, $state, $userid) use ($updateinvocations, $cm): void {
$this->assertEquals($cm, $comparecm);
$this->assertEquals(COMPLETION_UNKNOWN, $state);
$this->assertCompletionEquals($cm, $comparecm);
$this->assertCompletionEquals(COMPLETION_UNKNOWN, $state);
switch (self::getInvocationCount($updateinvocations)) {
case 1:
$this->assertEquals(100, $userid);
$this->assertCompletionEquals(100, $userid);
break;
case 2:
$this->assertEquals(101, $userid);
$this->assertCompletionEquals(101, $userid);
break;
case 3:
$this->assertEquals(201, $userid);
$this->assertCompletionEquals(201, $userid);
break;
default:
$this->fail('Unexpected invocation count');
@ -820,15 +820,15 @@ final class completionlib_test extends advanced_testcase {
$result = $completioninfo->get_data($cm, $wholecourse, $user->id);
// Course module ID of the returned completion data must match this activity's course module ID.
$this->assertEquals($cm->id, $result->coursemoduleid);
$this->assertCompletionEquals($cm->id, $result->coursemoduleid);
// User ID of the returned completion data must match the user's ID.
$this->assertEquals($user->id, $result->userid);
$this->assertCompletionEquals($user->id, $result->userid);
// The completion state of the returned completion data must match the expected completion state.
$this->assertEquals($completion, $result->completionstate);
$this->assertCompletionEquals($completion, $result->completionstate);
// If the user has no completion record, then the default record should be returned.
if (!$hasrecord) {
$this->assertEquals(0, $result->id);
$this->assertCompletionEquals(0, $result->id);
}
// Check that we are including relevant completion data for the module.
@ -889,8 +889,8 @@ final class completionlib_test extends advanced_testcase {
$this->assertTrue(property_exists($result, 'timemodified'));
$this->assertFalse(property_exists($result, 'other_cm_completion_data_fetched'));
$this->assertEquals($testcm->id, $result->coursemoduleid);
$this->assertEquals($this->user->id, $result->userid);
$this->assertCompletionEquals($testcm->id, $result->coursemoduleid);
$this->assertCompletionEquals($this->user->id, $result->userid);
$results[$testcm->id] = $result;
}
@ -902,7 +902,7 @@ final class completionlib_test extends advanced_testcase {
(cache::make('core', 'completion'))->purge();
foreach ($modinfo->cms as $testcm) {
$result = $completioninfo->get_data($testcm, false);
$this->assertEquals($result, $results[$testcm->id]);
$this->assertCompletionEquals($result, $results[$testcm->id]);
}
}
@ -939,13 +939,13 @@ final class completionlib_test extends advanced_testcase {
$completiondatabeforeview = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertTrue(array_key_exists('viewed', $completiondatabeforeview));
$this->assertTrue(array_key_exists('coursemoduleid', $completiondatabeforeview));
$this->assertEquals(0, $completiondatabeforeview['viewed']);
$this->assertEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
$this->assertCompletionEquals(0, $completiondatabeforeview['viewed']);
$this->assertCompletionEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
// Mark as completed before viewing it.
$completioninfo->update_state($cm, COMPLETION_COMPLETE, $this->user->id, true);
$completiondatabeforeview = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertEquals(0, $completiondatabeforeview['viewed']);
$this->assertCompletionEquals(0, $completiondatabeforeview['viewed']);
// Set viewed.
$completioninfo->set_module_viewed($cm, $this->user->id);
@ -953,16 +953,16 @@ final class completionlib_test extends advanced_testcase {
$completiondata = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertTrue(array_key_exists('viewed', $completiondata));
$this->assertTrue(array_key_exists('coursemoduleid', $completiondata));
$this->assertEquals(1, $completiondata['viewed']);
$this->assertEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
$this->assertCompletionEquals(1, $completiondata['viewed']);
$this->assertCompletionEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
$completioninfo->reset_all_state($cm);
$completiondataafterreset = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertTrue(array_key_exists('viewed', $completiondataafterreset));
$this->assertTrue(array_key_exists('coursemoduleid', $completiondataafterreset));
$this->assertEquals(1, $completiondataafterreset['viewed']);
$this->assertEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
$this->assertCompletionEquals(1, $completiondataafterreset['viewed']);
$this->assertCompletionEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
}
/**
@ -1014,7 +1014,7 @@ final class completionlib_test extends advanced_testcase {
$this->assertArrayHasKey('customcompletion', $choicecompletiondata);
$this->assertArrayHasKey('completionsubmit', $choicecompletiondata['customcompletion']);
$this->assertEquals(COMPLETION_INCOMPLETE, $choicecompletiondata['customcompletion']['completionsubmit']);
$this->assertCompletionEquals(COMPLETION_INCOMPLETE, $choicecompletiondata['customcompletion']['completionsubmit']);
// Mock a choice answer so user has completed the requirement.
$choicemockinfo = [
@ -1025,7 +1025,7 @@ final class completionlib_test extends advanced_testcase {
// Confirm fetching again reflects the completion.
$choicecompletiondata = $method->invoke($completioninfo, $cmchoice, $user->id);
$this->assertEquals(COMPLETION_COMPLETE, $choicecompletiondata['customcompletion']['completionsubmit']);
$this->assertCompletionEquals(COMPLETION_COMPLETE, $choicecompletiondata['customcompletion']['completionsubmit']);
// Check that fetching data for a module with no custom completion still provides its grade completion status.
$workshopcompletiondata = $method->invoke($completioninfo, $cmworkshop, $user->id);
@ -1033,8 +1033,8 @@ final class completionlib_test extends advanced_testcase {
$this->assertArrayHasKey('completiongrade', $workshopcompletiondata);
$this->assertArrayHasKey('passgrade', $workshopcompletiondata);
$this->assertArrayNotHasKey('customcompletion', $workshopcompletiondata);
$this->assertEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['completiongrade']);
$this->assertEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['passgrade']);
$this->assertCompletionEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['completiongrade']);
$this->assertCompletionEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['passgrade']);
// Check that fetching data for a module with no completion conditions does not provide any data.
$choice2completiondata = $method->invoke($completioninfo, $cmchoice2, $user->id);
@ -1066,11 +1066,11 @@ final class completionlib_test extends advanced_testcase {
$c->internal_set_data($cm, $data);
$d1 = $DB->get_field('course_modules_completion', 'id', array('coursemoduleid' => $cm->id));
$this->assertEquals($d1, $data->id);
$this->assertCompletionEquals($d1, $data->id);
$cache = cache::make('core', 'completion');
// Cache was not set for another user.
$cachevalue = $cache->get("{$data->userid}_{$cm->course}");
$this->assertEquals([
$this->assertCompletionEquals([
'cacherev' => $this->course->cacherev,
$cm->id => array_merge(
(array) $data,
@ -1095,13 +1095,13 @@ final class completionlib_test extends advanced_testcase {
$c->internal_set_data($cm2, $d2);
// Cache for current user returns the data.
$cachevalue = $cache->get($data->userid . '_' . $cm->course);
$this->assertEquals(array_merge(
$this->assertCompletionEquals(array_merge(
(array) $data,
['other_cm_completion_data_fetched' => true]
), $cachevalue[$cm->id]);
// Cache for another user is not filled.
$this->assertEquals(false, $cache->get($d2->userid . '_' . $cm2->course));
$this->assertCompletionEquals(false, $cache->get($d2->userid . '_' . $cm2->course));
// 3) Test where it THINKS the data is new (from cache) but actually in the database it has been set since.
$forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $this->course->id), $completionauto);
@ -1141,14 +1141,14 @@ final class completionlib_test extends advanced_testcase {
$data->coursemoduleid = $cm->id;
$c->internal_set_data($cm, $data);
$actual = $DB->get_records('course_completions');
$this->assertEquals(1, count($actual));
$this->assertEquals($this->user->id, reset($actual)->userid);
$this->assertCompletionEquals(1, count($actual));
$this->assertCompletionEquals($this->user->id, reset($actual)->userid);
$data->userid = $newuser2->id;
$c->internal_set_data($cm, $data, true);
$actual = $DB->get_records('course_completions');
$this->assertEquals(1, count($actual));
$this->assertEquals($this->user->id, reset($actual)->userid);
$this->assertCompletionEquals(1, count($actual));
$this->assertCompletionEquals($this->user->id, reset($actual)->userid);
}
/**
@ -1180,7 +1180,7 @@ final class completionlib_test extends advanced_testcase {
->method('get_recordset_sql')
->will($this->returnValue(new core_completionlib_fake_recordset(array($progress1, $progress2))));
$this->assertEquals(array(
$this->assertCompletionEquals(array(
100 => (object)array('id' => 100, 'firstname' => 'Woot', 'lastname' => 'Plugh',
'progress' => array(13 => $progress1)),
201 => (object)array('id' => 201, 'firstname' => 'Vroom', 'lastname' => 'Xyzzy',
@ -1220,10 +1220,10 @@ final class completionlib_test extends advanced_testcase {
->willReturnCallback(function ($paramids) use ($inorequalsinvocations, $ids) {
switch (self::getInvocationCount($inorequalsinvocations)) {
case 1:
$this->assertEquals(array_slice($ids, 0, 1000), $paramids);
$this->assertCompletionEquals(array_slice($ids, 0, 1000), $paramids);
return [' IN whatever', []];
case 2:
$this->assertEquals(array_slice($ids, 1000), $paramids);
$this->assertCompletionEquals(array_slice($ids, 1000), $paramids);
return [' IN whatever2', []];
default:
$this->fail('Unexpected invocation count');
@ -1343,32 +1343,32 @@ final class completionlib_test extends advanced_testcase {
$grade->finalgrade = null;
// Grade has pass mark and is not hidden, user passes.
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE_PASS,
completion_info::internal_get_grade_state($item, $grade));
// Same but user fails.
$grade->rawgrade = 3.9;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE_FAIL,
completion_info::internal_get_grade_state($item, $grade));
// User fails on raw grade but passes on final.
$grade->finalgrade = 4.0;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE_PASS,
completion_info::internal_get_grade_state($item, $grade));
// Item is hidden.
$item->hidden = 1;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE,
completion_info::internal_get_grade_state($item, $grade));
// Item isn't hidden but has no pass mark.
$item->hidden = 0;
$item->gradepass = 0;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE,
completion_info::internal_get_grade_state($item, $grade));
@ -1376,7 +1376,7 @@ final class completionlib_test extends advanced_testcase {
$item->hidden = 1;
$item->gradepass = 4;
$grade->finalgrade = 5.0;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE_PASS,
completion_info::internal_get_grade_state($item, $grade, true));
@ -1384,7 +1384,7 @@ final class completionlib_test extends advanced_testcase {
$item->hidden = 1;
$item->gradepass = 4;
$grade->finalgrade = 3.0;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE_FAIL_HIDDEN,
completion_info::internal_get_grade_state($item, $grade, true));
@ -1392,7 +1392,7 @@ final class completionlib_test extends advanced_testcase {
$item->hidden = 0;
$item->gradepass = 4;
$grade->finalgrade = 3.0;
$this->assertEquals(
$this->assertCompletionEquals(
COMPLETION_COMPLETE_FAIL,
completion_info::internal_get_grade_state($item, $grade, true));
}
@ -1522,9 +1522,9 @@ final class completionlib_test extends advanced_testcase {
$c = new completion_info($this->course);
$activities = $c->get_activities();
$this->assertEquals(1, count($activities));
$this->assertCompletionEquals(1, count($activities));
$this->assertTrue(isset($activities[$forum->cmid]));
$this->assertEquals($activities[$forum->cmid]->name, $forum->name);
$this->assertCompletionEquals($activities[$forum->cmid]->name, $forum->name);
$current = $c->get_data($activities[$forum->cmid], false, $this->user->id);
$current->completionstate = COMPLETION_COMPLETE;
@ -1534,12 +1534,12 @@ final class completionlib_test extends advanced_testcase {
$events = $sink->get_events();
$event = reset($events);
$this->assertInstanceOf('\core\event\course_module_completion_updated', $event);
$this->assertEquals($forum->cmid,
$this->assertCompletionEquals($forum->cmid,
$event->get_record_snapshot('course_modules_completion', $event->objectid)->coursemoduleid);
$this->assertEquals($current, $event->get_record_snapshot('course_modules_completion', $event->objectid));
$this->assertEquals(context_module::instance($forum->cmid), $event->get_context());
$this->assertEquals($USER->id, $event->userid);
$this->assertEquals($this->user->id, $event->relateduserid);
$this->assertCompletionEquals($current, $event->get_record_snapshot('course_modules_completion', $event->objectid));
$this->assertCompletionEquals(context_module::instance($forum->cmid), $event->get_context());
$this->assertCompletionEquals($USER->id, $event->userid);
$this->assertCompletionEquals($this->user->id, $event->relateduserid);
$this->assertInstanceOf('moodle_url', $event->get_url());
}
@ -1564,11 +1564,11 @@ final class completionlib_test extends advanced_testcase {
$event = reset($events);
$this->assertInstanceOf('\core\event\course_completed', $event);
$this->assertEquals($this->course->id, $event->get_record_snapshot('course_completions', $event->objectid)->course);
$this->assertEquals($this->course->id, $event->courseid);
$this->assertEquals($USER->id, $event->userid);
$this->assertEquals($this->user->id, $event->relateduserid);
$this->assertEquals(context_course::instance($this->course->id), $event->get_context());
$this->assertCompletionEquals($this->course->id, $event->get_record_snapshot('course_completions', $event->objectid)->course);
$this->assertCompletionEquals($this->course->id, $event->courseid);
$this->assertCompletionEquals($USER->id, $event->userid);
$this->assertCompletionEquals($this->user->id, $event->relateduserid);
$this->assertCompletionEquals(context_course::instance($this->course->id), $event->get_context());
$this->assertInstanceOf('moodle_url', $event->get_url());
}
@ -1593,10 +1593,10 @@ final class completionlib_test extends advanced_testcase {
$this->assertCount(1, $messages);
$message = array_pop($messages);
$this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom);
$this->assertEquals($this->user->id, $message->useridto);
$this->assertEquals('coursecompleted', $message->eventtype);
$this->assertEquals(get_string('coursecompleted', 'completion'), $message->subject);
$this->assertCompletionEquals(core_user::get_noreply_user()->id, $message->useridfrom);
$this->assertCompletionEquals($this->user->id, $message->useridto);
$this->assertCompletionEquals('coursecompleted', $message->eventtype);
$this->assertCompletionEquals(get_string('coursecompleted', 'completion'), $message->subject);
$this->assertStringContainsString($this->course->fullname, $message->fullmessage);
}
@ -1623,8 +1623,8 @@ final class completionlib_test extends advanced_testcase {
$sink->close();
$this->assertInstanceOf('\core\event\course_completion_updated', $event);
$this->assertEquals($this->course->id, $event->courseid);
$this->assertEquals($coursecontext, $event->get_context());
$this->assertCompletionEquals($this->course->id, $event->courseid);
$this->assertCompletionEquals($coursecontext, $event->get_context());
$this->assertInstanceOf('moodle_url', $event->get_url());
}
@ -1694,7 +1694,7 @@ final class completionlib_test extends advanced_testcase {
$this->expectException($expectedexception);
}
$gradecompletion = $completioninfo->get_grade_completion($cm, $this->user->id);
$this->assertEquals($expectedresult, $gradecompletion);
$this->assertCompletionEquals($expectedresult, $gradecompletion);
}
/**
@ -1725,7 +1725,7 @@ final class completionlib_test extends advanced_testcase {
// Without the grade_item, the activity is considered incomplete.
$completioninfo = new completion_info($this->course);
$this->assertEquals(COMPLETION_INCOMPLETE, $completioninfo->get_grade_completion($cm, $this->user->id));
$this->assertCompletionEquals(COMPLETION_INCOMPLETE, $completioninfo->get_grade_completion($cm, $this->user->id));
// Once the activity is graded, the grade_item is automatically created.
$assigninstance = new assign($cm->context, $cm, $this->course);
@ -1734,7 +1734,7 @@ final class completionlib_test extends advanced_testcase {
$assigninstance->update_grade($grade);
// The implicitly created grade_item does not have grade to pass defined so it is not distinguished.
$this->assertEquals(COMPLETION_COMPLETE, $completioninfo->get_grade_completion($cm, $this->user->id));
$this->assertCompletionEquals(COMPLETION_COMPLETE, $completioninfo->get_grade_completion($cm, $this->user->id));
}
/**
@ -1868,8 +1868,8 @@ final class completionlib_test extends advanced_testcase {
$method = new ReflectionMethod($ccompletion, '_save');
$completionid = $method->invoke($ccompletion);
$completions = $DB->get_records('course_completions');
$this->assertEquals(count($completions), 1);
$this->assertEquals(reset($completions)->id, $completionid);
$this->assertCompletionEquals(count($completions), 1);
$this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0;
$method = new ReflectionMethod($ccompletion, '_save');
@ -1910,15 +1910,15 @@ final class completionlib_test extends advanced_testcase {
$completionid = $ccompletion->mark_enrolled();
$completions = $DB->get_records('course_completions');
$this->assertEquals(count($completions), 1);
$this->assertEquals(reset($completions)->id, $completionid);
$this->assertCompletionEquals(count($completions), 1);
$this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0;
$completionid = $ccompletion->mark_enrolled();
$this->assertDebuggingCalled('Can not update data object, no id!');
$this->assertNull($completionid);
$completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions));
$this->assertCompletionEquals(1, count($completions));
}
/**
@ -1953,15 +1953,15 @@ final class completionlib_test extends advanced_testcase {
$completionid = $ccompletion->mark_inprogress();
$completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions));
$this->assertEquals(reset($completions)->id, $completionid);
$this->assertCompletionEquals(1, count($completions));
$this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0;
$completionid = $ccompletion->mark_inprogress();
$this->assertDebuggingCalled('Can not update data object, no id!');
$this->assertNull($completionid);
$completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions));
$this->assertCompletionEquals(1, count($completions));
}
/**
@ -1996,14 +1996,14 @@ final class completionlib_test extends advanced_testcase {
$completionid = $ccompletion->mark_complete();
$completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions));
$this->assertEquals(reset($completions)->id, $completionid);
$this->assertCompletionEquals(1, count($completions));
$this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0;
$completionid = $ccompletion->mark_complete();
$this->assertNull($completionid);
$completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions));
$this->assertCompletionEquals(1, count($completions));
}
/**
@ -2040,8 +2040,8 @@ final class completionlib_test extends advanced_testcase {
$completionid = $completion->mark_complete($record['timecompleted']);
$completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions));
$this->assertEquals(reset($completions)->id, $completionid);
$this->assertCompletionEquals(1, count($completions));
$this->assertCompletionEquals(reset($completions)->id, $completionid);
}
/**

View file

@ -308,7 +308,15 @@ final class date_test extends advanced_testcase {
$this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
// Admin should fix the settings.
set_error_handler(function ($errno, $errstr): void {
$this->assertStringContainsString('Unknown or bad timezone', $errstr);
restore_error_handler();
}, E_ALL);
$this->setTimezone('xxx/zzzz', 'Europe/Prague');
set_error_handler(function ($errno, $errstr): void {
$this->assertStringContainsString('Unknown or bad timezone', $errstr);
restore_error_handler();
}, E_ALL);
$this->assertSame('Europe/Prague', core_date::get_server_timezone());
}
@ -490,17 +498,36 @@ final class date_test extends advanced_testcase {
$this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
$this->assertSame('Europe/Prague', core_date::get_user_timezone());
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->setTimezone('xxx/yyy', 'Europe/London');
$this->assertCount(1, $invokable->get_invocations());
$USER->timezone = 'abc/def';
$CFG->forcetimezone = 'Europe/Berlin';
$this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
$this->assertSame('Europe/Berlin', core_date::get_user_timezone());
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->setTimezone('xxx/yyy', 'Europe/London');
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
$USER->timezone = 'abc/def';
$CFG->forcetimezone = 99;
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Europe/London', core_date::get_user_timezone(null));
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Europe/London', core_date::get_user_timezone());
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
// User object parameter.
$admin = get_admin();
@ -572,14 +599,30 @@ final class date_test extends advanced_testcase {
$this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
$this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
$USER->timezone = 'xxz/zzz';
$this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
$this->assertCount(0, $invokable->get_invocations());
restore_error_handler();
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->setTimezone('xxx', 'Europe/Prague');
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
$CFG->forcetimezone = '99';
$USER->timezone = 'xxx';
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
$this->assertCount(1, $invokable->get_invocations());
$this->assertSame('Europe/Prague', core_date::get_user_timezone(99));
$this->assertCount(2, $invokable->get_invocations());
$this->assertSame('Etc/GMT-1', core_date::get_user_timezone(1));
$this->assertCount(2, $invokable->get_invocations());
restore_error_handler();
$this->setTimezone('Europe/Prague');
$CFG->forcetimezone = 'Pacific/Auckland';
@ -593,7 +636,11 @@ final class date_test extends advanced_testcase {
$USER->timezone = 'Europe/London';
$CFG->forcetimezone = 99;
$tz = new DateTimeZone('Pacific/Auckland');
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Pacific/Auckland', core_date::get_user_timezone($tz));
$this->assertCount(0, $invokable->get_invocations());
restore_error_handler();
}
/**

View file

@ -501,7 +501,7 @@ final class grouplib_test extends \advanced_testcase {
'userid' => $user2->id,
'groupnames' => $group1->name,
],
], $records);
], array_values($records));
}
public function test_groups_get_group_by_name(): void {
@ -1158,7 +1158,7 @@ final class grouplib_test extends \advanced_testcase {
$this->assertEquals([$c1group1->id], array_keys($groups));
$this->assertEqualsCanonicalizing(
[$c1user1->id, $c12user1->id],
$groups[$c1group1->id]->members
array_values($groups[$c1group1->id]->members),
);
}

View file

@ -44,6 +44,26 @@ final class moodlelib_partial_test extends \advanced_testcase {
$this->assertEquals($expected, partial($callable, ...$initialargs)(...$calledargs));
}
public function test_partial_args_intance_methods(): void {
// Using named args on initial args only - instance method.
$this->assertEquals(
'foo/bar/baz/bum',
partial(
[$this, 'example_instance_method'],
...['foo' => 'foo']
)(...['bar', 'baz', 'bum']),
);
// Using named args on called args only - instance method.
$this->assertEquals(
'foo/bar/baz/bum',
partial(
[$this, 'example_instance_method'],
...['foo' => 'foo']
)(...['bar' => 'bar', 'baz' => 'baz', 'bum' => 'bum']),
);
}
/**
* An example static method as part of the testcase.
*
@ -109,18 +129,6 @@ final class moodlelib_partial_test extends \advanced_testcase {
['needle' => 'foo'],
true,
],
'Using named args on initial args only - instance method' => [
[new self(), 'example_instance_method'],
['foo' => 'foo'],
['bar', 'baz', 'bum'],
'foo/bar/baz/bum',
],
'Using named args on called args only - instance method' => [
[new self(), 'example_instance_method'],
['foo'],
['bar' => 'bar', 'baz' => 'baz', 'bum' => 'bum'],
'foo/bar/baz/bum',
],
'Using named args on initial args only - static method' => [
[self::class, 'example_static_method'],
['foo' => 'foo'],

View file

@ -3283,7 +3283,7 @@ EOF;
'nodiverts' => array(
'divertallemailsto' => null,
'divertallemailsexcept' => null,
array(
'addresses' => array(
'foo@example.com',
'test@real.com',
'fred.jones@example.com',
@ -3291,12 +3291,12 @@ EOF;
'fred@example.com',
'fred+verp@example.com',
),
false,
'expected' => false,
),
'alldiverts' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => null,
array(
'addresses' => array(
'foo@example.com',
'test@real.com',
'fred.jones@example.com',
@ -3304,65 +3304,65 @@ EOF;
'fred@example.com',
'fred+verp@example.com',
),
true,
'expected' => true,
),
'alsodiverts' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com',
array(
'addresses' => array(
'foo@example.com',
'test@real.com',
'fred.jones@example.com',
'Fred.Jones@Example.com',
),
true,
'expected' => true,
),
'divertsexceptions' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com',
array(
'addresses' => array(
'dev1@dev.com',
'fred@example.com',
'Fred@Example.com',
'fred+verp@example.com',
),
false,
'expected' => false,
),
'divertsexceptionsnewline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@dev.com\nfred(\+.*)?@example.com",
array(
'addresses' => array(
'dev1@dev.com',
'fred@example.com',
'fred+verp@example.com',
),
false,
'expected' => false,
),
'alsodivertsnewline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@dev.com\nfred(\+.*)?@example.com",
array(
'addresses' => array(
'foo@example.com',
'test@real.com',
'fred.jones@example.com',
),
true,
'expected' => true,
),
'alsodivertsblankline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@dev.com\n",
[
'addresses' => [
'lionel@example.com',
],
true,
'expected' => true,
),
'divertsexceptionblankline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@example.com\n",
[
'addresses' => [
'lionel@example.com',
],
false,
'expected' => false,
),
);
}

View file

@ -428,12 +428,12 @@ final class extension_test extends \advanced_testcase {
'mod_instance_helper with plugin disabled' => [
'bbbenabled' => false,
'apiclass' => mod_instance_helper::class,
'result' => [],
'extensionclasses' => [],
],
'mod_instance_helper with plugin enabled' => [
'bbbenabled' => true,
'apiclass' => mod_instance_helper::class,
'result' => [
'extensionclasses' => [
'bbbext_simple\\bigbluebuttonbn\\mod_instance_helper',
],
],

View file

@ -120,7 +120,7 @@ final class meeting_test extends \advanced_testcase {
* @covers ::create_meeting_data
* @covers ::create_meeting_metadata
*/
public function test_create_meeting(int $type, ?string $groupname): void {
public function test_create_meeting(int $type, ?string $groupname, $groupmode, $canjoin): void {
$this->resetAfterTest();
[$meeting, $useringroup, $usernotingroup, $groupid, $activity] =
$this->prepare_meeting($type, $groupname, SEPARATEGROUPS, false);
@ -142,7 +142,7 @@ final class meeting_test extends \advanced_testcase {
* @covers ::get_meeting_info
* @covers ::do_get_meeting_info
*/
public function test_get_meeting_info(int $type, ?string $groupname): void {
public function test_get_meeting_info(int $type, ?string $groupname, $groupmode, $canjoin): void {
$this->resetAfterTest();
[$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname);
$meetinginfo = $meeting->get_meeting_info();

View file

@ -741,31 +741,31 @@ final class manager_test extends \advanced_testcase {
return [
// User presets.
'listtemplate' => [
'templatename' => 'listtemplate',
'templatetoreset' => 'listtemplate',
'expected' => ['listtemplate', 'listtemplateheader', 'listtemplatefooter'],
],
'singletemplate' => [
'templatename' => 'singletemplate',
'templatetoreset' => 'singletemplate',
'expected' => ['singletemplate'],
],
'asearchtemplate' => [
'templatename' => 'asearchtemplate',
'templatetoreset' => 'asearchtemplate',
'expected' => ['asearchtemplate'],
],
'addtemplate' => [
'templatename' => 'addtemplate',
'templatetoreset' => 'addtemplate',
'expected' => ['addtemplate'],
],
'rsstemplate' => [
'templatename' => 'rsstemplate',
'templatetoreset' => 'rsstemplate',
'expected' => ['rsstemplate', 'rsstitletemplate'],
],
'csstemplate' => [
'templatename' => 'csstemplate',
'templatetoreset' => 'csstemplate',
'expected' => ['csstemplate'],
],
'jstemplate' => [
'templatename' => 'jstemplate',
'templatetoreset' => 'jstemplate',
'expected' => ['jstemplate'],
],
];

View file

@ -109,14 +109,14 @@ final class preset_importer_test extends \advanced_testcase {
public static function needs_mapping_provider(): array {
$basedprovider = static::preset_importer_provider();
$basedprovider['Empty database / Empty importer']['needsmapping'] = false;
$basedprovider['Empty database / Importer with fields']['needsmapping'] = false;
$basedprovider['Database with fields / Empty importer']['needsmapping'] = true;
$basedprovider['Same fields']['needsmapping'] = false;
$basedprovider['Fields to create']['needsmapping'] = true;
$basedprovider['Fields to remove']['needsmapping'] = true;
$basedprovider['Fields to update']['needsmapping'] = true;
$basedprovider['Fields to create, remove and update']['needsmapping'] = true;
$basedprovider['Empty database / Empty importer']['expectedresult'] = false;
$basedprovider['Empty database / Importer with fields']['expectedresult'] = false;
$basedprovider['Database with fields / Empty importer']['expectedresult'] = true;
$basedprovider['Same fields']['expectedresult'] = false;
$basedprovider['Fields to create']['expectedresult'] = true;
$basedprovider['Fields to remove']['expectedresult'] = true;
$basedprovider['Fields to update']['expectedresult'] = true;
$basedprovider['Fields to create, remove and update']['expectedresult'] = true;
return $basedprovider;
}
@ -304,6 +304,7 @@ final class preset_importer_test extends \advanced_testcase {
): void {
global $USER;
// xdebug_break();
$this->resetAfterTest();
$this->setAdminUser();
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');

View file

@ -36,7 +36,7 @@ final class result_test extends \advanced_testcase {
public static function result_data_provider(): array {
return [
'fill-in with case sensitive' => [
'result' => [
'providedresultdata' => [
'interactiontype' => 'fill-in',
'description' => '<p>Fill in the missing words</p>
<p>Meow .... this is a __________</p>
@ -47,13 +47,13 @@ final class result_test extends \advanced_testcase {
. '"https:\\/\\/h5p.org\\/x-api\\/case-sensitivity":true,'
. '"https:\\/\\/h5p.org\\/x-api\\/alternatives":[["cat"],["dog"]]},"contextExtensions":{}}',
],
'useranswers' => [
'expecteduseranswers' => [
'Gap #1 - cat' => (object) ['answer' => 'Cat', 'incorrect' => true],
'Gap #2 - dog' => (object) ['answer' => 'dog', 'correct' => true],
],
],
'fill-in with case insensitive' => [
'result' => [
'providedresultdata' => [
'interactiontype' => 'fill-in',
'description' => '<p>Fill in the missing words</p>
<p>Meow .... this is a __________</p>
@ -64,13 +64,13 @@ final class result_test extends \advanced_testcase {
. '"https:\\/\\/h5p.org\\/x-api\\/case-sensitivity":false,'
. '"https:\\/\\/h5p.org\\/x-api\\/alternatives":[["cat"],["dog"]]},"contextExtensions":{}}',
],
'useranswers' => [
'expecteduseranswers' => [
'Gap #1 - cat' => (object) ['answer' => 'Cat', 'correct' => true],
'Gap #2 - dog' => (object) ['answer' => 'dog', 'correct' => true],
],
],
'drag and drop' => [
'result' => [
'providedresultdata' => [
'interactiontype' => 'matching',
'description' => 'Drag and Drop Test',
'correctpattern' => '["0[.]0[,]0[.]2[,]1[.]1[,]1[.]0"]',
@ -85,7 +85,7 @@ final class result_test extends \advanced_testcase {
. '"http:\/\/h5p.org\/x-api\/h5p-subContentId":"59590246-f16e-4855-8dd6-c80e892ef96b"},'
. '"contextExtensions":{}}',
],
'useranswers' => [
'expecteduseranswers' => [
'Answer 1 (DZ1 and DZ2) - Dropzone 1, Dropzone 2' => (object) ['answer' => 'Dropzone 1', 'correct' => true],
'Anwser 2 (DZ2) - Dropzone 2' => (object) ['answer' => 'Dropzone 2', 'correct' => true],
'Anwser 3 (DZ1) - Dropzone 1' => (object) ['answer' => 'Dropzone 1', 'correct' => true],
@ -93,7 +93,7 @@ final class result_test extends \advanced_testcase {
],
],
'drag and drop with no answer' => [
'result' => [
'providedresultdata' => [
'interactiontype' => 'matching',
'description' => 'Drag and Drop Test',
'correctpattern' => '["0[.]0[,]0[.]2[,]1[.]1[,]1[.]0"]',
@ -108,7 +108,7 @@ final class result_test extends \advanced_testcase {
. '"http:\/\/h5p.org\/x-api\/h5p-subContentId":"59590246-f16e-4855-8dd6-c80e892ef96b"},'
. '"contextExtensions":{}}',
],
'useranswers' => [
'expecteduseranswers' => [
'Answer 1 (DZ1 and DZ2) - Dropzone 1, Dropzone 2' => (object) ['answer' => 'Dropzone 2', 'correct' => true],
'Anwser 2 (DZ2) - Dropzone 2' => (object) ['answer' => 'Dropzone 2', 'correct' => true],
'Anwser 3 (DZ1) - Dropzone 1' => (object) ['answer' => 'None', 'incorrect' => true],
@ -116,7 +116,7 @@ final class result_test extends \advanced_testcase {
],
],
'sort the paragraph text' => [
'result' => [
'providedresultdata' => [
'interactiontype' => 'sequencing',
'description' => 'SortParagraphs',
'correctpattern' => '["0[,]1[,]2[,]3[,]4"]',
@ -131,7 +131,7 @@ final class result_test extends \advanced_testcase {
'"extensions":{"http:\\/\\/h5p.org\\/x-api\\/h5p-local-content-id":39,'
. '"https:\\/\\/h5p.org\\/x-api\\/duplicates-interchangeable":1},"contextExtensions":{}}',
],
'useranswers' => [
'expecteduseranswers' => [
'#1 - First I wake up at 7.30 am' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#2 - Next I get dressed' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#3 - Afterward I have breakfast' => (object) ['answer' => 'Incorrect answer', 'fail' => true],
@ -140,7 +140,7 @@ final class result_test extends \advanced_testcase {
],
],
'sequencing images' => [
'result' => [
'providedresultdata' => [
'interactiontype' => 'sequencing',
'description' => 'Order the planets from smallest to largest',
'correctpattern' => '["item_3[,]item_0[,]item_7[,]item_1[,]item_5[,]item_2[,]item_4[,]item_6"]',
@ -152,7 +152,7 @@ final class result_test extends \advanced_testcase {
. '{"id":"item_6","description":{"en-US":"Jupiter"}}],"extensions":'
. '{"http:\/\/h5p.org\/x-api\/h5p-local-content-id":43},"contextExtensions":{}}',
],
'useranswers' => [
'expecteduseranswers' => [
'#1 - Mercury' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#2 - Mars' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#3 - Earth' => (object) ['answer' => 'Incorrect answer', 'fail' => true],

View file

@ -241,19 +241,19 @@ final class lib_test extends \advanced_testcase {
'name' => 'Test label 1',
'content' => '<p>Simple textual content<p>',
'format' => FORMAT_HTML,
'expected' => 'Test label 1'
'expectedname' => 'Test label 1'
],
'simple' => [
'name' => '',
'content' => '<p>Simple textual content<p>',
'format' => FORMAT_HTML,
'expected' => 'Simple textual content'
'expectedname' => 'Simple textual content'
],
'empty' => [
'name' => '',
'content' => '',
'format' => FORMAT_HTML,
'expected' => 'Test label 1'
'expectedname' => 'Test label 1'
],
'withaudiocontent' => [
'name' => '',
@ -263,7 +263,7 @@ final class lib_test extends \advanced_testcase {
@@PLUGINFILE@@/moodle-hit-song.mp3
</audio>&nbsp;</p>',
'format' => FORMAT_HTML,
'expected' => 'Test with audio'
'expectedname' => 'Test with audio'
],
'withvideo' => [
'name' => '',
@ -273,7 +273,7 @@ final class lib_test extends \advanced_testcase {
https://www.youtube.com/watch?v=xxxyy
</video>&nbsp;</p>',
'format' => FORMAT_HTML,
'expected' => 'Test video https://www.youtube.com/watch?v=xxxyy'
'expectedname' => 'Test video https://www.youtube.com/watch?v=xxxyy'
],
'with video trimming' => [
'name' => '',
@ -283,61 +283,61 @@ final class lib_test extends \advanced_testcase {
https://www.youtube.com/watch?v=xxxyy
</video>&nbsp;</p>',
'format' => FORMAT_HTML,
'expected' => 'Test with video to be trimmed https://www.youtube....'
'expectedname' => 'Test with video to be trimmed https://www.youtube....'
],
'with plain text' => [
'name' => '',
'content' => 'Content with @@PLUGINFILE@@/moodle-hit-song.mp3 nothing',
'format' => FORMAT_HTML,
'expected' => 'Content with nothing'
'expectedname' => 'Content with nothing'
],
'with several spaces' => [
'name' => '',
'content' => "Content with @@PLUGINFILE@@/moodle-hit-song.mp3 \r &nbsp; several spaces",
'format' => FORMAT_HTML,
'expected' => 'Content with several spaces'
'expectedname' => 'Content with several spaces'
],
'empty spaces' => [
'name' => '',
'content' => ' &nbsp; ',
'format' => FORMAT_HTML,
'expected' => 'Text and media area'
'expectedname' => 'Text and media area'
],
'only html' => [
'name' => '',
'content' => '<audio controls="controls"><source src=""></audio>',
'format' => FORMAT_HTML,
'expected' => 'Text and media area'
'expectedname' => 'Text and media area'
],
'markdown' => [
'name' => '',
'content' => "##Simple Title\n simple markdown format",
'format' => FORMAT_MARKDOWN,
'expected' => 'Simple Title simple markdown format'
'expectedname' => 'Simple Title simple markdown format'
],
'markdown with pluginfile' => [
'name' => '',
'content' => "##Simple Title\n simple markdown format @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_MARKDOWN,
'expected' => 'Simple Title simple markdown format'
'expectedname' => 'Simple Title simple markdown format'
],
'plain text' => [
'name' => '',
'content' => "Simple plain text @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_PLAIN,
'expected' => 'Simple plain text'
'expectedname' => 'Simple plain text'
],
'moodle format text' => [
'name' => '',
'content' => "Simple plain text @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_MOODLE,
'expected' => 'Simple plain text'
'expectedname' => 'Simple plain text'
],
'html format text' => [
'name' => '',
'content' => "<h1>Simple plain title</h1><p> with plain text</p> @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_HTML,
'expected' => 'Simple plain title with plain text'
'expectedname' => 'Simple plain title with plain text'
],
];
}

View file

@ -66,7 +66,7 @@ final class numeric_helper_test extends \advanced_testcase {
return [
"Using a decimal as a separator" => [
"decsep" => ".",
"test" => [
"tests" => [
["2.1", 2.1],
["1:4.2", "1:4.2"],
["2,1", 2],
@ -76,7 +76,7 @@ final class numeric_helper_test extends \advanced_testcase {
],
"Using a comma as a separator" => [
"decsep" => ",",
"test" => [
"tests" => [
["2,1", 2.1],
["1:4,2", "1:4.2"],
["2.1", 2.1],
@ -85,7 +85,7 @@ final class numeric_helper_test extends \advanced_testcase {
],
"Using a X as a separator" => [
"decsep" => "X",
"test" => [
"tests" => [
["2X1", 2.1],
["1:4X2", "1:4.2"],
["2.1", 2.1],
@ -104,7 +104,7 @@ final class numeric_helper_test extends \advanced_testcase {
return [
"Using a decimal as a separator" => [
"decsep" => ".",
"test" => [
"tests" => [
["2.1", 2.1],
["1:4.2", "1:4.2"],
["2,1", "2,1"],
@ -113,7 +113,7 @@ final class numeric_helper_test extends \advanced_testcase {
],
"Using a comma as a separator" => [
"decsep" => ",",
"test" => [
"tests" => [
["2,1", "2,1"],
["1:4,2", "1:4,2"],
["2.1", "2,1"],
@ -123,7 +123,7 @@ final class numeric_helper_test extends \advanced_testcase {
],
"Using a X as a separator" => [
"decsep" => "X",
"test" => [
"tests" => [
["2X1", "2X1"],
["1:4X2", "1:4X2"],
["2.1", "2X1"],

View file

@ -60,31 +60,31 @@ final class validate_quiz_access_test extends \advanced_testcase {
'cmid' => null,
'url' => null,
'configkey' => null,
'/Invalid parameter value detected \(Missing required key in single structure: cmid\)/'
'messageregex' => '/Invalid parameter value detected \(Missing required key in single structure: cmid\)/'
],
'no course module id' => [
'cmid' => null,
'url' => 'https://www.example.com/moodle',
'configkey' => hash('sha256', 'configkey'),
'/Invalid parameter value detected \(Missing required key in single structure: cmid\)/'
'messageregex' => '/Invalid parameter value detected \(Missing required key in single structure: cmid\)/'
],
'no url' => [
'cmid' => 123,
'url' => null,
'configkey' => hash('sha256', 'configkey'),
'/Invalid parameter value detected \(Missing required key in single structure: url\)/'
'messageregex' => '/Invalid parameter value detected \(Missing required key in single structure: url\)/'
],
'cmid is not an int' => [
'cmid' => 'test',
'url' => 'https://www.example.com/moodle',
'configkey' => null,
'/Invalid external api parameter: the value is "test", the server was expecting "int" type/'
'messageregex' => '/Invalid external api parameter: the value is "test", the server was expecting "int" type/'
],
'url is not a url' => [
'cmid' => 123,
'url' => 123,
'configkey' => hash('sha256', 'configkey'),
'/Invalid external api parameter: the value is "123", the server was expecting "url" type/'
'messageregex' => '/Invalid external api parameter: the value is "123", the server was expecting "url" type/'
],
];
}

View file

@ -225,7 +225,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class,
'expectedeventclass' => user_override_created::class,
],
'create user override - no calendar events should be created' => [
'existingdata' => [],
@ -239,7 +239,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class,
'expectedeventclass' => user_override_created::class,
],
'create user override - only timeopen' => [
'existingdata' => [],
@ -253,7 +253,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class,
'expectedeventclass' => user_override_created::class,
],
'create group override - no existing data' => [
'existingdata' => [],
@ -267,7 +267,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 1,
'expectedevent' => group_override_created::class,
'expectedeventclass' => group_override_created::class,
],
'create group override - no calendar events should be created' => [
'existingdata' => [],
@ -281,7 +281,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 1,
'expectedevent' => group_override_created::class,
'expectedeventclass' => group_override_created::class,
],
'create group override - only timeopen' => [
'existingdata' => [],
@ -295,7 +295,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => null,
],
'expectedrecordscreated' => 1,
'expectedevent' => group_override_created::class,
'expectedeventclass' => group_override_created::class,
],
'update user override - updating existing data' => [
'existingdata' => [
@ -318,7 +318,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 0,
'expectedevent' => user_override_updated::class,
'expectedeventclass' => user_override_updated::class,
],
'update group override - updating existing data' => [
'existingdata' => [
@ -341,7 +341,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test',
],
'expectedrecordscreated' => 0,
'expectedevent' => group_override_updated::class,
'expectedeventclass' => group_override_updated::class,
],
'attempts is set to unlimited (i.e. 0)' => [
'existingdata' => [],
@ -356,7 +356,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => null,
],
'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class,
'expectedeventclass' => user_override_created::class,
],
'some settings submitted are the same as what is in the quiz (valid)' => [
'existingdata' => [],
@ -372,7 +372,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => null,
],
'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class,
'expectedeventclass' => user_override_created::class,
],
];
}
@ -900,31 +900,31 @@ final class override_manager_test extends \advanced_testcase {
public static function delete_override_provider(): array {
return [
'delete by id (no events logged)' => [
'function' => fn($manager, $override) => $manager->delete_overrides_by_id([$override->id], false, false),
'deletefunction' => fn($manager, $override) => $manager->delete_overrides_by_id([$override->id], false, false),
'checkeventslogged' => false,
],
'delete single (no events logged)' => [
'function' => fn($manager, $override) => $manager->delete_overrides([$override], false, false),
'deletefunction' => fn($manager, $override) => $manager->delete_overrides([$override], false, false),
'checkeventslogged' => false,
],
'delete all (no events logged)' => [
'function' => fn($manager, $override) => $manager->delete_all_overrides(false, false),
'deletefunction' => fn($manager, $override) => $manager->delete_all_overrides(false, false),
'checkeventslogged' => false,
],
'delete by id (events logged)' => [
'function' => fn($manager, $override) => $manager->delete_overrides_by_id([$override->id], true, false),
'deletefunction' => fn($manager, $override) => $manager->delete_overrides_by_id([$override->id], true, false),
'checkeventslogged' => true,
],
'delete single (events logged)' => [
'function' => fn($manager, $override) => $manager->delete_overrides([$override], true, false),
'deletefunction' => fn($manager, $override) => $manager->delete_overrides([$override], true, false),
'checkeventslogged' => true,
],
'delete all (events logged)' => [
'function' => fn($manager, $override) => $manager->delete_all_overrides(true, false),
'deletefunction' => fn($manager, $override) => $manager->delete_all_overrides(true, false),
'checkeventslogged' => true,
],
'delete all in database (events logged)' => [
'function' => fn($manager, $override) => $manager->delete_all_overrides(true, false),
'deletefunction' => fn($manager, $override) => $manager->delete_all_overrides(true, false),
'checkeventslogged' => true,
],
];

View file

@ -34,19 +34,19 @@ final class restore_format_test extends \advanced_testcase {
public static function restore_format_test_provider(): array {
return [
'creole' => [
'data' => 'creole',
'format' => 'creole',
'expected' => 'creole',
],
'html' => [
'data' => 'html',
'format' => 'html',
'expected' => 'html',
],
'wikimarkup' => [
'data' => 'nwiki',
'format' => 'nwiki',
'expected' => 'nwiki',
],
'wrong format' => [
'data' => '../wrongformat123',
'format' => '../wrongformat123',
'expected' => 'wrongformat',
],
];

View file

@ -363,19 +363,19 @@ final class wikiparser_test extends \advanced_testcase {
public static function format_parser_provider(): array {
return [
'creole' => [
'data' => 'creole',
'format' => 'creole',
'expected' => 'creole',
],
'html' => [
'data' => 'html',
'format' => 'html',
'expected' => 'html',
],
'wikimarkup' => [
'data' => 'nwiki',
'format' => 'nwiki',
'expected' => 'nwiki',
],
'wrong format' => [
'data' => '../wrongformat123',
'format' => '../wrongformat123',
'expected' => 'exception',
],
];

View file

@ -1,14 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="lib/phpunit/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="lib/phpunit/bootstrap.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
backupGlobals="false"
backupStaticAttributes="false"
cacheResult="false"
stopOnError="false"
stopOnFailure="false"
@ -16,7 +12,9 @@
stopOnSkipped="false"
beStrictAboutTestsThatDoNotTestAnything="false"
beStrictAboutOutputDuringTests="true"
>
cacheDirectory=".phpunit.cache"
backupStaticProperties="false"
>
<php>
<!--<const name="PHPUNIT_LONGTEST" value="1"/> uncomment to execute also slow or otherwise expensive tests-->
@ -305,8 +303,8 @@
<!--@plugin_suites_end@-->
</testsuites>
<coverage>
<source>
<!--@coveragelist@-->
</coverage>
</source>
</phpunit>

View file

@ -272,32 +272,42 @@ final class helper_test extends \advanced_testcase {
*/
public static function load_question_facility_provider(): \Generator {
yield 'Facility case 1' => [
'Quiz 1 attempts' => [
// Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]),
],
'Expected quiz 1 facilities' => ['100.00%', '0.00%', '0.00%', '0.00%'],
'Quiz 2 attempts' => [
// Expected quiz 1 facilities.
'expectedquiz1facilities' => ['100.00%', '0.00%', '0.00%', '0.00%'],
// Quiz 2 attempts.
'quiz2attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]),
],
'Expected quiz 2 facilities' => ['100.00%', '50.00%', '0.00%', '0.00%'],
'Expected average facilities' => ['100.00%', '25.00%', '0.00%', '0.00%'],
// Expected quiz 2 facilities.
'expectedquiz2facilities' => ['100.00%', '50.00%', '0.00%', '0.00%'],
// Expected average facilities.
'expectedaveragefacilities' => ['100.00%', '25.00%', '0.00%', '0.00%'],
];
yield 'Facility case 2' => [
'Quiz 1 attempts' => [
// Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]),
self::generate_attempt_answers([1, 1, 1, 0]),
],
'Expected quiz 1 facilities' => ['100.00%', '66.67%', '33.33%', '0.00%'],
'Quiz 2 attempts' => [
// Expected quiz 1 facilities.
'expectedquiz1facilities' => ['100.00%', '66.67%', '33.33%', '0.00%'],
// Quiz 2 attempts.
'quiz2attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]),
self::generate_attempt_answers([1, 1, 1, 0]),
self::generate_attempt_answers([1, 1, 1, 1]),
],
'Expected quiz 2 facilities' => ['100.00%', '75.00%', '50.00%', '25.00%'],
'Expected average facilities' => ['100.00%', '70.83%', '41.67%', '12.50%'],
// Expected quiz 2 facilities.
'expectedquiz2facilities' => ['100.00%', '75.00%', '50.00%', '25.00%'],
// Expected average facilities.
'expectedaveragefacilities' => ['100.00%', '70.83%', '41.67%', '12.50%'],
];
}
@ -380,21 +390,26 @@ final class helper_test extends \advanced_testcase {
*/
public static function load_question_discriminative_efficiency_provider(): \Generator {
yield 'Discriminative efficiency' => [
'Quiz 1 attempts' => [
// Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]),
self::generate_attempt_answers([1, 0, 1, 0]),
self::generate_attempt_answers([1, 1, 1, 1]),
],
'Expected quiz 1 discriminative efficiency' => ['N/A', '33.33%', '33.33%', '100.00%'],
'Quiz 2 attempts' => [
// Expected quiz 1 facilities.
'expectedquiz1discriminativeefficiency' => ['N/A', '33.33%', '33.33%', '100.00%'],
// Quiz 2 attempts.
'quiz2attempts' => [
self::generate_attempt_answers([1, 1, 1, 1]),
self::generate_attempt_answers([0, 0, 0, 0]),
self::generate_attempt_answers([1, 0, 0, 1]),
self::generate_attempt_answers([0, 1, 1, 0]),
],
'Expected quiz 2 discriminative efficiency' => ['50.00%', '50.00%', '50.00%', '50.00%'],
'Expected average discriminative efficiency' => ['50.00%', '41.67%', '41.67%', '75.00%'],
// Expected quiz 2 facilities.
'expectedquiz2discriminativeefficiency' => ['50.00%', '50.00%', '50.00%', '50.00%'],
// Expected average facilities.
'expectedaveragediscriminativeefficiency' => ['50.00%', '41.67%', '41.67%', '75.00%'],
];
}
@ -501,21 +516,26 @@ final class helper_test extends \advanced_testcase {
*/
public static function load_question_discrimination_index_provider(): \Generator {
yield 'Discrimination Index' => [
'Quiz 1 attempts' => [
// Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]),
self::generate_attempt_answers([1, 0, 1, 0]),
self::generate_attempt_answers([1, 1, 1, 1]),
],
'Expected quiz 1 Discrimination Index' => ['N/A', '30.15%', '30.15%', '81.65%'],
'Quiz 2 attempts' => [
// Expected quiz 1 facilities.
'expectedquiz1discriminationindex' => ['N/A', '30.15%', '30.15%', '81.65%'],
// Quiz 2 attempts.
'quiz2attempts' => [
self::generate_attempt_answers([1, 1, 1, 1]),
self::generate_attempt_answers([0, 0, 0, 0]),
self::generate_attempt_answers([1, 0, 0, 1]),
self::generate_attempt_answers([0, 1, 1, 0]),
],
'Expected quiz 2 discrimination Index' => ['44.72%', '44.72%', '44.72%', '44.72%'],
'Expected average discrimination Index' => ['44.72%', '37.44%', '37.44%', '63.19%'],
// Expected quiz 2 facilities.
'expectedquiz2discriminationindex' => ['44.72%', '44.72%', '44.72%', '44.72%'],
// Expected average facilities.
'expectedaveragediscriminationindex' => ['44.72%', '37.44%', '37.44%', '63.19%'],
];
}

View file

@ -51,8 +51,10 @@ final class report_test extends advanced_testcase {
$this->assertEquals('My report with tags', $report->get('name'));
$this->assertEquals(datasource::TYPE_CUSTOM_REPORT, $report->get('type'));
$this->assertEqualsCanonicalizing(['cat', 'dog'],
core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $report->get('id')));
$this->assertEqualsCanonicalizing(
['cat', 'dog'],
array_values(core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $report->get('id'))),
);
$report = report::create_report((object) [
'name' => 'My report without tags',
@ -96,8 +98,10 @@ final class report_test extends advanced_testcase {
$this->assertEquals('My renamed report adding tags', $reportupdated->get('name'));
$this->assertTrue($reportupdated->get('uniquerows'));
$this->assertEqualsCanonicalizing(['cat', 'dog'],
core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $reportupdated->get('id')));
$this->assertEqualsCanonicalizing(
['cat', 'dog'],
array_values(core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $reportupdated->get('id'))),
);
}
/**

View file

@ -948,17 +948,17 @@ XML;
*
* @dataProvider sync_reference_provider
* @param array $storedfileargs
* @param array $storedfilemethodsmock
* @param array $mockfunctions
* @param bool $expectedresult
* @return void
*/
public function test_sync_reference(array $storedfileargs, $storedfilemethodsmock, bool $expectedresult): void {
public function test_sync_reference(array $storedfileargs, $mockfunctions, bool $expectedresult): void {
$this->resetAfterTest(true);
if (isset($storedfilemethodsmock[0])) {
if (isset($mockfunctions[0])) {
$storedfile = $this->createMock(\stored_file::class);
if ($storedfilemethodsmock[0] === 'get_referencelastsync') {
if ($mockfunctions[0] === 'get_referencelastsync') {
if (!$expectedresult) {
$storedfile->method('get_referencelastsync')->willReturn(DAYSECS + time());
}