You are here

public function StorageTest::testImmutableFormLegacyProtection in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/system/tests/src/Functional/Form/StorageTest.php \Drupal\Tests\system\Functional\Form\StorageTest::testImmutableFormLegacyProtection()

Verify that existing contrib code cannot overwrite immutable form state.

File

core/modules/system/tests/src/Functional/Form/StorageTest.php, line 186

Class

StorageTest
Tests a multistep form using form storage and makes sure validation and caching works right.

Namespace

Drupal\Tests\system\Functional\Form

Code

public function testImmutableFormLegacyProtection() {
  $this
    ->drupalGet('form_test/form-storage', [
    'query' => [
      'cache' => 1,
      'immutable' => 1,
    ],
  ]);

  // Ensure the hidden 'form_build_id' field is unique.
  $this
    ->assertSession()
    ->elementsCount('xpath', '//input[@name="form_build_id"]', 1);
  $build_id = $this
    ->assertSession()
    ->hiddenFieldExists('form_build_id')
    ->getValue();

  // Try to poison the form cache.
  $response = $this
    ->drupalGet('form-test/form-storage-legacy/' . $build_id, [
    'query' => [
      MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax',
    ],
  ], [
    'X-Requested-With: XMLHttpRequest',
  ]);
  $original = json_decode($response, TRUE);
  $this
    ->assertEquals($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded');
  $this
    ->assertNotEquals($original['form']['#build_id'], $build_id, 'New build_id was generated');

  // Assert that a watchdog message was logged by
  // \Drupal::formBuilder()->setCache().
  $status = (bool) Database::getConnection()
    ->select('watchdog')
    ->condition('message', 'Form build-id mismatch detected while attempting to store a form in the cache.')
    ->range(0, 1)
    ->countQuery()
    ->execute()
    ->fetchField();
  $this
    ->assertTrue($status, 'A watchdog message was logged by \\Drupal::formBuilder()->setCache');

  // Ensure that the form state was not poisoned by the preceding call.
  $response = $this
    ->drupalGet('form-test/form-storage-legacy/' . $build_id, [
    'query' => [
      MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax',
    ],
  ], [
    'X-Requested-With: XMLHttpRequest',
  ]);
  $original = json_decode($response, TRUE);
  $this
    ->assertEquals($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded');
  $this
    ->assertNotEquals($original['form']['#build_id'], $build_id, 'New build_id was generated');
  $this
    ->assertTrue(empty($original['form']['#poisoned']), 'Original form structure was preserved');
  $this
    ->assertTrue(empty($original['form_state']['poisoned']), 'Original form state was preserved');
}