Proyectos de Subversion Moodle

Rev

Rev 11 | | 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_user;
18
 
19
/**
20
 * Unit tests for user/profile/lib.php.
21
 *
22
 * @package core_user
23
 * @copyright 2014 The Open University
24
 * @licensehttp://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
1441 ariadna 26
final class profilelib_test extends \advanced_testcase {
1 efrain 27
 
28
    /**
29
     * Load required test libraries
30
     */
31
    public static function setUpBeforeClass(): void {
32
        global $CFG;
33
        require_once("{$CFG->dirroot}/user/profile/lib.php");
1441 ariadna 34
        parent::setUpBeforeClass();
1 efrain 35
    }
36
 
37
    /**
38
     * Tests profile_get_custom_fields function and checks it is consistent
39
     * with profile_user_record.
40
     */
11 efrain 41
    public function test_get_custom_fields(): void {
1 efrain 42
        $this->resetAfterTest();
43
        $user = $this->getDataGenerator()->create_user();
44
 
45
        // Add a custom field of textarea type.
46
        $id1 = $this->getDataGenerator()->create_custom_profile_field([
47
                'shortname' => 'frogdesc', 'name' => 'Description of frog',
48
                'datatype' => 'textarea'])->id;
49
 
50
        // Check the field is returned.
51
        $result = profile_get_custom_fields();
52
        $this->assertArrayHasKey($id1, $result);
53
        $this->assertEquals('frogdesc', $result[$id1]->shortname);
54
 
55
        // Textarea types are not included in user data though, so if we
56
        // use the 'only in user data' parameter, there is still nothing.
57
        $this->assertArrayNotHasKey($id1, profile_get_custom_fields(true));
58
 
59
        // Check that profile_user_record returns same (no) fields.
60
        $this->assertObjectNotHasProperty('frogdesc', profile_user_record($user->id));
61
 
62
        // Check that profile_user_record returns all the fields when requested.
63
        $this->assertObjectHasProperty('frogdesc', profile_user_record($user->id, false));
64
 
65
        // Add another custom field, this time of normal text type.
66
        $id2 = $this->getDataGenerator()->create_custom_profile_field(array(
67
                'shortname' => 'frogname', 'name' => 'Name of frog',
68
                'datatype' => 'text'))->id;
69
 
70
        // Check both are returned using normal option.
71
        $result = profile_get_custom_fields();
72
        $this->assertArrayHasKey($id2, $result);
73
        $this->assertEquals('frogname', $result[$id2]->shortname);
74
 
75
        // And check that only the one is returned the other way.
76
        $this->assertArrayHasKey($id2, profile_get_custom_fields(true));
77
 
78
        // Check profile_user_record returns same field.
79
        $this->assertObjectHasProperty('frogname', profile_user_record($user->id));
80
 
81
        // Check that profile_user_record returns all the fields when requested.
82
        $this->assertObjectHasProperty('frogname', profile_user_record($user->id, false));
83
    }
84
 
85
    /**
86
     * Make sure that all profile fields can be initialised without arguments.
87
     */
11 efrain 88
    public function test_default_constructor(): void {
1 efrain 89
        global $DB, $CFG;
90
        require_once($CFG->dirroot . '/user/profile/definelib.php');
91
        $datatypes = profile_list_datatypes();
92
        foreach ($datatypes as $datatype => $datatypename) {
93
            require_once($CFG->dirroot . '/user/profile/field/' .
94
                $datatype . '/field.class.php');
95
            $newfield = 'profile_field_' . $datatype;
96
            $formfield = new $newfield();
97
            $this->assertNotNull($formfield);
98
        }
99
    }
100
 
101
    /**
102
     * Test profile_view function
103
     */
