Projet

Général

Profil

Paste
Télécharger (110 ko) Statistiques
| Branche: | Révision:

root / drupal7 / modules / user / user.test @ 27e02aed

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, '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.'), '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, '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, '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.'), '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.'), '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.'), '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)), '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'), '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)), '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)), '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>', '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, 'Username matches.');
163
    $this->assertEqual($new_user->mail, $mail, 'E-mail address matches.');
164
    $this->assertEqual($new_user->theme, '', 'Correct theme field.');
165
    $this->assertEqual($new_user->signature, '', 'Correct signature field.');
166
    $this->assertTrue(($new_user->created > REQUEST_TIME - 20 ), 'Correct creation time.');
167
    $this->assertEqual($new_user->status, variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) == USER_REGISTER_VISITORS ? 1 : 0, 'Correct status field.');
168
    $this->assertEqual($new_user->timezone, variable_get('date_default_timezone'), 'Correct time zone field.');
169
    $this->assertEqual($new_user->language, '', 'Correct language field.');
170
    $this->assertEqual($new_user->picture, '', 'Correct picture field.');
171
    $this->assertEqual($new_user->init, $mail, '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'], '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'], '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'])), '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'])), '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, 'The field value was correctly 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, format_string('@js : The field value was correclty saved.', array('@js' => $js)));
254
      $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][1]['value'], $value + 1, format_string('@js : The field value was correclty saved.', array('@js' => $js)));
255
      $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][2]['value'], $value + 2, format_string('@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
      'foo+bar'                => array('Valid username', 'assertNull'), // '+' symbol is allowed
280
      'ᚠᛇᚻ᛫ᛒᛦᚦ'                => array('Valid UTF8 username', 'assertNull'), // runes
281
      ' foo'                   => array('Invalid username that starts with a space', 'assertNotNull'),
282
      'foo '                   => array('Invalid username that ends with a space', 'assertNotNull'),
283
      'foo  bar'               => array('Invalid username that contains 2 spaces \'&nbsp;&nbsp;\'', 'assertNotNull'),
284
      ''                       => array('Invalid empty username', 'assertNotNull'),
285
      'foo/'                   => array('Invalid username containing invalid chars', 'assertNotNull'),
286
      'foo' . chr(0) . 'bar'   => array('Invalid username containing chr(0)', 'assertNotNull'), // NULL
287
      'foo' . chr(13) . 'bar'  => array('Invalid username containing chr(13)', 'assertNotNull'), // CR
288
      str_repeat('x', USERNAME_MAX_LENGTH + 1) => array('Invalid excessively long username', 'assertNotNull'),
289
    );
290
    foreach ($test_cases as $name => $test_case) {
291
      list($description, $test) = $test_case;
292
      $result = user_validate_name($name);
293
      $this->$test($result, $description . ' (' . $name . ')');
294
    }
295
  }
296

    
297
  // Mail validation. More extensive tests can be found at common.test
298
  function testMailAddresses() {
299
    $test_cases = array( // '<username>' => array('<description>', 'assert<testName>'),
300
      ''                => array('Empty mail address', 'assertNotNull'),
301
      'foo'             => array('Invalid mail address', 'assertNotNull'),
302
      'foo@example.com' => array('Valid mail address', 'assertNull'),
303
    );
304
    foreach ($test_cases as $name => $test_case) {
305
      list($description, $test) = $test_case;
306
      $result = user_validate_mail($name);
307
      $this->$test($result, $description . ' (' . $name . ')');
308
    }
309
  }
310
}
311

    
312
/**
313
 * Functional tests for user logins, including rate limiting of login attempts.
314
 */
315
class UserLoginTestCase extends DrupalWebTestCase {
316
  public static function getInfo() {
317
    return array(
318
      'name' => 'User login',
319
      'description' => 'Ensure that login works as expected.',
320
      'group' => 'User',
321
    );
322
  }
323

    
324
  function setUp() {
325
    parent::setUp('user_session_test');
326
  }
327

    
328
  /**
329
   * Test the global login flood control.
330
   */
331
  function testGlobalLoginFloodControl() {
332
    // Set the global login limit.
333
    variable_set('user_failed_login_ip_limit', 10);
334
    // Set a high per-user limit out so that it is not relevant in the test.
335
    variable_set('user_failed_login_user_limit', 4000);
336

    
337
    $user1 = $this->drupalCreateUser(array());
338
    $incorrect_user1 = clone $user1;
339
    $incorrect_user1->pass_raw .= 'incorrect';
340

    
341
    // Try 2 failed logins.
342
    for ($i = 0; $i < 2; $i++) {
343
      $this->assertFailedLogin($incorrect_user1);
344
    }
345

    
346
    // A successful login will not reset the IP-based flood control count.
347
    $this->drupalLogin($user1);
348
    $this->drupalLogout();
349

    
350
    // Try 8 more failed logins, they should not trigger the flood control
351
    // mechanism.
352
    for ($i = 0; $i < 8; $i++) {
353
      $this->assertFailedLogin($incorrect_user1);
354
    }
355

    
356
    // The next login trial should result in an IP-based flood error message.
357
    $this->assertFailedLogin($incorrect_user1, 'ip');
358

    
359
    // A login with the correct password should also result in a flood error
360
    // message.
361
    $this->assertFailedLogin($user1, 'ip');
362
  }
363

    
364
  /**
365
   * Test the per-user login flood control.
366
   */
367
  function testPerUserLoginFloodControl() {
368
    // Set a high global limit out so that it is not relevant in the test.
369
    variable_set('user_failed_login_ip_limit', 4000);
370
    // Set the per-user login limit.
371
    variable_set('user_failed_login_user_limit', 3);
372

    
373
    $user1 = $this->drupalCreateUser(array());
374
    $incorrect_user1 = clone $user1;
375
    $incorrect_user1->pass_raw .= 'incorrect';
376

    
377
    $user2 = $this->drupalCreateUser(array());
378

    
379
    // Try 2 failed logins.
380
    for ($i = 0; $i < 2; $i++) {
381
      $this->assertFailedLogin($incorrect_user1);
382
    }
383

    
384
    // A successful login will reset the per-user flood control count.
385
    $this->drupalLogin($user1);
386
    $this->drupalLogout();
387

    
388
    // Try 3 failed logins for user 1, they will not trigger flood control.
389
    for ($i = 0; $i < 3; $i++) {
390
      $this->assertFailedLogin($incorrect_user1);
391
    }
392

    
393
    // Try one successful attempt for user 2, it should not trigger any
394
    // flood control.
395
    $this->drupalLogin($user2);
396
    $this->drupalLogout();
397

    
398
    // Try one more attempt for user 1, it should be rejected, even if the
399
    // correct password has been used.
400
    $this->assertFailedLogin($user1, 'user');
401
  }
402

    
403
  /**
404
   * Test that user password is re-hashed upon login after changing $count_log2.
405
   */
406
  function testPasswordRehashOnLogin() {
407
    // Load password hashing API.
408
    require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
409
    // Set initial $count_log2 to the default, DRUPAL_HASH_COUNT.
410
    variable_set('password_count_log2', DRUPAL_HASH_COUNT);
411
    // Create a new user and authenticate.
412
    $account = $this->drupalCreateUser(array());
413
    $password = $account->pass_raw;
414
    $this->drupalLogin($account);
415
    $this->drupalLogout();
416
    // Load the stored user. The password hash should reflect $count_log2.
417
    $account = user_load($account->uid);
418
    $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_HASH_COUNT);
419
    // Change $count_log2 and log in again.
420
    variable_set('password_count_log2', DRUPAL_HASH_COUNT + 1);
421
    $account->pass_raw = $password;
422
    $this->drupalLogin($account);
423
    // Load the stored user, which should have a different password hash now.
424
    $account = user_load($account->uid, TRUE);
425
    $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_HASH_COUNT + 1);
426
  }
427

    
428
  /**
429
   * Test logging in when an anon session already exists.
430
   */
431
  function testLoginWithAnonSession() {
432
    // Visit the callback to generate a session for this anon user.
433
    $this->drupalGet('user_session_test_anon_session');
434
    // Now login.
435
    $account = $this->drupalCreateUser(array());
436
    $this->drupalLogin($account);
437
  }
438

    
439
  /**
440
   * Make an unsuccessful login attempt.
441
   *
442
   * @param $account
443
   *   A user object with name and pass_raw attributes for the login attempt.
444
   * @param $flood_trigger
445
   *   Whether or not to expect that the flood control mechanism will be
446
   *   triggered.
447
   */
448
  function assertFailedLogin($account, $flood_trigger = NULL) {
449
    $edit = array(
450
      'name' => $account->name,
451
      'pass' => $account->pass_raw,
452
    );
453
    $this->drupalPost('user', $edit, t('Log in'));
454
    $this->assertNoFieldByXPath("//input[@name='pass' and @value!='']", NULL, 'Password value attribute is blank.');
455
    if (isset($flood_trigger)) {
456
      if ($flood_trigger == 'user') {
457
        $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'))));
458
      }
459
      else {
460
        // No uid, so the limit is IP-based.
461
        $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'))));
462
      }
463
    }
464
    else {
465
      $this->assertText(t('Sorry, unrecognized username or password. Have you forgotten your password?'));
466
    }
467
  }
468
}
469

    
470
/**
471
 * Tests resetting a user password.
472
 */
