Drupal PHP Cross Reference Content Management Systems

Source: /modules/user/user.test - 2330 lines - 97238 bytes - Summary - Text - Print

   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 \'&nbsp;&nbsp;\'', '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

title

Description

title

Description

title

title

Body