Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/search/tests/src/Functional/SearchCommentTest.php @ 4:a9cd425dd02b
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:11:55 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:307d7a7fd348 | 4:a9cd425dd02b |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Tests\search\Functional; | |
4 | |
5 use Behat\Mink\Exception\ResponseTextException; | |
6 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; | |
7 use Drupal\comment\Tests\CommentTestTrait; | |
8 use Drupal\field\Entity\FieldConfig; | |
9 use Drupal\Tests\BrowserTestBase; | |
10 use Drupal\Tests\Traits\Core\CronRunTrait; | |
11 use Drupal\user\RoleInterface; | |
12 use Drupal\filter\Entity\FilterFormat; | |
13 | |
14 /** | |
15 * Tests integration searching comments. | |
16 * | |
17 * @group search | |
18 */ | |
19 class SearchCommentTest extends BrowserTestBase { | |
20 | |
21 use CommentTestTrait; | |
22 use CronRunTrait; | |
23 | |
24 /** | |
25 * {@inheritdoc} | |
26 */ | |
27 protected static $modules = ['filter', 'node', 'comment', 'search']; | |
28 | |
29 /** | |
30 * Test subject for comments. | |
31 * | |
32 * @var string | |
33 */ | |
34 protected $commentSubject; | |
35 | |
36 /** | |
37 * ID for the administrator role. | |
38 * | |
39 * @var string | |
40 */ | |
41 protected $adminRole; | |
42 | |
43 /** | |
44 * A user with various administrative permissions. | |
45 * | |
46 * @var \Drupal\user\UserInterface | |
47 */ | |
48 protected $adminUser; | |
49 | |
50 /** | |
51 * Test node for searching. | |
52 * | |
53 * @var \Drupal\node\NodeInterface | |
54 */ | |
55 protected $node; | |
56 | |
57 protected function setUp() { | |
58 parent::setUp(); | |
59 | |
60 $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); | |
61 $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); | |
62 | |
63 $full_html_format = FilterFormat::create([ | |
64 'format' => 'full_html', | |
65 'name' => 'Full HTML', | |
66 'weight' => 1, | |
67 'filters' => [], | |
68 ]); | |
69 $full_html_format->save(); | |
70 | |
71 // Create and log in an administrative user having access to the Full HTML | |
72 // text format. | |
73 $permissions = [ | |
74 'administer filters', | |
75 $full_html_format->getPermissionName(), | |
76 'administer permissions', | |
77 'create page content', | |
78 'post comments', | |
79 'skip comment approval', | |
80 'access comments', | |
81 ]; | |
82 $this->adminUser = $this->drupalCreateUser($permissions); | |
83 $this->drupalLogin($this->adminUser); | |
84 // Add a comment field. | |
85 $this->addDefaultCommentField('node', 'article'); | |
86 } | |
87 | |
88 /** | |
89 * Verify that comments are rendered using proper format in search results. | |
90 */ | |
91 public function testSearchResultsComment() { | |
92 $node_storage = $this->container->get('entity.manager')->getStorage('node'); | |
93 // Create basic_html format that escapes all HTML. | |
94 $basic_html_format = FilterFormat::create([ | |
95 'format' => 'basic_html', | |
96 'name' => 'Basic HTML', | |
97 'weight' => 1, | |
98 'filters' => [ | |
99 'filter_html_escape' => ['status' => 1], | |
100 ], | |
101 'roles' => [RoleInterface::AUTHENTICATED_ID], | |
102 ]); | |
103 $basic_html_format->save(); | |
104 | |
105 $comment_body = 'Test comment body'; | |
106 | |
107 // Make preview optional. | |
108 $field = FieldConfig::loadByName('node', 'article', 'comment'); | |
109 $field->setSetting('preview', DRUPAL_OPTIONAL); | |
110 $field->save(); | |
111 | |
112 // Allow anonymous users to search content. | |
113 $edit = [ | |
114 RoleInterface::ANONYMOUS_ID . '[search content]' => 1, | |
115 RoleInterface::ANONYMOUS_ID . '[access comments]' => 1, | |
116 RoleInterface::ANONYMOUS_ID . '[post comments]' => 1, | |
117 ]; | |
118 $this->drupalPostForm('admin/people/permissions', $edit, t('Save permissions')); | |
119 | |
120 // Create a node. | |
121 $node = $this->drupalCreateNode(['type' => 'article']); | |
122 // Post a comment using 'Full HTML' text format. | |
123 $edit_comment = []; | |
124 $edit_comment['subject[0][value]'] = 'Test comment subject'; | |
125 $edit_comment['comment_body[0][value]'] = '<h1>' . $comment_body . '</h1>'; | |
126 $full_html_format_id = 'full_html'; | |
127 $edit_comment['comment_body[0][format]'] = $full_html_format_id; | |
128 $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment, t('Save')); | |
129 | |
130 // Post a comment with an evil script tag in the comment subject and a | |
131 // script tag nearby a keyword in the comment body. Use the 'FULL HTML' text | |
132 // format so the script tag stored. | |
133 $edit_comment2 = []; | |
134 $edit_comment2['subject[0][value]'] = "<script>alert('subjectkeyword');</script>"; | |
135 $edit_comment2['comment_body[0][value]'] = "nearbykeyword<script>alert('somethinggeneric');</script>"; | |
136 $edit_comment2['comment_body[0][format]'] = $full_html_format_id; | |
137 $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment2, t('Save')); | |
138 | |
139 // Post a comment with a keyword inside an evil script tag in the comment | |
140 // body. Use the 'FULL HTML' text format so the script tag is stored. | |
141 $edit_comment3 = []; | |
142 $edit_comment3['subject[0][value]'] = 'asubject'; | |
143 $edit_comment3['comment_body[0][value]'] = "<script>alert('insidekeyword');</script>"; | |
144 $edit_comment3['comment_body[0][format]'] = $full_html_format_id; | |
145 $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment3, t('Save')); | |
146 | |
147 // Invoke search index update. | |
148 $this->drupalLogout(); | |
149 $this->cronRun(); | |
150 | |
151 // Search for the comment subject. | |
152 $edit = [ | |
153 'keys' => "'" . $edit_comment['subject[0][value]'] . "'", | |
154 ]; | |
155 $this->drupalPostForm('search/node', $edit, t('Search')); | |
156 $node_storage->resetCache([$node->id()]); | |
157 $node2 = $node_storage->load($node->id()); | |
158 $this->assertText($node2->label(), 'Node found in search results.'); | |
159 $this->assertText($edit_comment['subject[0][value]'], 'Comment subject found in search results.'); | |
160 | |
161 // Search for the comment body. | |
162 $edit = [ | |
163 'keys' => "'" . $comment_body . "'", | |
164 ]; | |
165 $this->drupalPostForm(NULL, $edit, t('Search')); | |
166 $this->assertText($node2->label(), 'Node found in search results.'); | |
167 | |
168 // Verify that comment is rendered using proper format. | |
169 $this->assertText($comment_body, 'Comment body text found in search results.'); | |
170 $this->assertNoRaw(t('n/a'), 'HTML in comment body is not hidden.'); | |
171 $this->assertNoEscaped($edit_comment['comment_body[0][value]'], 'HTML in comment body is not escaped.'); | |
172 | |
173 // Search for the evil script comment subject. | |
174 $edit = [ | |
175 'keys' => 'subjectkeyword', | |
176 ]; | |
177 $this->drupalPostForm('search/node', $edit, t('Search')); | |
178 | |
179 // Verify the evil comment subject is escaped in search results. | |
180 $this->assertRaw('<script>alert('<strong>subjectkeyword</strong>');'); | |
181 $this->assertNoRaw('<script>'); | |
182 | |
183 // Search for the keyword near the evil script tag in the comment body. | |
184 $edit = [ | |
185 'keys' => 'nearbykeyword', | |
186 ]; | |
187 $this->drupalPostForm('search/node', $edit, t('Search')); | |
188 | |
189 // Verify that nearby script tag in the evil comment body is stripped from | |
190 // search results. | |
191 $this->assertRaw('<strong>nearbykeyword</strong>'); | |
192 $this->assertNoRaw('<script>'); | |
193 | |
194 // Search for contents inside the evil script tag in the comment body. | |
195 $edit = [ | |
196 'keys' => 'insidekeyword', | |
197 ]; | |
198 $this->drupalPostForm('search/node', $edit, t('Search')); | |
199 | |
200 // @todo Verify the actual search results. | |
201 // https://www.drupal.org/node/2551135 | |
202 | |
203 // Verify there is no script tag in search results. | |
204 $this->assertNoRaw('<script>'); | |
205 | |
206 // Hide comments. | |
207 $this->drupalLogin($this->adminUser); | |
208 $node->set('comment', CommentItemInterface::HIDDEN); | |
209 $node->save(); | |
210 | |
211 // Invoke search index update. | |
212 $this->drupalLogout(); | |
213 $this->cronRun(); | |
214 | |
215 // Search for $title. | |
216 $this->drupalPostForm('search/node', $edit, t('Search')); | |
217 $this->assertText(t('Your search yielded no results.')); | |
218 } | |
219 | |
220 /** | |
221 * Verify access rules for comment indexing with different permissions. | |
222 */ | |
223 public function testSearchResultsCommentAccess() { | |
224 $comment_body = 'Test comment body'; | |
225 $this->commentSubject = 'Test comment subject'; | |
226 $roles = $this->adminUser->getRoles(TRUE); | |
227 $this->adminRole = $roles[0]; | |
228 | |
229 // Create a node. | |
230 // Make preview optional. | |
231 $field = FieldConfig::loadByName('node', 'article', 'comment'); | |
232 $field->setSetting('preview', DRUPAL_OPTIONAL); | |
233 $field->save(); | |
234 $this->node = $this->drupalCreateNode(['type' => 'article']); | |
235 | |
236 // Post a comment using 'Full HTML' text format. | |
237 $edit_comment = []; | |
238 $edit_comment['subject[0][value]'] = $this->commentSubject; | |
239 $edit_comment['comment_body[0][value]'] = '<h1>' . $comment_body . '</h1>'; | |
240 $this->drupalPostForm('comment/reply/node/' . $this->node->id() . '/comment', $edit_comment, t('Save')); | |
241 | |
242 $this->drupalLogout(); | |
243 $this->setRolePermissions(RoleInterface::ANONYMOUS_ID); | |
244 $this->assertCommentAccess(FALSE, 'Anon user has search permission but no access comments permission, comments should not be indexed'); | |
245 | |
246 $this->setRolePermissions(RoleInterface::ANONYMOUS_ID, TRUE); | |
247 $this->assertCommentAccess(TRUE, 'Anon user has search permission and access comments permission, comments should be indexed'); | |
248 | |
249 $this->drupalLogin($this->adminUser); | |
250 $this->drupalGet('admin/people/permissions'); | |
251 | |
252 // Disable search access for authenticated user to test admin user. | |
253 $this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, FALSE, FALSE); | |
254 | |
255 $this->setRolePermissions($this->adminRole); | |
256 $this->assertCommentAccess(FALSE, 'Admin user has search permission but no access comments permission, comments should not be indexed'); | |
257 | |
258 $this->drupalGet('node/' . $this->node->id()); | |
259 $this->setRolePermissions($this->adminRole, TRUE); | |
260 $this->assertCommentAccess(TRUE, 'Admin user has search permission and access comments permission, comments should be indexed'); | |
261 | |
262 $this->setRolePermissions(RoleInterface::AUTHENTICATED_ID); | |
263 $this->assertCommentAccess(FALSE, 'Authenticated user has search permission but no access comments permission, comments should not be indexed'); | |
264 | |
265 $this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE); | |
266 $this->assertCommentAccess(TRUE, 'Authenticated user has search permission and access comments permission, comments should be indexed'); | |
267 | |
268 // Verify that access comments permission is inherited from the | |
269 // authenticated role. | |
270 $this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE, FALSE); | |
271 $this->setRolePermissions($this->adminRole); | |
272 $this->assertCommentAccess(TRUE, 'Admin user has search permission and no access comments permission, but comments should be indexed because admin user inherits authenticated user\'s permission to access comments'); | |
273 | |
274 // Verify that search content permission is inherited from the authenticated | |
275 // role. | |
276 $this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE, TRUE); | |
277 $this->setRolePermissions($this->adminRole, TRUE, FALSE); | |
278 $this->assertCommentAccess(TRUE, 'Admin user has access comments permission and no search permission, but comments should be indexed because admin user inherits authenticated user\'s permission to search'); | |
279 } | |
280 | |
281 /** | |
282 * Set permissions for role. | |
283 */ | |
284 public function setRolePermissions($rid, $access_comments = FALSE, $search_content = TRUE) { | |
285 $permissions = [ | |
286 'access comments' => $access_comments, | |
287 'search content' => $search_content, | |
288 ]; | |
289 user_role_change_permissions($rid, $permissions); | |
290 } | |
291 | |
292 /** | |
293 * Update search index and search for comment. | |
294 */ | |
295 public function assertCommentAccess($assume_access, $message) { | |
296 // Invoke search index update. | |
297 search_mark_for_reindex('node_search', $this->node->id()); | |
298 $this->cronRun(); | |
299 | |
300 // Search for the comment subject. | |
301 $edit = [ | |
302 'keys' => "'" . $this->commentSubject . "'", | |
303 ]; | |
304 $this->drupalPostForm('search/node', $edit, t('Search')); | |
305 | |
306 try { | |
307 if ($assume_access) { | |
308 $this->assertSession()->pageTextContains($this->node->label()); | |
309 $this->assertSession()->pageTextContains($this->commentSubject); | |
310 } | |
311 else { | |
312 $this->assertSession()->pageTextContains(t('Your search yielded no results.')); | |
313 } | |
314 } | |
315 catch (ResponseTextException $exception) { | |
316 $this->fail($message); | |
317 } | |
318 } | |
319 | |
320 /** | |
321 * Verify that 'add new comment' does not appear in search results or index. | |
322 */ | |
323 public function testAddNewComment() { | |
324 // Create a node with a short body. | |
325 $settings = [ | |
326 'type' => 'article', | |
327 'title' => 'short title', | |
328 'body' => [['value' => 'short body text']], | |
329 ]; | |
330 | |
331 $user = $this->drupalCreateUser([ | |
332 'search content', | |
333 'create article content', | |
334 'access content', | |
335 'post comments', | |
336 'access comments', | |
337 ]); | |
338 $this->drupalLogin($user); | |
339 | |
340 $node = $this->drupalCreateNode($settings); | |
341 // Verify that if you view the node on its own page, 'add new comment' | |
342 // is there. | |
343 $this->drupalGet('node/' . $node->id()); | |
344 $this->assertText(t('Add new comment')); | |
345 | |
346 // Run cron to index this page. | |
347 $this->drupalLogout(); | |
348 $this->cronRun(); | |
349 | |
350 // Search for 'comment'. Should be no results. | |
351 $this->drupalLogin($user); | |
352 $this->drupalPostForm('search/node', ['keys' => 'comment'], t('Search')); | |
353 $this->assertText(t('Your search yielded no results')); | |
354 | |
355 // Search for the node title. Should be found, and 'Add new comment' should | |
356 // not be part of the search snippet. | |
357 $this->drupalPostForm('search/node', ['keys' => 'short'], t('Search')); | |
358 $this->assertText($node->label(), 'Search for keyword worked'); | |
359 $this->assertNoText(t('Add new comment')); | |
360 } | |
361 | |
362 } |