annotate core/modules/search/tests/src/Functional/SearchRankingTest.php @ 18:af1871eacc83

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:33:08 +0100
parents 129ea1e6d783
children
rev   line source
Chris@17 1 <?php
Chris@17 2
Chris@17 3 namespace Drupal\Tests\search\Functional;
Chris@17 4
Chris@17 5 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
Chris@17 6 use Drupal\comment\Tests\CommentTestTrait;
Chris@18 7 use Drupal\Core\Database\Database;
Chris@17 8 use Drupal\Core\Url;
Chris@17 9 use Drupal\filter\Entity\FilterFormat;
Chris@17 10 use Drupal\search\Entity\SearchPage;
Chris@17 11 use Drupal\Tests\BrowserTestBase;
Chris@17 12 use Drupal\Tests\Traits\Core\CronRunTrait;
Chris@17 13
Chris@17 14 /**
Chris@17 15 * Indexes content and tests ranking factors.
Chris@17 16 *
Chris@17 17 * @group search
Chris@17 18 */
Chris@17 19 class SearchRankingTest extends BrowserTestBase {
Chris@17 20
Chris@17 21 use CommentTestTrait;
Chris@17 22 use CronRunTrait;
Chris@17 23
Chris@17 24 /**
Chris@17 25 * The node search page.
Chris@17 26 *
Chris@17 27 * @var \Drupal\search\SearchPageInterface
Chris@17 28 */
Chris@17 29 protected $nodeSearch;
Chris@17 30
Chris@17 31 /**
Chris@17 32 * {@inheritdoc}
Chris@17 33 */
Chris@17 34 protected static $modules = ['node', 'search', 'statistics', 'comment'];
Chris@17 35
Chris@17 36 protected function setUp() {
Chris@17 37 parent::setUp();
Chris@17 38
Chris@17 39 $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
Chris@17 40
Chris@17 41 // Create a plugin instance.
Chris@17 42 $this->nodeSearch = SearchPage::load('node_search');
Chris@17 43
Chris@17 44 // Log in with sufficient privileges.
Chris@17 45 $this->drupalLogin($this->drupalCreateUser(['post comments', 'skip comment approval', 'create page content', 'administer search']));
Chris@17 46 }
Chris@17 47
Chris@17 48 public function testRankings() {
Chris@17 49 // Add a comment field.
Chris@17 50 $this->addDefaultCommentField('node', 'page');
Chris@17 51
Chris@17 52 // Build a list of the rankings to test.
Chris@17 53 $node_ranks = ['sticky', 'promote', 'relevance', 'recent', 'comments', 'views'];
Chris@17 54
Chris@17 55 // Create nodes for testing.
Chris@17 56 $nodes = [];
Chris@17 57 foreach ($node_ranks as $node_rank) {
Chris@17 58 $settings = [
Chris@17 59 'type' => 'page',
Chris@17 60 'comment' => [
Chris@17 61 ['status' => CommentItemInterface::HIDDEN],
Chris@17 62 ],
Chris@17 63 'title' => 'Drupal rocks',
Chris@17 64 'body' => [['value' => "Drupal's search rocks"]],
Chris@17 65 // Node is one day old.
Chris@17 66 'created' => REQUEST_TIME - 24 * 3600,
Chris@17 67 'sticky' => 0,
Chris@17 68 'promote' => 0,
Chris@17 69 ];
Chris@17 70 foreach ([0, 1] as $num) {
Chris@17 71 if ($num == 1) {
Chris@17 72 switch ($node_rank) {
Chris@17 73 case 'sticky':
Chris@17 74 case 'promote':
Chris@17 75 $settings[$node_rank] = 1;
Chris@17 76 break;
Chris@17 77 case 'relevance':
Chris@17 78 $settings['body'][0]['value'] .= " really rocks";
Chris@17 79 break;
Chris@17 80 case 'recent':
Chris@17 81 // Node is 1 hour hold.
Chris@17 82 $settings['created'] = REQUEST_TIME - 3600;
Chris@17 83 break;
Chris@17 84 case 'comments':
Chris@17 85 $settings['comment'][0]['status'] = CommentItemInterface::OPEN;
Chris@17 86 break;
Chris@17 87 }
Chris@17 88 }
Chris@17 89 $nodes[$node_rank][$num] = $this->drupalCreateNode($settings);
Chris@17 90 }
Chris@17 91 }
Chris@17 92
Chris@17 93 // Add a comment to one of the nodes.
Chris@17 94 $edit = [];
Chris@17 95 $edit['subject[0][value]'] = 'my comment title';
Chris@17 96 $edit['comment_body[0][value]'] = 'some random comment';
Chris@17 97 $this->drupalGet('comment/reply/node/' . $nodes['comments'][1]->id() . '/comment');
Chris@17 98 $this->drupalPostForm(NULL, $edit, t('Preview'));
Chris@17 99 $this->drupalPostForm(NULL, $edit, t('Save'));
Chris@17 100
Chris@17 101 // Enable counting of statistics.
Chris@17 102 $this->config('statistics.settings')->set('count_content_views', 1)->save();
Chris@17 103
Chris@17 104 // Simulating content views is kind of difficult in the test. Leave that
Chris@17 105 // to the Statistics module. So instead go ahead and manually update the
Chris@17 106 // counter for this node.
Chris@17 107 $nid = $nodes['views'][1]->id();
Chris@18 108 Database::getConnection()->insert('node_counter')
Chris@17 109 ->fields(['totalcount' => 5, 'daycount' => 5, 'timestamp' => REQUEST_TIME, 'nid' => $nid])
Chris@17 110 ->execute();
Chris@17 111
Chris@17 112 // Run cron to update the search index and comment/statistics totals.
Chris@17 113 $this->cronRun();
Chris@17 114
Chris@17 115 // Test that the settings form displays the content ranking section.
Chris@17 116 $this->drupalGet('admin/config/search/pages/manage/node_search');
Chris@17 117 $this->assertText(t('Content ranking'));
Chris@17 118
Chris@17 119 // Check that all rankings are visible and set to 0.
Chris@17 120 foreach ($node_ranks as $node_rank) {
Chris@17 121 $this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="0"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 0.');
Chris@17 122 }
Chris@17 123
Chris@17 124 // Test each of the possible rankings.
Chris@17 125 $edit = [];
Chris@17 126 foreach ($node_ranks as $node_rank) {
Chris@17 127 // Enable the ranking we are testing.
Chris@17 128 $edit['rankings[' . $node_rank . '][value]'] = 10;
Chris@17 129 $this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
Chris@17 130 $this->drupalGet('admin/config/search/pages/manage/node_search');
Chris@17 131 $this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="10"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 10.');
Chris@17 132
Chris@17 133 // Reload the plugin to get the up-to-date values.
Chris@17 134 $this->nodeSearch = SearchPage::load('node_search');
Chris@17 135 // Do the search and assert the results.
Chris@17 136 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
Chris@17 137 $set = $this->nodeSearch->getPlugin()->execute();
Chris@17 138 $this->assertEqual($set[0]['node']->id(), $nodes[$node_rank][1]->id(), 'Search ranking "' . $node_rank . '" order.');
Chris@17 139
Chris@17 140 // Clear this ranking for the next test.
Chris@17 141 $edit['rankings[' . $node_rank . '][value]'] = 0;
Chris@17 142 }
Chris@17 143
Chris@17 144 // Save the final node_rank change then check that all rankings are visible
Chris@17 145 // and have been set back to 0.
Chris@17 146 $this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
Chris@17 147 $this->drupalGet('admin/config/search/pages/manage/node_search');
Chris@17 148 foreach ($node_ranks as $node_rank) {
Chris@17 149 $this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="0"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 0.');
Chris@17 150 }
Chris@17 151
Chris@17 152 // Try with sticky, then promoted. This is a test for issue
Chris@17 153 // https://www.drupal.org/node/771596.
Chris@17 154 $node_ranks = [
Chris@17 155 'sticky' => 10,
Chris@17 156 'promote' => 1,
Chris@17 157 'relevance' => 0,
Chris@17 158 'recent' => 0,
Chris@17 159 'comments' => 0,
Chris@17 160 'views' => 0,
Chris@17 161 ];
Chris@17 162 $configuration = $this->nodeSearch->getPlugin()->getConfiguration();
Chris@17 163 foreach ($node_ranks as $var => $value) {
Chris@17 164 $configuration['rankings'][$var] = $value;
Chris@17 165 }
Chris@17 166 $this->nodeSearch->getPlugin()->setConfiguration($configuration);
Chris@17 167 $this->nodeSearch->save();
Chris@17 168
Chris@17 169 // Do the search and assert the results. The sticky node should show up
Chris@17 170 // first, then the promoted node, then all the rest.
Chris@17 171 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
Chris@17 172 $set = $this->nodeSearch->getPlugin()->execute();
Chris@17 173 $this->assertEqual($set[0]['node']->id(), $nodes['sticky'][1]->id(), 'Search ranking for sticky first worked.');
Chris@17 174 $this->assertEqual($set[1]['node']->id(), $nodes['promote'][1]->id(), 'Search ranking for promoted second worked.');
Chris@17 175
Chris@17 176 // Try with recent, then comments. This is a test for issues
Chris@17 177 // https://www.drupal.org/node/771596 and
Chris@17 178 // https://www.drupal.org/node/303574.
Chris@17 179 $node_ranks = [
Chris@17 180 'sticky' => 0,
Chris@17 181 'promote' => 0,
Chris@17 182 'relevance' => 0,
Chris@17 183 'recent' => 10,
Chris@17 184 'comments' => 1,
Chris@17 185 'views' => 0,
Chris@17 186 ];
Chris@17 187 $configuration = $this->nodeSearch->getPlugin()->getConfiguration();
Chris@17 188 foreach ($node_ranks as $var => $value) {
Chris@17 189 $configuration['rankings'][$var] = $value;
Chris@17 190 }
Chris@17 191 $this->nodeSearch->getPlugin()->setConfiguration($configuration);
Chris@17 192 $this->nodeSearch->save();
Chris@17 193
Chris@17 194 // Do the search and assert the results. The recent node should show up
Chris@17 195 // first, then the commented node, then all the rest.
Chris@17 196 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
Chris@17 197 $set = $this->nodeSearch->getPlugin()->execute();
Chris@17 198 $this->assertEqual($set[0]['node']->id(), $nodes['recent'][1]->id(), 'Search ranking for recent first worked.');
Chris@17 199 $this->assertEqual($set[1]['node']->id(), $nodes['comments'][1]->id(), 'Search ranking for comments second worked.');
Chris@17 200
Chris@17 201 }
Chris@17 202
Chris@17 203 /**
Chris@17 204 * Test rankings of HTML tags.
Chris@17 205 */
Chris@17 206 public function testHTMLRankings() {
Chris@17 207 $full_html_format = FilterFormat::create([
Chris@17 208 'format' => 'full_html',
Chris@17 209 'name' => 'Full HTML',
Chris@17 210 ]);
Chris@17 211 $full_html_format->save();
Chris@17 212
Chris@17 213 // Test HTML tags with different weights.
Chris@17 214 $sorted_tags = ['h1', 'h2', 'h3', 'h4', 'a', 'h5', 'h6', 'notag'];
Chris@17 215 $shuffled_tags = $sorted_tags;
Chris@17 216
Chris@17 217 // Shuffle tags to ensure HTML tags are ranked properly.
Chris@17 218 shuffle($shuffled_tags);
Chris@17 219 $settings = [
Chris@17 220 'type' => 'page',
Chris@17 221 'title' => 'Simple node',
Chris@17 222 ];
Chris@17 223 $nodes = [];
Chris@17 224 foreach ($shuffled_tags as $tag) {
Chris@17 225 switch ($tag) {
Chris@17 226 case 'a':
Chris@17 227 $settings['body'] = [['value' => \Drupal::l('Drupal Rocks', new Url('<front>')), 'format' => 'full_html']];
Chris@17 228 break;
Chris@17 229 case 'notag':
Chris@17 230 $settings['body'] = [['value' => 'Drupal Rocks']];
Chris@17 231 break;
Chris@17 232 default:
Chris@17 233 $settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
Chris@17 234 break;
Chris@17 235 }
Chris@17 236 $nodes[$tag] = $this->drupalCreateNode($settings);
Chris@17 237 }
Chris@17 238
Chris@17 239 // Update the search index.
Chris@17 240 $this->nodeSearch->getPlugin()->updateIndex();
Chris@17 241 search_update_totals();
Chris@17 242
Chris@17 243 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
Chris@17 244 // Do the search and assert the results.
Chris@17 245 $set = $this->nodeSearch->getPlugin()->execute();
Chris@17 246
Chris@17 247 // Test the ranking of each tag.
Chris@17 248 foreach ($sorted_tags as $tag_rank => $tag) {
Chris@17 249 // Assert the results.
Chris@17 250 if ($tag == 'notag') {
Chris@17 251 $this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for plain text order.');
Chris@17 252 }
Chris@17 253 else {
Chris@17 254 $this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for "&lt;' . $sorted_tags[$tag_rank] . '&gt;" order.');
Chris@17 255 }
Chris@17 256 }
Chris@17 257
Chris@17 258 // Test tags with the same weight against the sorted tags.
Chris@17 259 $unsorted_tags = ['u', 'b', 'i', 'strong', 'em'];
Chris@17 260 foreach ($unsorted_tags as $tag) {
Chris@17 261 $settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
Chris@17 262 $node = $this->drupalCreateNode($settings);
Chris@17 263
Chris@17 264 // Update the search index.
Chris@17 265 $this->nodeSearch->getPlugin()->updateIndex();
Chris@17 266 search_update_totals();
Chris@17 267
Chris@17 268 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
Chris@17 269 // Do the search and assert the results.
Chris@17 270 $set = $this->nodeSearch->getPlugin()->execute();
Chris@17 271
Chris@17 272 // Ranking should always be second to last.
Chris@17 273 $set = array_slice($set, -2, 1);
Chris@17 274
Chris@17 275 // Assert the results.
Chris@17 276 $this->assertEqual($set[0]['node']->id(), $node->id(), 'Search tag ranking for "&lt;' . $tag . '&gt;" order.');
Chris@17 277
Chris@17 278 // Delete node so it doesn't show up in subsequent search results.
Chris@17 279 $node->delete();
Chris@17 280 }
Chris@17 281 }
Chris@17 282
Chris@17 283 }