3 namespace Drupal\Tests\views\Kernel\Plugin;
5 use Drupal\Core\Menu\MenuTreeParameters;
6 use Drupal\Core\Session\AnonymousUserSession;
7 use Drupal\views\Entity\View;
8 use Drupal\views\Views;
9 use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
10 use Symfony\Component\HttpFoundation\Request;
11 use Symfony\Component\HttpKernel\HttpKernelInterface;
14 * Tests the page display plugin.
17 * @see \Drupal\views\Plugin\display\Page
19 class DisplayPageTest extends ViewsKernelTestBase {
22 * Views used by this test.
26 public static $testViews = ['test_page_display', 'test_page_display_route', 'test_page_display_menu', 'test_display_more'];
33 public static $modules = ['system', 'user', 'field', 'views_test_data'];
36 * The router dumper to get all routes.
38 * @var \Drupal\Core\Routing\MatcherDumper
40 protected $routerDumper;
43 * Checks the behavior of the page for access denied/not found behaviors.
45 public function testPageResponses() {
46 \Drupal::currentUser()->setAccount(new AnonymousUserSession());
47 $subrequest = Request::create('/test_page_display_403', 'GET');
48 $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
49 $this->assertEqual($response->getStatusCode(), 403);
51 $subrequest = Request::create('/test_page_display_404', 'GET');
52 $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
53 $this->assertEqual($response->getStatusCode(), 404);
55 $subrequest = Request::create('/test_page_display_200', 'GET');
56 $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
57 $this->assertEqual($response->getStatusCode(), 200);
59 $subrequest = Request::create('/test_page_display_200', 'GET');
60 \Drupal::getContainer()->get('request_stack')->push($subrequest);
62 // Test accessing a disabled page for a view.
63 $view = Views::getView('test_page_display');
64 // Disable the view, rebuild menu, and request the page again.
65 $view->storage->disable()->save();
66 // Router rebuild would occur in a kernel terminate event so we need to
67 // simulate that here.
68 \Drupal::service('router.builder')->rebuild();
70 $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
71 $this->assertEqual($response->getStatusCode(), 404);
75 * Checks that the router items are properly registered
77 public function testPageRouterItems() {
78 $collection = \Drupal::service('views.route_subscriber')->routes();
80 // Check the controller defaults.
81 foreach ($collection as $id => $route) {
82 $this->assertEqual($route->getDefault('_controller'), 'Drupal\views\Routing\ViewPageController::handle');
83 $id_parts = explode('.', $id);
84 $this->assertEqual($route->getDefault('view_id'), $id_parts[1]);
85 $this->assertEqual($route->getDefault('display_id'), $id_parts[2]);
88 // Check the generated patterns and default values.
89 $route = $collection->get('view.test_page_display_route.page_1');
90 $this->assertEqual($route->getPath(), '/test_route_without_arguments');
92 $route = $collection->get('view.test_page_display_route.page_2');
93 $this->assertEqual($route->getPath(), '/test_route_with_argument/{arg_0}');
94 $this->assertTrue($route->hasDefault('arg_0'), 'A default value is set for the optional argument id.');
96 $route = $collection->get('view.test_page_display_route.page_3');
97 $this->assertEqual($route->getPath(), '/test_route_with_argument/{arg_0}/suffix');
98 $this->assertFalse($route->hasDefault('arg_0'), 'No default value is set for the required argument id.');
100 $route = $collection->get('view.test_page_display_route.page_4');
101 $this->assertEqual($route->getPath(), '/test_route_with_argument/{arg_0}/suffix/{arg_1}');
102 $this->assertFalse($route->hasDefault('arg_0'), 'No default value is set for the required argument id.');
103 $this->assertTrue($route->hasDefault('arg_1'), 'A default value is set for the optional argument id_2.');
105 $route = $collection->get('view.test_page_display_route.page_5');
106 $this->assertEqual($route->getPath(), '/test_route_with_argument/{arg_0}/{arg_1}');
107 $this->assertTrue($route->hasDefault('arg_0'), 'A default value is set for the optional argument id.');
108 $this->assertTrue($route->hasDefault('arg_1'), 'A default value is set for the optional argument id_2.');
110 $route = $collection->get('view.test_page_display_route.page_6');
111 $this->assertEqual($route->getPath(), '/test_route_with_argument/{arg_0}/{arg_1}');
112 $this->assertFalse($route->hasDefault('arg_0'), 'No default value is set for the required argument id.');
113 $this->assertFalse($route->hasDefault('arg_1'), 'No default value is set for the required argument id_2.');
117 * Tests the generated menu links of views.
119 public function testMenuLinks() {
120 \Drupal::service('plugin.manager.menu.link')->rebuild();
121 $tree = \Drupal::menuTree()->load('admin', new MenuTreeParameters());
122 $this->assertTrue(isset($tree['system.admin']->subtree['views_view:views.test_page_display_menu.page_4']));
123 $menu_link = $tree['system.admin']->subtree['views_view:views.test_page_display_menu.page_4']->link;
124 $this->assertEqual($menu_link->getTitle(), 'Test child (with parent)');
125 $this->assertEqual($menu_link->isExpanded(), TRUE);
126 $this->assertEqual($menu_link->getDescription(), 'Sample description.');
130 * Tests the calculated dependencies for various views using Page displays.
132 public function testDependencies() {
133 $view = Views::getView('test_page_display');
134 $this->assertIdentical(['module' => ['views_test_data']], $view->getDependencies());
136 $view = Views::getView('test_page_display_route');
138 'content' => ['StaticTest'],
139 'module' => ['views_test_data'],
141 $this->assertIdentical($expected, $view->getDependencies());
143 $view = Views::getView('test_page_display_menu');
153 $this->assertIdentical($expected, $view->getDependencies());
157 * Tests the readmore functionality.
159 public function testReadMore() {
160 /** @var \Drupal\Core\Render\RendererInterface $renderer */
161 $renderer = $this->container->get('renderer');
163 $expected_more_text = 'custom more text';
165 $view = Views::getView('test_display_more');
166 $this->executeView($view);
168 $output = $view->preview();
169 $output = $renderer->renderRoot($output);
171 $this->setRawContent($output);
172 $result = $this->xpath('//div[@class=:class]/a', [':class' => 'more-link']);
173 $this->assertEqual($result[0]->attributes()->href, \Drupal::url('view.test_display_more.page_1'), 'The right more link is shown.');
174 $this->assertEqual(trim($result[0][0]), $expected_more_text, 'The right link text is shown.');
176 // Test the renderMoreLink method directly. This could be directly unit
178 $more_link = $view->display_handler->renderMoreLink();
179 $more_link = $renderer->renderRoot($more_link);
180 $this->setRawContent($more_link);
181 $result = $this->xpath('//div[@class=:class]/a', [':class' => 'more-link']);
182 $this->assertEqual($result[0]->attributes()->href, \Drupal::url('view.test_display_more.page_1'), 'The right more link is shown.');
183 $this->assertEqual(trim($result[0][0]), $expected_more_text, 'The right link text is shown.');
185 // Test the useMoreText method directly. This could be directly unit
187 $more_text = $view->display_handler->useMoreText();
188 $this->assertEqual($more_text, $expected_more_text, 'The right more text is chosen.');
190 $view = Views::getView('test_display_more');
192 $view->display_handler->setOption('use_more', 0);
193 $this->executeView($view);
194 $output = $view->preview();
195 $output = $renderer->renderRoot($output);
196 $this->setRawContent($output);
197 $result = $this->xpath('//div[@class=:class]/a', [':class' => 'more-link']);
198 $this->assertTrue(empty($result), 'The more link is not shown.');
200 $view = Views::getView('test_display_more');
202 $view->display_handler->setOption('use_more', 0);
203 $view->display_handler->setOption('use_more_always', 0);
204 $view->display_handler->setOption('pager', [
207 'items_per_page' => 1,
211 $this->executeView($view);
212 $output = $view->preview();
213 $output = $renderer->renderRoot($output);
214 $this->setRawContent($output);
215 $result = $this->xpath('//div[@class=:class]/a', [':class' => 'more-link']);
216 $this->assertTrue(empty($result), 'The more link is not shown when view has more records.');
218 // Test the default value of use_more_always.
219 $view = View::create()->getExecutable();
220 $this->assertTrue($view->getDisplay()->getOption('use_more_always'), 'Always display the more link by default.');
224 * Tests the templates with empty rows.
226 public function testEmptyRow() {
227 $view = Views::getView('test_page_display');
228 $view->initDisplay();
229 $view->newDisplay('page', 'Page', 'empty_row');
233 'default' => '//div[@class="views-row"]',
234 'grid' => '//div[contains(@class, "views-col")]',
235 'html_list' => '//div[@class="item-list"]//li',
238 $themes = ['bartik', 'classy', 'seven', 'stable', 'stark'];
240 foreach ($themes as $theme) {
241 \Drupal::service('theme_handler')->install([$theme]);
242 \Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme($theme));
243 foreach ($styles as $type => $xpath) {
244 $view = Views::getView('test_page_display');
245 $view->storage->invalidateCaches();
246 $view->initDisplay();
247 $view->setDisplay('empty_row');
248 $view->displayHandlers->get('empty_row')->default_display->options['style']['type'] = $type;
250 $this->executeView($view);
251 $output = $view->preview();
252 $output = \Drupal::service('renderer')->renderRoot($output);
253 $this->setRawContent($output);
254 $this->assertCount(5, $this->xpath("{$xpath}[not(text()) and not(node())]"), "Empty rows in theme '$theme', type '$type'.");