473
class UserPasswordResetTestCase extends DrupalWebTestCase {
474
  protected $profile = 'standard';
475

    
476
  public static function getInfo() {
477
    return array(
478
      'name' => 'Reset password',
479
      'description' => 'Ensure that password reset methods work as expected.',
480
      'group' => 'User',
481
    );
482
  }
483

    
484
  /**
485
   * Retrieves password reset email and extracts the login link.
486
   */
487
  public function getResetURL() {
488
    // Assume the most recent email.
489
    $_emails = $this->drupalGetMails();
490
    $email = end($_emails);
491
    $urls = array();
492
    preg_match('#.+user/reset/.+#', $email['body'], $urls);
493

    
494
    return $urls[0];
495
  }
496

    
497
  /**
498
   * Tests password reset functionality.
499
   */
500
  function testUserPasswordReset() {
501
    // Create a user.
502
    $account = $this->drupalCreateUser();
503
    $this->drupalLogin($account);
504
    $this->drupalLogout();
505
    // Attempt to reset password.
506
    $edit = array('name' => $account->name);
507
    $this->drupalPost('user/password', $edit, t('E-mail new password'));
508
    // Confirm the password reset.
509
    $this->assertText(t('Further instructions have been sent to your e-mail address.'), 'Password reset instructions mailed message displayed.');
510

    
511
    // Create an image field to enable an Ajax request on the user profile page.
512
    $field = array(
513
      'field_name' => 'field_avatar',
514
      'type' => 'image',
515
      'settings' => array(),
516
      'cardinality' => 1,
517
    );
518
    field_create_field($field);
519

    
520
    $instance = array(
521
      'field_name' => $field['field_name'],
522
      'entity_type' => 'user',
523
      'label' => 'Avatar',
524
      'bundle' => 'user',
525
      'required' => FALSE,
526
      'settings' => array(),
527
      'widget' => array(
528
        'type' => 'image_image',
529
        'settings' => array(),
530
      ),
531
    );
532
    field_create_instance($instance);
533

    
534
    $resetURL = $this->getResetURL();
535
    $this->drupalGet($resetURL);
536

    
537
    // Check successful login.
538
    $this->drupalPost(NULL, NULL, t('Log in'));
539

    
540
    // Make sure the Ajax request from uploading a file does not invalidate the
541
    // reset token.
542
    $image = current($this->drupalGetTestFiles('image'));
543
    $edit = array(
544
      'files[field_avatar_und_0]' => drupal_realpath($image->uri),
545
    );
546
    $this->drupalPostAJAX(NULL, $edit, 'field_avatar_und_0_upload_button');
547

    
548
    // Change the forgotten password.
549
    $password = user_password();
550
    $edit = array('pass[pass1]' => $password, 'pass[pass2]' => $password);
551
    $this->drupalPost(NULL, $edit, t('Save'));
552
    $this->assertText(t('The changes have been saved.'), 'Forgotten password changed.');
553
  }
554

    
555
  /**
556
   * Test user password reset while logged in.
557
   */
558
  function testUserPasswordResetLoggedIn() {
559
    $account = $this->drupalCreateUser();
560
    $this->drupalLogin($account);
561
    // Make sure the test account has a valid password.
562
    user_save($account, array('pass' => user_password()));
563

    
564
    // Generate one time login link.
565
    $reset_url = user_pass_reset_url($account);
566
    $this->drupalGet($reset_url);
567

    
568
    $this->assertText('Reset password');
569
    $this->drupalPost(NULL, NULL, t('Log in'));
570

    
571
    $this->assertText('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.');
572

    
573
    $pass = user_password();
574
    $edit = array(
575
      'pass[pass1]' => $pass,
576
      'pass[pass2]' => $pass,
577
    );
578
    $this->drupalPost(NULL, $edit, t('Save'));
579

    
580
    $this->assertText('The changes have been saved.');
581
  }
582

    
583
  /**
584
   * Attempts login using an expired password reset link.
585
   */
586
  function testUserPasswordResetExpired() {
587
    // Set password reset timeout variable to 43200 seconds = 12 hours.
588
    $timeout = 43200;
589
    variable_set('user_password_reset_timeout', $timeout);
590

    
591
    // Create a user.
592
    $account = $this->drupalCreateUser();
593
    $this->drupalLogin($account);
594
    // Load real user object.
595
    $account = user_load($account->uid, TRUE);
596
    $this->drupalLogout();
597

    
598
    // To attempt an expired password reset, create a password reset link as if
599
    // its request time was 60 seconds older than the allowed limit of timeout.
600
    $bogus_timestamp = REQUEST_TIME - variable_get('user_password_reset_timeout', 86400) - 60;
601
    $this->drupalGet("user/reset/$account->uid/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login, $account->uid));
602
    $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.');
603
  }
604

    
605
  /**
606
   * Prefill the text box on incorrect login via link to password reset page.
607
   */
608
  function testUserPasswordTextboxFilled() {
609
    $this->drupalGet('user/login');
610
    $edit = array(
611
      'name' => $this->randomName(),
612
      'pass' => $this->randomName(),
613
    );
614
    $this->drupalPost('user', $edit, t('Log in'));
615
    $this->assertRaw(t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>',
616
      array('@password' => url('user/password', array('query' => array('name' => $edit['name']))))));
617
    unset($edit['pass']);
618
    $this->drupalGet('user/password', array('query' => array('name' => $edit['name'])));
619
    $this->assertFieldByName('name', $edit['name'], 'User name found.');
620
  }
621

    
622
  /**
623
   * Make sure that users cannot forge password reset URLs of other users.
624
   */
625
  function testResetImpersonation() {
626
    // Make sure user 1 has a valid password, so it does not interfere with the
627
    // test user accounts that are created below.
628
    $account = user_load(1);
629
    user_save($account, array('pass' => user_password()));
630

    
631
    // Create two identical user accounts except for the user name. They must
632
    // have the same empty password, so we can't use $this->drupalCreateUser().
633
    $edit = array();
634
    $edit['name'] = $this->randomName();
635
    $edit['mail'] = $edit['name'] . '@example.com';
636
    $edit['status'] = 1;
637

    
638
    $user1 = user_save(drupal_anonymous_user(), $edit);
639

    
640
    $edit['name'] = $this->randomName();
641
    $user2 = user_save(drupal_anonymous_user(), $edit);
642

    
643
    // The password reset URL must not be valid for the second user when only
644
    // the user ID is changed in the URL.
645
    $reset_url = user_pass_reset_url($user1);
646
    $attack_reset_url = str_replace("user/reset/$user1->uid", "user/reset/$user2->uid", $reset_url);
647
    $this->drupalGet($attack_reset_url);
648
    $this->assertNoText($user2->name, 'The invalid password reset page does not show the user name.');
649
    $this->assertUrl('user/password', array(), 'The user is redirected to the password reset request page.');
650
    $this->assertText('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.');
651

    
652
    // When legacy code calls user_pass_rehash() without providing the $uid
653
    // parameter, neither password reset URL should be valid since it is
654
    // impossible for the system to determine which user account the token was
655
    // intended for.
656
    $timestamp = REQUEST_TIME;
657
    // Pass an explicit NULL for the $uid parameter of user_pass_rehash()
658
    // rather than not passing it at all, to avoid triggering PHP warnings in
659
    // the test.
660
    $reset_url_token = user_pass_rehash($user1->pass, $timestamp, $user1->login, NULL);
661
    $reset_url = url("user/reset/$user1->uid/$timestamp/$reset_url_token", array('absolute' => TRUE));
662
    $this->drupalGet($reset_url);
663
    $this->assertNoText($user1->name, 'The invalid password reset page does not show the user name.');
664
    $this->assertUrl('user/password', array(), 'The user is redirected to the password reset request page.');
665
    $this->assertText('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.');
666
    $attack_reset_url = str_replace("user/reset/$user1->uid", "user/reset/$user2->uid", $reset_url);
667
    $this->drupalGet($attack_reset_url);
668
    $this->assertNoText($user2->name, 'The invalid password reset page does not show the user name.');
669
    $this->assertUrl('user/password', array(), 'The user is redirected to the password reset request page.');
670
    $this->assertText('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.');
671

    
672
    // To verify that user_pass_rehash() never returns a valid result in the
673
    // above situation (even if legacy code also called it to attempt to
674
    // validate the token, rather than just to generate the URL), check that a
675
    // second call with the same parameters produces a different result.
676
    $new_reset_url_token = user_pass_rehash($user1->pass, $timestamp, $user1->login, NULL);
677
    $this->assertNotEqual($reset_url_token, $new_reset_url_token);
678

    
679
    // However, when the duplicate account is removed, the password reset URL
680
    // should be valid.
681
    user_delete($user2->uid);
682
    $reset_url_token = user_pass_rehash($user1->pass, $timestamp, $user1->login, NULL);
683
    $reset_url = url("user/reset/$user1->uid/$timestamp/$reset_url_token", array('absolute' => TRUE));
684
    $this->drupalGet($reset_url);
685
    $this->assertText($user1->name, 'The valid password reset page shows the user name.');
686
    $this->assertUrl($reset_url, array(), 'The user remains on the password reset login page.');
687
    $this->assertNoText('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.');
688
  }
689

    
690
}
691

    
692
/**
693
 * Test cancelling a user.
694
 */
695
class UserCancelTestCase extends DrupalWebTestCase {
696
  public static function getInfo() {
697
    return array(
698
      'name' => 'Cancel account',
699
      'description' => 'Ensure that account cancellation methods work as expected.',
700
      'group' => 'User',
701
    );
702
  }
703

    
704
  function setUp() {
705
    parent::setUp('comment');
706
  }
707

    
708
  /**
709
   * Attempt to cancel account without permission.
710
   */
711
  function testUserCancelWithoutPermission() {
712
    variable_set('user_cancel_method', 'user_cancel_reassign');
713

    
714
    // Create a user.
715
    $account = $this->drupalCreateUser(array());
716
    $this->drupalLogin($account);
717
    // Load real user object.
718
    $account = user_load($account->uid, TRUE);
719

    
720
    // Create a node.
721
    $node = $this->drupalCreateNode(array('uid' => $account->uid));
722

    
723
    // Attempt to cancel account.
724
    $this->drupalGet('user/' . $account->uid . '/edit');
725
    $this->assertNoRaw(t('Cancel account'), 'No cancel account button displayed.');
726

    
727
    // Attempt bogus account cancellation request confirmation.
728
    $timestamp = $account->login;
729
    $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
730
    $this->assertResponse(403, 'Bogus cancelling request rejected.');
731
    $account = user_load($account->uid);
732
    $this->assertTrue($account->status == 1, 'User account was not canceled.');
733

    
734
    // Confirm user's content has not been altered.
735
    $test_node = node_load($node->nid, NULL, TRUE);
736
    $this->assertTrue(($test_node->uid == $account->uid && $test_node->status == 1), 'Node of the user has not been altered.');
737
  }
738

    
739
  /**
740
   * Tests that user account for uid 1 cannot be cancelled.
741
   *
742
   * This should never be possible, or the site owner would become unable to
743
   * administer the site.
744
   */
745
  function testUserCancelUid1() {
746
    // Update uid 1's name and password to we know it.
747
    $password = user_password();
748
    require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
749
    $account = array(
750
      'name' => 'user1',
751
      'pass' => user_hash_password(trim($password)),
752
    );
753
    // We cannot use user_save() here or the password would be hashed again.
754
    db_update('users')
755
      ->fields($account)
756
      ->condition('uid', 1)
757
      ->execute();
758

    
759
    // Reload and log in uid 1.
760
    $user1 = user_load(1, TRUE);
761
    $user1->pass_raw = $password;
762

    
763
    // Try to cancel uid 1's account with a different user.
764
    $this->admin_user = $this->drupalCreateUser(array('administer users'));
765
    $this->drupalLogin($this->admin_user);
766
    $edit = array(
767
      'operation' => 'cancel',
768
      'accounts[1]' => TRUE,
769
    );
770
    $this->drupalPost('admin/people', $edit, t('Update'));
771

    
772
    // Verify that uid 1's account was not cancelled.
773
    $user1 = user_load(1, TRUE);
774
    $this->assertEqual($user1->status, 1, 'User #1 still exists and is not blocked.');
775
  }
776

    
777
  /**
778
   * Attempt invalid account cancellations.
779
   */
780
  function testUserCancelInvalid() {
781
    variable_set('user_cancel_method', 'user_cancel_reassign');
782

    
783
    // Create a user.
784
    $account = $this->drupalCreateUser(array('cancel account'));
785
    $this->drupalLogin($account);
786
    // Load real user object.
787
    $account = user_load($account->uid, TRUE);
788

    
789
    // Create a node.
790
    $node = $this->drupalCreateNode(array('uid' => $account->uid));
791

    
792
    // Attempt to cancel account.
793
    $this->drupalPost('user/' . $account->uid . '/edit', NULL, t('Cancel account'));
794

    
795
    // Confirm account cancellation.
796
    $timestamp = time();
797
    $this->drupalPost(NULL, NULL, t('Cancel account'));
798
    $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), 'Account cancellation request mailed message displayed.');
799

    
800
    // Attempt bogus account cancellation request confirmation.
801
    $bogus_timestamp = $timestamp + 60;
802
    $this->drupalGet("user/$account->uid/cancel/confirm/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login, $account->uid));
803
    $this->assertText(t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'), 'Bogus cancelling request rejected.');
804
    $account = user_load($account->uid);
805
    $this->assertTrue($account->status == 1, 'User account was not canceled.');
806

    
807
    // Attempt expired account cancellation request confirmation.
808
    $bogus_timestamp = $timestamp - 86400 - 60;
809
    $this->drupalGet("user/$account->uid/cancel/confirm/$bogus_timestamp/" . user_pass_rehash($account->pass, $bogus_timestamp, $account->login, $account->uid));
810
    $this->assertText(t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'), 'Expired cancel account request rejected.');
811
    $accounts = user_load_multiple(array($account->uid), array('status' => 1));
812
    $this->assertTrue(reset($accounts), 'User account was not canceled.');
813

    
814
    // Confirm user's content has not been altered.
815
    $test_node = node_load($node->nid, NULL, TRUE);
816
    $this->assertTrue(($test_node->uid == $account->uid && $test_node->status == 1), 'Node of the user has not been altered.');
817
  }
818

    
819
  /**
820
   * Disable account and keep all content.
821
   */
822
  function testUserBlock() {
823
    variable_set('user_cancel_method', 'user_cancel_block');
824

    
825
    // Create a user.
826
    $web_user = $this->drupalCreateUser(array('cancel account'));
827
    $this->drupalLogin($web_user);
828

    
829
    // Load real user object.
830
    $account = user_load($web_user->uid, TRUE);
831

    
832
    // Attempt to cancel account.
833
    $this->drupalGet('user/' . $account->uid . '/edit');
834
    $this->drupalPost(NULL, NULL, t('Cancel account'));
835
    $this->assertText(t('Are you sure you want to cancel your account?'), 'Confirmation form to cancel account displayed.');
836
    $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.'), 'Informs that all content will be remain as is.');
837
    $this->assertNoText(t('Select the method to cancel the account above.'), 'Does not allow user to select account cancellation method.');
838

    
839
    // Confirm account cancellation.
840
    $timestamp = time();
841

    
842
    $this->drupalPost(NULL, NULL, t('Cancel account'));
843
    $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), 'Account cancellation request mailed message displayed.');
844

    
845
    // Confirm account cancellation request.
846
    $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
847
    $account = user_load($account->uid, TRUE);
848
    $this->assertTrue($account->status == 0, 'User has been blocked.');
849

    
850
    // Confirm that the confirmation message made it through to the end user.
851
    $this->assertRaw(t('%name has been disabled.', array('%name' => $account->name)), "Confirmation message displayed to user.");
852
  }
853

    
854
  /**
855
   * Disable account and unpublish all content.
856
   */
857
  function testUserBlockUnpublish() {
858
    variable_set('user_cancel_method', 'user_cancel_block_unpublish');
859

    
860
    // Create a user.
861
    $account = $this->drupalCreateUser(array('cancel account'));
862
    $this->drupalLogin($account);
863
    // Load real user object.
864
    $account = user_load($account->uid, TRUE);
865

    
866
    // Create a node with two revisions.
867
    $node = $this->drupalCreateNode(array('uid' => $account->uid));
868
    $settings = get_object_vars($node);
869
    $settings['revision'] = 1;
870
    $node = $this->drupalCreateNode($settings);
871

    
872
    // Attempt to cancel account.
873
    $this->drupalGet('user/' . $account->uid . '/edit');
874
    $this->drupalPost(NULL, NULL, t('Cancel account'));
875
    $this->assertText(t('Are you sure you want to cancel your account?'), 'Confirmation form to cancel account displayed.');
876
    $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.'), 'Informs that all content will be unpublished.');
877

    
878
    // Confirm account cancellation.
879
    $timestamp = time();
880
    $this->drupalPost(NULL, NULL, t('Cancel account'));
881
    $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), 'Account cancellation request mailed message displayed.');
882

    
883
    // Confirm account cancellation request.
884
    $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
885
    $account = user_load($account->uid, TRUE);
886
    $this->assertTrue($account->status == 0, 'User has been blocked.');
