bd815e657cb6a305e6f88bfb408e39dc590361df
[moodle.git] / blocks / tests / externallib_test.php
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/>.
17 /**
18  * External block functions unit tests
19  *
20  * @package    core_block
21  * @category   external
22  * @copyright  2017 Juan Leyva <juan@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @since      Moodle 3.3
25  */
27 defined('MOODLE_INTERNAL') || die();
29 global $CFG;
31 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
32 require_once($CFG->dirroot . '/my/lib.php');
34 /**
35  * External block functions unit tests
36  *
37  * @package    core_block
38  * @category   external
39  * @copyright  2015 Juan Leyva <juan@moodle.com>
40  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  * @since      Moodle 3.0
42  */
43 class core_block_externallib_testcase extends externallib_advanced_testcase {
45     /**
46      * Test get_course_blocks
47      */
48     public function test_get_course_blocks() {
49         global $DB, $FULLME;
51         $this->resetAfterTest(true);
53         $user = $this->getDataGenerator()->create_user();
54         $course = $this->getDataGenerator()->create_course();
55         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
56         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
58         $page = new moodle_page();
59         $page->set_context(context_course::instance($course->id));
60         $page->set_pagelayout('course');
61         $course->format = course_get_format($course)->get_format();
62         $page->set_pagetype('course-view-' . $course->format);
63         $page->blocks->load_blocks();
64         $newblock = 'calendar_upcoming';
65         $page->blocks->add_block_at_end_of_default_region($newblock);
66         $this->setUser($user);
68         // Check for the new block.
69         $result = core_block_external::get_course_blocks($course->id);
70         // We need to execute the return values cleaning process to simulate the web service server.
71         $result = external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result);
73         // Expect the new block.
74         $this->assertCount(1, $result['blocks']);
75         $this->assertEquals($newblock, $result['blocks'][0]['name']);
76     }
78     /**
79      * Test get_course_blocks on site home
80      */
81     public function test_get_course_blocks_site_home() {
82         global $DB, $FULLME;
84         $this->resetAfterTest(true);
86         $user = $this->getDataGenerator()->create_user();
88         $page = new moodle_page();
89         $page->set_context(context_course::instance(SITEID));
90         $page->set_pagelayout('frontpage');
91         $page->set_pagetype('site-index');
92         $page->blocks->load_blocks();
93         $newblock = 'calendar_upcoming';
94         $page->blocks->add_block_at_end_of_default_region($newblock);
95         $this->setUser($user);
97         // Check for the new block.
98         $result = core_block_external::get_course_blocks(SITEID);
99         // We need to execute the return values cleaning process to simulate the web service server.
100         $result = external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result);
102         // Expect the new block.
103         $this->assertCount(1, $result['blocks']);
104         $this->assertEquals($newblock, $result['blocks'][0]['name']);
105     }
107     /**
108      * Test get_course_blocks
109      */
110     public function test_get_course_blocks_overrides() {
111         global $DB, $CFG, $FULLME;
113         $this->resetAfterTest(true);
115         $CFG->defaultblocks_override = 'search_forums,course_list:calendar_upcoming,recent_activity';
117         $user = $this->getDataGenerator()->create_user();
118         $course = $this->getDataGenerator()->create_course();
119         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
120         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
122         $this->setUser($user);
124         // Try default blocks.
125         $result = core_block_external::get_course_blocks($course->id);
126         // We need to execute the return values cleaning process to simulate the web service server.
127         $result = external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result);
129         // Expect 4 default blocks.
130         $this->assertCount(4, $result['blocks']);
132         $expectedblocks = array('navigation', 'settings', 'search_forums', 'course_list',
133                                 'calendar_upcoming', 'recent_activity');
134         foreach ($result['blocks'] as $block) {
135             if (!in_array($block['name'], $expectedblocks)) {
136                 $this->fail("Unexpected block found: " . $block['name']);
137             }
138         }
140     }
142     /**
143      * Test get_course_blocks contents
144      */
145     public function test_get_course_blocks_contents() {
146         global $DB, $FULLME;
148         $this->resetAfterTest(true);
150         $user = $this->getDataGenerator()->create_user();
151         $course = $this->getDataGenerator()->create_course();
152         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
153         $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
154         $coursecontext = context_course::instance($course->id);
156         // Create a HTML block.
157         $title = 'Some course info';
158         $body = 'Some course info<br /><p>Some contents</p>';
159         $bodyformat = FORMAT_MOODLE;
160         $page = new moodle_page();
161         $page->set_context($coursecontext);
162         $page->set_pagelayout('course');
163         $course->format = course_get_format($course)->get_format();
164         $page->set_pagetype('course-view-' . $course->format);
165         $page->blocks->load_blocks();
166         $newblock = 'html';
167         $page->blocks->add_block_at_end_of_default_region($newblock);
169         $this->setUser($user);
170         // Re-create the page.
171         $page = new moodle_page();
172         $page->set_context($coursecontext);
173         $page->set_pagelayout('course');
174         $course->format = course_get_format($course)->get_format();
175         $page->set_pagetype('course-view-' . $course->format);
176         $page->blocks->load_blocks();
177         $blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region());
178         $block = end($blocks);
179         $block = block_instance('html', $block->instance);
180         $nonscalar = [
181             'something' => true,
182         ];
183         $configdata = (object) [
184             'title' => $title,
185             'text' => [
186                 'itemid' => 0,
187                 'text' => $body,
188                 'format' => $bodyformat,
189             ],
190             'nonscalar' => $nonscalar
191         ];
192         $block->instance_config_save((object) $configdata);
193         $filename = 'img.png';
194         $filerecord = array(
195             'contextid' => context_block::instance($block->instance->id)->id,
196             'component' => 'block_html',
197             'filearea' => 'content',
198             'itemid' => 0,
199             'filepath' => '/',
200             'filename' => $filename,
201         );
202         // Create an area to upload the file.
203         $fs = get_file_storage();
204         // Create a file from the string that we made earlier.
205         $file = $fs->create_file_from_string($filerecord, 'some fake content (should be an image).');
207         // Check for the new block.
208         $result = core_block_external::get_course_blocks($course->id, true);
209         // We need to execute the return values cleaning process to simulate the web service server.
210         $result = external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result);
212         // Expect the new block.
213         $this->assertCount(1, $result['blocks']);
214         $this->assertEquals($title, $result['blocks'][0]['contents']['title']);
215         $this->assertEquals($body, $result['blocks'][0]['contents']['content']);
216         $this->assertEquals(FORMAT_HTML, $result['blocks'][0]['contents']['contentformat']);    // Format change for external.
217         $this->assertEquals('', $result['blocks'][0]['contents']['footer']);
218         $this->assertCount(1, $result['blocks'][0]['contents']['files']);
219         $this->assertEquals($newblock, $result['blocks'][0]['name']);
220         $configcounts = 0;
221         foreach ($result['blocks'][0]['configs'] as $config) {
222             if ($config['type'] = 'plugin' && $config['name'] == 'allowcssclasses' && $config['value'] == json_encode('0')) {
223                 $configcounts++;
224             } else if ($config['type'] = 'instance' && $config['name'] == 'text' && $config['value'] == json_encode($body)) {
225                 $configcounts++;
226             } else if ($config['type'] = 'instance' && $config['name'] == 'title' && $config['value'] == json_encode($title)) {
227                 $configcounts++;
228             } else if ($config['type'] = 'instance' && $config['name'] == 'format' && $config['value'] == json_encode('0')) {
229                 $configcounts++;
230             } else if ($config['type'] = 'instance' && $config['name'] == 'nonscalar' &&
231                     $config['value'] == json_encode($nonscalar)) {
232                 $configcounts++;
233             }
234         }
235         $this->assertEquals(5, $configcounts);
236     }
238     /**
239      * Test user get default dashboard blocks.
240      */
241     public function test_get_dashboard_blocks_default_dashboard() {
242         global $PAGE, $DB;
243         $this->resetAfterTest(true);
245         $user = $this->getDataGenerator()->create_user();
246         $PAGE->set_url('/my/index.php');    // Need this because some internal API calls require the $PAGE url to be set.
248         // Force a setting change to check the returned blocks settings.
249         set_config('displaycategories', 0, 'block_recentlyaccessedcourses');
251         // Get the expected default blocks.
252         $alldefaultblocksordered = $DB->get_records_menu('block_instances',
253             array('pagetypepattern' => 'my-index'), 'defaultregion, defaultweight ASC', 'id, blockname');
255         $this->setUser($user);
257         // Check for the default blocks.
258         $result = core_block_external::get_dashboard_blocks($user->id);
259         // We need to execute the return values cleaning process to simulate the web service server.
260         $result = external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result);
261         // Expect all blogs except learning plans one (no learning plans to show).
262         $this->assertCount(count($alldefaultblocksordered) - 1, $result['blocks']);
263         $returnedblocks = array();
264         foreach ($result['blocks'] as $block) {
265             // Check all the returned blocks are in the expected blocks array.
266             $this->assertContains($block['name'], $alldefaultblocksordered);
267             $returnedblocks[] = $block['name'];
268             // Check the configuration returned for this default block.
269             if ($block['name'] == 'recentlyaccessedcourses') {
270                 $this->assertEquals('displaycategories', $block['configs'][0]['name']);
271                 $this->assertEquals(json_encode('0'), $block['configs'][0]['value']);
272                 $this->assertEquals('plugin', $block['configs'][0]['type']);
273             }
274         }
275         // Remove lp block.
276         array_shift($alldefaultblocksordered);
277         // Check that we received the blocks in the expected order.
278         $this->assertEquals(array_values($alldefaultblocksordered), $returnedblocks);
279     }
281     /**
282      * Test user get default dashboard blocks including a sticky block.
283      */
284     public function test_get_dashboard_blocks_default_dashboard_including_sticky_block() {
285         global $PAGE, $DB;
286         $this->resetAfterTest(true);
288         $user = $this->getDataGenerator()->create_user();
289         $PAGE->set_url('/my/index.php');    // Need this because some internal API calls require the $PAGE url to be set.
291         // Get the expected default blocks.
292         $alldefaultblocks = $DB->get_records_menu('block_instances', array('pagetypepattern' => 'my-index'), '', 'id, blockname');
294         // Now, add a sticky block.
295         $page = new moodle_page();
296         $page->set_context(context_system::instance());
297         $page->set_pagetype('my-index');
298         $page->set_url(new moodle_url('/'));
299         $page->blocks->add_region('side-pre');
300         $page->blocks->load_blocks();
301         $page->blocks->add_block('myprofile', 'side-pre', 0, true, '*');
303         $this->setUser($user);
305         // Check for the default blocks plus the sticky.
306         $result = core_block_external::get_dashboard_blocks($user->id);
307         // We need to execute the return values cleaning process to simulate the web service server.
308         $result = external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result);
309         // Expect all blogs plus sticky one except learning plans one (no learning plans to show).
310         $this->assertCount(count($alldefaultblocks), $result['blocks']);
311         $found = false;
312         foreach ($result['blocks'] as $block) {
313             if ($block['name'] == 'myprofile') {
314                 $this->assertEquals('side-pre', $block['region']);
315                 $found = true;
316                 continue;
317             }
318             // Check that the block is in the expected blocks array.
319             $this->assertContains($block['name'], $alldefaultblocks);
320         }
321         $this->assertTrue($found);
322     }
324     /**
325      * Test admin get user's custom dashboard blocks.
326      */
327     public function test_get_dashboard_blocks_custom_user_dashboard() {
328         global $PAGE, $DB;
329         $this->resetAfterTest(true);
331         $user = $this->getDataGenerator()->create_user();
332         $PAGE->set_url('/my/index.php');    // Need this because some internal API calls require the $PAGE url to be set.
334         // Get the expected default blocks.
335         $alldefaultblocks = $DB->get_records_menu('block_instances', array('pagetypepattern' => 'my-index'), '', 'id, blockname');
337         // Add a custom block.
338         $page = new moodle_page();
339         $page->set_context(context_user::instance($user->id));
340         $page->set_pagelayout('mydashboard');
341         $page->set_pagetype('my-index');
342         $page->blocks->add_region('content');
343         $currentpage = my_get_page($user->id, MY_PAGE_PRIVATE);
344         $page->set_subpage($currentpage->id);
345         $page->blocks->load_blocks();
346         $page->blocks->add_block('myprofile', 'content', 0, false);
348         $this->setAdminUser();
350         // Check for the new block as admin for a user.
351         $result = core_block_external::get_dashboard_blocks($user->id);
352         // We need to execute the return values cleaning process to simulate the web service server.
353         $result = external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result);
354         // Expect all default blogs plys the one we added except learning plans one (no learning plans to show).
355         $this->assertCount(count($alldefaultblocks), $result['blocks']);
356         $found = false;
357         foreach ($result['blocks'] as $block) {
358             if ($block['name'] == 'myprofile') {
359                 $this->assertEquals('content', $block['region']);
360                 $found = true;
361                 continue;
362             }
363             // Check that the block is in the expected blocks array.
364             $this->assertContains($block['name'], $alldefaultblocks);
365         }
366         $this->assertTrue($found);
367     }
369     /**
370      * Test user tries to get other user blocks not having permission.
371      */
372     public function test_get_dashboard_blocks_other_user_missing_permissions() {
373         $this->resetAfterTest(true);
375         $user1 = $this->getDataGenerator()->create_user();
376         $user2 = $this->getDataGenerator()->create_user();
378         $this->setUser($user1);
380         $this->expectException('moodle_exception');
381         core_block_external::get_dashboard_blocks($user2->id);
382     }