11 efrain 104
    public function test_profile_view(): void {
1 efrain 105
        global $USER;
106
 
107
        $this->resetAfterTest();
108
 
109
        // Course without sections.
110
        $course = $this->getDataGenerator()->create_course();
111
        $context = \context_course::instance($course->id);
112
        $user = $this->getDataGenerator()->create_user();
113
        $usercontext = \context_user::instance($user->id);
114
 
115
        $this->setUser($user);
116
 
117
        // Redirect events to the sink, so we can recover them later.
118
        $sink = $this->redirectEvents();
119
 
120
        profile_view($user, $context, $course);
121
        $events = $sink->get_events();
122
        $event = reset($events);
123
 
124
        // Check the event details are correct.
125
        $this->assertInstanceOf('\core\event\user_profile_viewed', $event);
126
        $this->assertEquals($context, $event->get_context());
127
        $this->assertEquals($user->id, $event->relateduserid);
128
        $this->assertEquals($course->id, $event->other['courseid']);
129
        $this->assertEquals($course->shortname, $event->other['courseshortname']);
130
        $this->assertEquals($course->fullname, $event->other['coursefullname']);
131
 
132
        profile_view($user, $usercontext);
133
        $events = $sink->get_events();
134
        $event = array_pop($events);
135
        $sink->close();
136
 
137
        $this->assertInstanceOf('\core\event\user_profile_viewed', $event);
138
        $this->assertEquals($usercontext, $event->get_context());
139
        $this->assertEquals($user->id, $event->relateduserid);
140
 
141
    }
142
 
143
    /**
144
     * Test that {@link user_not_fully_set_up()} takes required custom fields into account.
145
     */
11 efrain 146
    public function test_profile_has_required_custom_fields_set(): void {
1 efrain 147
        global $CFG;
148
        require_once($CFG->dirroot.'/mnet/lib.php');
149
 
150
        $this->resetAfterTest();
151
 
152
        // Add a required, visible, unlocked custom field.
153
        $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'house', 'name' => 'House', 'required' => 1,
154
            'visible' => 1, 'locked' => 0, 'datatype' => 'text']);
155
 
156
        // Add an optional, visible, unlocked custom field.
157
        $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'pet', 'name' => 'Pet', 'required' => 0,
158
            'visible' => 1, 'locked' => 0, 'datatype' => 'text']);
159
 
160
        // Add required but invisible custom field.
161
        $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'secretid', 'name' => 'Secret ID',
162
            'required' => 1, 'visible' => 0, 'locked' => 0, 'datatype' => 'text']);
163
 
164
        // Add required but locked custom field.
165
        $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'muggleborn', 'name' => 'Muggle-born',
166
            'required' => 1, 'visible' => 1, 'locked' => 1, 'datatype' => 'checkbox']);
167
 
168
        // Create some student accounts.
169
        $hermione = $this->getDataGenerator()->create_user();
170
        $harry = $this->getDataGenerator()->create_user();
171
        $ron = $this->getDataGenerator()->create_user();
172
        $draco = $this->getDataGenerator()->create_user();
173
 
174
        // Hermione has all available custom fields filled (of course she has).
175
        profile_save_data((object)['id' => $hermione->id, 'profile_field_house' => 'Gryffindor']);
176
        profile_save_data((object)['id' => $hermione->id, 'profile_field_pet' => 'Crookshanks']);
177
 
178
        // Harry has only the optional field filled.
179
        profile_save_data((object)['id' => $harry->id, 'profile_field_pet' => 'Hedwig']);
180
 
181
        // Draco has only the required field filled.
182
        profile_save_data((object)['id' => $draco->id, 'profile_field_house' => 'Slytherin']);
183
 
184
        // Only students with required fields filled should be considered as fully set up in the default (strict) mode.
185
        $this->assertFalse(user_not_fully_set_up($hermione));
186
        $this->assertFalse(user_not_fully_set_up($draco));
187
        $this->assertTrue(user_not_fully_set_up($harry));
188
        $this->assertTrue(user_not_fully_set_up($ron));
189
 
190
        // In the lax mode, students do not need to have required fields filled.