887

    
888
    // Confirm user's content has been unpublished.
889
    $test_node = node_load($node->nid, NULL, TRUE);
890
    $this->assertTrue($test_node->status == 0, 'Node of the user has been unpublished.');
891
    $test_node = node_load($node->nid, $node->vid, TRUE);
892
    $this->assertTrue($test_node->status == 0, 'Node revision of the user has been unpublished.');
893

    
894
    // Confirm that the confirmation message made it through to the end user.
895
    $this->assertRaw(t('%name has been disabled.', array('%name' => $account->name)), "Confirmation message displayed to user.");
896
  }
897

    
898
  /**
899
   * Delete account and anonymize all content.
900
   */
901
  function testUserAnonymize() {
902
    variable_set('user_cancel_method', 'user_cancel_reassign');
903

    
904
    // Create a user.
905
    $account = $this->drupalCreateUser(array('cancel account'));
906
    $this->drupalLogin($account);
907
    // Load real user object.
908
    $account = user_load($account->uid, TRUE);
909

    
910
    // Create a simple node.
911
    $node = $this->drupalCreateNode(array('uid' => $account->uid));
912

    
913
    // Create a node with two revisions, the initial one belonging to the
914
    // cancelling user.
915
    $revision_node = $this->drupalCreateNode(array('uid' => $account->uid));
916
    $revision = $revision_node->vid;
917
    $settings = get_object_vars($revision_node);
918
    $settings['revision'] = 1;
919
    $settings['uid'] = 1; // Set new/current revision to someone else.
920
    $revision_node = $this->drupalCreateNode($settings);
921

    
922
    // Attempt to cancel account.
923
    $this->drupalGet('user/' . $account->uid . '/edit');
924
    $this->drupalPost(NULL, NULL, t('Cancel account'));
925
    $this->assertText(t('Are you sure you want to cancel your account?'), 'Confirmation form to cancel account displayed.');
926
    $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')))), 'Informs that all content will be attributed to anonymous account.');
927

    
928
    // Confirm account cancellation.
929
    $timestamp = time();
930
    $this->drupalPost(NULL, NULL, t('Cancel account'));
931
    $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), 'Account cancellation request mailed message displayed.');
932

    
933
    // Confirm account cancellation request.
934
    $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
935
    $this->assertFalse(user_load($account->uid, TRUE), 'User is not found in the database.');
936

    
937
    // Confirm that user's content has been attributed to anonymous user.
938
    $test_node = node_load($node->nid, NULL, TRUE);
939
    $this->assertTrue(($test_node->uid == 0 && $test_node->status == 1), 'Node of the user has been attributed to anonymous user.');
940
    $test_node = node_load($revision_node->nid, $revision, TRUE);
941
    $this->assertTrue(($test_node->revision_uid == 0 && $test_node->status == 1), 'Node revision of the user has been attributed to anonymous user.');
942
    $test_node = node_load($revision_node->nid, NULL, TRUE);
943
    $this->assertTrue(($test_node->uid != 0 && $test_node->status == 1), "Current revision of the user's node was not attributed to anonymous user.");
944

    
945
    // Confirm that the confirmation message made it through to the end user.
946
    $this->assertRaw(t('%name has been deleted.', array('%name' => $account->name)), "Confirmation message displayed to user.");
947
  }
948

    
949
  /**
950
   * Delete account and remove all content.
951
   */
952
  function testUserDelete() {
953
    variable_set('user_cancel_method', 'user_cancel_delete');
954

    
955
    // Create a user.
956
    $account = $this->drupalCreateUser(array('cancel account', 'post comments', 'skip comment approval'));
957
    $this->drupalLogin($account);
958
    // Load real user object.
959
    $account = user_load($account->uid, TRUE);
960

    
961
    // Create a simple node.
962
    $node = $this->drupalCreateNode(array('uid' => $account->uid));
963

    
964
    // Create comment.
965
    $langcode = LANGUAGE_NONE;
966
    $edit = array();
967
    $edit['subject'] = $this->randomName(8);
968
    $edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16);
969

    
970
    $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
971
    $this->drupalPost(NULL, array(), t('Save'));
972
    $this->assertText(t('Your comment has been posted.'));
973
    $comments = comment_load_multiple(array(), array('subject' => $edit['subject']));
974
    $comment = reset($comments);
975
    $this->assertTrue($comment->cid, 'Comment found.');
976

    
977
    // Create a node with two revisions, the initial one belonging to the
978
    // cancelling user.
979
    $revision_node = $this->drupalCreateNode(array('uid' => $account->uid));
980
    $revision = $revision_node->vid;
981
    $settings = get_object_vars($revision_node);
982
    $settings['revision'] = 1;
983
    $settings['uid'] = 1; // Set new/current revision to someone else.
984
    $revision_node = $this->drupalCreateNode($settings);
985

    
986
    // Attempt to cancel account.
987
    $this->drupalGet('user/' . $account->uid . '/edit');
988
    $this->drupalPost(NULL, NULL, t('Cancel account'));
989
    $this->assertText(t('Are you sure you want to cancel your account?'), 'Confirmation form to cancel account displayed.');
990
    $this->assertText(t('Your account will be removed and all account information deleted. All of your content will also be deleted.'), 'Informs that all content will be deleted.');
991

    
992
    // Confirm account cancellation.
993
    $timestamp = time();
994
    $this->drupalPost(NULL, NULL, t('Cancel account'));
995
    $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), 'Account cancellation request mailed message displayed.');
996

    
997
    // Confirm account cancellation request.
998
    $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid));
999
    $this->assertFalse(user_load($account->uid, TRUE), 'User is not found in the database.');
1000

    
1001
    // Confirm that user's content has been deleted.
1002
    $this->assertFalse(node_load($node->nid, NULL, TRUE), 'Node of the user has been deleted.');
1003
    $this->assertFalse(node_load($node->nid, $revision, TRUE), 'Node revision of the user has been deleted.');
1004
    $this->assertTrue(node_load($revision_node->nid, NULL, TRUE), "Current revision of the user's node was not deleted.");
1005
    $this->assertFalse(comment_load($comment->cid), 'Comment of the user has been deleted.');
1006

    
1007
    // Confirm that the confirmation message made it through to the end user.
1008
    $this->assertRaw(t('%name has been deleted.', array('%name' => $account->name)), "Confirmation message displayed to user.");
1009
  }
1010

    
1011
  /**
1012
   * Create an administrative user and delete another user.
1013
   */
1014
  function testUserCancelByAdmin() {
1015
    variable_set('user_cancel_method', 'user_cancel_reassign');
1016

    
1017
    // Create a regular user.
1018
    $account = $this->drupalCreateUser(array());
1019

    
1020
    // Create administrative user.
1021
    $admin_user = $this->drupalCreateUser(array('administer users'));
1022
    $this->drupalLogin($admin_user);
1023

    
1024
    // Delete regular user.
1025
    $this->drupalGet('user/' . $account->uid . '/edit');
1026
    $this->drupalPost(NULL, NULL, t('Cancel account'));
1027
    $this->assertRaw(t('Are you sure you want to cancel the account %name?', array('%name' => $account->name)), 'Confirmation form to cancel account displayed.');
1028
    $this->assertText(t('Select the method to cancel the account above.'), 'Allows to select account cancellation method.');
1029

    
1030
    // Confirm deletion.
1031
    $this->drupalPost(NULL, NULL, t('Cancel account'));
1032
    $this->assertRaw(t('%name has been deleted.', array('%name' => $account->name)), 'User deleted.');
1033
    $this->assertFalse(user_load($account->uid), 'User is not found in the database.');
1034
  }
1035

    
1036
  /**
1037
   * Create an administrative user and mass-delete other users.
1038
   */
1039
  function testMassUserCancelByAdmin() {
1040
    variable_set('user_cancel_method', 'user_cancel_reassign');
1041
    // Enable account cancellation notification.
1042
    variable_set('user_mail_status_canceled_notify', TRUE);
1043

    
1044
    // Create administrative user.
1045
    $admin_user = $this->drupalCreateUser(array('administer users'));
1046
    $this->drupalLogin($admin_user);
1047

    
1048
    // Create some users.
1049
    $users = array();
1050
    for ($i = 0; $i < 3; $i++) {
1051
      $account = $this->drupalCreateUser(array());
1052
      $users[$account->uid] = $account;
1053
    }
1054

    
1055
    // Cancel user accounts, including own one.
1056
    $edit = array();
1057
    $edit['operation'] = 'cancel';
1058
    foreach ($users as $uid => $account) {
1059
      $edit['accounts[' . $uid . ']'] = TRUE;
1060
    }
1061
    $edit['accounts[' . $admin_user->uid . ']'] = TRUE;
1062
    // Also try to cancel uid 1.
1063
    $edit['accounts[1]'] = TRUE;
1064
    $this->drupalPost('admin/people', $edit, t('Update'));
1065
    $this->assertText(t('Are you sure you want to cancel these user accounts?'), 'Confirmation form to cancel accounts displayed.');
1066
    $this->assertText(t('When cancelling these accounts'), 'Allows to select account cancellation method.');
1067
    $this->assertText(t('Require e-mail confirmation to cancel account.'), 'Allows to send confirmation mail.');
1068
    $this->assertText(t('Notify user when account is canceled.'), 'Allows to send notification mail.');
1069

    
1070
    // Confirm deletion.
1071
    $this->drupalPost(NULL, NULL, t('Cancel accounts'));
1072
    $status = TRUE;
1073
    foreach ($users as $account) {
1074
      $status = $status && (strpos($this->content, t('%name has been deleted.', array('%name' => $account->name))) !== FALSE);
1075
      $status = $status && !user_load($account->uid, TRUE);
1076
    }
1077
    $this->assertTrue($status, 'Users deleted and not found in the database.');
1078

    
1079
    // Ensure that admin account was not cancelled.
1080
    $this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), 'Account cancellation request mailed message displayed.');
1081
    $admin_user = user_load($admin_user->uid);
1082
    $this->assertTrue($admin_user->status == 1, 'Administrative user is found in the database and enabled.');
1083

    
1084
    // Verify that uid 1's account was not cancelled.
1085
    $user1 = user_load(1, TRUE);
1086
    $this->assertEqual($user1->status, 1, 'User #1 still exists and is not blocked.');
1087
  }
1088
}
1089

    
1090
class UserPictureTestCase extends DrupalWebTestCase {
1091
  protected $user;
1092
  protected $_directory_test;
1093

    
1094
  public static function getInfo() {
1095
    return array(
1096
      'name' => 'Upload user picture',
1097
      'description' => 'Assure that dimension check, extension check and image scaling work as designed.',
1098
      'group' => 'User'
1099
    );
1100
  }
1101

    
1102
  function setUp() {
1103
    parent::setUp();
1104
    // Enable user pictures.
1105
    variable_set('user_pictures', 1);
1106

    
1107
    $this->user = $this->drupalCreateUser();
1108

    
1109
    // Test if directories specified in settings exist in filesystem.
1110
    $file_dir = 'public://';
1111
    $file_check = file_prepare_directory($file_dir, FILE_CREATE_DIRECTORY);
1112
    // TODO: Test public and private methods?
1113

    
1114
    $picture_dir = variable_get('user_picture_path', 'pictures');
1115
    $picture_path = $file_dir . $picture_dir;
1116

    
1117
    $pic_check = file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY);
1118
    $this->_directory_test = is_writable($picture_path);
1119
    $this->assertTrue($this->_directory_test, "The directory $picture_path doesn't exist or is not writable. Further tests won't be made.");
1120
  }
1121

    
1122
  function testNoPicture() {
1123
    $this->drupalLogin($this->user);
1124

    
1125
    // Try to upload a file that is not an image for the user picture.
1126
    $not_an_image = current($this->drupalGetTestFiles('html'));
1127
    $this->saveUserPicture($not_an_image);
1128
    $this->assertRaw(t('Only JPEG, PNG and GIF images are allowed.'), 'Non-image files are not accepted.');
1129
  }
1130

    
1131
  /**
1132
   * Do the test:
1133
   *  GD Toolkit is installed
1134
   *  Picture has invalid dimension
1135
   *
1136
   * results: The image should be uploaded because ImageGDToolkit resizes the picture
1137
   */
1138
  function testWithGDinvalidDimension() {
1139
    if ($this->_directory_test && image_get_toolkit()) {
1140
      $this->drupalLogin($this->user);
1141

    
1142
      $image = current($this->drupalGetTestFiles('image'));
1143
      $info = image_get_info($image->uri);
1144

    
1145
      // Set new variables: invalid dimensions, valid filesize (0 = no limit).
1146
      $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10);
1147
      variable_set('user_picture_dimensions', $test_dim);
1148
      variable_set('user_picture_file_size', 0);
1149

    
1150
      $pic_path = $this->saveUserPicture($image);
1151
      // Check that the image was resized and is being displayed on the
1152
      // user's profile page.
1153
      $text = t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $test_dim));
1154
      $this->assertRaw($text, 'Image was resized.');
1155
      $alt = t("@user's picture", array('@user' => format_username($this->user)));
1156
      $style = variable_get('user_picture_style', '');
1157
      $this->assertRaw(check_plain(image_style_url($style, $pic_path)), "Image is displayed in user's edit page");
