diff options
Diffstat (limited to 'modules/simpletest/tests/form.test')
-rw-r--r-- | modules/simpletest/tests/form.test | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test index 1d430b582..f90b854c7 100644 --- a/modules/simpletest/tests/form.test +++ b/modules/simpletest/tests/form.test @@ -1156,6 +1156,182 @@ class FormsFormStorageTestCase extends DrupalWebTestCase { $this->assertText('State persisted.'); } } + + /** + * Verify that the form build-id remains the same when validation errors + * occur on a mutable form. + */ + function testMutableForm() { + // Request the form with 'cache' query parameter to enable form caching. + $this->drupalGet('form_test/form-storage', array('query' => array('cache' => 1))); + $buildIdFields = $this->xpath('//input[@name="form_build_id"]'); + $this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page'); + $buildId = (string) $buildIdFields[0]['value']; + + // Trigger validation error by submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Continue submit'); + + // Verify that the build-id did not change. + $this->assertFieldByName('form_build_id', $buildId, 'Build id remains the same when form validation fails'); + } + + /** + * Verifies that form build-id is regenerated when loading an immutable form + * from the cache. + */ + function testImmutableForm() { + // Request the form with 'cache' query parameter to enable form caching. + $this->drupalGet('form_test/form-storage', array('query' => array('cache' => 1, 'immutable' => 1))); + $buildIdFields = $this->xpath('//input[@name="form_build_id"]'); + $this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page'); + $buildId = (string) $buildIdFields[0]['value']; + + // Trigger validation error by submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Continue submit'); + + // Verify that the build-id did change. + $this->assertNoFieldByName('form_build_id', $buildId, 'Build id changes when form validation fails'); + + // Retrieve the new build-id. + $buildIdFields = $this->xpath('//input[@name="form_build_id"]'); + $this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page'); + $buildId = (string) $buildIdFields[0]['value']; + + // Trigger validation error by again submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Continue submit'); + + // Verify that the build-id does not change the second time. + $this->assertFieldByName('form_build_id', $buildId, 'Build id remains the same when form validation fails subsequently'); + } + + /** + * Verify that existing contrib code cannot overwrite immutable form state. + */ + public function testImmutableFormLegacyProtection() { + $this->drupalGet('form_test/form-storage', array('query' => array('cache' => 1, 'immutable' => 1))); + $build_id_fields = $this->xpath('//input[@name="form_build_id"]'); + $this->assertEqual(count($build_id_fields), 1, 'One form build id field on the page'); + $build_id = (string) $build_id_fields[0]['value']; + + // Try to poison the form cache. + $original = $this->drupalGetAJAX('form_test/form-storage-legacy/' . $build_id); + $this->assertEqual($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded'); + $this->assertNotEqual($original['form']['#build_id'], $build_id, 'New build_id was generated'); + + // Assert that a watchdog message was logged by form_set_cache. + $status = (bool) db_query_range('SELECT 1 FROM {watchdog} WHERE message = :message', 0, 1, array(':message' => 'Form build-id mismatch detected while attempting to store a form in the cache.')); + $this->assert($status, 'A watchdog message was logged by form_set_cache'); + + // Ensure that the form state was not poisoned by the preceeding call. + $original = $this->drupalGetAJAX('form_test/form-storage-legacy/' . $build_id); + $this->assertEqual($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded'); + $this->assertNotEqual($original['form']['#build_id'], $build_id, 'New build_id was generated'); + $this->assert(empty($original['form']['#poisoned']), 'Original form structure was preserved'); + $this->assert(empty($original['form_state']['poisoned']), 'Original form state was preserved'); + } +} + +/** + * Test the form storage when page caching for anonymous users is turned on. + */ +class FormsFormStoragePageCacheTestCase extends DrupalWebTestCase { + protected $profile = 'testing'; + + public static function getInfo() { + return array( + 'name' => 'Forms using form storage on cached pages', + 'description' => 'Tests a form using form storage and makes sure validation and caching works when page caching for anonymous users is turned on.', + 'group' => 'Form API', + ); + } + + public function setUp() { + parent::setUp('form_test'); + + variable_set('cache', TRUE); + } + + /** + * Return the build id of the current form. + */ + protected function getFormBuildId() { + $build_id_fields = $this->xpath('//input[@name="form_build_id"]'); + $this->assertEqual(count($build_id_fields), 1, 'One form build id field on the page'); + return (string) $build_id_fields[0]['value']; + } + + /** + * Build-id is regenerated when validating cached form. + */ + public function testValidateFormStorageOnCachedPage() { + $this->drupalGet('form_test/form-storage-page-cache'); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.'); + $this->assertText('No old build id', 'No old build id on the page'); + $build_id_initial = $this->getFormBuildId(); + + // Trigger validation error by submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Save'); + $this->assertText($build_id_initial, 'Old build id on the page'); + $build_id_first_validation = $this->getFormBuildId(); + $this->assertNotEqual($build_id_initial, $build_id_first_validation, 'Build id changes when form validation fails'); + + // Trigger validation error by again submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Save'); + $this->assertText('No old build id', 'No old build id on the page'); + $build_id_second_validation = $this->getFormBuildId(); + $this->assertEqual($build_id_first_validation, $build_id_second_validation, 'Build id remains the same when form validation fails subsequently'); + + // Repeat the test sequence but this time with a page loaded from the cache. + $this->drupalGet('form_test/form-storage-page-cache'); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.'); + $this->assertText('No old build id', 'No old build id on the page'); + $build_id_from_cache_initial = $this->getFormBuildId(); + $this->assertEqual($build_id_initial, $build_id_from_cache_initial, 'Build id is the same as on the first request'); + + // Trigger validation error by submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Save'); + $this->assertText($build_id_initial, 'Old build id is initial build id'); + $build_id_from_cache_first_validation = $this->getFormBuildId(); + $this->assertNotEqual($build_id_initial, $build_id_from_cache_first_validation, 'Build id changes when form validation fails'); + $this->assertNotEqual($build_id_first_validation, $build_id_from_cache_first_validation, 'Build id from first user is not reused'); + + // Trigger validation error by again submitting an empty title. + $edit = array('title' => ''); + $this->drupalPost(NULL, $edit, 'Save'); + $this->assertText('No old build id', 'No old build id on the page'); + $build_id_from_cache_second_validation = $this->getFormBuildId(); + $this->assertEqual($build_id_from_cache_first_validation, $build_id_from_cache_second_validation, 'Build id remains the same when form validation fails subsequently'); + } + + /** + * Build-id is regenerated when rebuilding cached form. + */ + public function testRebuildFormStorageOnCachedPage() { + $this->drupalGet('form_test/form-storage-page-cache'); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.'); + $this->assertText('No old build id', 'No old build id on the page'); + $build_id_initial = $this->getFormBuildId(); + + // Trigger rebuild, should regenerate build id. + $edit = array('title' => 'something'); + $this->drupalPost(NULL, $edit, 'Rebuild'); + $this->assertText($build_id_initial, 'Initial build id as old build id on the page'); + $build_id_first_rebuild = $this->getFormBuildId(); + $this->assertNotEqual($build_id_initial, $build_id_first_rebuild, 'Build id changes on first rebuild.'); + + // Trigger subsequent rebuild, should regenerate the build id again. + $edit = array('title' => 'something'); + $this->drupalPost(NULL, $edit, 'Rebuild'); + $this->assertText($build_id_first_rebuild, 'First build id as old build id on the page'); + $build_id_second_rebuild = $this->getFormBuildId(); + $this->assertNotEqual($build_id_first_rebuild, $build_id_second_rebuild, 'Build id changes on second rebuild.'); + } } /** |