Index: modules/simpletest/tests/form.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v retrieving revision 1.13 diff -u -r1.13 form.test --- modules/simpletest/tests/form.test 2 Jun 2009 13:47:26 -0000 1.13 +++ modules/simpletest/tests/form.test 18 Jun 2009 16:40:25 -0000 @@ -385,6 +385,41 @@ } /** + * Test of Form API behavior of disabled fields. + */ +class FormDisabledFieldTestCase extends DrupalWebTestCase { + + public static function getInfo() { + return array( + 'name' => t('Disabled field'), + 'description' => t('Test of Form API behavior of disabled fields.'), + 'group' => t('Form API'), + ); + } + + public function setUp() { + parent::setUp('form_test'); + } + + /** + * Test of Form API behavior of disabled fields. + * + * Bypass SimpleTest's checks for disabled fields being submitted using the + * $edit array by using th eadditional_post parameter. This forces SimpleTest + * to post any values placed in the array. The form API does not ignore + * values for disabled fields so the value should be saved. + */ + public function testDisabledField() { + $edit = array( + 'form_test_disabled_field' => $this->randomName(), + ); + $this->drupalPost('form_test/disabled-field', array(), t('Save configuration'), array('additional_post' => $edit)); + $this->assertText(t('The configuration options have been saved.')); + $this->assertFieldByName('form_test_disabled_field', $edit['form_test_disabled_field']); + } +} + +/** * Test the form storage on a multistep form. * * The tested form puts data into the storage during the initial form @@ -430,7 +465,7 @@ $user = $this->drupalCreateUser(array('access content')); $this->drupalLogin($user); - $this->drupalPost('form_test/form-storage', array('title' => 'new', 'value' => 'value_is_set'), 'Continue', array('query' => 'cache=1')); + $this->drupalPost('form_test/form-storage', array('title' => 'new', 'value' => 'value_is_set'), 'Continue', array('url_options' => array('query' => 'cache=1'))); $this->assertText('Form constructions: 1', t('The form has been constructed one time till now.')); $this->drupalPost(NULL, array(), 'Save', array('query' => 'cache=1')); Index: modules/simpletest/tests/form_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v retrieving revision 1.7 diff -u -r1.7 form_test.module --- modules/simpletest/tests/form_test.module 27 May 2009 18:34:00 -0000 1.7 +++ modules/simpletest/tests/form_test.module 18 Jun 2009 16:40:25 -0000 @@ -66,6 +66,14 @@ 'type' => MENU_CALLBACK, ); + $items['form_test/disabled-field'] = array( + 'title' => 'Disabled field', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('form_test_disabled_field_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; } @@ -233,7 +241,7 @@ * drupal_form_submit using the values specified in this function. * * The form's field test_value begins at 'initial_value', and is changed - * to 'form_submitted' when the form is submitted successfully. On + * to 'form_submitted' when the form is submitted successfully. On * completion this function is passed 'done' to complete the process. */ function form_test_drupal_form_submit_batch_api($arg = '') { @@ -289,6 +297,21 @@ } /** + * A settings form with a disabled field on it. + */ +function form_test_disabled_field_form($form_state) { + $form = array(); + + $form['form_test_disabled_field'] = array( + '#type' => 'textfield', + '#default_value' => variable_get('form_test_disabled_field', ''), + '#disabled' => TRUE, + ); + + return system_settings_form($form); +} + +/** * A multistep form for testing the form storage. * * It uses two steps for editing a virtual "thing". Any changes to it are saved Index: modules/translation/translation.test =================================================================== RCS file: /cvs/drupal/drupal/modules/translation/translation.test,v retrieving revision 1.12 diff -u -r1.12 translation.test --- modules/translation/translation.test 12 Jun 2009 08:39:40 -0000 1.12 +++ modules/translation/translation.test 18 Jun 2009 16:40:25 -0000 @@ -111,10 +111,14 @@ } else { // Ensure that it is enabled. - $this->assertTrue(true, 'Language [' . $language_code . '] already installed.'); - $this->drupalPost(NULL, array('enabled[' . $language_code . ']' => TRUE), t('Save configuration')); - - $this->assertRaw(t('Configuration saved.'), t('Language successfully enabled.')); + $this->assertTrue(TRUE, 'Language [' . $language_code . '] already installed.'); + if (!$this->xpath("//input[@id='edit-enabled-" . $language_code . "' and @checked='checked']")) { + $this->drupalPost(NULL, array('enabled[' . $language_code . ']' => TRUE), t('Save configuration')); + $this->assertRaw(t('Configuration saved.'), t('Language [' . $language_code . '] successfully enabled.')); + } + else { + $this->assertTrue(TRUE, t('Language [' . $language_code . '] already enabled.')); + } } } Index: modules/simpletest/drupal_web_test_case.php =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v retrieving revision 1.117 diff -u -r1.117 drupal_web_test_case.php --- modules/simpletest/drupal_web_test_case.php 16 Jun 2009 04:43:47 -0000 1.117 +++ modules/simpletest/drupal_web_test_case.php 18 Jun 2009 16:40:25 -0000 @@ -1313,13 +1313,15 @@ * NULL to post to the current page. For multi-stage forms you can set the * path to NULL and have it post to the last received page. Example: * - * // First step in form. - * $edit = array(...); - * $this->drupalPost('some_url', $edit, t('Save')); - * - * // Second step in form. - * $edit = array(...); - * $this->drupalPost(NULL, $edit, t('Save')); + * @code + * // First step in form. + * $edit = array(...); + * $this->drupalPost('some_url', $edit, t('Save')); + * + * // Second step in form. + * $edit = array(...); + * $this->drupalPost(NULL, $edit, t('Save')); + * @endcode * @param $edit * Field data in an associative array. Changes the current input fields * (where possible) to the values indicated. A checkbox can be set to @@ -1329,20 +1331,37 @@ * * Multiple select fields can be set using name[] and setting each of the * possible values. Example: - * $edit = array(); - * $edit['name[]'] = array('value1', 'value2'); + * @code + * $edit = array(); + * $edit['name[]'] = array('value1', 'value2'); + * @endcode * @param $submit * Value of the submit button. * @param $options - * Options to be forwarded to url(). - * @param $headers - * An array containing additional HTTP request headers, each formatted as - * "name: value". - */ - protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array()) { + * Array with additional options. The following keys can be used: + * - "url_options": Options to be passed to url() as $options parameter. + * - "headers": Array with HTTP headers, each formatted as "name: value". + * - "additional_post": An associative array of additional POST data to be + * submitted in addition to any values in $edit. The values will not be + * checked against the current form as values in $edit are and thus it + * can be used to submit values for disabled fields or non-existant + * fields. An example for how to send values for disabled fields follows: + * + * @code + * $options = array('additional_post' => array('disabled_field' => value)); + * @endcode + */ + protected function drupalPost($path, $edit, $submit, array $options = array()) { + + $options += array( + 'url_options' => array(), + 'headers' => array(), + 'additional_post' => array(), + ); + $submit_matches = FALSE; if (isset($path)) { - $html = $this->drupalGet($path, $options); + $html = $this->drupalGet($path, $options['url_options']); } if ($this->parse()) { $edit_save = $edit; @@ -1359,6 +1378,7 @@ // We post only if we managed to handle every field in edit and the // submit button matches. if (!$edit && $submit_matches) { + $post += $options['additional_post']; if ($upload) { // TODO: cURL handles file uploads for us, but the implementation // is broken. This is a less than elegant workaround. Alternatives @@ -1379,7 +1399,7 @@ } $post = implode('&', $post); } - $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $headers)); + $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $options['headers'])); // Ensure that any changes to variables in the other thread are picked up. $this->refreshVariables(); @@ -1464,6 +1484,18 @@ foreach ($elements as $element) { // SimpleXML objects need string casting all the time. $name = (string) $element['name']; + + // Generate a failure when disabled elements are set, as those cannot be 'successful' (ie. be part + // of form submissions), according to: + // http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.12 + if (!empty($element['disabled'])) { + if (isset($edit[$name])) { + $this->fail(t('Field @name is disabled, sending of disabled fields is not allowed.', array('@name' => $name))); + } + unset($edit[$name]); + continue; + } + // This can either be the type of or the name of the tag itself // for