3 namespace Drupal\Tests\views\Unit;
5 use Drupal\Component\Plugin\PluginManagerInterface;
6 use Drupal\Core\DependencyInjection\ContainerBuilder;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
9 use Drupal\Tests\UnitTestCase;
10 use Drupal\views\Entity\View;
11 use Drupal\views\Plugin\views\cache\CachePluginBase;
12 use Drupal\views\Plugin\views\cache\None as NoneCache;
13 use Drupal\views\Plugin\views\pager\None as NonePager;
14 use Drupal\views\Plugin\views\query\QueryPluginBase;
15 use Drupal\views\ViewExecutable;
16 use Symfony\Component\Routing\Route;
19 * @coversDefaultClass \Drupal\views\ViewExecutable
22 class ViewExecutableTest extends UnitTestCase {
25 * Indicates that a display is enabled.
27 const DISPLAY_ENABLED = TRUE;
30 * Indicates that a display is disabled.
32 const DISPLAY_DISABLED = FALSE;
35 * A mocked display collection.
37 * @var \Drupal\views\DisplayPluginCollection|\PHPUnit_Framework_MockObject_MockObject
39 protected $displayHandlers;
42 * The mocked view executable.
44 * @var \Drupal\views\ViewExecutableFactory|\PHPUnit_Framework_MockObject_MockObject
46 protected $viewExecutableFactory;
49 * The tested view executable.
51 * @var \Drupal\views\ViewExecutable
53 protected $executable;
56 * The mocked view entity.
58 * @var \Drupal\views\ViewEntityInterface|\PHPUnit_Framework_MockObject_MockObject
65 * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
70 * The mocked views data.
72 * @var \Drupal\views\ViewsData|\PHPUnit_Framework_MockObject_MockObject
77 * The mocked display handler.
79 * @var \Drupal\views\Plugin\views\display\DisplayPluginInterface|\PHPUnit_Framework_MockObject_MockObject
81 protected $displayHandler;
84 * The mocked route provider.
86 * @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
88 protected $routeProvider;
91 * The mocked none cache plugin.
93 * @var \Drupal\views\Plugin\views\cache\None|\PHPUnit_Framework_MockObject_MockObject
98 * The mocked cache plugin that returns a successful result.
100 * @var \Drupal\views\Plugin\views\cache\None|\PHPUnit_Framework_MockObject_MockObject
102 protected $successCache;
107 protected function setUp() {
110 $this->view = $this->getMock('Drupal\views\ViewEntityInterface');
111 $this->user = $this->getMock('Drupal\Core\Session\AccountInterface');
112 $this->viewsData = $this->getMockBuilder('Drupal\views\ViewsData')
113 ->disableOriginalConstructor()
115 $this->displayHandler = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayRouterInterface')
116 ->disableOriginalConstructor()
118 $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
119 $this->displayHandlers = $this->getMockBuilder('Drupal\views\DisplayPluginCollection')
120 ->disableOriginalConstructor()
123 $this->executable = new ViewExecutable($this->view, $this->user, $this->viewsData, $this->routeProvider);
124 $this->executable->display_handler = $this->displayHandler;
125 $this->executable->displayHandlers = $this->displayHandlers;
127 $this->viewExecutableFactory = $this->getMockBuilder('Drupal\views\ViewExecutableFactory')
128 ->disableOriginalConstructor()
131 $module_handler = $this->getMockBuilder(ModuleHandlerInterface::class)
134 $this->noneCache = $this->getMockBuilder(NoneCache::class)
135 ->disableOriginalConstructor()
138 $success_cache = $this->prophesize(CachePluginBase::class);
139 $success_cache->cacheGet('results')->willReturn(TRUE);
140 $this->successCache = $success_cache->reveal();
142 $cache_manager = $this->prophesize(PluginManagerInterface::class);
143 $cache_manager->createInstance('none')->willReturn($this->noneCache);
145 $translation = $this->getStringTranslationStub();
146 $container = new ContainerBuilder();
147 $container->set('string_translation', $translation);
148 $container->set('views.executable', $this->viewExecutableFactory);
149 $container->set('module_handler', $module_handler);
150 $container->set('plugin.manager.views.cache', $cache_manager->reveal());
151 \Drupal::setContainer($container);
157 public function testGetUrlWithOverriddenUrl() {
158 $url = Url::fromRoute('example');
159 $this->executable->override_url = $url;
161 $this->assertSame($url, $this->executable->getUrl());
167 public function testGetUrlWithPathNoPlaceholders() {
168 $this->displayHandler->expects($this->any())
169 ->method('getRoutedDisplay')
170 ->willReturn($this->displayHandler);
171 $this->displayHandlers->expects($this->any())
173 ->willReturn($this->displayHandler);
174 $this->displayHandler->expects($this->any())
175 ->method('getUrlInfo')
176 ->willReturn(Url::fromRoute('views.test.page_1'));
177 $this->displayHandler->expects($this->any())
179 ->willReturn('test-path');
181 $this->assertEquals(Url::fromRoute('views.test.page_1'), $this->executable->getUrl());
187 public function testGetUrlWithoutRouterDisplay() {
188 $this->displayHandler = $this->getMock('Drupal\views\Plugin\views\display\DisplayPluginInterface');
189 $this->displayHandlers->expects($this->any())
191 ->willReturn($this->displayHandler);
192 $this->executable->display_handler = $this->displayHandler;
194 $this->setExpectedException(\InvalidArgumentException::class);
195 $this->executable->getUrl();
201 public function testGetUrlWithPlaceholdersAndArgs() {
202 $this->displayHandler->expects($this->any())
203 ->method('getRoutedDisplay')
204 ->willReturn($this->displayHandler);
205 $this->displayHandlers->expects($this->any())
207 ->willReturn($this->displayHandler);
208 $this->displayHandler->expects($this->any())
209 ->method('getUrlInfo')
210 ->willReturn(Url::fromRoute('views.test.page_1'));
211 $this->displayHandler->expects($this->any())
213 ->willReturn('test-path/%');
215 $route = new Route('/test-path/{arg_0}');
216 $this->routeProvider->expects($this->any())
217 ->method('getRouteByName')
218 ->with('views.test.page_1')
219 ->willReturn($route);
221 $this->assertEquals(Url::fromRoute('views.test.page_1', ['arg_0' => 'test']), $this->executable->getUrl(['test']));
227 public function testGetUrlWithPlaceholdersAndWithoutArgs() {
228 $this->displayHandler->expects($this->any())
229 ->method('getRoutedDisplay')
230 ->willReturn($this->displayHandler);
231 $this->displayHandlers->expects($this->any())
233 ->willReturn($this->displayHandler);
234 $this->displayHandler->expects($this->any())
235 ->method('getUrlInfo')
236 ->willReturn(Url::fromRoute('views.test.page_1'));
237 $this->displayHandler->expects($this->any())
239 ->willReturn('test-path/%/%');
241 $route = new Route('/test-path/{arg_0}/{arg_1}');
242 $this->routeProvider->expects($this->any())
243 ->method('getRouteByName')
244 ->with('views.test.page_1')
245 ->willReturn($route);
247 $this->assertEquals(Url::fromRoute('views.test.page_1', ['arg_0' => '*', 'arg_1' => '*']), $this->executable->getUrl());
253 public function testGetUrlWithPlaceholdersAndWithoutArgsAndExceptionValue() {
254 $this->displayHandler->expects($this->any())
255 ->method('getRoutedDisplay')
256 ->willReturn($this->displayHandler);
257 $this->displayHandlers->expects($this->any())
259 ->willReturn($this->displayHandler);
260 $this->displayHandler->expects($this->any())
261 ->method('getUrlInfo')
262 ->willReturn(Url::fromRoute('views.test.page_1'));
263 $this->displayHandler->expects($this->any())
265 ->willReturn('test-path/%/%');
267 $route = new Route('/test-path/{arg_0}/{arg_1}');
268 $this->routeProvider->expects($this->any())
269 ->method('getRouteByName')
270 ->with('views.test.page_1')
271 ->willReturn($route);
273 $argument_handler = $this->getMockBuilder('Drupal\views\Plugin\views\argument\ArgumentPluginBase')
274 ->disableOriginalConstructor()
276 $argument_handler->options['exception']['value'] = 'exception_0';
277 $this->executable->argument['key_1'] = $argument_handler;
278 $argument_handler = $this->getMockBuilder('Drupal\views\Plugin\views\argument\ArgumentPluginBase')
279 ->disableOriginalConstructor()
281 $argument_handler->options['exception']['value'] = 'exception_1';
282 $this->executable->argument['key_2'] = $argument_handler;
284 $this->assertEquals(Url::fromRoute('views.test.page_1', ['arg_0' => 'exception_0', 'arg_1' => 'exception_1']), $this->executable->getUrl());
288 * @covers ::buildThemeFunctions
290 public function testBuildThemeFunctions() {
291 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
292 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
293 list($view, $display) = $this->setupBaseViewAndDisplay();
295 unset($view->display_handler);
297 'test_hook__test_view',
300 $this->assertEquals($expected, $view->buildThemeFunctions('test_hook'));
302 $view->display_handler = $display;
304 'test_hook__test_view__default',
305 'test_hook__default',
308 'test_hook__and_three',
309 'test_hook__test_view',
312 $this->assertEquals($expected, $view->buildThemeFunctions('test_hook'));
314 //Change the name of the display plugin and make sure that is in the array.
315 $view->display_handler->display['display_plugin'] = 'default2';
318 'test_hook__test_view__default',
319 'test_hook__default',
322 'test_hook__and_three',
323 'test_hook__test_view__default2',
324 'test_hook__default2',
325 'test_hook__test_view',
328 $this->assertEquals($expected, $view->buildThemeFunctions('test_hook'));
332 * @covers ::generateHandlerId
334 public function testGenerateHandlerId() {
335 // Test the generateHandlerId() method.
336 $test_ids = ['test' => 'test', 'test_1' => 'test_1'];
337 $this->assertEquals(ViewExecutable::generateHandlerId('new', $test_ids), 'new');
338 $this->assertEquals(ViewExecutable::generateHandlerId('test', $test_ids), 'test_2');
342 * @covers ::addHandler
344 public function testAddHandler() {
345 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
346 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
347 list($view, $display) = $this->setupBaseViewAndDisplay();
350 $views_data['test_field'] = [
351 'field' => ['id' => 'standard'],
352 'filter' => ['id' => 'standard'],
353 'argument' => ['id' => 'standard'],
354 'sort' => ['id' => 'standard'],
357 $this->viewsData->expects($this->atLeastOnce())
359 ->with('test_entity')
360 ->willReturn($views_data);
362 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
363 $display->expects($this->atLeastOnce())
364 ->method('setOption')
365 ->with($this->callback(function($argument) {
367 }), ['test_field' => [
368 'id' => 'test_field',
369 'table' => 'test_entity',
370 'field' => 'test_field',
371 'plugin_id' => 'standard',
375 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
376 $view->addHandler('default', $handler_type, 'test_entity', 'test_field');
381 * @covers ::addHandler
383 public function testAddHandlerWithEntityField() {
384 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
385 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
386 list($view, $display) = $this->setupBaseViewAndDisplay();
389 $views_data['table']['entity type'] = 'test_entity_type';
390 $views_data['test_field'] = [
391 'entity field' => 'test_field',
392 'field' => ['id' => 'standard'],
393 'filter' => ['id' => 'standard'],
394 'argument' => ['id' => 'standard'],
395 'sort' => ['id' => 'standard'],
398 $this->viewsData->expects($this->atLeastOnce())
400 ->with('test_entity')
401 ->willReturn($views_data);
403 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
404 $display->expects($this->atLeastOnce())
405 ->method('setOption')
406 ->with($this->callback(function($argument) {
408 }), ['test_field' => [
409 'id' => 'test_field',
410 'table' => 'test_entity',
411 'field' => 'test_field',
412 'entity_type' => 'test_entity_type',
413 'entity_field' => 'test_field',
414 'plugin_id' => 'standard',
418 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
419 $view->addHandler('default', $handler_type, 'test_entity', 'test_field');
424 * @covers ::attachDisplays
426 public function testAttachDisplays() {
427 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
428 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
429 list($view, $display) = $this->setupBaseViewAndDisplay();
431 $display->expects($this->atLeastOnce())
432 ->method('acceptAttachments')
434 $display->expects($this->atLeastOnce())
435 ->method('getAttachedDisplays')
436 ->willReturn(['page_1']);
438 $cloned_view = $this->getMockBuilder('Drupal\views\ViewExecutable')
439 ->disableOriginalConstructor()
441 $this->viewExecutableFactory->expects($this->atLeastOnce())
443 ->willReturn($cloned_view);
445 $page_display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
446 ->disableOriginalConstructor()
449 $page_display->expects($this->atLeastOnce())
450 ->method('isEnabled')
453 $display_collection = $this->getMockBuilder('Drupal\views\DisplayPluginCollection')
454 ->disableOriginalConstructor()
457 $display_collection->expects($this->atLeastOnce())
460 ->willReturn($page_display);
461 $view->displayHandlers = $display_collection;
463 // Setup the expectations.
464 $page_display->expects($this->once())
466 ->with($cloned_view, 'default', $view->element);
468 $view->attachDisplays();
472 * Setups a view executable and default display.
475 * Returns the view executable and default display.
477 protected function setupBaseViewAndDisplay() {
480 'tag' => 'OnE, TWO, and three',
484 'display_plugin' => 'default',
485 'display_title' => 'Default',
490 $storage = new View($config, 'view');
491 $view = new ViewExecutable($storage, $this->user, $this->viewsData, $this->routeProvider);
492 $display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
493 ->disableOriginalConstructor()
495 $display->expects($this->any())
496 ->method('getPlugin')
497 ->with($this->equalTo('cache'))
498 ->willReturn($this->successCache);
500 $display->display = $config['display']['default'];
502 $view->current_display = 'default';
503 $view->display_handler = $display;
504 $view->displayHandlers = $this->displayHandlers;
505 $view->displayHandlers->expects($this->any())
508 ->willReturn($display);
509 $view->displayHandlers->expects($this->any())
514 foreach (array_keys($view->getHandlerTypes()) as $type) {
518 return [$view, $display];
522 * @covers ::setItemsPerPage
523 * @covers ::getItemsPerPage
525 public function testSetItemsPerPageBeforePreRender() {
526 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
527 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
528 list($view, $display) = $this->setupBaseViewAndDisplay();
530 $view->setItemsPerPage(12);
531 $this->assertEquals(12, $view->getItemsPerPage());
532 $this->assertContains('items_per_page:12', $view->element['#cache']['keys']);
536 * @covers ::setItemsPerPage
537 * @covers ::getItemsPerPage
539 public function testSetItemsPerPageDuringPreRender() {
540 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
541 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
542 list($view, $display) = $this->setupBaseViewAndDisplay();
544 $elements = &$view->element;
545 $elements['#cache'] += ['keys' => []];
546 $elements['#pre_rendered'] = TRUE;
548 $view->setItemsPerPage(12);
549 $this->assertEquals(12, $view->getItemsPerPage());
550 $this->assertNotContains('items_per_page:12', $view->element['#cache']['keys']);
554 * @covers ::setOffset
555 * @covers ::getOffset
557 public function testSetOffsetBeforePreRender() {
558 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
559 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
560 list($view, $display) = $this->setupBaseViewAndDisplay();
562 $view->setOffset(12);
563 $this->assertEquals(12, $view->getOffset());
564 $this->assertContains('offset:12', $view->element['#cache']['keys']);
568 * @covers ::setOffset
569 * @covers ::getOffset
571 public function testSetOffsetDuringPreRender() {
572 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
573 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
574 list($view, $display) = $this->setupBaseViewAndDisplay();
576 $elements = &$view->element;
577 $elements['#cache'] += ['keys' => []];
578 $elements['#pre_rendered'] = TRUE;
580 $view->setOffset(12);
581 $this->assertEquals(12, $view->getOffset());
582 $this->assertNotContains('offset:12', $view->element['#cache']['keys']);
586 * @covers ::setCurrentPage
587 * @covers ::getCurrentPage
589 public function testSetCurrentPageBeforePreRender() {
590 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
591 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
592 list($view, $display) = $this->setupBaseViewAndDisplay();
594 $view->setCurrentPage(12);
595 $this->assertEquals(12, $view->getCurrentPage());
596 $this->assertContains('page:12', $view->element['#cache']['keys']);
600 * @covers ::setCurrentPage
601 * @covers ::getCurrentPage
603 public function testSetCurrentPageDuringPreRender() {
604 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
605 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
606 list($view, $display) = $this->setupBaseViewAndDisplay();
608 $elements = &$view->element;
609 $elements['#cache'] += ['keys' => []];
610 $elements['#pre_rendered'] = TRUE;
612 $view->setCurrentPage(12);
613 $this->assertEquals(12, $view->getCurrentPage());
614 $this->assertNotContains('page:12', $view->element['#cache']['keys']);
620 public function testCacheIsIgnoredDuringPreview() {
621 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
622 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
623 list($view, $display) = $this->setupBaseViewAndDisplay();
625 // Pager needs to be set to avoid false test failures.
626 $view->pager = $this->getMockBuilder(NonePager::class)
627 ->disableOriginalConstructor()
630 $query = $this->getMockBuilder(QueryPluginBase::class)
631 ->disableOriginalConstructor()
634 $view->query = $query;
636 $view->live_preview = TRUE;
638 $this->noneCache->expects($this->once())->method('cacheGet');
639 $query->expects($this->once())->method('execute');
645 * Tests the return values for the execute() method.
647 * @param bool $display_enabled
648 * Whether the display to test should be enabled.
649 * @param bool $expected_result
650 * The expected result when calling execute().
653 * @dataProvider providerExecuteReturn
655 public function testExecuteReturn($display_enabled, $expected_result) {
656 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
657 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
658 list($view, $display) = $this->setupBaseViewAndDisplay();
660 $display->expects($this->any())
661 ->method('isEnabled')
662 ->willReturn($display_enabled);
664 // Pager needs to be set to avoid false test failures.
665 $view->pager = $this->getMockBuilder(NonePager::class)
666 ->disableOriginalConstructor()
669 $query = $this->getMockBuilder(QueryPluginBase::class)
670 ->disableOriginalConstructor()
673 $view->query = $query;
676 $this->assertEquals($expected_result, $view->execute());
680 * Provider for testExecuteReturn().
683 * An array of arrays containing the display state and expected value.
685 public function providerExecuteReturn() {
687 'enabled' => [static::DISPLAY_ENABLED, TRUE],
688 'disabled' => [static::DISPLAY_DISABLED, FALSE],