|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Tests for profile.module. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * A class for common methods for testing profile fields. |
|
10 */ |
|
11 class ProfileTestCase extends DrupalWebTestCase { |
|
12 protected $admin_user; |
|
13 protected $normal_user; |
|
14 |
|
15 function setUp() { |
|
16 parent::setUp('profile'); |
|
17 variable_set('user_register', USER_REGISTER_VISITORS); |
|
18 |
|
19 $this->admin_user = $this->drupalCreateUser(array('administer users', 'access user profiles', 'administer blocks')); |
|
20 |
|
21 // This is the user whose profile will be edited. |
|
22 $this->normal_user = $this->drupalCreateUser(); |
|
23 } |
|
24 |
|
25 /** |
|
26 * Create a profile field. |
|
27 * |
|
28 * @param $type |
|
29 * The field type to be created. |
|
30 * @param $category |
|
31 * The category in which the field should be created. |
|
32 * @param $edit |
|
33 * Additional parameters to be submitted. |
|
34 * @return |
|
35 * The fid of the field that was just created. |
|
36 */ |
|
37 function createProfileField($type = 'textfield', $category = 'simpletest', $edit = array()) { |
|
38 $edit['title'] = $title = $this->randomName(8); |
|
39 $edit['name'] = $form_name = 'profile_' . $title; |
|
40 $edit['category'] = $category; |
|
41 $edit['explanation'] = $this->randomName(50); |
|
42 |
|
43 $this->drupalPost('admin/config/people/profile/add/' . $type, $edit, t('Save field')); |
|
44 $fid = db_query("SELECT fid FROM {profile_field} WHERE title = :title", array(':title' => $title))->fetchField(); |
|
45 $this->assertTrue($fid, 'New Profile field has been entered in the database'); |
|
46 |
|
47 // Check that the new field is appearing on the user edit form. |
|
48 $this->drupalGet('user/' . $this->admin_user->uid . '/edit/' . $category); |
|
49 |
|
50 // Checking field. |
|
51 if ($type == 'date') { |
|
52 $this->assertField($form_name . '[month]', 'Found month selection field'); |
|
53 $this->assertField($form_name . '[day]', 'Found day selection field'); |
|
54 $this->assertField($form_name . '[year]', 'Found day selection field'); |
|
55 } |
|
56 else { |
|
57 $this->assertField($form_name , format_string('Found form named @name', array('@name' => $form_name))); |
|
58 } |
|
59 |
|
60 // Checking name. |
|
61 $this->assertText($title, format_string('Checking title for field %title', array('%title' => $title))); |
|
62 // Checking explanation. |
|
63 $this->assertText($edit['explanation'], format_string('Checking explanation for field %title', array('%title' => $title))); |
|
64 |
|
65 return array( |
|
66 'fid' => $fid, |
|
67 'type' => $type, |
|
68 'form_name' => $form_name, |
|
69 'title' => $title, |
|
70 'category' => $category, |
|
71 ); |
|
72 } |
|
73 |
|
74 /** |
|
75 * Update a profile field. |
|
76 * |
|
77 * @param $fid |
|
78 * The fid of the field to be updated. |
|
79 * @param $type |
|
80 * The type of field to be updated. |
|
81 * @param $edit |
|
82 * Field parameters to be submitted. |
|
83 * @return |
|
84 * Array representation of the updated field. |
|
85 */ |
|
86 function updateProfileField($fid, $type = 'textfield', $edit = array()) { |
|
87 |
|
88 $form_name = $edit['name']; |
|
89 $title = $edit['title']; |
|
90 $category = $edit['category']; |
|
91 |
|
92 $this->drupalPost('admin/config/people/profile/edit/' . $fid, $edit, t('Save field')); |
|
93 |
|
94 // Check that the updated field is appearing on the user edit form. |
|
95 $this->drupalGet('user/' . $this->admin_user->uid . '/edit/' . $category); |
|
96 |
|
97 // Checking field. |
|
98 if ($type == 'date') { |
|
99 $this->assertField($form_name . '[month]', 'Found month selection field'); |
|
100 $this->assertField($form_name . '[day]', 'Found day selection field'); |
|
101 $this->assertField($form_name . '[year]', 'Found day selection field'); |
|
102 } |
|
103 else { |
|
104 $this->assertField($form_name , format_string('Found form named @name', array('@name' => $form_name))); |
|
105 } |
|
106 |
|
107 // Checking name. |
|
108 $this->assertText($title, format_string('Checking title for field %title', array('%title' => $title))); |
|
109 // Checking explanation. |
|
110 $this->assertText($edit['explanation'], format_string('Checking explanation for field %title', array('%title' => $title))); |
|
111 |
|
112 return array( |
|
113 'fid' => $fid, |
|
114 'type' => $type, |
|
115 'form_name' => $form_name, |
|
116 'title' => $title, |
|
117 'category' => $category, |
|
118 ); |
|
119 } |
|
120 |
|
121 /** |
|
122 * Set the profile field to a random value |
|
123 * |
|
124 * @param $field |
|
125 * The field that should be set. |
|
126 * @param $value |
|
127 * The value for the field, defaults to a random string. |
|
128 * @return |
|
129 * The value that has been assigned to |
|
130 */ |
|
131 function setProfileField($field, $value = NULL) { |
|
132 |
|
133 if (!isset($value)) { |
|
134 $value = $this->randomName(); |
|
135 } |
|
136 |
|
137 $edit = array( |
|
138 $field['form_name'] => $value, |
|
139 ); |
|
140 $this->drupalPost('user/' . $this->normal_user->uid . '/edit/' . $field['category'], $edit, t('Save')); |
|
141 |
|
142 // Check profile page. |
|
143 $content = $this->drupalGet('user/' . $this->normal_user->uid); |
|
144 $this->assertText($field['title'], format_string('Found profile field with title %title', array('%title' => $field['title']))); |
|
145 |
|
146 if ($field['type'] != 'checkbox') { |
|
147 // $value must be cast to a string in order to be found by assertText. |
|
148 $this->assertText("$value", format_string('Found profile field with value %value', array('%value' => $value))); |
|
149 } |
|
150 |
|
151 return $value; |
|
152 } |
|
153 |
|
154 /** |
|
155 * Delete a profile field. |
|
156 * |
|
157 * @param $field |
|
158 * The field to be deleted. |
|
159 */ |
|
160 function deleteProfileField($field) { |
|
161 $this->drupalPost('admin/config/people/profile/delete/' . $field['fid'], array(), t('Delete')); |
|
162 $this->drupalGet('admin/config/people/profile'); |
|
163 $this->assertNoText($field['title'], format_string('Checking deleted field %title', array('%title' => $field['title']))); |
|
164 } |
|
165 } |
|
166 |
|
167 class ProfileTestFields extends ProfileTestCase { |
|
168 public static function getInfo() { |
|
169 return array( |
|
170 'name' => 'Test single fields', |
|
171 'description' => 'Testing profile module with add/edit/delete textfield, textarea, list, checkbox, and url fields into profile page', |
|
172 'group' => 'Profile' |
|
173 ); |
|
174 } |
|
175 |
|
176 /** |
|
177 * Test each of the field types. List selection and date fields are tested |
|
178 * separately because they need some special handling. |
|
179 */ |
|
180 function testProfileFields() { |
|
181 $this->drupalLogin($this->admin_user); |
|
182 |
|
183 // Set test values for every field type. |
|
184 $field_types = array( |
|
185 'textfield' => $this->randomName(), |
|
186 'textarea' => $this->randomName(), |
|
187 'list' => $this->randomName(), |
|
188 'checkbox' => 1, |
|
189 // An underscore is an invalid character in a domain name. The method randomName can |
|
190 // return an underscore. |
|
191 'url' => 'http://www.' . str_replace('_', '', $this->randomName(10)) . '.org', |
|
192 ); |
|
193 |
|
194 // For each field type, create a field, give it a value, update the field, |
|
195 // and delete the field. |
|
196 foreach ($field_types as $type => $value) { |
|
197 $field = $this->createProfileField($type); |
|
198 $this->setProfileField($field, $value); |
|
199 $edit = array( |
|
200 'name' => $field['form_name'], |
|
201 'title' => $this->randomName(), |
|
202 'category' => $field['category'], |
|
203 'explanation' => $this->randomName(), |
|
204 ); |
|
205 $field = $this->updateProfileField($field['fid'], $field['type'], $edit); |
|
206 $this->deleteProfileField($field); |
|
207 } |
|
208 } |
|
209 } |
|
210 |
|
211 class ProfileTestSelect extends ProfileTestCase { |
|
212 public static function getInfo() { |
|
213 return array( |
|
214 'name' => 'Test select field', |
|
215 'description' => 'Testing profile module with add/edit/delete a select field', |
|
216 'group' => 'Profile' |
|
217 ); |
|
218 } |
|
219 |
|
220 /** |
|
221 * Create a list selection field, give it a value, update and delete the field. |
|
222 */ |
|
223 function testProfileSelectionField() { |
|
224 $this->drupalLogin($this->admin_user); |
|
225 |
|
226 $edit = array( |
|
227 'options' => implode("\n", range(1, 10)), |
|
228 ); |
|
229 $field = $this->createProfileField('selection', 'simpletest', $edit); |
|
230 |
|
231 $this->setProfileField($field, rand(1, 10)); |
|
232 |
|
233 $edit = array( |
|
234 'name' => $field['form_name'], |
|
235 'title' => $this->randomName(), |
|
236 'category' => $field['category'], |
|
237 'explanation' => $this->randomName(), |
|
238 ); |
|
239 $field = $this->updateProfileField($field['fid'], $field['type'], $edit); |
|
240 $this->deleteProfileField($field); |
|
241 } |
|
242 } |
|
243 |
|
244 class ProfileTestDate extends ProfileTestCase { |
|
245 public static function getInfo() { |
|
246 return array( |
|
247 'name' => 'Test date field', |
|
248 'description' => 'Testing profile module with add/edit/delete a date field', |
|
249 'group' => 'Profile' |
|
250 ); |
|
251 } |
|
252 |
|
253 /** |
|
254 * Create a date field, give it a value, update and delete the field. |
|
255 */ |
|
256 function testProfileDateField() { |
|
257 $this->drupalLogin($this->admin_user); |
|
258 |
|
259 variable_set('date_format_short', 'm/d/Y - H:i'); |
|
260 $field = $this->createProfileField('date'); |
|
261 |
|
262 // Set date to January 09, 1983 |
|
263 $edit = array( |
|
264 $field['form_name'] . '[month]' => 1, |
|
265 $field['form_name'] . '[day]' => 9, |
|
266 $field['form_name'] . '[year]' => 1983, |
|
267 ); |
|
268 |
|
269 $this->drupalPost('user/' . $this->normal_user->uid . '/edit/' . $field['category'], $edit, t('Save')); |
|
270 |
|
271 // Check profile page. |
|
272 $this->drupalGet('user/' . $this->normal_user->uid); |
|
273 $this->assertText($field['title'], format_string('Found profile field with title %title', array('%title' => $field['title']))); |
|
274 |
|
275 $this->assertText('01/09/1983', 'Found date profile field.'); |
|
276 |
|
277 $edit = array( |
|
278 'name' => $field['form_name'], |
|
279 'title' => $this->randomName(), |
|
280 'category' => $field['category'], |
|
281 'explanation' => $this->randomName(), |
|
282 ); |
|
283 $field = $this->updateProfileField($field['fid'], $field['type'], $edit); |
|
284 $this->deleteProfileField($field); |
|
285 } |
|
286 } |
|
287 |
|
288 class ProfileTestWeights extends ProfileTestCase { |
|
289 public static function getInfo() { |
|
290 return array( |
|
291 'name' => 'Test field weights', |
|
292 'description' => 'Testing profile modules weigting of fields', |
|
293 'group' => 'Profile' |
|
294 ); |
|
295 } |
|
296 |
|
297 function testProfileFieldWeights() { |
|
298 $this->drupalLogin($this->admin_user); |
|
299 |
|
300 $category = $this->randomName(); |
|
301 $field1 = $this->createProfileField('textfield', $category, array('weight' => 1)); |
|
302 $field2 = $this->createProfileField('textfield', $category, array('weight' => -1)); |
|
303 |
|
304 $this->setProfileField($field1, $this->randomName(8)); |
|
305 $this->setProfileField($field2, $this->randomName(8)); |
|
306 |
|
307 $profile_edit = $this->drupalGet('user/' . $this->normal_user->uid . '/edit/' . $category); |
|
308 $this->assertTrue(strpos($profile_edit, $field1['title']) > strpos($profile_edit, $field2['title']), 'Profile field weights are respected on the user edit form.'); |
|
309 |
|
310 $profile_page = $this->drupalGet('user/' . $this->normal_user->uid); |
|
311 $this->assertTrue(strpos($profile_page, $field1['title']) > strpos($profile_page, $field2['title']), 'Profile field weights are respected on the user profile page.'); |
|
312 } |
|
313 } |
|
314 |
|
315 /** |
|
316 * Test profile field autocompletion and access. |
|
317 */ |
|
318 class ProfileTestAutocomplete extends ProfileTestCase { |
|
319 public static function getInfo() { |
|
320 return array( |
|
321 'name' => 'Autocompletion', |
|
322 'description' => 'Test profile fields with autocompletion.', |
|
323 'group' => 'Profile' |
|
324 ); |
|
325 } |
|
326 |
|
327 /** |
|
328 * Tests profile field autocompletion and access. |
|
329 */ |
|
330 function testAutocomplete() { |
|
331 $this->drupalLogin($this->admin_user); |
|
332 |
|
333 // Create a new profile field with autocompletion enabled. |
|
334 $category = $this->randomName(); |
|
335 $field = $this->createProfileField('textfield', $category, array('weight' => 1, 'autocomplete' => 1)); |
|
336 |
|
337 // Enter profile field value. |
|
338 $field['value'] = $this->randomName(); |
|
339 $this->setProfileField($field, $field['value']); |
|
340 |
|
341 // Set some html for what we want to see in the page output later. |
|
342 // Autocomplete always uses non-clean URLs. |
|
343 $current_clean_url = isset($GLOBALS['conf']['clean_url']) ? $GLOBALS['conf']['clean_url'] : NULL; |
|
344 $GLOBALS['conf']['clean_url'] = 0; |
|
345 $autocomplete_url = url('profile/autocomplete/' . $field['fid'], array('absolute' => TRUE, 'script' => 'index.php')); |
|
346 $GLOBALS['conf']['clean_url'] = $current_clean_url; |
|
347 $autocomplete_id = drupal_html_id('edit-' . $field['form_name'] . '-autocomplete'); |
|
348 $autocomplete_html = '<input type="hidden" id="' . $autocomplete_id . '" value="' . $autocomplete_url . '" disabled="disabled" class="autocomplete" />'; |
|
349 |
|
350 // Check that autocompletion html is found on the user's profile edit page. |
|
351 $this->drupalGet('user/' . $this->admin_user->uid . '/edit/' . $category); |
|
352 $this->assertRaw($autocomplete_html, 'Autocomplete found.'); |
|
353 $this->assertFieldByXPath( |
|
354 '//input[@type="text" and @name="' . $field['form_name'] . '" and contains(@class, "form-autocomplete")]', |
|
355 '', |
|
356 'Text input field found' |
|
357 ); |
|
358 $this->assertRaw('misc/autocomplete.js', 'Autocomplete JavaScript found.'); |
|
359 $this->assertRaw('class="form-text form-autocomplete"', 'Autocomplete form element class found.'); |
|
360 |
|
361 // Check the autocompletion path using the first letter of our user's profile |
|
362 // field value to make sure access is allowed and a valid result if found. |
|
363 $this->drupalGet('profile/autocomplete/' . $field['fid'] . '/' . $field['value'][0]); |
|
364 $this->assertResponse(200, 'Autocomplete path allowed to user with permission.'); |
|
365 $this->assertRaw($field['value'], 'Autocomplete value found.'); |
|
366 |
|
367 // Logout and login with a user without the 'access user profiles' permission. |
|
368 $this->drupalLogout(); |
|
369 $this->drupalLogin($this->normal_user); |
|
370 |
|
371 // Check that autocompletion html is not found on the user's profile edit page. |
|
372 $this->drupalGet('user/' . $this->normal_user->uid . '/edit/' . $category); |
|
373 $this->assertNoRaw($autocomplete_html, 'Autocomplete not found.'); |
|
374 |
|
375 // User should be denied access to the profile autocomplete path. |
|
376 $this->drupalGet('profile/autocomplete/' . $field['fid'] . '/' . $field['value'][0]); |
|
377 $this->assertResponse(403, 'Autocomplete path denied to user without permission.'); |
|
378 } |
|
379 } |
|
380 |
|
381 class ProfileBlockTestCase extends ProfileTestCase { |
|
382 public static function getInfo() { |
|
383 return array( |
|
384 'name' => 'Block availability', |
|
385 'description' => 'Check if the Author Information block is available.', |
|
386 'group' => 'Profile', |
|
387 ); |
|
388 } |
|
389 |
|
390 function setUp() { |
|
391 parent::setUp(); |
|
392 |
|
393 // Login the admin user. |
|
394 $this->drupalLogin($this->admin_user); |
|
395 |
|
396 // Create two fields. |
|
397 $category = $this->randomName(); |
|
398 $this->field1 = $this->createProfileField('textfield', $category, array('weight' => 0)); |
|
399 $this->field2 = $this->createProfileField('textfield', $category, array('weight' => 1)); |
|
400 |
|
401 // Assign values to those fields. |
|
402 $this->value1 = $this->setProfileField($this->field1); |
|
403 $this->value2 = $this->setProfileField($this->field2); |
|
404 |
|
405 // Create a node authored by the normal user. |
|
406 $this->node = $this->drupalCreateNode(array( |
|
407 'uid' => $this->normal_user->uid, |
|
408 )); |
|
409 } |
|
410 |
|
411 function testAuthorInformationBlock() { |
|
412 // Set the block to a region to confirm the block is available. |
|
413 $edit = array(); |
|
414 $edit['blocks[profile_author-information][region]'] = 'footer'; |
|
415 $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); |
|
416 $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.'); |
|
417 |
|
418 // Enable field 1. |
|
419 $this->drupalPost('admin/structure/block/manage/profile/author-information/configure', array( |
|
420 'profile_block_author_fields[' . $this->field1['form_name'] . ']' => TRUE, |
|
421 ), t('Save block')); |
|
422 $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.'); |
|
423 |
|
424 // Visit the node and confirm that the field is displayed. |
|
425 $this->drupalGet('node/' . $this->node->nid); |
|
426 $this->assertRaw($this->value1, 'Field 1 is displayed'); |
|
427 $this->assertNoRaw($this->value2, 'Field 2 is not displayed'); |
|
428 |
|
429 // Enable only field 2. |
|
430 $this->drupalPost('admin/structure/block/manage/profile/author-information/configure', array( |
|
431 'profile_block_author_fields[' . $this->field1['form_name'] . ']' => FALSE, |
|
432 'profile_block_author_fields[' . $this->field2['form_name'] . ']' => TRUE, |
|
433 ), t('Save block')); |
|
434 $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.'); |
|
435 |
|
436 // Visit the node and confirm that the field is displayed. |
|
437 $this->drupalGet('node/' . $this->node->nid); |
|
438 $this->assertNoRaw($this->value1, 'Field 1 is not displayed'); |
|
439 $this->assertRaw($this->value2, 'Field 2 is displayed'); |
|
440 |
|
441 // Enable both fields. |
|
442 $this->drupalPost('admin/structure/block/manage/profile/author-information/configure', array( |
|
443 'profile_block_author_fields[' . $this->field1['form_name'] . ']' => TRUE, |
|
444 'profile_block_author_fields[' . $this->field2['form_name'] . ']' => TRUE, |
|
445 ), t('Save block')); |
|
446 $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.'); |
|
447 |
|
448 // Visit the node and confirm that the field is displayed. |
|
449 $this->drupalGet('node/' . $this->node->nid); |
|
450 $this->assertRaw($this->value1, 'Field 1 is displayed'); |
|
451 $this->assertRaw($this->value2, 'Field 2 is displayed'); |
|
452 |
|
453 // Enable the link to the user profile. |
|
454 $this->drupalPost('admin/structure/block/manage/profile/author-information/configure', array( |
|
455 'profile_block_author_fields[user_profile]' => TRUE, |
|
456 ), t('Save block')); |
|
457 $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.'); |
|
458 |
|
459 // Visit the node and confirm that the user profile link is displayed. |
|
460 $this->drupalGet('node/' . $this->node->nid); |
|
461 $this->clickLink(t('View full user profile')); |
|
462 $this->assertEqual($this->getUrl(), url('user/' . $this->normal_user->uid, array('absolute' => TRUE))); |
|
463 } |
|
464 } |
|
465 |
|
466 /** |
|
467 * Test profile browsing. |
|
468 */ |
|
469 class ProfileTestBrowsing extends ProfileTestCase { |
|
470 public static function getInfo() { |
|
471 return array( |
|
472 'name' => 'Profile browsing', |
|
473 'description' => 'Test profile browsing.', |
|
474 'group' => 'Profile', |
|
475 ); |
|
476 } |
|
477 |
|
478 /** |
|
479 * Test profile browsing. |
|
480 */ |
|
481 function testProfileBrowsing() { |
|
482 $this->drupalLogin($this->admin_user); |
|
483 $field = $this->createProfileField('list', 'simpletest', array('page' => '%value')); |
|
484 |
|
485 // Set a random value for the profile field. |
|
486 $value = $this->setProfileField($field); |
|
487 |
|
488 // Check that user is found on the profile browse page. |
|
489 $this->drupalGet("profile/{$field['form_name']}/$value"); |
|
490 $this->assertText($this->normal_user->name); |
|
491 } |
|
492 } |
|
493 |
|
494 /** |
|
495 * Test profile integration with user CRUD operations. |
|
496 */ |
|
497 class ProfileCrudTestCase extends ProfileTestCase { |
|
498 public static function getInfo() { |
|
499 return array( |
|
500 'name' => 'Profile CRUD tests', |
|
501 'description' => 'Test profile integration with user create, read, update, delete.', |
|
502 'group' => 'Profile', |
|
503 ); |
|
504 } |
|
505 |
|
506 /** |
|
507 * Test profile integration with user CRUD operations. |
|
508 */ |
|
509 public function testUserCRUD() { |
|
510 // @todo Add profile fields in addition to base user properties. |
|
511 $edit = array( |
|
512 'name' => 'Test user', |
|
513 'mail' => 'test@example.com', |
|
514 ); |
|
515 |
|
516 // Create. |
|
517 // @todo Add assertions. |
|
518 $account = user_save(NULL, $edit); |
|
519 |
|
520 // Read. |
|
521 // @todo Add assertions. |
|
522 $account = user_load($account->uid); |
|
523 |
|
524 // Update. |
|
525 // @todo Add assertions. |
|
526 $account = user_save($account, $edit); |
|
527 |
|
528 // Delete. |
|
529 // @todo Add assertions. |
|
530 user_delete($account->uid); |
|
531 } |
|
532 } |
|
533 |
|
534 /** |
|
535 * TODO: |
|
536 * - Test field visibility |
|
537 * - Test required fields |
|
538 * - Test fields on registration form |
|
539 * - Test updating fields |
|
540 */ |