Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.407 diff -u -p -r1.407 form.inc --- includes/form.inc 27 Nov 2009 15:14:58 -0000 1.407 +++ includes/form.inc 28 Nov 2009 16:19:22 -0000 @@ -459,6 +459,10 @@ function drupal_form_submit($form_id, &$ // Merge in default values. $form_state += form_state_defaults(); + // Reset form validation. + $form_state['must_validate'] = TRUE; + form_clear_error(); + drupal_prepare_form($form_id, $form, $form_state); drupal_process_form($form_id, $form, $form_state); } Index: modules/simpletest/tests/form.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v retrieving revision 1.25 diff -u -p -r1.25 form.test --- modules/simpletest/tests/form.test 18 Nov 2009 18:51:11 -0000 1.25 +++ modules/simpletest/tests/form.test 28 Nov 2009 16:42:34 -0000 @@ -354,6 +354,71 @@ class FormsElementsTableSelectFunctional } /** + * Test the programmatic form submission behavior. + */ +class FormsProgrammaticTestCase extends DrupalWebTestCase { + + function getInfo() { + return array( + 'name' => 'Programmatic form submissions', + 'description' => 'Test the programmatic form submission behavior.', + 'group' => 'Form API', + ); + } + + function setUp() { + parent::setUp('form_test'); + } + + /** + * Test the programmatic form submission workflow. + */ + function testSubmissionWorkflow() { + // Backup the current batch status and reset it to avoid conflicts while + // processing the dummy form submit handler. + $current_batch = $batch =& batch_get(); + $batch = array(); + + $this->submitForm(); + $this->submitForm('test 1'); + $this->submitForm(); + $this->submitForm('test 2'); + + // Restore the current batch status. + $batch = $current_batch; + } + + /** + * Helper function used to programmatically submit the form defined in + * form_test.module with the given value. + * + * @param string $value + * The field value to be submitted. + */ + private function submitForm($value = NULL) { + // Programmatically submit the given value. + $form_state = array('values' => array('submitted_field' => $value)); + drupal_form_submit('form_test_programmatic_form', $form_state); + + $errors = form_get_errors(); + $valid_form = empty($errors); + $valid_input = !empty($value); + + // If no value was passed the form should return an error and viceversa. + $args = array('%value' => $value, '%errors' => $valid_form ? '' : implode(' ', $errors)); + $this->assertTrue($valid_input == $valid_form, t('Input value: %value
Validation handler errors: %errors', $args)); + + // We check submitted values only if we have a valid input. + if ($valid_input) { + // By fetching the value from $form_state['storage'] we ensure that the + // submission handler was properly executed. + $submitted_value = $form_state['storage']['programmatic_form_submit']; + $this->assertTrue($submitted_value == $value, t('Submission handler correctly executed: %submitted_value', array('%submitted_value' => $submitted_value))); + } + } +} + +/** * Test using drupal_form_submit in a batch. */ class FormAPITestCase extends DrupalWebTestCase { Index: modules/simpletest/tests/form_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v retrieving revision 1.17 diff -u -p -r1.17 form_test.module --- modules/simpletest/tests/form_test.module 21 Nov 2009 17:01:31 -0000 1.17 +++ modules/simpletest/tests/form_test.module 28 Nov 2009 16:42:46 -0000 @@ -212,6 +212,40 @@ function _form_test_tableselect_js_selec } /** + * Form builder to test programmatic form submissions. + */ +function form_test_programmatic_form($form, &$form_state) { + $form['submitted_field'] = array( + '#title' => 'Submitted', + '#type' => 'textfield', + ); + + return $form; +} + +/** + * Form validation handler for programmatic form submissions. + * + * To test that the validation handler is correctly executed, the field value is + * explicitly required here. + */ +function form_test_programmatic_form_validate($form, &$form_state) { + if (empty($form_state['values']['submitted_field'])) { + form_set_error('submitted_field', t('Submitted field is required.')); + } +} + +/** + * Form submit handler for programmatic form submissions. + * + * To test that the submission handler is correctly executed, we store the + * submitted value in a place we can access from the caller context. + */ +function form_test_programmatic_form_submit($form, &$form_state) { + $form_state['storage']['programmatic_form_submit'] = $form_state['values']['submitted_field']; +} + +/** * Page callback for the batch/drupal_form_submit interaction test. * * When called without any arguments we set up a batch that calls