You are here

UserAccountFormFieldsTest.php in Drupal 10

File

core/modules/user/tests/src/Kernel/UserAccountFormFieldsTest.php
View source
<?php

namespace Drupal\Tests\user\Kernel;

use Drupal\Core\Form\FormState;
use Drupal\KernelTests\KernelTestBase;

/**
 * Verifies that the field order in user account forms is compatible with
 * password managers of web browsers.
 *
 * @group user
 */
class UserAccountFormFieldsTest extends KernelTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  protected static $modules = [
    'system',
    'user',
    'field',
  ];

  /**
   * Tests the root user account form section in the "Configure site" form.
   */
  public function testInstallConfigureForm() {
    require_once $this->root . '/core/includes/install.core.inc';
    require_once $this->root . '/core/includes/install.inc';
    $install_state = install_state_defaults();
    $form_state = new FormState();
    $form_state
      ->addBuildInfo('args', [
      &$install_state,
    ]);
    $form = $this->container
      ->get('form_builder')
      ->buildForm('Drupal\\Core\\Installer\\Form\\SiteConfigureForm', $form_state);

    // Verify name and pass field order.
    $this
      ->assertFieldOrder($form['admin_account']['account']);

    // Verify that web browsers may autocomplete the email value and
    // autofill/prefill the name and pass values.
    foreach ([
      'mail',
      'name',
      'pass',
    ] as $key) {
      $this
        ->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'{$key}' field: 'autocomplete' attribute not found.");
    }
  }

  /**
   * Tests the user registration form.
   */
  public function testUserRegistrationForm() {

    // Install default configuration; required for AccountFormController.
    $this
      ->installConfig([
      'user',
    ]);

    // Disable email confirmation to unlock the password field.
    $this
      ->config('user.settings')
      ->set('verify_mail', FALSE)
      ->save();
    $form = $this
      ->buildAccountForm('register');

    // Verify name and pass field order.
    $this
      ->assertFieldOrder($form['account']);

    // Verify that web browsers may autocomplete the email value and
    // autofill/prefill the name and pass values.
    foreach ([
      'mail',
      'name',
      'pass',
    ] as $key) {
      $this
        ->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'{$key}' field: 'autocomplete' attribute not found.");
    }
  }

  /**
   * Tests the user edit form.
   */
  public function testUserEditForm() {

    // Install default configuration; required for AccountFormController.
    $this
      ->installConfig([
      'user',
    ]);
    $form = $this
      ->buildAccountForm('default');

    // Verify name and pass field order.
    $this
      ->assertFieldOrder($form['account']);

    // Verify that autocomplete is off on all account fields.
    foreach ([
      'mail',
      'name',
      'pass',
    ] as $key) {
      $this
        ->assertSame('off', $form['account'][$key]['#attributes']['autocomplete'], "'{$key}' field: 'autocomplete' attribute is 'off'.");
    }
  }

  /**
   * Asserts that the 'name' form element is directly before the 'pass' element.
   *
   * @param array $elements
   *   A form array section that contains the user account form elements.
   *
   * @internal
   */
  protected function assertFieldOrder(array $elements) : void {
    $name_index = 0;
    $name_weight = 0;
    $pass_index = 0;
    $pass_weight = 0;
    $index = 0;
    foreach ($elements as $key => $element) {
      if ($key === 'name') {
        $name_index = $index;
        $name_weight = $element['#weight'];
        $this
          ->assertTrue($element['#sorted'], "'name' field is #sorted.");
      }
      elseif ($key === 'pass') {
        $pass_index = $index;
        $pass_weight = $element['#weight'];
        $this
          ->assertTrue($element['#sorted'], "'pass' field is #sorted.");
      }
      $index++;
    }
    $this
      ->assertEquals($pass_index - 1, $name_index, "'name' field ({$name_index}) appears before 'pass' field ({$pass_index}).");
    $this
      ->assertLessThan($pass_weight, $name_weight, "'name' field weight ({$name_weight}) should be smaller than 'pass' field weight ({$pass_weight}).");
  }

  /**
   * Builds the user account form for a given operation.
   *
   * @param string $operation
   *   The entity operation; one of 'register' or 'default'.
   *
   * @return array
   *   The form array.
   */
  protected function buildAccountForm($operation) {

    // @see HtmlEntityFormController::getFormObject()
    $entity_type = 'user';
    $fields = [];
    if ($operation != 'register') {
      $fields['uid'] = 2;
    }
    $entity = $this->container
      ->get('entity_type.manager')
      ->getStorage($entity_type)
      ->create($fields);

    // @see EntityFormBuilder::getForm()
    return $this->container
      ->get('entity.form_builder')
      ->getForm($entity, $operation);
  }

}

Classes

Namesort descending Description
UserAccountFormFieldsTest Verifies that the field order in user account forms is compatible with password managers of web browsers.