list.test

Tests for list.module.

File

modules/field/modules/list/tests/list.test

View source
<?php


/**
 * @file
 * Tests for list.module.
 */

/**
 * Tests for the 'List' field types.
 */
class ListFieldTestCase extends FieldTestCase {
    protected $field;
    protected $instance;
    protected $field_name;
    public static function getInfo() {
        return array(
            'name' => 'List field',
            'description' => 'Test the List field type.',
            'group' => 'Field types',
        );
    }
    function setUp() {
        parent::setUp('field_test');
        $this->field_name = 'test_list';
        $this->field = array(
            'field_name' => $this->field_name,
            'type' => 'list_integer',
            'cardinality' => 1,
            'settings' => array(
                'allowed_values' => array(
                    1 => 'One',
                    2 => 'Two',
                    3 => 'Three',
                ),
            ),
        );
        $this->field = field_create_field($this->field);
        $this->instance = array(
            'field_name' => $this->field_name,
            'entity_type' => 'test_entity',
            'bundle' => 'test_bundle',
            'widget' => array(
                'type' => 'options_buttons',
            ),
        );
        $this->instance = field_create_instance($this->instance);
    }
    
    /**
     * Test that allowed values can be updated.
     */
    function testUpdateAllowedValues() {
        $langcode = LANGUAGE_NONE;
        // All three options appear.
        $entity = field_test_create_stub_entity();
        $form = drupal_get_form('field_test_entity_form', $entity);
        $this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][3]), 'Option 3 exists');
        // Use one of the values in an actual entity, and check that this value
        // cannot be removed from the list.
        $entity = field_test_create_stub_entity();
        $entity->{$this->field_name}[$langcode][0] = array(
            'value' => 1,
        );
        field_test_entity_save($entity);
        $this->field['settings']['allowed_values'] = array(
            2 => 'Two',
        );
        try {
            field_update_field($this->field);
            $this->fail(t('Cannot update a list field to not include keys with existing data.'));
        } catch (FieldException $e) {
            $this->pass(t('Cannot update a list field to not include keys with existing data.'));
        }
        // Empty the value, so that we can actually remove the option.
        $entity->{$this->field_name}[$langcode] = array();
        field_test_entity_save($entity);
        // Removed options do not appear.
        $this->field['settings']['allowed_values'] = array(
            2 => 'Two',
        );
        field_update_field($this->field);
        $entity = field_test_create_stub_entity();
        $form = drupal_get_form('field_test_entity_form', $entity);
        $this->assertTrue(empty($form[$this->field_name][$langcode][1]), 'Option 1 does not exist');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
        $this->assertTrue(empty($form[$this->field_name][$langcode][3]), 'Option 3 does not exist');
        // Completely new options appear.
        $this->field['settings']['allowed_values'] = array(
            10 => 'Update',
            20 => 'Twenty',
        );
        field_update_field($this->field);
        $form = drupal_get_form('field_test_entity_form', $entity);
        $this->assertTrue(empty($form[$this->field_name][$langcode][1]), 'Option 1 does not exist');
        $this->assertTrue(empty($form[$this->field_name][$langcode][2]), 'Option 2 does not exist');
        $this->assertTrue(empty($form[$this->field_name][$langcode][3]), 'Option 3 does not exist');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][10]), 'Option 10 exists');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][20]), 'Option 20 exists');
        // Options are reset when a new field with the same name is created.
        field_delete_field($this->field_name);
        unset($this->field['id']);
        $this->field['settings']['allowed_values'] = array(
            1 => 'One',
            2 => 'Two',
            3 => 'Three',
        );
        $this->field = field_create_field($this->field);
        $this->instance = array(
            'field_name' => $this->field_name,
            'entity_type' => 'test_entity',
            'bundle' => 'test_bundle',
            'widget' => array(
                'type' => 'options_buttons',
            ),
        );
        $this->instance = field_create_instance($this->instance);
        $entity = field_test_create_stub_entity();
        $form = drupal_get_form('field_test_entity_form', $entity);
        $this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), 'Option 2 exists');
        $this->assertTrue(!empty($form[$this->field_name][$langcode][3]), 'Option 3 exists');
    }

}

/**
 * Sets up a List field for testing allowed values functions.
 */
