3 namespace Drupal\Tests\layout_builder\Unit;
5 use Drupal\Core\Entity\EntityFieldManagerInterface;
6 use Drupal\Core\Entity\EntityStorageInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Entity\EntityTypeManagerInterface;
9 use Drupal\Core\Entity\FieldableEntityInterface;
10 use Drupal\Core\Field\FieldStorageDefinitionInterface;
11 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
12 use Drupal\layout_builder\SectionStorage\SectionStorageDefinition;
13 use Drupal\Tests\UnitTestCase;
14 use Prophecy\Argument;
15 use Symfony\Component\Routing\Route;
16 use Symfony\Component\Routing\RouteCollection;
19 * @coversDefaultClass \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage
21 * @group layout_builder
23 class OverridesSectionStorageTest extends UnitTestCase {
28 * @var \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage
33 * The entity type manager.
35 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
37 protected $entityTypeManager;
40 * The entity field manager.
42 * @var \Drupal\Core\Entity\EntityFieldManagerInterface
44 protected $entityFieldManager;
49 protected function setUp() {
52 $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
53 $this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class);
55 $definition = new SectionStorageDefinition([
57 'class' => OverridesSectionStorage::class,
59 $this->plugin = new OverridesSectionStorage([], 'overrides', $definition, $this->entityTypeManager->reveal(), $this->entityFieldManager->reveal());
63 * @covers ::extractIdFromRoute
65 * @dataProvider providerTestExtractIdFromRoute
67 public function testExtractIdFromRoute($expected, $value, array $defaults) {
68 $result = $this->plugin->extractIdFromRoute($value, [], 'the_parameter_name', $defaults);
69 $this->assertSame($expected, $result);
73 * Provides data for ::testExtractIdFromRoute().
75 public function providerTestExtractIdFromRoute() {
77 $data['with value, with layout'] = [
78 'my_entity_type.entity_with_layout',
79 'my_entity_type.entity_with_layout',
82 $data['with value, without layout'] = [
87 $data['empty value, populated defaults'] = [
88 'my_entity_type.entity_with_layout',
91 'entity_type_id' => 'my_entity_type',
92 'my_entity_type' => 'entity_with_layout',
95 $data['empty value, empty defaults'] = [
104 * @covers ::getSectionListFromId
106 * @dataProvider providerTestGetSectionListFromId
108 public function testGetSectionListFromId($success, $expected_entity_type_id, $id) {
109 $defaults['the_parameter_name'] = $id;
111 if ($expected_entity_type_id) {
112 $entity_storage = $this->prophesize(EntityStorageInterface::class);
114 $entity_without_layout = $this->prophesize(FieldableEntityInterface::class);
115 $entity_without_layout->hasField('layout_builder__layout')->willReturn(FALSE);
116 $entity_without_layout->get('layout_builder__layout')->shouldNotBeCalled();
117 $entity_storage->load('entity_without_layout')->willReturn($entity_without_layout->reveal());
119 $entity_with_layout = $this->prophesize(FieldableEntityInterface::class);
120 $entity_with_layout->hasField('layout_builder__layout')->willReturn(TRUE);
121 $entity_with_layout->get('layout_builder__layout')->willReturn('the_return_value');
122 $entity_storage->load('entity_with_layout')->willReturn($entity_with_layout->reveal());
124 $this->entityTypeManager->getStorage($expected_entity_type_id)->willReturn($entity_storage->reveal());
127 $this->entityTypeManager->getStorage(Argument::any())->shouldNotBeCalled();
131 $this->setExpectedException(\InvalidArgumentException::class);
134 $result = $this->plugin->getSectionListFromId($id);
136 $this->assertEquals('the_return_value', $result);
141 * Provides data for ::testGetSectionListFromId().
143 public function providerTestGetSectionListFromId() {
145 $data['with value, with layout'] = [
148 'my_entity_type.entity_with_layout',
150 $data['with value, without layout'] = [
153 'my_entity_type.entity_without_layout',
155 $data['empty value, empty defaults'] = [
164 * @covers ::buildRoutes
165 * @covers ::hasIntegerId
166 * @covers ::getEntityTypes
168 public function testBuildRoutes() {
171 $not_fieldable = $this->prophesize(EntityTypeInterface::class);
172 $not_fieldable->entityClassImplements(FieldableEntityInterface::class)->willReturn(FALSE);
173 $entity_types['not_fieldable'] = $not_fieldable->reveal();
175 $no_view_builder = $this->prophesize(EntityTypeInterface::class);
176 $no_view_builder->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
177 $no_view_builder->hasViewBuilderClass()->willReturn(FALSE);
178 $entity_types['no_view_builder'] = $no_view_builder->reveal();
180 $no_canonical_link = $this->prophesize(EntityTypeInterface::class);
181 $no_canonical_link->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
182 $no_canonical_link->hasViewBuilderClass()->willReturn(TRUE);
183 $no_canonical_link->hasLinkTemplate('canonical')->willReturn(FALSE);
184 $entity_types['no_canonical_link'] = $no_canonical_link->reveal();
185 $this->entityFieldManager->getFieldStorageDefinitions('no_canonical_link')->shouldNotBeCalled();
187 $with_string_id = $this->prophesize(EntityTypeInterface::class);
188 $with_string_id->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
189 $with_string_id->hasViewBuilderClass()->willReturn(TRUE);
190 $with_string_id->hasLinkTemplate('canonical')->willReturn(TRUE);
191 $with_string_id->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
192 $with_string_id->id()->willReturn('with_string_id');
193 $with_string_id->getKey('id')->willReturn('id');
194 $entity_types['with_string_id'] = $with_string_id->reveal();
195 $string_id = $this->prophesize(FieldStorageDefinitionInterface::class);
196 $string_id->getType()->willReturn('string');
197 $this->entityFieldManager->getFieldStorageDefinitions('with_string_id')->willReturn(['id' => $string_id->reveal()]);
199 $with_integer_id = $this->prophesize(EntityTypeInterface::class);
200 $with_integer_id->entityClassImplements(FieldableEntityInterface::class)->willReturn(TRUE);
201 $with_integer_id->hasViewBuilderClass()->willReturn(TRUE);
202 $with_integer_id->hasLinkTemplate('canonical')->willReturn(TRUE);
203 $with_integer_id->getLinkTemplate('canonical')->willReturn('/entity/{entity}');
204 $with_integer_id->id()->willReturn('with_integer_id');
205 $with_integer_id->getKey('id')->willReturn('id');
206 $entity_types['with_integer_id'] = $with_integer_id->reveal();
207 $integer_id = $this->prophesize(FieldStorageDefinitionInterface::class);
208 $integer_id->getType()->willReturn('integer');
209 $this->entityFieldManager->getFieldStorageDefinitions('with_integer_id')->willReturn(['id' => $integer_id->reveal()]);
211 $this->entityTypeManager->getDefinitions()->willReturn($entity_types);
214 'layout_builder.overrides.with_string_id.view' => new Route(
215 '/entity/{entity}/layout',
217 'entity_type_id' => 'with_string_id',
218 'section_storage_type' => 'overrides',
219 'section_storage' => '',
220 'is_rebuilding' => FALSE,
221 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
222 '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
225 '_has_layout_section' => 'true',
229 'section_storage' => ['layout_builder_tempstore' => TRUE],
230 'with_string_id' => ['type' => 'entity:with_string_id'],
232 '_layout_builder' => TRUE,
235 'layout_builder.overrides.with_string_id.save' => new Route(
236 '/entity/{entity}/layout/save',
238 'entity_type_id' => 'with_string_id',
239 'section_storage_type' => 'overrides',
240 'section_storage' => '',
241 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
244 '_has_layout_section' => 'true',
248 'section_storage' => ['layout_builder_tempstore' => TRUE],
249 'with_string_id' => ['type' => 'entity:with_string_id'],
251 '_layout_builder' => TRUE,
254 'layout_builder.overrides.with_string_id.cancel' => new Route(
255 '/entity/{entity}/layout/cancel',
257 'entity_type_id' => 'with_string_id',
258 'section_storage_type' => 'overrides',
259 'section_storage' => '',
260 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
263 '_has_layout_section' => 'true',
267 'section_storage' => ['layout_builder_tempstore' => TRUE],
268 'with_string_id' => ['type' => 'entity:with_string_id'],
270 '_layout_builder' => TRUE,
273 'layout_builder.overrides.with_string_id.revert' => new Route(
274 '/entity/{entity}/layout/revert',
276 'entity_type_id' => 'with_string_id',
277 'section_storage_type' => 'overrides',
278 'section_storage' => '',
279 '_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
282 '_has_layout_section' => 'true',
286 'section_storage' => ['layout_builder_tempstore' => TRUE],
287 'with_string_id' => ['type' => 'entity:with_string_id'],
289 '_layout_builder' => TRUE,
292 'layout_builder.overrides.with_integer_id.view' => new Route(
293 '/entity/{entity}/layout',
295 'entity_type_id' => 'with_integer_id',
296 'section_storage_type' => 'overrides',
297 'section_storage' => '',
298 'is_rebuilding' => FALSE,
299 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
300 '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
303 '_has_layout_section' => 'true',
304 'with_integer_id' => '\d+',
308 'section_storage' => ['layout_builder_tempstore' => TRUE],
309 'with_integer_id' => ['type' => 'entity:with_integer_id'],
311 '_layout_builder' => TRUE,
314 'layout_builder.overrides.with_integer_id.save' => new Route(
315 '/entity/{entity}/layout/save',
317 'entity_type_id' => 'with_integer_id',
318 'section_storage_type' => 'overrides',
319 'section_storage' => '',
320 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
323 '_has_layout_section' => 'true',
324 'with_integer_id' => '\d+',
328 'section_storage' => ['layout_builder_tempstore' => TRUE],
329 'with_integer_id' => ['type' => 'entity:with_integer_id'],
331 '_layout_builder' => TRUE,
334 'layout_builder.overrides.with_integer_id.cancel' => new Route(
335 '/entity/{entity}/layout/cancel',
337 'entity_type_id' => 'with_integer_id',
338 'section_storage_type' => 'overrides',
339 'section_storage' => '',
340 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
343 '_has_layout_section' => 'true',
344 'with_integer_id' => '\d+',
348 'section_storage' => ['layout_builder_tempstore' => TRUE],
349 'with_integer_id' => ['type' => 'entity:with_integer_id'],
351 '_layout_builder' => TRUE,
354 'layout_builder.overrides.with_integer_id.revert' => new Route(
355 '/entity/{entity}/layout/revert',
357 'entity_type_id' => 'with_integer_id',
358 'section_storage_type' => 'overrides',
359 'section_storage' => '',
360 '_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
363 '_has_layout_section' => 'true',
364 'with_integer_id' => '\d+',
368 'section_storage' => ['layout_builder_tempstore' => TRUE],
369 'with_integer_id' => ['type' => 'entity:with_integer_id'],
371 '_layout_builder' => TRUE,
376 $collection = new RouteCollection();
377 $this->plugin->buildRoutes($collection);
378 $this->assertEquals($expected, $collection->all());
379 $this->assertSame(array_keys($expected), array_keys($collection->all()));