Project

General

Profile

Paste
Download (30.7 KB) Statistics
| Branch: | Revision:

root / drupal7 / modules / field_ui / field_ui.test @ b0dc3a2e

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
}