| Drupal | PHP Cross Reference | Content Management Systems |
1 <?php 2 3 /** 4 * @file 5 * Tests for user.module. 6 */ 7 8 class UserRegistrationTestCase extends DrupalWebTestCase { 9 public static function getInfo() { 10 return array( 11 'name' => 'User registration', 12 'description' => 'Test registration of user under different configurations.', 13 'group' => 'User' 14 ); 15 } 16 17 function setUp() { 18 parent::setUp('field_test'); 19 } 20 21 function testRegistrationWithEmailVerification() { 22 // Require e-mail verification. 23 variable_set('user_email_verification', TRUE); 24 25 // Set registration to administrator only. 26 variable_set('user_register', USER_REGISTER_ADMINISTRATORS_ONLY); 27 $this->drupalGet('user/register'); 28 $this->assertResponse(403, t('Registration page is inaccessible when only administrators can create accounts.')); 29 30 // Allow registration by site visitors without administrator approval. 31 variable_set('user_register', USER_REGISTER_VISITORS); 32 $edit = array(); 33 $edit['name'] = $name = $this->randomName(); 34 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 35 $this->drupalPost('user/register', $edit, t('Create new account')); 36 $this->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), t('User registered successfully.')); 37 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 38 $new_user = reset($accounts); 39 $this->assertTrue($new_user->status, t('New account is active after registration.')); 40 41 // Allow registration by site visitors, but require administrator approval. 42 variable_set('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); 43 $edit = array(); 44 $edit['name'] = $name = $this->randomName(); 45 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 46 $this->drupalPost('user/register', $edit, t('Create new account')); 47 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 48 $new_user = reset($accounts); 49 $this->assertFalse($new_user->status, t('New account is blocked until approved by an administrator.')); 50 } 51 52 function testRegistrationWithoutEmailVerification() { 53 // Don't require e-mail verification. 54 variable_set('user_email_verification', FALSE); 55 56 // Allow registration by site visitors without administrator approval. 57 variable_set('user_register', USER_REGISTER_VISITORS); 58 $edit = array(); 59 $edit['name'] = $name = $this->randomName(); 60 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 61 62 // Try entering a mismatching password. 63 $edit['pass[pass1]'] = '99999.0'; 64 $edit['pass[pass2]'] = '99999'; 65 $this->drupalPost('user/register', $edit, t('Create new account')); 66 $this->assertText(t('The specified passwords do not match.'), t('Typing mismatched passwords displays an error message.')); 67 68 // Enter a correct password. 69 $edit['pass[pass1]'] = $new_pass = $this->randomName(); 70 $edit['pass[pass2]'] = $new_pass; 71 $this->drupalPost('user/register', $edit, t('Create new account')); 72 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 73 $new_user = reset($accounts); 74 $this->assertText(t('Registration successful. You are now logged in.'), t('Users are logged in after registering.')); 75 $this->drupalLogout(); 76 77 // Allow registration by site visitors, but require administrator approval. 78 variable_set('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); 79 $edit = array(); 80 $edit['name'] = $name = $this->randomName(); 81 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 82 $edit['pass[pass1]'] = $pass = $this->randomName(); 83 $edit['pass[pass2]'] = $pass; 84 $this->drupalPost('user/register', $edit, t('Create new account')); 85 $this->assertText(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.'), t('Users are notified of pending approval')); 86 87 // Try to login before administrator approval. 88 $auth = array( 89 'name' => $name, 90 'pass' => $pass, 91 ); 92 $this->drupalPost('user/login', $auth, t('Log in')); 93 $this->assertText(t('The username @name has not been activated or is blocked.', array('@name' => $name)), t('User cannot login yet.')); 94 95 // Activate the new account. 96 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 97 $new_user = reset($accounts); 98 $admin_user = $this->drupalCreateUser(array('administer users')); 99 $this->drupalLogin($admin_user); 100 $edit = array( 101 'status' => 1, 102 ); 103 $this->drupalPost('user/' . $new_user->uid . '/edit', $edit, t('Save')); 104 $this->drupalLogout(); 105 106 // Login after administrator approval. 107 $this->drupalPost('user/login', $auth, t('Log in')); 108 $this->assertText(t('Member for'), t('User can log in after administrator approval.')); 109 } 110 111 function testRegistrationEmailDuplicates() { 112 // Don't require e-mail verification. 113 variable_set('user_email_verification', FALSE); 114 115 // Allow registration by site visitors without administrator approval. 116 variable_set('user_register', USER_REGISTER_VISITORS); 117 118 // Set up a user to check for duplicates. 119 $duplicate_user = $this->drupalCreateUser(); 120 121 $edit = array(); 122 $edit['name'] = $this->randomName(); 123 $edit['mail'] = $duplicate_user->mail; 124 125 // Attempt to create a new account using an existing e-mail address. 126 $this->drupalPost('user/register', $edit, t('Create new account')); 127 $this->assertText(t('The e-mail address @email is already registered.', array('@email' => $duplicate_user->mail)), t('Supplying an exact duplicate email address displays an error message')); 128 129 // Attempt to bypass duplicate email registration validation by adding spaces. 130 $edit['mail'] = ' ' . $duplicate_user->mail . ' '; 131 132 $this->drupalPost('user/register', $edit, t('Create new account')); 133 $this->assertText(t('The e-mail address @email is already registered.', array('@email' => $duplicate_user->mail)), t('Supplying a duplicate email address with added whitespace displays an error message')); 134 } 135 136 function testRegistrationDefaultValues() { 137 // Allow registration by site visitors without administrator approval. 138 variable_set('user_register', USER_REGISTER_VISITORS); 139 140 // Don't require e-mail verification. 141 variable_set('user_email_verification', FALSE); 142 143 // Set the default timezone to Brussels. 144 variable_set('configurable_timezones', 1); 145 variable_set('date_default_timezone', 'Europe/Brussels'); 146 147 // Check that the account information fieldset's options are not displayed 148 // is a fieldset if there is not more than one fieldset in the form. 149 $this->drupalGet('user/register'); 150 $this->assertNoRaw('<fieldset id="edit-account"><legend>Account information</legend>', t('Account settings fieldset was hidden.')); 151 152 $edit = array(); 153 $edit['name'] = $name = $this->randomName(); 154 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 155 $edit['pass[pass1]'] = $new_pass = $this->randomName(); 156 $edit['pass[pass2]'] = $new_pass; 157 $this->drupalPost(NULL, $edit, t('Create new account')); 158 159 // Check user fields. 160 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 161 $new_user = reset($accounts); 162 $this->assertEqual($new_user->name, $name, t('Username matches.')); 163 $this->assertEqual($new_user->mail, $mail, t('E-mail address matches.')); 164 $this->assertEqual($new_user->theme, '', t('Correct theme field.')); 165 $this->assertEqual($new_user->signature, '', t('Correct signature field.')); 166 $this->assertTrue(($new_user->created > REQUEST_TIME - 20 ), t('Correct creation time.')); 167 $this->assertEqual($new_user->status, variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) == USER_REGISTER_VISITORS ? 1 : 0, t('Correct status field.')); 168 $this->assertEqual($new_user->timezone, variable_get('date_default_timezone'), t('Correct time zone field.')); 169 $this->assertEqual($new_user->language, '', t('Correct language field.')); 170 $this->assertEqual($new_user->picture, '', t('Correct picture field.')); 171 $this->assertEqual($new_user->init, $mail, t('Correct init field.')); 172 } 173 174 /** 175 * Tests Field API fields on user registration forms. 176 */ 177 function testRegistrationWithUserFields() { 178 // Create a field, and an instance on 'user' entity type. 179 $field = array( 180 'type' => 'test_field', 181 'field_name' => 'test_user_field', 182 'cardinality' => 1, 183 ); 184 field_create_field($field); 185 $instance = array( 186 'field_name' => 'test_user_field', 187 'entity_type' => 'user', 188 'label' => 'Some user field', 189 'bundle' => 'user', 190 'required' => TRUE, 191 'settings' => array('user_register_form' => FALSE), 192 ); 193 field_create_instance($instance); 194 195 // Check that the field does not appear on the registration form. 196 $this->drupalGet('user/register'); 197 $this->assertNoText($instance['label'], t('The field does not appear on user registration form')); 198 199 // Have the field appear on the registration form. 200 $instance['settings']['user_register_form'] = TRUE; 201 field_update_instance($instance); 202 $this->drupalGet('user/register'); 203 $this->assertText($instance['label'], t('The field appears on user registration form')); 204 205 // Check that validation errors are correctly reported. 206 $edit = array(); 207 $edit['name'] = $name = $this->randomName(); 208 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 209 // Missing input in required field. 210 $edit['test_user_field[und][0][value]'] = ''; 211 $this->drupalPost(NULL, $edit, t('Create new account')); 212 $this->assertRaw(t('@name field is required.', array('@name' => $instance['label'])), t('Field validation error was correctly reported.')); 213 // Invalid input. 214 $edit['test_user_field[und][0][value]'] = '-1'; 215 $this->drupalPost(NULL, $edit, t('Create new account')); 216 $this->assertRaw(t('%name does not accept the value -1.', array('%name' => $instance['label'])), t('Field validation error was correctly reported.')); 217 218 // Submit with valid data. 219 $value = rand(1, 255); 220 $edit['test_user_field[und][0][value]'] = $value; 221 $this->drupalPost(NULL, $edit, t('Create new account')); 222 // Check user fields. 223 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 224 $new_user = reset($accounts); 225 $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][0]['value'], $value, t('The field value was correclty saved.')); 226 227 // Check that the 'add more' button works. 228 $field['cardinality'] = FIELD_CARDINALITY_UNLIMITED; 229 field_update_field($field); 230 foreach (array('js', 'nojs') as $js) { 231 $this->drupalGet('user/register'); 232 // Add two inputs. 233 $value = rand(1, 255); 234 $edit = array(); 235 $edit['test_user_field[und][0][value]'] = $value; 236 if ($js == 'js') { 237 $this->drupalPostAJAX(NULL, $edit, 'test_user_field_add_more'); 238 $this->drupalPostAJAX(NULL, $edit, 'test_user_field_add_more'); 239 } 240 else { 241 $this->drupalPost(NULL, $edit, t('Add another item')); 242 $this->drupalPost(NULL, $edit, t('Add another item')); 243 } 244 // Submit with three values. 245 $edit['test_user_field[und][1][value]'] = $value + 1; 246 $edit['test_user_field[und][2][value]'] = $value + 2; 247 $edit['name'] = $name = $this->randomName(); 248 $edit['mail'] = $mail = $edit['name'] . '@example.com'; 249 $this->drupalPost(NULL, $edit, t('Create new account')); 250 // Check user fields. 251 $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); 252 $new_user = reset($accounts); 253 $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][0]['value'], $value, t('@js : The field value was correclty saved.', array('@js' => $js))); 254 $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][1]['value'], $value + 1, t('@js : The field value was correclty saved.', array('@js' => $js))); 255 $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][2]['value'], $value + 2, t('@js : The field value was correclty saved.', array('@js' => $js))); 256 } 257 } 258 } 259 260 class UserValidationTestCase extends DrupalWebTestCase { 261 public static function getInfo() { 262 return array( 263 'name' => 'Username/e-mail validation', 264 'description' => 'Verify that username/email validity checks behave as designed.', 265 'group' => 'User' 266 ); 267 } 268 269 // Username validation. 270 function testUsernames() { 271 $test_cases = array( // '<username>' => array('<description>', 'assert<testName>'), 272 'foo' => array('Valid username', 'assertNull'), 273 'FOO' => array('Valid username', 'assertNull'), 274 'Foo O\'Bar' => array('Valid username', 'assertNull'), 275 'foo@bar' => array('Valid username', 'assertNull'), 276 'foo@example.com' => array('Valid username', 'assertNull'), 277 'foo@-example.com' => array('Valid username', 'assertNull'), // invalid domains are allowed in usernames 278 'þòøÇߪř€' => array('Valid username', 'assertNull'), 279 'ᚠᛇᚻ᛫ᛒᛦᚦ' => array('Valid UTF8 username', 'assertNull'), // runes 280 ' foo' => array('Invalid username that starts with a space', 'assertNotNull'), 281 'foo ' => array('Invalid username that ends with a space', 'assertNotNull'), 282 'foo bar' => array('Invalid username that contains 2 spaces \' \'', 'assertNotNull'), 283 '' => array('Invalid empty username', 'assertNotNull'), 284 'foo/' => array('Invalid username containing invalid chars', 'assertNotNull'), 285 'foo' . chr(0) . 'bar' => array('Invalid username containing chr(0)', 'assertNotNull'), // NULL 286 'foo' . chr(13) . 'bar' => array('Invalid username containing chr(13)', 'assertNotNull'), // CR 287 str_repeat('x', USERNAME_MAX_LENGTH + 1) => array('Invalid excessively long username', 'assertNotNull'), 288 ); 289 foreach ($test_cases as $name => $test_case) { 290 list($description, $test) = $test_case; 291 $result = user_validate_name($name); 292 $this->$test($result, $description . ' (' . $name . ')'); 293 } 294 } 295 296 // Mail validation. More extensive tests can be found at common.test 297 function testMailAddresses() { 298 $test_cases = array( // '<username>' => array('<description>', 'assert<testName>'), 299 '' => array('Empty mail address', 'assertNotNull'), 300 'foo' => array('Invalid mail address', 'assertNotNull'), 301 'foo@example.com' => array('Valid mail address', 'assertNull'), 302 ); 303 foreach ($test_cases as $name => $test_case) { 304 list($description, $test) = $test_case; 305 $result = user_validate_mail($name); 306 $this->$test($result, $description . ' (' . $name . ')'); 307 } 308 } 309 } 310 311 /** 312 * Functional tests for user logins, including rate limiting of login attempts. 313 */ 314 class UserLoginTestCase extends DrupalWebTestCase { 315 public static function getInfo() { 316 return array( 317 'name' => 'User login', 318 'description' => 'Ensure that login works as expected.', 319 'group' => 'User', 320 ); 321 } 322 323 /** 324 * Test the global login flood control. 325 */ 326 function testGlobalLoginFloodControl() { 327 // Set the global login limit. 328 variable_set('user_failed_login_ip_limit', 10); 329 // Set a high per-user limit out so that it is not relevant in the test. 330 variable_set('user_failed_login_user_limit', 4000); 331 332 $user1 = $this->drupalCreateUser(array()); 333 $incorrect_user1 = clone $user1; 334 $incorrect_user1->pass_raw .= 'incorrect'; 335 336 // Try 2 failed logins. 337 for ($i = 0; $i < 2; $i++) { 338 $this->assertFailedLogin($incorrect_user1); 339 } 340 341 // A successful login will not reset the IP-based flood control count. 342 $this->drupalLogin($user1); 343 $this->drupalLogout(); 344 345 // Try 8 more failed logins, they should not trigger the flood control 346 // mechanism. 347 for ($i = 0; $i < 8; $i++) { 348 $this->assertFailedLogin($incorrect_user1); 349 } 350 351 // The next login trial should result in an IP-based flood error message. 352 $this->assertFailedLogin($incorrect_user1, 'ip'); 353 354 // A login with the correct password should also result in a flood error 355 // message. 356 $this->assertFailedLogin($user1, 'ip'); 357 } 358 359 /** 360 * Test the per-user login flood control. 361 */ 362 function testPerUserLoginFloodControl() { 363 // Set a high global limit out so that it is not relevant in the test. 364 variable_set('user_failed_login_ip_limit', 4000); 365 // Set the per-user login limit. 366 variable_set('user_failed_login_user_limit', 3); 367 368 $user1 = $this->drupalCreateUser(array()); 369 $incorrect_user1 = clone $user1; 370 $incorrect_user1->pass_raw .= 'incorrect'; 371 372 $user2 = $this->drupalCreateUser(array()); 373 374 // Try 2 failed logins. 375 for ($i = 0; $i < 2; $i++) { 376 $this->assertFailedLogin($incorrect_user1); 377 } 378 379 // A successful login will reset the per-user flood control count. 380 $this->drupalLogin($user1); 381 $this->drupalLogout(); 382 383 // Try 3 failed logins for user 1, they will not trigger flood control. 384 for ($i = 0; $i < 3; $i++) { 385 $this->assertFailedLogin($incorrect_user1); 386 } 387 388 // Try one successful attempt for user 2, it should not trigger any 389 // flood control. 390 $this->drupalLogin($user2); 391 $this->drupalLogout(); 392 393 // Try one more attempt for user 1, it should be rejected, even if the 394 // correct password has been used. 395 $this->assertFailedLogin($user1, 'user'); 396 } 397 398 /** 399 * Test that user password is re-hashed upon login after changing $count_log2. 400 */ 401 function testPasswordRehashOnLogin() { 402 // Load password hashing API. 403 require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); 404 // Set initial $count_log2 to the default, DRUPAL_HASH_COUNT. 405 variable_set('password_count_log2', DRUPAL_HASH_COUNT); 406 // Create a new user and authenticate. 407 $account = $this->drupalCreateUser(array()); 408 $password = $account->pass_raw; 409 $this->drupalLogin($account); 410 $this->drupalLogout(); 411 // Load the stored user. The password hash should reflect $count_log2. 412 $account = user_load($account->uid); 413 $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_HASH_COUNT); 414 // Change $count_log2 and log in again. 415 variable_set('password_count_log2', DRUPAL_HASH_COUNT + 1); 416 $account->pass_raw = $password; 417 $this->drupalLogin($account); 418 // Load the stored user, which should have a different password hash now. 419 $account = user_load($account->uid, TRUE); 420 $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_HASH_COUNT + 1); 421 } 422 423 /** 424 * Make an unsuccessful login attempt. 425 * 426 * @param $account 427 * A user object with name and pass_raw attributes for the login attempt. 428 * @param $flood_trigger 429 * Whether or not to expect that the flood control mechanism will be 430 * triggered. 431 */ 432 function assertFailedLogin($account, $flood_trigger = NULL) { 433 $edit = array( 434 'name' => $account->name, 435 'pass' => $account->pass_raw, 436 ); 437 $this->drupalPost('user', $edit, t('Log in')); 438 $this->assertNoFieldByXPath("//input[@name='pass' and @value!='']", NULL, t('Password value attribute is blank.')); 439 if (isset($flood_trigger)) { 440 if ($flood_trigger == 'user') { 441 $this->assertRaw(format_plural(variable_get('user_failed_login_user_limit', 5), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password')))); 442 } 443 else { 444 // No uid, so the limit is IP-based. 445 $this->assertRaw(t('Sorry, too many failed login attempts from your IP address. This IP address is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password')))); 446 } 447 } 448 else { 449 $this->assertText(t('Sorry, unrecognized username or password. Have you forgotten your password?')); 450 } 451 } 452 } 453 454 /** 455 * Tests resetting a user password. 456 */ 457 class UserPasswordResetTestCase extends DrupalWebTestCase { 458 protected $profile = 'standard'; 459 460 public static function getInfo() { 461 return array( 462 'name' => 'Reset password', 463 'description' => 'Ensure that password reset methods work as expected.', 464 'group' => 'User', 465 ); 466 } 467 468 /** 469 * Tests password reset functionality. 470 */ 471 function testUserPasswordReset() { 472 // Create a user. 473 $account = $this->drupalCreateUser(); 474 $this->drupalLogin($account); 475 $this->drupalLogout(); 476 // Attempt to reset password. 477 $edit = array('name' => $account->name); 478 $this->drupalPost('user/password', $edit, t('E-mail new password')); 479 // Confirm the password reset. 480 $this->assertText(t('Further instructions have been sent to your e-mail address.'), 'Password reset instructions mailed message displayed.'); 481 } 482 483 /** 484 * Attempts login using an expired password reset link. 485 */ 486 function testUserPasswordResetExpired() { 487 // Set password reset timeout variable to 43200 seconds = 12 hours. 488 $timeout = 43200; 489 variable_set('user_password_reset_timeout', $timeout); 490 491 // Create a user. 492 $account = $this->drupalCreateUser(); 493 $this->drupalLogin($account); 494 // Load real user object. 495 $account = user_load($account->uid, TRUE); 496 $this->drupalLogout(); 497 498 // To attempt an expired password reset, create a password reset link as if 499 // its request time was 60 seconds older than the allowed limit of timeout. 500 $bogus_timestamp = REQUEST_TIME - variable_get('user_password_reset_timeout', 86400) - 60; 501 $this->drupalGet("user/reset/$account->uid/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login)); 502 $this->assertText(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'), 'Expired password reset request rejected.'); 503 } 504 } 505 506 /** 507 * Test cancelling a user. 508 */ 509 class UserCancelTestCase extends DrupalWebTestCase { 510 public static function getInfo() { 511 return array( 512 'name' => 'Cancel account', 513 'description' => 'Ensure that account cancellation methods work as expected.', 514 'group' => 'User', 515 ); 516 } 517 518 function setUp() { 519 parent::setUp('comment'); 520 } 521 522 /** 523 * Attempt to cancel account without permission. 524 */ 525 function testUserCancelWithoutPermission() { 526 variable_set('user_cancel_method', 'user_cancel_reassign'); 527 528 // Create a user. 529 $account = $this->drupalCreateUser(array()); 530 $this->drupalLogin($account); 531 // Load real user object. 532 $account = user_load($account->uid, TRUE); 533 534 // Create a node. 535 $node = $this->drupalCreateNode(array('uid' => $account->uid)); 536 537 // Attempt to cancel account. 538 $this->drupalGet('user/' . $account->uid . '/edit'); 539 $this->assertNoRaw(t('Cancel account'), t('No cancel account button displayed.')); 540 541 // Attempt bogus account cancellation request confirmation. 542 $timestamp = $account->login; 543 $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login)); 544 $this->assertResponse(403, t('Bogus cancelling request rejected.')); 545 $account = user_load($account->uid); 546 $this->assertTrue($account->status == 1, t('User account was not canceled.')); 547 548 // Confirm user's content has not been altered. 549 $test_node = node_load($node->nid, NULL, TRUE); 550 $this->assertTrue(($test_node->uid == $account->uid && $test_node->status == 1), t('Node of the user has not been altered.')); 551 } 552 553 /** 554 * Tests that user account for uid 1 cannot be cancelled. 555 * 556 * This should never be possible, or the site owner would become unable to 557 * administer the site. 558 */ 559 function testUserCancelUid1() { 560 // Update uid 1's name and password to we know it. 561 $password = user_password(); 562 require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); 563 $account = array( 564 'name' => 'user1', 565 'pass' => user_hash_password(trim($password)), 566 ); 567 // We cannot use user_save() here or the password would be hashed again. 568 db_update('users') 569 ->fields($account) 570 ->condition('uid', 1) 571 ->execute(); 572 573 // Reload and log in uid 1. 574 $user1 = user_load(1, TRUE); 575 $user1->pass_raw = $password; 576 577 // Try to cancel uid 1's account with a different user. 578 $this->admin_user = $this->drupalCreateUser(array('administer users')); 579 $this->drupalLogin($this->admin_user); 580 $edit = array( 581 'operation' => 'cancel', 582 'accounts[1]' => TRUE, 583 ); 584 $this->drupalPost('admin/people', $edit, t('Update')); 585 586 // Verify that uid 1's account was not cancelled. 587 $user1 = user_load(1, TRUE); 588 $this->assertEqual($user1->status, 1, t('User #1 still exists and is not blocked.')); 589 } 590 591 /** 592 * Attempt invalid account cancellations. 593 */ 594 function testUserCancelInvalid() { 595 variable_set('user_cancel_method', 'user_cancel_reassign'); 596 597 // Create a user. 598 $account = $this->drupalCreateUser(array('cancel account')); 599 $this->drupalLogin($account); 600 // Load real user object. 601 $account = user_load($account->uid, TRUE); 602 603 // Create a node. 604 $node = $this->drupalCreateNode(array('uid' => $account->uid)); 605 606 // Attempt to cancel account. 607 $this->drupalPost('user/' . $account->uid . '/edit', NULL, t('Cancel account')); 608 609 // Confirm account cancellation. 610 $timestamp = time(); 611 $this->drupalPost(NULL, NULL, t('Cancel account')); 612 $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.')); 613 614 // Attempt bogus account cancellation request confirmation. 615 $bogus_timestamp = $timestamp + 60; 616 $this->drupalGet("user/$account->uid/cancel/confirm/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login)); 617 $this->assertText(t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'), t('Bogus cancelling request rejected.')); 618 $account = user_load($account->uid); 619 $this->assertTrue($account->status == 1, t('User account was not canceled.')); 620 621 // Attempt expired account cancellation request confirmation. 622 $bogus_timestamp = $timestamp - 86400 - 60; 623 $this->drupalGet("user/$account->uid/cancel/confirm/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login)); 624 $this->assertText(t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'), t('Expired cancel account request rejected.')); 625 $accounts = user_load_multiple(array($account->uid), array('status' => 1)); 626 $this->assertTrue(reset($accounts), t('User account was not canceled.')); 627 628 // Confirm user's content has not been altered. 629 $test_node = node_load($node->nid, NULL, TRUE); 630 $this->assertTrue(($test_node->uid == $account->uid && $test_node->status == 1), t('Node of the user has not been altered.')); 631 } 632 633 /** 634 * Disable account and keep all content. 635 */ 636 function testUserBlock() { 637 variable_set('user_cancel_method', 'user_cancel_block'); 638 639 // Create a user. 640 $web_user = $this->drupalCreateUser(array('cancel account')); 641 $this->drupalLogin($web_user); 642 643 // Load real user object. 644 $account = user_load($web_user->uid, TRUE); 645 646 // Attempt to cancel account. 647 $this->drupalGet('user/' . $account->uid . '/edit'); 648 $this->drupalPost(NULL, NULL, t('Cancel account')); 649 $this->assertText(t('Are you sure you want to cancel your account?'), t('Confirmation form to cancel account displayed.')); 650 $this->assertText(t('Your account will be blocked and you will no longer be able to log in. All of your content will remain attributed to your user name.'), t('Informs that all content will be remain as is.')); 651 $this->assertNoText(t('Select the method to cancel the account above.'), t('Does not allow user to select account cancellation method.')); 652 653 // Confirm account cancellation. 654 $timestamp = time(); 655 656 $this->drupalPost(NULL, NULL, t('Cancel account')); 657 $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.')); 658 659 // Confirm account cancellation request. 660 $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login)); 661 $account = user_load($account->uid, TRUE); 662 $this->assertTrue($account->status == 0, t('User has been blocked.')); 663 664 // Confirm user is logged out. 665 $this->assertNoText($account->name, t('Logged out.')); 666 } 667 668 /** 669 * Disable account and unpublish all content. 670 */ 671 function testUserBlockUnpublish() { 672 variable_set('user_cancel_method', 'user_cancel_block_unpublish'); 673 674 // Create a user. 675 $account = $this->drupalCreateUser(array('cancel account')); 676 $this->drupalLogin($account); 677 // Load real user object. 678 $account = user_load($account->uid, TRUE); 679 680 // Create a node with two revisions. 681 $node = $this->drupalCreateNode(array('uid' => $account->uid)); 682 $settings = get_object_vars($node); 683 $settings['revision'] = 1; 684 $node = $this->drupalCreateNode($settings); 685 686 // Attempt to cancel account. 687 $this->drupalGet('user/' . $account->uid . '/edit'); 688 $this->drupalPost(NULL, NULL, t('Cancel account')); 689 $this->assertText(t('Are you sure you want to cancel your account?'), t('Confirmation form to cancel account displayed.')); 690 $this->assertText(t('Your account will be blocked and you will no longer be able to log in. All of your content will be hidden from everyone but administrators.'), t('Informs that all content will be unpublished.')); 691 692 // Confirm account cancellation. 693 $timestamp = time(); 694 $this->drupalPost(NULL, NULL, t('Cancel account')); 695 $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.')); 696 697 // Confirm account cancellation request. 698 $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login)); 699 $account = user_load($account->uid, TRUE); 700 $this->assertTrue($account->status == 0, t('User has been blocked.')); 701 702 // Confirm user's content has been unpublished. 703 $test_node = node_load($node->nid, NULL, TRUE); 704 $this->assertTrue($test_node->status == 0, t('Node of the user has been unpublished.')); 705 $test_node = node_load($node->nid, $node->vid, TRUE); 706 $this->assertTrue($test_node->status == 0, t('Node revision of the user has been unpublished.')); 707 708 // Confirm user is logged out. 709 $this->assertNoText($account->name, t('Logged out.')); 710 } 711 712 /** 713 * Delete account and anonymize all content. 714 */ 715 function testUserAnonymize() { 716 variable_set('user_cancel_method', 'user_cancel_reassign'); 717 718 // Create a user. 719 $account = $this->drupalCreateUser(array('cancel account')); 720 $this->drupalLogin($account); 721 // Load real user object. 722 $account = user_load($account->uid, TRUE); 723 724 // Create a simple node. 725 $node = $this->drupalCreateNode(array('uid' => $account->uid)); 726 727 // Create a node with two revisions, the initial one belonging to the 728 // cancelling user. 729 $revision_node = $this->drupalCreateNode(array('uid' => $account->uid)); 730 $revision = $revision_node->vid; 731 $settings = get_object_vars($revision_node); 732 $settings['revision'] = 1; 733 $settings['uid'] = 1; // Set new/current revision to someone else. 734 $revision_node = $this->drupalCreateNode($settings); 735 736 // Attempt to cancel account. 737 $this->drupalGet('user/' . $account->uid . '/edit'); 738 $this->drupalPost(NULL, NULL, t('Cancel account')); 739 $this->assertText(t('Are you sure you want to cancel your account?'), t('Confirmation form to cancel account displayed.')); 740 $this->assertRaw(t('Your account will be removed and all account information deleted. All of your content will be assigned to the %anonymous-name user.', array('%anonymous-name' => variable_get('anonymous', t('Anonymous')))), t('Informs that all content will be attributed to anonymous account.')); 741 742 // Confirm account cancellation. 743 $timestamp = time(); 744 $this->drupalPost(NULL, NULL, t('Cancel account')); 745 $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.')); 746 747 // Confirm account cancellation request. 748 $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login)); 749 $this->assertFalse(user_load($account->uid, TRUE), t('User is not found in the database.')); 750 751 // Confirm that user's content has been attributed to anonymous user. 752 $test_node = node_load($node->nid, NULL, TRUE); 753 $this->assertTrue(($test_node->uid == 0 && $test_node->status == 1), t('Node of the user has been attributed to anonymous user.')); 754 $test_node = node_load($revision_node->nid, $revision, TRUE); 755 $this->assertTrue(($test_node->revision_uid == 0 && $test_node->status == 1), t('Node revision of the user has been attributed to anonymous user.')); 756 $test_node = node_load($revision_node->nid, NULL, TRUE); 757 $this->assertTrue(($test_node->uid != 0 && $test_node->status == 1), t("Current revision of the user's node was not attributed to anonymous user.")); 758 759 // Confirm that user is logged out. 760 $this->assertNoText($account->name, t('Logged out.')); 761 } 762 763 /** 764 * Delete account and remove all content. 765 */ 766 function testUserDelete() { 767 variable_set('user_cancel_method', 'user_cancel_delete'); 768 769 // Create a user. 770 $account = $this->drupalCreateUser(array('cancel account', 'post comments', 'skip comment approval')); 771 $this->drupalLogin($account); 772 // Load real user object. 773 $account = user_load($account->uid, TRUE); 774 775 // Create a simple node. 776 $node = $this->drupalCreateNode(array('uid' => $account->uid)); 777 778 // Create comment. 779 $langcode = LANGUAGE_NONE; 780 $edit = array(); 781 $edit['subject'] = $this->randomName(8); 782 $edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16); 783 784 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview')); 785 $this->drupalPost(NULL, array(), t('Save')); 786 $this->assertText(t('Your comment has been posted.')); 787 $comments = comment_load_multiple(array(), array('subject' => $edit['subject'])); 788 $comment = reset($comments); 789 $this->assertTrue($comment->cid, t('Comment found.')); 790 791 // Create a node with two revisions, the initial one belonging to the 792 // cancelling user. 793 $revision_node = $this->drupalCreateNode(array('uid' => $account->uid)); 794 $revision = $revision_node->vid; 795 $settings = get_object_vars($revision_node); 796 $settings['revision'] = 1; 797 $settings['uid'] = 1; // Set new/current revision to someone else. 798 $revision_node = $this->drupalCreateNode($settings); 799 800 // Attempt to cancel account. 801 $this->drupalGet('user/' . $account->uid . '/edit'); 802 $this->drupalPost(NULL, NULL, t('Cancel account')); 803 $this->assertText(t('Are you sure you want to cancel your account?'), t('Confirmation form to cancel account displayed.')); 804 $this->assertText(t('Your account will be removed and all account information deleted. All of your content will also be deleted.'), t('Informs that all content will be deleted.')); 805 806 // Confirm account cancellation. 807 $timestamp = time(); 808 $this->drupalPost(NULL, NULL, t('Cancel account')); 809 $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.')); 810 811 // Confirm account cancellation request. 812 $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login)); 813 $this->assertFalse(user_load($account->uid, TRUE), t('User is not found in the database.')); 814 815 // Confirm that user's content has been deleted. 816 $this->assertFalse(node_load($node->nid, NULL, TRUE), t('Node of the user has been deleted.')); 817 $this->assertFalse(node_load($node->nid, $revision, TRUE), t('Node revision of the user has been deleted.')); 818 $this->assertTrue(node_load($revision_node->nid, NULL, TRUE), t("Current revision of the user's node was not deleted.")); 819 $this->assertFalse(comment_load($comment->cid), t('Comment of the user has been deleted.')); 820 821 // Confirm that user is logged out. 822 $this->assertNoText($account->name, t('Logged out.')); 823 } 824 825 /** 826 * Create an administrative user and delete another user. 827 */ 828 function testUserCancelByAdmin() { 829 variable_set('user_cancel_method', 'user_cancel_reassign'); 830 831 // Create a regular user. 832 $account = $this->drupalCreateUser(array()); 833 834 // Create administrative user. 835 $admin_user = $this->drupalCreateUser(array('administer users')); 836 $this->drupalLogin($admin_user); 837 838 // Delete regular user. 839 $this->drupalGet('user/' . $account->uid . '/edit'); 840 $this->drupalPost(NULL, NULL, t('Cancel account')); 841 $this->assertRaw(t('Are you sure you want to cancel the account %name?', array('%name' => $account->name)), t('Confirmation form to cancel account displayed.')); 842 $this->assertText(t('Select the method to cancel the account above.'), t('Allows to select account cancellation method.')); 843 844 // Confirm deletion. 845 $this->drupalPost(NULL, NULL, t('Cancel account')); 846 $this->assertRaw(t('%name has been deleted.', array('%name' => $account->name)), t('User deleted.')); 847 $this->assertFalse(user_load($account->uid), t('User is not found in the database.')); 848 } 849 850 /** 851 * Create an administrative user and mass-delete other users. 852 */ 853 function testMassUserCancelByAdmin() { 854 variable_set('user_cancel_method', 'user_cancel_reassign'); 855 // Enable account cancellation notification. 856 variable_set('user_mail_status_canceled_notify', TRUE); 857 858 // Create administrative user. 859 $admin_user = $this->drupalCreateUser(array('administer users')); 860 $this->drupalLogin($admin_user); 861 862 // Create some users. 863 $users = array(); 864 for ($i = 0; $i < 3; $i++) { 865 $account = $this->drupalCreateUser(array()); 866 $users[$account->uid] = $account; 867 } 868 869 // Cancel user accounts, including own one. 870 $edit = array(); 871 $edit['operation'] = 'cancel'; 872 foreach ($users as $uid => $account) { 873 $edit['accounts[' . $uid . ']'] = TRUE; 874 } 875 $edit['accounts[' . $admin_user->uid . ']'] = TRUE; 876 // Also try to cancel uid 1. 877 $edit['accounts[1]'] = TRUE; 878 $this->drupalPost('admin/people', $edit, t('Update')); 879 $this->assertText(t('Are you sure you want to cancel these user accounts?'), t('Confirmation form to cancel accounts displayed.')); 880 $this->assertText(t('When cancelling these accounts'), t('Allows to select account cancellation method.')); 881 $this->assertText(t('Require e-mail confirmation to cancel account.'), t('Allows to send confirmation mail.')); 882 $this->assertText(t('Notify user when account is canceled.'), t('Allows to send notification mail.')); 883 884 // Confirm deletion. 885 $this->drupalPost(NULL, NULL, t('Cancel accounts')); 886 $status = TRUE; 887 foreach ($users as $account) { 888 $status = $status && (strpos($this->content, t('%name has been deleted.', array('%name' => $account->name))) !== FALSE); 889 $status = $status && !user_load($account->uid, TRUE); 890 } 891 $this->assertTrue($status, t('Users deleted and not found in the database.')); 892 893 // Ensure that admin account was not cancelled. 894 $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.')); 895 $admin_user = user_load($admin_user->uid); 896 $this->assertTrue($admin_user->status == 1, t('Administrative user is found in the database and enabled.')); 897 898 // Verify that uid 1's account was not cancelled. 899 $user1 = user_load(1, TRUE); 900 $this->assertEqual($user1->status, 1, t('User #1 still exists and is not blocked.')); 901 } 902 } 903 904 class UserPictureTestCase extends DrupalWebTestCase { 905 protected $user; 906 protected $_directory_test; 907 908 public static function getInfo() { 909 return array( 910 'name' => 'Upload user picture', 911 'description' => 'Assure that dimension check, extension check and image scaling work as designed.', 912 'group' => 'User' 913 ); 914 } 915 916 function setUp() { 917 parent::setUp(); 918 // Enable user pictures. 919 variable_set('user_pictures', 1); 920 921 $this->user = $this->drupalCreateUser(); 922 923 // Test if directories specified in settings exist in filesystem. 924 $file_dir = 'public://'; 925 $file_check = file_prepare_directory($file_dir, FILE_CREATE_DIRECTORY); 926 // TODO: Test public and private methods? 927 928 $picture_dir = variable_get('user_picture_path', 'pictures'); 929 $picture_path = $file_dir . $picture_dir; 930 931 $pic_check = file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY); 932 $this->_directory_test = is_writable($picture_path); 933 $this->assertTrue($this->_directory_test, "The directory $picture_path doesn't exist or is not writable. Further tests won't be made."); 934 } 935 936 function testNoPicture() { 937 $this->drupalLogin($this->user); 938 939 // Try to upload a file that is not an image for the user picture. 940 $not_an_image = current($this->drupalGetTestFiles('html')); 941 $this->saveUserPicture($not_an_image); 942 $this->assertRaw(t('Only JPEG, PNG and GIF images are allowed.'), t('Non-image files are not accepted.')); 943 } 944 945 /** 946 * Do the test: 947 * GD Toolkit is installed 948 * Picture has invalid dimension 949 * 950 * results: The image should be uploaded because ImageGDToolkit resizes the picture 951 */ 952 function testWithGDinvalidDimension() { 953 if ($this->_directory_test && image_get_toolkit()) { 954 $this->drupalLogin($this->user); 955 956 $image = current($this->drupalGetTestFiles('image')); 957 $info = image_get_info($image->uri); 958 959 // Set new variables: invalid dimensions, valid filesize (0 = no limit). 960 $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10); 961 variable_set('user_picture_dimensions', $test_dim); 962 variable_set('user_picture_file_size', 0); 963 964 $pic_path = $this->saveUserPicture($image); 965 // Check that the image was resized and is being displayed on the 966 // user's profile page. 967 $text = t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $test_dim)); 968 $this->assertRaw($text, t('Image was resized.')); 969 $alt = t("@user's picture", array('@user' => format_username($this->user))); 970 $style = variable_get('user_picture_style', ''); 971 $this->assertRaw(image_style_url($style, $pic_path), t("Image is displayed in user's edit page")); 972 973 // Check if file is located in proper directory. 974 $this->assertTrue(is_file($pic_path), t("File is located in proper directory")); 975 } 976 } 977 978 /** 979 * Do the test: 980 * GD Toolkit is installed 981 * Picture has invalid size 982 * 983 * results: The image should be uploaded because ImageGDToolkit resizes the picture 984 */ 985 function testWithGDinvalidSize() { 986 if ($this->_directory_test && image_get_toolkit()) { 987 $this->drupalLogin($this->user); 988 989 // Images are sorted first by size then by name. We need an image 990 // bigger than 1 KB so we'll grab the last one. 991 $files = $this->drupalGetTestFiles('image'); 992 $image = end($files); 993 $info = image_get_info($image->uri); 994 995 // Set new variables: valid dimensions, invalid filesize. 996 $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); 997 $test_size = 1; 998 variable_set('user_picture_dimensions', $test_dim); 999 variable_set('user_picture_file_size', $test_size); 1000 1001 $pic_path = $this->saveUserPicture($image); 1002 1003 // Test that the upload failed and that the correct reason was cited. 1004 $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename)); 1005 $this->assertRaw($text, t('Upload failed.')); 1006 $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->uri)), '%maxsize' => format_size($test_size * 1024))); 1007 $this->assertRaw($text, t('File size cited as reason for failure.')); 1008 1009 // Check if file is not uploaded. 1010 $this->assertFalse(is_file($pic_path), t('File was not uploaded.')); 1011 } 1012 } 1013 1014 /** 1015 * Do the test: 1016 * GD Toolkit is not installed 1017 * Picture has invalid size 1018 * 1019 * results: The image shouldn't be uploaded 1020 */ 1021 function testWithoutGDinvalidDimension() { 1022 if ($this->_directory_test && !image_get_toolkit()) { 1023 $this->drupalLogin($this->user); 1024 1025 $image = current($this->drupalGetTestFiles('image')); 1026 $info = image_get_info($image->uri); 1027 1028 // Set new variables: invalid dimensions, valid filesize (0 = no limit). 1029 $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10); 1030 variable_set('user_picture_dimensions', $test_dim); 1031 variable_set('user_picture_file_size', 0); 1032 1033 $pic_path = $this->saveUserPicture($image); 1034 1035 // Test that the upload failed and that the correct reason was cited. 1036 $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename)); 1037 $this->assertRaw($text, t('Upload failed.')); 1038 $text = t('The image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => $test_dim)); 1039 $this->assertRaw($text, t('Checking response on invalid image (dimensions).')); 1040 1041 // Check if file is not uploaded. 1042 $this->assertFalse(is_file($pic_path), t('File was not uploaded.')); 1043 } 1044 } 1045 1046 /** 1047 * Do the test: 1048 * GD Toolkit is not installed 1049 * Picture has invalid size 1050 * 1051 * results: The image shouldn't be uploaded 1052 */ 1053 function testWithoutGDinvalidSize() { 1054 if ($this->_directory_test && !image_get_toolkit()) { 1055 $this->drupalLogin($this->user); 1056 1057 $image = current($this->drupalGetTestFiles('image')); 1058 $info = image_get_info($image->uri); 1059 1060 // Set new variables: valid dimensions, invalid filesize. 1061 $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); 1062 $test_size = 1; 1063 variable_set('user_picture_dimensions', $test_dim); 1064 variable_set('user_picture_file_size', $test_size); 1065 1066 $pic_path = $this->saveUserPicture($image); 1067 1068 // Test that the upload failed and that the correct reason was cited. 1069 $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename)); 1070 $this->assertRaw($text, t('Upload failed.')); 1071 $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->uri)), '%maxsize' => format_size($test_size * 1024))); 1072 $this->assertRaw($text, t('File size cited as reason for failure.')); 1073 1074 // Check if file is not uploaded. 1075 $this->assertFalse(is_file($pic_path), t('File was not uploaded.')); 1076 } 1077 } 1078 1079 /** 1080 * Do the test: 1081 * Picture is valid (proper size and dimension) 1082 * 1083 * results: The image should be uploaded 1084 */ 1085 function testPictureIsValid() { 1086 if ($this->_directory_test) { 1087 $this->drupalLogin($this->user); 1088 1089 $image = current($this->drupalGetTestFiles('image')); 1090 $info = image_get_info($image->uri); 1091 1092 // Set new variables: valid dimensions, valid filesize (0 = no limit). 1093 $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); 1094 variable_set('user_picture_dimensions', $test_dim); 1095 variable_set('user_picture_file_size', 0); 1096 1097 $pic_path = $this->saveUserPicture($image); 1098 1099 // Check if image is displayed in user's profile page. 1100 $this->drupalGet('user'); 1101 $this->assertRaw(file_uri_target($pic_path), t("Image is displayed in user's profile page")); 1102 1103 // Check if file is located in proper directory. 1104 $this->assertTrue(is_file($pic_path), t('File is located in proper directory')); 1105 1106 // Set new picture dimensions. 1107 $test_dim = ($info['width'] + 5) . 'x' . ($info['height'] + 5); 1108 variable_set('user_picture_dimensions', $test_dim); 1109 1110 $pic_path2 = $this->saveUserPicture($image); 1111 $this->assertNotEqual($pic_path, $pic_path2, t('Filename of second picture is different.')); 1112 } 1113 } 1114 1115 /** 1116 * Test HTTP schema working with user pictures. 1117 */ 1118 function testExternalPicture() { 1119 $this->drupalLogin($this->user); 1120 // Set the default picture to an URI with a HTTP schema. 1121 $images = $this->drupalGetTestFiles('image'); 1122 $image = $images[0]; 1123 $pic_path = file_create_url($image->uri); 1124 variable_set('user_picture_default', $pic_path); 1125 1126 // Check if image is displayed in user's profile page. 1127 $this->drupalGet('user'); 1128 1129 // Get the user picture image via xpath. 1130 $elements = $this->xpath('//div[@class="user-picture"]/img'); 1131 $this->assertEqual(count($elements), 1, t("There is exactly one user picture on the user's profile page")); 1132 $this->assertEqual($pic_path, (string) $elements[0]['src'], t("User picture source is correct.")); 1133 } 1134 1135 /** 1136 * Tests deletion of user pictures. 1137 */ 1138 function testDeletePicture() { 1139 $this->drupalLogin($this->user); 1140 1141 $image = current($this->drupalGetTestFiles('image')); 1142 $info = image_get_info($image->uri); 1143 1144 // Set new variables: valid dimensions, valid filesize (0 = no limit). 1145 $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); 1146 variable_set('user_picture_dimensions', $test_dim); 1147 variable_set('user_picture_file_size', 0); 1148 1149 // Save a new picture. 1150 $edit = array('files[picture_upload]' => drupal_realpath($image->uri)); 1151 $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save')); 1152 1153 // Load actual user data from database. 1154 $account = user_load($this->user->uid, TRUE); 1155 $pic_path = isset($account->picture) ? $account->picture->uri : NULL; 1156 1157 // Check if image is displayed in user's profile page. 1158 $this->drupalGet('user'); 1159 $this->assertRaw(file_uri_target($pic_path), "Image is displayed in user's profile page"); 1160 1161 // Check if file is located in proper directory. 1162 $this->assertTrue(is_file($pic_path), 'File is located in proper directory'); 1163 1164 $edit = array('picture_delete' => 1); 1165 $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save')); 1166 1167 // Load actual user data from database. 1168 $account1 = user_load($this->user->uid, TRUE); 1169 $this->assertNull($account1->picture, 'User object has no picture'); 1170 1171 $file = file_load($account->picture->fid); 1172 $this->assertFalse($file, 'File is removed from database'); 1173 1174 // Clear out PHP's file stat cache so we see the current value. 1175 clearstatcache(); 1176 $this->assertFalse(is_file($pic_path), 'File is removed from file system'); 1177 } 1178 1179 function saveUserPicture($image) { 1180 $edit = array('files[picture_upload]' => drupal_realpath($image->uri)); 1181 $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save')); 1182 1183 // Load actual user data from database. 1184 $account = user_load($this->user->uid, TRUE); 1185 return isset($account->picture) ? $account->picture->uri : NULL; 1186 } 1187 1188 /** 1189 * Tests the admin form validates user picture settings. 1190 */ 1191 function testUserPictureAdminFormValidation() { 1192 $this->drupalLogin($this->drupalCreateUser(array('administer users'))); 1193 1194 // The default values are valid. 1195 $this->drupalPost('admin/config/people/accounts', array(), t('Save configuration')); 1196 $this->assertText(t('The configuration options have been saved.'), 'The default values are valid.'); 1197 1198 // The form does not save with an invalid file size. 1199 $edit = array( 1200 'user_picture_file_size' => $this->randomName(), 1201 ); 1202 $this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration')); 1203 $this->assertNoText(t('The configuration options have been saved.'), 'The form does not save with an invalid file size.'); 1204 } 1205 } 1206 1207 1208 class UserPermissionsTestCase extends DrupalWebTestCase { 1209 protected $admin_user; 1210 protected $rid; 1211 1212 public static function getInfo() { 1213 return array( 1214 'name' => 'Role permissions', 1215 'description' => 'Verify that role permissions can be added and removed via the permissions page.', 1216 'group' => 'User' 1217 ); 1218 } 1219 1220 function setUp() { 1221 parent::setUp(); 1222 1223 $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'access user profiles', 'administer site configuration', 'administer modules', 'administer users')); 1224 1225 // Find the new role ID - it must be the maximum. 1226 $all_rids = array_keys($this->admin_user->roles); 1227 sort($all_rids); 1228 $this->rid = array_pop($all_rids); 1229 } 1230 1231 /** 1232 * Change user permissions and check user_access(). 1233 */ 1234 function testUserPermissionChanges() { 1235 $this->drupalLogin($this->admin_user); 1236 $rid = $this->rid; 1237 $account = $this->admin_user; 1238 1239 // Add a permission. 1240 $this->assertFalse(user_access('administer nodes', $account), t('User does not have "administer nodes" permission.')); 1241 $edit = array(); 1242 $edit[$rid . '[administer nodes]'] = TRUE; 1243 $this->drupalPost('admin/people/permissions', $edit, t('Save permissions')); 1244 $this->assertText(t('The changes have been saved.'), t('Successful save message displayed.')); 1245 drupal_static_reset('user_access'); 1246 drupal_static_reset('user_role_permissions'); 1247 $this->assertTrue(user_access('administer nodes', $account), t('User now has "administer nodes" permission.')); 1248 1249 // Remove a permission. 1250 $this->assertTrue(user_access('access user profiles', $account), t('User has "access user profiles" permission.')); 1251 $edit = array(); 1252 $edit[$rid . '[access user profiles]'] = FALSE; 1253 $this->drupalPost('admin/people/permissions', $edit, t('Save permissions')); 1254 $this->assertText(t('The changes have been saved.'), t('Successful save message displayed.')); 1255 drupal_static_reset('user_access'); 1256 drupal_static_reset('user_role_permissions'); 1257 $this->assertFalse(user_access('access user profiles', $account), t('User no longer has "access user profiles" permission.')); 1258 } 1259 1260 /** 1261 * Test assigning of permissions for the administrator role. 1262 */ 1263 function testAdministratorRole() { 1264 $this->drupalLogin($this->admin_user); 1265 $this->drupalGet('admin/config/people/accounts'); 1266 1267 // Set the user's role to be the administrator role. 1268 $edit = array(); 1269 $edit['user_admin_role'] = $this->rid; 1270 $this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration')); 1271 1272 // Enable aggregator module and ensure the 'administer news feeds' 1273 // permission is assigned by default. 1274 $edit = array(); 1275 $edit['modules[Core][aggregator][enable]'] = TRUE; 1276 $this->drupalPost('admin/modules', $edit, t('Save configuration')); 1277 $this->assertTrue(user_access('administer news feeds', $this->admin_user), t('The permission was automatically assigned to the administrator role')); 1278 } 1279 1280 /** 1281 * Verify proper permission changes by user_role_change_permissions(). 1282 */ 1283 function testUserRoleChangePermissions() { 1284 $rid = $this->rid; 1285 $account = $this->admin_user; 1286 1287 // Verify current permissions. 1288 $this->assertFalse(user_access('administer nodes', $account), t('User does not have "administer nodes" permission.')); 1289 $this->assertTrue(user_access('access user profiles', $account), t('User has "access user profiles" permission.')); 1290 $this->assertTrue(user_access('administer site configuration', $account), t('User has "administer site configuration" permission.')); 1291 1292 // Change permissions. 1293 $permissions = array( 1294 'administer nodes' => 1, 1295 'access user profiles' => 0, 1296 ); 1297 user_role_change_permissions($rid, $permissions); 1298 1299 // Verify proper permission changes. 1300 $this->assertTrue(user_access('administer nodes', $account), t('User now has "administer nodes" permission.')); 1301 $this->assertFalse(user_access('access user profiles', $account), t('User no longer has "access user profiles" permission.')); 1302 $this->assertTrue(user_access('administer site configuration', $account), t('User still has "administer site configuration" permission.')); 1303 } 1304 } 1305 1306 class UserAdminTestCase extends DrupalWebTestCase { 1307 public static function getInfo() { 1308 return array( 1309 'name' => 'User administration', 1310 'description' => 'Test user administration page functionality.', 1311 'group' => 'User' 1312 ); 1313 } 1314 1315 /** 1316 * Registers a user and deletes it. 1317 */ 1318 function testUserAdmin() { 1319 1320 $user_a = $this->drupalCreateUser(array()); 1321 $user_b = $this->drupalCreateUser(array('administer taxonomy')); 1322 $user_c = $this->drupalCreateUser(array('administer taxonomy')); 1323 1324 // Create admin user to delete registered user. 1325 $admin_user = $this->drupalCreateUser(array('administer users')); 1326 $this->drupalLogin($admin_user); 1327 $this->drupalGet('admin/people'); 1328 $this->assertText($user_a->name, t('Found user A on admin users page')); 1329 $this->assertText($user_b->name, t('Found user B on admin users page')); 1330 $this->assertText($user_c->name, t('Found user C on admin users page')); 1331 $this->assertText($admin_user->name, t('Found Admin user on admin users page')); 1332 1333 // Test for existence of edit link in table. 1334 $link = l(t('edit'), "user/$user_a->uid/edit", array('query' => array('destination' => 'admin/people'))); 1335 $this->assertRaw($link, t('Found user A edit link on admin users page')); 1336 1337 // Filter the users by permission 'administer taxonomy'. 1338 $edit = array(); 1339 $edit['permission'] = 'administer taxonomy'; 1340 $this->drupalPost('admin/people', $edit, t('Filter')); 1341 1342 // Check if the correct users show up. 1343 $this->assertNoText($user_a->name, t('User A not on filtered by perm admin users page')); 1344 $this->assertText($user_b->name, t('Found user B on filtered by perm admin users page')); 1345 $this->assertText($user_c->name, t('Found user C on filtered by perm admin users page')); 1346 1347 // Filter the users by role. Grab the system-generated role name for User C. 1348 $edit['role'] = max(array_flip($user_c->roles)); 1349 $this->drupalPost('admin/people', $edit, t('Refine')); 1350 1351 // Check if the correct users show up when filtered by role. 1352 $this->assertNoText($user_a->name, t('User A not on filtered by role on admin users page')); 1353 $this->assertNoText($user_b->name, t('User B not on filtered by role on admin users page')); 1354 $this->assertText($user_c->name, t('User C on filtered by role on admin users page')); 1355 1356 // Test blocking of a user. 1357 $account = user_load($user_c->uid); 1358 $this->assertEqual($account->status, 1, 'User C not blocked'); 1359 $edit = array(); 1360 $edit['operation'] = 'block'; 1361 $edit['accounts[' . $account->uid . ']'] = TRUE; 1362 $this->drupalPost('admin/people', $edit, t('Update')); 1363 $account = user_load($user_c->uid, TRUE); 1364 $this->assertEqual($account->status, 0, 'User C blocked'); 1365 1366 // Test unblocking of a user from /admin/people page and sending of activation mail 1367 $editunblock = array(); 1368 $editunblock['operation'] = 'unblock'; 1369 $editunblock['accounts[' . $account->uid . ']'] = TRUE; 1370 $this->drupalPost('admin/people', $editunblock, t('Update')); 1371 $account = user_load($user_c->uid, TRUE); 1372 $this->assertEqual($account->status, 1, 'User C unblocked'); 1373 $this->assertMail("to", $account->mail, "Activation mail sent to user C"); 1374 1375 // Test blocking and unblocking another user from /user/[uid]/edit form and sending of activation mail 1376 $user_d = $this->drupalCreateUser(array()); 1377 $account1 = user_load($user_d->uid, TRUE); 1378 $this->drupalPost('user/' . $account1->uid . '/edit', array('status' => 0), t('Save')); 1379 $account1 = user_load($user_d->uid, TRUE); 1380 $this->assertEqual($account1->status, 0, 'User D blocked'); 1381 $this->drupalPost('user/' . $account1->uid . '/edit', array('status' => TRUE), t('Save')); 1382 $account1 = user_load($user_d->uid, TRUE); 1383 $this->assertEqual($account1->status, 1, 'User D unblocked'); 1384 $this->assertMail("to", $account1->mail, "Activation mail sent to user D"); 1385 } 1386 } 1387 1388 /** 1389 * Tests for user-configurable time zones. 1390 */ 1391 class UserTimeZoneFunctionalTest extends DrupalWebTestCase { 1392 public static function getInfo() { 1393 return array( 1394 'name' => 'User time zones', 1395 'description' => 'Set a user time zone and verify that dates are displayed in local time.', 1396 'group' => 'User', 1397 ); 1398 } 1399 1400 /** 1401 * Tests the display of dates and time when user-configurable time zones are set. 1402 */ 1403 function testUserTimeZone() { 1404 // Setup date/time settings for Los Angeles time. 1405 variable_set('date_default_timezone', 'America/Los_Angeles'); 1406 variable_set('configurable_timezones', 1); 1407 variable_set('date_format_medium', 'Y-m-d H:i T'); 1408 1409 // Create a user account and login. 1410 $web_user = $this->drupalCreateUser(); 1411 $this->drupalLogin($web_user); 1412 1413 // Create some nodes with different authored-on dates. 1414 // Two dates in PST (winter time): 1415 $date1 = '2007-03-09 21:00:00 -0800'; 1416 $date2 = '2007-03-11 01:00:00 -0800'; 1417 // One date in PDT (summer time): 1418 $date3 = '2007-03-20 21:00:00 -0700'; 1419 $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article')); 1420 $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article')); 1421 $node3 = $this->drupalCreateNode(array('created' => strtotime($date3), 'type' => 'article')); 1422 1423 // Confirm date format and time zone. 1424 $this->drupalGet("node/$node1->nid"); 1425 $this->assertText('2007-03-09 21:00 PST', t('Date should be PST.')); 1426 $this->drupalGet("node/$node2->nid"); 1427 $this->assertText('2007-03-11 01:00 PST', t('Date should be PST.')); 1428 $this->drupalGet("node/$node3->nid"); 1429 $this->assertText('2007-03-20 21:00 PDT', t('Date should be PDT.')); 1430 1431 // Change user time zone to Santiago time. 1432 $edit = array(); 1433 $edit['mail'] = $web_user->mail; 1434 $edit['timezone'] = 'America/Santiago'; 1435 $this->drupalPost("user/$web_user->uid/edit", $edit, t('Save')); 1436 $this->assertText(t('The changes have been saved.'), t('Time zone changed to Santiago time.')); 1437 1438 // Confirm date format and time zone. 1439 $this->drupalGet("node/$node1->nid"); 1440 $this->assertText('2007-03-10 02:00 CLST', t('Date should be Chile summer time; five hours ahead of PST.')); 1441 $this->drupalGet("node/$node2->nid"); 1442 $this->assertText('2007-03-11 05:00 CLT', t('Date should be Chile time; four hours ahead of PST')); 1443 $this->drupalGet("node/$node3->nid"); 1444 $this->assertText('2007-03-21 00:00 CLT', t('Date should be Chile time; three hours ahead of PDT.')); 1445 } 1446 } 1447 1448 /** 1449 * Test user autocompletion. 1450 */ 1451 class UserAutocompleteTestCase extends DrupalWebTestCase { 1452 public static function getInfo() { 1453 return array( 1454 'name' => 'User autocompletion', 1455 'description' => 'Test user autocompletion functionality.', 1456 'group' => 'User' 1457 ); 1458 } 1459 1460 function setUp() { 1461 parent::setUp(); 1462 1463 // Set up two users with different permissions to test access. 1464 $this->unprivileged_user = $this->drupalCreateUser(); 1465 $this->privileged_user = $this->drupalCreateUser(array('access user profiles')); 1466 } 1467 1468 /** 1469 * Tests access to user autocompletion and verify the correct results. 1470 */ 1471 function testUserAutocomplete() { 1472 // Check access from unprivileged user, should be denied. 1473 $this->drupalLogin($this->unprivileged_user); 1474 $this->drupalGet('user/autocomplete/' . $this->unprivileged_user->name[0]); 1475 $this->assertResponse(403, t('Autocompletion access denied to user without permission.')); 1476 1477 // Check access from privileged user. 1478 $this->drupalLogout(); 1479 $this->drupalLogin($this->privileged_user); 1480 $this->drupalGet('user/autocomplete/' . $this->unprivileged_user->name[0]); 1481 $this->assertResponse(200, t('Autocompletion access allowed.')); 1482 1483 // Using first letter of the user's name, make sure the user's full name is in the results. 1484 $this->assertRaw($this->unprivileged_user->name, t('User name found in autocompletion results.')); 1485 } 1486 } 1487 1488 1489 /** 1490 * Tests user links in the secondary menu. 1491 */ 1492 class UserAccountLinksUnitTests extends DrupalWebTestCase { 1493 public static function getInfo() { 1494 return array( 1495 'name' => 'User account links', 1496 'description' => 'Test user-account links.', 1497 'group' => 'User' 1498 ); 1499 } 1500 1501 function setUp() { 1502 parent::setUp('menu'); 1503 } 1504 1505 /** 1506 * Tests the secondary menu. 1507 */ 1508 function testSecondaryMenu() { 1509 // Create a regular user. 1510 $user = $this->drupalCreateUser(array()); 1511 1512 // Log in and get the homepage. 1513 $this->drupalLogin($user); 1514 $this->drupalGet('<front>'); 1515 1516 // For a logged-in user, expect the secondary menu to have links for "My 1517 // account" and "Log out". 1518 $link = $this->xpath('//ul[@id=:menu_id]/li/a[contains(@href, :href) and text()=:text]', array( 1519 ':menu_id' => 'secondary-menu-links', 1520 ':href' => 'user', 1521 ':text' => 'My account', 1522 )); 1523 $this->assertEqual(count($link), 1, 'My account link is in secondary menu.'); 1524 1525 $link = $this->xpath('//ul[@id=:menu_id]/li/a[contains(@href, :href) and text()=:text]', array( 1526 ':menu_id' => 'secondary-menu-links', 1527 ':href' => 'user/logout', 1528 ':text' => 'Log out', 1529 )); 1530 $this->assertEqual(count($link), 1, 'Log out link is in secondary menu.'); 1531 1532 // Log out and get the homepage. 1533 $this->drupalLogout(); 1534 $this->drupalGet('<front>'); 1535 1536 // For a logged-out user, expect no secondary links. 1537 $element = $this->xpath('//ul[@id=:menu_id]', array(':menu_id' => 'secondary-menu-links')); 1538 $this->assertEqual(count($element), 0, 'No secondary-menu for logged-out users.'); 1539 } 1540 1541 /** 1542 * Tests disabling the 'My account' link. 1543 */ 1544 function testDisabledAccountLink() { 1545 // Create an admin user and log in. 1546 $this->drupalLogin($this->drupalCreateUser(array('access administration pages', 'administer menu'))); 1547 1548 // Verify that the 'My account' link is enabled. 1549 $this->drupalGet('admin/structure/menu/manage/user-menu'); 1550 $this->assertFieldChecked('edit-mlid2-hidden', "The 'My account' link is enabled by default."); 1551 1552 // Disable the 'My account' link. 1553 $edit = array( 1554 'mlid:2[hidden]' => FALSE, 1555 ); 1556 $this->drupalPost('admin/structure/menu/manage/user-menu', $edit, t('Save configuration')); 1557 1558 // Get the homepage. 1559 $this->drupalGet('<front>'); 1560 1561 // Verify that the 'My account' link does not appear when disabled. 1562 $link = $this->xpath('//ul[@id=:menu_id]/li/a[contains(@href, :href) and text()=:text]', array( 1563 ':menu_id' => 'secondary-menu-links', 1564 ':href' => 'user', 1565 ':text' => 'My account', 1566 )); 1567 $this->assertEqual(count($link), 0, 'My account link is not in the secondary menu.'); 1568 } 1569 1570 } 1571 1572 /** 1573 * Test user blocks. 1574 */ 1575 class UserBlocksUnitTests extends DrupalWebTestCase { 1576 public static function getInfo() { 1577 return array( 1578 'name' => 'User blocks', 1579 'description' => 'Test user blocks.', 1580 'group' => 'User' 1581 ); 1582 } 1583 1584 /** 1585 * Test the user login block. 1586 */ 1587 function testUserLoginBlock() { 1588 // Create a user with some permission that anonymous users lack. 1589 $user = $this->drupalCreateUser(array('administer permissions')); 1590 1591 // Log in using the block. 1592 $edit = array(); 1593 $edit['name'] = $user->name; 1594 $edit['pass'] = $user->pass_raw; 1595 $this->drupalPost('admin/people/permissions', $edit, t('Log in')); 1596 $this->assertNoText(t('User login'), t('Logged in.')); 1597 1598 // Check that we are still on the same page. 1599 $this->assertEqual(url('admin/people/permissions', array('absolute' => TRUE)), $this->getUrl(), t('Still on the same page after login for access denied page')); 1600 1601 // Now, log out and repeat with a non-403 page. 1602 $this->drupalLogout(); 1603 $this->drupalPost('filter/tips', $edit, t('Log in')); 1604 $this->assertNoText(t('User login'), t('Logged in.')); 1605 $this->assertPattern('!<title.*?' . t('Compose tips') . '.*?</title>!', t('Still on the same page after login for allowed page')); 1606 1607 // Check that the user login block is not vulnerable to information 1608 // disclosure to third party sites. 1609 $this->drupalLogout(); 1610 $this->drupalPost('http://example.com/', $edit, t('Log in'), array('external' => FALSE)); 1611 // Check that we remain on the site after login. 1612 $this->assertEqual(url('user/' . $user->uid, array('absolute' => TRUE)), $this->getUrl(), t('Redirected to user profile page after login from the frontpage')); 1613 } 1614 1615 /** 1616 * Test the Who's Online block. 1617 */ 1618 function testWhosOnlineBlock() { 1619 // Generate users and make sure there are no current user sessions. 1620 $user1 = $this->drupalCreateUser(array()); 1621 $user2 = $this->drupalCreateUser(array()); 1622 $user3 = $this->drupalCreateUser(array()); 1623 $this->assertEqual(db_query("SELECT COUNT(*) FROM {sessions}")->fetchField(), 0, t('Sessions table is empty.')); 1624 1625 // Insert a user with two sessions. 1626 $this->insertSession(array('uid' => $user1->uid)); 1627 $this->insertSession(array('uid' => $user1->uid)); 1628 $this->assertEqual(db_query("SELECT COUNT(*) FROM {sessions} WHERE uid = :uid", array(':uid' => $user1->uid))->fetchField(), 2, t('Duplicate user session has been inserted.')); 1629 1630 // Insert a user with only one session. 1631 $this->insertSession(array('uid' => $user2->uid, 'timestamp' => REQUEST_TIME + 1)); 1632 1633 // Insert an inactive logged-in user who should not be seen in the block. 1634 $this->insertSession(array('uid' => $user3->uid, 'timestamp' => (REQUEST_TIME - variable_get('user_block_seconds_online', 900) - 1))); 1635 1636 // Insert two anonymous user sessions. 1637 $this->insertSession(); 1638 $this->insertSession(); 1639 1640 // Test block output. 1641 $block = user_block_view('online'); 1642 $this->drupalSetContent($block['content']); 1643 $this->assertRaw(t('2 users'), t('Correct number of online users (2 users).')); 1644 $this->assertText($user1->name, t('Active user 1 found in online list.')); 1645 $this->assertText($user2->name, t('Active user 2 found in online list.')); 1646 $this->assertNoText($user3->name, t("Inactive user not found in online list.")); 1647 $this->assertTrue(strpos($this->drupalGetContent(), $user1->name) > strpos($this->drupalGetContent(), $user2->name), t('Online users are ordered correctly.')); 1648 } 1649 1650 /** 1651 * Insert a user session into the {sessions} table. This function is used 1652 * since we cannot log in more than one user at the same time in tests. 1653 */ 1654 private function insertSession(array $fields = array()) { 1655 $fields += array( 1656 'uid' => 0, 1657 'sid' => drupal_hash_base64(uniqid(mt_rand(), TRUE)), 1658 'timestamp' => REQUEST_TIME, 1659 ); 1660 db_insert('sessions') 1661 ->fields($fields) 1662 ->execute(); 1663 $this->assertEqual(db_query("SELECT COUNT(*) FROM {sessions} WHERE uid = :uid AND sid = :sid AND timestamp = :timestamp", array(':uid' => $fields['uid'], ':sid' => $fields['sid'], ':timestamp' => $fields['timestamp']))->fetchField(), 1, t('Session record inserted.')); 1664 } 1665 } 1666 1667 /** 1668 * Tests saving a user account. 1669 */ 1670 class UserSaveTestCase extends DrupalWebTestCase { 1671 1672 public static function getInfo() { 1673 return array( 1674 'name' => 'User save test', 1675 'description' => 'Test user_save() for arbitrary new uid.', 1676 'group' => 'User', 1677 ); 1678 } 1679 1680 /** 1681 * Test creating a user with arbitrary uid. 1682 */ 1683 function testUserImport() { 1684 // User ID must be a number that is not in the database. 1685 $max_uid = db_query('SELECT MAX(uid) FROM {users}')->fetchField(); 1686 $test_uid = $max_uid + mt_rand(1000, 1000000); 1687 $test_name = $this->randomName(); 1688 1689 // Create the base user, based on drupalCreateUser(). 1690 $user = array( 1691 'name' => $test_name, 1692 'uid' => $test_uid, 1693 'mail' => $test_name . '@example.com', 1694 'is_new' => TRUE, 1695 'pass' => user_password(), 1696 'status' => 1, 1697 ); 1698 $user_by_return = user_save(drupal_anonymous_user(), $user); 1699 $this->assertTrue($user_by_return, t('Loading user by return of user_save().')); 1700 1701 // Test if created user exists. 1702 $user_by_uid = user_load($test_uid); 1703 $this->assertTrue($user_by_uid, t('Loading user by uid.')); 1704 1705 $user_by_name = user_load_by_name($test_name); 1706 $this->assertTrue($user_by_name, t('Loading user by name.')); 1707 } 1708 } 1709 1710 /** 1711 * Test the create user administration page. 1712 */ 1713 class UserCreateTestCase extends DrupalWebTestCase { 1714 1715 public static function getInfo() { 1716 return array( 1717 'name' => 'User create', 1718 'description' => 'Test the create user administration page.', 1719 'group' => 'User', 1720 ); 1721 } 1722 1723 /** 1724 * Create a user through the administration interface and ensure that it 1725 * displays in the user list. 1726 */ 1727 protected function testUserAdd() { 1728 $user = $this->drupalCreateUser(array('administer users')); 1729 $this->drupalLogin($user); 1730 1731 foreach (array(FALSE, TRUE) as $notify) { 1732 $edit = array( 1733 'name' => $this->randomName(), 1734 'mail' => $this->randomName() . '@example.com', 1735 'pass[pass1]' => $pass = $this->randomString(), 1736 'pass[pass2]' => $pass, 1737 'notify' => $notify, 1738 ); 1739 $this->drupalPost('admin/people/create', $edit, t('Create new account')); 1740 1741 if ($notify) { 1742 $this->assertText(t('A welcome message with further instructions has been e-mailed to the new user @name.', array('@name' => $edit['name'])), 'User created'); 1743 $this->assertEqual(count($this->drupalGetMails()), 1, 'Notification e-mail sent'); 1744 } 1745 else { 1746 $this->assertText(t('Created a new user account for @name. No e-mail has been sent.', array('@name' => $edit['name'])), 'User created'); 1747 $this->assertEqual(count($this->drupalGetMails()), 0, 'Notification e-mail not sent'); 1748 } 1749 1750 $this->drupalGet('admin/people'); 1751 $this->assertText($edit['name'], 'User found in list of users'); 1752 } 1753 } 1754 } 1755 1756 /** 1757 * Tests editing a user account. 1758 */ 1759 class UserEditTestCase extends DrupalWebTestCase { 1760 1761 public static function getInfo() { 1762 return array( 1763 'name' => 'User edit', 1764 'description' => 'Test user edit page.', 1765 'group' => 'User', 1766 ); 1767 } 1768 1769 /** 1770 * Test user edit page. 1771 */ 1772 function testUserEdit() { 1773 // Test user edit functionality with user pictures disabled. 1774 variable_set('user_pictures', 0); 1775 $user1 = $this->drupalCreateUser(array('change own username')); 1776 $user2 = $this->drupalCreateUser(array()); 1777 $this->drupalLogin($user1); 1778 1779 // Test that error message appears when attempting to use a non-unique user name. 1780 $edit['name'] = $user2->name; 1781 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1782 $this->assertRaw(t('The name %name is already taken.', array('%name' => $edit['name']))); 1783 1784 // Repeat the test with user pictures enabled, which modifies the form. 1785 variable_set('user_pictures', 1); 1786 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1787 $this->assertRaw(t('The name %name is already taken.', array('%name' => $edit['name']))); 1788 1789 // Check that filling out a single password field does not validate. 1790 $edit = array(); 1791 $edit['pass[pass1]'] = ''; 1792 $edit['pass[pass2]'] = $this->randomName(); 1793 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1794 $this->assertText(t("The specified passwords do not match."), t('Typing mismatched passwords displays an error message.')); 1795 1796 $edit['pass[pass1]'] = $this->randomName(); 1797 $edit['pass[pass2]'] = ''; 1798 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1799 $this->assertText(t("The specified passwords do not match."), t('Typing mismatched passwords displays an error message.')); 1800 1801 // Test that the error message appears when attempting to change the mail or 1802 // pass without the current password. 1803 $edit = array(); 1804 $edit['mail'] = $this->randomName() . '@new.example.com'; 1805 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1806 $this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => t('E-mail address')))); 1807 1808 $edit['current_pass'] = $user1->pass_raw; 1809 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1810 $this->assertRaw(t("The changes have been saved.")); 1811 1812 // Test that the user must enter current password before changing passwords. 1813 $edit = array(); 1814 $edit['pass[pass1]'] = $new_pass = $this->randomName(); 1815 $edit['pass[pass2]'] = $new_pass; 1816 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1817 $this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => t('Password')))); 1818 1819 // Try again with the current password. 1820 $edit['current_pass'] = $user1->pass_raw; 1821 $this->drupalPost("user/$user1->uid/edit", $edit, t('Save')); 1822 $this->assertRaw(t("The changes have been saved.")); 1823 1824 // Make sure the user can log in with their new password. 1825 $this->drupalLogout(); 1826 $user1->pass_raw = $new_pass; 1827 $this->drupalLogin($user1); 1828 $this->drupalLogout(); 1829 } 1830 } 1831 1832 /** 1833 * Test case for user signatures. 1834 */ 1835 class UserSignatureTestCase extends DrupalWebTestCase { 1836 public static function getInfo() { 1837 return array( 1838 'name' => 'User signatures', 1839 'description' => 'Test user signatures.', 1840 'group' => 'User', 1841 ); 1842 } 1843 1844 function setUp() { 1845 parent::setUp('comment'); 1846 1847 // Enable user signatures. 1848 variable_set('user_signatures', 1); 1849 1850 // Prefetch text formats. 1851 $this->full_html_format = filter_format_load('full_html'); 1852 $this->plain_text_format = filter_format_load('plain_text'); 1853 1854 // Create regular and administrative users. 1855 $this->web_user = $this->drupalCreateUser(array()); 1856 $admin_permissions = array('administer comments'); 1857 foreach (filter_formats() as $format) { 1858 if ($permission = filter_permission_name($format)) { 1859 $admin_permissions[] = $permission; 1860 } 1861 } 1862 $this->admin_user = $this->drupalCreateUser($admin_permissions); 1863 } 1864 1865 /** 1866 * Test that a user can change their signature format and that it is respected 1867 * upon display. 1868 */ 1869 function testUserSignature() { 1870 // Create a new node with comments on. 1871 $node = $this->drupalCreateNode(array('comment' => COMMENT_NODE_OPEN)); 1872 1873 // Verify that user signature field is not displayed on registration form. 1874 $this->drupalGet('user/register'); 1875 $this->assertNoText(t('Signature')); 1876 1877 // Log in as a regular user and create a signature. 1878 $this->drupalLogin($this->web_user); 1879 $signature_text = "<h1>" . $this->randomName() . "</h1>"; 1880 $edit = array( 1881 'signature[value]' => $signature_text, 1882 'signature[format]' => $this->plain_text_format->format, 1883 ); 1884 $this->drupalPost('user/' . $this->web_user->uid . '/edit', $edit, t('Save')); 1885 1886 // Verify that values were stored. 1887 $this->assertFieldByName('signature[value]', $edit['signature[value]'], 'Submitted signature text found.'); 1888 $this->assertFieldByName('signature[format]', $edit['signature[format]'], 'Submitted signature format found.'); 1889 1890 // Create a comment. 1891 $langcode = LANGUAGE_NONE; 1892 $edit = array(); 1893 $edit['subject'] = $this->randomName(8); 1894 $edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16); 1895 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview')); 1896 $this->drupalPost(NULL, array(), t('Save')); 1897 1898 // Get the comment ID. (This technique is the same one used in the Comment 1899 // module's CommentHelperCase test case.) 1900 preg_match('/#comment-([0-9]+)/', $this->getURL(), $match); 1901 $comment_id = $match[1]; 1902 1903 // Log in as an administrator and edit the comment to use Full HTML, so 1904 // that the comment text itself is not filtered at all. 1905 $this->drupalLogin($this->admin_user); 1906 $edit['comment_body[' . $langcode . '][0][format]'] = $this->full_html_format->format; 1907 $this->drupalPost('comment/' . $comment_id . '/edit', $edit, t('Save')); 1908 1909 // Assert that the signature did not make it through unfiltered. 1910 $this->drupalGet('node/' . $node->nid); 1911 $this->assertNoRaw($signature_text, 'Unfiltered signature text not found.'); 1912 $this->assertRaw(check_markup($signature_text, $this->plain_text_format->format), 'Filtered signature text found.'); 1913 } 1914 } 1915 1916 /* 1917 * Test that a user, having editing their own account, can still log in. 1918 */ 1919 class UserEditedOwnAccountTestCase extends DrupalWebTestCase { 1920 1921 public static function getInfo() { 1922 return array( 1923 'name' => 'User edited own account', 1924 'description' => 'Test user edited own account can still log in.', 1925 'group' => 'User', 1926 ); 1927 } 1928 1929 function testUserEditedOwnAccount() { 1930 // Change account setting 'Who can register accounts?' to Administrators 1931 // only. 1932 variable_set('user_register', USER_REGISTER_ADMINISTRATORS_ONLY); 1933 1934 // Create a new user account and log in. 1935 $account = $this->drupalCreateUser(array('change own username')); 1936 $this->drupalLogin($account); 1937 1938 // Change own username. 1939 $edit = array(); 1940 $edit['name'] = $this->randomName(); 1941 $this->drupalPost('user/' . $account->uid . '/edit', $edit, t('Save')); 1942 1943 // Log out. 1944 $this->drupalLogout(); 1945 1946 // Set the new name on the user account and attempt to log back in. 1947 $account->name = $edit['name']; 1948 $this->drupalLogin($account); 1949 } 1950 } 1951 1952 /** 1953 * Test case to test adding, editing and deleting roles. 1954 */ 1955 class UserRoleAdminTestCase extends DrupalWebTestCase { 1956 1957 public static function getInfo() { 1958 return array( 1959 'name' => 'User role administration', 1960 'description' => 'Test adding, editing and deleting user roles and changing role weights.', 1961 'group' => 'User', 1962 ); 1963 } 1964 1965 function setUp() { 1966 parent::setUp(); 1967 $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'administer users')); 1968 } 1969 1970 /** 1971 * Test adding, renaming and deleting roles. 1972 */ 1973 function testRoleAdministration() { 1974 $this->drupalLogin($this->admin_user); 1975 1976 // Test adding a role. (In doing so, we use a role name that happens to 1977 // correspond to an integer, to test that the role administration pages 1978 // correctly distinguish between role names and IDs.) 1979 $role_name = '123'; 1980 $edit = array('name' => $role_name); 1981 $this->drupalPost('admin/people/permissions/roles', $edit, t('Add role')); 1982 $this->assertText(t('The role has been added.'), t('The role has been added.')); 1983 $role = user_role_load_by_name($role_name); 1984 $this->assertTrue(is_object($role), t('The role was successfully retrieved from the database.')); 1985 1986 // Try adding a duplicate role. 1987 $this->drupalPost(NULL, $edit, t('Add role')); 1988 $this->assertRaw(t('The role name %name already exists. Choose another role name.', array('%name' => $role_name)), t('Duplicate role warning displayed.')); 1989 1990 // Test renaming a role. 1991 $old_name = $role_name; 1992 $role_name = '456'; 1993 $edit = array('name' => $role_name); 1994 $this->drupalPost("admin/people/permissions/roles/edit/{$role->rid}", $edit, t('Save role')); 1995 $this->assertText(t('The role has been renamed.'), t('The role has been renamed.')); 1996 $this->assertFalse(user_role_load_by_name($old_name), t('The role can no longer be retrieved from the database using its old name.')); 1997 $this->assertTrue(is_object(user_role_load_by_name($role_name)), t('The role can be retrieved from the database using its new name.')); 1998 1999 // Test deleting a role. 2000 $this->drupalPost("admin/people/permissions/roles/edit/{$role->rid}", NULL, t('Delete role')); 2001 $this->drupalPost(NULL, NULL, t('Delete')); 2002 $this->assertText(t('The role has been deleted.'), t('The role has been deleted')); 2003 $this->assertNoLinkByHref("admin/people/permissions/roles/edit/{$role->rid}", t('Role edit link removed.')); 2004 $this->assertFalse(user_role_load_by_name($role_name), t('A deleted role can no longer be loaded.')); 2005 2006 // Make sure that the system-defined roles cannot be edited via the user 2007 // interface. 2008 $this->drupalGet('admin/people/permissions/roles/edit/' . DRUPAL_ANONYMOUS_RID); 2009 $this->assertResponse(403, t('Access denied when trying to edit the built-in anonymous role.')); 2010 $this->drupalGet('admin/people/permissions/roles/edit/' . DRUPAL_AUTHENTICATED_RID); 2011 $this->assertResponse(403, t('Access denied when trying to edit the built-in authenticated role.')); 2012 } 2013 2014 /** 2015 * Test user role weight change operation. 2016 */ 2017 function testRoleWeightChange() { 2018 $this->drupalLogin($this->admin_user); 2019 2020 // Pick up a random role and get its weight. 2021 $rid = array_rand(user_roles()); 2022 $role = user_role_load($rid); 2023 $old_weight = $role->weight; 2024 2025 // Change the role weight and submit the form. 2026 $edit = array('roles['. $rid .'][weight]' => $old_weight + 1); 2027 $this->drupalPost('admin/people/permissions/roles', $edit, t('Save order')); 2028 $this->assertText(t('The role settings have been updated.'), t('The role settings form submitted successfully.')); 2029 2030 // Retrieve the saved role and compare its weight. 2031 $role = user_role_load($rid); 2032 $new_weight = $role->weight; 2033 $this->assertTrue(($old_weight + 1) == $new_weight, t('Role weight updated successfully.')); 2034 } 2035 } 2036 2037 /** 2038 * Test user token replacement in strings. 2039 */ 2040 class UserTokenReplaceTestCase extends DrupalWebTestCase { 2041 public static function getInfo() { 2042 return array( 2043 'name' => 'User token replacement', 2044 'description' => 'Generates text using placeholders for dummy content to check user token replacement.', 2045 'group' => 'User', 2046 ); 2047 } 2048 2049 /** 2050 * Creates a user, then tests the tokens generated from it. 2051 */ 2052 function testUserTokenReplacement() { 2053 global $language; 2054 $url_options = array( 2055 'absolute' => TRUE, 2056 'language' => $language, 2057 ); 2058 2059 // Create two users and log them in one after another. 2060 $user1 = $this->drupalCreateUser(array()); 2061 $user2 = $this->drupalCreateUser(array()); 2062 $this->drupalLogin($user1); 2063 $this->drupalLogout(); 2064 $this->drupalLogin($user2); 2065 2066 $account = user_load($user1->uid); 2067 $global_account = user_load($GLOBALS['user']->uid); 2068 2069 // Generate and test sanitized tokens. 2070 $tests = array(); 2071 $tests['[user:uid]'] = $account->uid; 2072 $tests['[user:name]'] = check_plain(format_username($account)); 2073 $tests['[user:mail]'] = check_plain($account->mail); 2074 $tests['[user:url]'] = url("user/$account->uid", $url_options); 2075 $tests['[user:edit-url]'] = url("user/$account->uid/edit", $url_options); 2076 $tests['[user:last-login]'] = format_date($account->login, 'medium', '', NULL, $language->language); 2077 $tests['[user:last-login:short]'] = format_date($account->login, 'short', '', NULL, $language->language); 2078 $tests['[user:created]'] = format_date($account->created, 'medium', '', NULL, $language->language); 2079 $tests['[user:created:short]'] = format_date($account->created, 'short', '', NULL, $language->language); 2080 $tests['[current-user:name]'] = check_plain(format_username($global_account)); 2081 2082 // Test to make sure that we generated something for each token. 2083 $this->assertFalse(in_array(0, array_map('strlen', $tests)), t('No empty tokens generated.')); 2084 2085 foreach ($tests as $input => $expected) { 2086 $output = token_replace($input, array('user' => $account), array('language' => $language)); 2087 $this->assertEqual($output, $expected, t('Sanitized user token %token replaced.', array('%token' => $input))); 2088 } 2089 2090 // Generate and test unsanitized tokens. 2091 $tests['[user:name]'] = format_username($account); 2092 $tests['[user:mail]'] = $account->mail; 2093 $tests['[current-user:name]'] = format_username($global_account); 2094 2095 foreach ($tests as $input => $expected) { 2096 $output = token_replace($input, array('user' => $account), array('language' => $language, 'sanitize' => FALSE)); 2097 $this->assertEqual($output, $expected, t('Unsanitized user token %token replaced.', array('%token' => $input))); 2098 } 2099 } 2100 } 2101 2102 /** 2103 * Test user search. 2104 */ 2105 class UserUserSearchTestCase extends DrupalWebTestCase { 2106 public static function getInfo() { 2107 return array( 2108 'name' => 'User search', 2109 'description' => 'Testing that only user with the right permission can see the email address in the user search.', 2110 'group' => 'User', 2111 ); 2112 } 2113 2114 function testUserSearch() { 2115 $user1 = $this->drupalCreateUser(array('access user profiles', 'search content', 'use advanced search')); 2116 $this->drupalLogin($user1); 2117 $keys = $user1->mail; 2118 $edit = array('keys' => $keys); 2119 $this->drupalPost('search/user/', $edit, t('Search')); 2120 $this->assertNoText($keys); 2121 $this->drupalLogout(); 2122 2123 $user2 = $this->drupalCreateUser(array('administer users', 'access user profiles', 'search content', 'use advanced search')); 2124 $this->drupalLogin($user2); 2125 $keys = $user2->mail; 2126 $edit = array('keys' => $keys); 2127 $this->drupalPost('search/user/', $edit, t('Search')); 2128 $this->assertText($keys); 2129 $this->drupalLogout(); 2130 } 2131 } 2132 2133 2134 /** 2135 * Test role assignment. 2136 */ 2137 class UserRolesAssignmentTestCase extends DrupalWebTestCase { 2138 protected $admin_user; 2139 2140 public static function getInfo() { 2141 return array( 2142 'name' => t('Role assignment'), 2143 'description' => t('Tests that users can be assigned and unassigned roles.'), 2144 'group' => t('User') 2145 ); 2146 } 2147 2148 function setUp() { 2149 parent::setUp(); 2150 $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'administer users')); 2151 $this->drupalLogin($this->admin_user); 2152 } 2153 2154 /** 2155 * Tests that a user can be assigned a role and that the role can be removed 2156 * again. 2157 */ 2158 function testAssignAndRemoveRole() { 2159 $rid = $this->drupalCreateRole(array('administer content types')); 2160 $account = $this->drupalCreateUser(); 2161 2162 // Assign the role to the user. 2163 $this->drupalPost('user/' . $account->uid . '/edit', array("roles[$rid]" => $rid), t('Save')); 2164 $this->assertText(t('The changes have been saved.')); 2165 $this->assertFieldChecked('edit-roles-' . $rid, t('Role is assigned.')); 2166 $this->userLoadAndCheckRoleAssigned($account, $rid); 2167 2168 // Remove the role from the user. 2169 $this->drupalPost('user/' . $account->uid . '/edit', array("roles[$rid]" => FALSE), t('Save')); 2170 $this->assertText(t('The changes have been saved.')); 2171 $this->assertNoFieldChecked('edit-roles-' . $rid, t('Role is removed from user.')); 2172 $this->userLoadAndCheckRoleAssigned($account, $rid, FALSE); 2173 } 2174 2175 /** 2176 * Tests that when creating a user the role can be assigned. And that it can 2177 * be removed again. 2178 */ 2179 function testCreateUserWithRole() { 2180 $rid = $this->drupalCreateRole(array('administer content types')); 2181 // Create a new user and add the role at the same time. 2182 $edit = array( 2183 'name' => $this->randomName(), 2184 'mail' => $this->randomName() . '@example.com', 2185 'pass[pass1]' => $pass = $this->randomString(), 2186 'pass[pass2]' => $pass, 2187 "roles[$rid]" => $rid, 2188 ); 2189 $this->drupalPost('admin/people/create', $edit, t('Create new account')); 2190 $this->assertText(t('Created a new user account for !name.', array('!name' => $edit['name']))); 2191 // Get the newly added user. 2192 $account = user_load_by_name($edit['name']); 2193 2194 $this->drupalGet('user/' . $account->uid . '/edit'); 2195 $this->assertFieldChecked('edit-roles-' . $rid, t('Role is assigned.')); 2196 $this->userLoadAndCheckRoleAssigned($account, $rid); 2197 2198 // Remove the role again. 2199 $this->drupalPost('user/' . $account->uid . '/edit', array("roles[$rid]" => FALSE), t('Save')); 2200 $this->assertText(t('The changes have been saved.')); 2201 $this->assertNoFieldChecked('edit-roles-' . $rid, t('Role is removed from user.')); 2202 $this->userLoadAndCheckRoleAssigned($account, $rid, FALSE); 2203 } 2204 2205 /** 2206 * Check role on user object. 2207 * 2208 * @param object $account 2209 * The user account to check. 2210 * @param string $rid 2211 * The role ID to search for. 2212 * @param bool $is_assigned 2213 * (optional) Whether to assert that $rid exists (TRUE) or not (FALSE). 2214 * Defaults to TRUE. 2215 */ 2216 private function userLoadAndCheckRoleAssigned($account, $rid, $is_assigned = TRUE) { 2217 $account = user_load($account->uid, TRUE); 2218 if ($is_assigned) { 2219 $this->assertTrue(array_key_exists($rid, $account->roles), t('The role is present in the user object.')); 2220 } 2221 else { 2222 $this->assertFalse(array_key_exists($rid, $account->roles), t('The role is not present in the user object.')); 2223 } 2224 } 2225 } 2226 2227 2228 /** 2229 * Unit test for authmap assignment. 2230 */ 2231 class UserAuthmapAssignmentTestCase extends DrupalWebTestCase { 2232 public static function getInfo() { 2233 return array( 2234 'name' => t('Authmap assignment'), 2235 'description' => t('Tests that users can be assigned and unassigned authmaps.'), 2236 'group' => t('User') 2237 ); 2238 } 2239 2240 /** 2241 * Test authmap assignment and retrieval. 2242 */ 2243 function testAuthmapAssignment() { 2244 $account = $this->drupalCreateUser(); 2245 2246 // Assign authmaps to the user. 2247 $authmaps = array( 2248 'authname_poll' => 'external username one', 2249 'authname_book' => 'external username two', 2250 ); 2251 user_set_authmaps($account, $authmaps); 2252 2253 // Test for expected authmaps. 2254 $expected_authmaps = array( 2255 'external username one' => array( 2256 'poll' => 'external username one', 2257 ), 2258 'external username two' => array( 2259 'book' => 'external username two', 2260 ), 2261 ); 2262 foreach ($expected_authmaps as $authname => $expected_output) { 2263 $this->assertIdentical(user_get_authmaps($authname), $expected_output, t('Authmap for authname %authname was set correctly.', array('%authname' => $authname))); 2264 } 2265 2266 // Remove authmap for module poll, add authmap for module blog. 2267 $authmaps = array( 2268 'authname_poll' => NULL, 2269 'authname_blog' => 'external username three', 2270 ); 2271 user_set_authmaps($account, $authmaps); 2272 2273 // Assert that external username one does not have authmaps. 2274 $remove_username = 'external username one'; 2275 unset($expected_authmaps[$remove_username]); 2276 $this->assertFalse(user_get_authmaps($remove_username), t('Authmap for %authname was removed.', array('%authname' => $remove_username))); 2277 2278 // Assert that a new authmap was created for external username three, and 2279 // existing authmaps for external username two were unchanged. 2280 $expected_authmaps['external username three'] = array('blog' => 'external username three'); 2281 foreach ($expected_authmaps as $authname => $expected_output) { 2282 $this->assertIdentical(user_get_authmaps($authname), $expected_output, t('Authmap for authname %authname was set correctly.', array('%authname' => $authname))); 2283 } 2284 } 2285 } 2286 2287 /** 2288 * Tests user_validate_current_pass on a custom form. 2289 */ 2290 class UserValidateCurrentPassCustomForm extends DrupalWebTestCase { 2291 2292 public static function getInfo() { 2293 return array( 2294 'name' => 'User validate current pass custom form', 2295 'description' => 'Test that user_validate_current_pass is usable on a custom form.', 2296 'group' => 'User', 2297 ); 2298 } 2299 2300 /** 2301 * User with permission to view content. 2302 */ 2303 protected $accessUser; 2304 2305 /** 2306 * User permission to administer users. 2307 */ 2308 protected $adminUser; 2309 2310 function setUp() { 2311 parent::setUp('user_form_test'); 2312 // Create two users 2313 $this->accessUser = $this->drupalCreateUser(array('access content')); 2314 $this->adminUser = $this->drupalCreateUser(array('administer users')); 2315 } 2316 2317 /** 2318 * Tests that user_validate_current_pass can be reused on a custom form. 2319 */ 2320 function testUserValidateCurrentPassCustomForm() { 2321 $this->drupalLogin($this->adminUser); 2322 2323 // Submit the custom form with the admin user using the access user's password. 2324 $edit = array(); 2325 $edit['user_form_test_field'] = $this->accessUser->name; 2326 $edit['current_pass'] = $this->accessUser->pass_raw; 2327 $this->drupalPost('user_form_test_current_password/' . $this->accessUser->uid, $edit, t('Test')); 2328 $this->assertText(t('The password has been validated and the form submitted successfully.')); 2329 } 2330 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title