function StorageTest::testImmutableFormLegacyProtection

Same name in other branches
  1. 8.9.x core/modules/system/tests/src/Functional/Form/StorageTest.php \Drupal\Tests\system\Functional\Form\StorageTest::testImmutableFormLegacyProtection()
  2. 10 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 184

Class

StorageTest
Tests a multistep form using form storage.

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->assertArrayNotHasKey('#poisoned', $original['form'], 'Original form structure was preserved');
    $this->assertArrayNotHasKey('poisoned', $original['form_state'], 'Original form state was preserved');
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.