<?php
// $Id$

/**
 * @file
 * Tests for the 'List' field types.
 */

/**
 * Tests for the 'List' field types.
 */
class ListFieldTestCase extends FieldTestCase {
  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',
      'cardinality' => 1,
      'settings' => array(
        'allowed_values' => "1|One\n2|Two\n3|Three\n",
      ),
    );
    $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]), t('Option 1 exists'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), t('Option 2 exists'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][3]), t('Option 3 exists'));

    // Removed options do not appear.
    $this->field['settings']['allowed_values'] = "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]), t('Option 1 does not exist'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), t('Option 2 exists'));
    $this->assertTrue(empty($form[$this->field_name][$langcode][3]), t('Option 3 does not exist'));

    // Completely new options appear.
    $this->field['settings']['allowed_values'] = "10|Update\n20|Twenty";
    field_update_field($this->field);
    $form = drupal_get_form('field_test_entity_form', $entity);
    $this->assertTrue(empty($form[$this->field_name][$langcode][1]), t('Option 1 does not exist'));
    $this->assertTrue(empty($form[$this->field_name][$langcode][2]), t('Option 2 does not exist'));
    $this->assertTrue(empty($form[$this->field_name][$langcode][3]), t('Option 3 does not exist'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][10]), t('Option 10 exists'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][20]), t('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'] = "1|One\n2|Two\n3|Three\n";
    $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]), t('Option 1 exists'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][2]), t('Option 2 exists'));
    $this->assertTrue(!empty($form[$this->field_name][$langcode][3]), t('Option 3 exists'));
  }
}

/**
* List module UI tests.
*/
class ListFieldUITestCase extends FieldTestCase {
  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'));
    $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);

    // Create random field name.
    $this->field_label = $this->randomString();
    $this->field_name = strtolower($this->randomName());
  }

  /**
   * Tests that allowed values are properly validated in the UI.
   */
  function testAllowedValues() {
    $element_name = "field[settings][allowed_values]";

    //Test 'List' field type.
    $admin_path = $this->createListFieldAndEdit('list');
    //Check that non-integer keys are rejected.
    $edit = array($element_name => "1.1|one\n");
    $this->drupalPost($admin_path, $edit, t('Save settings'));
    $this->assertText("keys must be integers", t('Form validation failed.'));

    // Test 'List (number)' field type.
    $admin_path = $this->createListFieldAndEdit('list_number');
    //Check that non-numeric keys are rejected.
    $edit = array($element_name => "1|one\nB|two");
    $this->drupalPost($admin_path, $edit, t('Save settings'));
    $this->assertText("each key must be a valid integer or decimal", t('Form validation failed.'));

    //Test 'List (text)' field type.
    $admin_path = $this->createListFieldAndEdit('list_text');
    //Check that over long keys are rejected.
    $edit = array($element_name => "1|one\n" . $this->randomName(256) . "|two");
    $this->drupalPost($admin_path, $edit, t('Save settings'));
    $this->assertText("each key must be a string at most 255 characters long", t('Form validation failed.'));
  }

  /**
   * Helper function to create list field of a given type and get the edit page.
   *
   * @param string $type
   *   'list', 'list_boolean', 'list_number', or 'list_text'
   */
  private function createListFieldAndEdit($type) {
    // Create a test field and instance.
    $field_name = 'test_' . $type;
    $field = array(
      'field_name' => $field_name,
      'type' => $type,
    );
    field_create_field($field);
    $instance = array(
      'field_name' => $field_name,
      'entity_type' => 'node',
      'bundle' => $this->type,
    );
    field_create_instance($instance);

    $admin_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $field_name;
    return $admin_path;
  }

}