191
        $this->assertFalse(user_not_fully_set_up($hermione, false));
192
        $this->assertFalse(user_not_fully_set_up($draco, false));
193
        $this->assertFalse(user_not_fully_set_up($harry, false));
194
        $this->assertFalse(user_not_fully_set_up($ron, false));
195
 
196
        // Lack of required core field is seen as a problem in either mode.
197
        unset($hermione->email);
198
        $this->assertTrue(user_not_fully_set_up($hermione, true));
199
        $this->assertTrue(user_not_fully_set_up($hermione, false));
200
 
201
        // When confirming remote MNet users, we do not have custom fields available.
202
        $roamingharry = mnet_strip_user($harry, ['firstname', 'lastname', 'email']);
203
        $roaminghermione = mnet_strip_user($hermione, ['firstname', 'lastname', 'email']);
204
 
205
        $this->assertTrue(user_not_fully_set_up($roamingharry, true));
206
        $this->assertFalse(user_not_fully_set_up($roamingharry, false));
207
        $this->assertTrue(user_not_fully_set_up($roaminghermione, true));
208
        $this->assertTrue(user_not_fully_set_up($roaminghermione, false));
209
    }
210
 
211
    /**
212
     * Test that user generator sets the custom profile fields
213
     */
11 efrain 214
    public function test_profile_fields_in_generator(): void {
1 efrain 215
        global $CFG;
216
        require_once($CFG->dirroot.'/mnet/lib.php');
217
 
218
        $this->resetAfterTest();
219
 
220
        // Add a required, visible, unlocked custom field.
221
        $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'house', 'name' => 'House', 'required' => 1,
222
            'visible' => 1, 'locked' => 0, 'datatype' => 'text', 'defaultdata' => null]);
223
 
224
        // Create some student accounts.
225
        $hermione = $this->getDataGenerator()->create_user(['profile_field_house' => 'Gryffindor']);
226
        $harry = $this->getDataGenerator()->create_user();
227
 
228
        // Only students with required fields filled should be considered as fully set up.
229
        $this->assertFalse(user_not_fully_set_up($hermione));
230
        $this->assertTrue(user_not_fully_set_up($harry));
231
 
232
        // Test that the profile fields were actually set.
233
        $profilefields1 = profile_user_record($hermione->id);
234
        $this->assertEquals('Gryffindor', $profilefields1->house);
235
 
236
        $profilefields2 = profile_user_record($harry->id);
237
        $this->assertObjectHasProperty('house', $profilefields2);
238
        $this->assertNull($profilefields2->house);
239
    }
240
 
241
    /**
242
     * Tests the profile_get_custom_field_data_by_shortname function when working normally.
243
     */
11 efrain 244
    public function test_profile_get_custom_field_data_by_shortname_normal(): void {
1 efrain 245
        global $DB;
246
 
247
        $this->resetAfterTest();
248
 
249
        // Create 3 profile fields.
250
        $generator = $this->getDataGenerator();
251
        $field1 = $generator->create_custom_profile_field(['datatype' => 'text',
252
                'shortname' => 'speciality', 'name' => 'Speciality',
253
                'visible' => PROFILE_VISIBLE_ALL]);
254
        $field2 = $generator->create_custom_profile_field(['datatype' => 'menu',
255
                'shortname' => 'veggie', 'name' => 'Vegetarian',
256
                'visible' => PROFILE_VISIBLE_PRIVATE]);
257
 
258
        // Get the first field data and check it is correct.
259
        $data = profile_get_custom_field_data_by_shortname('speciality');
260
        $this->assertEquals('Speciality', $data->name);
261
        $this->assertEquals(PROFILE_VISIBLE_ALL, $data->visible);
262
        $this->assertEquals($field1->id, $data->id);
263
 
264
        // Get the second field data, checking there is no database query this time.
265
        $before = $DB->perf_get_queries();
266
        $data = profile_get_custom_field_data_by_shortname('veggie');
267
        $this->assertEquals($before, $DB->perf_get_queries());
268
        $this->assertEquals('Vegetarian', $data->name);
269
        $this->assertEquals(PROFILE_VISIBLE_PRIVATE, $data->visible);
270
        $this->assertEquals($field2->id, $data->id);
271
    }
