annotate core/modules/field_ui/src/Tests/ManageDisplayTest.php @ 6:875880e46745

Styling
author Chris Cannam
date Fri, 08 Dec 2017 13:21:27 +0000
parents 4c8ae668cc8c
children 7a779792577d
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\field_ui\Tests;
Chris@0 4
Chris@0 5 use Drupal\Component\Utility\Unicode;
Chris@0 6 use Drupal\Core\Entity\Entity\EntityFormDisplay;
Chris@0 7 use Drupal\Core\Entity\Entity\EntityViewDisplay;
Chris@0 8 use Drupal\Core\Entity\EntityInterface;
Chris@0 9 use Drupal\Core\Language\LanguageInterface;
Chris@0 10 use Drupal\node\Entity\NodeType;
Chris@0 11 use Drupal\simpletest\WebTestBase;
Chris@0 12 use Drupal\taxonomy\Entity\Vocabulary;
Chris@0 13
Chris@0 14 /**
Chris@0 15 * Tests the Field UI "Manage display" and "Manage form display" screens.
Chris@0 16 *
Chris@0 17 * @group field_ui
Chris@0 18 */
Chris@0 19 class ManageDisplayTest extends WebTestBase {
Chris@0 20
Chris@0 21 use FieldUiTestTrait;
Chris@0 22
Chris@0 23 /**
Chris@0 24 * Modules to install.
Chris@0 25 *
Chris@0 26 * @var array
Chris@0 27 */
Chris@0 28 public static $modules = ['node', 'field_ui', 'taxonomy', 'search', 'field_test', 'field_third_party_test', 'block'];
Chris@0 29
Chris@0 30 /**
Chris@0 31 * {@inheritdoc}
Chris@0 32 */
Chris@0 33 protected function setUp() {
Chris@0 34 parent::setUp();
Chris@0 35 $this->drupalPlaceBlock('system_breadcrumb_block');
Chris@0 36 $this->drupalPlaceBlock('local_tasks_block');
Chris@0 37
Chris@0 38 // Create a test user.
Chris@0 39 $admin_user = $this->drupalCreateUser(['access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer account settings', 'administer user display', 'bypass node access']);
Chris@0 40 $this->drupalLogin($admin_user);
Chris@0 41
Chris@0 42 // Create content type, with underscores.
Chris@0 43 $type_name = strtolower($this->randomMachineName(8)) . '_test';
Chris@0 44 $type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]);
Chris@0 45 $this->type = $type->id();
Chris@0 46
Chris@0 47 // Create a default vocabulary.
Chris@0 48 $vocabulary = Vocabulary::create([
Chris@0 49 'name' => $this->randomMachineName(),
Chris@0 50 'description' => $this->randomMachineName(),
Chris@0 51 'vid' => Unicode::strtolower($this->randomMachineName()),
Chris@0 52 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
Chris@0 53 'help' => '',
Chris@0 54 'nodes' => ['article' => 'article'],
Chris@0 55 'weight' => mt_rand(0, 10),
Chris@0 56 ]);
Chris@0 57 $vocabulary->save();
Chris@0 58 $this->vocabulary = $vocabulary->id();
Chris@0 59 }
Chris@0 60
Chris@0 61 /**
Chris@0 62 * Tests formatter settings.
Chris@0 63 */
Chris@0 64 public function testFormatterUI() {
Chris@0 65 $manage_fields = 'admin/structure/types/manage/' . $this->type;
Chris@0 66 $manage_display = $manage_fields . '/display';
Chris@0 67
Chris@0 68 // Create a field, and a node with some data for the field.
Chris@0 69 $this->fieldUIAddNewField($manage_fields, 'test', 'Test field');
Chris@0 70
Chris@0 71 // Get the display options (formatter and settings) that were automatically
Chris@0 72 // assigned for the 'default' display.
Chris@0 73 $display = entity_get_display('node', $this->type, 'default');
Chris@0 74 $display_options = $display->getComponent('field_test');
Chris@0 75 $format = $display_options['type'];
Chris@0 76 $default_settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings($format);
Chris@0 77 $setting_name = key($default_settings);
Chris@0 78 $setting_value = $display_options['settings'][$setting_name];
Chris@0 79
Chris@0 80 // Display the "Manage display" screen and check that the expected formatter
Chris@0 81 // is selected.
Chris@0 82 $this->drupalGet($manage_display);
Chris@0 83 $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.');
Chris@0 84 $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
Chris@0 85
Chris@0 86 // Check whether formatter weights are respected.
Chris@0 87 $result = $this->xpath('//select[@id=:id]/option', [':id' => 'edit-fields-field-test-type']);
Chris@0 88 $options = array_map(function ($item) {
Chris@0 89 return (string) $item->attributes()->value[0];
Chris@0 90 }, $result);
Chris@0 91 $expected_options = [
Chris@0 92 'field_no_settings',
Chris@0 93 'field_empty_test',
Chris@0 94 'field_empty_setting',
Chris@0 95 'field_test_default',
Chris@0 96 'field_test_multiple',
Chris@0 97 'field_test_with_prepare_view',
Chris@0 98 'field_test_applicable',
Chris@0 99 ];
Chris@0 100 $this->assertEqual($options, $expected_options, 'The expected formatter ordering is respected.');
Chris@0 101
Chris@0 102 // Ensure that fields can be hidden directly by changing the region.
Chris@0 103 $this->drupalGet($manage_display);
Chris@0 104 $this->assertFieldByName('fields[field_test][region]', 'content');
Chris@0 105 $edit = ['fields[field_test][region]' => 'hidden'];
Chris@0 106 $this->drupalPostForm($manage_display, $edit, t('Save'));
Chris@0 107 $this->assertFieldByName('fields[field_test][region]', 'hidden');
Chris@0 108 $display = EntityViewDisplay::load("node.{$this->type}.default");
Chris@0 109 $this->assertNull($display->getComponent('field_test'));
Chris@0 110
Chris@0 111 // Restore the field to the content region.
Chris@0 112 $edit = [
Chris@0 113 'fields[field_test][type]' => 'field_test_default',
Chris@0 114 'fields[field_test][region]' => 'content',
Chris@0 115 ];
Chris@0 116 $this->drupalPostForm($manage_display, $edit, t('Save'));
Chris@0 117
Chris@0 118 // Change the formatter and check that the summary is updated.
Chris@0 119 $edit = [
Chris@0 120 'fields[field_test][type]' => 'field_test_multiple',
Chris@0 121 'fields[field_test][region]' => 'content',
Chris@0 122 'refresh_rows' => 'field_test'
Chris@0 123 ];
Chris@0 124 $this->drupalPostAjaxForm(NULL, $edit, ['op' => t('Refresh')]);
Chris@0 125 $format = 'field_test_multiple';
Chris@0 126 $default_settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings($format);
Chris@0 127 $setting_name = key($default_settings);
Chris@0 128 $setting_value = $default_settings[$setting_name];
Chris@0 129 $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.');
Chris@0 130 $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
Chris@0 131
Chris@0 132 // Submit the form and check that the display is updated.
Chris@0 133 $this->drupalPostForm(NULL, [], t('Save'));
Chris@0 134 $display = entity_get_display('node', $this->type, 'default');
Chris@0 135 $display_options = $display->getComponent('field_test');
Chris@0 136 $current_format = $display_options['type'];
Chris@0 137 $current_setting_value = $display_options['settings'][$setting_name];
Chris@0 138 $this->assertEqual($current_format, $format, 'The formatter was updated.');
Chris@0 139 $this->assertEqual($current_setting_value, $setting_value, 'The setting was updated.');
Chris@0 140
Chris@0 141 // Assert that hook_field_formatter_settings_summary_alter() is called.
Chris@0 142 $this->assertText('field_test_field_formatter_settings_summary_alter');
Chris@0 143
Chris@0 144 // Click on the formatter settings button to open the formatter settings
Chris@0 145 // form.
Chris@0 146 $this->drupalPostAjaxForm(NULL, [], "field_test_settings_edit");
Chris@0 147
Chris@0 148 // Assert that the field added in
Chris@0 149 // field_test_field_formatter_third_party_settings_form() is present.
Chris@0 150 $fieldname = 'fields[field_test][settings_edit_form][third_party_settings][field_third_party_test][field_test_field_formatter_third_party_settings_form]';
Chris@0 151 $this->assertField($fieldname, 'The field added in hook_field_formatter_third_party_settings_form() is present on the settings form.');
Chris@0 152 $edit = [$fieldname => 'foo'];
Chris@0 153 $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
Chris@0 154
Chris@0 155 // Save the form to save the third party settings.
Chris@0 156 $this->drupalPostForm(NULL, [], t('Save'));
Chris@0 157
Chris@0 158 \Drupal::entityManager()->clearCachedFieldDefinitions();
Chris@0 159 $id = 'node.' . $this->type . '.default';
Chris@0 160 $storage = $this->container->get('entity_type.manager')->getStorage('entity_view_display');
Chris@0 161 $storage->resetCache([$id]);
Chris@0 162 $display = $storage->load($id);
Chris@0 163 $this->assertEqual($display->getRenderer('field_test')->getThirdPartySetting('field_third_party_test', 'field_test_field_formatter_third_party_settings_form'), 'foo');
Chris@0 164 $this->assertTrue(in_array('field_third_party_test', $display->calculateDependencies()->getDependencies()['module']), 'The display has a dependency on field_third_party_test module.');
Chris@0 165
Chris@0 166 // Confirm that the third party settings are not updated on the settings form.
Chris@0 167 $this->drupalPostAjaxForm(NULL, [], "field_test_settings_edit");
Chris@0 168 $this->assertFieldByName($fieldname, '');
Chris@0 169
Chris@0 170 // Test the empty setting formatter.
Chris@0 171 $edit = [
Chris@0 172 'fields[field_test][type]' => 'field_empty_setting',
Chris@0 173 'fields[field_test][region]' => 'content',
Chris@0 174 ];
Chris@0 175 $this->drupalPostForm(NULL, $edit, t('Save'));
Chris@0 176 $this->assertNoText('Default empty setting now has a value.');
Chris@0 177 $this->assertFieldById('edit-fields-field-test-settings-edit');
Chris@0 178 $this->drupalPostAjaxForm(NULL, [], "field_test_settings_edit");
Chris@0 179 $fieldname = 'fields[field_test][settings_edit_form][settings][field_empty_setting]';
Chris@0 180 $edit = [$fieldname => 'non empty setting'];
Chris@0 181 $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
Chris@0 182 $this->assertText('Default empty setting now has a value.');
Chris@0 183
Chris@0 184 // Test the settings form behavior. An edit button should be present since
Chris@0 185 // there are third party settings to configure.
Chris@0 186 $edit = [
Chris@0 187 'fields[field_test][type]' => 'field_no_settings',
Chris@0 188 'fields[field_test][region]' => 'content',
Chris@0 189 'refresh_rows' => 'field_test',
Chris@0 190 ];
Chris@0 191 $this->drupalPostAjaxForm(NULL, $edit, ['op' => t('Refresh')]);
Chris@0 192 $this->assertFieldByName('field_test_settings_edit');
Chris@0 193
Chris@0 194 // Make sure we can save the third party settings when there are no settings available
Chris@0 195 $this->drupalPostAjaxForm(NULL, [], "field_test_settings_edit");
Chris@0 196 $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
Chris@0 197
Chris@0 198 // When a module providing third-party settings to a formatter (or widget)
Chris@0 199 // is uninstalled, the formatter remains enabled but the provided settings,
Chris@0 200 // together with the corresponding form elements, are removed from the
Chris@0 201 // display component.
Chris@0 202 \Drupal::service('module_installer')->uninstall(['field_third_party_test']);
Chris@0 203
Chris@0 204 // Ensure the button is still there after the module has been disabled.
Chris@0 205 $this->drupalGet($manage_display);
Chris@0 206 $this->assertResponse(200);
Chris@0 207 $this->assertFieldByName('field_test_settings_edit');
Chris@0 208
Chris@0 209 // Ensure that third-party form elements are not present anymore.
Chris@0 210 $this->drupalPostAjaxForm(NULL, [], 'field_test_settings_edit');
Chris@0 211 $fieldname = 'fields[field_test][settings_edit_form][third_party_settings][field_third_party_test][field_test_field_formatter_third_party_settings_form]';
Chris@0 212 $this->assertNoField($fieldname);
Chris@0 213
Chris@0 214 // Ensure that third-party settings were removed from the formatter.
Chris@0 215 $display = EntityViewDisplay::load("node.{$this->type}.default");
Chris@0 216 $component = $display->getComponent('field_test');
Chris@0 217 $this->assertFalse(array_key_exists('field_third_party_test', $component['third_party_settings']));
Chris@0 218 }
Chris@0 219
Chris@0 220 /**
Chris@0 221 * Tests widget settings.
Chris@0 222 */
Chris@0 223 public function testWidgetUI() {
Chris@0 224 // Admin Manage Fields page.
Chris@0 225 $manage_fields = 'admin/structure/types/manage/' . $this->type;
Chris@0 226 // Admin Manage Display page.
Chris@0 227 $manage_display = $manage_fields . '/form-display';
Chris@0 228
Chris@0 229 // Creates a new field that can be used with multiple formatters.
Chris@0 230 // Reference: Drupal\field_test\Plugin\Field\FieldWidget\TestFieldWidgetMultiple::isApplicable().
Chris@0 231 $this->fieldUIAddNewField($manage_fields, 'test', 'Test field');
Chris@0 232
Chris@0 233 // Get the display options (formatter and settings) that were automatically
Chris@0 234 // assigned for the 'default' display.
Chris@0 235 $display = entity_get_form_display('node', $this->type, 'default');
Chris@0 236 $display_options = $display->getComponent('field_test');
Chris@0 237 $widget_type = $display_options['type'];
Chris@0 238 $default_settings = \Drupal::service('plugin.manager.field.widget')->getDefaultSettings($widget_type);
Chris@0 239 $setting_name = key($default_settings);
Chris@0 240 $setting_value = $display_options['settings'][$setting_name];
Chris@0 241
Chris@0 242 // Display the "Manage form display" screen and check if the expected
Chris@0 243 // widget is selected.
Chris@0 244 $this->drupalGet($manage_display);
Chris@0 245 $this->assertFieldByName('fields[field_test][type]', $widget_type, 'The expected widget is selected.');
Chris@0 246 $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
Chris@0 247
Chris@0 248 // Check whether widget weights are respected.
Chris@0 249 $result = $this->xpath('//select[@id=:id]/option', [':id' => 'edit-fields-field-test-type']);
Chris@0 250 $options = array_map(function ($item) {
Chris@0 251 return (string) $item->attributes()->value[0];
Chris@0 252 }, $result);
Chris@0 253 $expected_options = [
Chris@0 254 'test_field_widget',
Chris@0 255 'test_field_widget_multiple',
Chris@0 256 ];
Chris@0 257 $this->assertEqual($options, $expected_options, 'The expected widget ordering is respected.');
Chris@0 258
Chris@0 259 // Change the widget and check that the summary is updated.
Chris@0 260 $edit = [
Chris@0 261 'fields[field_test][type]' => 'test_field_widget_multiple',
Chris@0 262 'fields[field_test][region]' => 'content',
Chris@0 263 'refresh_rows' => 'field_test',
Chris@0 264 ];
Chris@0 265 $this->drupalPostAjaxForm(NULL, $edit, ['op' => t('Refresh')]);
Chris@0 266 $widget_type = 'test_field_widget_multiple';
Chris@0 267 $default_settings = \Drupal::service('plugin.manager.field.widget')->getDefaultSettings($widget_type);
Chris@0 268 $setting_name = key($default_settings);
Chris@0 269 $setting_value = $default_settings[$setting_name];
Chris@0 270 $this->assertFieldByName('fields[field_test][type]', $widget_type, 'The expected widget is selected.');
Chris@0 271 $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
Chris@0 272
Chris@0 273 // Submit the form and check that the display is updated.
Chris@0 274 $this->drupalPostForm(NULL, [], t('Save'));
Chris@0 275 $display = entity_get_form_display('node', $this->type, 'default');
Chris@0 276 $display_options = $display->getComponent('field_test');
Chris@0 277 $current_widget = $display_options['type'];
Chris@0 278 $current_setting_value = $display_options['settings'][$setting_name];
Chris@0 279 $this->assertEqual($current_widget, $widget_type, 'The widget was updated.');
Chris@0 280 $this->assertEqual($current_setting_value, $setting_value, 'The setting was updated.');
Chris@0 281
Chris@0 282 // Assert that hook_field_widget_settings_summary_alter() is called.
Chris@0 283 $this->assertText('field_test_field_widget_settings_summary_alter');
Chris@0 284
Chris@0 285 // Click on the widget settings button to open the widget settings form.
Chris@0 286 $this->drupalPostAjaxForm(NULL, [], "field_test_settings_edit");
Chris@0 287
Chris@0 288 // Assert that the field added in
Chris@0 289 // field_test_field_widget_third_party_settings_form() is present.
Chris@0 290 $fieldname = 'fields[field_test][settings_edit_form][third_party_settings][field_third_party_test][field_test_widget_third_party_settings_form]';
Chris@0 291 $this->assertField($fieldname, 'The field added in hook_field_widget_third_party_settings_form() is present on the settings form.');
Chris@0 292 $edit = [$fieldname => 'foo'];
Chris@0 293 $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
Chris@0 294
Chris@0 295 // Save the form to save the third party settings.
Chris@0 296 $this->drupalPostForm(NULL, [], t('Save'));
Chris@0 297 \Drupal::entityManager()->clearCachedFieldDefinitions();
Chris@0 298 $storage = $this->container->get('entity_type.manager')->getStorage('entity_form_display');
Chris@0 299 $storage->resetCache(['node.' . $this->type . '.default']);
Chris@0 300 $display = $storage->load('node.' . $this->type . '.default');
Chris@0 301 $this->assertEqual($display->getRenderer('field_test')->getThirdPartySetting('field_third_party_test', 'field_test_widget_third_party_settings_form'), 'foo');
Chris@0 302 $this->assertTrue(in_array('field_third_party_test', $display->calculateDependencies()->getDependencies()['module']), 'Form display does not have a dependency on field_third_party_test module.');
Chris@0 303
Chris@0 304 // Confirm that the third party settings are not updated on the settings form.
Chris@0 305 $this->drupalPostAjaxForm(NULL, [], "field_test_settings_edit");
Chris@0 306 $this->assertFieldByName($fieldname, '');
Chris@0 307
Chris@0 308 // Creates a new field that can not be used with the multiple formatter.
Chris@0 309 // Reference: Drupal\field_test\Plugin\Field\FieldWidget\TestFieldWidgetMultiple::isApplicable().
Chris@0 310 $this->fieldUIAddNewField($manage_fields, 'onewidgetfield', 'One Widget Field');
Chris@0 311
Chris@0 312 // Go to the Manage Form Display.
Chris@0 313 $this->drupalGet($manage_display);
Chris@0 314
Chris@0 315 // Checks if the select elements contain the specified options.
Chris@0 316 $this->assertFieldSelectOptions('fields[field_test][type]', ['test_field_widget', 'test_field_widget_multiple']);
Chris@0 317 $this->assertFieldSelectOptions('fields[field_onewidgetfield][type]', ['test_field_widget']);
Chris@0 318
Chris@0 319 // Ensure that fields can be hidden directly by changing the region.
Chris@0 320 $this->assertFieldByName('fields[field_test][region]', 'content');
Chris@0 321 $edit = ['fields[field_test][region]' => 'hidden'];
Chris@0 322 $this->drupalPostForm(NULL, $edit, t('Save'));
Chris@0 323 $this->assertFieldByName('fields[field_test][region]', 'hidden');
Chris@0 324 $display = EntityFormDisplay::load("node.{$this->type}.default");
Chris@0 325 $this->assertNull($display->getComponent('field_test'));
Chris@0 326 }
Chris@0 327
Chris@0 328 /**
Chris@0 329 * Tests switching view modes to use custom or 'default' settings'.
Chris@0 330 */
Chris@0 331 public function testViewModeCustom() {
Chris@0 332 // Create a field, and a node with some data for the field.
Chris@0 333 $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->type, 'test', 'Test field');
Chris@0 334 \Drupal::entityManager()->clearCachedFieldDefinitions();
Chris@0 335 // For this test, use a formatter setting value that is an integer unlikely
Chris@0 336 // to appear in a rendered node other than as part of the field being tested
Chris@0 337 // (for example, unlikely to be part of the "Submitted by ... on ..." line).
Chris@0 338 $value = 12345;
Chris@0 339 $settings = [
Chris@0 340 'type' => $this->type,
Chris@0 341 'field_test' => [['value' => $value]],
Chris@0 342 ];
Chris@0 343 $node = $this->drupalCreateNode($settings);
Chris@0 344
Chris@0 345 // Gather expected output values with the various formatters.
Chris@0 346 $formatter_plugin_manager = \Drupal::service('plugin.manager.field.formatter');
Chris@0 347 $field_test_default_settings = $formatter_plugin_manager->getDefaultSettings('field_test_default');
Chris@0 348 $field_test_with_prepare_view_settings = $formatter_plugin_manager->getDefaultSettings('field_test_with_prepare_view');
Chris@0 349 $output = [
Chris@0 350 'field_test_default' => $field_test_default_settings['test_formatter_setting'] . '|' . $value,
Chris@0 351 'field_test_with_prepare_view' => $field_test_with_prepare_view_settings['test_formatter_setting_additional'] . '|' . $value . '|' . ($value + 1),
Chris@0 352 ];
Chris@0 353
Chris@0 354 // Check that the field is displayed with the default formatter in 'rss'
Chris@0 355 // mode (uses 'default'), and hidden in 'teaser' mode (uses custom settings).
Chris@0 356 $this->assertNodeViewText($node, 'rss', $output['field_test_default'], "The field is displayed as expected in view modes that use 'default' settings.");
Chris@0 357 $this->assertNodeViewNoText($node, 'teaser', $value, "The field is hidden in view modes that use custom settings.");
Chris@0 358
Chris@0 359 // Change formatter for 'default' mode, check that the field is displayed
Chris@0 360 // accordingly in 'rss' mode.
Chris@0 361 $edit = [
Chris@0 362 'fields[field_test][type]' => 'field_test_with_prepare_view',
Chris@0 363 'fields[field_test][region]' => 'content',
Chris@0 364 ];
Chris@0 365 $this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
Chris@0 366 $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in view modes that use 'default' settings.");
Chris@0 367
Chris@0 368 // Specialize the 'rss' mode, check that the field is displayed the same.
Chris@0 369 $edit = [
Chris@0 370 "display_modes_custom[rss]" => TRUE,
Chris@0 371 ];
Chris@0 372 $this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
Chris@0 373 $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in newly specialized 'rss' mode.");
Chris@0 374
Chris@0 375 // Set the field to 'hidden' in the view mode, check that the field is
Chris@0 376 // hidden.
Chris@0 377 $edit = [
Chris@0 378 'fields[field_test][region]' => 'hidden',
Chris@0 379 ];
Chris@0 380 $this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display/rss', $edit, t('Save'));
Chris@0 381 $this->assertNodeViewNoText($node, 'rss', $value, "The field is hidden in 'rss' mode.");
Chris@0 382
Chris@0 383 // Set the view mode back to 'default', check that the field is displayed
Chris@0 384 // accordingly.
Chris@0 385 $edit = [
Chris@0 386 "display_modes_custom[rss]" => FALSE,
Chris@0 387 ];
Chris@0 388 $this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
Chris@0 389 $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.");
Chris@0 390
Chris@0 391 // Specialize the view mode again.
Chris@0 392 $edit = [
Chris@0 393 "display_modes_custom[rss]" => TRUE,
Chris@0 394 ];
Chris@0 395 $this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
Chris@0 396 // Check that the previous settings for the view mode have been kept.
Chris@0 397 $this->assertNodeViewNoText($node, 'rss', $value, "The previous settings are kept when 'rss' mode is specialized again.");
Chris@0 398 }
Chris@0 399
Chris@0 400 /**
Chris@0 401 * Tests the local tasks are displayed correctly for view modes.
Chris@0 402 */
Chris@0 403 public function testViewModeLocalTasks() {
Chris@0 404 $manage_display = 'admin/structure/types/manage/' . $this->type . '/display';
Chris@0 405 $this->drupalGet($manage_display);
Chris@0 406 $this->assertNoLink('Full content');
Chris@0 407 $this->assertLink('Teaser');
Chris@0 408
Chris@0 409 $this->drupalGet($manage_display . '/teaser');
Chris@0 410 $this->assertNoLink('Full content');
Chris@0 411 $this->assertLink('Default');
Chris@0 412 }
Chris@0 413
Chris@0 414 /**
Chris@0 415 * Tests that fields with no explicit display settings do not break.
Chris@0 416 */
Chris@0 417 public function testNonInitializedFields() {
Chris@0 418 // Create a test field.
Chris@0 419 $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->type, 'test', 'Test');
Chris@0 420
Chris@0 421 // Check that the field appears as 'hidden' on the 'Manage display' page
Chris@0 422 // for the 'teaser' mode.
Chris@0 423 $this->drupalGet('admin/structure/types/manage/' . $this->type . '/display/teaser');
Chris@0 424 $this->assertFieldByName('fields[field_test][region]', 'hidden', 'The field is displayed as \'hidden \'.');
Chris@0 425 }
Chris@0 426
Chris@0 427 /**
Chris@0 428 * Tests hiding the view modes fieldset when there's only one available.
Chris@0 429 */
Chris@0 430 public function testSingleViewMode() {
Chris@0 431 $this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary . '/display');
Chris@0 432 $this->assertNoText('Use custom display settings for the following view modes', 'Custom display settings fieldset found.');
Chris@0 433
Chris@0 434 // This may not trigger a notice when 'view_modes_custom' isn't available.
Chris@0 435 $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary . '/overview/display', [], t('Save'));
Chris@0 436 }
Chris@0 437
Chris@0 438 /**
Chris@0 439 * Tests that a message is shown when there are no fields.
Chris@0 440 */
Chris@0 441 public function testNoFieldsDisplayOverview() {
Chris@0 442 // Create a fresh content type without any fields.
Chris@0 443 NodeType::create([
Chris@0 444 'type' => 'no_fields',
Chris@0 445 'name' => 'No fields',
Chris@0 446 ])->save();
Chris@0 447
Chris@0 448 $this->drupalGet('admin/structure/types/manage/no_fields/display');
Chris@0 449 $this->assertRaw(t('There are no fields yet added. You can add new fields on the <a href=":link">Manage fields</a> page.', [':link' => \Drupal::url('entity.node.field_ui_fields', ['node_type' => 'no_fields'])]));
Chris@0 450 }
Chris@0 451
Chris@0 452 /**
Chris@0 453 * Asserts that a string is found in the rendered node in a view mode.
Chris@0 454 *
Chris@0 455 * @param EntityInterface $node
Chris@0 456 * The node.
Chris@0 457 * @param $view_mode
Chris@0 458 * The view mode in which the node should be displayed.
Chris@0 459 * @param $text
Chris@0 460 * Plain text to look for.
Chris@0 461 * @param $message
Chris@0 462 * Message to display.
Chris@0 463 *
Chris@0 464 * @return
Chris@0 465 * TRUE on pass, FALSE on fail.
Chris@0 466 */
Chris@0 467 public function assertNodeViewText(EntityInterface $node, $view_mode, $text, $message) {
Chris@0 468 return $this->assertNodeViewTextHelper($node, $view_mode, $text, $message, FALSE);
Chris@0 469 }
Chris@0 470
Chris@0 471 /**
Chris@0 472 * Asserts that a string is not found in the rendered node in a view mode.
Chris@0 473 *
Chris@0 474 * @param EntityInterface $node
Chris@0 475 * The node.
Chris@0 476 * @param $view_mode
Chris@0 477 * The view mode in which the node should be displayed.
Chris@0 478 * @param $text
Chris@0 479 * Plain text to look for.
Chris@0 480 * @param $message
Chris@0 481 * Message to display.
Chris@0 482 * @return
Chris@0 483 * TRUE on pass, FALSE on fail.
Chris@0 484 */
Chris@0 485 public function assertNodeViewNoText(EntityInterface $node, $view_mode, $text, $message) {
Chris@0 486 return $this->assertNodeViewTextHelper($node, $view_mode, $text, $message, TRUE);
Chris@0 487 }
Chris@0 488
Chris@0 489 /**
Chris@0 490 * Asserts that a string is (not) found in the rendered nodein a view mode.
Chris@0 491 *
Chris@0 492 * This helper function is used by assertNodeViewText() and
Chris@0 493 * assertNodeViewNoText().
Chris@0 494 *
Chris@0 495 * @param EntityInterface $node
Chris@0 496 * The node.
Chris@0 497 * @param $view_mode
Chris@0 498 * The view mode in which the node should be displayed.
Chris@0 499 * @param $text
Chris@0 500 * Plain text to look for.
Chris@0 501 * @param $message
Chris@0 502 * Message to display.
Chris@0 503 * @param $not_exists
Chris@0 504 * TRUE if this text should not exist, FALSE if it should.
Chris@0 505 *
Chris@0 506 * @return
Chris@0 507 * TRUE on pass, FALSE on fail.
Chris@0 508 */
Chris@0 509 public function assertNodeViewTextHelper(EntityInterface $node, $view_mode, $text, $message, $not_exists) {
Chris@0 510 // Make sure caches on the tester side are refreshed after changes
Chris@0 511 // submitted on the tested side.
Chris@0 512 \Drupal::entityManager()->clearCachedFieldDefinitions();
Chris@0 513
Chris@0 514 // Save current content so that we can restore it when we're done.
Chris@0 515 $old_content = $this->getRawContent();
Chris@0 516
Chris@0 517 // Render a cloned node, so that we do not alter the original.
Chris@0 518 $clone = clone $node;
Chris@0 519 $element = node_view($clone, $view_mode);
Chris@0 520 $output = \Drupal::service('renderer')->renderRoot($element);
Chris@0 521 $this->verbose(t('Rendered node - view mode: @view_mode', ['@view_mode' => $view_mode]) . '<hr />' . $output);
Chris@0 522
Chris@0 523 // Assign content so that WebTestBase functions can be used.
Chris@0 524 $this->setRawContent($output);
Chris@0 525 $method = ($not_exists ? 'assertNoText' : 'assertText');
Chris@0 526 $return = $this->{$method}((string) $text, $message);
Chris@0 527
Chris@0 528 // Restore previous content.
Chris@0 529 $this->setRawContent($old_content);
Chris@0 530
Chris@0 531 return $return;
Chris@0 532 }
Chris@0 533
Chris@0 534 /**
Chris@0 535 * Checks if a select element contains the specified options.
Chris@0 536 *
Chris@0 537 * @param string $name
Chris@0 538 * The field name.
Chris@0 539 * @param array $expected_options
Chris@0 540 * An array of expected options.
Chris@0 541 *
Chris@0 542 * @return bool
Chris@0 543 * TRUE if the assertion succeeded, FALSE otherwise.
Chris@0 544 */
Chris@0 545 protected function assertFieldSelectOptions($name, array $expected_options) {
Chris@0 546 $xpath = $this->buildXPathQuery('//select[@name=:name]', [':name' => $name]);
Chris@0 547 $fields = $this->xpath($xpath);
Chris@0 548 if ($fields) {
Chris@0 549 $field = $fields[0];
Chris@0 550 $options = $this->getAllOptionsList($field);
Chris@0 551
Chris@0 552 sort($options);
Chris@0 553 sort($expected_options);
Chris@0 554
Chris@0 555 return $this->assertIdentical($options, $expected_options);
Chris@0 556 }
Chris@0 557 else {
Chris@0 558 return $this->fail('Unable to find field ' . $name);
Chris@0 559 }
Chris@0 560 }
Chris@0 561
Chris@0 562 /**
Chris@0 563 * Extracts all options from a select element.
Chris@0 564 *
Chris@0 565 * @param \SimpleXMLElement $element
Chris@0 566 * The select element field information.
Chris@0 567 *
Chris@0 568 * @return array
Chris@0 569 * An array of option values as strings.
Chris@0 570 */
Chris@0 571 protected function getAllOptionsList(\SimpleXMLElement $element) {
Chris@0 572 $options = [];
Chris@0 573 // Add all options items.
Chris@0 574 foreach ($element->option as $option) {
Chris@0 575 $options[] = (string) $option['value'];
Chris@0 576 }
Chris@0 577
Chris@0 578 // Loops trough all the option groups
Chris@0 579 foreach ($element->optgroup as $optgroup) {
Chris@0 580 $options = array_merge($this->getAllOptionsList($optgroup), $options);
Chris@0 581 }
Chris@0 582
Chris@0 583 return $options;
Chris@0 584 }
Chris@0 585
Chris@0 586 }