Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / node / tests / src / Functional / Views / FrontPageTest.php
1 <?php
2
3 namespace Drupal\Tests\node\Functional\Views;
4
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Language\LanguageInterface;
7 use Drupal\Core\Url;
8 use Drupal\node\Entity\Node;
9 use Drupal\Tests\views\Functional\ViewTestBase;
10 use Drupal\views\Tests\AssertViewsCacheTagsTrait;
11 use Drupal\views\ViewExecutable;
12 use Drupal\views\Views;
13
14 /**
15  * Tests the default frontpage provided by views.
16  *
17  * @group node
18  */
19 class FrontPageTest extends ViewTestBase {
20
21   use AssertViewsCacheTagsTrait;
22
23   /**
24    * {@inheritdoc}
25    */
26   protected $dumpHeaders = TRUE;
27
28   /**
29    * The entity storage for nodes.
30    *
31    * @var \Drupal\node\NodeStorage
32    */
33   protected $nodeStorage;
34
35   /**
36    * Modules to enable.
37    *
38    * @var array
39    */
40   public static $modules = ['node', 'contextual'];
41
42   /**
43    * {@inheritdoc}
44    */
45   protected function setUp($import_test_views = TRUE) {
46     parent::setUp($import_test_views);
47
48     $this->nodeStorage = $this->container->get('entity.manager')
49       ->getStorage('node');
50   }
51
52   /**
53    * Tests the frontpage.
54    */
55   public function testFrontPage() {
56     $site_name = $this->randomMachineName();
57     $this->config('system.site')
58       ->set('name', $site_name)
59       ->save();
60
61     $view = Views::getView('frontpage');
62
63     // Tests \Drupal\node\Plugin\views\row\RssPluginBase::calculateDependencies().
64     $expected = [
65       'config' => [
66         'core.entity_view_mode.node.rss',
67         'core.entity_view_mode.node.teaser',
68       ],
69       'module' => [
70         'node',
71         'user',
72       ],
73     ];
74     $this->assertIdentical($expected, $view->getDependencies());
75
76     $view->setDisplay('page_1');
77     $this->executeView($view);
78     $view->preview();
79
80     $this->assertEqual($view->getTitle(), format_string('Welcome to @site_name', ['@site_name' => $site_name]), 'The welcome title is used for the empty view.');
81     $view->destroy();
82
83     // Create some nodes on the frontpage view. Add more than 10 nodes in order
84     // to enable paging.
85     $expected = [];
86     for ($i = 0; $i < 20; $i++) {
87       $values = [];
88       $values['type'] = 'article';
89       $values['title'] = $this->randomMachineName();
90       $values['promote'] = TRUE;
91       $values['status'] = TRUE;
92       // Test descending sort order.
93       $values['created'] = REQUEST_TIME - $i;
94       // Test the sticky order.
95       if ($i == 5) {
96         $values['sticky'] = TRUE;
97         $node = $this->nodeStorage->create($values);
98         $node->save();
99         // Put the sticky on at the front.
100         array_unshift($expected, ['nid' => $node->id()]);
101       }
102       else {
103         $values['sticky'] = FALSE;
104         $node = $this->nodeStorage->create($values);
105         $node->save();
106         array_push($expected, ['nid' => $node->id()]);
107       }
108     }
109
110     // Create some nodes which aren't on the frontpage, either because they
111     // aren't promoted or because they aren't published.
112     $not_expected_nids = [];
113
114     $values = [];
115     $values['type'] = 'article';
116     $values['title'] = $this->randomMachineName();
117     $values['status'] = TRUE;
118     $values['promote'] = FALSE;
119     $node = $this->nodeStorage->create($values);
120     $node->save();
121     $not_expected_nids[] = $node->id();
122
123     $values['promote'] = TRUE;
124     $values['status'] = FALSE;
125     $values['title'] = $this->randomMachineName();
126     $node = $this->nodeStorage->create($values);
127     $node->save();
128     $not_expected_nids[] = $node->id();
129
130     $values['promote'] = TRUE;
131     $values['sticky'] = TRUE;
132     $values['status'] = FALSE;
133     $values['title'] = $this->randomMachineName();
134     $node = $this->nodeStorage->create($values);
135     $node->save();
136     $not_expected_nids[] = $node->id();
137
138     $column_map = ['nid' => 'nid'];
139
140     $view->setDisplay('page_1');
141     $this->executeView($view);
142     $this->assertIdenticalResultset($view, array_slice($expected, 0, 10), $column_map, 'Ensure that the right nodes are displayed on the frontpage.');
143     $this->assertNotInResultSet($view, $not_expected_nids, 'Ensure no unexpected node is in the result.');
144     $view->destroy();
145
146     $view->setDisplay('page_1');
147     $view->setCurrentPage(1);
148     $this->executeView($view);
149     $this->assertIdenticalResultset($view, array_slice($expected, 10, 10), $column_map, 'Ensure that the right nodes are displayed on second page of the frontpage.');
150     $this->assertNotInResultSet($view, $not_expected_nids, 'Ensure no unexpected node is in the result.');
151     $view->destroy();
152   }
153
154   /**
155    * Verifies that an amount of nids aren't in the result.
156    *
157    * @param \Drupal\views\ViewExecutable $view
158    *   An executed View.
159    * @param array $not_expected_nids
160    *   An array of nids which should not be part of the resultset.
161    * @param string $message
162    *   (optional) A custom message to display with the assertion.
163    */
164   protected function assertNotInResultSet(ViewExecutable $view, array $not_expected_nids, $message = '') {
165     $found_nids = array_filter($view->result, function ($row) use ($not_expected_nids) {
166       return in_array($row->nid, $not_expected_nids);
167     });
168     $this->assertFalse($found_nids, $message);
169   }
170
171   /**
172    * Tests the frontpage when logged in as admin.
173    */
174   public function testAdminFrontPage() {
175     // When a user with sufficient permissions is logged in, views_ui adds
176     // contextual links to the homepage view. This verifies there are no errors.
177     \Drupal::service('module_installer')->install(['views_ui']);
178     // Log in root user with sufficient permissions.
179     $this->drupalLogin($this->rootUser);
180     // Test frontpage view.
181     $this->drupalGet('node');
182     $this->assertResponse(200);
183     // Check that the frontpage view was rendered.
184     $this->assertPattern('/class=".+view-frontpage/', 'Frontpage view was rendered');
185   }
186
187   /**
188    * Tests the cache tags when using the "none" cache plugin.
189    */
190   public function testCacheTagsWithCachePluginNone() {
191     $this->enablePageCaching();
192     $this->doTestFrontPageViewCacheTags(FALSE);
193   }
194
195   /**
196    * Tests the cache tags when using the "tag" cache plugin.
197    */
198   public function testCacheTagsWithCachePluginTag() {
199     $this->enablePageCaching();
200
201     $view = Views::getView('frontpage');
202     $view->setDisplay('page_1');
203     $view->display_handler->overrideOption('cache', [
204       'type' => 'tag',
205     ]);
206     $view->save();
207
208     $this->doTestFrontPageViewCacheTags(TRUE);
209   }
210
211   /**
212    * Tests the cache tags when using the "time" cache plugin.
213    */
214   public function testCacheTagsWithCachePluginTime() {
215     $this->enablePageCaching();
216
217     $view = Views::getView('frontpage');
218     $view->setDisplay('page_1');
219     $view->display_handler->overrideOption('cache', [
220       'type' => 'time',
221       'options' => [
222         'results_lifespan' => 3600,
223         'output_lifespan' => 3600,
224       ],
225     ]);
226     $view->save();
227
228     $this->doTestFrontPageViewCacheTags(TRUE);
229   }
230
231   /**
232    * Tests the cache tags on the front page.
233    *
234    * @param bool $do_assert_views_caches
235    *   Whether to check Views' result & output caches.
236    */
237   protected function doTestFrontPageViewCacheTags($do_assert_views_caches) {
238     $view = Views::getView('frontpage');
239     $view->setDisplay('page_1');
240
241     $cache_contexts = [
242       // Cache contexts associated with the view.
243       'user.node_grants:view',
244       'languages:' . LanguageInterface::TYPE_INTERFACE,
245       // Cache contexts associated with the route's access checking.
246       'user.permissions',
247       // Default cache contexts of the renderer.
248       'theme',
249       'url.query_args',
250       // Attached feed.
251       'url.site',
252     ];
253
254     $cache_context_tags = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts)->getCacheTags();
255
256     // Test before there are any nodes.
257     $empty_node_listing_cache_tags = [
258       'config:views.view.frontpage',
259       'node_list',
260     ];
261
262     $render_cache_tags = Cache::mergeTags($empty_node_listing_cache_tags, $cache_context_tags);
263     $render_cache_tags = Cache::mergeTags($render_cache_tags, ['config:system.site']);
264     $this->assertViewsCacheTags(
265       $view,
266       $empty_node_listing_cache_tags,
267       $do_assert_views_caches,
268       $render_cache_tags
269     );
270     $expected_tags = Cache::mergeTags($empty_node_listing_cache_tags, $cache_context_tags);
271     $expected_tags = Cache::mergeTags($expected_tags, ['http_response', 'rendered', 'config:user.role.anonymous', 'config:system.site']);
272     $this->assertPageCacheContextsAndTags(
273       Url::fromRoute('view.frontpage.page_1'),
274       $cache_contexts,
275       $expected_tags
276     );
277
278     // Create some nodes on the frontpage view. Add more than 10 nodes in order
279     // to enable paging.
280     $this->drupalCreateContentType(['type' => 'article']);
281     for ($i = 0; $i < 15; $i++) {
282       $node = Node::create([
283         'body' => [
284           [
285             'value' => $this->randomMachineName(32),
286             'format' => filter_default_format(),
287           ],
288         ],
289         'type' => 'article',
290         'created' => $i,
291         'title' => $this->randomMachineName(8),
292         'nid' => $i + 1,
293       ]);
294       $node->enforceIsNew(TRUE);
295       $node->save();
296     }
297     $cache_contexts = Cache::mergeContexts($cache_contexts, [
298       'timezone',
299     ]);
300
301     $this->pass('First page');
302     // First page.
303     $first_page_result_cache_tags = [
304       'config:views.view.frontpage',
305       'node_list',
306       'node:6',
307       'node:7',
308       'node:8',
309       'node:9',
310       'node:10',
311       'node:11',
312       'node:12',
313       'node:13',
314       'node:14',
315       'node:15',
316     ];
317     $cache_context_tags = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts)->getCacheTags();
318     $first_page_output_cache_tags = Cache::mergeTags($first_page_result_cache_tags, $cache_context_tags);
319     $first_page_output_cache_tags = Cache::mergeTags($first_page_output_cache_tags, [
320         'config:filter.format.plain_text',
321         'node_view',
322         'user_view',
323         'user:0',
324       ]
325     );
326     $view->setDisplay('page_1');
327     $view->setCurrentPage(0);
328     $this->assertViewsCacheTags(
329       $view,
330       $first_page_result_cache_tags,
331       $do_assert_views_caches,
332       $first_page_output_cache_tags
333     );
334     $this->assertPageCacheContextsAndTags(
335       Url::fromRoute('view.frontpage.page_1'),
336       $cache_contexts,
337       Cache::mergeTags($first_page_output_cache_tags, ['http_response', 'rendered', 'config:user.role.anonymous'])
338     );
339
340     // Second page.
341     $this->pass('Second page');
342     $this->assertPageCacheContextsAndTags(Url::fromRoute('view.frontpage.page_1', [], ['query' => ['page' => 1]]), $cache_contexts, [
343       // The cache tags for the listed nodes.
344       'node:1',
345       'node:2',
346       'node:3',
347       'node:4',
348       'node:5',
349       // The rest.
350       'config:filter.format.plain_text',
351       'config:views.view.frontpage',
352       'node_list',
353       'node_view',
354       'user_view',
355       'user:0',
356       'http_response',
357       'rendered',
358       // FinishResponseSubscriber adds this cache tag to responses that have the
359       // 'user.permissions' cache context for anonymous users.
360       'config:user.role.anonymous',
361     ]);
362
363     // Let's update a node title on the first page and ensure that the page
364     // cache entry invalidates.
365     $node = Node::load(10);
366     $title = $node->getTitle() . 'a';
367     $node->setTitle($title);
368     $node->save();
369
370     $this->drupalGet(Url::fromRoute('view.frontpage.page_1'));
371     $this->assertText($title);
372   }
373
374 }