1<?php 2 3namespace Drupal\Tests\serialization\Unit\Normalizer; 4 5use Drupal\Core\Entity\EntityFieldManagerInterface; 6use Drupal\Core\Entity\EntityTypeManagerInterface; 7use Drupal\Core\Entity\EntityTypeRepositoryInterface; 8use Drupal\Core\Entity\FieldableEntityInterface; 9use Drupal\Core\Field\FieldItemListInterface; 10use Drupal\serialization\Normalizer\EntityNormalizer; 11use Drupal\Tests\UnitTestCase; 12use Symfony\Component\Serializer\Exception\UnexpectedValueException; 13 14/** 15 * @coversDefaultClass \Drupal\serialization\Normalizer\EntityNormalizer 16 * @group serialization 17 */ 18class EntityNormalizerTest extends UnitTestCase { 19 20 /** 21 * The mock entity field manager. 22 * 23 * @var \Drupal\Core\Entity\EntityFieldManagerInterface|\PHPUnit\Framework\MockObject\MockObject 24 */ 25 protected $entityFieldManager; 26 27 /** 28 * The mock entity type manager. 29 * 30 * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit\Framework\MockObject\MockObject 31 */ 32 protected $entityTypeManager; 33 34 /** 35 * The mock entity type repository. 36 * 37 * @var \Drupal\Core\Entity\EntityTypeRepositoryInterface|\PHPUnit\Framework\MockObject\MockObject 38 */ 39 protected $entityTypeRepository; 40 41 /** 42 * The mock serializer. 43 * 44 * @var \Symfony\Component\Serializer\SerializerInterface|\PHPUnit\Framework\MockObject\MockObject 45 */ 46 protected $serializer; 47 48 /** 49 * The entity normalizer. 50 * 51 * @var \Drupal\serialization\Normalizer\EntityNormalizer 52 */ 53 protected $entityNormalizer; 54 55 /** 56 * {@inheritdoc} 57 */ 58 protected function setUp() { 59 $this->entityFieldManager = $this->createMock(EntityFieldManagerInterface::class); 60 $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class); 61 $this->entityTypeRepository = $this->createMock(EntityTypeRepositoryInterface::class); 62 63 $this->entityNormalizer = new EntityNormalizer( 64 $this->entityTypeManager, 65 $this->entityTypeRepository, 66 $this->entityFieldManager 67 ); 68 } 69 70 /** 71 * Tests the normalize() method. 72 * 73 * @covers ::normalize 74 */ 75 public function testNormalize() { 76 $list_item_1 = $this->createMock('Drupal\Core\TypedData\TypedDataInterface'); 77 $list_item_2 = $this->createMock('Drupal\Core\TypedData\TypedDataInterface'); 78 79 $definitions = [ 80 'field_1' => $list_item_1, 81 'field_2' => $list_item_2, 82 ]; 83 84 $content_entity = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityBase') 85 ->disableOriginalConstructor() 86 ->setMethods(['getFields']) 87 ->getMockForAbstractClass(); 88 $content_entity->expects($this->once()) 89 ->method('getFields') 90 ->will($this->returnValue($definitions)); 91 92 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\Serializer') 93 ->disableOriginalConstructor() 94 ->setMethods(['normalize']) 95 ->getMock(); 96 $serializer->expects($this->at(0)) 97 ->method('normalize') 98 ->with($list_item_1, 'test_format'); 99 $serializer->expects($this->at(1)) 100 ->method('normalize') 101 ->with($list_item_2, 'test_format'); 102 103 $this->entityNormalizer->setSerializer($serializer); 104 105 $this->entityNormalizer->normalize($content_entity, 'test_format'); 106 } 107 108 /** 109 * Tests the denormalize() method with no entity type provided in context. 110 * 111 * @covers ::denormalize 112 */ 113 public function testDenormalizeWithNoEntityType() { 114 $this->expectException(UnexpectedValueException::class); 115 $this->entityNormalizer->denormalize([], 'Drupal\Core\Entity\ContentEntityBase'); 116 } 117 118 /** 119 * Tests the denormalize method with a bundle property. 120 * 121 * @covers ::denormalize 122 */ 123 public function testDenormalizeWithValidBundle() { 124 $test_data = [ 125 'key_1' => 'value_1', 126 'key_2' => 'value_2', 127 'test_type' => [ 128 ['name' => 'test_bundle'], 129 ], 130 ]; 131 132 $entity_type = $this->createMock('Drupal\Core\Entity\EntityTypeInterface'); 133 134 $entity_type->expects($this->once()) 135 ->method('id') 136 ->willReturn('test'); 137 $entity_type->expects($this->once()) 138 ->method('hasKey') 139 ->with('bundle') 140 ->will($this->returnValue(TRUE)); 141 $entity_type->expects($this->once()) 142 ->method('getKey') 143 ->with('bundle') 144 ->will($this->returnValue('test_type')); 145 $entity_type->expects($this->once()) 146 ->method('entityClassImplements') 147 ->with(FieldableEntityInterface::class) 148 ->willReturn(TRUE); 149 150 $entity_type->expects($this->once()) 151 ->method('getBundleEntityType') 152 ->will($this->returnValue('test_bundle')); 153 154 $entity_type_storage_definition = $this->createMock('Drupal\Core\Field\FieldStorageDefinitionInterface'); 155 $entity_type_storage_definition->expects($this->once()) 156 ->method('getMainPropertyName') 157 ->will($this->returnValue('name')); 158 159 $entity_type_definition = $this->createMock('Drupal\Core\Field\FieldDefinitionInterface'); 160 $entity_type_definition->expects($this->once()) 161 ->method('getFieldStorageDefinition') 162 ->will($this->returnValue($entity_type_storage_definition)); 163 164 $base_definitions = [ 165 'test_type' => $entity_type_definition, 166 ]; 167 168 $this->entityTypeManager->expects($this->at(0)) 169 ->method('getDefinition') 170 ->with('test') 171 ->will($this->returnValue($entity_type)); 172 $this->entityFieldManager->expects($this->at(0)) 173 ->method('getBaseFieldDefinitions') 174 ->with('test') 175 ->will($this->returnValue($base_definitions)); 176 177 $entity_query_mock = $this->createMock('Drupal\Core\Entity\Query\QueryInterface'); 178 $entity_query_mock->expects($this->once()) 179 ->method('execute') 180 ->will($this->returnValue(['test_bundle' => 'test_bundle'])); 181 182 $entity_type_storage = $this->createMock('Drupal\Core\Entity\EntityStorageInterface'); 183 $entity_type_storage->expects($this->once()) 184 ->method('getQuery') 185 ->will($this->returnValue($entity_query_mock)); 186 187 $this->entityTypeManager->expects($this->at(1)) 188 ->method('getStorage') 189 ->with('test_bundle') 190 ->will($this->returnValue($entity_type_storage)); 191 192 $key_1 = $this->createMock(FieldItemListInterface::class); 193 $key_2 = $this->createMock(FieldItemListInterface::class); 194 195 $entity = $this->createMock(FieldableEntityInterface::class); 196 $entity->expects($this->at(0)) 197 ->method('get') 198 ->with('key_1') 199 ->willReturn($key_1); 200 $entity->expects($this->at(1)) 201 ->method('get') 202 ->with('key_2') 203 ->willReturn($key_2); 204 205 $storage = $this->createMock('Drupal\Core\Entity\EntityStorageInterface'); 206 // Create should only be called with the bundle property at first. 207 $expected_test_data = [ 208 'test_type' => 'test_bundle', 209 ]; 210 211 $storage->expects($this->once()) 212 ->method('create') 213 ->with($expected_test_data) 214 ->will($this->returnValue($entity)); 215 216 $this->entityTypeManager->expects($this->at(2)) 217 ->method('getStorage') 218 ->with('test') 219 ->will($this->returnValue($storage)); 220 221 // Setup expectations for the serializer. This will be called for each field 222 // item. 223 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\Serializer') 224 ->disableOriginalConstructor() 225 ->setMethods(['denormalize']) 226 ->getMock(); 227 $serializer->expects($this->at(0)) 228 ->method('denormalize') 229 ->with('value_1', get_class($key_1), NULL, ['target_instance' => $key_1, 'entity_type' => 'test']); 230 $serializer->expects($this->at(1)) 231 ->method('denormalize') 232 ->with('value_2', get_class($key_2), NULL, ['target_instance' => $key_2, 'entity_type' => 'test']); 233 234 $this->entityNormalizer->setSerializer($serializer); 235 236 $this->assertNotNull($this->entityNormalizer->denormalize($test_data, 'Drupal\Core\Entity\ContentEntityBase', NULL, ['entity_type' => 'test'])); 237 } 238 239 /** 240 * Tests the denormalize method with a bundle property. 241 * 242 * @covers ::denormalize 243 */ 244 public function testDenormalizeWithInvalidBundle() { 245 $test_data = [ 246 'key_1' => 'value_1', 247 'key_2' => 'value_2', 248 'test_type' => [ 249 ['name' => 'test_bundle'], 250 ], 251 ]; 252 253 $entity_type = $this->createMock('Drupal\Core\Entity\EntityTypeInterface'); 254 255 $entity_type->expects($this->once()) 256 ->method('id') 257 ->willReturn('test'); 258 $entity_type->expects($this->once()) 259 ->method('hasKey') 260 ->with('bundle') 261 ->will($this->returnValue(TRUE)); 262 $entity_type->expects($this->once()) 263 ->method('getKey') 264 ->with('bundle') 265 ->will($this->returnValue('test_type')); 266 $entity_type->expects($this->once()) 267 ->method('entityClassImplements') 268 ->with(FieldableEntityInterface::class) 269 ->willReturn(TRUE); 270 271 $entity_type->expects($this->once()) 272 ->method('getBundleEntityType') 273 ->will($this->returnValue('test_bundle')); 274 275 $entity_type_storage_definition = $this->createMock('Drupal\Core\Field\FieldStorageDefinitionInterface'); 276 $entity_type_storage_definition->expects($this->once()) 277 ->method('getMainPropertyName') 278 ->will($this->returnValue('name')); 279 280 $entity_type_definition = $this->createMock('Drupal\Core\Field\FieldDefinitionInterface'); 281 $entity_type_definition->expects($this->once()) 282 ->method('getFieldStorageDefinition') 283 ->will($this->returnValue($entity_type_storage_definition)); 284 285 $base_definitions = [ 286 'test_type' => $entity_type_definition, 287 ]; 288 289 $this->entityTypeManager->expects($this->at(0)) 290 ->method('getDefinition') 291 ->with('test') 292 ->will($this->returnValue($entity_type)); 293 $this->entityFieldManager->expects($this->at(0)) 294 ->method('getBaseFieldDefinitions') 295 ->with('test') 296 ->will($this->returnValue($base_definitions)); 297 298 $entity_query_mock = $this->createMock('Drupal\Core\Entity\Query\QueryInterface'); 299 $entity_query_mock->expects($this->once()) 300 ->method('execute') 301 ->will($this->returnValue(['test_bundle_other' => 'test_bundle_other'])); 302 303 $entity_type_storage = $this->createMock('Drupal\Core\Entity\EntityStorageInterface'); 304 $entity_type_storage->expects($this->once()) 305 ->method('getQuery') 306 ->will($this->returnValue($entity_query_mock)); 307 308 $this->entityTypeManager->expects($this->at(1)) 309 ->method('getStorage') 310 ->with('test_bundle') 311 ->will($this->returnValue($entity_type_storage)); 312 313 $this->expectException(UnexpectedValueException::class); 314 $this->entityNormalizer->denormalize($test_data, 'Drupal\Core\Entity\ContentEntityBase', NULL, ['entity_type' => 'test']); 315 } 316 317 /** 318 * Tests the denormalize method with no bundle defined. 319 * 320 * @covers ::denormalize 321 */ 322 public function testDenormalizeWithNoBundle() { 323 $test_data = [ 324 'key_1' => 'value_1', 325 'key_2' => 'value_2', 326 ]; 327 328 $entity_type = $this->createMock('Drupal\Core\Entity\EntityTypeInterface'); 329 $entity_type->expects($this->once()) 330 ->method('entityClassImplements') 331 ->with(FieldableEntityInterface::class) 332 ->willReturn(TRUE); 333 $entity_type->expects($this->once()) 334 ->method('hasKey') 335 ->with('bundle') 336 ->will($this->returnValue(FALSE)); 337 $entity_type->expects($this->never()) 338 ->method('getKey'); 339 340 $this->entityTypeManager->expects($this->once()) 341 ->method('getDefinition') 342 ->with('test') 343 ->will($this->returnValue($entity_type)); 344 345 $key_1 = $this->createMock(FieldItemListInterface::class); 346 $key_2 = $this->createMock(FieldItemListInterface::class); 347 348 $entity = $this->createMock(FieldableEntityInterface::class); 349 $entity->expects($this->at(0)) 350 ->method('get') 351 ->with('key_1') 352 ->willReturn($key_1); 353 $entity->expects($this->at(1)) 354 ->method('get') 355 ->with('key_2') 356 ->willReturn($key_2); 357 358 $storage = $this->createMock('Drupal\Core\Entity\EntityStorageInterface'); 359 $storage->expects($this->once()) 360 ->method('create') 361 ->with([]) 362 ->will($this->returnValue($entity)); 363 364 $this->entityTypeManager->expects($this->once()) 365 ->method('getStorage') 366 ->with('test') 367 ->will($this->returnValue($storage)); 368 369 $this->entityFieldManager->expects($this->never()) 370 ->method('getBaseFieldDefinitions'); 371 372 // Setup expectations for the serializer. This will be called for each field 373 // item. 374 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\Serializer') 375 ->disableOriginalConstructor() 376 ->setMethods(['denormalize']) 377 ->getMock(); 378 $serializer->expects($this->at(0)) 379 ->method('denormalize') 380 ->with('value_1', get_class($key_1), NULL, ['target_instance' => $key_1, 'entity_type' => 'test']); 381 $serializer->expects($this->at(1)) 382 ->method('denormalize') 383 ->with('value_2', get_class($key_2), NULL, ['target_instance' => $key_2, 'entity_type' => 'test']); 384 385 $this->entityNormalizer->setSerializer($serializer); 386 387 $this->assertNotNull($this->entityNormalizer->denormalize($test_data, 'Drupal\Core\Entity\ContentEntityBase', NULL, ['entity_type' => 'test'])); 388 } 389 390 /** 391 * Tests the denormalize method with no bundle defined. 392 * 393 * @covers ::denormalize 394 */ 395 public function testDenormalizeWithNoFieldableEntityType() { 396 $test_data = [ 397 'key_1' => 'value_1', 398 'key_2' => 'value_2', 399 ]; 400 401 $entity_type = $this->createMock('Drupal\Core\Entity\EntityTypeInterface'); 402 $entity_type->expects($this->once()) 403 ->method('entityClassImplements') 404 ->with(FieldableEntityInterface::class) 405 ->willReturn(FALSE); 406 407 $entity_type->expects($this->never()) 408 ->method('getKey'); 409 410 $this->entityTypeManager->expects($this->once()) 411 ->method('getDefinition') 412 ->with('test') 413 ->will($this->returnValue($entity_type)); 414 415 $storage = $this->createMock('Drupal\Core\Entity\EntityStorageInterface'); 416 $storage->expects($this->once()) 417 ->method('create') 418 ->with($test_data) 419 ->will($this->returnValue($this->createMock('Drupal\Core\Entity\EntityInterface'))); 420 421 $this->entityTypeManager->expects($this->once()) 422 ->method('getStorage') 423 ->with('test') 424 ->will($this->returnValue($storage)); 425 426 $this->entityFieldManager->expects($this->never()) 427 ->method('getBaseFieldDefinitions'); 428 429 $this->assertNotNull($this->entityNormalizer->denormalize($test_data, 'Drupal\Core\Entity\ContentEntityBase', NULL, ['entity_type' => 'test'])); 430 } 431 432} 433