452 lines
17 KiB
Plaintext
452 lines
17 KiB
Plaintext
<?php
|
|
// $Id$
|
|
|
|
/**
|
|
* @file
|
|
* Unit tests for the Drupal Form API.
|
|
*/
|
|
|
|
class FormsTestCase extends DrupalWebTestCase {
|
|
|
|
public static function getInfo() {
|
|
return array(
|
|
'name' => '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."));
|
|
}
|
|
}
|