1158

    
1159
      // Check if file is located in proper directory.
1160
      $this->assertTrue(is_file($pic_path), "File is located in proper directory");
1161
    }
1162
  }
1163

    
1164
  /**
1165
   * Do the test:
1166
   *  GD Toolkit is installed
1167
   *  Picture has invalid size
1168
   *
1169
   * results: The image should be uploaded because ImageGDToolkit resizes the picture
1170
   */
1171
  function testWithGDinvalidSize() {
1172
    if ($this->_directory_test && image_get_toolkit()) {
1173
      $this->drupalLogin($this->user);
1174

    
1175
      // Images are sorted first by size then by name. We need an image
1176
      // bigger than 1 KB so we'll grab the last one.
1177
      $files = $this->drupalGetTestFiles('image');
1178
      $image = end($files);
1179
      $info = image_get_info($image->uri);
1180

    
1181
      // Set new variables: valid dimensions, invalid filesize.
1182
      $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
1183
      $test_size = 1;
1184
      variable_set('user_picture_dimensions', $test_dim);
1185
      variable_set('user_picture_file_size', $test_size);
1186

    
1187
      $pic_path = $this->saveUserPicture($image);
1188

    
1189
      // Test that the upload failed and that the correct reason was cited.
1190
      $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename));
1191
      $this->assertRaw($text, 'Upload failed.');
1192
      $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)));
1193
      $this->assertRaw($text, 'File size cited as reason for failure.');
1194

    
1195
      // Check if file is not uploaded.
1196
      $this->assertFalse(is_file($pic_path), 'File was not uploaded.');
1197
    }
1198
  }
1199

    
1200
  /**
1201
   * Do the test:
1202
   *  GD Toolkit is not installed
1203
   *  Picture has invalid size
1204
   *
1205
   * results: The image shouldn't be uploaded
1206
   */
1207
  function testWithoutGDinvalidDimension() {
1208
    if ($this->_directory_test && !image_get_toolkit()) {
1209
      $this->drupalLogin($this->user);
1210

    
1211
      $image = current($this->drupalGetTestFiles('image'));
1212
      $info = image_get_info($image->uri);
1213

    
1214
      // Set new variables: invalid dimensions, valid filesize (0 = no limit).
1215
      $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10);
1216
      variable_set('user_picture_dimensions', $test_dim);
1217
      variable_set('user_picture_file_size', 0);
1218

    
1219
      $pic_path = $this->saveUserPicture($image);
1220

    
1221
      // Test that the upload failed and that the correct reason was cited.
1222
      $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename));
1223
      $this->assertRaw($text, 'Upload failed.');
1224
      $text = t('The image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => $test_dim));
1225
      $this->assertRaw($text, 'Checking response on invalid image (dimensions).');
1226

    
1227
      // Check if file is not uploaded.
1228
      $this->assertFalse(is_file($pic_path), 'File was not uploaded.');
1229
    }
1230
  }
1231

    
1232
  /**
1233
   * Do the test:
1234
   *  GD Toolkit is not installed
1235
   *  Picture has invalid size
1236
   *
1237
   * results: The image shouldn't be uploaded
1238
   */
1239
  function testWithoutGDinvalidSize() {
1240
    if ($this->_directory_test && !image_get_toolkit()) {
1241
      $this->drupalLogin($this->user);
1242

    
1243
      $image = current($this->drupalGetTestFiles('image'));
1244
      $info = image_get_info($image->uri);
1245

    
1246
      // Set new variables: valid dimensions, invalid filesize.
1247
      $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
1248
      $test_size = 1;
1249
      variable_set('user_picture_dimensions', $test_dim);
1250
      variable_set('user_picture_file_size', $test_size);
1251

    
1252
      $pic_path = $this->saveUserPicture($image);
1253

    
1254
      // Test that the upload failed and that the correct reason was cited.
1255
      $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename));
1256
      $this->assertRaw($text, 'Upload failed.');
1257
      $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)));
1258
      $this->assertRaw($text, 'File size cited as reason for failure.');
1259

    
1260
      // Check if file is not uploaded.
1261
      $this->assertFalse(is_file($pic_path), 'File was not uploaded.');
1262
    }
1263
  }
1264

    
1265
  /**
1266
   * Do the test:
1267
   *  Picture is valid (proper size and dimension)
1268
   *
1269
   * results: The image should be uploaded
1270
   */
1271
  function testPictureIsValid() {
1272
    if ($this->_directory_test) {
1273
      $this->drupalLogin($this->user);
1274

    
1275
      $image = current($this->drupalGetTestFiles('image'));
1276
      $info = image_get_info($image->uri);
1277

    
1278
      // Set new variables: valid dimensions, valid filesize (0 = no limit).
1279
      $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
1280
      variable_set('user_picture_dimensions', $test_dim);
1281
      variable_set('user_picture_file_size', 0);
1282

    
1283
      $pic_path = $this->saveUserPicture($image);
1284

    
1285
      // Check if image is displayed in user's profile page.
1286
      $this->drupalGet('user');
1287
      $this->assertRaw(file_uri_target($pic_path), "Image is displayed in user's profile page");
1288

    
1289
      // Check if file is located in proper directory.
1290
      $this->assertTrue(is_file($pic_path), 'File is located in proper directory');
1291

    
1292
      // Set new picture dimensions.
1293
      $test_dim = ($info['width'] + 5) . 'x' . ($info['height'] + 5);
1294
      variable_set('user_picture_dimensions', $test_dim);
1295

    
1296
      $pic_path2 = $this->saveUserPicture($image);
1297
      $this->assertNotEqual($pic_path, $pic_path2, 'Filename of second picture is different.');
1298

    
1299
      // Check if user picture has a valid file ID after saving the user.
1300
      $account = user_load($this->user->uid, TRUE);
1301
      $this->assertTrue(is_object($account->picture), 'User picture object is valid after user load.');
1302
      $this->assertNotNull($account->picture->fid, 'User picture object has a FID after user load.');
1303
      $this->assertTrue(is_file($account->picture->uri), 'File is located in proper directory after user load.');
1304
      user_save($account);
1305
      // Verify that the user save does not destroy the user picture object.
1306
      $this->assertTrue(is_object($account->picture), 'User picture object is valid after user save.');
1307
      $this->assertNotNull($account->picture->fid, 'User picture object has a FID after user save.');
1308
      $this->assertTrue(is_file($account->picture->uri), 'File is located in proper directory after user save.');
1309
    }
1310
  }
1311

    
1312
  /**
1313
   * Test HTTP schema working with user pictures.
1314
   */
1315
  function testExternalPicture() {
1316
    $this->drupalLogin($this->user);
1317
    // Set the default picture to an URI with a HTTP schema.
1318
    $images = $this->drupalGetTestFiles('image');
1319
    $image = $images[0];
1320
    $pic_path = file_create_url($image->uri);
1321
    variable_set('user_picture_default', $pic_path);
1322

    
1323
    // Check if image is displayed in user's profile page.
1324
    $this->drupalGet('user');
1325

    
1326
    // Get the user picture image via xpath.
1327
    $elements = $this->xpath('//div[@class="user-picture"]/img');
1328
    $this->assertEqual(count($elements), 1, "There is exactly one user picture on the user's profile page");
1329
    $this->assertEqual($pic_path, (string) $elements[0]['src'], "User picture source is correct.");
1330
  }
1331

    
1332
  /**
1333
   * Tests deletion of user pictures.
1334
   */
1335
  function testDeletePicture() {
1336
    $this->drupalLogin($this->user);
1337

    
1338
    $image = current($this->drupalGetTestFiles('image'));
1339
    $info = image_get_info($image->uri);
1340

    
1341
    // Set new variables: valid dimensions, valid filesize (0 = no limit).
1342
    $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
1343
    variable_set('user_picture_dimensions', $test_dim);
1344
    variable_set('user_picture_file_size', 0);
1345

    
1346
    // Save a new picture.
1347
    $edit = array('files[picture_upload]' => drupal_realpath($image->uri));
1348
    $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save'));
1349

    
1350
    // Load actual user data from database.
1351
    $account = user_load($this->user->uid, TRUE);
1352
    $pic_path = isset($account->picture) ? $account->picture->uri : NULL;
1353

    
1354
    // Check if image is displayed in user's profile page.
1355
    $this->drupalGet('user');
1356
    $this->assertRaw(file_uri_target($pic_path), "Image is displayed in user's profile page");
1357

    
1358
    // Check if file is located in proper directory.
1359
    $this->assertTrue(is_file($pic_path), 'File is located in proper directory');
1360

    
1361
    $edit = array('picture_delete' => 1);
1362
    $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save'));
1363

    
1364
    // Load actual user data from database.
1365
    $account1 = user_load($this->user->uid, TRUE);
1366
    $this->assertNull($account1->picture, 'User object has no picture');
1367

    
1368
    $file = file_load($account->picture->fid);
1369
    $this->assertFalse($file, 'File is removed from database');
1370

    
1371
    // Clear out PHP's file stat cache so we see the current value.
1372
    clearstatcache();
1373
    $this->assertFalse(is_file($pic_path), 'File is removed from file system');
1374
  }
1375

    
1376
  function saveUserPicture($image) {
1377
    $edit = array('files[picture_upload]' => drupal_realpath($image->uri));
1378
    $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save'));
1379

    
1380
    // Load actual user data from database.
1381
    $account = user_load($this->user->uid, TRUE);
1382
    return isset($account->picture) ? $account->picture->uri : NULL;
1383
  }
1384

    
1385
  /**
1386
   * Tests the admin form validates user picture settings.
1387
   */
1388
  function testUserPictureAdminFormValidation() {
1389
    $this->drupalLogin($this->drupalCreateUser(array('administer users')));
1390

    
1391
    // The default values are valid.
1392
    $this->drupalPost('admin/config/people/accounts', array(), t('Save configuration'));
1393
    $this->assertText(t('The configuration options have been saved.'), 'The default values are valid.');
1394

    
1395
    // The form does not save with an invalid file size.
1396
    $edit = array(
1397
      'user_picture_file_size' => $this->randomName(),
1398
    );
1399
    $this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration'));
1400
    $this->assertNoText(t('The configuration options have been saved.'), 'The form does not save with an invalid file size.');
1401
  }
1402
}
1403

    
1404

    
1405
class UserPermissionsTestCase extends DrupalWebTestCase {
1406
  protected $admin_user;
1407
  protected $rid;
1408

    
1409
  public static function getInfo() {
1410
    return array(
1411
      'name' => 'Role permissions',
1412
      'description' => 'Verify that role permissions can be added and removed via the permissions page.',
1413
      'group' => 'User'
1414
    );
1415
  }
1416

    
1417
  function setUp() {
1418
    parent::setUp();
1419

    
1420
    $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'access user profiles', 'administer site configuration', 'administer modules', 'administer users'));
1421

    
1422
    // Find the new role ID - it must be the maximum.
1423
    $all_rids = array_keys($this->admin_user->roles);
1424
    sort($all_rids);
1425
    $this->rid = array_pop($all_rids);
1426
  }
1427

    
1428
  /**
1429
   * Change user permissions and check user_access().
1430
   */
1431
  function testUserPermissionChanges() {
1432
    $this->drupalLogin($this->admin_user);
1433
    $rid = $this->rid;
1434
    $account = $this->admin_user;
1435

    
1436
    // Add a permission.
1437
    $this->assertFalse(user_access('administer nodes', $account), 'User does not have "administer nodes" permission.');
1438
    $edit = array();
1439
    $edit[$rid . '[administer nodes]'] = TRUE;
1440
    $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
1441
    $this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
1442
    drupal_static_reset('user_access');
1443
    drupal_static_reset('user_role_permissions');
1444
    $this->assertTrue(user_access('administer nodes', $account), 'User now has "administer nodes" permission.');
1445

    
1446
    // Remove a permission.
1447
    $this->assertTrue(user_access('access user profiles', $account), 'User has "access user profiles" permission.');
1448
    $edit = array();
1449
    $edit[$rid . '[access user profiles]'] = FALSE;
1450
    $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
1451
    $this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
1452
    drupal_static_reset('user_access');
1453
    drupal_static_reset('user_role_permissions');
1454
    $this->assertFalse(user_access('access user profiles', $account), 'User no longer has "access user profiles" permission.');
1455
  }
1456

    
1457
  /**
1458
   * Test assigning of permissions for the administrator role.
1459
   */
1460
  function testAdministratorRole() {
1461
    $this->drupalLogin($this->admin_user);
1462
    $this->drupalGet('admin/config/people/accounts');
1463

    
1464
    // Set the user's role to be the administrator role.
1465
    $edit = array();
1466
    $edit['user_admin_role'] = $this->rid;
1467
    $this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration'));
1468

    
1469
    // Enable aggregator module and ensure the 'administer news feeds'
1470
    // permission is assigned by default.
1471
    $edit = array();
1472
    $edit['modules[Core][aggregator][enable]'] = TRUE;
1473
    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
1474
    $this->assertTrue(user_access('administer news feeds', $this->admin_user), 'The permission was automatically assigned to the administrator role');
1475
  }
1476

    
1477
  /**
1478
   * Verify proper permission changes by user_role_change_permissions().
1479
   */