class ListDynamicValuesTestCase extends FieldTestCase {
    protected $field;
    protected $field_name;
    protected $instance;
    protected $test;
    protected $entity;
    function setUp() {
        parent::setUp(array(
            'list',
            'field_test',
            'list_test',
        ));
        $this->field_name = 'test_list';
        $this->field = array(
            'field_name' => $this->field_name,
            'type' => 'list_text',
            'cardinality' => 1,
            'settings' => array(
                'allowed_values_function' => 'list_test_dynamic_values_callback',
            ),
        );
        $this->field = field_create_field($this->field);
        $this->instance = array(
            'field_name' => $this->field_name,
            'entity_type' => 'test_entity',
            'bundle' => 'test_bundle',
            'required' => TRUE,
            'widget' => array(
                'type' => 'options_select',
            ),
        );
        $this->instance = field_create_instance($this->instance);
        $this->test = array(
            'id' => mt_rand(1, 10),
            // Make sure this does not equal the ID so that
            // list_test_dynamic_values_callback() always returns 4 values.
'vid' => mt_rand(20, 30),
            'bundle' => 'test_bundle',
            'label' => $this->randomName(),
        );
        $this->entity = call_user_func_array('field_test_create_stub_entity', $this->test);
    }

}

/**
 * Tests the List field allowed values function.
 */
class ListDynamicValuesValidationTestCase extends ListDynamicValuesTestCase {
    public static function getInfo() {
        return array(
            'name' => 'List field dynamic values',
            'description' => 'Test the List field allowed values function.',
            'group' => 'Field types',
        );
    }
    
    /**
     * Test that allowed values function gets the entity.
     */
    function testDynamicAllowedValues() {
        // Verify that the test passes against every value we had.
        foreach ($this->test as $key => $value) {
            $this->entity->test_list[LANGUAGE_NONE][0]['value'] = $value;
            try {
                field_attach_validate('test_entity', $this->entity);
                $this->pass("{$key} should pass");
            } catch (FieldValidationException $e) {
                // This will display as an exception, no need for a separate error.
                throw $e;
            }
        }
        // Now verify that the test does not pass against anything else.
        foreach ($this->test as $key => $value) {
            $this->entity->test_list[LANGUAGE_NONE][0]['value'] = is_numeric($value) ? 100 - $value : 'X' . $value;
            $pass = FALSE;
            try {
                field_attach_validate('test_entity', $this->entity);
            } catch (FieldValidationException $e) {
                $pass = TRUE;
            }
            $this->assertTrue($pass, $key . ' should not pass');
        }
    }

}

/**
 * List module UI tests.
 */
class ListFieldUITestCase extends FieldTestCase {
    protected $type;
    protected $hyphen_type;
    protected $field_name;
    protected $admin_path;
    public static function getInfo() {
        return array(
            'name' => 'List field UI',
            'description' => 'Test the List field UI functionality.',
            'group' => 'Field types',
        );
    }
    function setUp() {
        parent::setUp('field_test', 'field_ui');
        // Create test user.
        $admin_user = $this->drupalCreateUser(array(
            'access content',
            'administer content types',
            'administer taxonomy',
            'administer fields',
        ));
        $this->drupalLogin($admin_user);
        // Create content type, with underscores.
        $type_name = 'test_' . strtolower($this->randomName());
        $type = $this->drupalCreateContentType(array(
            'name' => $type_name,
            'type' => $type_name,
        ));
        $this->type = $type->type;
        // Store a valid URL name, with hyphens instead of underscores.
        $this->hyphen_type = str_replace('_', '-', $this->type);
    }
    
