cms/drupal/modules/field_ui/field_ui.test
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * Tests for field_ui.module.
       
     6  */
       
     7 
       
     8 /**
       
     9  * Provides common functionality for the Field UI test classes.
       
    10  */
       
    11 class FieldUITestCase extends DrupalWebTestCase {
       
    12 
       
    13   function setUp() {
       
    14     // Since this is a base class for many test cases, support the same
       
    15     // flexibility that DrupalWebTestCase::setUp() has for the modules to be
       
    16     // passed in as either an array or a variable number of string arguments.
       
    17     $modules = func_get_args();
       
    18     if (isset($modules[0]) && is_array($modules[0])) {
       
    19       $modules = $modules[0];
       
    20     }
       
    21     $modules[] = 'field_test';
       
    22     parent::setUp($modules);
       
    23 
       
    24     // Create test user.
       
    25     $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
       
    26     $this->drupalLogin($admin_user);
       
    27 
       
    28     // Create content type, with underscores.
       
    29     $type_name = strtolower($this->randomName(8)) . '_test';
       
    30     $type = $this->drupalCreateContentType(array('name' => $type_name, 'type' => $type_name));
       
    31     $this->type = $type->type;
       
    32     // Store a valid URL name, with hyphens instead of underscores.
       
    33     $this->hyphen_type = str_replace('_', '-', $this->type);
       
    34   }
       
    35 
       
    36   /**
       
    37    * Creates a new field through the Field UI.
       
    38    *
       
    39    * @param $bundle_path
       
    40    *   Admin path of the bundle that the new field is to be attached to.
       
    41    * @param $initial_edit
       
    42    *   $edit parameter for drupalPost() on the first step ('Manage fields'
       
    43    *   screen).
       
    44    * @param $field_edit
       
    45    *   $edit parameter for drupalPost() on the second step ('Field settings'
       
    46    *   form).
       
    47    * @param $instance_edit
       
    48    *   $edit parameter for drupalPost() on the third step ('Instance settings'
       
    49    *   form).
       
    50    */
       
    51   function fieldUIAddNewField($bundle_path, $initial_edit, $field_edit = array(), $instance_edit = array()) {
       
    52     // Use 'test_field' field type by default.
       
    53     $initial_edit += array(
       
    54       'fields[_add_new_field][type]' => 'test_field',
       
    55       'fields[_add_new_field][widget_type]' => 'test_field_widget',
       
    56     );
       
    57     $label = $initial_edit['fields[_add_new_field][label]'];
       
    58     $field_name = $initial_edit['fields[_add_new_field][field_name]'];
       
    59 
       
    60     // First step : 'Add new field' on the 'Manage fields' page.
       
    61     $this->drupalPost("$bundle_path/fields",  $initial_edit, t('Save'));
       
    62     $this->assertRaw(t('These settings apply to the %label field everywhere it is used.', array('%label' => $label)), 'Field settings page was displayed.');
       
    63 
       
    64     // Second step : 'Field settings' form.
       
    65     $this->drupalPost(NULL, $field_edit, t('Save field settings'));
       
    66     $this->assertRaw(t('Updated field %label field settings.', array('%label' => $label)), 'Redirected to instance and widget settings page.');
       
    67 
       
    68     // Third step : 'Instance settings' form.
       
    69     $this->drupalPost(NULL, $instance_edit, t('Save settings'));
       
    70     $this->assertRaw(t('Saved %label configuration.', array('%label' => $label)), 'Redirected to "Manage fields" page.');
       
    71 
       
    72     // Check that the field appears in the overview form.
       
    73     $this->assertFieldByXPath('//table[@id="field-overview"]//td[1]', $label, 'Field was created and appears in the overview page.');
       
    74   }
       
    75 
       
    76   /**
       
    77    * Adds an existing field through the Field UI.
       
    78    *
       
    79    * @param $bundle_path
       
    80    *   Admin path of the bundle that the field is to be attached to.
       
    81    * @param $initial_edit
       
    82    *   $edit parameter for drupalPost() on the first step ('Manage fields'
       
    83    *   screen).
       
    84    * @param $instance_edit
       
    85    *   $edit parameter for drupalPost() on the second step ('Instance settings'
       
    86    *   form).
       
    87    */
       
    88   function fieldUIAddExistingField($bundle_path, $initial_edit, $instance_edit = array()) {
       
    89     // Use 'test_field_widget' by default.
       
    90     $initial_edit += array(
       
    91       'fields[_add_existing_field][widget_type]' => 'test_field_widget',
       
    92     );
       
    93     $label = $initial_edit['fields[_add_existing_field][label]'];
       
    94     $field_name = $initial_edit['fields[_add_existing_field][field_name]'];
       
    95 
       
    96     // First step : 'Add existing field' on the 'Manage fields' page.
       
    97     $this->drupalPost("$bundle_path/fields", $initial_edit, t('Save'));
       
    98 
       
    99     // Second step : 'Instance settings' form.
       
   100     $this->drupalPost(NULL, $instance_edit, t('Save settings'));
       
   101     $this->assertRaw(t('Saved %label configuration.', array('%label' => $label)), 'Redirected to "Manage fields" page.');
       
   102 
       
   103     // Check that the field appears in the overview form.
       
   104     $this->assertFieldByXPath('//table[@id="field-overview"]//td[1]', $label, 'Field was created and appears in the overview page.');
       
   105   }
       
   106 
       
   107   /**
       
   108    * Deletes a field instance through the Field UI.
       
   109    *
       
   110    * @param $bundle_path
       
   111    *   Admin path of the bundle that the field instance is to be deleted from.
       
   112    * @param $field_name
       
   113    *   The name of the field.
       
   114    * @param $label
       
   115    *   The label of the field.
       
   116    * @param $bundle_label
       
   117    *   The label of the bundle.
       
   118    */
       
   119   function fieldUIDeleteField($bundle_path, $field_name, $label, $bundle_label) {
       
   120     // Display confirmation form.
       
   121     $this->drupalGet("$bundle_path/fields/$field_name/delete");
       
   122     $this->assertRaw(t('Are you sure you want to delete the field %label', array('%label' => $label)), 'Delete confirmation was found.');
       
   123 
       
   124     // Submit confirmation form.
       
   125     $this->drupalPost(NULL, array(), t('Delete'));
       
   126     $this->assertRaw(t('The field %label has been deleted from the %type content type.', array('%label' => $label, '%type' => $bundle_label)), 'Delete message was found.');
       
   127 
       
   128     // Check that the field does not appear in the overview form.
       
   129     $this->assertNoFieldByXPath('//table[@id="field-overview"]//span[@class="label-field"]', $label, 'Field does not appear in the overview page.');
       
   130   }
       
   131 }
       
   132 
       
   133 /**
       
   134  * Tests the functionality of the 'Manage fields' screen.
       
   135  */
       
   136 class FieldUIManageFieldsTestCase extends FieldUITestCase {
       
   137   public static function getInfo() {
       
   138     return array(
       
   139       'name' => 'Manage fields',
       
   140       'description' => 'Test the Field UI "Manage fields" screen.',
       
   141       'group' => 'Field UI',
       
   142     );
       
   143   }
       
   144 
       
   145   function setUp() {
       
   146     parent::setUp();
       
   147 
       
   148     // Create random field name.
       
   149     $this->field_label = $this->randomName(8);
       
   150     $this->field_name_input =  strtolower($this->randomName(8));
       
   151     $this->field_name = 'field_'. $this->field_name_input;
       
   152   }
       
   153 
       
   154   /**
       
   155    * Runs the field CRUD tests.
       
   156    *
       
   157    * In order to act on the same fields, and not create the fields over and over
       
   158    * again the following tests create, update and delete the same fields.
       
   159    */
       
   160   function testCRUDFields() {
       
   161     $this->manageFieldsPage();
       
   162     $this->createField();
       
   163     $this->updateField();
       
   164     $this->addExistingField();
       
   165   }
       
   166 
       
   167   /**
       
   168    * Tests the manage fields page.
       
   169    */
       
   170   function manageFieldsPage() {
       
   171     $this->drupalGet('admin/structure/types/manage/' . $this->hyphen_type . '/fields');
       
   172     // Check all table columns.
       
   173     $table_headers = array(
       
   174       t('Label'),
       
   175       t('Machine name'),
       
   176       t('Field type'),
       
   177       t('Widget'),
       
   178       t('Operations'),
       
   179     );
       
   180     foreach ($table_headers as $table_header) {
       
   181       // We check that the label appear in the table headings.
       
   182       $this->assertRaw($table_header . '</th>', format_string('%table_header table header was found.', array('%table_header' => $table_header)));
       
   183     }
       
   184 
       
   185     // "Add new field" and "Add existing field" aren't a table heading so just
       
   186     // test the text.
       
   187     foreach (array('Add new field', 'Add existing field') as $element) {
       
   188       $this->assertText($element, format_string('"@element" was found.', array('@element' => $element)));
       
   189     }
       
   190   }
       
   191 
       
   192   /**
       
   193    * Tests adding a new field.
       
   194    *
       
   195    * @todo Assert properties can bet set in the form and read back in $field and
       
   196    * $instances.
       
   197    */
       
   198   function createField() {
       
   199     // Create a test field.
       
   200     $edit = array(
       
   201       'fields[_add_new_field][label]' => $this->field_label,
       
   202       'fields[_add_new_field][field_name]' => $this->field_name_input,
       
   203     );
       
   204     $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->hyphen_type, $edit);
       
   205 
       
   206     // Assert the field appears in the "add existing field" section for
       
   207     // different entity types; e.g. if a field was added in a node entity, it
       
   208     // should also appear in the 'taxonomy term' entity.
       
   209     $vocabulary = taxonomy_vocabulary_load(1);
       
   210     $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->machine_name . '/fields');
       
   211     $this->assertTrue($this->xpath('//select[@name="fields[_add_existing_field][field_name]"]//option[@value="' . $this->field_name . '"]'), 'Existing field was found in account settings.');
       
   212   }
       
   213 
       
   214   /**
       
   215    * Tests editing an existing field.
       
   216    */
       
   217   function updateField() {
       
   218     // Go to the field edit page.
       
   219     $this->drupalGet('admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $this->field_name);
       
   220 
       
   221     // Populate the field settings with new settings.
       
   222     $string = 'updated dummy test string';
       
   223     $edit = array(
       
   224       'field[settings][test_field_setting]' => $string,
       
   225       'instance[settings][test_instance_setting]' => $string,
       
   226       'instance[widget][settings][test_widget_setting]' => $string,
       
   227     );
       
   228     $this->drupalPost(NULL, $edit, t('Save settings'));
       
   229 
       
   230     // Assert the field settings are correct.
       
   231     $this->assertFieldSettings($this->type, $this->field_name, $string);
       
   232 
       
   233     // Assert redirection back to the "manage fields" page.
       
   234     $this->assertText(t('Saved @label configuration.', array('@label' => $this->field_label)), 'Redirected to "Manage fields" page.');
       
   235   }
       
   236 
       
   237   /**
       
   238    * Tests adding an existing field in another content type.
       
   239    */
       
   240   function addExistingField() {
       
   241     // Check "Add existing field" appears.
       
   242     $this->drupalGet('admin/structure/types/manage/page/fields');
       
   243     $this->assertRaw(t('Add existing field'), '"Add existing field" was found.');
       
   244 
       
   245     // Check that the list of options respects entity type restrictions on
       
   246     // fields. The 'comment' field is restricted to the 'comment' entity type
       
   247     // and should not appear in the list.
       
   248     $this->assertFalse($this->xpath('//select[@id="edit-add-existing-field-field-name"]//option[@value="comment"]'), 'The list of options respects entity type restrictions.');
       
   249 
       
   250     // Add a new field based on an existing field.
       
   251     $edit = array(
       
   252       'fields[_add_existing_field][label]' => $this->field_label . '_2',
       
   253       'fields[_add_existing_field][field_name]' => $this->field_name,
       
   254     );
       
   255     $this->fieldUIAddExistingField("admin/structure/types/manage/page", $edit);
       
   256   }
       
   257 
       
   258   /**
       
   259    * Asserts field settings are as expected.
       
   260    *
       
   261    * @param $bundle
       
   262    *   The bundle name for the instance.
       
   263    * @param $field_name
       
   264    *   The field name for the instance.
       
   265    * @param $string
       
   266    *   The settings text.
       
   267    * @param $entity_type
       
   268    *   The entity type for the instance.
       
   269    */
       
   270   function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
       
   271     // Reset the fields info.
       
   272     field_info_cache_clear();
       
   273     // Assert field settings.
       
   274     $field = field_info_field($field_name);
       
   275     $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
       
   276 
       
   277     // Assert instance and widget settings.
       
   278     $instance = field_info_instance($entity_type, $field_name, $bundle);
       
   279     $this->assertTrue($instance['settings']['test_instance_setting'] == $string, 'Field instance settings were found.');
       
   280     $this->assertTrue($instance['widget']['settings']['test_widget_setting'] == $string, 'Field widget settings were found.');
       
   281   }
       
   282 
       
   283   /**
       
   284    * Tests that default value is correctly validated and saved.
       
   285    */
       
   286   function testDefaultValue() {
       
   287     // Create a test field and instance.
       
   288     $field_name = 'test';
       
   289     $field = array(
       
   290       'field_name' => $field_name,
       
   291       'type' => 'test_field'
       
   292     );
       
   293     field_create_field($field);
       
   294     $instance = array(
       
   295       'field_name' => $field_name,
       
   296       'entity_type' => 'node',
       
   297       'bundle' => $this->type,
       
   298     );
       
   299     field_create_instance($instance);
       
   300 
       
   301     $langcode = LANGUAGE_NONE;
       
   302     $admin_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $field_name;
       
   303     $element_id = "edit-$field_name-$langcode-0-value";
       
   304     $element_name = "{$field_name}[$langcode][0][value]";
       
   305     $this->drupalGet($admin_path);
       
   306     $this->assertFieldById($element_id, '', 'The default value widget was empty.');
       
   307 
       
   308     // Check that invalid default values are rejected.
       
   309     $edit = array($element_name => '-1');
       
   310     $this->drupalPost($admin_path, $edit, t('Save settings'));
       
   311     $this->assertText("$field_name does not accept the value -1", 'Form vaildation failed.');
       
   312 
       
   313     // Check that the default value is saved.
       
   314     $edit = array($element_name => '1');
       
   315     $this->drupalPost($admin_path, $edit, t('Save settings'));
       
   316     $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
       
   317     $instance = field_info_instance('node', $field_name, $this->type);
       
   318     $this->assertEqual($instance['default_value'], array(array('value' => 1)), 'The default value was correctly saved.');
       
   319 
       
   320     // Check that the default value shows up in the form
       
   321     $this->drupalGet($admin_path);
       
   322     $this->assertFieldById($element_id, '1', 'The default value widget was displayed with the correct value.');
       
   323 
       
   324     // Check that the default value can be emptied.
       
   325     $edit = array($element_name => '');
       
   326     $this->drupalPost(NULL, $edit, t('Save settings'));
       
   327     $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
       
   328     field_info_cache_clear();
       
   329     $instance = field_info_instance('node', $field_name, $this->type);
       
   330     $this->assertEqual($instance['default_value'], NULL, 'The default value was correctly saved.');
       
   331   }
       
   332 
       
   333   /**
       
   334    * Tests that deletion removes fields and instances as expected.
       
   335    */
       
   336   function testDeleteField() {
       
   337     // Create a new field.
       
   338     $bundle_path1 = 'admin/structure/types/manage/' . $this->hyphen_type;
       
   339     $edit1 = array(
       
   340       'fields[_add_new_field][label]' => $this->field_label,
       
   341       'fields[_add_new_field][field_name]' => $this->field_name_input,
       
   342     );
       
   343     $this->fieldUIAddNewField($bundle_path1, $edit1);
       
   344 
       
   345     // Create an additional node type.
       
   346     $type_name2 = strtolower($this->randomName(8)) . '_test';
       
   347     $type2 = $this->drupalCreateContentType(array('name' => $type_name2, 'type' => $type_name2));
       
   348     $type_name2 = $type2->type;
       
   349     $hyphen_type2 = str_replace('_', '-', $type_name2);
       
   350 
       
   351     // Add an instance to the second node type.
       
   352     $bundle_path2 = 'admin/structure/types/manage/' . $hyphen_type2;
       
   353     $edit2 = array(
       
   354       'fields[_add_existing_field][label]' => $this->field_label,
       
   355       'fields[_add_existing_field][field_name]' => $this->field_name,
       
   356     );
       
   357     $this->fieldUIAddExistingField($bundle_path2, $edit2);
       
   358 
       
   359     // Delete the first instance.
       
   360     $this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type);
       
   361 
       
   362     // Reset the fields info.
       
   363     field_info_cache_clear();
       
   364     // Check that the field instance was deleted.
       
   365     $this->assertNull(field_info_instance('node', $this->field_name, $this->type), 'Field instance was deleted.');
       
   366     // Check that the field was not deleted
       
   367     $this->assertNotNull(field_info_field($this->field_name), 'Field was not deleted.');
       
   368 
       
   369     // Delete the second instance.
       
   370     $this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2);
       
   371 
       
   372     // Reset the fields info.
       
   373     field_info_cache_clear();
       
   374     // Check that the field instance was deleted.
       
   375     $this->assertNull(field_info_instance('node', $this->field_name, $type_name2), 'Field instance was deleted.');
       
   376     // Check that the field was deleted too.
       
   377     $this->assertNull(field_info_field($this->field_name), 'Field was deleted.');
       
   378   }
       
   379 
       
   380   /**
       
   381    * Tests that Field UI respects the 'no_ui' option in hook_field_info().
       
   382    */
       
   383   function testHiddenFields() {
       
   384     $bundle_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/';
       
   385 
       
   386     // Check that the field type is not available in the 'add new field' row.
       
   387     $this->drupalGet($bundle_path);
       
   388     $this->assertFalse($this->xpath('//select[@id="edit-add-new-field-type"]//option[@value="hidden_test_field"]'), "The 'add new field' select respects field types 'no_ui' property.");
       
   389 
       
   390     // Create a field and an instance programmatically.
       
   391     $field_name = 'hidden_test_field';
       
   392     field_create_field(array('field_name' => $field_name, 'type' => $field_name));
       
   393     $instance = array(
       
   394       'field_name' => $field_name,
       
   395       'bundle' => $this->type,
       
   396       'entity_type' => 'node',
       
   397       'label' => t('Hidden field'),
       
   398       'widget' => array('type' => 'test_field_widget'),
       
   399     );
       
   400     field_create_instance($instance);
       
   401     $this->assertTrue(field_read_instance('node', $field_name, $this->type), format_string('An instance of the field %field was created programmatically.', array('%field' => $field_name)));
       
   402 
       
   403     // Check that the newly added instance appears on the 'Manage Fields'
       
   404     // screen.
       
   405     $this->drupalGet($bundle_path);
       
   406     $this->assertFieldByXPath('//table[@id="field-overview"]//td[1]', $instance['label'], 'Field was created and appears in the overview page.');
       
   407 
       
   408     // Check that the instance does not appear in the 'add existing field' row
       
   409     // on other bundles.
       
   410     $bundle_path = 'admin/structure/types/manage/article/fields/';
       
   411     $this->drupalGet($bundle_path);
       
   412     $this->assertFalse($this->xpath('//select[@id="edit-add-existing-field-field-name"]//option[@value=:field_name]', array(':field_name' => $field_name)), "The 'add existing field' select respects field types 'no_ui' property.");
       
   413   }
       
   414 
       
   415   /**
       
   416    * Tests renaming a bundle.
       
   417    */
       
   418   function testRenameBundle() {
       
   419     $type2 = strtolower($this->randomName(8)) . '_' .'test';
       
   420     $hyphen_type2 = str_replace('_', '-', $type2);
       
   421 
       
   422     $options = array(
       
   423       'type' => $type2,
       
   424     );
       
   425     $this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type, $options, t('Save content type'));
       
   426 
       
   427     $this->drupalGet('admin/structure/types/manage/' . $hyphen_type2 . '/fields');
       
   428   }
       
   429 
       
   430   /**
       
   431    * Tests that a duplicate field name is caught by validation.
       
   432    */
       
   433   function testDuplicateFieldName() {
       
   434     // field_tags already exists, so we're expecting an error when trying to
       
   435     // create a new field with the same name.
       
   436     $edit = array(
       
   437       'fields[_add_new_field][field_name]' => 'tags',
       
   438       'fields[_add_new_field][label]' => $this->randomName(),
       
   439       'fields[_add_new_field][type]' => 'taxonomy_term_reference',
       
   440       'fields[_add_new_field][widget_type]' => 'options_select',
       
   441     );
       
   442     $url = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields';
       
   443     $this->drupalPost($url, $edit, t('Save'));
       
   444 
       
   445     $this->assertText(t('The machine-readable name is already in use. It must be unique.'));
       
   446     $this->assertUrl($url, array(), 'Stayed on the same page.');
       
   447   }
       
   448 
       
   449   /**
       
   450    * Tests that external URLs in the 'destinations' query parameter are blocked.
       
   451    */
       
   452   function testExternalDestinations() {
       
   453     $path = 'admin/structure/types/manage/article/fields/field_tags/field-settings';
       
   454     $options = array(
       
   455       'query' => array('destinations' => array('http://example.com')),
       
   456     );
       
   457     $this->drupalPost($path, NULL, t('Save field settings'), $options);
       
   458 
       
   459     $this->assertUrl('admin/structure/types/manage/article/fields', array(), 'Stayed on the same site.');
       
   460   }
       
   461 }
       
   462 
       
   463 /**
       
   464  * Tests the functionality of the 'Manage display' screens.
       
   465  */
       
   466 class FieldUIManageDisplayTestCase extends FieldUITestCase {
       
   467   public static function getInfo() {
       
   468     return array(
       
   469       'name' => 'Manage display',
       
   470       'description' => 'Test the Field UI "Manage display" screens.',
       
   471       'group' => 'Field UI',
       
   472     );
       
   473   }
       
   474 
       
   475   function setUp() {
       
   476     parent::setUp(array('search'));
       
   477   }
       
   478 
       
   479   /**
       
   480    * Tests formatter settings.
       
   481    */
       
   482   function testFormatterUI() {
       
   483     $manage_fields = 'admin/structure/types/manage/' . $this->hyphen_type;
       
   484     $manage_display = $manage_fields . '/display';
       
   485 
       
   486     // Create a field, and a node with some data for the field.
       
   487     $edit = array(
       
   488       'fields[_add_new_field][label]' => 'Test field',
       
   489       'fields[_add_new_field][field_name]' => 'test',
       
   490     );
       
   491     $this->fieldUIAddNewField($manage_fields, $edit);
       
   492 
       
   493     // Clear the test-side cache and get the saved field instance.
       
   494     field_info_cache_clear();
       
   495     $instance = field_info_instance('node', 'field_test', $this->type);
       
   496     $format = $instance['display']['default']['type'];
       
   497     $default_settings = field_info_formatter_settings($format);
       
   498     $setting_name = key($default_settings);
       
   499     $setting_value = $instance['display']['default']['settings'][$setting_name];
       
   500 
       
   501     // Display the "Manage display" screen and check that the expected formatter is
       
   502     // selected.
       
   503     $this->drupalGet($manage_display);
       
   504     $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.');
       
   505     $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
       
   506 
       
   507     // Change the formatter and check that the summary is updated.
       
   508     $edit = array('fields[field_test][type]' => 'field_test_multiple', 'refresh_rows' => 'field_test');
       
   509     $this->drupalPostAJAX(NULL, $edit, array('op' => t('Refresh')));
       
   510     $format = 'field_test_multiple';
       
   511     $default_settings = field_info_formatter_settings($format);
       
   512     $setting_name = key($default_settings);
       
   513     $setting_value = $default_settings[$setting_name];
       
   514     $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.');
       
   515     $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
       
   516 
       
   517     // Submit the form and check that the instance is updated.
       
   518     $this->drupalPost(NULL, array(), t('Save'));
       
   519     field_info_cache_clear();
       
   520     $instance = field_info_instance('node', 'field_test', $this->type);
       
   521     $current_format = $instance['display']['default']['type'];
       
   522     $current_setting_value = $instance['display']['default']['settings'][$setting_name];
       
   523     $this->assertEqual($current_format, $format, 'The formatter was updated.');
       
   524     $this->assertEqual($current_setting_value, $setting_value, 'The setting was updated.');
       
   525   }
       
   526 
       
   527   /**
       
   528    * Tests switching view modes to use custom or 'default' settings'.
       
   529    */
       
   530   function testViewModeCustom() {
       
   531     // Create a field, and a node with some data for the field.
       
   532     $edit = array(
       
   533       'fields[_add_new_field][label]' => 'Test field',
       
   534       'fields[_add_new_field][field_name]' => 'test',
       
   535     );
       
   536     $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->hyphen_type, $edit);
       
   537     // For this test, use a formatter setting value that is an integer unlikely
       
   538     // to appear in a rendered node other than as part of the field being tested
       
   539     // (for example, unlikely to be part of the "Submitted by ... on ..." line).
       
   540     $value = 12345;
       
   541     $settings = array(
       
   542       'type' => $this->type,
       
   543       'field_test' => array(LANGUAGE_NONE => array(array('value' => $value))),
       
   544     );
       
   545     $node = $this->drupalCreateNode($settings);
       
   546 
       
   547     // Gather expected output values with the various formatters.
       
   548     $formatters = field_info_formatter_types();
       
   549     $output = array(
       
   550       'field_test_default' => $formatters['field_test_default']['settings']['test_formatter_setting'] . '|' . $value,
       
   551       'field_test_with_prepare_view' => $formatters['field_test_with_prepare_view']['settings']['test_formatter_setting_additional'] . '|' . $value. '|' . ($value + 1),
       
   552     );
       
   553 
       
   554     // Check that the field is displayed with the default formatter in 'rss'
       
   555     // mode (uses 'default'), and hidden in 'teaser' mode (uses custom settings).
       
   556     $this->assertNodeViewText($node, 'rss', $output['field_test_default'], "The field is displayed as expected in view modes that use 'default' settings.");
       
   557     $this->assertNodeViewNoText($node, 'teaser', $value, "The field is hidden in view modes that use custom settings.");
       
   558 
       
   559     // Change fomatter for 'default' mode, check that the field is displayed
       
   560     // accordingly in 'rss' mode.
       
   561     $edit = array(
       
   562       'fields[field_test][type]' => 'field_test_with_prepare_view',
       
   563     );
       
   564     $this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
       
   565     $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in view modes that use 'default' settings.");
       
   566 
       
   567     // Specialize the 'rss' mode, check that the field is displayed the same.
       
   568     $edit = array(
       
   569       "view_modes_custom[rss]" => TRUE,
       
   570     );
       
   571     $this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
       
   572     $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in newly specialized 'rss' mode.");
       
   573 
       
   574     // Set the field to 'hidden' in the view mode, check that the field is
       
   575     // hidden.
       
   576     $edit = array(
       
   577       'fields[field_test][type]' => 'hidden',
       
   578     );
       
   579     $this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display/rss', $edit, t('Save'));
       
   580     $this->assertNodeViewNoText($node, 'rss', $value, "The field is hidden in 'rss' mode.");
       
   581 
       
   582     // Set the view mode back to 'default', check that the field is displayed
       
   583     // accordingly.
       
   584     $edit = array(
       
   585       "view_modes_custom[rss]" => FALSE,
       
   586     );
       
   587     $this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
       
   588     $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected when 'rss' mode is set back to 'default' settings.");
       
   589 
       
   590     // Specialize the view mode again.
       
   591     $edit = array(
       
   592       "view_modes_custom[rss]" => TRUE,
       
   593     );
       
   594     $this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
       
   595     // Check that the previous settings for the view mode have been kept.
       
   596     $this->assertNodeViewNoText($node, 'rss', $value, "The previous settings are kept when 'rss' mode is specialized again.");
       
   597   }
       
   598 
       
   599   /**
       
   600    * Asserts that a string is found in the rendered node in a view mode.
       
   601    *
       
   602    * @param $node
       
   603    *   The node.
       
   604    * @param $view_mode
       
   605    *   The view mode in which the node should be displayed.
       
   606    * @param $text
       
   607    *   Plain text to look for.
       
   608    * @param $message
       
   609    *   Message to display.
       
   610    *
       
   611    * @return
       
   612    *   TRUE on pass, FALSE on fail.
       
   613    */
       
   614   function assertNodeViewText($node, $view_mode, $text, $message) {
       
   615     return $this->assertNodeViewTextHelper($node, $view_mode, $text, $message, FALSE);
       
   616   }
       
   617 
       
   618   /**
       
   619    * Asserts that a string is not found in the rendered node in a view mode.
       
   620    *
       
   621    * @param $node
       
   622    *   The node.
       
   623    * @param $view_mode
       
   624    *   The view mode in which the node should be displayed.
       
   625    * @param $text
       
   626    *   Plain text to look for.
       
   627    * @param $message
       
   628    *   Message to display.
       
   629    * @return
       
   630    *   TRUE on pass, FALSE on fail.
       
   631    */
       
   632   function assertNodeViewNoText($node, $view_mode, $text, $message) {
       
   633     return $this->assertNodeViewTextHelper($node, $view_mode, $text, $message, TRUE);
       
   634   }
       
   635 
       
   636   /**
       
   637    * Asserts that a string is (not) found in the rendered nodein a view mode.
       
   638    *
       
   639    * This helper function is used by assertNodeViewText() and
       
   640    * assertNodeViewNoText().
       
   641    *
       
   642    * @param $node
       
   643    *   The node.
       
   644    * @param $view_mode
       
   645    *   The view mode in which the node should be displayed.
       
   646    * @param $text
       
   647    *   Plain text to look for.
       
   648    * @param $message
       
   649    *   Message to display.
       
   650    * @param $not_exists
       
   651    *   TRUE if this text should not exist, FALSE if it should.
       
   652    *
       
   653    * @return
       
   654    *   TRUE on pass, FALSE on fail.
       
   655    */
       
   656   function assertNodeViewTextHelper($node, $view_mode, $text, $message, $not_exists) {
       
   657     // Make sure caches on the tester side are refreshed after changes
       
   658     // submitted on the tested side.
       
   659     field_info_cache_clear();
       
   660 
       
   661     // Save current content so that we can restore it when we're done.
       
   662     $old_content = $this->drupalGetContent();
       
   663 
       
   664     // Render a cloned node, so that we do not alter the original.
       
   665     $clone = clone $node;
       
   666     $element = node_view($clone, $view_mode);
       
   667     $output = drupal_render($element);
       
   668     $this->verbose(t('Rendered node - view mode: @view_mode', array('@view_mode' => $view_mode)) . '<hr />'. $output);
       
   669 
       
   670     // Assign content so that DrupalWebTestCase functions can be used.
       
   671     $this->drupalSetContent($output);
       
   672     $method = ($not_exists ? 'assertNoText' : 'assertText');
       
   673     $return = $this->{$method}((string) $text, $message);
       
   674 
       
   675     // Restore previous content.
       
   676     $this->drupalSetContent($old_content);
       
   677 
       
   678     return $return;
       
   679   }
       
   680 }
       
   681 
       
   682 /**
       
   683  * Tests custom widget hooks and callbacks on the field administration pages.
       
   684  */
       
   685 class FieldUIAlterTestCase extends DrupalWebTestCase {
       
   686   public static function getInfo() {
       
   687     return array(
       
   688       'name' => 'Widget customization',
       
   689       'description' => 'Test custom field widget hooks and callbacks on field administration pages.',
       
   690       'group' => 'Field UI',
       
   691     );
       
   692   }
       
   693 
       
   694   function setUp() {
       
   695     parent::setUp(array('field_test'));
       
   696 
       
   697     // Create test user.
       
   698     $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users', 'administer fields'));
       
   699     $this->drupalLogin($admin_user);
       
   700   }
       
   701 
       
   702   /**
       
   703    * Tests hook_field_widget_properties_alter() on the default field widget.
       
   704    *
       
   705    * @see field_test_field_widget_properties_alter()
       
   706    * @see field_test_field_widget_properties_user_alter()
       
   707    * @see field_test_field_widget_form_alter()
       
   708    */
       
   709   function testDefaultWidgetPropertiesAlter() {
       
   710     // Create the alter_test_text field and an instance on article nodes.
       
   711     field_create_field(array(
       
   712       'field_name' => 'alter_test_text',
       
   713       'type' => 'text',
       
   714     ));
       
   715     field_create_instance(array(
       
   716       'field_name' => 'alter_test_text',
       
   717       'entity_type' => 'node',
       
   718       'bundle' => 'article',
       
   719       'widget' => array(
       
   720         'type' => 'text_textfield',
       
   721         'size' => 60,
       
   722       ),
       
   723     ));
       
   724 
       
   725     // Test that field_test_field_widget_properties_alter() sets the size to
       
   726     // 42 and that field_test_field_widget_form_alter() reports the correct
       
   727     // size when the form is displayed.
       
   728     $this->drupalGet('admin/structure/types/manage/article/fields/alter_test_text');
       
   729     $this->assertText('Field size: 42', 'Altered field size is found in hook_field_widget_form_alter().');
       
   730 
       
   731     // Create the alter_test_options field.
       
   732     field_create_field(array(
       
   733       'field_name' => 'alter_test_options',
       
   734       'type' => 'list_text'
       
   735     ));
       
   736     // Create instances on users and page nodes.
       
   737     field_create_instance(array(
       
   738       'field_name' => 'alter_test_options',
       
   739       'entity_type' => 'user',
       
   740       'bundle' => 'user',
       
   741       'widget' => array(
       
   742         'type' => 'options_select',
       
   743       )
       
   744     ));
       
   745     field_create_instance(array(
       
   746       'field_name' => 'alter_test_options',
       
   747       'entity_type' => 'node',
       
   748       'bundle' => 'page',
       
   749       'widget' => array(
       
   750         'type' => 'options_select',
       
   751       )
       
   752     ));
       
   753 
       
   754     // Test that field_test_field_widget_properties_user_alter() replaces
       
   755     // the widget and that field_test_field_widget_form_alter() reports the
       
   756     // correct widget name when the form is displayed.
       
   757     $this->drupalGet('admin/config/people/accounts/fields/alter_test_options');
       
   758     $this->assertText('Widget type: options_buttons', 'Widget type is altered for users in hook_field_widget_form_alter().');
       
   759 
       
   760     // Test that the widget is not altered on page nodes.
       
   761     $this->drupalGet('admin/structure/types/manage/page/fields/alter_test_options');
       
   762     $this->assertText('Widget type: options_select', 'Widget type is not altered for pages in hook_field_widget_form_alter().');
       
   763   }
       
   764 }