1480
  function testUserRoleChangePermissions() {
1481
    $rid = $this->rid;
1482
    $account = $this->admin_user;
1483

    
1484
    // Verify current permissions.
1485
    $this->assertFalse(user_access('administer nodes', $account), 'User does not have "administer nodes" permission.');
1486
    $this->assertTrue(user_access('access user profiles', $account), 'User has "access user profiles" permission.');
1487
    $this->assertTrue(user_access('administer site configuration', $account), 'User has "administer site configuration" permission.');
1488

    
1489
    // Change permissions.
1490
    $permissions = array(
1491
      'administer nodes' => 1,
1492
      'access user profiles' => 0,
1493
    );
1494
    user_role_change_permissions($rid, $permissions);
1495

    
1496
    // Verify proper permission changes.
1497
    $this->assertTrue(user_access('administer nodes', $account), 'User now has "administer nodes" permission.');
1498
    $this->assertFalse(user_access('access user profiles', $account), 'User no longer has "access user profiles" permission.');
1499
    $this->assertTrue(user_access('administer site configuration', $account), 'User still has "administer site configuration" permission.');
1500
  }
1501
}
1502

    
1503
class UserAdminTestCase extends DrupalWebTestCase {
1504
  public static function getInfo() {
1505
    return array(
1506
      'name' => 'User administration',
1507
      'description' => 'Test user administration page functionality.',
1508
      'group' => 'User'
1509
    );
1510
  }
1511

    
1512
  /**
1513
   * Registers a user and deletes it.
1514
   */
1515
  function testUserAdmin() {
1516

    
1517
    $user_a = $this->drupalCreateUser(array());
1518
    $user_b = $this->drupalCreateUser(array('administer taxonomy'));
1519
    $user_c = $this->drupalCreateUser(array('administer taxonomy'));
1520

    
1521
    // Create admin user to delete registered user.
1522
    $admin_user = $this->drupalCreateUser(array('administer users'));
1523
    $this->drupalLogin($admin_user);
1524
    $this->drupalGet('admin/people');
1525
    $this->assertText($user_a->name, 'Found user A on admin users page');
1526
    $this->assertText($user_b->name, 'Found user B on admin users page');
1527
    $this->assertText($user_c->name, 'Found user C on admin users page');
1528
    $this->assertText($admin_user->name, 'Found Admin user on admin users page');
1529

    
1530
    // Test for existence of edit link in table.
1531
    $link = l(t('edit'), "user/$user_a->uid/edit", array('query' => array('destination' => 'admin/people')));
1532
    $this->assertRaw($link, 'Found user A edit link on admin users page');
1533

    
1534
    // Filter the users by permission 'administer taxonomy'.
1535
    $edit = array();
1536
    $edit['permission'] = 'administer taxonomy';
1537
    $this->drupalPost('admin/people', $edit, t('Filter'));
1538

    
1539
    // Check if the correct users show up.
1540
    $this->assertNoText($user_a->name, 'User A not on filtered by perm admin users page');
1541
    $this->assertText($user_b->name, 'Found user B on filtered by perm admin users page');
1542
    $this->assertText($user_c->name, 'Found user C on filtered by perm admin users page');
1543

    
1544
    // Filter the users by role. Grab the system-generated role name for User C.
1545
    $edit['role'] = max(array_flip($user_c->roles));
1546
    $this->drupalPost('admin/people', $edit, t('Refine'));
1547

    
1548
    // Check if the correct users show up when filtered by role.
1549
    $this->assertNoText($user_a->name, 'User A not on filtered by role on admin users page');
1550
    $this->assertNoText($user_b->name, 'User B not on filtered by role on admin users page');
1551
    $this->assertText($user_c->name, 'User C on filtered by role on admin users page');
1552

    
1553
    // Test blocking of a user.
1554
    $account = user_load($user_c->uid);
1555
    $this->assertEqual($account->status, 1, 'User C not blocked');
1556
    $edit = array();
1557
    $edit['operation'] = 'block';
1558
    $edit['accounts[' . $account->uid . ']'] = TRUE;
1559
    $this->drupalPost('admin/people', $edit, t('Update'));
1560
    $account = user_load($user_c->uid, TRUE);
1561
    $this->assertEqual($account->status, 0, 'User C blocked');
1562

    
1563
    // Test unblocking of a user from /admin/people page and sending of activation mail
1564
    $editunblock = array();
1565
    $editunblock['operation'] = 'unblock';
1566
    $editunblock['accounts[' . $account->uid . ']'] = TRUE;
1567
    $this->drupalPost('admin/people', $editunblock, t('Update'));
1568
    $account = user_load($user_c->uid, TRUE);
1569
    $this->assertEqual($account->status, 1, 'User C unblocked');
1570
    $this->assertMail("to", $account->mail, "Activation mail sent to user C");
1571

    
1572
    // Test blocking and unblocking another user from /user/[uid]/edit form and sending of activation mail
1573
    $user_d = $this->drupalCreateUser(array());
1574
    $account1 = user_load($user_d->uid, TRUE);
1575
    $this->drupalPost('user/' . $account1->uid . '/edit', array('status' => 0), t('Save'));
1576
    $account1 = user_load($user_d->uid, TRUE);
1577
    $this->assertEqual($account1->status, 0, 'User D blocked');
1578
    $this->drupalPost('user/' . $account1->uid . '/edit', array('status' => TRUE), t('Save'));
1579
    $account1 = user_load($user_d->uid, TRUE);
1580
    $this->assertEqual($account1->status, 1, 'User D unblocked');
1581
    $this->assertMail("to", $account1->mail, "Activation mail sent to user D");
1582
  }
1583
}
1584

    
1585
/**
1586
 * Tests for user-configurable time zones.
1587
 */
1588
class UserTimeZoneFunctionalTest extends DrupalWebTestCase {
1589
  public static function getInfo() {
1590
    return array(
1591
      'name' => 'User time zones',
1592
      'description' => 'Set a user time zone and verify that dates are displayed in local time.',
1593
      'group' => 'User',
1594
    );
1595
  }
1596

    
1597
  /**
1598
   * Tests the display of dates and time when user-configurable time zones are set.
1599
   */
1600
  function testUserTimeZone() {
1601
    // Setup date/time settings for Los Angeles time.
1602
    variable_set('date_default_timezone', 'America/Los_Angeles');
1603
    variable_set('configurable_timezones', 1);
1604

    
1605
    // Override the 'medium' date format, which is the default for node
1606
    // creation time. Since we are testing time zones with Daylight Saving
1607
    // Time, and need to future proof against changes to the zoneinfo database,
1608
    // we choose the 'I' format placeholder instead of a human-readable zone
1609
    // name. With 'I', a 1 means the date is in DST, and 0 if not.
1610
    variable_set('date_format_medium', 'Y-m-d H:i I');
1611

    
1612
    // Create a user account and login.
1613
    $web_user = $this->drupalCreateUser();
1614
    $this->drupalLogin($web_user);
1615

    
1616
    // Create some nodes with different authored-on dates.
1617
    // Two dates in PST (winter time):
1618
    $date1 = '2007-03-09 21:00:00 -0800';
1619
    $date2 = '2007-03-11 01:00:00 -0800';
1620
    // One date in PDT (summer time):
1621
    $date3 = '2007-03-20 21:00:00 -0700';
1622
    $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article'));
1623
    $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article'));
1624
    $node3 = $this->drupalCreateNode(array('created' => strtotime($date3), 'type' => 'article'));
1625

    
1626
    // Confirm date format and time zone.
1627
    $this->drupalGet("node/$node1->nid");
1628
    $this->assertText('2007-03-09 21:00 0', 'Date should be PST.');
1629
    $this->drupalGet("node/$node2->nid");
1630
    $this->assertText('2007-03-11 01:00 0', 'Date should be PST.');
1631
    $this->drupalGet("node/$node3->nid");
1632
    $this->assertText('2007-03-20 21:00 1', 'Date should be PDT.');
1633

    
1634
    // Change user time zone to Santiago time.
1635
    $edit = array();
1636
    $edit['mail'] = $web_user->mail;
1637
    $edit['timezone'] = 'America/Santiago';
1638
    $this->drupalPost("user/$web_user->uid/edit", $edit, t('Save'));
1639
    $this->assertText(t('The changes have been saved.'), 'Time zone changed to Santiago time.');
1640

    
1641
    // Confirm date format and time zone.
1642
    $this->drupalGet("node/$node1->nid");
1643
    $this->assertText('2007-03-10 02:00 1', 'Date should be Chile summer time; five hours ahead of PST.');
1644
    $this->drupalGet("node/$node2->nid");
1645
    $this->assertText('2007-03-11 05:00 0', 'Date should be Chile time; four hours ahead of PST');
1646
    $this->drupalGet("node/$node3->nid");
1647
    $this->assertText('2007-03-21 00:00 0', 'Date should be Chile time; three hours ahead of PDT.');
1648
  }
1649
}
1650

    
1651
/**
1652
 * Test user autocompletion.
1653
 */
1654
class UserAutocompleteTestCase extends DrupalWebTestCase {
1655
  public static function getInfo() {
1656
    return array(
1657
      'name' => 'User autocompletion',
1658
      'description' => 'Test user autocompletion functionality.',
1659
      'group' => 'User'
1660
    );
1661
  }
1662

    
1663
  function setUp() {
1664
    parent::setUp();
1665

    
1666
    // Set up two users with different permissions to test access.
1667
    $this->unprivileged_user = $this->drupalCreateUser();
1668
    $this->privileged_user = $this->drupalCreateUser(array('access user profiles'));
1669
  }
1670

    
1671
  /**
1672
   * Tests access to user autocompletion and verify the correct results.
1673
   */
1674
  function testUserAutocomplete() {
1675
    // Check access from unprivileged user, should be denied.
1676
    $this->drupalLogin($this->unprivileged_user);
1677
    $this->drupalGet('user/autocomplete/' . $this->unprivileged_user->name[0]);
1678
    $this->assertResponse(403, 'Autocompletion access denied to user without permission.');
1679

    
1680
    // Check access from privileged user.
1681
    $this->drupalLogout();
1682
    $this->drupalLogin($this->privileged_user);
1683
    $this->drupalGet('user/autocomplete/' . $this->unprivileged_user->name[0]);
1684
    $this->assertResponse(200, 'Autocompletion access allowed.');
1685

    
1686
    // Using first letter of the user's name, make sure the user's full name is in the results.
1687
    $this->assertRaw($this->unprivileged_user->name, 'User name found in autocompletion results.');
1688
  }
1689
}
1690

    
1691

    
1692
/**
1693
 * Tests user links in the secondary menu.
1694
 */
1695
class UserAccountLinksUnitTests extends DrupalWebTestCase {
1696
  public static function getInfo() {
1697
    return array(
1698
      'name' => 'User account links',
1699
      'description' => 'Test user-account links.',
1700
      'group' => 'User'
1701
    );
1702
  }
1703

    
1704
  function setUp() {
1705
    parent::setUp('menu');
1706
  }
1707

    
1708
  /**
1709
   * Tests the secondary menu.
1710
   */
1711
  function testSecondaryMenu() {
1712
    // Create a regular user.
1713
    $user = $this->drupalCreateUser(array());
1714

    
1715
    // Log in and get the homepage.
1716
    $this->drupalLogin($user);
1717
    $this->drupalGet('<front>');
1718

    
1719
    // For a logged-in user, expect the secondary menu to have links for "My
1720
    // account" and "Log out".
1721
    $link = $this->xpath('//ul[@id=:menu_id]/li/a[contains(@href, :href) and text()=:text]', array(
1722
      ':menu_id' => 'secondary-menu-links',
1723
      ':href' => 'user',
1724
      ':text' => 'My account',
1725
    ));
1726
    $this->assertEqual(count($link), 1, 'My account link is in secondary menu.');
1727

    
1728
    $link = $this->xpath('//ul[@id=:menu_id]/li/a[contains(@href, :href) and text()=:text]', array(
1729
      ':menu_id' => 'secondary-menu-links',
1730
      ':href' => 'user/logout',
1731
      ':text' => 'Log out',
1732
    ));
1733
    $this->assertEqual(count($link), 1, 'Log out link is in secondary menu.');
1734

    
1735
    // Log out and get the homepage.
1736
    $this->drupalLogout();
1737
    $this->drupalGet('<front>');
1738

    
1739
    // For a logged-out user, expect no secondary links.
1740
    $element = $this->xpath('//ul[@id=:menu_id]', array(':menu_id' => 'secondary-menu-links'));
1741
    $this->assertEqual(count($element), 0, 'No secondary-menu for logged-out users.');
1742
  }
1743

    
1744
  /**
1745
   * Tests disabling the 'My account' link.
1746
   */
1747
  function testDisabledAccountLink() {
1748
    // Create an admin user and log in.
1749
    $this->drupalLogin($this->drupalCreateUser(array('access administration pages', 'administer menu')));
1750

    
1751
    // Verify that the 'My account' link is enabled.
1752
    $this->drupalGet('admin/structure/menu/manage/user-menu');
1753
    $label = $this->xpath('//label[contains(.,:text)]/@for', array(':text' => 'Enable My account menu link'));
1754
    $this->assertFieldChecked((string) $label[0], "The 'My account' link is enabled by default.");
1755

    
1756
    // Disable the 'My account' link.
1757
    $input = $this->xpath('//input[@id=:field_id]/@name', array(':field_id' => (string)$label[0]));
1758
    $edit = array(
1759
      (string) $input[0] => FALSE,
1760
    );
1761
    $this->drupalPost('admin/structure/menu/manage/user-menu', $edit, t('Save configuration'));
1762

    
1763
    // Get the homepage.
1764
    $this->drupalGet('<front>');
1765

    
1766
    // Verify that the 'My account' link does not appear when disabled.
1767
    $link = $this->xpath('//ul[@id=:menu_id]/li/a[contains(@href, :href) and text()=:text]', array(
1768
      ':menu_id' => 'secondary-menu-links',
1769
      ':href' => 'user',
1770
      ':text' => 'My account',
1771
    ));
1772
    $this->assertEqual(count($link), 0, 'My account link is not in the secondary menu.');
1773
  }
1774

    
1775
}
1776

    
1777
/**
1778
 * Test user blocks.
1779
 */
