0

I'm trying to create a Functional test for the dev version of the No Autocomplete module to test that if the configuration is set then an autocomplete attribute=off will be added to the password edit in the user login form.

<?php

namespace Drupal\Tests\no_autocomplete\Functional;

use Drupal\Tests\BrowserTestBase;

class FormTest extends BrowserTestBase {

  protected static $modules = ['no_autocomplete'];

  public function testUserLoginForm() {

    $account = $this->drupalCreateUser(['administer no_autocomplete']);
    $this->drupalLogin($account);

    $this->drupalGet('/admin/config/people/no_autocomplete');

    $edit = [
      'no_autocomplete_login_form' => 1,
    ];
    $this->drupalPostForm(NULL, $edit, 'op');

    $this->drupalLogout();
    $this->drupalGet('/user/login');

    $this->assertSession()->elementAttributeContains('css', '#edit-pass', 'autocomplete', 'off');
  }

}

So basically I'm trying to test this hook after that the configuration is set:

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Turn off autocomplete on key forms.
 */
function no_autocomplete_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Add to the user_login.
  if (\Drupal::service('config.factory')->get('no_autocomplete.settings')->get('no_autocomplete_login_form')) {
    $form['pass']['#attributes']['autocomplete'] = 'off';
  }
}

The problem is that the module works as expected, but when I run the test this line inside the hook:

\Drupal::service('config.factory')->get('no_autocomplete.settings')->get('no_autocomplete_login_form')

Always return FALSE, because this is the default configuration value that comes in the no_autocomplete.settings file, if I change the value from FALSE to 5, the 5 is returned. But when I check the value of the config in the test it assert correct with TRUE, inside the test the value is TRUE but inside the hook the value is FALSE (or whatever the default value of the variable is) I check the value in the test with the following lines:

$config_factory = $this->container->get('config.factory');

$no_autocomplete_login_form = $config_factory->get('no_autocomplete.settings')->get('no_autocomplete_login_form');

$this->assertSession()->assert($no_autocomplete_login_form == TRUE, t('The default configuration value for no_autocomplete_login_form should be TRUE.'));

$this->assertSession()->elementAttributeContains('css', '#edit-pass', 'autocomplete', 'off');
  }

}

So, the configuration variable have TRUE as value, but inside the hook the value is always FALSE, so the autocomplete=off attribute is never added to the form element en the test fail.

I'm trying to read in the wrong way the variable inside the hook or I'm missing something here?

EDIT: It seems a cache problem, if I clean the cache inside the hooks the test is OK, but the only problem is that I really don't need to clean the cache for made the module works.

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Turn off autocomplete on key forms.
 */
function no_autocomplete_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Add to the user_login.
  drupal_flush_all_caches();
  if (\Drupal::service('config.factory')->get('no_autocomplete.settings')->get('no_autocomplete_login_form')) {
    $form['pass']['#attributes']['autocomplete'] = 'off';
  }
}

So I don't know now if this is a Drupal or PHPUnit issue. Any ideas?

0

I found an answer that solve this problem, but I think that maybe there are other answer to this.

After some ideas from @tim.plunkett on slack:

as i see it: with render caching, changing the config value will not alter the form

and

the tl;dr is that any conditionals in render-related code need cache contexts

I made the test work with this code:

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Turn off autocomplete on key forms.
 */
function no_autocomplete_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Adding cache tags.
  $form['#cache']['tags'] = ['config:no_autocomplete.settings'];

  // Add to the user_login.
  if (\Drupal::service('config.factory')->get('no_autocomplete.settings')->get('no_autocomplete_login_form')) {
    $form['pass']['#attributes']['autocomplete'] = 'off';
  }
}

This is the simplest way that I was found because in this case the config object only have one variable and each time that the config is changed is because this variable has changed, so in this case I think that the use of the cache tags is fine.

But I'm still trying to made works the code with a custom cache contexts. But I don't have luck for the moment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.