    /**
     * List (integer) : test 'allowed values' input.
     */
    function testListAllowedValuesInteger() {
        $this->field_name = 'field_list_integer';
        $this->createListField('list_integer');
        // Flat list of textual values.
        $string = "Zero\nOne";
        $array = array(
            '0' => 'Zero',
            '1' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
        // Explicit integer keys.
        $string = "0|Zero\n2|Two";
        $array = array(
            '0' => 'Zero',
            '2' => 'Two',
        );
        $this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.');
        // Check that values can be added and removed.
        $string = "0|Zero\n1|One";
        $array = array(
            '0' => 'Zero',
            '1' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
        // Non-integer keys.
        $this->assertAllowedValuesInput("1.1|One", 'keys must be integers', 'Non integer keys are rejected.');
        $this->assertAllowedValuesInput("abc|abc", 'keys must be integers', 'Non integer keys are rejected.');
        // Mixed list of keyed and unkeyed values.
        $this->assertAllowedValuesInput("Zero\n1|One", 'invalid input', 'Mixed lists are rejected.');
        // Create a node with actual data for the field.
        $settings = array(
            'type' => $this->type,
            $this->field_name => array(
                LANGUAGE_NONE => array(
                    array(
                        'value' => 1,
                    ),
                ),
            ),
        );
        $node = $this->drupalCreateNode($settings);
        // Check that a flat list of values is rejected once the field has data.
        $this->assertAllowedValuesInput("Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.');
        // Check that values can be added but values in use cannot be removed.
        $string = "0|Zero\n1|One\n2|Two";
        $array = array(
            '0' => 'Zero',
            '1' => 'One',
            '2' => 'Two',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values can be added.');
        $string = "0|Zero\n1|One";
        $array = array(
            '0' => 'Zero',
            '1' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
        $this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
        // Delete the node, remove the value.
        node_delete($node->nid);
        $string = "0|Zero";
        $array = array(
            '0' => 'Zero',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
    }
    
    /**
     * List (float) : test 'allowed values' input.
     */
    function testListAllowedValuesFloat() {
        $this->field_name = 'field_list_float';
        $this->createListField('list_float');
        // Flat list of textual values.
        $string = "Zero\nOne";
        $array = array(
            '0' => 'Zero',
            '1' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
        // Explicit numeric keys.
        $string = "0|Zero\n.5|Point five";
        $array = array(
            '0' => 'Zero',
            '0.5' => 'Point five',
        );
        $this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.');
        // Check that values can be added and removed.
        $string = "0|Zero\n.5|Point five\n1.0|One";
        $array = array(
            '0' => 'Zero',
            '0.5' => 'Point five',
            '1' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
        // Non-numeric keys.
        $this->assertAllowedValuesInput("abc|abc\n", 'each key must be a valid integer or decimal', 'Non numeric keys are rejected.');
        // Mixed list of keyed and unkeyed values.
        $this->assertAllowedValuesInput("Zero\n1|One\n", 'invalid input', 'Mixed lists are rejected.');
        // Create a node with actual data for the field.
        $settings = array(
            'type' => $this->type,
            $this->field_name => array(
                LANGUAGE_NONE => array(
                    array(
                        'value' => 0.5,
                    ),
                ),
            ),
        );
        $node = $this->drupalCreateNode($settings);
        // Check that a flat list of values is rejected once the field has data.
        $this->assertAllowedValuesInput("Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.');
        // Check that values can be added but values in use cannot be removed.
        $string = "0|Zero\n.5|Point five\n2|Two";
        $array = array(
            '0' => 'Zero',
            '0.5' => 'Point five',
            '2' => 'Two',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values can be added.');
        $string = "0|Zero\n.5|Point five";
        $array = array(
            '0' => 'Zero',
            '0.5' => 'Point five',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
        $this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
        // Delete the node, remove the value.
        node_delete($node->nid);
        $string = "0|Zero";
        $array = array(
            '0' => 'Zero',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
    }
    
    /**
     * List (text) : test 'allowed values' input.
     */
    function testListAllowedValuesText() {
        $this->field_name = 'field_list_text';
        $this->createListField('list_text');
        // Flat list of textual values.
        $string = "Zero\nOne";
        $array = array(
            'Zero' => 'Zero',
            'One' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
        // Explicit keys.
        $string = "zero|Zero\none|One";
        $array = array(
            'zero' => 'Zero',
            'one' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Explicit keys are accepted.');
        // Check that values can be added and removed.
        $string = "zero|Zero\ntwo|Two";
        $array = array(
            'zero' => 'Zero',
            'two' => 'Two',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
        // Mixed list of keyed and unkeyed values.
        $string = "zero|Zero\nOne\n";
        $array = array(
            'zero' => 'Zero',
            'One' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Mixed lists are accepted.');
        // Overly long keys.
        $this->assertAllowedValuesInput("zero|Zero\n" . $this->randomName(256) . "|One", 'each key must be a string at most 255 characters long', 'Overly long keys are rejected.');
        // Create a node with actual data for the field.
        $settings = array(
            'type' => $this->type,
            $this->field_name => array(
                LANGUAGE_NONE => array(
                    array(
                        'value' => 'One',
                    ),
                ),
            ),
        );
        $node = $this->drupalCreateNode($settings);
        // Check that flat lists of values are still accepted once the field has
        // data.
        $string = "Zero\nOne";
        $array = array(
            'Zero' => 'Zero',
            'One' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are still accepted once the field has data.');
        // Check that values can be added but values in use cannot be removed.
        $string = "Zero\nOne\nTwo";
        $array = array(
            'Zero' => 'Zero',
            'One' => 'One',
            'Two' => 'Two',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values can be added.');
        $string = "Zero\nOne";
        $array = array(
            'Zero' => 'Zero',
            'One' => 'One',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
        $this->assertAllowedValuesInput("Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
        // Delete the node, remove the value.
        node_delete($node->nid);
        $string = "Zero";
        $array = array(
            'Zero' => 'Zero',
        );
        $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
    }
    
    /**
     * List (boolen) : test 'On/Off' values input.
     */
    function testListAllowedValuesBoolean() {
        $this->field_name = 'field_list_boolean';
        $this->createListField('list_boolean');
        // Check that the separate 'On' and 'Off' form fields work.
        $on = $this->randomName();
        $off = $this->randomName();
        $allowed_values = array(
            1 => $on,
            0 => $off,
        );
        $edit = array(
            'on' => $on,
            'off' => $off,
        );
        $this->drupalPost($this->admin_path, $edit, t('Save settings'));
        $this->assertText("Saved field_list_boolean configuration.", "The 'On' and 'Off' form fields work for boolean fields.");
        // Test the allowed_values on the field settings form.
        $this->drupalGet($this->admin_path);
        $this->assertFieldByName('on', $on, "The 'On' value is stored correctly.");
        $this->assertFieldByName('off', $off, "The 'Off' value is stored correctly.");
        $field = field_info_field($this->field_name);
        $this->assertEqual($field['settings']['allowed_values'], $allowed_values, 'The allowed value is correct');
        $this->assertFalse(isset($field['settings']['on']), 'The on value is not saved into settings');
        $this->assertFalse(isset($field['settings']['off']), 'The off value is not saved into settings');
    }
    
    /**
     * List (text) : test 'allowed values function' input.
     */
    function testDynamicListAllowedValuesText() {
        $this->field_name = 'field_list_text';
        $this->createListField('list_text', array(
            'allowed_values_function' => 'list_test_dynamic_values_callback',
            'allowed_values' => '',
        ));
        $this->drupalGet($this->admin_path);
    }
    
    /**
     * Helper function to create list field of a given type.
     *
     * @param string $type
     *   'list_integer', 'list_float', 'list_text' or 'list_boolean'
     * @param array $settings
     *
     * @throws \FieldException
     */
    protected function createListField($type, $settings = array()) {
        // Create a test field and instance.
        $field = array(
            'field_name' => $this->field_name,
            'type' => $type,
        );
        if (!empty($settings)) {
            $field['settings'] = $settings;
        }
        field_create_field($field);
        $instance = array(
            'field_name' => $this->field_name,
            'entity_type' => 'node',
            'bundle' => $this->type,
        );
        field_create_instance($instance);
        $this->admin_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $this->field_name;
    }
    
    /**
     * Tests a string input for the 'allowed values' form element.
     *
     * @param $input_string
     *   The input string, in the pipe-linefeed format expected by the form
     *   element.
     * @param $result
     *   Either an expected resulting array in
     *   $field['settings']['allowed_values'], or an expected error message.
     * @param $message
     *   Message to display.
     */
    function assertAllowedValuesInput($input_string, $result, $message) {
        $edit = array(
            'field[settings][allowed_values]' => $input_string,
        );
        $this->drupalPost($this->admin_path, $edit, t('Save settings'));
        if (is_string($result)) {
            $this->assertText($result, $message);
        }
        else {
            field_info_cache_clear();
            $field = field_info_field($this->field_name);
            $this->assertIdentical($field['settings']['allowed_values'], $result, $message);
        }
    }

}

Classes

Title Deprecated Summary
ListDynamicValuesTestCase Sets up a List field for testing allowed values functions.
ListDynamicValuesValidationTestCase Tests the List field allowed values function.
ListFieldTestCase Tests for the 'List' field types.
ListFieldUITestCase List module UI tests.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.