Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace core_courseformat;
18
 
19
use stdClass;
20
 
21
/**
22
 * Tests for the stateupdates class.
23
 *
24
 * @package    core_courseformat
25
 * @category   test
26
 * @copyright  2021 Sara Arjona (sara@moodle.com)
27
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28
 * @coversDefaultClass \core_courseformat\stateupdates
29
 */
30
class stateupdates_test extends \advanced_testcase {
31
 
32
    /**
33
     * Test for add_course_put.
34
     *
35
     * @dataProvider add_course_put_provider
36
     * @covers ::add_course_put
37
     *
38
     * @param string $role the user role in the course
39
     */
40
    public function test_add_course_put(string $role): void {
41
        global $PAGE;
42
 
43
        $this->resetAfterTest();
44
 
45
        $course = $this->getDataGenerator()->create_course(['format' => 'topics']);
46
 
47
        // Create and enrol user using given role.
48
        if ($role == 'admin') {
49
            $this->setAdminUser();
50
        } else {
51
            $user = $this->getDataGenerator()->create_user();
52
            if ($role != 'unenroled') {
53
                $this->getDataGenerator()->enrol_user($user->id, $course->id, $role);
54
            }
55
            $this->setUser($user);
56
        }
57
 
58
        // Initialise stateupdates.
59
        $format = course_get_format($course);
60
        $updates = new stateupdates($format);
61
 
62
        // Get the expected export.
63
        $renderer = $format->get_renderer($PAGE);
64
        $stateclass = $format->get_output_classname("state\\course");
65
        $currentstate = new $stateclass($format);
66
        $expected = $currentstate->export_for_template($renderer);
67
 
68
        $updates->add_course_put();
69
 
70
        $updatelist = $updates->jsonSerialize();
71
        $this->assertCount(1, $updatelist);
72
 
73
        $update = array_pop($updatelist);
74
        $this->assertEquals('put', $update->action);
75
        $this->assertEquals('course', $update->name);
76
        $this->assertEquals($expected, $update->fields);
77
    }
78
 
79
    /**
80
     * Data provider for test_add_course_put.
81
     *
82
     * @return array testing scenarios
83
     */
84
    public function add_course_put_provider() {
85
        return [
86
            'Admin role' => [
87
                'admin',
88
            ],
89
            'Teacher role' => [
90
                'editingteacher',
91
            ],
92
            'Student role' => [
93
                'student',
94
            ],
95
        ];
96
    }
97
 
98
    /**
99
     * Helper methods to find a specific update in the updadelist.
100
     *
101
     * @param array $updatelist the update list
102
     * @param string $action the action to find
103
     * @param string $name the element name to find
104
     * @param int $identifier the element id value
105
     * @return stdClass|null the object found, if any.
106
     */
107
    private function find_update(
108
        array $updatelist,
109
        string $action,
110
        string $name,
111
        int $identifier
112
    ): ?stdClass {
113
        foreach ($updatelist as $update) {
114
            if ($update->action != $action || $update->name != $name) {
115
                continue;
116
            }
117
            if (!isset($update->fields->id)) {
118
                continue;
119
            }
120
            if ($update->fields->id == $identifier) {
121
                return $update;
122
            }
123
        }
124
        return null;
125
    }
126
 
127
    /**
128
     * Add track about a section state update.
129
     *
130
     * @dataProvider add_section_provider
131
     * @covers ::add_section_create
132
     * @covers ::add_section_remove
133
     * @covers ::add_section_put
134
     *
135
     * @param string $action the action name
136
     * @param string $role the user role name
137
     * @param array $expected the expected results
138
     */
139
    public function test_add_section(string $action, string $role, array $expected): void {
140
        global $PAGE, $DB;
141
 
142
        $this->resetAfterTest();
143
 
144
        $course = $this->getDataGenerator()->create_course(['numsections' => 2, 'format' => 'topics']);
145
 
146
        // Set section 2 hidden.
147
        set_section_visible($course->id, 2, 0);
148
 
149
        // Create and enrol user using given role.
150
        if ($role == 'admin') {
151
            $this->setAdminUser();
152
        } else {
153
            $user = $this->getDataGenerator()->create_user();
154
            if ($role != 'unenroled') {
155
                $this->getDataGenerator()->enrol_user($user->id, $course->id, $role);
156
            }
157
            $this->setUser($user);
158
        }
159
 
160
        // Initialise stateupdates.
161
        $format = course_get_format($course);
162
        $updates = new stateupdates($format);
163
 
164
        $modinfo = $format->get_modinfo();
165
 
166
        // Get the expected export.
167
        $renderer = $format->get_renderer($PAGE);
168
        $stateclass = $format->get_output_classname("state\\section");
169
 
170
        // Execute method for both sections.
171
        $method = "add_section_{$action}";
172
        $sections = $modinfo->get_section_info_all();
173
        foreach ($sections as $section) {
174
            $updates->$method($section->id);
175
        }
176
 
177
        $updatelist = $updates->jsonSerialize();
178
        $this->assertCount(count($expected), $updatelist);
179
 
180
        foreach ($expected as $sectionnum) {
181
            $section = $sections[$sectionnum];
182
            $currentstate = new $stateclass($format, $section);
183
            $expected = $currentstate->export_for_template($renderer);
184
 
185
            $update = $this->find_update($updatelist, $action, 'section', $section->id);
186
            $this->assertEquals($action, $update->action);
187
            $this->assertEquals('section', $update->name);
188
            // Delete does not provide all fields.
189
            if ($action == 'remove') {
190
                $this->assertEquals($section->id, $update->fields->id);
191
            } else {
192
                $this->assertEquals($expected, $update->fields);
193
            }
194
        }
195
    }
196
 
197
    /**
198
     * Data provider for test_add_section.
199
     *
200
     * @return array testing scenarios
201
     */
202
    public function add_section_provider(): array {
203
        return array_merge(
204
            $this->add_section_provider_helper('put'),
205
            $this->add_section_provider_helper('create'),
206
            $this->add_section_provider_helper('remove'),
207
        );
208
    }
209
 
210
    /**
211
     * Helper for add_section_provider scenarios.
212
     *
213
     * @param string $action the action to perform
214
     * @return array testing scenarios
215
     */
216
    private function add_section_provider_helper(string $action): array {
217
        // Delete does not depends on user permissions.
218
        if ($action == 'remove') {
219
            $studentsections = [0, 1, 2];
220
        } else {
221
            $studentsections = [0, 1];
222
        }
223
 
224
        return [
225
            "$action admin role" => [
226
                'action' => $action,
227
                'role' => 'admin',
228
                'expected' => [0, 1, 2],
229
            ],
230
            "$action teacher role" => [
231
                'action' => $action,
232
                'role' => 'editingteacher',
233
                'expected' => [0, 1, 2],
234
            ],
235
            "$action student role" => [
236
                'action' => $action,
237
                'role' => 'student',
238
                'expected' => $studentsections,
239
            ],
240
        ];
241
    }
242
 
243
 
244
    /**
245
     * Add track about a course module state update.
246
     *
247
     * @dataProvider add_cm_provider
248
     * @covers ::add_cm_put
249
     * @covers ::add_cm_create
250
     * @covers ::add_cm_remove
251
     *
252
     * @param string $action the action name
253
     * @param string $role the user role name
254
     * @param array $expected the expected results
255
     */
256
    public function test_add_cm(string $action, string $role, array $expected): void {
257
        global $PAGE, $DB;
258
 
259
        $this->resetAfterTest();
260
 
261
        $course = $this->getDataGenerator()->create_course(['numsections' => 2, 'format' => 'topics']);
262
 
263
        // Set section 2 hidden.
264
        set_section_visible($course->id, 2, 0);
265
 
266
        // Create 2 activities on each section.
267
        $activities = [];
268
        $activities[] = $this->getDataGenerator()->create_module(
269
            'book',
270
            ['course' => $course->id],
271
            ['section' => 1, 'visible' => true]
272
        );
273
        $activities[] = $this->getDataGenerator()->create_module(
274
            'book',
275
            ['course' => $course->id],
276
            ['section' => 1, 'visible' => false]
277
        );
278
        $activities[] = $this->getDataGenerator()->create_module(
279
            'book',
280
            ['course' => $course->id],
281
            ['section' => 2, 'visible' => true]
282
        );
283
        $activities[] = $this->getDataGenerator()->create_module(
284
            'book',
285
            ['course' => $course->id],
286
            ['section' => 2, 'visible' => false]
287
        );
288
 
289
        // Create and enrol user using given role.
290
        if ($role == 'admin') {
291
            $this->setAdminUser();
292
        } else {
293
            $user = $this->getDataGenerator()->create_user();
294
            if ($role != 'unenroled') {
295
                $this->getDataGenerator()->enrol_user($user->id, $course->id, $role);
296
            }
297
            $this->setUser($user);
298
        }
299
 
300
        // Initialise stateupdates.
301
        $format = course_get_format($course);
302
        $updates = new stateupdates($format);
303
 
304
        $modinfo = $format->get_modinfo();
305
 
306
        // Get the expected export.
307
        $renderer = $format->get_renderer($PAGE);
308
        $stateclass = $format->get_output_classname("state\\cm");
309
 
310
        // Execute method for both sections.
311
        $method = "add_cm_{$action}";
312
 
313
        foreach ($activities as $activity) {
314
            $updates->$method($activity->cmid);
315
        }
316
 
317
        $updatelist = $updates->jsonSerialize();
318
        $this->assertCount(count($expected), $updatelist);
319
 
320
        foreach ($expected as $cmnum) {
321
            $activity = $activities[$cmnum];
322
 
323
            $cm = $modinfo->get_cm($activity->cmid);
324
            $section = $modinfo->get_section_info($cm->sectionnum);
325
 
326
            $currentstate = new $stateclass($format, $section, $cm);
327
            $expected = $currentstate->export_for_template($renderer);
328
 
329
            $update = $this->find_update($updatelist, $action, 'cm', $cm->id);
330
            $this->assertEquals($action, $update->action);
331
            $this->assertEquals('cm', $update->name);
332
            // Delete does not provide all fields.
333
            if ($action == 'remove') {
334
                $this->assertEquals($cm->id, $update->fields->id);
335
            } else {
336
                $this->assertEquals($expected, $update->fields);
337
            }
338
        }
339
    }
340
 
341
    /**
342
     * Data provider for test_add_cm.
343
     *
344
     * @return array testing scenarios
345
     */
346
    public function add_cm_provider(): array {
347
        return array_merge(
348
            $this->add_cm_provider_helper('put'),
349
            $this->add_cm_provider_helper('create'),
350
            $this->add_cm_provider_helper('remove'),
351
        );
352
    }
353
 
354
    /**
355
     * Helper for add_cm_provider scenarios.
356
     *
357
     * @param string $action the action to perform
358
     * @return array testing scenarios
359
     */
360
    private function add_cm_provider_helper(string $action): array {
361
        // Delete does not depends on user permissions.
362
        if ($action == 'remove') {
363
            $studentcms = [0, 1, 2, 3];
364
        } else {
365
            $studentcms = [0];
366
        }
367
 
368
        return [
369
            "$action admin role" => [
370
                'action' => $action,
371
                'role' => 'admin',
372
                'expected' => [0, 1, 2, 3],
373
            ],
374
            "$action teacher role" => [
375
                'action' => $action,
376
                'role' => 'editingteacher',
377
                'expected' => [0, 1, 2, 3],
378
            ],
379
            "$action student role" => [
380
                'action' => $action,
381
                'role' => 'student',
382
                'expected' => $studentcms,
383
            ],
384
        ];
385
    }
386
 
387
    /**
388
     * Test components can add data to delegated section state updates.
389
     * @covers ::add_section_put
390
     */
391
    public function test_put_section_state_extra_updates(): void {
392
        global $DB, $CFG;
393
        $this->resetAfterTest();
394
 
395
        require_once($CFG->libdir . '/tests/fixtures/sectiondelegatetest.php');
396
 
397
        $course = $this->getDataGenerator()->create_course();
398
        $activity = $this->getDataGenerator()->create_module(
399
            'assign',
400
            ['course' => $course->id]
401
        );
402
 
403
        // The test component section delegate will add the activity cm info into the state.
404
        $section = formatactions::section($course)->create_delegated('test_component', $activity->cmid);
405
 
406
        $format = course_get_format($course);
407
        $updates = new \core_courseformat\stateupdates($format);
408
 
409
        $updates->add_section_put($section->id);
410
 
411
        $data = $updates->jsonSerialize();
412
 
413
        $this->assertCount(2, $data);
414
 
415
        $sectiondata = $data[0];
416
        $this->assertEquals('section', $sectiondata->name);
417
        $this->assertEquals('put', $sectiondata->action);
418
        $this->assertEquals($section->id, $sectiondata->fields->id);
419
 
420
        $cmdata = $data[1];
421
        $this->assertEquals('cm', $cmdata->name);
422
        $this->assertEquals('put', $cmdata->action);
423
        $this->assertEquals($activity->cmid, $cmdata->fields->id);
424
    }
425
}