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',
226 '_layout_builder_access' => 'view',
230 'section_storage' => ['layout_builder_tempstore' => TRUE],
231 'with_string_id' => ['type' => 'entity:with_string_id'],
233 '_layout_builder' => TRUE,
236 'layout_builder.overrides.with_string_id.save' => new Route(
237 '/entity/{entity}/layout/save',
239 'entity_type_id' => 'with_string_id',
240 'section_storage_type' => 'overrides',
241 'section_storage' => '',
242 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
245 '_has_layout_section' => 'true',
246 '_layout_builder_access' => 'view',
250 'section_storage' => ['layout_builder_tempstore' => TRUE],
251 'with_string_id' => ['type' => 'entity:with_string_id'],
253 '_layout_builder' => TRUE,
256 'layout_builder.overrides.with_string_id.cancel' => new Route(
257 '/entity/{entity}/layout/cancel',
259 'entity_type_id' => 'with_string_id',
260 'section_storage_type' => 'overrides',
261 'section_storage' => '',
262 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
265 '_has_layout_section' => 'true',
266 '_layout_builder_access' => 'view',
270 'section_storage' => ['layout_builder_tempstore' => TRUE],
271 'with_string_id' => ['type' => 'entity:with_string_id'],
273 '_layout_builder' => TRUE,
276 'layout_builder.overrides.with_string_id.revert' => new Route(
277 '/entity/{entity}/layout/revert',
279 'entity_type_id' => 'with_string_id',
280 'section_storage_type' => 'overrides',
281 'section_storage' => '',
282 '_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
285 '_has_layout_section' => 'true',
286 '_layout_builder_access' => 'view',
290 'section_storage' => ['layout_builder_tempstore' => TRUE],
291 'with_string_id' => ['type' => 'entity:with_string_id'],
293 '_layout_builder' => TRUE,
296 'layout_builder.overrides.with_integer_id.view' => new Route(
297 '/entity/{entity}/layout',
299 'entity_type_id' => 'with_integer_id',
300 'section_storage_type' => 'overrides',
301 'section_storage' => '',
302 'is_rebuilding' => FALSE,
303 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::layout',
304 '_title_callback' => '\Drupal\layout_builder\Controller\LayoutBuilderController::title',
307 '_has_layout_section' => 'true',
308 '_layout_builder_access' => 'view',
309 'with_integer_id' => '\d+',
313 'section_storage' => ['layout_builder_tempstore' => TRUE],
314 'with_integer_id' => ['type' => 'entity:with_integer_id'],
316 '_layout_builder' => TRUE,
319 'layout_builder.overrides.with_integer_id.save' => new Route(
320 '/entity/{entity}/layout/save',
322 'entity_type_id' => 'with_integer_id',
323 'section_storage_type' => 'overrides',
324 'section_storage' => '',
325 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::saveLayout',
328 '_has_layout_section' => 'true',
329 '_layout_builder_access' => 'view',
330 'with_integer_id' => '\d+',
334 'section_storage' => ['layout_builder_tempstore' => TRUE],
335 'with_integer_id' => ['type' => 'entity:with_integer_id'],
337 '_layout_builder' => TRUE,
340 'layout_builder.overrides.with_integer_id.cancel' => new Route(
341 '/entity/{entity}/layout/cancel',
343 'entity_type_id' => 'with_integer_id',
344 'section_storage_type' => 'overrides',
345 'section_storage' => '',
346 '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::cancelLayout',
349 '_has_layout_section' => 'true',
350 '_layout_builder_access' => 'view',
351 'with_integer_id' => '\d+',
355 'section_storage' => ['layout_builder_tempstore' => TRUE],
356 'with_integer_id' => ['type' => 'entity:with_integer_id'],
358 '_layout_builder' => TRUE,
361 'layout_builder.overrides.with_integer_id.revert' => new Route(
362 '/entity/{entity}/layout/revert',
364 'entity_type_id' => 'with_integer_id',
365 'section_storage_type' => 'overrides',
366 'section_storage' => '',
367 '_form' => '\Drupal\layout_builder\Form\RevertOverridesForm',
370 '_has_layout_section' => 'true',
371 '_layout_builder_access' => 'view',
372 'with_integer_id' => '\d+',
376 'section_storage' => ['layout_builder_tempstore' => TRUE],
377 'with_integer_id' => ['type' => 'entity:with_integer_id'],
379 '_layout_builder' => TRUE,
384 $collection = new RouteCollection();
385 $this->plugin->buildRoutes($collection);
386 $this->assertEquals($expected, $collection->all());
387 $this->assertSame(array_keys($expected), array_keys($collection->all()));