annotate core/modules/field/tests/src/Kernel/FieldAttachOtherTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Tests\field\Kernel;
Chris@0 4
Chris@0 5 use Drupal\Core\Form\FormState;
Chris@0 6 use Drupal\entity_test\Entity\EntityTest;
Chris@0 7
Chris@0 8 /**
Chris@0 9 * Tests other Field API functions.
Chris@0 10 *
Chris@0 11 * @group field
Chris@0 12 * @todo move this to the Entity module
Chris@0 13 */
Chris@0 14 class FieldAttachOtherTest extends FieldKernelTestBase {
Chris@0 15
Chris@0 16 protected function setUp() {
Chris@0 17 parent::setUp();
Chris@0 18 $this->container->get('router.builder')->rebuild();
Chris@0 19 $this->installEntitySchema('entity_test_rev');
Chris@0 20 $this->createFieldWithStorage();
Chris@0 21 }
Chris@0 22
Chris@0 23 /**
Chris@0 24 * Test rendering fields with EntityDisplay build().
Chris@0 25 */
Chris@0 26 public function testEntityDisplayBuild() {
Chris@0 27 $this->createFieldWithStorage('_2');
Chris@0 28
Chris@0 29 $entity_type = 'entity_test';
Chris@0 30 $entity_init = $this->container->get('entity_type.manager')
Chris@0 31 ->getStorage($entity_type)
Chris@0 32 ->create();
Chris@0 33
Chris@0 34 // Populate values to be displayed.
Chris@0 35 $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
Chris@0 36 $entity_init->{$this->fieldTestData->field_name}->setValue($values);
Chris@0 37 $values_2 = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
Chris@0 38 $entity_init->{$this->fieldTestData->field_name_2}->setValue($values_2);
Chris@0 39
Chris@0 40 // Simple formatter, label displayed.
Chris@0 41 $entity = clone($entity_init);
Chris@0 42 $display = entity_get_display($entity_type, $entity->bundle(), 'full');
Chris@0 43
Chris@0 44 $formatter_setting = $this->randomMachineName();
Chris@0 45 $display_options = [
Chris@0 46 'label' => 'above',
Chris@0 47 'type' => 'field_test_default',
Chris@0 48 'settings' => [
Chris@0 49 'test_formatter_setting' => $formatter_setting,
Chris@0 50 ],
Chris@0 51 ];
Chris@0 52 $display->setComponent($this->fieldTestData->field_name, $display_options);
Chris@0 53
Chris@0 54 $formatter_setting_2 = $this->randomMachineName();
Chris@0 55 $display_options_2 = [
Chris@0 56 'label' => 'above',
Chris@0 57 'type' => 'field_test_default',
Chris@0 58 'settings' => [
Chris@0 59 'test_formatter_setting' => $formatter_setting_2,
Chris@0 60 ],
Chris@0 61 ];
Chris@0 62 $display->setComponent($this->fieldTestData->field_name_2, $display_options_2);
Chris@0 63
Chris@0 64 // View all fields.
Chris@0 65 $content = $display->build($entity);
Chris@0 66 $this->render($content);
Chris@0 67 $this->assertRaw($this->fieldTestData->field->getLabel(), "First field's label is displayed.");
Chris@0 68 foreach ($values as $delta => $value) {
Chris@0 69 $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
Chris@0 70 }
Chris@0 71 $this->assertRaw($this->fieldTestData->field_2->getLabel(), "Second field's label is displayed.");
Chris@0 72 foreach ($values_2 as $delta => $value) {
Chris@0 73 $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
Chris@0 74 }
Chris@0 75
Chris@0 76 // Label hidden.
Chris@0 77 $entity = clone($entity_init);
Chris@0 78 $display_options['label'] = 'hidden';
Chris@0 79 $display->setComponent($this->fieldTestData->field_name, $display_options);
Chris@0 80 $content = $display->build($entity);
Chris@0 81 $this->render($content);
Chris@0 82 $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden label: label is not displayed.");
Chris@0 83
Chris@0 84 // Field hidden.
Chris@0 85 $entity = clone($entity_init);
Chris@0 86 $display->removeComponent($this->fieldTestData->field_name);
Chris@0 87 $content = $display->build($entity);
Chris@0 88 $this->render($content);
Chris@0 89 $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden field: label is not displayed.");
Chris@0 90 foreach ($values as $delta => $value) {
Chris@0 91 $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
Chris@0 92 }
Chris@0 93
Chris@0 94 // Multiple formatter.
Chris@0 95 $entity = clone($entity_init);
Chris@0 96 $formatter_setting = $this->randomMachineName();
Chris@0 97 $display->setComponent($this->fieldTestData->field_name, [
Chris@0 98 'label' => 'above',
Chris@0 99 'type' => 'field_test_multiple',
Chris@0 100 'settings' => [
Chris@0 101 'test_formatter_setting_multiple' => $formatter_setting,
Chris@0 102 ],
Chris@0 103 ]);
Chris@0 104 $content = $display->build($entity);
Chris@0 105 $this->render($content);
Chris@0 106 $expected_output = $formatter_setting;
Chris@0 107 foreach ($values as $delta => $value) {
Chris@0 108 $expected_output .= "|$delta:{$value['value']}";
Chris@0 109 }
Chris@0 110 $this->assertRaw($expected_output, "Multiple formatter: all values are displayed, formatter settings are applied.");
Chris@0 111
Chris@0 112 // Test a formatter that uses hook_field_formatter_prepare_view().
Chris@0 113 $entity = clone($entity_init);
Chris@0 114 $formatter_setting = $this->randomMachineName();
Chris@0 115 $display->setComponent($this->fieldTestData->field_name, [
Chris@0 116 'label' => 'above',
Chris@0 117 'type' => 'field_test_with_prepare_view',
Chris@0 118 'settings' => [
Chris@0 119 'test_formatter_setting_additional' => $formatter_setting,
Chris@0 120 ],
Chris@0 121 ]);
Chris@0 122 $content = $display->build($entity);
Chris@0 123 $this->render($content);
Chris@0 124 foreach ($values as $delta => $value) {
Chris@0 125 $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1);
Chris@0 126 $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied.");
Chris@0 127 }
Chris@0 128
Chris@0 129 // TODO:
Chris@0 130 // - check display order with several fields
Chris@0 131 }
Chris@0 132
Chris@0 133 /**
Chris@0 134 * Tests rendering fields with EntityDisplay::buildMultiple().
Chris@0 135 */
Chris@0 136 public function testEntityDisplayViewMultiple() {
Chris@0 137 // Use a formatter that has a prepareView() step.
Chris@0 138 $display = entity_get_display('entity_test', 'entity_test', 'full')
Chris@0 139 ->setComponent($this->fieldTestData->field_name, [
Chris@0 140 'type' => 'field_test_with_prepare_view',
Chris@0 141 ]);
Chris@0 142
Chris@0 143 // Create two entities.
Chris@0 144 $entity1 = EntityTest::create(['id' => 1, 'type' => 'entity_test']);
Chris@0 145 $entity1->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1));
Chris@0 146 $entity2 = EntityTest::create(['id' => 2, 'type' => 'entity_test']);
Chris@0 147 $entity2->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1));
Chris@0 148
Chris@0 149 // Run buildMultiple(), and check that the entities come out as expected.
Chris@0 150 $display->buildMultiple([$entity1, $entity2]);
Chris@0 151 $item1 = $entity1->{$this->fieldTestData->field_name}[0];
Chris@0 152 $this->assertEqual($item1->additional_formatter_value, $item1->value + 1, 'Entity 1 ran through the prepareView() formatter method.');
Chris@0 153 $item2 = $entity2->{$this->fieldTestData->field_name}[0];
Chris@0 154 $this->assertEqual($item2->additional_formatter_value, $item2->value + 1, 'Entity 2 ran through the prepareView() formatter method.');
Chris@0 155 }
Chris@0 156
Chris@0 157 /**
Chris@0 158 * Test entity cache.
Chris@0 159 *
Chris@0 160 * Complements unit test coverage in
Chris@0 161 * \Drupal\Tests\Core\Entity\Sql\SqlContentEntityStorageTest.
Chris@0 162 */
Chris@0 163 public function testEntityCache() {
Chris@0 164 // Initialize random values and a test entity.
Chris@0 165 $entity_init = EntityTest::create(['type' => $this->fieldTestData->field->getTargetBundle()]);
Chris@0 166 $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
Chris@0 167
Chris@0 168 // Non-cacheable entity type.
Chris@0 169 $entity_type = 'entity_test';
Chris@0 170 $cid = "values:$entity_type:" . $entity_init->id();
Chris@0 171
Chris@0 172 // Check that no initial cache entry is present.
Chris@0 173 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no initial cache entry');
Chris@0 174
Chris@0 175 // Save, and check that no cache entry is present.
Chris@0 176 $entity = clone($entity_init);
Chris@0 177 $entity->{$this->fieldTestData->field_name}->setValue($values);
Chris@0 178 $entity = $this->entitySaveReload($entity);
Chris@0 179 $cid = "values:$entity_type:" . $entity->id();
Chris@0 180 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no cache entry on insert and load');
Chris@0 181
Chris@0 182 // Cacheable entity type.
Chris@0 183 $entity_type = 'entity_test_rev';
Chris@0 184 $this->createFieldWithStorage('_2', $entity_type);
Chris@0 185
Chris@0 186 $entity_init = $this->container->get('entity_type.manager')
Chris@0 187 ->getStorage($entity_type)
Chris@0 188 ->create([
Chris@0 189 'type' => $entity_type,
Chris@0 190 ]);
Chris@0 191
Chris@0 192 // Check that no initial cache entry is present.
Chris@0 193 $cid = "values:$entity_type:" . $entity->id();
Chris@0 194 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no initial cache entry');
Chris@0 195
Chris@0 196 // Save, and check that no cache entry is present.
Chris@0 197 $entity = clone($entity_init);
Chris@0 198 $entity->{$this->fieldTestData->field_name_2} = $values;
Chris@0 199 $entity->save();
Chris@0 200 $cid = "values:$entity_type:" . $entity->id();
Chris@0 201
Chris@0 202 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on insert');
Chris@0 203 // Load, and check that a cache entry is present with the expected values.
Chris@0 204 $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId());
Chris@0 205 $controller->resetCache();
Chris@0 206 $cached_entity = $controller->load($entity->id());
Chris@0 207 $cache = \Drupal::cache('entity')->get($cid);
Chris@0 208 $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
Chris@0 209
Chris@0 210 // Update with different values, and check that the cache entry is wiped.
Chris@0 211 $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
Chris@0 212 $entity->{$this->fieldTestData->field_name_2} = $values;
Chris@0 213 $entity->save();
Chris@0 214 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on update');
Chris@0 215
Chris@0 216 // Load, and check that a cache entry is present with the expected values.
Chris@0 217 $controller->resetCache();
Chris@0 218 $cached_entity = $controller->load($entity->id());
Chris@0 219 $cache = \Drupal::cache('entity')->get($cid);
Chris@0 220 $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
Chris@0 221
Chris@0 222 // Create a new revision, and check that the cache entry is wiped.
Chris@0 223 $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
Chris@0 224 $entity->{$this->fieldTestData->field_name_2} = $values;
Chris@0 225 $entity->setNewRevision();
Chris@0 226 $entity->save();
Chris@0 227 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on new revision creation');
Chris@0 228
Chris@0 229 // Load, and check that a cache entry is present with the expected values.
Chris@0 230 $controller->resetCache();
Chris@0 231 $cached_entity = $controller->load($entity->id());
Chris@0 232 $cache = \Drupal::cache('entity')->get($cid);
Chris@0 233 $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
Chris@0 234
Chris@0 235 // Delete, and check that the cache entry is wiped.
Chris@0 236 $entity->delete();
Chris@0 237 $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry after delete');
Chris@0 238 }
Chris@0 239
Chris@0 240 /**
Chris@0 241 * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::buildForm().
Chris@0 242 *
Chris@0 243 * This could be much more thorough, but it does verify that the correct
Chris@0 244 * widgets show up.
Chris@0 245 */
Chris@0 246 public function testEntityFormDisplayBuildForm() {
Chris@0 247 $this->createFieldWithStorage('_2');
Chris@0 248
Chris@0 249 $entity_type = 'entity_test';
Chris@0 250 $entity = entity_create($entity_type, ['id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()]);
Chris@0 251
Chris@0 252 // Test generating widgets for all fields.
Chris@0 253 $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
Chris@0 254 $form = [];
Chris@0 255 $form_state = new FormState();
Chris@0 256 $display->buildForm($entity, $form, $form_state);
Chris@0 257
Chris@0 258 $this->assertEqual($form[$this->fieldTestData->field_name]['widget']['#title'], $this->fieldTestData->field->getLabel(), "First field's form title is {$this->fieldTestData->field->getLabel()}");
Chris@0 259 $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget']['#title'], $this->fieldTestData->field_2->getLabel(), "Second field's form title is {$this->fieldTestData->field_2->getLabel()}");
Chris@0 260 for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) {
Chris@0 261 // field_test_widget uses 'textfield'
Chris@0 262 $this->assertEqual($form[$this->fieldTestData->field_name]['widget'][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
Chris@0 263 }
Chris@0 264 for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
Chris@0 265 // field_test_widget uses 'textfield'
Chris@0 266 $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
Chris@0 267 }
Chris@0 268
Chris@0 269 // Test generating widgets for all fields.
Chris@0 270 $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
Chris@0 271 foreach ($display->getComponents() as $name => $options) {
Chris@0 272 if ($name != $this->fieldTestData->field_name_2) {
Chris@0 273 $display->removeComponent($name);
Chris@0 274 }
Chris@0 275 }
Chris@0 276 $form = [];
Chris@0 277 $form_state = new FormState();
Chris@0 278 $display->buildForm($entity, $form, $form_state);
Chris@0 279
Chris@0 280 $this->assertFalse(isset($form[$this->fieldTestData->field_name]), 'The first field does not exist in the form');
Chris@0 281 $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget']['#title'], $this->fieldTestData->field_2->getLabel(), "Second field's form title is {$this->fieldTestData->field_2->getLabel()}");
Chris@0 282 for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
Chris@0 283 // field_test_widget uses 'textfield'
Chris@0 284 $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
Chris@0 285 }
Chris@0 286 }
Chris@0 287
Chris@0 288 /**
Chris@0 289 * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::extractFormValues().
Chris@0 290 */
Chris@0 291 public function testEntityFormDisplayExtractFormValues() {
Chris@0 292 $this->createFieldWithStorage('_2');
Chris@0 293
Chris@0 294 $entity_type = 'entity_test';
Chris@0 295 $entity_init = $this->container->get('entity_type.manager')
Chris@0 296 ->getStorage($entity_type)
Chris@0 297 ->create(['id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()]);
Chris@0 298
Chris@0 299 // Build the form for all fields.
Chris@0 300 $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
Chris@0 301 $form = [];
Chris@0 302 $form_state = new FormState();
Chris@0 303 $display->buildForm($entity_init, $form, $form_state);
Chris@0 304
Chris@0 305 // Simulate incoming values.
Chris@0 306 // First field.
Chris@0 307 $values = [];
Chris@0 308 $weights = [];
Chris@0 309 for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) {
Chris@0 310 $values[$delta]['value'] = mt_rand(1, 127);
Chris@0 311 // Assign random weight.
Chris@0 312 do {
Chris@0 313 $weight = mt_rand(0, $this->fieldTestData->field_storage->getCardinality());
Chris@0 314 } while (in_array($weight, $weights));
Chris@0 315 $weights[$delta] = $weight;
Chris@0 316 $values[$delta]['_weight'] = $weight;
Chris@0 317 }
Chris@0 318 // Leave an empty value. 'field_test' fields are empty if empty().
Chris@0 319 $values[1]['value'] = 0;
Chris@0 320 // Second field.
Chris@0 321 $values_2 = [];
Chris@0 322 $weights_2 = [];
Chris@0 323 for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
Chris@0 324 $values_2[$delta]['value'] = mt_rand(1, 127);
Chris@0 325 // Assign random weight.
Chris@0 326 do {
Chris@0 327 $weight = mt_rand(0, $this->fieldTestData->field_storage_2->getCardinality());
Chris@0 328 } while (in_array($weight, $weights_2));
Chris@0 329 $weights_2[$delta] = $weight;
Chris@0 330 $values_2[$delta]['_weight'] = $weight;
Chris@0 331 }
Chris@0 332 // Leave an empty value. 'field_test' fields are empty if empty().
Chris@0 333 $values_2[1]['value'] = 0;
Chris@0 334
Chris@0 335 // Pretend the form has been built.
Chris@0 336 $form_state->setFormObject(\Drupal::entityManager()->getFormObject($entity_type, 'default'));
Chris@0 337 \Drupal::formBuilder()->prepareForm('field_test_entity_form', $form, $form_state);
Chris@0 338 \Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state);
Chris@0 339 $form_state->setValue($this->fieldTestData->field_name, $values);
Chris@0 340 $form_state->setValue($this->fieldTestData->field_name_2, $values_2);
Chris@0 341
Chris@0 342 // Extract values for all fields.
Chris@0 343 $entity = clone($entity_init);
Chris@0 344 $display->extractFormValues($entity, $form, $form_state);
Chris@0 345
Chris@0 346 asort($weights);
Chris@0 347 asort($weights_2);
Chris@0 348 $expected_values = [];
Chris@0 349 $expected_values_2 = [];
Chris@0 350 foreach ($weights as $key => $value) {
Chris@0 351 if ($key != 1) {
Chris@0 352 $expected_values[] = ['value' => $values[$key]['value']];
Chris@0 353 }
Chris@0 354 }
Chris@0 355 $this->assertIdentical($entity->{$this->fieldTestData->field_name}->getValue(), $expected_values, 'Submit filters empty values');
Chris@0 356 foreach ($weights_2 as $key => $value) {
Chris@0 357 if ($key != 1) {
Chris@0 358 $expected_values_2[] = ['value' => $values_2[$key]['value']];
Chris@0 359 }
Chris@0 360 }
Chris@0 361 $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
Chris@0 362
Chris@0 363 // Call EntityFormDisplayInterface::extractFormValues() for a single field (the second field).
Chris@0 364 foreach ($display->getComponents() as $name => $options) {
Chris@0 365 if ($name != $this->fieldTestData->field_name_2) {
Chris@0 366 $display->removeComponent($name);
Chris@0 367 }
Chris@0 368 }
Chris@0 369 $entity = clone($entity_init);
Chris@0 370 $display->extractFormValues($entity, $form, $form_state);
Chris@0 371 $expected_values_2 = [];
Chris@0 372 foreach ($weights_2 as $key => $value) {
Chris@0 373 if ($key != 1) {
Chris@0 374 $expected_values_2[] = ['value' => $values_2[$key]['value']];
Chris@0 375 }
Chris@0 376 }
Chris@0 377 $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'The first field is empty in the entity object');
Chris@0 378 $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
Chris@0 379 }
Chris@0 380
Chris@0 381 }