Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / serialization / tests / src / Unit / Normalizer / EntityReferenceFieldItemNormalizerTest.php
1 <?php
2
3 namespace Drupal\Tests\serialization\Unit\Normalizer;
4
5 use Drupal\Core\Entity\EntityInterface;
6 use Drupal\Core\Field\FieldDefinitionInterface;
7 use Drupal\Core\TypedData\TypedDataInterface;
8 use Drupal\Core\Entity\EntityRepositoryInterface;
9 use Drupal\Core\Entity\FieldableEntityInterface;
10 use Drupal\Core\Field\FieldItemInterface;
11 use Drupal\Core\Field\FieldItemListInterface;
12 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
13 use Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer;
14 use Drupal\Tests\UnitTestCase;
15 use Prophecy\Argument;
16 use Symfony\Component\Serializer\Exception\InvalidArgumentException;
17 use Symfony\Component\Serializer\Exception\UnexpectedValueException;
18 use Symfony\Component\Serializer\Serializer;
19
20 /**
21  * @coversDefaultClass \Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer
22  * @group serialization
23  */
24 class EntityReferenceFieldItemNormalizerTest extends UnitTestCase {
25
26   /**
27    * The mock serializer.
28    *
29    * @var \Symfony\Component\Serializer\SerializerInterface|\Prophecy\Prophecy\ObjectProphecy
30    */
31   protected $serializer;
32
33   /**
34    * The normalizer under test.
35    *
36    * @var \Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer
37    */
38   protected $normalizer;
39
40   /**
41    * The mock field item.
42    *
43    * @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem|\Prophecy\Prophecy\ObjectProphecy
44    */
45   protected $fieldItem;
46
47   /**
48    * The mock entity repository.
49    *
50    * @var \Drupal\Core\Entity\EntityRepositoryInterface|\Prophecy\Prophecy\ObjectProphecy
51    */
52   protected $entityRepository;
53
54   /**
55    * The mock field definition.
56    *
57    * @var \Drupal\Core\Field\FieldDefinitionInterface|\Prophecy\Prophecy\ObjectProphecy
58    */
59   protected $fieldDefinition;
60
61   /**
62    * {@inheritdoc}
63    */
64   protected function setUp() {
65     $this->entityRepository = $this->prophesize(EntityRepositoryInterface::class);
66     $this->normalizer = new EntityReferenceFieldItemNormalizer($this->entityRepository->reveal());
67
68     $this->serializer = $this->prophesize(Serializer::class);
69     // Set up the serializer to return an entity property.
70     $this->serializer->normalize(Argument::cetera())
71       ->willReturn(['value' => 'test']);
72
73     $this->normalizer->setSerializer($this->serializer->reveal());
74
75     $this->fieldItem = $this->prophesize(EntityReferenceItem::class);
76     $this->fieldItem->getIterator()
77       ->willReturn(new \ArrayIterator(['target_id' => []]));
78
79     $this->fieldDefinition = $this->prophesize(FieldDefinitionInterface::class);
80
81   }
82
83   /**
84    * @covers ::supportsNormalization
85    */
86   public function testSupportsNormalization() {
87     $this->assertTrue($this->normalizer->supportsNormalization($this->fieldItem->reveal()));
88     $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
89   }
90
91   /**
92    * @covers ::supportsDenormalization
93    */
94   public function testSupportsDenormalization() {
95     $this->assertTrue($this->normalizer->supportsDenormalization([], EntityReferenceItem::class));
96     $this->assertFalse($this->normalizer->supportsDenormalization([], FieldItemInterface::class));
97   }
98
99   /**
100    * @covers ::normalize
101    */
102   public function testNormalize() {
103     $test_url = '/test/100';
104
105     $entity = $this->prophesize(EntityInterface::class);
106     $entity->url('canonical')
107       ->willReturn($test_url)
108       ->shouldBeCalled();
109     $entity->uuid()
110       ->willReturn('080e3add-f9d5-41ac-9821-eea55b7b42fb')
111       ->shouldBeCalled();
112     $entity->getEntityTypeId()
113       ->willReturn('test_type')
114       ->shouldBeCalled();
115
116     $entity_reference = $this->prophesize(TypedDataInterface::class);
117     $entity_reference->getValue()
118       ->willReturn($entity->reveal())
119       ->shouldBeCalled();
120
121     $this->fieldItem->get('entity')
122       ->willReturn($entity_reference)
123       ->shouldBeCalled();
124
125     $normalized = $this->normalizer->normalize($this->fieldItem->reveal());
126
127     $expected = [
128       'target_id' => ['value' => 'test'],
129       'target_type' => 'test_type',
130       'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
131       'url' => $test_url,
132     ];
133     $this->assertSame($expected, $normalized);
134   }
135
136   /**
137    * @covers ::normalize
138    */
139   public function testNormalizeWithNoEntity() {
140     $entity_reference = $this->prophesize(TypedDataInterface::class);
141     $entity_reference->getValue()
142       ->willReturn(NULL)
143       ->shouldBeCalled();
144
145     $this->fieldItem->get('entity')
146       ->willReturn($entity_reference->reveal())
147       ->shouldBeCalled();
148
149     $normalized = $this->normalizer->normalize($this->fieldItem->reveal());
150
151     $expected = [
152       'target_id' => ['value' => 'test'],
153     ];
154     $this->assertSame($expected, $normalized);
155   }
156
157   /**
158    * @covers ::denormalize
159    */
160   public function testDenormalizeWithTypeAndUuid() {
161     $data = [
162       'target_id' => ['value' => 'test'],
163       'target_type' => 'test_type',
164       'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
165     ];
166
167     $entity = $this->prophesize(FieldableEntityInterface::class);
168     $entity->id()
169       ->willReturn('test')
170       ->shouldBeCalled();
171     $this->entityRepository
172       ->loadEntityByUuid($data['target_type'], $data['target_uuid'])
173       ->willReturn($entity)
174       ->shouldBeCalled();
175
176     $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled();
177
178     $this->assertDenormalize($data);
179   }
180
181   /**
182    * @covers ::denormalize
183    */
184   public function testDenormalizeWithUuidWithoutType() {
185     $data = [
186       'target_id' => ['value' => 'test'],
187       'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
188     ];
189
190     $entity = $this->prophesize(FieldableEntityInterface::class);
191     $entity->id()
192       ->willReturn('test')
193       ->shouldBeCalled();
194     $this->entityRepository
195       ->loadEntityByUuid('test_type', $data['target_uuid'])
196       ->willReturn($entity)
197       ->shouldBeCalled();
198
199     $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled();
200
201     $this->assertDenormalize($data);
202   }
203
204   /**
205    * @covers ::denormalize
206    */
207   public function testDenormalizeWithUuidWithIncorrectType() {
208     $this->setExpectedException(UnexpectedValueException::class, 'The field "field_reference" property "target_type" must be set to "test_type" or omitted.');
209
210     $data = [
211       'target_id' => ['value' => 'test'],
212       'target_type' => 'wrong_type',
213       'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb',
214     ];
215
216     $this->fieldDefinition
217       ->getName()
218       ->willReturn('field_reference')
219       ->shouldBeCalled();
220
221     $this->assertDenormalize($data);
222   }
223
224   /**
225    * @covers ::denormalize
226    */
227   public function testDenormalizeWithTypeWithIncorrectUuid() {
228     $this->setExpectedException(InvalidArgumentException::class, 'No "test_type" entity found with UUID "unique-but-none-non-existent" for field "field_reference"');
229
230     $data = [
231       'target_id' => ['value' => 'test'],
232       'target_type' => 'test_type',
233       'target_uuid' => 'unique-but-none-non-existent',
234     ];
235     $this->entityRepository
236       ->loadEntityByUuid($data['target_type'], $data['target_uuid'])
237       ->willReturn(NULL)
238       ->shouldBeCalled();
239     $this->fieldItem
240       ->getName()
241       ->willReturn('field_reference')
242       ->shouldBeCalled();
243
244     $this->assertDenormalize($data);
245   }
246
247   /**
248    * @covers ::denormalize
249    */
250   public function testDenormalizeWithEmtpyUuid() {
251     $this->setExpectedException(InvalidArgumentException::class, 'If provided "target_uuid" cannot be empty for field "test_type".');
252
253     $data = [
254       'target_id' => ['value' => 'test'],
255       'target_type' => 'test_type',
256       'target_uuid' => '',
257     ];
258     $this->fieldItem
259       ->getName()
260       ->willReturn('field_reference')
261       ->shouldBeCalled();
262
263     $this->assertDenormalize($data);
264   }
265
266   /**
267    * @covers ::denormalize
268    */
269   public function testDenormalizeWithId() {
270     $data = [
271       'target_id' => ['value' => 'test'],
272     ];
273     $this->fieldItem->setValue($data)->shouldBeCalled();
274
275     $this->assertDenormalize($data);
276   }
277
278   /**
279    * Asserts denormalization process is correct for give data.
280    *
281    * @param array $data
282    *   The data to denormalize.
283    */
284   protected function assertDenormalize(array $data) {
285     $this->fieldItem->getParent()
286       ->willReturn($this->prophesize(FieldItemListInterface::class)->reveal());
287     $this->fieldItem->getFieldDefinition()->willReturn($this->fieldDefinition->reveal());
288     if (!empty($data['target_uuid'])) {
289       $this->fieldDefinition
290         ->getSetting('target_type')
291         ->willReturn('test_type')
292         ->shouldBeCalled();
293     }
294
295     $context = ['target_instance' => $this->fieldItem->reveal()];
296     $denormalized = $this->normalizer->denormalize($data, EntityReferenceItem::class, 'json', $context);
297     $this->assertSame($context['target_instance'], $denormalized);
298   }
299
300 }