1780
class UserBlocksUnitTests extends DrupalWebTestCase {
1781
  public static function getInfo() {
1782
    return array(
1783
      'name' => 'User blocks',
1784
      'description' => 'Test user blocks.',
1785
      'group' => 'User'
1786
    );
1787
  }
1788

    
1789
  /**
1790
   * Test the user login block.
1791
   */
1792
  function testUserLoginBlock() {
1793
    // Create a user with some permission that anonymous users lack.
1794
    $user = $this->drupalCreateUser(array('administer permissions'));
1795

    
1796
    // Log in using the block.
1797
    $edit = array();
1798
    $edit['name'] = $user->name;
1799
    $edit['pass'] = $user->pass_raw;
1800
    $this->drupalPost('admin/people/permissions', $edit, t('Log in'));
1801
    $this->assertNoText(t('User login'), 'Logged in.');
1802

    
1803
    // Check that we are still on the same page.
1804
    $this->assertEqual(url('admin/people/permissions', array('absolute' => TRUE)), $this->getUrl(), 'Still on the same page after login for access denied page');
1805

    
1806
    // Now, log out and repeat with a non-403 page.
1807
    $this->drupalLogout();
1808
    $this->drupalPost('filter/tips', $edit, t('Log in'));
1809
    $this->assertNoText(t('User login'), 'Logged in.');
1810
    $this->assertPattern('!<title.*?' . t('Compose tips') . '.*?</title>!', 'Still on the same page after login for allowed page');
1811

    
1812
    // Check that the user login block is not vulnerable to information
1813
    // disclosure to third party sites.
1814
    $this->drupalLogout();
1815
    $this->drupalPost('http://example.com/', $edit, t('Log in'), array('external' => FALSE));
1816
    // Check that we remain on the site after login.
1817
    $this->assertEqual(url('user/' . $user->uid, array('absolute' => TRUE)), $this->getUrl(), 'Redirected to user profile page after login from the frontpage');
1818
  }
1819

    
1820
  /**
1821
   * Test the Who's Online block.
1822
   */
1823
  function testWhosOnlineBlock() {
1824
    // Generate users and make sure there are no current user sessions.
1825
    $user1 = $this->drupalCreateUser(array());
1826
    $user2 = $this->drupalCreateUser(array());
1827
    $user3 = $this->drupalCreateUser(array());
1828
    $this->assertEqual(db_query("SELECT COUNT(*) FROM {sessions}")->fetchField(), 0, 'Sessions table is empty.');
1829

    
1830
    // Insert a user with two sessions.
1831
    $this->insertSession(array('uid' => $user1->uid));
1832
    $this->insertSession(array('uid' => $user1->uid));
1833
    $this->assertEqual(db_query("SELECT COUNT(*) FROM {sessions} WHERE uid = :uid", array(':uid' => $user1->uid))->fetchField(), 2, 'Duplicate user session has been inserted.');
1834

    
1835
    // Insert a user with only one session.
1836
    $this->insertSession(array('uid' => $user2->uid, 'timestamp' => REQUEST_TIME + 1));
1837

    
1838
    // Insert an inactive logged-in user who should not be seen in the block.
1839
    $this->insertSession(array('uid' => $user3->uid, 'timestamp' => (REQUEST_TIME - variable_get('user_block_seconds_online', 900) - 1)));
1840

    
1841
    // Insert two anonymous user sessions.
1842
    $this->insertSession();
1843
    $this->insertSession();
1844

    
1845
    // Test block output.
1846
    $block = user_block_view('online');
1847
    $this->drupalSetContent($block['content']);
1848
    $this->assertRaw(t('2 users'), 'Correct number of online users (2 users).');
1849
    $this->assertText($user1->name, 'Active user 1 found in online list.');
1850
    $this->assertText($user2->name, 'Active user 2 found in online list.');
1851
    $this->assertNoText($user3->name, "Inactive user not found in online list.");
1852
    $this->assertTrue(strpos($this->drupalGetContent(), $user1->name) > strpos($this->drupalGetContent(), $user2->name), 'Online users are ordered correctly.');
1853
  }
1854

    
1855
  /**
1856
   * Insert a user session into the {sessions} table. This function is used
1857
   * since we cannot log in more than one user at the same time in tests.
1858
   */
1859
  private function insertSession(array $fields = array()) {
1860
    $fields += array(
1861
      'uid' => 0,
1862
      'sid' => drupal_hash_base64(uniqid(mt_rand(), TRUE)),
1863
      'timestamp' => REQUEST_TIME,
1864
    );
1865
    db_insert('sessions')
1866
      ->fields($fields)
1867
      ->execute();
1868
    $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, 'Session record inserted.');
1869
  }
1870
}
1871

    
1872
/**
1873
 * Tests saving a user account.
1874
 */
1875
class UserSaveTestCase extends DrupalWebTestCase {
1876

    
1877
  public static function getInfo() {
1878
    return array(
1879
      'name' => 'User save test',
1880
      'description' => 'Test user_save() for arbitrary new uid.',
1881
      'group' => 'User',
1882
    );
1883
  }
1884

    
1885
  /**
1886
   * Test creating a user with arbitrary uid.
1887
   */
1888
  function testUserImport() {
1889
    // User ID must be a number that is not in the database.
1890
    $max_uid = db_query('SELECT MAX(uid) FROM {users}')->fetchField();
1891
    $test_uid = $max_uid + mt_rand(1000, 1000000);
1892
    $test_name = $this->randomName();
1893

    
1894
    // Create the base user, based on drupalCreateUser().
1895
    $user = array(
1896
      'name' => $test_name,
1897
      'uid' => $test_uid,
1898
      'mail' => $test_name . '@example.com',
1899
      'is_new' => TRUE,
1900
      'pass' => user_password(),
1901
      'status' => 1,
1902
    );
1903
    $user_by_return = user_save(drupal_anonymous_user(), $user);
1904
    $this->assertTrue($user_by_return, 'Loading user by return of user_save().');
1905

    
1906
    // Test if created user exists.
1907
    $user_by_uid = user_load($test_uid);
1908
    $this->assertTrue($user_by_uid, 'Loading user by uid.');
1909

    
1910
    $user_by_name = user_load_by_name($test_name);
1911
    $this->assertTrue($user_by_name, 'Loading user by name.');
1912
  }
1913
}
1914

    
1915
/**
1916
 * Test the create user administration page.
1917
 */
1918
class UserCreateTestCase extends DrupalWebTestCase {
1919

    
1920
  public static function getInfo() {
1921
    return array(
1922
      'name' => 'User create',
1923
      'description' => 'Test the create user administration page.',
1924
      'group' => 'User',
1925
    );
1926
  }
1927

    
1928
  /**
1929
   * Create a user through the administration interface and ensure that it
1930
   * displays in the user list.
1931
   */
1932
  protected function testUserAdd() {
1933
    $user = $this->drupalCreateUser(array('administer users'));
1934
    $this->drupalLogin($user);
1935

    
1936
    foreach (array(FALSE, TRUE) as $notify) {
1937
      $edit = array(
1938
        'name' => $this->randomName(),
1939
        'mail' => $this->randomName() . '@example.com',
1940
        'pass[pass1]' => $pass = $this->randomString(),
1941
        'pass[pass2]' => $pass,
1942
        'notify' => $notify,
1943
      );
1944
      $this->drupalPost('admin/people/create', $edit, t('Create new account'));
1945

    
1946
      if ($notify) {
1947
        $this->assertText(t('A welcome message with further instructions has been e-mailed to the new user @name.', array('@name' => $edit['name'])), 'User created');
1948
        $this->assertEqual(count($this->drupalGetMails()), 1, 'Notification e-mail sent');
1949
      }
1950
      else {
1951
        $this->assertText(t('Created a new user account for @name. No e-mail has been sent.', array('@name' => $edit['name'])), 'User created');
1952
        $this->assertEqual(count($this->drupalGetMails()), 0, 'Notification e-mail not sent');
1953
      }
1954

    
1955
      $this->drupalGet('admin/people');
1956
      $this->assertText($edit['name'], 'User found in list of users');
1957
    }
1958

    
1959
    // Test that the password '0' is considered a password.
1960
    $name = $this->randomName();
1961
    $edit = array(
1962
      'name' => $name,
1963
      'mail' => $name . '@example.com',
1964
      'pass[pass1]' => 0,
1965
      'pass[pass2]' => 0,
1966
      'notify' => FALSE,
1967
    );
1968
    $this->drupalPost('admin/people/create', $edit, t('Create new account'));
1969
    $this->assertText(t('Created a new user account for @name. No e-mail has been sent.', array('@name' => $edit['name'])), 'User created with password 0');
1970
    $this->assertNoText('Password field is required');
1971
  }
1972
}
1973

    
1974
/**
1975
 * Tests editing a user account.
1976
 */
1977
class UserEditTestCase extends DrupalWebTestCase {
1978

    
1979
  public static function getInfo() {
1980
    return array(
1981
      'name' => 'User edit',
1982
      'description' => 'Test user edit page.',
1983
      'group' => 'User',
1984
    );
1985
  }
1986

    
1987
  /**
1988
   * Test user edit page.
1989
   */
1990
  function testUserEdit() {
1991
    // Test user edit functionality with user pictures disabled.
1992
    variable_set('user_pictures', 0);
1993
    $user1 = $this->drupalCreateUser(array('change own username'));
1994
    $user2 = $this->drupalCreateUser(array());
1995
    $this->drupalLogin($user1);
1996

    
1997
    // Test that error message appears when attempting to use a non-unique user name.
1998
    $edit['name'] = $user2->name;
1999
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2000
    $this->assertRaw(t('The name %name is already taken.', array('%name' => $edit['name'])));
2001

    
2002
    // Repeat the test with user pictures enabled, which modifies the form.
2003
    variable_set('user_pictures', 1);
2004
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2005
    $this->assertRaw(t('The name %name is already taken.', array('%name' => $edit['name'])));
2006

    
2007
    // Check that filling out a single password field does not validate.
2008
    $edit = array();
2009
    $edit['pass[pass1]'] = '';
2010
    $edit['pass[pass2]'] = $this->randomName();
2011
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2012
    $this->assertText(t("The specified passwords do not match."), 'Typing mismatched passwords displays an error message.');
2013

    
2014
    $edit['pass[pass1]'] = $this->randomName();
2015
    $edit['pass[pass2]'] = '';
2016
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2017
    $this->assertText(t("The specified passwords do not match."), 'Typing mismatched passwords displays an error message.');
2018

    
2019
    // Test that the error message appears when attempting to change the mail or
2020
    // pass without the current password.
2021
    $edit = array();
2022
    $edit['mail'] = $this->randomName() . '@new.example.com';
2023
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2024
    $this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => t('E-mail address'))));
2025

    
2026
    $edit['current_pass'] = $user1->pass_raw;
2027
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2028
    $this->assertRaw(t("The changes have been saved."));
2029

    
2030
    // Test that the user must enter current password before changing passwords.
2031
    $edit = array();
2032
    $edit['pass[pass1]'] = $new_pass = $this->randomName();
2033
    $edit['pass[pass2]'] = $new_pass;
2034
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2035
    $this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => t('Password'))));
2036

    
2037
    // Try again with the current password.
2038
    $edit['current_pass'] = $user1->pass_raw;
2039
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2040
    $this->assertRaw(t("The changes have been saved."));
2041

    
2042
    // Make sure the user can log in with their new password.
2043
    $this->drupalLogout();
2044
    $user1->pass_raw = $new_pass;
2045
    $this->drupalLogin($user1);
2046
    $this->drupalLogout();
2047
  }
2048

    
2049
  /**
2050
   * Tests setting the password to "0".
2051
   */
2052
  public function testUserWith0Password() {
2053
    $admin = $this->drupalCreateUser(array('administer users'));
2054
    $this->drupalLogin($admin);
2055
    // Create a regular user.
2056
    $user1 = $this->drupalCreateUser(array());
2057

    
2058
    $edit = array('pass[pass1]' => '0', 'pass[pass2]' => '0');
2059
    $this->drupalPost("user/" . $user1->uid . "/edit", $edit, t('Save'));
2060
    $this->assertRaw(t("The changes have been saved."));
2061

    
2062
    $this->drupalLogout();
2063
    $user1->pass_raw = '0';
2064
    $this->drupalLogin($user1);
2065
    $this->drupalLogout();
2066
  }
