PageRenderTime 24ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/enrol/lti/tests/sync_members_test.php

https://github.com/mackensen/moodle
PHP | 400 lines | 197 code | 51 blank | 152 comment | 8 complexity | f020bf7ecd81e8e68544e466f4cce7e0 MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Tests for the sync_members scheduled task class.
  18. *
  19. * @package enrol_lti
  20. * @copyright 2016 Jun Pataleta <jun@moodle.com>
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. use enrol_lti\data_connector;
  24. use enrol_lti\helper;
  25. use enrol_lti\task\sync_members;
  26. use enrol_lti\tool_provider;
  27. use IMSGlobal\LTI\ToolProvider\Context;
  28. use IMSGlobal\LTI\ToolProvider\ResourceLink;
  29. use IMSGlobal\LTI\ToolProvider\ToolConsumer;
  30. use IMSGlobal\LTI\ToolProvider\User;
  31. defined('MOODLE_INTERNAL') || die();
  32. /**
  33. * Tests for the sync_members scheduled task class.
  34. *
  35. * @package enrol_lti
  36. * @copyright 2016 Jun Pataleta <jun@moodle.com>
  37. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38. */
  39. class sync_members_testcase extends advanced_testcase {
  40. /** @var dummy_sync_members_task $task */
  41. protected $task;
  42. /** @var stdClass $tool The published tool. */
  43. protected $tool;
  44. /** @var User[] $members */
  45. protected $members;
  46. /** @var ToolConsumer $consumer */
  47. protected $consumer;
  48. /** @var Context $context */
  49. protected $context;
  50. /** @var ResourceLink $resourcelink */
  51. protected $resourcelink;
  52. public function setUp(): void {
  53. $this->resetAfterTest();
  54. // Set this user as the admin.
  55. $this->setAdminUser();
  56. $this->task = new dummy_sync_members_task();
  57. $generator = $this->getDataGenerator();
  58. $course = $generator->create_course();
  59. $tooldata = [
  60. 'courseid' => $course->id,
  61. 'membersyncmode' => helper::MEMBER_SYNC_ENROL_AND_UNENROL,
  62. 'membersync' => 1,
  63. ];
  64. $tool = $generator->create_lti_tool((object)$tooldata);
  65. $this->tool = helper::get_lti_tool($tool->id);
  66. $dataconnector = $this->task->get_dataconnector();
  67. $this->consumer = new ToolConsumer('Consumer1Key', $dataconnector);
  68. $this->consumer->name = 'Consumer1';
  69. $this->consumer->secret = 'Consumer1Secret';
  70. $this->consumer->save();
  71. $toolprovider = new tool_provider($this->tool->id);
  72. $toolprovider->consumer = $this->consumer;
  73. $toolprovider->map_tool_to_consumer();
  74. $imageurl = $this->getExternalTestFileUrl('test.jpg');
  75. $count = 10;
  76. $this->members = [];
  77. for ($i = 1; $i <= $count; $i++) {
  78. $user = new User();
  79. $user->firstname = 'Firstname' . $i;
  80. $user->lastname = 'Lastname' . $i;
  81. $user->ltiUserId = 'user' . $i;
  82. // Set user image values for some users.
  83. if ($i % 3 == 0) {
  84. $user->image = $imageurl;
  85. }
  86. $this->members[] = $user;
  87. }
  88. $this->context = Context::fromConsumer($this->consumer, 'testlticontextid');
  89. $this->context->save();
  90. $this->resourcelink = ResourceLink::fromContext($this->context, 'testresourcelinkid');
  91. $this->resourcelink->save();
  92. }
  93. /**
  94. * Test for sync_members::do_context_membership_request().
  95. */
  96. public function test_do_context_membership_request() {
  97. // Suppress output.
  98. ob_start();
  99. $members = $this->task->do_context_membership_request($this->context);
  100. ob_end_clean();
  101. $this->assertFalse($members);
  102. }
  103. /**
  104. * Test for sync_members::do_resourcelink_membership_request().
  105. */
  106. public function test_do_resourcelink_membership_request() {
  107. $members = $this->task->do_resourcelink_membership_request($this->resourcelink);
  108. $this->assertFalse($members);
  109. }
  110. /**
  111. * Test for sync_members::execute() when auth_lti is disabled.
  112. */
  113. public function test_execute_authdisabled() {
  114. ob_start();
  115. $this->task->execute();
  116. $output = ob_get_clean();
  117. $message = 'Skipping task - ' . get_string('pluginnotenabled', 'auth', get_string('pluginname', 'auth_lti'));
  118. $this->assertStringContainsString($message, $output);
  119. }
  120. /**
  121. * Test for sync_members::execute() when enrol_lti is disabled.
  122. */
  123. public function test_execute_enroldisabled() {
  124. // Enable auth_lti.
  125. $this->enable_auth();
  126. ob_start();
  127. $this->task->execute();
  128. $output = ob_get_clean();
  129. $message = 'Skipping task - ' . get_string('enrolisdisabled', 'enrol_lti');
  130. $this->assertStringContainsString($message, $output);
  131. }
  132. /**
  133. * Test for sync_members::execute().
  134. */
  135. public function test_execute() {
  136. // Enable auth_lti.
  137. $this->enable_auth();
  138. // Enable enrol_lti.
  139. $this->enable_enrol();
  140. ob_start();
  141. $this->task->execute();
  142. $output = ob_get_clean();
  143. $membersyncmessage = "Completed - Synced members for tool '{$this->tool->id}' in the course '{$this->tool->courseid}'";
  144. $this->assertStringContainsString($membersyncmessage, $output);
  145. $imagesyncmessage = "Completed - Synced 0 profile images.";
  146. $this->assertStringContainsString($imagesyncmessage, $output);
  147. }
  148. /**
  149. * Test for sync_members::fetch_members_from_consumer() with no resource link nor context associated with the consumer.
  150. */
  151. public function test_fetch_members_from_consumer_noresourcelink_nocontext() {
  152. // Suppress output.
  153. ob_start();
  154. $members = $this->task->fetch_members_from_consumer($this->consumer);
  155. ob_end_clean();
  156. $this->assertFalse($members);
  157. }
  158. /**
  159. * Test for sync_members::get_name().
  160. */
  161. public function test_get_name() {
  162. $this->assertEquals(get_string('tasksyncmembers', 'enrol_lti'), $this->task->get_name());
  163. }
  164. /**
  165. * Test for sync_members::should_sync_enrol().
  166. */
  167. public function test_should_sync_enrol() {
  168. $this->assertTrue($this->task->should_sync_enrol(helper::MEMBER_SYNC_ENROL_AND_UNENROL));
  169. $this->assertTrue($this->task->should_sync_enrol(helper::MEMBER_SYNC_ENROL_NEW));
  170. $this->assertFalse($this->task->should_sync_enrol(helper::MEMBER_SYNC_UNENROL_MISSING));
  171. }
  172. /**
  173. * Test for sync_members::should_sync_unenrol().
  174. */
  175. public function test_should_sync_unenrol() {
  176. $this->assertTrue($this->task->should_sync_unenrol(helper::MEMBER_SYNC_ENROL_AND_UNENROL));
  177. $this->assertFalse($this->task->should_sync_unenrol(helper::MEMBER_SYNC_ENROL_NEW));
  178. $this->assertTrue($this->task->should_sync_unenrol(helper::MEMBER_SYNC_UNENROL_MISSING));
  179. }
  180. /**
  181. * Test for sync_members::sync_member_information().
  182. */
  183. public function test_sync_member_information() {
  184. list($totalcount, $enrolledcount) = $this->task->sync_member_information($this->tool, $this->consumer, $this->members);
  185. $membercount = count($this->members);
  186. $this->assertCount(10, $this->members);
  187. $this->assertEquals($membercount, $totalcount);
  188. $this->assertEquals($membercount, $enrolledcount);
  189. }
  190. /**
  191. * Test for sync_members::sync_profile_images().
  192. */
  193. public function test_sync_profile_images() {
  194. $task = $this->task;
  195. list($totalcount, $enrolledcount) = $task->sync_member_information($this->tool, $this->consumer, $this->members);
  196. $membercount = count($this->members);
  197. $this->assertCount(10, $this->members);
  198. $this->assertEquals($membercount, $totalcount);
  199. $this->assertEquals($membercount, $enrolledcount);
  200. // Suppress output.
  201. ob_start();
  202. $this->assertEquals(3, $task->sync_profile_images());
  203. ob_end_clean();
  204. }
  205. /**
  206. * Test for sync_members::sync_unenrol().
  207. */
  208. public function test_sync_unenrol() {
  209. $tool = $this->tool;
  210. $task = $this->task;
  211. $task->sync_member_information($tool, $this->consumer, $this->members);
  212. // Simulate that the fetched list of current users has been reduced by 3.
  213. $unenrolcount = 3;
  214. for ($i = 0; $i < $unenrolcount; $i++) {
  215. $task->pop_current_users();
  216. }
  217. $this->assertEquals($unenrolcount, $task->sync_unenrol($tool));
  218. }
  219. /**
  220. * Enable auth_lti plugin.
  221. */
  222. protected function enable_auth() {
  223. $auths = get_enabled_auth_plugins();
  224. if (!in_array('lti', $auths)) {
  225. $auths[] = 'lti';
  226. }
  227. set_config('auth', implode(',', $auths));
  228. }
  229. /**
  230. * Enable enrol_lti plugin.
  231. */
  232. protected function enable_enrol() {
  233. $enabled = enrol_get_plugins(true);
  234. $enabled['lti'] = true;
  235. $enabled = array_keys($enabled);
  236. set_config('enrol_plugins_enabled', implode(',', $enabled));
  237. }
  238. }
  239. /**
  240. * Class dummy_sync_members_task.
  241. *
  242. * A class that extends sync_members so that we can expose the protected methods that we would like to test.
  243. *
  244. * @copyright 2016 Jun Pataleta <jun@moodle.com>
  245. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  246. */
  247. class dummy_sync_members_task extends sync_members {
  248. /**
  249. * Exposes/generates the dataconnector property.
  250. *
  251. * @return data_connector
  252. */
  253. public function get_dataconnector() {
  254. if (!$this->dataconnector) {
  255. $this->dataconnector = new data_connector();
  256. }
  257. return $this->dataconnector;
  258. }
  259. /**
  260. * Helper method that removes an element in the array of current users.
  261. */
  262. public function pop_current_users() {
  263. array_pop($this->currentusers);
  264. }
  265. /**
  266. * Exposes sync_members::do_context_membership_request()
  267. *
  268. * @param Context $context The context object.
  269. * @param ResourceLink $resourcelink The resource link object.
  270. * @param string $membershipsurltemplate The memberships endpoint URL template.
  271. * @return bool|User[] Array of User objects upon successful membership service request. False, otherwise.
  272. */
  273. public function do_context_membership_request(Context $context, ResourceLink $resourcelink = null,
  274. $membershipsurltemplate = '') {
  275. $members = parent::do_context_membership_request($context, $resourcelink, $membershipsurltemplate);
  276. return $members;
  277. }
  278. /**
  279. * Exposes sync_members::do_resourcelink_membership_request()
  280. *
  281. * @param ResourceLink $resourcelink
  282. * @return bool|User[]
  283. */
  284. public function do_resourcelink_membership_request(ResourceLink $resourcelink) {
  285. $members = parent::do_resourcelink_membership_request($resourcelink);
  286. return $members;
  287. }
  288. /**
  289. * Exposes sync_members::fetch_members_from_consumer()
  290. *
  291. * @param ToolConsumer $consumer
  292. * @return bool|User[]
  293. */
  294. public function fetch_members_from_consumer(ToolConsumer $consumer) {
  295. $members = parent::fetch_members_from_consumer($consumer);
  296. return $members;
  297. }
  298. /**
  299. * Exposes sync_members::should_sync_unenrol()
  300. *
  301. * @param int $syncmode The tool's membersyncmode.
  302. * @return bool
  303. */
  304. public function should_sync_unenrol($syncmode) {
  305. $shouldsync = parent::should_sync_unenrol($syncmode);
  306. return $shouldsync;
  307. }
  308. /**
  309. * Exposes sync_members::should_sync_enrol()
  310. *
  311. * @param int $syncmode The tool's membersyncmode.
  312. * @return bool
  313. */
  314. public function should_sync_enrol($syncmode) {
  315. $shouldsync = parent::should_sync_enrol($syncmode);
  316. return $shouldsync;
  317. }
  318. /**
  319. * Exposes sync_members::sync_member_information()
  320. *
  321. * @param stdClass $tool
  322. * @param ToolConsumer $consumer
  323. * @param User[] $members
  324. * @return array
  325. */
  326. public function sync_member_information(stdClass $tool, ToolConsumer $consumer, $members) {
  327. $result = parent::sync_member_information($tool, $consumer, $members);
  328. return $result;
  329. }
  330. /**
  331. * Exposes sync_members::sync_profile_images()
  332. *
  333. * @return int
  334. */
  335. public function sync_profile_images() {
  336. $count = parent::sync_profile_images();
  337. return $count;
  338. }
  339. /**
  340. * Exposes sync_members::sync_unenrol()
  341. *
  342. * @param stdClass $tool
  343. * @return int
  344. */
  345. public function sync_unenrol(stdClass $tool) {
  346. $count = parent::sync_unenrol($tool);
  347. return $count;
  348. }
  349. }