272
 
273
    /**
274
     * Tests the profile_get_custom_field_data_by_shortname function with a field that doesn't exist.
275
     */
11 efrain 276
    public function test_profile_get_custom_field_data_by_shortname_missing(): void {
1 efrain 277
        $this->assertNull(profile_get_custom_field_data_by_shortname('speciality'));
278
    }
279
 
280
    /**
281
     * Data provider for {@see test_profile_get_custom_field_data_by_shortname_case_sensitivity}
282
     *
283
     * @return array[]
284
     */
1441 ariadna 285
    public static function profile_get_custom_field_data_by_shortname_case_sensitivity_provider(): array {
1 efrain 286
        return [
287
            'Matching case, case-sensitive search' => ['hello', 'hello', true, true],
288
            'Matching case, case-insensitive search' => ['hello', 'hello', false, true],
289
            'Non-matching case, case-sensitive search' => ['hello', 'Hello', true, false],
290
            'Non-matching case, case-insensitive search' => ['hello', 'Hello', false, true],
291
            'Non-matching, case-sensitive search' => ['hello', 'hola', true, false],
292
            'Non-matching, case-insensitive search' => ['hello', 'hola', false, false],
293
        ];
294
    }
295
 
296
    /**
297
     * Test retrieving custom field by shortname, specifying case-sensitivity when matching
298
     *
299
     * @param string $shortname
300
     * @param string $shortnamesearch
301
     * @param bool $casesensitive
302
     * @param bool $expectmatch
303
     *
304
     * @dataProvider profile_get_custom_field_data_by_shortname_case_sensitivity_provider
305
     */
306
    public function test_profile_get_custom_field_data_by_shortname_case_sensitivity(
307
        string $shortname,
308
        string $shortnamesearch,
309
        bool $casesensitive,
310
        bool $expectmatch
311
    ): void {
312
        $this->resetAfterTest();
313
 
314
        $this->getDataGenerator()->create_custom_profile_field([
315
            'datatype' => 'text',
316
            'shortname' => $shortname,
317
            'name' => 'My field',
318
        ]);
319
 
320
        $customfield = profile_get_custom_field_data_by_shortname($shortnamesearch, $casesensitive);
321
        if ($expectmatch) {
322
            $this->assertInstanceOf(\stdClass::class, $customfield);
323
            $this->assertEquals('text', $customfield->datatype);
324
            $this->assertEquals($shortname, $customfield->shortname);
325
            $this->assertEquals('My field', $customfield->name);
326
        } else {
327
            $this->assertNull($customfield);
328
        }
329
    }
330
 
331
    /**
332
     * Test profile field loading via profile_get_user_field helper
333
     *
334
     * @covers ::profile_get_user_field
335
     */
336
    public function test_profile_get_user_field(): void {
337
        $this->resetAfterTest();
338
 
339
        $profilefield = $this->getDataGenerator()->create_custom_profile_field([
340
            'shortname' => 'fruit',
341
            'name' => 'Fruit',
342
            'datatype' => 'text',
343
        ]);
344
        $user = $this->getDataGenerator()->create_user(['profile_field_fruit' => 'Apple']);
345
 
346
        $fieldinstance = profile_get_user_field('text', $profilefield->id, $user->id);
347
        $this->assertInstanceOf(\profile_field_text::class, $fieldinstance);
348
        $this->assertEquals($profilefield->id, $fieldinstance->fieldid);
349
        $this->assertEquals($user->id, $fieldinstance->userid);
350
        $this->assertEquals('Apple', $fieldinstance->data);
351
    }
352
}