2067
}
2068

    
2069
/**
2070
 * Tests editing a user account with and without a form rebuild.
2071
 */
2072
class UserEditRebuildTestCase extends DrupalWebTestCase {
2073

    
2074
  public static function getInfo() {
2075
    return array(
2076
      'name' => 'User edit with form rebuild',
2077
      'description' => 'Test user edit page when a form rebuild is triggered.',
2078
      'group' => 'User',
2079
    );
2080
  }
2081

    
2082
  function setUp() {
2083
    parent::setUp('user_form_test');
2084
  }
2085

    
2086
  /**
2087
   * Test user edit page when the form is set to rebuild.
2088
   */
2089
  function testUserEditFormRebuild() {
2090
    $user1 = $this->drupalCreateUser(array('change own username'));
2091
    $this->drupalLogin($user1);
2092

    
2093
    $roles = array_keys($user1->roles);
2094
    // Save the user form twice.
2095
    $edit = array();
2096
    $edit['current_pass'] = $user1->pass_raw;
2097
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2098
    $this->assertRaw(t("The changes have been saved."));
2099
    $this->drupalPost(NULL, $edit, t('Save'));
2100
    $this->assertRaw(t("The changes have been saved."));
2101
    $saved_user1 = entity_load_unchanged('user', $user1->uid);
2102
    $this->assertEqual(count($roles), count($saved_user1->roles), 'Count of user roles in database matches original count.');
2103
    $diff = array_diff(array_keys($saved_user1->roles), $roles);
2104
    $this->assertTrue(empty($diff), format_string('User roles in database match original: @roles', array('@roles' => implode(', ', $saved_user1->roles))));
2105
    // Set variable that causes the form to be rebuilt in user_form_test.module.
2106
    variable_set('user_form_test_user_profile_form_rebuild', TRUE);
2107
    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
2108
    $this->assertRaw(t("The changes have been saved."));
2109
    $this->drupalPost(NULL, $edit, t('Save'));
2110
    $this->assertRaw(t("The changes have been saved."));
2111
    $saved_user1 = entity_load_unchanged('user', $user1->uid);
2112
    $this->assertEqual(count($roles), count($saved_user1->roles), 'Count of user roles in database matches original count.');
2113
    $diff = array_diff(array_keys($saved_user1->roles), $roles);
2114
    $this->assertTrue(empty($diff), format_string('User roles in database match original: @roles', array('@roles' => implode(', ', $saved_user1->roles))));
2115
  }
2116
}
2117

    
2118
/**
2119
 * Test case for user signatures.
2120
 */
2121
class UserSignatureTestCase extends DrupalWebTestCase {
2122
  public static function getInfo() {
2123
    return array(
2124
      'name' => 'User signatures',
2125
      'description' => 'Test user signatures.',
2126
      'group' => 'User',
2127
    );
2128
  }
2129

    
2130
  function setUp() {
2131
    parent::setUp('comment');
2132

    
2133
    // Enable user signatures.
2134
    variable_set('user_signatures', 1);
2135

    
2136
    // Prefetch text formats.
2137
    $this->full_html_format = filter_format_load('full_html');
2138
    $this->plain_text_format = filter_format_load('plain_text');
2139

    
2140
    // Create regular and administrative users.
2141
    $this->web_user = $this->drupalCreateUser(array());
2142
    $admin_permissions = array('administer comments');
2143
    foreach (filter_formats() as $format) {
2144
      if ($permission = filter_permission_name($format)) {
2145
        $admin_permissions[] = $permission;
2146
      }
2147
    }
2148
    $this->admin_user = $this->drupalCreateUser($admin_permissions);
2149
  }
2150

    
2151
  /**
2152
   * Test that a user can change their signature format and that it is respected
2153
   * upon display.
2154
   */
2155
  function testUserSignature() {
2156
    // Create a new node with comments on.
2157
    $node = $this->drupalCreateNode(array('comment' => COMMENT_NODE_OPEN));
2158

    
2159
    // Verify that user signature field is not displayed on registration form.
2160
    $this->drupalGet('user/register');
2161
    $this->assertNoText(t('Signature'));
2162

    
2163
    // Log in as a regular user and create a signature.
2164
    $this->drupalLogin($this->web_user);
2165
    $signature_text = "<h1>" . $this->randomName() . "</h1>";
2166
    $edit = array(
2167
      'signature[value]' => $signature_text,
2168
      'signature[format]' => $this->plain_text_format->format,
2169
    );
2170
    $this->drupalPost('user/' . $this->web_user->uid . '/edit', $edit, t('Save'));
2171

    
2172
    // Verify that values were stored.
2173
    $this->assertFieldByName('signature[value]', $edit['signature[value]'], 'Submitted signature text found.');
2174
    $this->assertFieldByName('signature[format]', $edit['signature[format]'], 'Submitted signature format found.');
2175

    
2176
    // Create a comment.
2177
    $langcode = LANGUAGE_NONE;
2178
    $edit = array();
2179
    $edit['subject'] = $this->randomName(8);
2180
    $edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16);
2181
    $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
2182
    $this->drupalPost(NULL, array(), t('Save'));
2183

    
2184
    // Get the comment ID. (This technique is the same one used in the Comment
2185
    // module's CommentHelperCase test case.)
2186
    preg_match('/#comment-([0-9]+)/', $this->getURL(), $match);
2187
    $comment_id = $match[1];
2188

    
2189
    // Log in as an administrator and edit the comment to use Full HTML, so
2190
    // that the comment text itself is not filtered at all.
2191
    $this->drupalLogin($this->admin_user);
2192
    $edit['comment_body[' . $langcode . '][0][format]'] = $this->full_html_format->format;
2193
    $this->drupalPost('comment/' . $comment_id . '/edit', $edit, t('Save'));
2194

    
2195
    // Assert that the signature did not make it through unfiltered.
2196
    $this->drupalGet('node/' . $node->nid);
2197
    $this->assertNoRaw($signature_text, 'Unfiltered signature text not found.');
2198
    $this->assertRaw(check_markup($signature_text, $this->plain_text_format->format), 'Filtered signature text found.');
2199
  }
2200
}
2201

    
2202
/*
2203
 * Test that a user, having editing their own account, can still log in.
2204
 */
2205
class UserEditedOwnAccountTestCase extends DrupalWebTestCase {
2206

    
2207
  public static function getInfo() {
2208
    return array(
2209
      'name' => 'User edited own account',
2210
      'description' => 'Test user edited own account can still log in.',
2211
      'group' => 'User',
2212
    );
2213
  }
2214

    
2215
  function testUserEditedOwnAccount() {
2216
    // Change account setting 'Who can register accounts?' to Administrators
2217
    // only.
2218
    variable_set('user_register', USER_REGISTER_ADMINISTRATORS_ONLY);
2219

    
2220
    // Create a new user account and log in.
2221
    $account = $this->drupalCreateUser(array('change own username'));
2222
    $this->drupalLogin($account);
2223

    
2224
    // Change own username.
2225
    $edit = array();
2226
    $edit['name'] = $this->randomName();
2227
    $this->drupalPost('user/' . $account->uid . '/edit', $edit, t('Save'));
2228

    
2229
    // Log out.
2230
    $this->drupalLogout();
2231

    
2232
    // Set the new name on the user account and attempt to log back in.
2233
    $account->name = $edit['name'];
2234
    $this->drupalLogin($account);
2235
  }
2236
}
2237

    
2238
/**
2239
 * Test case to test adding, editing and deleting roles.
2240
 */
2241
class UserRoleAdminTestCase extends DrupalWebTestCase {
2242

    
2243
  public static function getInfo() {
2244
    return array(
2245
      'name' => 'User role administration',
2246
      'description' => 'Test adding, editing and deleting user roles and changing role weights.',
2247
      'group' => 'User',
2248
    );
2249
  }
2250

    
2251
  function setUp() {
2252
    parent::setUp();
2253
    $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'administer users'));
2254
  }
2255

    
2256
  /**
2257
   * Test adding, renaming and deleting roles.
2258
   */
2259
  function testRoleAdministration() {
2260
    $this->drupalLogin($this->admin_user);
2261

    
2262
    // Test adding a role. (In doing so, we use a role name that happens to
2263
    // correspond to an integer, to test that the role administration pages
2264
    // correctly distinguish between role names and IDs.)
2265
    $role_name = '123';
2266
    $edit = array('name' => $role_name);
2267
    $this->drupalPost('admin/people/permissions/roles', $edit, t('Add role'));
2268
    $this->assertText(t('The role has been added.'), 'The role has been added.');
2269
    $role = user_role_load_by_name($role_name);
2270
    $this->assertTrue(is_object($role), 'The role was successfully retrieved from the database.');
2271

    
2272
    // Try adding a duplicate role.
2273
    $this->drupalPost(NULL, $edit, t('Add role'));
2274
    $this->assertRaw(t('The role name %name already exists. Choose another role name.', array('%name' => $role_name)), 'Duplicate role warning displayed.');
2275

    
2276
    // Test renaming a role.
2277
    $old_name = $role_name;
2278
    $role_name = '456';
2279
    $edit = array('name' => $role_name);
2280
    $this->drupalPost("admin/people/permissions/roles/edit/{$role->rid}", $edit, t('Save role'));
2281
    $this->assertText(t('The role has been renamed.'), 'The role has been renamed.');
2282
    $this->assertFalse(user_role_load_by_name($old_name), 'The role can no longer be retrieved from the database using its old name.');
2283
    $this->assertTrue(is_object(user_role_load_by_name($role_name)), 'The role can be retrieved from the database using its new name.');
2284

    
2285
    // Test deleting the default administrator role.
2286
    $role_name = 'administrator';
2287
    $role = user_role_load_by_name($role_name);
2288
    $this->drupalPost("admin/people/permissions/roles/edit/{$role->rid}", NULL, t('Delete role'));
2289
    $this->drupalPost(NULL, NULL, t('Delete'));
2290
    $this->assertText(t('The role has been deleted.'), 'The role has been deleted');
2291
    $this->assertNoLinkByHref("admin/people/permissions/roles/edit/{$role->rid}", 'Role edit link removed.');
2292
    $this->assertFalse(user_role_load_by_name($role_name), 'A deleted role can no longer be loaded.');
2293
    // Make sure this role is no longer configured as the administrator role.
2294
    $this->assertNull(variable_get('user_admin_role'), 'The administrator role is no longer configured as the administrator role.');
2295

    
2296
    // Make sure that the system-defined roles cannot be edited via the user
2297
    // interface.
2298
    $this->drupalGet('admin/people/permissions/roles/edit/' . DRUPAL_ANONYMOUS_RID);
2299
    $this->assertResponse(403, 'Access denied when trying to edit the built-in anonymous role.');
2300
    $this->drupalGet('admin/people/permissions/roles/edit/' . DRUPAL_AUTHENTICATED_RID);
2301
    $this->assertResponse(403, 'Access denied when trying to edit the built-in authenticated role.');
2302
  }
2303

    
2304
  /**
2305
   * Test user role weight change operation.
2306
   */
2307
  function testRoleWeightChange() {
2308
    $this->drupalLogin($this->admin_user);
2309

    
2310
    // Pick up a random role and get its weight.
2311
    $rid = array_rand(user_roles());
2312
    $role = user_role_load($rid);
2313
    $old_weight = $role->weight;
2314

    
2315
    // Change the role weight and submit the form.
2316
    $edit = array('roles['. $rid .'][weight]' => $old_weight + 1);
2317
    $this->drupalPost('admin/people/permissions/roles', $edit, t('Save order'));
2318
    $this->assertText(t('The role settings have been updated.'), 'The role settings form submitted successfully.');
2319

    
2320
    // Retrieve the saved role and compare its weight.
2321
    $role = user_role_load($rid);
2322
    $new_weight = $role->weight;
2323
    $this->assertTrue(($old_weight + 1) == $new_weight, 'Role weight updated successfully.');
2324
  }
2325
}
2326

    
2327
/**
2328
 * Test user token replacement in strings.
2329
 */
