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 phpcs.xml
jsconfig.json jsconfig.json
UPGRADING-CURRENT.md UPGRADING-CURRENT.md
.phpunit.cache

View file

@ -468,7 +468,7 @@ final class manager_util_test extends \advanced_testcase {
$CFG->dirroot = $oldroot; $CFG->dirroot = $oldroot;
} }
public function clean_features_path_list() { public static function clean_features_path_list() {
return array( 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/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'], ['/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. * Test the pseudo states of a data request with an export request.
* *
* @dataProvider status_state_provider * @dataProvider status_state_provider
* @param int $status * @param int $state
* @param bool $resettable * @param bool $resettable
* @param bool $active * @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 = new \tool_dataprivacy\data_request();
$uut->set('status', $status); $uut->set('status', $state);
$uut->set('type', api::DATAREQUEST_TYPE_EXPORT); $uut->set('type', api::DATAREQUEST_TYPE_EXPORT);
$this->assertEquals($resettable, $uut->is_resettable()); $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. * Test the pseudo states of a data request with a delete request.
* *
* @dataProvider status_state_provider * @dataProvider status_state_provider
* @param int $status * @param int $state
* @param bool $resettable * @param bool $resettable
* @param bool $active * @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 = new \tool_dataprivacy\data_request();
$uut->set('status', $status); $uut->set('status', $state);
$uut->set('type', api::DATAREQUEST_TYPE_DELETE); $uut->set('type', api::DATAREQUEST_TYPE_DELETE);
$this->assertEquals($resettable, $uut->is_resettable()); $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. * Test the pseudo states of a data request.
* *
* @dataProvider status_state_provider * @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 = new \tool_dataprivacy\data_request();
$uut->set('status', $status); $uut->set('status', $state);
$uut->set('type', api::DATAREQUEST_TYPE_OTHERS); $uut->set('type', api::DATAREQUEST_TYPE_OTHERS);
$this->assertFalse($uut->is_resettable()); $this->assertFalse($uut->is_resettable());
@ -142,7 +142,7 @@ final class data_request_test extends data_privacy_testcase {
$states = []; $states = [];
foreach (self::status_state_provider() as $thisstatus) { foreach (self::status_state_provider() as $thisstatus) {
if (!$thisstatus['resettable']) { 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. * Ensure that requests which are not resettable cause an exception to be thrown.
* *
* @dataProvider non_resettable_provider * @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 = new \tool_dataprivacy\data_request();
$uut->set('status', $status); $uut->set('status', $state);
$this->expectException(\moodle_exception::class); $this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('cannotreset', 'tool_dataprivacy')); $this->expectExceptionMessage(get_string('cannotreset', 'tool_dataprivacy'));

View file

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

View file

@ -134,15 +134,15 @@ final class httpsreplace_test extends \advanced_testcase {
/** /**
* Test upgrade_http_links * Test upgrade_http_links
* @param string $content Example content that we'll attempt to replace. * @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. * @param string $expectedcontent What content we are expecting afterwards.
* @dataProvider upgrade_http_links_provider * @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; global $DB;
$this->resetAfterTest(); $this->resetAfterTest();
$this->expectOutputRegex($ouputregex); $this->expectOutputRegex($outputregex);
$finder = new tool_httpreplace_url_finder_mock(); $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. * Test the parsing to host + path components.
* *
* @dataProvider url_provider * @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 $host the expected host component of the URL.
* @param string $path the expected path 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. * @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 { public static function url_provider(): array {
return [ return [
'No path' => [ 'No path' => [
'url' => 'https://example.moodle.net', 'urlstring' => 'https://example.moodle.net',
'host' => 'example.moodle.net', 'host' => 'example.moodle.net',
'path' => null, 'path' => null,
'exception' => false, 'exception' => false,
], ],
'Slash path' => [ 'Slash path' => [
'url' => 'https://example.moodle.net/', 'urlstring' => 'https://example.moodle.net/',
'host' => 'example.moodle.net', 'host' => 'example.moodle.net',
'path' => '/', 'path' => '/',
'exception' => false, 'exception' => false,
], ],
'Path includes file and extension' => [ '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', 'host' => 'example.moodle.net',
'path' => '/uploads/123456789/pic.png', 'path' => '/uploads/123456789/pic.png',
'exception' => false, 'exception' => false,
], ],
'Path includes file, extension and params' => [ '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', 'host' => 'example.moodle.net',
'path' => '/uploads/123456789/pic.png', 'path' => '/uploads/123456789/pic.png',
'exception' => false, 'exception' => false,
], ],
'Malformed - invalid' => [ 'Malformed - invalid' => [
'url' => 'invalid', 'urlstring' => 'invalid',
'host' => null, 'host' => null,
'path' => null, 'path' => null,
'exception' => true, 'exception' => true,
], ],
'Direct, non-encoded utf8 - invalid' => [ 'Direct, non-encoded utf8 - invalid' => [
'url' => 'http://москва.рф/services/', 'urlstring' => 'http://москва.рф/services/',
'host' => 'москва.рф', 'host' => 'москва.рф',
'path' => '/services/', 'path' => '/services/',
'exception' => true, 'exception' => true,

View file

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

View file

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

View file

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

View file

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

View file

@ -98,28 +98,28 @@ final class application_registration_repository_test extends \advanced_testcase
* *
* @dataProvider save_data_provider * @dataProvider save_data_provider
* @covers ::save * @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(); $this->resetAfterTest();
$reg = application_registration::create_draft($regdata['name'], $regdata['uniqueid']); $reg = application_registration::create_draft($registrationdata['name'], $registrationdata['uniqueid']);
if (isset($regdata['platformid'])) { if (isset($registrationdata['platformid'])) {
$reg->set_platformid($regdata['platformid']); $reg->set_platformid($registrationdata['platformid']);
} }
if (isset($regdata['clientid'])) { if (isset($registrationdata['clientid'])) {
$reg->set_clientid($regdata['clientid']); $reg->set_clientid($registrationdata['clientid']);
} }
if (isset($regdata['authenticationrequesturl'])) { if (isset($registrationdata['authenticationrequesturl'])) {
$reg->set_authenticationrequesturl($regdata['authenticationrequesturl']); $reg->set_authenticationrequesturl($registrationdata['authenticationrequesturl']);
} }
if (isset($regdata['jwksurl'])) { if (isset($registrationdata['jwksurl'])) {
$reg->set_jwksurl($regdata['jwksurl']); $reg->set_jwksurl($registrationdata['jwksurl']);
} }
if (isset($regdata['accesstokenurl'])) { if (isset($registrationdata['accesstokenurl'])) {
$reg->set_accesstokenurl($regdata['accesstokenurl']); $reg->set_accesstokenurl($registrationdata['accesstokenurl']);
} }
if (!empty($regdata['setcomplete'])) { if (!empty($registrationdata['setcomplete'])) {
$reg->complete_registration(); $reg->complete_registration();
} }
$repository = new application_registration_repository(); $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 { public static function user_launch_provider(): array {
return [ return [
'New tool: no legacy data, no migration claim sent' => [ 'New tool: no legacy data, no migration claim sent' => [
'legacy_data' => null, 'legacydata' => null,
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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' => [ 'Migrated tool: Legacy data exists, no change in user_id so omitted from claim' => [
'legacy_data' => [ 'legacydata' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
'tools' => [ 'tools' => [
['secret' => 'toolsecret1'], ['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', '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' => [ 'Migrated tool: Legacy data exists, platform signs with different valid secret' => [
'legacy_data' => [ 'legacydata' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
'tools' => [ 'tools' => [
['secret' => 'toolsecret1'], ['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', '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' => [ 'Migrated tool: Legacy data exists, no migration claim sent' => [
'legacy_data' => [ 'legacydata' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
'tools' => [ 'tools' => [
['secret' => 'toolsecret1'], ['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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' => [ 'Migrated tool: Legacy data exists, migration claim signature generated using invalid secret' => [
'legacy_data' => [ 'legacydata' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
'tools' => [ 'tools' => [
['secret' => 'toolsecret1'], ['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', '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' => [ 'Migrated tool: Legacy data exists, migration claim signature omitted' => [
'legacy_data' => [ 'legacydata' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
'tools' => [ 'tools' => [
['secret' => 'toolsecret1'], ['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', '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' => [ 'Migrated tool: Legacy data exists, migration claim missing oauth_consumer_key' => [
'legacy_data' => [ 'legacydata' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
'tools' => [ 'tools' => [
['secret' => 'toolsecret1'], ['secret' => 'toolsecret1'],
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'user_id' => 'user-id-123', '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'); require_once($CFG->dirroot . '/auth/lti/auth.php');
return [ return [
'Migrated tool, user ids changed, new and existing users present in sync' => [ 'Migrated tool, user ids changed, new and existing users present in sync' => [
'legacy_data' => [ 'legacydata' => [
'users' => [ 'users' => [
['user_id' => '1'], ['user_id' => '1'],
['user_id' => '2'], ['user_id' => '2'],
@ -811,8 +811,8 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'resource_config' => null, 'resourceconfig' => null,
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
@ -823,7 +823,7 @@ final class sync_members_test extends \lti_advantage_testcase {
'resource_link_id' => '4b6fa' '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_1'], ['1'])[0],
self::get_mock_members_with_ids(['1p3_2'], ['2'])[0], self::get_mock_members_with_ids(['1p3_2'], ['2'])[0],
self::get_mock_members_with_ids(['1p3_3'], ['3'])[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' => [ 'Migrated tool, no change in user ids, new and existing users present in sync' => [
'legacy_data' => [ 'legacydata' => [
'users' => [ 'users' => [
['user_id' => '1'], ['user_id' => '1'],
['user_id' => '2'], ['user_id' => '2'],
@ -862,8 +862,8 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'resource_config' => null, 'resourceconfig' => null,
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
@ -873,7 +873,7 @@ final class sync_members_test extends \lti_advantage_testcase {
'resource_link_id' => '4b6fa' 'resource_link_id' => '4b6fa'
], ],
], ],
'sync_members_data' => [ 'syncmembers' => [
self::get_mock_members_with_ids(['1'], null)[0], self::get_mock_members_with_ids(['1'], null)[0],
self::get_mock_members_with_ids(['2'], null)[0], self::get_mock_members_with_ids(['2'], null)[0],
self::get_mock_members_with_ids(['3'], 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' => [ 'New tool, no launch migration claim, change in user ids, new and existing users present in sync' => [
'legacy_data' => [ 'legacydata' => [
'users' => [ 'users' => [
['user_id' => '1'], ['user_id' => '1'],
['user_id' => '2'], ['user_id' => '2'],
@ -912,12 +912,12 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'resource_config' => null, 'resourceconfig' => null,
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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_1'], null)[0],
self::get_mock_members_with_ids(['1p3_2'], null)[0], self::get_mock_members_with_ids(['1p3_2'], null)[0],
self::get_mock_members_with_ids(['1p3_3'], 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' => [ 'New tool, no launch migration claim, no change in user ids, new and existing users present in sync' => [
'legacy_data' => [ 'legacydata' => [
'users' => [ 'users' => [
['user_id' => '1'], ['user_id' => '1'],
['user_id' => '2'], ['user_id' => '2'],
@ -956,12 +956,12 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'resource_config' => null, 'resourceconfig' => null,
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1'])[0],
'launch_migration_claim' => null, 'launch_migration_claim' => null,
], ],
'sync_members_data' => [ 'syncmembers' => [
self::get_mock_members_with_ids(['1'], null)[0], self::get_mock_members_with_ids(['1'], null)[0],
self::get_mock_members_with_ids(['2'], null)[0], self::get_mock_members_with_ids(['2'], null)[0],
self::get_mock_members_with_ids(['3'], 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' => [ 'New tool, migration only via member sync, no launch claim, new and existing users present in sync' => [
'legacy_data' => [ 'legacydata' => [
'users' => [ 'users' => [
['user_id' => '1'], ['user_id' => '1'],
['user_id' => '2'], ['user_id' => '2'],
@ -1000,12 +1000,12 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'resource_config' => null, 'resourceconfig' => null,
'launch_data' => [ 'launchdata' => [
'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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_1'], ['1'])[0],
self::get_mock_members_with_ids(['1p3_2'], ['2'])[0], self::get_mock_members_with_ids(['1p3_2'], ['2'])[0],
self::get_mock_members_with_ids(['1p3_3'], ['3'])[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' => [ 'Default provisioning modes, mixed bag of users and roles' => [
'legacy_data' => null, 'legacydata' => null,
'resource_config' => [ 'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY, 'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY,
'provisioningmodeinstructor' => \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], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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. // 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, [ self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor', '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' => [ 'All automatic provisioning, mixed bag of users and roles' => [
'legacy_data' => null, 'legacydata' => null,
'resource_config' => [ 'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY, 'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY,
'provisioningmodeinstructor' => \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], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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. // 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, [ self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor', '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' => [ 'All prompt provisioning, mixed bag of users and roles' => [
'legacy_data' => null, 'legacydata' => null,
'resource_config' => [ 'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_PROMPT_NEW_EXISTING, 'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_PROMPT_NEW_EXISTING,
'provisioningmodeinstructor' => \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], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => null, '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. // 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, [ self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor', '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' => [ 'All automatic provisioning, with legacy data and migration claim, mixed bag of users and roles' => [
'legacy_data' => [ 'legacydata' => [
'users' => [ 'users' => [
['user_id' => '2'], ['user_id' => '2'],
['user_id' => '3'], ['user_id' => '3'],
@ -1196,11 +1196,11 @@ final class sync_members_test extends \lti_advantage_testcase {
['secret' => 'toolsecret2'], ['secret' => 'toolsecret2'],
] ]
], ],
'resource_config' => [ 'resourceconfig' => [
'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY, 'provisioningmodelearner' => \auth_plugin_lti::PROVISIONING_MODE_AUTO_ONLY,
'provisioningmodeinstructor' => \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], 'user' => self::get_mock_launch_users_with_ids(['1p3_1'])[0],
'launch_migration_claim' => [ 'launch_migration_claim' => [
'consumer_key' => 'CONSUMER_1', 'consumer_key' => 'CONSUMER_1',
@ -1210,7 +1210,7 @@ final class sync_members_test extends \lti_advantage_testcase {
'resource_link_id' => '4b6fa' '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. // 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, [ self::get_mock_members_with_ids(['1p3_1'], null, true, true, true, false, [
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor', 'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',

View file

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

View file

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

View file

@ -280,6 +280,9 @@ final class dml_pgsql_read_replica_test extends \advanced_testcase {
]; ];
$this->resetDebugging(); $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 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary);
$db2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions); $db2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions);
$this->assertNotEmpty($db2->get_records('user')); $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. // Attempt to connect to the existing DB host will succeed.
$this->assertEquals("Readwrite db connection succeeded for host {$cfg->dbhost}", $debugging[1]); $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', 'primarykey' => 'id',
'fieldprefix' => 'ban', 'fieldprefix' => 'ban',
'tablealias' => 'banana', 'tablealias' => 'banana',
'banana.id AS banid', 'expected' => 'banana.id AS banid',
], ],
'multiple fields' => [ 'multiple fields' => [
'tablename' => 'test_table_multiple', 'tablename' => 'test_table_multiple',
@ -57,7 +57,7 @@ final class dml_table_test extends \database_driver_testcase {
'primarykey' => 'id', 'primarykey' => 'id',
'fieldprefix' => 'ban', 'fieldprefix' => 'ban',
'tablealias' => 'banana', '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; $DB = $this->tdb;
require_once($CFG->dirroot . '/lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php'); 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}"; $sql = "SELECT * FROM {users}";
@ -499,31 +500,31 @@ final class dml_test extends \database_driver_testcase {
$CFG->debugsqltrace = 1; $CFG->debugsqltrace = 1;
$out = $fixture->four($sql); $out = $fixture->four($sql);
$expected = <<<EOD $expected = <<<EOD
SELECT * FROM {users} SELECT \* FROM {users}
-- line 64 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 ReflectionMethod->invoke\(\)
EOD; EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out); $this->assertMatchesRegularExpression('@' . $this->unix_to_os_dirsep($expected) . '@', $out);
$CFG->debugsqltrace = 2; $CFG->debugsqltrace = 2;
$out = $fixture->four($sql); $out = $fixture->four($sql);
$expected = <<<EOD $expected = <<<EOD
SELECT * FROM {users} SELECT \* FROM {users}
-- line 64 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 ReflectionMethod->invoke\(\)
-- line 73 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->one\(\)
EOD; EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out); $this->assertMatchesRegularExpression('@' . $this->unix_to_os_dirsep($expected) . '@', $out);
$CFG->debugsqltrace = 5; $CFG->debugsqltrace = 5;
$out = $fixture->four($sql); $out = $fixture->four($sql);
$expected = <<<EOD $expected = <<<EOD
SELECT * FROM {users} SELECT \* FROM {users}
-- line 64 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 ReflectionMethod->invoke\(\)
-- line 73 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->one\(\)
-- line 82 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->two\(\)
-- line 91 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/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() -- line \d+ of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four\(\)
EOD; EOD;
$this->assertEquals($this->unix_to_os_dirsep($expected), $out); $this->assertMatchesRegularExpression('@' . $this->unix_to_os_dirsep($expected) . '@', $out);
$CFG->debugsqltrace = 0; $CFG->debugsqltrace = 0;
} }
@ -4666,7 +4667,7 @@ EOD;
'name' => 'Bob', 'name' => 'Bob',
'falias' => 'Dan, Grace', '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 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class test_dml_sql_debugging_fixture { class test_dml_sql_debugging_fixture {
/** @var db handle */
private $db;
/** /**
* constructor * Constructor
* @param testcase $testcase test object * @param \moodle_database $db The database handle to use for this fixture
*/ */
public function __construct($testcase) { public function __construct(
$this->db = $testcase->getMockBuilder(\moodle_database::class) /** @var \moodle_database The database handle to use for this fixture */
->getMockForAbstractClass(); private \moodle_database $db,
) {
} }
/** /**

View file

@ -29,6 +29,7 @@ use stdClass, ReflectionClass;
use moodle_database, pgsql_native_moodle_database; use moodle_database, pgsql_native_moodle_database;
use xmldb_table; use xmldb_table;
use moodle_exception; use moodle_exception;
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
/** /**
* Test specific features of the Postgres dml. * Test specific features of the Postgres dml.
@ -396,6 +397,7 @@ final class pgsql_native_moodle_database_test extends \advanced_testcase {
/** /**
* Test SSL connection. * Test SSL connection.
*/ */
#[WithoutErrorHandler]
public function test_ssl_connection(): void { public function test_ssl_connection(): void {
$pgconnerr = 'pg_connect(): Unable to connect to PostgreSQL server:'; $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); unlink($textfile);
// Behavior is different between old PHP versions and new ones. Let's detect it. // Behavior is different between old PHP versions and new ones. Let's detect it.
$result = false; $result = false;
try {
// Old PHP versions were not printing any warning. set_error_handler(function ($errno, $errstr) use (&$result) {
$result = $zip_archive->close(); $result = $errstr;
} catch (\Exception $e) { $this->assertStringContainsString('ZipArchive::close', $errstr);
// New PHP versions print PHP Warning. }, E_WARNING);
$this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e); $this->assertFalse($zip_archive->close());
$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);
}
$this->assertFileDoesNotExist($archive); $this->assertFileDoesNotExist($archive);
restore_error_handler();
} }
/** /**

View file

@ -20,6 +20,8 @@ use core\http_client;
use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack; use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware; use GuzzleHttp\Middleware;
use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
/** /**
* Advanced PHPUnit test case customised for Moodle. * 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. * Note: use setUp() or setUpBeforeClass() in your test cases.
* *
* @param string $name * @param string $name
* @param array $data
* @param string $dataName
*/ */
final public function __construct($name = null, array $data = [], $dataname = '') { final public function __construct(string $name = null) {
parent::__construct($name, $data, $dataname); parent::__construct($name);
$this->setBackupGlobals(false); $this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setPreserveGlobalState(false); $this->setPreserveGlobalState(false);
} }
/** #[Before]
* Runs the bare test sequence. final public function setup_test_environment(): void {
*/
final public function runBare(): void {
global $CFG, $DB; global $CFG, $DB;
if (phpunit_util::$lastdbwrites != $DB->perf_get_writes()) { 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(); $this->testdbtransaction = $DB->start_delegated_transaction();
} }
try { $this->setCurrentTimeStart();
$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 {
// 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. #[After]
\core_component::reset(); 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');
if (isset($e)) { // We need to reset the autoloader.
// Cleanup after failed expectation. \core_component::reset();
self::resetAllData();
throw $e;
}
// Deal with any debugging messages. // Deal with any debugging messages.
$debugerror = phpunit_util::display_debugging_messages(true); $debugerror = phpunit_util::display_debugging_messages(true);

View file

@ -1,5 +1,4 @@
<?php <?php
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // 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 * @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 * Base class for PHPUnit test cases customised for Moodle
@ -605,7 +605,42 @@ abstract class base_testcase extends PHPUnit\Framework\TestCase {
* @return int * @return int
*/ */
protected static function getInvocationCount(InvocationOrder $counter): int { protected static function getInvocationCount(InvocationOrder $counter): int {
if (method_exists($counter, 'numberOfInvocations')) {
return $counter->numberOfInvocations();
}
return $counter->getInvocationCount(); return $counter->getInvocationCount();
} }
// phpcs:enable // 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 <?php
use PHPUnit\Framework\Attributes\After;
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // 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 // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // 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 * 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 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
abstract class basic_testcase extends base_testcase { abstract class basic_testcase extends base_testcase {
/** /**
* Constructs a test case with the given name. * Constructs a test case with the given name.
* *
* Note: use setUp() or setUpBeforeClass() in your test cases.
* *
* @param string $name * @param string $name
* @param array $data
* @param string $dataName
*/ */
final public function __construct($name = null, array $data = array(), $dataName = '') { final public function __construct($name = null) {
parent::__construct($name, $data, $dataName); parent::__construct($name);
$this->setBackupGlobals(false); $this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false); $this->setRunTestInSeparateProcess(false);
} }
/** #[After]
* Runs the bare test sequence and log any changes in global state or database. final public function test_teardown(): void {
* @return void
*/
final public function runBare(): void {
global $DB; 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()) { if ($DB->is_transaction_started()) {
phpunit_util::reset_all_data(); 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); phpunit_util::reset_all_data(true);

View file

@ -1,4 +1,6 @@
<?php <?php
use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // 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. * Constructs a test case with the given name.
* *
* @param string $name * @param string $name
* @param array $data
* @param string $dataName
*/ */
final public function __construct($name = null, array $data = array(), $dataName = '') { final public function __construct($name = null) {
parent::__construct($name, $data, $dataName); parent::__construct($name);
$this->setBackupGlobals(false); $this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false); $this->setRunTestInSeparateProcess(false);
} }
@ -101,9 +100,9 @@ abstract class database_driver_testcase extends base_testcase {
self::$extradb = $d; self::$extradb = $d;
} }
protected function setUp(): void { #[Before]
protected function setup_extradb(): void {
global $DB; global $DB;
parent::setUp();
if (self::$extradb) { if (self::$extradb) {
$this->tdb = 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 // delete all test tables
$dbman = $this->tdb->get_manager(); $dbman = $this->tdb->get_manager();
$tables = $this->tdb->get_tables(false); $tables = $this->tdb->get_tables(false);
@ -122,7 +122,6 @@ abstract class database_driver_testcase extends base_testcase {
$dbman->drop_table($table); $dbman->drop_table($table);
} }
} }
parent::tearDown();
} }
public static function tearDownAfterClass(): void { public static function tearDownAfterClass(): void {
@ -134,34 +133,13 @@ abstract class database_driver_testcase extends base_testcase {
parent::tearDownAfterClass(); parent::tearDownAfterClass();
} }
/** #[After]
* Runs the bare test sequence. public function check_debugging(): void {
* @return void // Deal with any debugging messages.
*/ $debugerror = phpunit_util::display_debugging_messages(true);
public function runBare(): void { $this->resetDebugging();
try { if (!empty($debugerror)) {
parent::runBare(); trigger_error('Unexpected debugging() call detected.' . "\n" . $debugerror, E_USER_NOTICE);
// 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) { if ($warnings) {
$warnings = implode("\n", $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:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation> <xs:annotation>
<xs:documentation source="https://phpunit.de/documentation.html"> <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:documentation>
<xs:appinfo source="https://phpunit.de/documentation.html"/> <xs:appinfo source="https://phpunit.de/documentation.html"/>
</xs:annotation> </xs:annotation>
@ -32,7 +32,6 @@
<xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/>
<xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/>
<xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <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="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/>
<xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/>
</xs:complexType> </xs:complexType>
@ -57,62 +56,19 @@
</xs:complexType> </xs:complexType>
<xs:complexType name="extensionsType"> <xs:complexType name="extensionsType">
<xs:sequence> <xs:sequence>
<xs:element name="extension" type="objectType" maxOccurs="unbounded"/> <xs:element name="bootstrap" type="bootstrapType" maxOccurs="unbounded"/>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:complexType name="listenersType"> <xs:complexType name="bootstrapType">
<xs:sequence> <xs:sequence>
<xs:element name="listener" type="objectType" maxOccurs="unbounded"/> <xs:element name="parameter" type="parameterType" minOccurs="0" 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:sequence> </xs:sequence>
<xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="class" type="xs:string" use="required"/>
<xs:attribute name="file" type="xs:anyURI"/>
</xs:complexType> </xs:complexType>
<xs:complexType name="arrayType"> <xs:complexType name="parameterType">
<xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/>
<xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> <xs:attribute name="value" type="xs:string" use="required"/>
</xs:sequence>
</xs:complexType> </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:simpleType name="columnsType">
<xs:union> <xs:union>
<xs:simpleType> <xs:simpleType>
@ -135,7 +91,7 @@
</xs:group> </xs:group>
<xs:complexType name="directoryFilterType"> <xs:complexType name="directoryFilterType">
<xs:simpleContent> <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="prefix" default=""/>
<xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/>
<xs:attributeGroup ref="phpVersionGroup"/> <xs:attributeGroup ref="phpVersionGroup"/>
@ -207,19 +163,14 @@
</xs:complexType> </xs:complexType>
<xs:attributeGroup name="configAttributeGroup"> <xs:attributeGroup name="configAttributeGroup">
<xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <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="bootstrap" type="xs:anyURI"/>
<xs:attribute name="cacheDirectory" type="xs:anyURI"/>
<xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/>
<xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/>
<xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="colors" type="xs:boolean" default="false"/>
<xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="columns" type="columnsType" default="80"/>
<xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/>
<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="processIsolation" 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="stopOnDefect" type="xs:boolean" default="false"/>
<xs:attribute name="stopOnError" 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="failOnWarning" type="xs:boolean" default="false"/>
<xs:attribute name="beStrictAboutChangesToGlobalState" 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="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="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/>
<xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <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="defaultTimeLimit" type="xs:integer" default="0"/>
<xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/>
<xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
<xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
<xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <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="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="testdox" type="xs:boolean" default="false"/>
<xs:attribute name="stderr" 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="reverseDefectList" type="xs:boolean" default="false"/>
<xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" 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="executionOrder" type="executionOrderType" default="default"/>
<xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <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:attributeGroup>
<xs:group name="configGroup"> <xs:group name="configGroup">
<xs:all> <xs:all>
<xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element ref="testSuiteFacet" minOccurs="0"/>
<xs:element name="groups" type="groupsType" 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="coverage" type="coverageType" minOccurs="0"/>
<xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/>
<xs:element name="extensions" type="extensionsType" 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:element name="php" type="phpType" minOccurs="0"/>
</xs:all> </xs:all>
</xs:group> </xs:group>
@ -279,8 +229,10 @@
</xs:complexType> </xs:complexType>
<xs:complexType name="testSuiteType"> <xs:complexType name="testSuiteType">
<xs:sequence> <xs:sequence>
<xs:group ref="pathGroup"/> <xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:group ref="pathGroup"/>
<xs:element name="exclude" type="xs:string"/>
</xs:choice>
</xs:sequence> </xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType> </xs:complexType>
@ -301,8 +253,6 @@
<xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" />
<xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" />
<xs:element name="testdoxText" 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:all>
</xs:group> </xs:group>
<xs:complexType name="logToFileType"> <xs:complexType name="logToFileType">
@ -319,6 +269,12 @@
<xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/>
<xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/>
<xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <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>
<xs:complexType name="coverageReportTextType"> <xs:complexType name="coverageReportTextType">
<xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/>

View file

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

View file

@ -16,6 +16,7 @@
namespace core; namespace core;
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
use phpunit_util; use phpunit_util;
/** /**
@ -235,16 +236,7 @@ STRING;
global $DB; global $DB;
$DB->set_field('user', 'confirmed', 1, ['id' => -1]); $DB->set_field('user', 'confirmed', 1, ['id' => -1]);
// Let's convert the user warnings into an assert-able exception. $this->expectException(\core_phpunit\exception\test_exception::class);
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 database modification'); $this->expectExceptionMessage('Warning: unexpected database modification');
phpunit_util::reset_all_data(true); phpunit_util::reset_all_data(true);
} }
@ -261,15 +253,6 @@ STRING;
unset($CFG->admin); unset($CFG->admin);
$CFG->rolesactive = 0; $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->expectException(\Exception::class);
$this->expectExceptionMessageMatches('/rolesactive.*xx value.*removal.*admin/ms'); // 3 messages matched. $this->expectExceptionMessageMatches('/rolesactive.*xx value.*removal.*admin/ms'); // 3 messages matched.
phpunit_util::reset_all_data(true); phpunit_util::reset_all_data(true);
@ -285,15 +268,6 @@ STRING;
global $USER; global $USER;
$USER->id = 10; $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->expectException(\Exception::class);
$this->expectExceptionMessage('Warning: unexpected change of $USER'); $this->expectExceptionMessage('Warning: unexpected change of $USER');
phpunit_util::reset_all_data(true); phpunit_util::reset_all_data(true);
@ -309,15 +283,6 @@ STRING;
global $COURSE; global $COURSE;
$COURSE->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->expectException(\Exception::class);
$this->expectExceptionMessage('Warning: unexpected change of $COURSE'); $this->expectExceptionMessage('Warning: unexpected change of $COURSE');
phpunit_util::reset_all_data(true); phpunit_util::reset_all_data(true);
@ -338,15 +303,6 @@ STRING;
$USER->id = 10; $USER->id = 10;
$COURSE->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->expectException(\Exception::class);
$this->expectExceptionMessageMatches('/resetting.*rolesactive.*new.*removal.*USER.*COURSE/ms'); // 6 messages matched. $this->expectExceptionMessageMatches('/resetting.*rolesactive.*new.*removal.*USER.*COURSE/ms'); // 6 messages matched.
phpunit_util::reset_all_data(true); 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 $canonicalize
* @param boolean $ignoreCase * @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 { bool $canonicalize = false, bool $ignoreCase = false): void {
// Nasty cheating hack: prevent random failures on timemodified field. // Nasty cheating hack: prevent random failures on timemodified field.
if (is_array($actual) && (is_object($expected) || is_array($expected))) { if (is_array($actual) && (is_object($expected) || is_array($expected))) {
@ -104,33 +104,33 @@ final class completionlib_test extends advanced_testcase {
// Config alone. // Config alone.
$CFG->enablecompletion = COMPLETION_DISABLED; $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; $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.
$course = (object)array('id' => 13); $course = (object)array('id' => 13);
$c = new completion_info($course); $c = new completion_info($course);
$course->enablecompletion = COMPLETION_DISABLED; $course->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled()); $this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled());
$course->enablecompletion = COMPLETION_ENABLED; $course->enablecompletion = COMPLETION_ENABLED;
$this->assertEquals(COMPLETION_ENABLED, $c->is_enabled()); $this->assertCompletionEquals(COMPLETION_ENABLED, $c->is_enabled());
$CFG->enablecompletion = COMPLETION_DISABLED; $CFG->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled()); $this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled());
// Course and CM. // Course and CM.
$cm = new stdClass(); $cm = new stdClass();
$cm->completion = COMPLETION_TRACKING_MANUAL; $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; $CFG->enablecompletion = COMPLETION_ENABLED;
$course->enablecompletion = COMPLETION_DISABLED; $course->enablecompletion = COMPLETION_DISABLED;
$this->assertEquals(COMPLETION_DISABLED, $c->is_enabled($cm)); $this->assertCompletionEquals(COMPLETION_DISABLED, $c->is_enabled($cm));
$course->enablecompletion = COMPLETION_ENABLED; $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; $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; $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 { ): void {
switch (self::getInvocationCount($setinvocations)) { switch (self::getInvocationCount($setinvocations)) {
case 1: case 1:
$this->assertEquals($cm, $comparecm); $this->assertCompletionEquals($cm, $comparecm);
$comparewith1->evaluate($comparewith); $comparewith1->evaluate($comparewith);
break; break;
case 2: case 2:
$this->assertEquals($cm, $comparecm); $this->assertCompletionEquals($cm, $comparecm);
$comparewith2->evaluate($comparewith); $comparewith2->evaluate($comparewith);
break; break;
default: default:
@ -407,7 +407,7 @@ final class completionlib_test extends advanced_testcase {
$current = (object)['viewed' => COMPLETION_NOT_VIEWED]; $current = (object)['viewed' => COMPLETION_NOT_VIEWED];
$completioninfo = new completion_info($this->course); $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. // The target user already received a grade, so internal_get_state should be already complete.
$completioninfo = new completion_info($this->course); $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. // The target user already received a grade, so internal_get_state should be already complete.
$completioninfo = new completion_info($this->course); $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. // 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. // Fetch completion for the user who hasn't made a choice yet.
$completion = $completioninfo->internal_get_state($cminfo, $this->user->id, COMPLETION_INCOMPLETE); $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. // Have the user make a choice.
$choicewithoptions = choice_get_choice($choice->id); $choicewithoptions = choice_get_choice($choice->id);
$optionids = array_keys($choicewithoptions->option); $optionids = array_keys($choicewithoptions->option);
choice_user_submit_response($optionids[0], $choice, $this->user->id, $this->course, $cminfo); choice_user_submit_response($optionids[0], $choice, $this->user->id, $this->course, $cminfo);
$completion = $completioninfo->internal_get_state($cminfo, $this->user->id, COMPLETION_INCOMPLETE); $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)); ->will($this->returnValue(666));
$c = new completion_info($course); $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) $c->expects($updateinvocations)
->method('update_state') ->method('update_state')
->willReturnCallback(function ($comparecm, $state, $userid) use ($updateinvocations, $cm): void { ->willReturnCallback(function ($comparecm, $state, $userid) use ($updateinvocations, $cm): void {
$this->assertEquals($cm, $comparecm); $this->assertCompletionEquals($cm, $comparecm);
$this->assertEquals(COMPLETION_UNKNOWN, $state); $this->assertCompletionEquals(COMPLETION_UNKNOWN, $state);
switch (self::getInvocationCount($updateinvocations)) { switch (self::getInvocationCount($updateinvocations)) {
case 1: case 1:
$this->assertEquals(100, $userid); $this->assertCompletionEquals(100, $userid);
break; break;
case 2: case 2:
$this->assertEquals(101, $userid); $this->assertCompletionEquals(101, $userid);
break; break;
case 3: case 3:
$this->assertEquals(201, $userid); $this->assertCompletionEquals(201, $userid);
break; break;
default: default:
$this->fail('Unexpected invocation count'); $this->fail('Unexpected invocation count');
@ -820,15 +820,15 @@ final class completionlib_test extends advanced_testcase {
$result = $completioninfo->get_data($cm, $wholecourse, $user->id); $result = $completioninfo->get_data($cm, $wholecourse, $user->id);
// Course module ID of the returned completion data must match this activity's course module 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. // 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. // 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 the user has no completion record, then the default record should be returned.
if (!$hasrecord) { if (!$hasrecord) {
$this->assertEquals(0, $result->id); $this->assertCompletionEquals(0, $result->id);
} }
// Check that we are including relevant completion data for the module. // 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->assertTrue(property_exists($result, 'timemodified'));
$this->assertFalse(property_exists($result, 'other_cm_completion_data_fetched')); $this->assertFalse(property_exists($result, 'other_cm_completion_data_fetched'));
$this->assertEquals($testcm->id, $result->coursemoduleid); $this->assertCompletionEquals($testcm->id, $result->coursemoduleid);
$this->assertEquals($this->user->id, $result->userid); $this->assertCompletionEquals($this->user->id, $result->userid);
$results[$testcm->id] = $result; $results[$testcm->id] = $result;
} }
@ -902,7 +902,7 @@ final class completionlib_test extends advanced_testcase {
(cache::make('core', 'completion'))->purge(); (cache::make('core', 'completion'))->purge();
foreach ($modinfo->cms as $testcm) { foreach ($modinfo->cms as $testcm) {
$result = $completioninfo->get_data($testcm, false); $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); $completiondatabeforeview = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertTrue(array_key_exists('viewed', $completiondatabeforeview)); $this->assertTrue(array_key_exists('viewed', $completiondatabeforeview));
$this->assertTrue(array_key_exists('coursemoduleid', $completiondatabeforeview)); $this->assertTrue(array_key_exists('coursemoduleid', $completiondatabeforeview));
$this->assertEquals(0, $completiondatabeforeview['viewed']); $this->assertCompletionEquals(0, $completiondatabeforeview['viewed']);
$this->assertEquals($cm->id, $completiondatabeforeview['coursemoduleid']); $this->assertCompletionEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
// Mark as completed before viewing it. // Mark as completed before viewing it.
$completioninfo->update_state($cm, COMPLETION_COMPLETE, $this->user->id, true); $completioninfo->update_state($cm, COMPLETION_COMPLETE, $this->user->id, true);
$completiondatabeforeview = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata); $completiondatabeforeview = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertEquals(0, $completiondatabeforeview['viewed']); $this->assertCompletionEquals(0, $completiondatabeforeview['viewed']);
// Set viewed. // Set viewed.
$completioninfo->set_module_viewed($cm, $this->user->id); $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); $completiondata = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertTrue(array_key_exists('viewed', $completiondata)); $this->assertTrue(array_key_exists('viewed', $completiondata));
$this->assertTrue(array_key_exists('coursemoduleid', $completiondata)); $this->assertTrue(array_key_exists('coursemoduleid', $completiondata));
$this->assertEquals(1, $completiondata['viewed']); $this->assertCompletionEquals(1, $completiondata['viewed']);
$this->assertEquals($cm->id, $completiondatabeforeview['coursemoduleid']); $this->assertCompletionEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
$completioninfo->reset_all_state($cm); $completioninfo->reset_all_state($cm);
$completiondataafterreset = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata); $completiondataafterreset = $completioninfo->get_completion_data($cm->id, $this->user->id, $defaultdata);
$this->assertTrue(array_key_exists('viewed', $completiondataafterreset)); $this->assertTrue(array_key_exists('viewed', $completiondataafterreset));
$this->assertTrue(array_key_exists('coursemoduleid', $completiondataafterreset)); $this->assertTrue(array_key_exists('coursemoduleid', $completiondataafterreset));
$this->assertEquals(1, $completiondataafterreset['viewed']); $this->assertCompletionEquals(1, $completiondataafterreset['viewed']);
$this->assertEquals($cm->id, $completiondatabeforeview['coursemoduleid']); $this->assertCompletionEquals($cm->id, $completiondatabeforeview['coursemoduleid']);
} }
/** /**
@ -1014,7 +1014,7 @@ final class completionlib_test extends advanced_testcase {
$this->assertArrayHasKey('customcompletion', $choicecompletiondata); $this->assertArrayHasKey('customcompletion', $choicecompletiondata);
$this->assertArrayHasKey('completionsubmit', $choicecompletiondata['customcompletion']); $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. // Mock a choice answer so user has completed the requirement.
$choicemockinfo = [ $choicemockinfo = [
@ -1025,7 +1025,7 @@ final class completionlib_test extends advanced_testcase {
// Confirm fetching again reflects the completion. // Confirm fetching again reflects the completion.
$choicecompletiondata = $method->invoke($completioninfo, $cmchoice, $user->id); $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. // Check that fetching data for a module with no custom completion still provides its grade completion status.
$workshopcompletiondata = $method->invoke($completioninfo, $cmworkshop, $user->id); $workshopcompletiondata = $method->invoke($completioninfo, $cmworkshop, $user->id);
@ -1033,8 +1033,8 @@ final class completionlib_test extends advanced_testcase {
$this->assertArrayHasKey('completiongrade', $workshopcompletiondata); $this->assertArrayHasKey('completiongrade', $workshopcompletiondata);
$this->assertArrayHasKey('passgrade', $workshopcompletiondata); $this->assertArrayHasKey('passgrade', $workshopcompletiondata);
$this->assertArrayNotHasKey('customcompletion', $workshopcompletiondata); $this->assertArrayNotHasKey('customcompletion', $workshopcompletiondata);
$this->assertEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['completiongrade']); $this->assertCompletionEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['completiongrade']);
$this->assertEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['passgrade']); $this->assertCompletionEquals(COMPLETION_INCOMPLETE, $workshopcompletiondata['passgrade']);
// Check that fetching data for a module with no completion conditions does not provide any data. // Check that fetching data for a module with no completion conditions does not provide any data.
$choice2completiondata = $method->invoke($completioninfo, $cmchoice2, $user->id); $choice2completiondata = $method->invoke($completioninfo, $cmchoice2, $user->id);
@ -1066,11 +1066,11 @@ final class completionlib_test extends advanced_testcase {
$c->internal_set_data($cm, $data); $c->internal_set_data($cm, $data);
$d1 = $DB->get_field('course_modules_completion', 'id', array('coursemoduleid' => $cm->id)); $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 = cache::make('core', 'completion');
// Cache was not set for another user. // Cache was not set for another user.
$cachevalue = $cache->get("{$data->userid}_{$cm->course}"); $cachevalue = $cache->get("{$data->userid}_{$cm->course}");
$this->assertEquals([ $this->assertCompletionEquals([
'cacherev' => $this->course->cacherev, 'cacherev' => $this->course->cacherev,
$cm->id => array_merge( $cm->id => array_merge(
(array) $data, (array) $data,
@ -1095,13 +1095,13 @@ final class completionlib_test extends advanced_testcase {
$c->internal_set_data($cm2, $d2); $c->internal_set_data($cm2, $d2);
// Cache for current user returns the data. // Cache for current user returns the data.
$cachevalue = $cache->get($data->userid . '_' . $cm->course); $cachevalue = $cache->get($data->userid . '_' . $cm->course);
$this->assertEquals(array_merge( $this->assertCompletionEquals(array_merge(
(array) $data, (array) $data,
['other_cm_completion_data_fetched' => true] ['other_cm_completion_data_fetched' => true]
), $cachevalue[$cm->id]); ), $cachevalue[$cm->id]);
// Cache for another user is not filled. // 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. // 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); $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; $data->coursemoduleid = $cm->id;
$c->internal_set_data($cm, $data); $c->internal_set_data($cm, $data);
$actual = $DB->get_records('course_completions'); $actual = $DB->get_records('course_completions');
$this->assertEquals(1, count($actual)); $this->assertCompletionEquals(1, count($actual));
$this->assertEquals($this->user->id, reset($actual)->userid); $this->assertCompletionEquals($this->user->id, reset($actual)->userid);
$data->userid = $newuser2->id; $data->userid = $newuser2->id;
$c->internal_set_data($cm, $data, true); $c->internal_set_data($cm, $data, true);
$actual = $DB->get_records('course_completions'); $actual = $DB->get_records('course_completions');
$this->assertEquals(1, count($actual)); $this->assertCompletionEquals(1, count($actual));
$this->assertEquals($this->user->id, reset($actual)->userid); $this->assertCompletionEquals($this->user->id, reset($actual)->userid);
} }
/** /**
@ -1180,7 +1180,7 @@ final class completionlib_test extends advanced_testcase {
->method('get_recordset_sql') ->method('get_recordset_sql')
->will($this->returnValue(new core_completionlib_fake_recordset(array($progress1, $progress2)))); ->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', 100 => (object)array('id' => 100, 'firstname' => 'Woot', 'lastname' => 'Plugh',
'progress' => array(13 => $progress1)), 'progress' => array(13 => $progress1)),
201 => (object)array('id' => 201, 'firstname' => 'Vroom', 'lastname' => 'Xyzzy', 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) { ->willReturnCallback(function ($paramids) use ($inorequalsinvocations, $ids) {
switch (self::getInvocationCount($inorequalsinvocations)) { switch (self::getInvocationCount($inorequalsinvocations)) {
case 1: case 1:
$this->assertEquals(array_slice($ids, 0, 1000), $paramids); $this->assertCompletionEquals(array_slice($ids, 0, 1000), $paramids);
return [' IN whatever', []]; return [' IN whatever', []];
case 2: case 2:
$this->assertEquals(array_slice($ids, 1000), $paramids); $this->assertCompletionEquals(array_slice($ids, 1000), $paramids);
return [' IN whatever2', []]; return [' IN whatever2', []];
default: default:
$this->fail('Unexpected invocation count'); $this->fail('Unexpected invocation count');
@ -1343,32 +1343,32 @@ final class completionlib_test extends advanced_testcase {
$grade->finalgrade = null; $grade->finalgrade = null;
// Grade has pass mark and is not hidden, user passes. // Grade has pass mark and is not hidden, user passes.
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE_PASS, COMPLETION_COMPLETE_PASS,
completion_info::internal_get_grade_state($item, $grade)); completion_info::internal_get_grade_state($item, $grade));
// Same but user fails. // Same but user fails.
$grade->rawgrade = 3.9; $grade->rawgrade = 3.9;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE_FAIL, COMPLETION_COMPLETE_FAIL,
completion_info::internal_get_grade_state($item, $grade)); completion_info::internal_get_grade_state($item, $grade));
// User fails on raw grade but passes on final. // User fails on raw grade but passes on final.
$grade->finalgrade = 4.0; $grade->finalgrade = 4.0;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE_PASS, COMPLETION_COMPLETE_PASS,
completion_info::internal_get_grade_state($item, $grade)); completion_info::internal_get_grade_state($item, $grade));
// Item is hidden. // Item is hidden.
$item->hidden = 1; $item->hidden = 1;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE, COMPLETION_COMPLETE,
completion_info::internal_get_grade_state($item, $grade)); completion_info::internal_get_grade_state($item, $grade));
// Item isn't hidden but has no pass mark. // Item isn't hidden but has no pass mark.
$item->hidden = 0; $item->hidden = 0;
$item->gradepass = 0; $item->gradepass = 0;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE, COMPLETION_COMPLETE,
completion_info::internal_get_grade_state($item, $grade)); completion_info::internal_get_grade_state($item, $grade));
@ -1376,7 +1376,7 @@ final class completionlib_test extends advanced_testcase {
$item->hidden = 1; $item->hidden = 1;
$item->gradepass = 4; $item->gradepass = 4;
$grade->finalgrade = 5.0; $grade->finalgrade = 5.0;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE_PASS, COMPLETION_COMPLETE_PASS,
completion_info::internal_get_grade_state($item, $grade, true)); completion_info::internal_get_grade_state($item, $grade, true));
@ -1384,7 +1384,7 @@ final class completionlib_test extends advanced_testcase {
$item->hidden = 1; $item->hidden = 1;
$item->gradepass = 4; $item->gradepass = 4;
$grade->finalgrade = 3.0; $grade->finalgrade = 3.0;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE_FAIL_HIDDEN, COMPLETION_COMPLETE_FAIL_HIDDEN,
completion_info::internal_get_grade_state($item, $grade, true)); completion_info::internal_get_grade_state($item, $grade, true));
@ -1392,7 +1392,7 @@ final class completionlib_test extends advanced_testcase {
$item->hidden = 0; $item->hidden = 0;
$item->gradepass = 4; $item->gradepass = 4;
$grade->finalgrade = 3.0; $grade->finalgrade = 3.0;
$this->assertEquals( $this->assertCompletionEquals(
COMPLETION_COMPLETE_FAIL, COMPLETION_COMPLETE_FAIL,
completion_info::internal_get_grade_state($item, $grade, true)); 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); $c = new completion_info($this->course);
$activities = $c->get_activities(); $activities = $c->get_activities();
$this->assertEquals(1, count($activities)); $this->assertCompletionEquals(1, count($activities));
$this->assertTrue(isset($activities[$forum->cmid])); $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 = $c->get_data($activities[$forum->cmid], false, $this->user->id);
$current->completionstate = COMPLETION_COMPLETE; $current->completionstate = COMPLETION_COMPLETE;
@ -1534,12 +1534,12 @@ final class completionlib_test extends advanced_testcase {
$events = $sink->get_events(); $events = $sink->get_events();
$event = reset($events); $event = reset($events);
$this->assertInstanceOf('\core\event\course_module_completion_updated', $event); $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); $event->get_record_snapshot('course_modules_completion', $event->objectid)->coursemoduleid);
$this->assertEquals($current, $event->get_record_snapshot('course_modules_completion', $event->objectid)); $this->assertCompletionEquals($current, $event->get_record_snapshot('course_modules_completion', $event->objectid));
$this->assertEquals(context_module::instance($forum->cmid), $event->get_context()); $this->assertCompletionEquals(context_module::instance($forum->cmid), $event->get_context());
$this->assertEquals($USER->id, $event->userid); $this->assertCompletionEquals($USER->id, $event->userid);
$this->assertEquals($this->user->id, $event->relateduserid); $this->assertCompletionEquals($this->user->id, $event->relateduserid);
$this->assertInstanceOf('moodle_url', $event->get_url()); $this->assertInstanceOf('moodle_url', $event->get_url());
} }
@ -1564,11 +1564,11 @@ final class completionlib_test extends advanced_testcase {
$event = reset($events); $event = reset($events);
$this->assertInstanceOf('\core\event\course_completed', $event); $this->assertInstanceOf('\core\event\course_completed', $event);
$this->assertEquals($this->course->id, $event->get_record_snapshot('course_completions', $event->objectid)->course); $this->assertCompletionEquals($this->course->id, $event->get_record_snapshot('course_completions', $event->objectid)->course);
$this->assertEquals($this->course->id, $event->courseid); $this->assertCompletionEquals($this->course->id, $event->courseid);
$this->assertEquals($USER->id, $event->userid); $this->assertCompletionEquals($USER->id, $event->userid);
$this->assertEquals($this->user->id, $event->relateduserid); $this->assertCompletionEquals($this->user->id, $event->relateduserid);
$this->assertEquals(context_course::instance($this->course->id), $event->get_context()); $this->assertCompletionEquals(context_course::instance($this->course->id), $event->get_context());
$this->assertInstanceOf('moodle_url', $event->get_url()); $this->assertInstanceOf('moodle_url', $event->get_url());
} }
@ -1593,10 +1593,10 @@ final class completionlib_test extends advanced_testcase {
$this->assertCount(1, $messages); $this->assertCount(1, $messages);
$message = array_pop($messages); $message = array_pop($messages);
$this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertCompletionEquals(core_user::get_noreply_user()->id, $message->useridfrom);
$this->assertEquals($this->user->id, $message->useridto); $this->assertCompletionEquals($this->user->id, $message->useridto);
$this->assertEquals('coursecompleted', $message->eventtype); $this->assertCompletionEquals('coursecompleted', $message->eventtype);
$this->assertEquals(get_string('coursecompleted', 'completion'), $message->subject); $this->assertCompletionEquals(get_string('coursecompleted', 'completion'), $message->subject);
$this->assertStringContainsString($this->course->fullname, $message->fullmessage); $this->assertStringContainsString($this->course->fullname, $message->fullmessage);
} }
@ -1623,8 +1623,8 @@ final class completionlib_test extends advanced_testcase {
$sink->close(); $sink->close();
$this->assertInstanceOf('\core\event\course_completion_updated', $event); $this->assertInstanceOf('\core\event\course_completion_updated', $event);
$this->assertEquals($this->course->id, $event->courseid); $this->assertCompletionEquals($this->course->id, $event->courseid);
$this->assertEquals($coursecontext, $event->get_context()); $this->assertCompletionEquals($coursecontext, $event->get_context());
$this->assertInstanceOf('moodle_url', $event->get_url()); $this->assertInstanceOf('moodle_url', $event->get_url());
} }
@ -1694,7 +1694,7 @@ final class completionlib_test extends advanced_testcase {
$this->expectException($expectedexception); $this->expectException($expectedexception);
} }
$gradecompletion = $completioninfo->get_grade_completion($cm, $this->user->id); $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. // Without the grade_item, the activity is considered incomplete.
$completioninfo = new completion_info($this->course); $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. // Once the activity is graded, the grade_item is automatically created.
$assigninstance = new assign($cm->context, $cm, $this->course); $assigninstance = new assign($cm->context, $cm, $this->course);
@ -1734,7 +1734,7 @@ final class completionlib_test extends advanced_testcase {
$assigninstance->update_grade($grade); $assigninstance->update_grade($grade);
// The implicitly created grade_item does not have grade to pass defined so it is not distinguished. // 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'); $method = new ReflectionMethod($ccompletion, '_save');
$completionid = $method->invoke($ccompletion); $completionid = $method->invoke($ccompletion);
$completions = $DB->get_records('course_completions'); $completions = $DB->get_records('course_completions');
$this->assertEquals(count($completions), 1); $this->assertCompletionEquals(count($completions), 1);
$this->assertEquals(reset($completions)->id, $completionid); $this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0; $ccompletion->id = 0;
$method = new ReflectionMethod($ccompletion, '_save'); $method = new ReflectionMethod($ccompletion, '_save');
@ -1910,15 +1910,15 @@ final class completionlib_test extends advanced_testcase {
$completionid = $ccompletion->mark_enrolled(); $completionid = $ccompletion->mark_enrolled();
$completions = $DB->get_records('course_completions'); $completions = $DB->get_records('course_completions');
$this->assertEquals(count($completions), 1); $this->assertCompletionEquals(count($completions), 1);
$this->assertEquals(reset($completions)->id, $completionid); $this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0; $ccompletion->id = 0;
$completionid = $ccompletion->mark_enrolled(); $completionid = $ccompletion->mark_enrolled();
$this->assertDebuggingCalled('Can not update data object, no id!'); $this->assertDebuggingCalled('Can not update data object, no id!');
$this->assertNull($completionid); $this->assertNull($completionid);
$completions = $DB->get_records('course_completions'); $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(); $completionid = $ccompletion->mark_inprogress();
$completions = $DB->get_records('course_completions'); $completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions)); $this->assertCompletionEquals(1, count($completions));
$this->assertEquals(reset($completions)->id, $completionid); $this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0; $ccompletion->id = 0;
$completionid = $ccompletion->mark_inprogress(); $completionid = $ccompletion->mark_inprogress();
$this->assertDebuggingCalled('Can not update data object, no id!'); $this->assertDebuggingCalled('Can not update data object, no id!');
$this->assertNull($completionid); $this->assertNull($completionid);
$completions = $DB->get_records('course_completions'); $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(); $completionid = $ccompletion->mark_complete();
$completions = $DB->get_records('course_completions'); $completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions)); $this->assertCompletionEquals(1, count($completions));
$this->assertEquals(reset($completions)->id, $completionid); $this->assertCompletionEquals(reset($completions)->id, $completionid);
$ccompletion->id = 0; $ccompletion->id = 0;
$completionid = $ccompletion->mark_complete(); $completionid = $ccompletion->mark_complete();
$this->assertNull($completionid); $this->assertNull($completionid);
$completions = $DB->get_records('course_completions'); $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']); $completionid = $completion->mark_complete($record['timecompleted']);
$completions = $DB->get_records('course_completions'); $completions = $DB->get_records('course_completions');
$this->assertEquals(1, count($completions)); $this->assertCompletionEquals(1, count($completions));
$this->assertEquals(reset($completions)->id, $completionid); $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()); $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
// Admin should fix the settings. // 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'); $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()); $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(null));
$this->assertSame('Europe/Prague', core_date::get_user_timezone()); $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->setTimezone('xxx/yyy', 'Europe/London');
$this->assertCount(1, $invokable->get_invocations());
$USER->timezone = 'abc/def'; $USER->timezone = 'abc/def';
$CFG->forcetimezone = 'Europe/Berlin'; $CFG->forcetimezone = 'Europe/Berlin';
$this->assertSame('Europe/Berlin', core_date::get_user_timezone(null)); $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
$this->assertSame('Europe/Berlin', core_date::get_user_timezone()); $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->setTimezone('xxx/yyy', 'Europe/London');
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
$USER->timezone = 'abc/def'; $USER->timezone = 'abc/def';
$CFG->forcetimezone = 99; $CFG->forcetimezone = 99;
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Europe/London', core_date::get_user_timezone(null)); $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->assertSame('Europe/London', core_date::get_user_timezone());
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
// User object parameter. // User object parameter.
$admin = get_admin(); $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/London', core_date::get_user_timezone('Europe/London'));
$this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz')); $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
$USER->timezone = 'xxz/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->setTimezone('xxx', 'Europe/Prague');
$this->assertCount(1, $invokable->get_invocations());
restore_error_handler();
$CFG->forcetimezone = '99'; $CFG->forcetimezone = '99';
$USER->timezone = 'xxx'; $USER->timezone = 'xxx';
$invokable = self::get_invokable();
set_error_handler($invokable, E_ALL);
$this->assertSame('Europe/Prague', core_date::get_user_timezone('99')); $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->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->assertSame('Etc/GMT-1', core_date::get_user_timezone(1));
$this->assertCount(2, $invokable->get_invocations());
restore_error_handler();
$this->setTimezone('Europe/Prague'); $this->setTimezone('Europe/Prague');
$CFG->forcetimezone = 'Pacific/Auckland'; $CFG->forcetimezone = 'Pacific/Auckland';
@ -593,7 +636,11 @@ final class date_test extends advanced_testcase {
$USER->timezone = 'Europe/London'; $USER->timezone = 'Europe/London';
$CFG->forcetimezone = 99; $CFG->forcetimezone = 99;
$tz = new DateTimeZone('Pacific/Auckland'); $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->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, 'userid' => $user2->id,
'groupnames' => $group1->name, 'groupnames' => $group1->name,
], ],
], $records); ], array_values($records));
} }
public function test_groups_get_group_by_name(): void { 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->assertEquals([$c1group1->id], array_keys($groups));
$this->assertEqualsCanonicalizing( $this->assertEqualsCanonicalizing(
[$c1user1->id, $c12user1->id], [$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)); $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. * An example static method as part of the testcase.
* *
@ -109,18 +129,6 @@ final class moodlelib_partial_test extends \advanced_testcase {
['needle' => 'foo'], ['needle' => 'foo'],
true, 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' => [ 'Using named args on initial args only - static method' => [
[self::class, 'example_static_method'], [self::class, 'example_static_method'],
['foo' => 'foo'], ['foo' => 'foo'],

View file

@ -3283,7 +3283,7 @@ EOF;
'nodiverts' => array( 'nodiverts' => array(
'divertallemailsto' => null, 'divertallemailsto' => null,
'divertallemailsexcept' => null, 'divertallemailsexcept' => null,
array( 'addresses' => array(
'foo@example.com', 'foo@example.com',
'test@real.com', 'test@real.com',
'fred.jones@example.com', 'fred.jones@example.com',
@ -3291,12 +3291,12 @@ EOF;
'fred@example.com', 'fred@example.com',
'fred+verp@example.com', 'fred+verp@example.com',
), ),
false, 'expected' => false,
), ),
'alldiverts' => array( 'alldiverts' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => null, 'divertallemailsexcept' => null,
array( 'addresses' => array(
'foo@example.com', 'foo@example.com',
'test@real.com', 'test@real.com',
'fred.jones@example.com', 'fred.jones@example.com',
@ -3304,65 +3304,65 @@ EOF;
'fred@example.com', 'fred@example.com',
'fred+verp@example.com', 'fred+verp@example.com',
), ),
true, 'expected' => true,
), ),
'alsodiverts' => array( 'alsodiverts' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com', 'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com',
array( 'addresses' => array(
'foo@example.com', 'foo@example.com',
'test@real.com', 'test@real.com',
'fred.jones@example.com', 'fred.jones@example.com',
'Fred.Jones@Example.com', 'Fred.Jones@Example.com',
), ),
true, 'expected' => true,
), ),
'divertsexceptions' => array( 'divertsexceptions' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com', 'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com',
array( 'addresses' => array(
'dev1@dev.com', 'dev1@dev.com',
'fred@example.com', 'fred@example.com',
'Fred@Example.com', 'Fred@Example.com',
'fred+verp@example.com', 'fred+verp@example.com',
), ),
false, 'expected' => false,
), ),
'divertsexceptionsnewline' => array( 'divertsexceptionsnewline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@dev.com\nfred(\+.*)?@example.com", 'divertallemailsexcept' => "@dev.com\nfred(\+.*)?@example.com",
array( 'addresses' => array(
'dev1@dev.com', 'dev1@dev.com',
'fred@example.com', 'fred@example.com',
'fred+verp@example.com', 'fred+verp@example.com',
), ),
false, 'expected' => false,
), ),
'alsodivertsnewline' => array( 'alsodivertsnewline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@dev.com\nfred(\+.*)?@example.com", 'divertallemailsexcept' => "@dev.com\nfred(\+.*)?@example.com",
array( 'addresses' => array(
'foo@example.com', 'foo@example.com',
'test@real.com', 'test@real.com',
'fred.jones@example.com', 'fred.jones@example.com',
), ),
true, 'expected' => true,
), ),
'alsodivertsblankline' => array( 'alsodivertsblankline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@dev.com\n", 'divertallemailsexcept' => "@dev.com\n",
[ 'addresses' => [
'lionel@example.com', 'lionel@example.com',
], ],
true, 'expected' => true,
), ),
'divertsexceptionblankline' => array( 'divertsexceptionblankline' => array(
'divertallemailsto' => 'somewhere@elsewhere.com', 'divertallemailsto' => 'somewhere@elsewhere.com',
'divertallemailsexcept' => "@example.com\n", 'divertallemailsexcept' => "@example.com\n",
[ 'addresses' => [
'lionel@example.com', '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' => [ 'mod_instance_helper with plugin disabled' => [
'bbbenabled' => false, 'bbbenabled' => false,
'apiclass' => mod_instance_helper::class, 'apiclass' => mod_instance_helper::class,
'result' => [], 'extensionclasses' => [],
], ],
'mod_instance_helper with plugin enabled' => [ 'mod_instance_helper with plugin enabled' => [
'bbbenabled' => true, 'bbbenabled' => true,
'apiclass' => mod_instance_helper::class, 'apiclass' => mod_instance_helper::class,
'result' => [ 'extensionclasses' => [
'bbbext_simple\\bigbluebuttonbn\\mod_instance_helper', '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_data
* @covers ::create_meeting_metadata * @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(); $this->resetAfterTest();
[$meeting, $useringroup, $usernotingroup, $groupid, $activity] = [$meeting, $useringroup, $usernotingroup, $groupid, $activity] =
$this->prepare_meeting($type, $groupname, SEPARATEGROUPS, false); $this->prepare_meeting($type, $groupname, SEPARATEGROUPS, false);
@ -142,7 +142,7 @@ final class meeting_test extends \advanced_testcase {
* @covers ::get_meeting_info * @covers ::get_meeting_info
* @covers ::do_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(); $this->resetAfterTest();
[$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname); [$meeting, $useringroup, $usernotingroup, $groupid, $activity] = $this->prepare_meeting($type, $groupname);
$meetinginfo = $meeting->get_meeting_info(); $meetinginfo = $meeting->get_meeting_info();

View file

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

View file

@ -109,14 +109,14 @@ final class preset_importer_test extends \advanced_testcase {
public static function needs_mapping_provider(): array { public static function needs_mapping_provider(): array {
$basedprovider = static::preset_importer_provider(); $basedprovider = static::preset_importer_provider();
$basedprovider['Empty database / Empty importer']['needsmapping'] = false; $basedprovider['Empty database / Empty importer']['expectedresult'] = false;
$basedprovider['Empty database / Importer with fields']['needsmapping'] = false; $basedprovider['Empty database / Importer with fields']['expectedresult'] = false;
$basedprovider['Database with fields / Empty importer']['needsmapping'] = true; $basedprovider['Database with fields / Empty importer']['expectedresult'] = true;
$basedprovider['Same fields']['needsmapping'] = false; $basedprovider['Same fields']['expectedresult'] = false;
$basedprovider['Fields to create']['needsmapping'] = true; $basedprovider['Fields to create']['expectedresult'] = true;
$basedprovider['Fields to remove']['needsmapping'] = true; $basedprovider['Fields to remove']['expectedresult'] = true;
$basedprovider['Fields to update']['needsmapping'] = true; $basedprovider['Fields to update']['expectedresult'] = true;
$basedprovider['Fields to create, remove and update']['needsmapping'] = true; $basedprovider['Fields to create, remove and update']['expectedresult'] = true;
return $basedprovider; return $basedprovider;
} }
@ -304,6 +304,7 @@ final class preset_importer_test extends \advanced_testcase {
): void { ): void {
global $USER; global $USER;
// xdebug_break();
$this->resetAfterTest(); $this->resetAfterTest();
$this->setAdminUser(); $this->setAdminUser();
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); $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 { public static function result_data_provider(): array {
return [ return [
'fill-in with case sensitive' => [ 'fill-in with case sensitive' => [
'result' => [ 'providedresultdata' => [
'interactiontype' => 'fill-in', 'interactiontype' => 'fill-in',
'description' => '<p>Fill in the missing words</p> 'description' => '<p>Fill in the missing words</p>
<p>Meow .... this is a __________</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\\/case-sensitivity":true,'
. '"https:\\/\\/h5p.org\\/x-api\\/alternatives":[["cat"],["dog"]]},"contextExtensions":{}}', . '"https:\\/\\/h5p.org\\/x-api\\/alternatives":[["cat"],["dog"]]},"contextExtensions":{}}',
], ],
'useranswers' => [ 'expecteduseranswers' => [
'Gap #1 - cat' => (object) ['answer' => 'Cat', 'incorrect' => true], 'Gap #1 - cat' => (object) ['answer' => 'Cat', 'incorrect' => true],
'Gap #2 - dog' => (object) ['answer' => 'dog', 'correct' => true], 'Gap #2 - dog' => (object) ['answer' => 'dog', 'correct' => true],
], ],
], ],
'fill-in with case insensitive' => [ 'fill-in with case insensitive' => [
'result' => [ 'providedresultdata' => [
'interactiontype' => 'fill-in', 'interactiontype' => 'fill-in',
'description' => '<p>Fill in the missing words</p> 'description' => '<p>Fill in the missing words</p>
<p>Meow .... this is a __________</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\\/case-sensitivity":false,'
. '"https:\\/\\/h5p.org\\/x-api\\/alternatives":[["cat"],["dog"]]},"contextExtensions":{}}', . '"https:\\/\\/h5p.org\\/x-api\\/alternatives":[["cat"],["dog"]]},"contextExtensions":{}}',
], ],
'useranswers' => [ 'expecteduseranswers' => [
'Gap #1 - cat' => (object) ['answer' => 'Cat', 'correct' => true], 'Gap #1 - cat' => (object) ['answer' => 'Cat', 'correct' => true],
'Gap #2 - dog' => (object) ['answer' => 'dog', 'correct' => true], 'Gap #2 - dog' => (object) ['answer' => 'dog', 'correct' => true],
], ],
], ],
'drag and drop' => [ 'drag and drop' => [
'result' => [ 'providedresultdata' => [
'interactiontype' => 'matching', 'interactiontype' => 'matching',
'description' => 'Drag and Drop Test', 'description' => 'Drag and Drop Test',
'correctpattern' => '["0[.]0[,]0[.]2[,]1[.]1[,]1[.]0"]', '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"},' . '"http:\/\/h5p.org\/x-api\/h5p-subContentId":"59590246-f16e-4855-8dd6-c80e892ef96b"},'
. '"contextExtensions":{}}', . '"contextExtensions":{}}',
], ],
'useranswers' => [ 'expecteduseranswers' => [
'Answer 1 (DZ1 and DZ2) - Dropzone 1, Dropzone 2' => (object) ['answer' => 'Dropzone 1', 'correct' => true], '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 2 (DZ2) - Dropzone 2' => (object) ['answer' => 'Dropzone 2', 'correct' => true],
'Anwser 3 (DZ1) - Dropzone 1' => (object) ['answer' => 'Dropzone 1', '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' => [ 'drag and drop with no answer' => [
'result' => [ 'providedresultdata' => [
'interactiontype' => 'matching', 'interactiontype' => 'matching',
'description' => 'Drag and Drop Test', 'description' => 'Drag and Drop Test',
'correctpattern' => '["0[.]0[,]0[.]2[,]1[.]1[,]1[.]0"]', '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"},' . '"http:\/\/h5p.org\/x-api\/h5p-subContentId":"59590246-f16e-4855-8dd6-c80e892ef96b"},'
. '"contextExtensions":{}}', . '"contextExtensions":{}}',
], ],
'useranswers' => [ 'expecteduseranswers' => [
'Answer 1 (DZ1 and DZ2) - Dropzone 1, Dropzone 2' => (object) ['answer' => 'Dropzone 2', 'correct' => true], '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 2 (DZ2) - Dropzone 2' => (object) ['answer' => 'Dropzone 2', 'correct' => true],
'Anwser 3 (DZ1) - Dropzone 1' => (object) ['answer' => 'None', 'incorrect' => 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' => [ 'sort the paragraph text' => [
'result' => [ 'providedresultdata' => [
'interactiontype' => 'sequencing', 'interactiontype' => 'sequencing',
'description' => 'SortParagraphs', 'description' => 'SortParagraphs',
'correctpattern' => '["0[,]1[,]2[,]3[,]4"]', '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,' '"extensions":{"http:\\/\\/h5p.org\\/x-api\\/h5p-local-content-id":39,'
. '"https:\\/\\/h5p.org\\/x-api\\/duplicates-interchangeable":1},"contextExtensions":{}}', . '"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], '#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], '#2 - Next I get dressed' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#3 - Afterward I have breakfast' => (object) ['answer' => 'Incorrect answer', 'fail' => 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' => [ 'sequencing images' => [
'result' => [ 'providedresultdata' => [
'interactiontype' => 'sequencing', 'interactiontype' => 'sequencing',
'description' => 'Order the planets from smallest to largest', '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"]', '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":' . '{"id":"item_6","description":{"en-US":"Jupiter"}}],"extensions":'
. '{"http:\/\/h5p.org\/x-api\/h5p-local-content-id":43},"contextExtensions":{}}', . '{"http:\/\/h5p.org\/x-api\/h5p-local-content-id":43},"contextExtensions":{}}',
], ],
'useranswers' => [ 'expecteduseranswers' => [
'#1 - Mercury' => (object) ['answer' => 'Correct answer', 'pass' => true], '#1 - Mercury' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#2 - Mars' => (object) ['answer' => 'Correct answer', 'pass' => true], '#2 - Mars' => (object) ['answer' => 'Correct answer', 'pass' => true],
'#3 - Earth' => (object) ['answer' => 'Incorrect answer', 'fail' => 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', 'name' => 'Test label 1',
'content' => '<p>Simple textual content<p>', 'content' => '<p>Simple textual content<p>',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Test label 1' 'expectedname' => 'Test label 1'
], ],
'simple' => [ 'simple' => [
'name' => '', 'name' => '',
'content' => '<p>Simple textual content<p>', 'content' => '<p>Simple textual content<p>',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Simple textual content' 'expectedname' => 'Simple textual content'
], ],
'empty' => [ 'empty' => [
'name' => '', 'name' => '',
'content' => '', 'content' => '',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Test label 1' 'expectedname' => 'Test label 1'
], ],
'withaudiocontent' => [ 'withaudiocontent' => [
'name' => '', 'name' => '',
@ -263,7 +263,7 @@ final class lib_test extends \advanced_testcase {
@@PLUGINFILE@@/moodle-hit-song.mp3 @@PLUGINFILE@@/moodle-hit-song.mp3
</audio>&nbsp;</p>', </audio>&nbsp;</p>',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Test with audio' 'expectedname' => 'Test with audio'
], ],
'withvideo' => [ 'withvideo' => [
'name' => '', 'name' => '',
@ -273,7 +273,7 @@ final class lib_test extends \advanced_testcase {
https://www.youtube.com/watch?v=xxxyy https://www.youtube.com/watch?v=xxxyy
</video>&nbsp;</p>', </video>&nbsp;</p>',
'format' => FORMAT_HTML, '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' => [ 'with video trimming' => [
'name' => '', 'name' => '',
@ -283,61 +283,61 @@ final class lib_test extends \advanced_testcase {
https://www.youtube.com/watch?v=xxxyy https://www.youtube.com/watch?v=xxxyy
</video>&nbsp;</p>', </video>&nbsp;</p>',
'format' => FORMAT_HTML, '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' => [ 'with plain text' => [
'name' => '', 'name' => '',
'content' => 'Content with @@PLUGINFILE@@/moodle-hit-song.mp3 nothing', 'content' => 'Content with @@PLUGINFILE@@/moodle-hit-song.mp3 nothing',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Content with nothing' 'expectedname' => 'Content with nothing'
], ],
'with several spaces' => [ 'with several spaces' => [
'name' => '', 'name' => '',
'content' => "Content with @@PLUGINFILE@@/moodle-hit-song.mp3 \r &nbsp; several spaces", 'content' => "Content with @@PLUGINFILE@@/moodle-hit-song.mp3 \r &nbsp; several spaces",
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Content with several spaces' 'expectedname' => 'Content with several spaces'
], ],
'empty spaces' => [ 'empty spaces' => [
'name' => '', 'name' => '',
'content' => ' &nbsp; ', 'content' => ' &nbsp; ',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Text and media area' 'expectedname' => 'Text and media area'
], ],
'only html' => [ 'only html' => [
'name' => '', 'name' => '',
'content' => '<audio controls="controls"><source src=""></audio>', 'content' => '<audio controls="controls"><source src=""></audio>',
'format' => FORMAT_HTML, 'format' => FORMAT_HTML,
'expected' => 'Text and media area' 'expectedname' => 'Text and media area'
], ],
'markdown' => [ 'markdown' => [
'name' => '', 'name' => '',
'content' => "##Simple Title\n simple markdown format", 'content' => "##Simple Title\n simple markdown format",
'format' => FORMAT_MARKDOWN, 'format' => FORMAT_MARKDOWN,
'expected' => 'Simple Title simple markdown format' 'expectedname' => 'Simple Title simple markdown format'
], ],
'markdown with pluginfile' => [ 'markdown with pluginfile' => [
'name' => '', 'name' => '',
'content' => "##Simple Title\n simple markdown format @@PLUGINFILE@@/moodle-hit-song.mp3", 'content' => "##Simple Title\n simple markdown format @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_MARKDOWN, 'format' => FORMAT_MARKDOWN,
'expected' => 'Simple Title simple markdown format' 'expectedname' => 'Simple Title simple markdown format'
], ],
'plain text' => [ 'plain text' => [
'name' => '', 'name' => '',
'content' => "Simple plain text @@PLUGINFILE@@/moodle-hit-song.mp3", 'content' => "Simple plain text @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_PLAIN, 'format' => FORMAT_PLAIN,
'expected' => 'Simple plain text' 'expectedname' => 'Simple plain text'
], ],
'moodle format text' => [ 'moodle format text' => [
'name' => '', 'name' => '',
'content' => "Simple plain text @@PLUGINFILE@@/moodle-hit-song.mp3", 'content' => "Simple plain text @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_MOODLE, 'format' => FORMAT_MOODLE,
'expected' => 'Simple plain text' 'expectedname' => 'Simple plain text'
], ],
'html format text' => [ 'html format text' => [
'name' => '', 'name' => '',
'content' => "<h1>Simple plain title</h1><p> with plain text</p> @@PLUGINFILE@@/moodle-hit-song.mp3", 'content' => "<h1>Simple plain title</h1><p> with plain text</p> @@PLUGINFILE@@/moodle-hit-song.mp3",
'format' => FORMAT_HTML, '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 [ return [
"Using a decimal as a separator" => [ "Using a decimal as a separator" => [
"decsep" => ".", "decsep" => ".",
"test" => [ "tests" => [
["2.1", 2.1], ["2.1", 2.1],
["1:4.2", "1:4.2"], ["1:4.2", "1:4.2"],
["2,1", 2], ["2,1", 2],
@ -76,7 +76,7 @@ final class numeric_helper_test extends \advanced_testcase {
], ],
"Using a comma as a separator" => [ "Using a comma as a separator" => [
"decsep" => ",", "decsep" => ",",
"test" => [ "tests" => [
["2,1", 2.1], ["2,1", 2.1],
["1:4,2", "1:4.2"], ["1:4,2", "1:4.2"],
["2.1", 2.1], ["2.1", 2.1],
@ -85,7 +85,7 @@ final class numeric_helper_test extends \advanced_testcase {
], ],
"Using a X as a separator" => [ "Using a X as a separator" => [
"decsep" => "X", "decsep" => "X",
"test" => [ "tests" => [
["2X1", 2.1], ["2X1", 2.1],
["1:4X2", "1:4.2"], ["1:4X2", "1:4.2"],
["2.1", 2.1], ["2.1", 2.1],
@ -104,7 +104,7 @@ final class numeric_helper_test extends \advanced_testcase {
return [ return [
"Using a decimal as a separator" => [ "Using a decimal as a separator" => [
"decsep" => ".", "decsep" => ".",
"test" => [ "tests" => [
["2.1", 2.1], ["2.1", 2.1],
["1:4.2", "1:4.2"], ["1:4.2", "1:4.2"],
["2,1", "2,1"], ["2,1", "2,1"],
@ -113,7 +113,7 @@ final class numeric_helper_test extends \advanced_testcase {
], ],
"Using a comma as a separator" => [ "Using a comma as a separator" => [
"decsep" => ",", "decsep" => ",",
"test" => [ "tests" => [
["2,1", "2,1"], ["2,1", "2,1"],
["1:4,2", "1:4,2"], ["1:4,2", "1:4,2"],
["2.1", "2,1"], ["2.1", "2,1"],
@ -123,7 +123,7 @@ final class numeric_helper_test extends \advanced_testcase {
], ],
"Using a X as a separator" => [ "Using a X as a separator" => [
"decsep" => "X", "decsep" => "X",
"test" => [ "tests" => [
["2X1", "2X1"], ["2X1", "2X1"],
["1:4X2", "1:4X2"], ["1:4X2", "1:4X2"],
["2.1", "2X1"], ["2.1", "2X1"],

View file

@ -60,31 +60,31 @@ final class validate_quiz_access_test extends \advanced_testcase {
'cmid' => null, 'cmid' => null,
'url' => null, 'url' => null,
'configkey' => 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' => [ 'no course module id' => [
'cmid' => null, 'cmid' => null,
'url' => 'https://www.example.com/moodle', 'url' => 'https://www.example.com/moodle',
'configkey' => hash('sha256', 'configkey'), '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' => [ 'no url' => [
'cmid' => 123, 'cmid' => 123,
'url' => null, 'url' => null,
'configkey' => hash('sha256', 'configkey'), '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 is not an int' => [
'cmid' => 'test', 'cmid' => 'test',
'url' => 'https://www.example.com/moodle', 'url' => 'https://www.example.com/moodle',
'configkey' => null, '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' => [ 'url is not a url' => [
'cmid' => 123, 'cmid' => 123,
'url' => 123, 'url' => 123,
'configkey' => hash('sha256', 'configkey'), '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', 'password' => 'test',
], ],
'expectedrecordscreated' => 1, 'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class, 'expectedeventclass' => user_override_created::class,
], ],
'create user override - no calendar events should be created' => [ 'create user override - no calendar events should be created' => [
'existingdata' => [], 'existingdata' => [],
@ -239,7 +239,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test', 'password' => 'test',
], ],
'expectedrecordscreated' => 1, 'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class, 'expectedeventclass' => user_override_created::class,
], ],
'create user override - only timeopen' => [ 'create user override - only timeopen' => [
'existingdata' => [], 'existingdata' => [],
@ -253,7 +253,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test', 'password' => 'test',
], ],
'expectedrecordscreated' => 1, 'expectedrecordscreated' => 1,
'expectedevent' => user_override_created::class, 'expectedeventclass' => user_override_created::class,
], ],
'create group override - no existing data' => [ 'create group override - no existing data' => [
'existingdata' => [], 'existingdata' => [],
@ -267,7 +267,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test', 'password' => 'test',
], ],
'expectedrecordscreated' => 1, 'expectedrecordscreated' => 1,
'expectedevent' => group_override_created::class, 'expectedeventclass' => group_override_created::class,
], ],
'create group override - no calendar events should be created' => [ 'create group override - no calendar events should be created' => [
'existingdata' => [], 'existingdata' => [],
@ -281,7 +281,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test', 'password' => 'test',
], ],
'expectedrecordscreated' => 1, 'expectedrecordscreated' => 1,
'expectedevent' => group_override_created::class, 'expectedeventclass' => group_override_created::class,
], ],
'create group override - only timeopen' => [ 'create group override - only timeopen' => [
'existingdata' => [], 'existingdata' => [],
@ -295,7 +295,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => null, 'password' => null,
], ],
'expectedrecordscreated' => 1, 'expectedrecordscreated' => 1,
'expectedevent' => group_override_created::class, 'expectedeventclass' => group_override_created::class,
], ],
'update user override - updating existing data' => [ 'update user override - updating existing data' => [
'existingdata' => [ 'existingdata' => [
@ -318,7 +318,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test', 'password' => 'test',
], ],
'expectedrecordscreated' => 0, 'expectedrecordscreated' => 0,
'expectedevent' => user_override_updated::class, 'expectedeventclass' => user_override_updated::class,
], ],
'update group override - updating existing data' => [ 'update group override - updating existing data' => [
'existingdata' => [ 'existingdata' => [
@ -341,7 +341,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => 'test', 'password' => 'test',
], ],
'expectedrecordscreated' => 0, 'expectedrecordscreated' => 0,
'expectedevent' => group_override_updated::class, 'expectedeventclass' => group_override_updated::class,
], ],
'attempts is set to unlimited (i.e. 0)' => [ 'attempts is set to unlimited (i.e. 0)' => [
'existingdata' => [], 'existingdata' => [],
@ -356,7 +356,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => null, 'password' => null,
], ],
'expectedrecordscreated' => 1, '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)' => [ 'some settings submitted are the same as what is in the quiz (valid)' => [
'existingdata' => [], 'existingdata' => [],
@ -372,7 +372,7 @@ final class override_manager_test extends \advanced_testcase {
'password' => null, 'password' => null,
], ],
'expectedrecordscreated' => 1, '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 { public static function delete_override_provider(): array {
return [ return [
'delete by id (no events logged)' => [ '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, 'checkeventslogged' => false,
], ],
'delete single (no events logged)' => [ '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, 'checkeventslogged' => false,
], ],
'delete all (no events logged)' => [ '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, 'checkeventslogged' => false,
], ],
'delete by id (events logged)' => [ '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, 'checkeventslogged' => true,
], ],
'delete single (events logged)' => [ '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, 'checkeventslogged' => true,
], ],
'delete all (events logged)' => [ '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, 'checkeventslogged' => true,
], ],
'delete all in database (events logged)' => [ '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, 'checkeventslogged' => true,
], ],
]; ];

View file

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

View file

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

View file

@ -1,22 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit <phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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" bootstrap="lib/phpunit/bootstrap.php"
convertErrorsToExceptions="true" processIsolation="false"
convertNoticesToExceptions="true" backupGlobals="false"
convertWarningsToExceptions="true" cacheResult="false"
processIsolation="false" stopOnError="false"
backupGlobals="false" stopOnFailure="false"
backupStaticAttributes="false" stopOnIncomplete="false"
cacheResult="false" stopOnSkipped="false"
stopOnError="false" beStrictAboutTestsThatDoNotTestAnything="false"
stopOnFailure="false" beStrictAboutOutputDuringTests="true"
stopOnIncomplete="false" cacheDirectory=".phpunit.cache"
stopOnSkipped="false" backupStaticProperties="false"
beStrictAboutTestsThatDoNotTestAnything="false" >
beStrictAboutOutputDuringTests="true"
>
<php> <php>
<!--<const name="PHPUNIT_LONGTEST" value="1"/> uncomment to execute also slow or otherwise expensive tests--> <!--<const name="PHPUNIT_LONGTEST" value="1"/> uncomment to execute also slow or otherwise expensive tests-->
@ -305,8 +303,8 @@
<!--@plugin_suites_end@--> <!--@plugin_suites_end@-->
</testsuites> </testsuites>
<coverage> <source>
<!--@coveragelist@--> <!--@coveragelist@-->
</coverage> </source>
</phpunit> </phpunit>

View file

@ -272,32 +272,42 @@ final class helper_test extends \advanced_testcase {
*/ */
public static function load_question_facility_provider(): \Generator { public static function load_question_facility_provider(): \Generator {
yield 'Facility case 1' => [ yield 'Facility case 1' => [
'Quiz 1 attempts' => [ // Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]), self::generate_attempt_answers([1, 0, 0, 0]),
], ],
'Expected quiz 1 facilities' => ['100.00%', '0.00%', '0.00%', '0.00%'], // Expected quiz 1 facilities.
'Quiz 2 attempts' => [ '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, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]), self::generate_attempt_answers([1, 1, 0, 0]),
], ],
'Expected quiz 2 facilities' => ['100.00%', '50.00%', '0.00%', '0.00%'], // Expected quiz 2 facilities.
'Expected average facilities' => ['100.00%', '25.00%', '0.00%', '0.00%'], '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' => [ yield 'Facility case 2' => [
'Quiz 1 attempts' => [ // Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]), self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 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, 0]),
], ],
'Expected quiz 1 facilities' => ['100.00%', '66.67%', '33.33%', '0.00%'], // Expected quiz 1 facilities.
'Quiz 2 attempts' => [ '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, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 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, 0]),
self::generate_attempt_answers([1, 1, 1, 1]), self::generate_attempt_answers([1, 1, 1, 1]),
], ],
'Expected quiz 2 facilities' => ['100.00%', '75.00%', '50.00%', '25.00%'], // Expected quiz 2 facilities.
'Expected average facilities' => ['100.00%', '70.83%', '41.67%', '12.50%'], '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 { public static function load_question_discriminative_efficiency_provider(): \Generator {
yield 'Discriminative efficiency' => [ yield 'Discriminative efficiency' => [
'Quiz 1 attempts' => [ // Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]), self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]), self::generate_attempt_answers([1, 1, 0, 0]),
self::generate_attempt_answers([1, 0, 1, 0]), self::generate_attempt_answers([1, 0, 1, 0]),
self::generate_attempt_answers([1, 1, 1, 1]), self::generate_attempt_answers([1, 1, 1, 1]),
], ],
'Expected quiz 1 discriminative efficiency' => ['N/A', '33.33%', '33.33%', '100.00%'], // Expected quiz 1 facilities.
'Quiz 2 attempts' => [ '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([1, 1, 1, 1]),
self::generate_attempt_answers([0, 0, 0, 0]), self::generate_attempt_answers([0, 0, 0, 0]),
self::generate_attempt_answers([1, 0, 0, 1]), self::generate_attempt_answers([1, 0, 0, 1]),
self::generate_attempt_answers([0, 1, 1, 0]), self::generate_attempt_answers([0, 1, 1, 0]),
], ],
'Expected quiz 2 discriminative efficiency' => ['50.00%', '50.00%', '50.00%', '50.00%'], // Expected quiz 2 facilities.
'Expected average discriminative efficiency' => ['50.00%', '41.67%', '41.67%', '75.00%'], '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 { public static function load_question_discrimination_index_provider(): \Generator {
yield 'Discrimination Index' => [ yield 'Discrimination Index' => [
'Quiz 1 attempts' => [ // Quiz 1 attempts.
'quiz1attempts' => [
self::generate_attempt_answers([1, 0, 0, 0]), self::generate_attempt_answers([1, 0, 0, 0]),
self::generate_attempt_answers([1, 1, 0, 0]), self::generate_attempt_answers([1, 1, 0, 0]),
self::generate_attempt_answers([1, 0, 1, 0]), self::generate_attempt_answers([1, 0, 1, 0]),
self::generate_attempt_answers([1, 1, 1, 1]), self::generate_attempt_answers([1, 1, 1, 1]),
], ],
'Expected quiz 1 Discrimination Index' => ['N/A', '30.15%', '30.15%', '81.65%'], // Expected quiz 1 facilities.
'Quiz 2 attempts' => [ '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([1, 1, 1, 1]),
self::generate_attempt_answers([0, 0, 0, 0]), self::generate_attempt_answers([0, 0, 0, 0]),
self::generate_attempt_answers([1, 0, 0, 1]), self::generate_attempt_answers([1, 0, 0, 1]),
self::generate_attempt_answers([0, 1, 1, 0]), self::generate_attempt_answers([0, 1, 1, 0]),
], ],
'Expected quiz 2 discrimination Index' => ['44.72%', '44.72%', '44.72%', '44.72%'], // Expected quiz 2 facilities.
'Expected average discrimination Index' => ['44.72%', '37.44%', '37.44%', '63.19%'], '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('My report with tags', $report->get('name'));
$this->assertEquals(datasource::TYPE_CUSTOM_REPORT, $report->get('type')); $this->assertEquals(datasource::TYPE_CUSTOM_REPORT, $report->get('type'));
$this->assertEqualsCanonicalizing(['cat', 'dog'], $this->assertEqualsCanonicalizing(
core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $report->get('id'))); ['cat', 'dog'],
array_values(core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $report->get('id'))),
);
$report = report::create_report((object) [ $report = report::create_report((object) [
'name' => 'My report without tags', '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->assertEquals('My renamed report adding tags', $reportupdated->get('name'));
$this->assertTrue($reportupdated->get('uniquerows')); $this->assertTrue($reportupdated->get('uniquerows'));
$this->assertEqualsCanonicalizing(['cat', 'dog'], $this->assertEqualsCanonicalizing(
core_tag_tag::get_item_tags_array('core_reportbuilder', 'reportbuilder_report', $reportupdated->get('id'))); ['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 * @dataProvider sync_reference_provider
* @param array $storedfileargs * @param array $storedfileargs
* @param array $storedfilemethodsmock * @param array $mockfunctions
* @param bool $expectedresult * @param bool $expectedresult
* @return void * @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); $this->resetAfterTest(true);
if (isset($storedfilemethodsmock[0])) { if (isset($mockfunctions[0])) {
$storedfile = $this->createMock(\stored_file::class); $storedfile = $this->createMock(\stored_file::class);
if ($storedfilemethodsmock[0] === 'get_referencelastsync') { if ($mockfunctions[0] === 'get_referencelastsync') {
if (!$expectedresult) { if (!$expectedresult) {
$storedfile->method('get_referencelastsync')->willReturn(DAYSECS + time()); $storedfile->method('get_referencelastsync')->willReturn(DAYSECS + time());
} }