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) {
369 'id' => 'test_field',
370 'table' => 'test_entity',
371 'field' => 'test_field',
372 'plugin_id' => 'standard',
377 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
378 $view->addHandler('default', $handler_type, 'test_entity', 'test_field');
383 * @covers ::addHandler
385 public function testAddHandlerWithEntityField() {
386 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
387 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
388 list($view, $display) = $this->setupBaseViewAndDisplay();
391 $views_data['table']['entity type'] = 'test_entity_type';
392 $views_data['test_field'] = [
393 'entity field' => 'test_field',
394 'field' => ['id' => 'standard'],
395 'filter' => ['id' => 'standard'],
396 'argument' => ['id' => 'standard'],
397 'sort' => ['id' => 'standard'],
400 $this->viewsData->expects($this->atLeastOnce())
402 ->with('test_entity')
403 ->willReturn($views_data);
405 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
406 $display->expects($this->atLeastOnce())
407 ->method('setOption')
408 ->with($this->callback(function ($argument) {
412 'id' => 'test_field',
413 'table' => 'test_entity',
414 'field' => 'test_field',
415 'entity_type' => 'test_entity_type',
416 'entity_field' => 'test_field',
417 'plugin_id' => 'standard',
422 foreach (['field', 'filter', 'argument', 'sort'] as $handler_type) {
423 $view->addHandler('default', $handler_type, 'test_entity', 'test_field');
428 * @covers ::attachDisplays
430 public function testAttachDisplays() {
431 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
432 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
433 list($view, $display) = $this->setupBaseViewAndDisplay();
435 $display->expects($this->atLeastOnce())
436 ->method('acceptAttachments')
438 $display->expects($this->atLeastOnce())
439 ->method('getAttachedDisplays')
440 ->willReturn(['page_1']);
442 $cloned_view = $this->getMockBuilder('Drupal\views\ViewExecutable')
443 ->disableOriginalConstructor()
445 $this->viewExecutableFactory->expects($this->atLeastOnce())
447 ->willReturn($cloned_view);
449 $page_display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
450 ->disableOriginalConstructor()
453 $page_display->expects($this->atLeastOnce())
454 ->method('isEnabled')
457 $display_collection = $this->getMockBuilder('Drupal\views\DisplayPluginCollection')
458 ->disableOriginalConstructor()
461 $display_collection->expects($this->atLeastOnce())
464 ->willReturn($page_display);
465 $view->displayHandlers = $display_collection;
467 // Setup the expectations.
468 $page_display->expects($this->once())
470 ->with($cloned_view, 'default', $view->element);
472 $view->attachDisplays();
476 * Setups a view executable and default display.
479 * Returns the view executable and default display.
481 protected function setupBaseViewAndDisplay() {
484 'tag' => 'OnE, TWO, and three',
488 'display_plugin' => 'default',
489 'display_title' => 'Default',
494 $storage = new View($config, 'view');
495 $view = new ViewExecutable($storage, $this->user, $this->viewsData, $this->routeProvider);
496 $display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
497 ->disableOriginalConstructor()
499 $display->expects($this->any())
500 ->method('getPlugin')
501 ->with($this->equalTo('cache'))
502 ->willReturn($this->successCache);
504 $display->display = $config['display']['default'];
506 $view->current_display = 'default';
507 $view->display_handler = $display;
508 $view->displayHandlers = $this->displayHandlers;
509 $view->displayHandlers->expects($this->any())
512 ->willReturn($display);
513 $view->displayHandlers->expects($this->any())
518 foreach (array_keys($view->getHandlerTypes()) as $type) {
522 return [$view, $display];
526 * @covers ::setItemsPerPage
527 * @covers ::getItemsPerPage
529 public function testSetItemsPerPageBeforePreRender() {
530 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
531 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
532 list($view, $display) = $this->setupBaseViewAndDisplay();
534 $view->setItemsPerPage(12);
535 $this->assertEquals(12, $view->getItemsPerPage());
536 $this->assertContains('items_per_page:12', $view->element['#cache']['keys']);
540 * @covers ::setItemsPerPage
541 * @covers ::getItemsPerPage
543 public function testSetItemsPerPageDuringPreRender() {
544 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
545 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
546 list($view, $display) = $this->setupBaseViewAndDisplay();
548 $elements = &$view->element;
549 $elements['#cache'] += ['keys' => []];
550 $elements['#pre_rendered'] = TRUE;
552 $view->setItemsPerPage(12);
553 $this->assertEquals(12, $view->getItemsPerPage());
554 $this->assertNotContains('items_per_page:12', $view->element['#cache']['keys']);
558 * @covers ::setOffset
559 * @covers ::getOffset
561 public function testSetOffsetBeforePreRender() {
562 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
563 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
564 list($view, $display) = $this->setupBaseViewAndDisplay();
566 $view->setOffset(12);
567 $this->assertEquals(12, $view->getOffset());
568 $this->assertContains('offset:12', $view->element['#cache']['keys']);
572 * @covers ::setOffset
573 * @covers ::getOffset
575 public function testSetOffsetDuringPreRender() {
576 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
577 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
578 list($view, $display) = $this->setupBaseViewAndDisplay();
580 $elements = &$view->element;
581 $elements['#cache'] += ['keys' => []];
582 $elements['#pre_rendered'] = TRUE;
584 $view->setOffset(12);
585 $this->assertEquals(12, $view->getOffset());
586 $this->assertNotContains('offset:12', $view->element['#cache']['keys']);
590 * @covers ::setCurrentPage
591 * @covers ::getCurrentPage
593 public function testSetCurrentPageBeforePreRender() {
594 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
595 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
596 list($view, $display) = $this->setupBaseViewAndDisplay();
598 $view->setCurrentPage(12);
599 $this->assertEquals(12, $view->getCurrentPage());
600 $this->assertContains('page:12', $view->element['#cache']['keys']);
604 * @covers ::setCurrentPage
605 * @covers ::getCurrentPage
607 public function testSetCurrentPageDuringPreRender() {
608 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
609 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
610 list($view, $display) = $this->setupBaseViewAndDisplay();
612 $elements = &$view->element;
613 $elements['#cache'] += ['keys' => []];
614 $elements['#pre_rendered'] = TRUE;
616 $view->setCurrentPage(12);
617 $this->assertEquals(12, $view->getCurrentPage());
618 $this->assertNotContains('page:12', $view->element['#cache']['keys']);
624 public function testCacheIsIgnoredDuringPreview() {
625 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
626 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
627 list($view, $display) = $this->setupBaseViewAndDisplay();
629 // Pager needs to be set to avoid false test failures.
630 $view->pager = $this->getMockBuilder(NonePager::class)
631 ->disableOriginalConstructor()
634 $query = $this->getMockBuilder(QueryPluginBase::class)
635 ->disableOriginalConstructor()
638 $view->query = $query;
640 $view->live_preview = TRUE;
642 $this->noneCache->expects($this->once())->method('cacheGet');
643 $query->expects($this->once())->method('execute');
649 * Tests the return values for the execute() method.
651 * @param bool $display_enabled
652 * Whether the display to test should be enabled.
653 * @param bool $expected_result
654 * The expected result when calling execute().
657 * @dataProvider providerExecuteReturn
659 public function testExecuteReturn($display_enabled, $expected_result) {
660 /** @var \Drupal\views\ViewExecutable|\PHPUnit_Framework_MockObject_MockObject $view */
661 /** @var \Drupal\views\Plugin\views\display\DisplayPluginBase|\PHPUnit_Framework_MockObject_MockObject $display */
662 list($view, $display) = $this->setupBaseViewAndDisplay();
664 $display->expects($this->any())
665 ->method('isEnabled')
666 ->willReturn($display_enabled);
668 // Pager needs to be set to avoid false test failures.
669 $view->pager = $this->getMockBuilder(NonePager::class)
670 ->disableOriginalConstructor()
673 $query = $this->getMockBuilder(QueryPluginBase::class)
674 ->disableOriginalConstructor()
677 $view->query = $query;
680 $this->assertEquals($expected_result, $view->execute());
684 * Provider for testExecuteReturn().
687 * An array of arrays containing the display state and expected value.
689 public function providerExecuteReturn() {
691 'enabled' => [static::DISPLAY_ENABLED, TRUE],
692 'disabled' => [static::DISPLAY_DISABLED, FALSE],