2330
class UserTokenReplaceTestCase extends DrupalWebTestCase {
2331
  public static function getInfo() {
2332
    return array(
2333
      'name' => 'User token replacement',
2334
      'description' => 'Generates text using placeholders for dummy content to check user token replacement.',
2335
      'group' => 'User',
2336
    );
2337
  }
2338

    
2339
  /**
2340
   * Creates a user, then tests the tokens generated from it.
2341
   */
2342
  function testUserTokenReplacement() {
2343
    global $language;
2344
    $url_options = array(
2345
      'absolute' => TRUE,
2346
      'language' => $language,
2347
    );
2348

    
2349
    // Create two users and log them in one after another.
2350
    $user1 = $this->drupalCreateUser(array());
2351
    $user2 = $this->drupalCreateUser(array());
2352
    $this->drupalLogin($user1);
2353
    $this->drupalLogout();
2354
    $this->drupalLogin($user2);
2355

    
2356
    $account = user_load($user1->uid);
2357
    $global_account = user_load($GLOBALS['user']->uid);
2358

    
2359
    // Generate and test sanitized tokens.
2360
    $tests = array();
2361
    $tests['[user:uid]'] = $account->uid;
2362
    $tests['[user:name]'] = check_plain(format_username($account));
2363
    $tests['[user:mail]'] = check_plain($account->mail);
2364
    $tests['[user:url]'] = url("user/$account->uid", $url_options);
2365
    $tests['[user:edit-url]'] = url("user/$account->uid/edit", $url_options);
2366
    $tests['[user:last-login]'] = format_date($account->login, 'medium', '', NULL, $language->language);
2367
    $tests['[user:last-login:short]'] = format_date($account->login, 'short', '', NULL, $language->language);
2368
    $tests['[user:created]'] = format_date($account->created, 'medium', '', NULL, $language->language);
2369
    $tests['[user:created:short]'] = format_date($account->created, 'short', '', NULL, $language->language);
2370
    $tests['[current-user:name]'] = check_plain(format_username($global_account));
2371

    
2372
    // Test to make sure that we generated something for each token.
2373
    $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
2374

    
2375
    foreach ($tests as $input => $expected) {
2376
      $output = token_replace($input, array('user' => $account), array('language' => $language));
2377
      $this->assertEqual($output, $expected, format_string('Sanitized user token %token replaced.', array('%token' => $input)));
2378
    }
2379

    
2380
    // Generate and test unsanitized tokens.
2381
    $tests['[user:name]'] = format_username($account);
2382
    $tests['[user:mail]'] = $account->mail;
2383
    $tests['[current-user:name]'] = format_username($global_account);
2384

    
2385
    foreach ($tests as $input => $expected) {
2386
      $output = token_replace($input, array('user' => $account), array('language' => $language, 'sanitize' => FALSE));
2387
      $this->assertEqual($output, $expected, format_string('Unsanitized user token %token replaced.', array('%token' => $input)));
2388
    }
2389
  }
2390
}
2391

    
2392
/**
2393
 * Test user search.
2394
 */
2395
class UserUserSearchTestCase extends DrupalWebTestCase {
2396
  public static function getInfo() {
2397
    return array(
2398
      'name' => 'User search',
2399
      'description' => 'Tests the user search page and verifies that sensitive information is hidden from unauthorized users.',
2400
      'group' => 'User',
2401
    );
2402
  }
2403

    
2404
  function testUserSearch() {
2405
    // Verify that a user without 'administer users' permission cannot search
2406
    // for users by email address. Additionally, ensure that the username has a
2407
    // plus sign to ensure searching works with that.
2408
    $user1 = $this->drupalCreateUser(array('access user profiles', 'search content', 'use advanced search'));
2409
    $edit['name'] = 'foo+bar';
2410
    $edit['mail'] = $edit['name'] . '@example.com';
2411
    user_save($user1, $edit);
2412
    $this->drupalLogin($user1);
2413
    $keys = $user1->mail;
2414
    $edit = array('keys' => $keys);
2415
    $this->drupalPost('search/user/', $edit, t('Search'));
2416
    $this->assertNoText($keys);
2417
    $this->drupalLogout();
2418

    
2419
    $user2 = $this->drupalCreateUser(array('administer users', 'access user profiles', 'search content', 'use advanced search'));
2420
    $this->drupalLogin($user2);
2421
    $keys = $user2->mail;
2422
    $edit = array('keys' => $keys);
2423
    $this->drupalPost('search/user/', $edit, t('Search'));
2424
    $this->assertText($keys);
2425

    
2426
    // Verify that wildcard search works.
2427
    $keys = $user1->name;
2428
    $keys = substr($keys, 0, 2) . '*' . substr($keys, 4, 2);
2429
    $edit = array('keys' => $keys);
2430
    $this->drupalPost('search/user/', $edit, t('Search'));
2431
    $this->assertText($user1->name, 'Search for username wildcard resulted in user name on page for administrative user.');
2432

    
2433
    // Verify that wildcard search works for email.
2434
    $keys = $user1->mail;
2435
    $keys = substr($keys, 0, 2) . '*' . substr($keys, 4, 2);
2436
    $edit = array('keys' => $keys);
2437
    $this->drupalPost('search/user/', $edit, t('Search'));
2438
    $this->assertText($user1->name, 'Search for email wildcard resulted in user name on page for administrative user.');
2439

    
2440
    // Create a blocked user.
2441
    $blocked_user = $this->drupalCreateUser();
2442
    $edit = array('status' => 0);
2443
    $blocked_user = user_save($blocked_user, $edit);
2444

    
2445
    // Verify that users with "administer users" permissions can see blocked
2446
    // accounts in search results.
2447
    $edit = array('keys' => $blocked_user->name);
2448
    $this->drupalPost('search/user/', $edit, t('Search'));
2449
    $this->assertText($blocked_user->name, 'Blocked users are listed on the user search results for users with the "administer users" permission.');
2450

    
2451
    // Verify that users without "administer users" permissions do not see
2452
    // blocked accounts in search results.
2453
    $this->drupalLogin($user1);
2454
    $edit = array('keys' => $blocked_user->name);
2455
    $this->drupalPost('search/user/', $edit, t('Search'));
2456
    $this->assertNoText($blocked_user->name, 'Blocked users are hidden from the user search results.');
2457

    
2458
    $this->drupalLogout();
2459
  }
2460
}
2461

    
2462
/**
2463
 * Test role assignment.
2464
 */
2465
class UserRolesAssignmentTestCase extends DrupalWebTestCase {
2466
  protected $admin_user;
2467

    
2468
  public static function getInfo() {
2469
    return array(
2470
      'name' => 'Role assignment',
2471
      'description' => 'Tests that users can be assigned and unassigned roles.',
2472
      'group' => 'User'
2473
    );
2474
  }
2475

    
2476
  function setUp() {
2477
    parent::setUp();
2478
    $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'administer users'));
2479
    $this->drupalLogin($this->admin_user);
2480
  }
2481

    
2482
  /**
2483
   * Tests that a user can be assigned a role and that the role can be removed
2484
   * again.
2485
   */
2486
  function testAssignAndRemoveRole()  {
2487
    $rid = $this->drupalCreateRole(array('administer content types'));
2488
    $account = $this->drupalCreateUser();
2489

    
2490
    // Assign the role to the user.
2491
    $this->drupalPost('user/' . $account->uid . '/edit', array("roles[$rid]" => $rid), t('Save'));
2492
    $this->assertText(t('The changes have been saved.'));
2493
    $this->assertFieldChecked('edit-roles-' . $rid, 'Role is assigned.');
2494
    $this->userLoadAndCheckRoleAssigned($account, $rid);
2495

    
2496
    // Remove the role from the user.
2497
    $this->drupalPost('user/' . $account->uid . '/edit', array("roles[$rid]" => FALSE), t('Save'));
2498
    $this->assertText(t('The changes have been saved.'));
2499
    $this->assertNoFieldChecked('edit-roles-' . $rid, 'Role is removed from user.');
2500
    $this->userLoadAndCheckRoleAssigned($account, $rid, FALSE);
2501
  }
2502

    
2503
  /**
2504
   * Tests that when creating a user the role can be assigned. And that it can
2505
   * be removed again.
2506
   */
2507
  function testCreateUserWithRole() {
2508
    $rid = $this->drupalCreateRole(array('administer content types'));
2509
    // Create a new user and add the role at the same time.
2510
    $edit = array(
2511
      'name' => $this->randomName(),
2512
      'mail' => $this->randomName() . '@example.com',
2513
      'pass[pass1]' => $pass = $this->randomString(),
2514
      'pass[pass2]' => $pass,
2515
      "roles[$rid]" => $rid,
2516
    );
2517
    $this->drupalPost('admin/people/create', $edit, t('Create new account'));
2518
    $this->assertText(t('Created a new user account for !name.', array('!name' => $edit['name'])));
2519
    // Get the newly added user.
2520
    $account = user_load_by_name($edit['name']);
2521

    
2522
    $this->drupalGet('user/' . $account->uid . '/edit');
2523
    $this->assertFieldChecked('edit-roles-' . $rid, 'Role is assigned.');
2524
    $this->userLoadAndCheckRoleAssigned($account, $rid);
2525

    
2526
    // Remove the role again.
2527
    $this->drupalPost('user/' . $account->uid . '/edit', array("roles[$rid]" => FALSE), t('Save'));
2528
    $this->assertText(t('The changes have been saved.'));
2529
    $this->assertNoFieldChecked('edit-roles-' . $rid, 'Role is removed from user.');
2530
    $this->userLoadAndCheckRoleAssigned($account, $rid, FALSE);
2531
  }
2532

    
2533
  /**
2534
   * Check role on user object.
2535
   *
2536
   * @param object $account
2537
   *   The user account to check.
2538
   * @param string $rid
2539
   *   The role ID to search for.
2540
   * @param bool $is_assigned
2541
   *   (optional) Whether to assert that $rid exists (TRUE) or not (FALSE).
2542
   *   Defaults to TRUE.
2543
   */
2544
  private function userLoadAndCheckRoleAssigned($account, $rid, $is_assigned = TRUE) {
2545
    $account = user_load($account->uid, TRUE);
2546
    if ($is_assigned) {
2547
      $this->assertTrue(array_key_exists($rid, $account->roles), 'The role is present in the user object.');
2548
    }
2549
    else {
2550
      $this->assertFalse(array_key_exists($rid, $account->roles), 'The role is not present in the user object.');
2551
    }
2552
  }
2553
}
2554

    
2555

    
2556
/**
2557
 * Unit test for authmap assignment.
2558
 */
2559
class UserAuthmapAssignmentTestCase extends DrupalWebTestCase {
2560
  public static function getInfo() {
2561
    return array(
2562
      'name' => 'Authmap assignment',
2563
      'description' => 'Tests that users can be assigned and unassigned authmaps.',
2564
      'group' => 'User'
2565
    );
2566
  }
2567

    
2568
  /**
2569
   * Test authmap assignment and retrieval.
2570
   */
2571
  function testAuthmapAssignment()  {
2572
    $account = $this->drupalCreateUser();
2573

    
2574
    // Assign authmaps to the user.
2575
    $authmaps = array(
2576
      'authname_poll' => 'external username one',
2577
      'authname_book' => 'external username two',
2578
    );
2579
    user_set_authmaps($account, $authmaps);
2580

    
2581
    // Test for expected authmaps.
2582
    $expected_authmaps = array(
2583
      'external username one' => array(
2584
        'poll' => 'external username one',
2585
      ),
2586
      'external username two' => array(
2587
        'book' => 'external username two',
2588
      ),
2589
    );
2590
    foreach ($expected_authmaps as $authname => $expected_output) {
2591
      $this->assertIdentical(user_get_authmaps($authname), $expected_output, format_string('Authmap for authname %authname was set correctly.', array('%authname' => $authname)));
2592
    }
2593

    
2594
    // Remove authmap for module poll, add authmap for module blog.
2595
    $authmaps = array(
2596
      'authname_poll' => NULL,
2597
      'authname_blog' => 'external username three',
2598
    );
2599
    user_set_authmaps($account, $authmaps);
2600

    
2601
    // Assert that external username one does not have authmaps.
2602
    $remove_username = 'external username one';
2603
    unset($expected_authmaps[$remove_username]);
2604
    $this->assertFalse(user_get_authmaps($remove_username), format_string('Authmap for %authname was removed.', array('%authname' => $remove_username)));
2605

    
2606
    // Assert that a new authmap was created for external username three, and
2607
    // existing authmaps for external username two were unchanged.
2608
    $expected_authmaps['external username three'] = array('blog' => 'external username three');
2609
    foreach ($expected_authmaps as $authname => $expected_output) {
2610
      $this->assertIdentical(user_get_authmaps($authname), $expected_output, format_string('Authmap for authname %authname was set correctly.', array('%authname' => $authname)));
2611
    }
2612
  }
2613
}
2614

    
2615
/**
2616
 * Tests user_validate_current_pass on a custom form.
2617
 */
2618
class UserValidateCurrentPassCustomForm extends DrupalWebTestCase {
2619

    
2620
  public static function getInfo() {
2621
    return array(
2622
      'name' => 'User validate current pass custom form',
2623
      'description' => 'Test that user_validate_current_pass is usable on a custom form.',
2624
      'group' => 'User',
2625
    );
2626
  }
2627

    
2628
  /**
2629
   * User with permission to view content.
2630
   */
2631
  protected $accessUser;
2632

    
2633
  /**
2634
   * User permission to administer users.
2635
   */
2636
  protected $adminUser;
2637

    
2638
  function setUp() {
2639
    parent::setUp('user_form_test');
2640
    // Create two users
2641
    $this->accessUser = $this->drupalCreateUser(array('access content'));
2642
    $this->adminUser = $this->drupalCreateUser(array('administer users'));
2643
  }
2644

    
2645
  /**
2646
   * Tests that user_validate_current_pass can be reused on a custom form.
2647
   */
2648
  function testUserValidateCurrentPassCustomForm() {
2649
    $this->drupalLogin($this->adminUser);
2650

    
2651
    // Submit the custom form with the admin user using the access user's password.
2652
    $edit = array();
2653
    $edit['user_form_test_field'] = $this->accessUser->name;
2654
    $edit['current_pass'] = $this->accessUser->pass_raw;
2655
    $this->drupalPost('user_form_test_current_password/' . $this->accessUser->uid, $edit, t('Test'));
2656
    $this->assertText(t('The password has been validated and the form submitted successfully.'));
2657
  }
2658
}