Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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\external;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
global $CFG;
22
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
23
 
24
use core_external\external_api;
25
 
26
/**
27
 * Tests for the get_state class.
28
 *
29
 * @package    core_course
30
 * @category   test
31
 * @copyright  2021 Sara Arjona (sara@moodle.com)
32
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 * @coversDefaultClass \core_courseformat\external\get_state
34
 */
1441 ariadna 35
final class get_state_test extends \externallib_advanced_testcase {
1 efrain 36
 
37
    /** @var array Sections in the testing course. */
38
    private $sections;
39
 
40
    /** @var array Activities in the testing course. */
41
    private $activities;
42
 
43
    /**
44
     * Setup to ensure that fixtures are loaded.
45
     */
46
    public static function setupBeforeClass(): void {
47
        global $CFG;
48
 
49
        require_once($CFG->dirroot . '/course/lib.php');
50
        require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest.php');
51
        require_once($CFG->dirroot . '/course/format/tests/fixtures/format_theunittest_output_course_format_state.php');
52
    }
53
 
54
    /**
55
     * Setup testcase.
56
     */
57
    public function setUp(): void {
1441 ariadna 58
        parent::setUp();
1 efrain 59
        $this->resetAfterTest();
60
 
61
        $this->sections = [];
62
        $this->activities = [];
63
    }
64
 
65
    /**
66
     * Test tearDown.
67
     */
68
    public function tearDown(): void {
69
        unset($this->sections);
70
        unset($this->activities);
1441 ariadna 71
        parent::tearDown();
1 efrain 72
    }
73
 
74
    /**
75
     * Test the behaviour of get_state::execute().
76
     *
77
     * @dataProvider get_state_provider
78
     * @covers ::execute
79
     *
80
     * @param string $role The role of the user that will execute the method.
81
     * @param string $format The course format of the course where the method will be executed.
82
     * @param string|null $expectedexception If this call will raise an exception, this is its name.
83
     */
84
    public function test_get_state(string $role, string $format = 'topics', ?string $expectedexception = null): void {
85
        $this->resetAfterTest();
86
 
87
        // Create a course.
88
        $numsections = 6;
1441 ariadna 89
 
1 efrain 90
        $course = $this->getDataGenerator()->create_course(['numsections' => $numsections, 'format' => $format]);
91
        $hiddensections = [4, 6];
92
        foreach ($hiddensections as $section) {
93
            set_section_visible($course->id, $section, 0);
94
        }
95
 
96
        // Create and enrol user.
97
        $isadmin = ($role == 'admin');
98
        $canedit = $isadmin || ($role == 'editingteacher');
99
        if ($isadmin) {
100
            $this->setAdminUser();
101
        } else {
102
            $user = $this->getDataGenerator()->create_user();
103
            if ($role != 'unenroled') {
104
                $this->getDataGenerator()->enrol_user($user->id, $course->id, $role);
105
            }
106
            $this->setUser($user);
107
        }
1441 ariadna 108
        $visiblesections = $numsections + 1; // We include topic 0.
109
        if (!$canedit) {
110
            // User won't see the hidden sections. Remove them from the total.
111
            $visiblesections = $visiblesections - count($hiddensections);
112
        }
113
        if ($format == 'social') {
114
            $visiblesections = 1; // But Social format has one section visible.
115
        }
1 efrain 116
 
117
        // Social course format automatically creates a forum activity.
118
        if (course_get_format($course)->get_format() === 'social') {
119
            $cms = get_fast_modinfo($course)->get_cms();
120
 
121
            // Let's add this assertion just to ensure course format has only one activity.
122
            $this->assertCount(1, $cms);
123
            $activitycm = reset($cms);
124
 
125
            // And that activity is a forum.
126
            $this->assertEquals('forum', $activitycm->modname);
127
 
128
            // Assign the activity cm to the activities array.
129
            $this->activities[$activitycm->id] = $activitycm;
130
        } else {
131
            // Add some activities to the course.
1441 ariadna 132
            $this->create_activity($course->id, 'qbank', 0, true, $canedit);
1 efrain 133
            $this->create_activity($course->id, 'page', 1, true, $canedit);
134
            $this->create_activity($course->id, 'forum', 1, true, $canedit);
135
            $this->create_activity($course->id, 'book', 1, false, $canedit);
136
            $this->create_activity($course->id, 'assign', 2, false, $canedit);
137
            $this->create_activity($course->id, 'glossary', 4, true, $canedit);
138
            $this->create_activity($course->id, 'label', 5, false, $canedit);
139
            $this->create_activity($course->id, 'feedback', 5, true, $canedit);
140
        }
141
 
142
        if ($expectedexception) {
143
            $this->expectException($expectedexception);
144
        }
145
 
146
        // Get course state.
147
        $result = get_state::execute($course->id);
148
        $result = external_api::clean_returnvalue(get_state::execute_returns(), $result);
149
        $result = json_decode($result);
150
        if ($format == 'theunittest') {
151
            // These course format's hasn't the renderer file, so a debugging message will be displayed.
152
            $this->assertDebuggingCalled();
153
        }
154
 
155
        // Check course information.
156
        $this->assertEquals($numsections, $result->course->numsections);
157
        $this->assertCount($visiblesections, $result->section);
158
        $this->assertCount(count($this->activities), $result->cm);
159
        $this->assertCount(count($result->course->sectionlist), $result->section);
160
        if ($format == 'theunittest') {
161
            $this->assertTrue(property_exists($result->course, 'newfancyelement'));
162
        } else {
163
            $this->assertFalse(property_exists($result->course, 'newfancyelement'));
164
        }
165
 
166
        // Check sections information.
167
        foreach ($result->section as $section) {
168
            if (in_array($section->number, $hiddensections)) {
169
                $this->assertFalse($section->visible);
170
            } else {
171
                $this->assertTrue($section->visible);
172
            }
173
            // Check section is defined in course->sectionlist.
174
            $this->assertContains($section->id, $result->course->sectionlist);
175
            // Check course modules list for this section is the expected.
176
            if (array_key_exists($section->number, $this->sections)) {
177
                $this->assertEquals($this->sections[$section->number], $section->cmlist);
178
            }
179
        }
1441 ariadna 180
        // Check course modules information,
181
        // must not contain modules that cannot be displayed to the course page under any circumstances.
1 efrain 182
        foreach ($result->cm as $cm) {
183
            $this->assertEquals($this->activities[$cm->id]->name, $cm->name);
184
            $this->assertEquals((bool) $this->activities[$cm->id]->visible, $cm->visible);
1441 ariadna 185
            $this->assertNotEquals('qbank', $this->activities[$cm->id]->modname);
1 efrain 186
        }
187
    }
188
 
189
    /**
190
     * Data provider for test_get_state().
191
     *
192
     * @return array
193
     */
1441 ariadna 194
    public static function get_state_provider(): array {
1 efrain 195
        return [
196
            // ROLES. Testing behaviour depending on the user role calling the method.
197
            'Admin user should work' => [
198
                'role' => 'admin',
199
            ],
200
            'Editing teacher should work' => [
201
                'role' => 'editingteacher',
202
            ],
203
            'Student should work' => [
204
                'role' => 'student',
205
            ],
206
            'Unenroled user should raise an exception' => [
207
                'role' => 'unenroled',
208
                'format' => 'topics',
209
                'expectedexception' => 'moodle_exception',
210
            ],
211
 
212
            // COURSEFORMAT. Test behaviour depending on course formats.
213
            'Single activity format should work (admin)' => [
214
                'role' => 'admin',
215
                'format' => 'singleactivity',
216
            ],
217
            'Social format should work (admin)' => [
218
                'role' => 'admin',
219
                'format' => 'social',
220
            ],
221
            'Weeks format should work (admin)' => [
222
                'role' => 'admin',
223
                'format' => 'weeks',
224
            ],
225
            'The unit tests format should work (admin)' => [
226
                'role' => 'admin',
227
                'format' => 'theunittest',
228
            ],
229
            'Single activity format should work (student)' => [
230
                'role' => 'student',
231
                'format' => 'singleactivity',
232
            ],
233
            'Social format should work (student)' => [
234
                'role' => 'student',
235
                'format' => 'social',
236
            ],
237
            'Weeks format should work (student)' => [
238
                'role' => 'student',
239
                'format' => 'weeks',
240
            ],
241
            'The unit tests format should work (student)' => [
242
                'role' => 'student',
243
                'format' => 'theunittest',
244
            ],
245
            'Single activity format should raise an exception (unenroled)' => [
246
                'role' => 'unenroled',
247
                'format' => 'singleactivity',
248
                'expectedexception' => 'moodle_exception',
249
            ],
250
            'Social format should raise an exception (unenroled)' => [
251
                'role' => 'unenroled',
252
                'format' => 'social',
253
                'expectedexception' => 'moodle_exception',
254
            ],
255
            'Weeks format should raise an exception (unenroled)' => [
256
                'role' => 'unenroled',
257
                'format' => 'weeks',
258
                'expectedexception' => 'moodle_exception',
259
            ],
260
            'The unit tests format should raise an exception (unenroled)' => [
261
                'role' => 'unenroled',
262
                'format' => 'theunittest',
263
                'expectedexception' => 'moodle_exception',
264
            ],
265
        ];
266
    }
267
 
268
    /**
269
     * Helper method to create an activity into a section and add it to the $sections and $activities arrays.
270
     * For non-admin users, only visible activities will be added to the activities and sections arrays.
271
     *
272
     * @param int $courseid Course identifier where the activity will be added.
273
     * @param string $type Activity type ('forum', 'assign', ...).
274
     * @param int $section Section number where the activity will be added.
275
     * @param bool $visible Whether the activity will be visible or not.
276
     * @param bool $canedit Whether the activity will be accessed later by a user with editing capabilities
277
     */
278
    private function create_activity(int $courseid, string $type, int $section, bool $visible = true, bool $canedit = true): void {
279
        $activity = $this->getDataGenerator()->create_module(
280
            $type,
281
            ['course' => $courseid],
282
            ['section' => $section, 'visible' => $visible]
283
        );
284
 
285
        list(, $activitycm) = get_course_and_cm_from_instance($activity->id, $type);
286
 
1441 ariadna 287
        if (($visible || $canedit) && $activitycm->is_of_type_that_can_display()) {
1 efrain 288
            $this->activities[$activitycm->id] = $activitycm;
289
            $this->sections[$section][] = $activitycm->id;
290
        }
291
    }
292
}