'Required field validation', 'description' => 'Carriage returns, tabs, and spaces are not valid content for a required field.', 'group' => 'Form API', ); } /** * Check several empty values for required forms elements. * * If the form field is found in form_get_errors() then the test pass. */ function testRequiredFields() { // Originates from http://drupal.org/node/117748 // Sets of empty strings and arrays $empty_strings = array('""' => "", '"\n"' => "\n", '" "' => " ", '"\t"' => "\t", '" \n\t "' => " \n\t ", '"\n\n\n\n\n"' => "\n\n\n\n\n"); $empty_arrays = array('array()' => array()); $elements['textfield']['element'] = array('#title' => $this->randomName(), '#type' => 'textfield', '#required' => TRUE); $elements['textfield']['empty_values'] = $empty_strings; $elements['password']['element'] = array('#title' => $this->randomName(), '#type' => 'password', '#required' => TRUE); $elements['password']['empty_values'] = $empty_strings; $elements['password_confirm']['element'] = array('#title' => $this->randomName(), '#type' => 'password_confirm', '#required' => TRUE); $elements['password_confirm']['empty_values'] = $empty_strings; $elements['textarea']['element'] = array('#title' => $this->randomName(), '#type' => 'textarea', '#required' => TRUE); $elements['textarea']['empty_values'] = $empty_strings; $elements['radios']['element'] = array('#title' => $this->randomName(), '#type' => 'radios', '#required' => TRUE, '#options' => array($this->randomName(), $this->randomName(), $this->randomName())); $elements['radios']['empty_values'] = $empty_arrays; $elements['checkboxes']['element'] = array('#title' => $this->randomName(), '#type' => 'checkboxes', '#required' => TRUE, '#options' => array($this->randomName(), $this->randomName(), $this->randomName())); $elements['checkboxes']['empty_values'] = $empty_arrays; $elements['select']['element'] = array('#title' => $this->randomName(), '#type' => 'select', '#required' => TRUE, '#options' => array($this->randomName(), $this->randomName(), $this->randomName())); $elements['select']['empty_values'] = $empty_strings; $elements['file']['element'] = array('#title' => $this->randomName(), '#type' => 'file', '#required' => TRUE); $elements['file']['empty_values'] = $empty_strings; // Go through all the elements and all the empty values for them foreach ($elements as $type => $data) { foreach ($data['empty_values'] as $key => $empty) { $form_id = $this->randomName(); $form = $form_state = array(); $form['op'] = array('#type' => 'submit', '#value' => t('Submit')); $element = $data['element']['#title']; $form[$element] = $data['element']; $form_state['values'][$element] = $empty; $form_state['input'] = $form_state['values']; $form_state['input']['form_id'] = $form_id; $form_state['method'] = 'post'; drupal_prepare_form($form_id, $form, $form_state); drupal_process_form($form_id, $form, $form_state); $errors = form_get_errors(); $this->assertTrue(isset($errors[$element]), "Check empty($key) '$type' field '$element'"); } } // Clear the expected form error messages so they don't appear as exceptions. drupal_get_messages(); } } /** * Test form type functions for expected behavior. */ class FormsTestTypeCase extends DrupalUnitTestCase { public static function getInfo() { return array( 'name' => 'Form type-specific tests', 'description' => 'Test form type functions for expected behavior.', 'group' => 'Form API', ); } /** * Test form_type_checkbox_value() function for expected behavior. */ function testFormCheckboxValue() { $form['#return_value'] = $return_value = $this->randomName(); $form['#default_value'] = $default_value = $this->randomName(); // Element is disabled , and $edit is not empty. $form['#disabled'] = TRUE; $edit = array(1); $this->assertEqual(form_type_checkbox_value($form, $edit), $default_value, t('form_type_checkbox_value() returns the default value when #disabled is set.')); // Element is not disabled, $edit is not empty. unset($form['#disabled']); $this->assertEqual(form_type_checkbox_value($form, $edit), $return_value, t('form_type_checkbox_value() returns the return value when #disabled is not set.')); // Element is not disabled, $edit is empty. $edit = array(); $this->assertIdentical(form_type_checkbox_value($form, $edit), 0, t('form_type_checkbox_value() returns 0 when #disabled is not set, and $edit is empty.')); // $edit is FALSE. $edit = FALSE; $this->assertNull(form_type_checkbox_value($form, $edit), t('form_type_checkbox_value() returns NULL when $edit is FALSE')); } } /** * Test the tableselect form element for expected behavior. */ class FormsElementsTableSelectFunctionalTest extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'Tableselect form element type test', 'description' => 'Test the tableselect element for expected behavior', 'group' => 'Form API', ); } function setUp() { parent::setUp('form_test'); } /** * Test the display of checkboxes when #multiple is TRUE. */ function testMultipleTrue() { $this->drupalGet('form_test/tableselect/multiple-true'); $this->assertNoText(t('Empty text.'), t('Empty text should not be displayed.')); // Test for the presence of the Select all rows tableheader. $this->assertFieldByXPath('//th[@class="select-all"]', NULL, t('Presence of the "Select all" checkbox.')); $rows = array('row1', 'row2', 'row3'); foreach ($rows as $row) { $this->assertFieldByXPath('//input[@type="checkbox"]', $row, t('Checkbox for value @row.', array('@row' => $row))); } } /** * Test the display of radios when #multiple is FALSE. */ function testMultipleFalse() { $this->drupalGet('form_test/tableselect/multiple-false'); $this->assertNoText(t('Empty text.'), t('Empty text should not be displayed.')); // Test for the absence of the Select all rows tableheader. $this->assertNoFieldByXPath('//th[@class="select-all"]', '', t('Absence of the "Select all" checkbox.')); $rows = array('row1', 'row2', 'row3'); foreach ($rows as $row) { $this->assertFieldByXPath('//input[@type="radio"]', $row, t('Radio button for value @row.', array('@row' => $row))); } } /** * Test the display of the #empty text when #options is an empty array. */ function testEmptyText() { $this->drupalGet('form_test/tableselect/empty-text'); $this->assertText(t('Empty text.'), t('Empty text should be displayed.')); } /** * Test the submission of single and multiple values when #multiple is TRUE. */ function testMultipleTrueSubmit() { // Test a submission with one checkbox checked. $edit = array(); $edit['tableselect[row1]'] = TRUE; $this->drupalPost('form_test/tableselect/multiple-true', $edit, 'Submit'); $this->assertText(t('Submitted: row1 = row1'), t('Checked checkbox row1')); $this->assertText(t('Submitted: row2 = 0'), t('Unchecked checkbox row2.')); $this->assertText(t('Submitted: row3 = 0'), t('Unchecked checkbox row3.')); // Test a submission with multiple checkboxes checked. $edit['tableselect[row1]'] = TRUE; $edit['tableselect[row3]'] = TRUE; $this->drupalPost('form_test/tableselect/multiple-true', $edit, 'Submit'); $this->assertText(t('Submitted: row1 = row1'), t('Checked checkbox row1.')); $this->assertText(t('Submitted: row2 = 0'), t('Unchecked checkbox row2.')); $this->assertText(t('Submitted: row3 = row3'), t('Checked checkbox row3.')); } /** * Test submission of values when #multiple is FALSE. */ function testMultipleFalseSubmit() { $edit['tableselect'] = 'row1'; $this->drupalPost('form_test/tableselect/multiple-false', $edit, 'Submit'); $this->assertText(t('Submitted: row1'), t('Selected radio button')); } /** * Test the #js_select property. */ function testAdvancedSelect() { // When #multiple = TRUE a Select all checkbox should be displayed by default. $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-default'); $this->assertFieldByXPath('//th[@class="select-all"]', NULL, t('Display a "Select all" checkbox by default when #multiple is TRUE.')); // When #js_select is set to FALSE, a "Select all" checkbox should not be displayed. $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-no-advanced-select'); $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, t('Do not display a "Select all" checkbox when #js_select is FALSE.')); // A "Select all" checkbox never makes sense when #multiple = FALSE, regardless of the value of #js_select. $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-default'); $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, t('Do not display a "Select all" checkbox when #multiple is FALSE.')); $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-advanced-select'); $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, t('Do not display a "Select all" checkbox when #multiple is FALSE, even when #js_select is TRUE.')); } /** * Test the whether the option checker gives an error on invalid tableselect values for checkboxes. */ function testMultipleTrueOptionchecker() { list($header, $options) = _form_test_tableselect_get_data(); $form['tableselect'] = array( '#type' => 'tableselect', '#header' => $header, '#options' => $options, ); // Test with a valid value. list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'row1')); $this->assertFalse(isset($errors['tableselect']), t('Option checker allows valid values for checkboxes.')); // Test with an invalid value. list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'non_existing_value')); $this->assertTrue(isset($errors['tableselect']), t('Option checker disallows invalid values for checkboxes.')); } /** * Test the whether the option checker gives an error on invalid tableselect values for radios. */ function testMultipleFalseOptionchecker() { list($header, $options) = _form_test_tableselect_get_data(); $form['tableselect'] = array( '#type' => 'tableselect', '#header' => $header, '#options' => $options, '#multiple' => FALSE, ); // Test with a valid value. list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'row1')); $this->assertFalse(isset($errors['tableselect']), t('Option checker allows valid values for radio buttons.')); // Test with an invalid value. list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'non_existing_value')); $this->assertTrue(isset($errors['tableselect']), t('Option checker disallows invalid values for radio buttons.')); } /** * Helper function for the option check test to submit a form while collecting errors. * * @param $form_element * A form element to test. * @param $edit * An array containing post data. * * @return * An array containing the processed form, the form_state and any errors. */ private function formSubmitHelper($form_element, $edit) { $form_id = $this->randomName(); $form_state = form_state_defaults(); $form = array(); $form = array_merge($form, $form_element); $form['op'] = array('#type' => 'submit', '#value' => t('Submit')); $form_state['input'] = $edit; $form_state['input']['form_id'] = $form_id; drupal_prepare_form($form_id, $form, $form_state); drupal_process_form($form_id, $form, $form_state); $errors = form_get_errors(); // Clear errors and messages. drupal_get_messages(); form_clear_error(); // Return the processed form together with form_state and errors // to allow the caller lowlevel access to the form. return array($form, $form_state, $errors); } } /** * Test the form_clean_id() for expected behavior. */ class FormsFormCleanIdFunctionalTest extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'form_clean_id() test', 'description' => 'Test the function form_clean_id() for expected behavior', 'group' => 'Form API', ); } function setUp() { parent::setUp('form_test'); } /** * Test the uniqueness of the form_clean_id() function. */ function testFormCleanId() { $this->drupalGet('form_test/form_clean_id'); $this->assertNoUniqueText('form-test-form-clean-id-presence'); $this->assertUniqueText('form-test-form-clean-id-presence-1'); $this->assertUniqueText('form-test-form-clean-id-presence-2'); $this->assertNoUniqueText('Test Textfield'); } } /** * Test using drupal_form_submit in a batch. */ class FormAPITestCase extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'Drupal Execute and Batch API', 'description' => 'Tests the compatibility of drupal_form_submit and the Batch API', 'group' => 'Form API', ); } /** * Check that we can run drupal_form_submit during a batch. */ function testDrupalFormSubmitInBatch() { // Our test is going to modify the following variable. variable_set('form_test_mock_submit', 'initial_state'); // This is a page that sets a batch, which calls drupal_form_submit, which // modifies the variable we set up above. $this->drupalGet('form_test/drupal_form_submit_batch_api'); // If the drupal_form_submit call executed correctly our test variable will be // set to 'form_submitted'. $this->assertEqual('form_submitted', variable_get('form_test_mock_submit', 'initial_state'), t('Check drupal_form_submit called submit handlers when running in a batch')); // Clean our variable up. variable_del('form_test_mock_submit'); } function setUp() { parent::setUp('form_test'); } } /** * Test the form storage on a multistep form. * * The tested form puts data into the storage during the initial form * construction. These tests verify that there are no duplicate form * constructions, with and without manual form caching activiated. Furthermore * when a validation error occurs, it makes sure that changed form element * values aren't lost due to a wrong form rebuild. */ class FormsFormStorageTestCase extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'Multistep form using form storage', 'description' => 'Tests a multistep form using form storage and makes sure validation and caching works right.', 'group' => 'Form API', ); } function setUp() { parent::setUp('form_test'); } /** * Tests using the form in a usual way. */ function testForm() { $user = $this->drupalCreateUser(array('access content')); $this->drupalLogin($user); $this->drupalPost('form_test/form-storage', array('title' => 'new', 'value' => 'value_is_set'), 'Continue'); $this->assertText('Form constructions: 2', t('The form has been constructed two times till now.')); $this->drupalPost(NULL, array(), 'Save'); $this->assertText('Form constructions: 3', t('The form has been constructed three times till now.')); $this->assertText('Title: new', t('The form storage has stored the values.')); } /** * Tests using the form with an activated #cache property. */ function testFormCached() { $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->assertText('Form constructions: 1', t('The form has been constructed one time till now.')); $this->drupalPost(NULL, array(), 'Save', array('query' => 'cache=1')); $this->assertText('Form constructions: 2', t('The form has been constructed two times till now.')); $this->assertText('Title: new', t('The form storage has stored the values.')); } /** * Tests validation when form storage is used. */ function testValidation() { $user = $this->drupalCreateUser(array('access content')); $this->drupalLogin($user); $this->drupalPost('form_test/form-storage', array('title' => '', 'value' => 'value_is_set'), 'Continue'); $this->assertPattern('/value_is_set/', t("The input values have been kept.")); } }