Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Form controller for search_embedded_form form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SearchEmbeddedForm extends FormBase {
|
||||
|
||||
|
@ -48,7 +50,7 @@ class SearchEmbeddedForm extends FormBase {
|
|||
$state = \Drupal::state();
|
||||
$submit_count = (int) $state->get('search_embedded_form.submit_count');
|
||||
$state->set('search_embedded_form.submit_count', $submit_count + 1);
|
||||
drupal_set_message($this->t('Test form was submitted'));
|
||||
$this->messenger()->addStatus($this->t('Test form was submitted'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,5 +5,4 @@ package: Testing
|
|||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- test_page_test
|
||||
|
||||
- drupal:test_page_test
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\search_extra_type\Plugin\Search;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Routing\UrlGeneratorTrait;
|
||||
use Drupal\Core\Url;
|
||||
|
@ -59,7 +59,7 @@ class SearchExtraTypeSearch extends ConfigurableSearchPluginBase {
|
|||
'link' => Url::fromRoute('test_page_test.test_page')->toString(),
|
||||
'type' => 'Dummy result type',
|
||||
'title' => 'Dummy title',
|
||||
'snippet' => SafeMarkup::format("Dummy search snippet to display. Keywords: @keywords\n\nConditions: @search_parameters", ['@keywords' => $this->keywords, '@search_parameters' => print_r($this->searchParameters, TRUE)]),
|
||||
'snippet' => new FormattableMarkup("Dummy search snippet to display. Keywords: @keywords\n\nConditions: @search_parameters", ['@keywords' => $this->keywords, '@search_parameters' => print_r($this->searchParameters, TRUE)]),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ class SearchExtraTypeSearch extends ConfigurableSearchPluginBase {
|
|||
$pager = [
|
||||
'#type' => 'pager',
|
||||
];
|
||||
$output['suffix']['#markup'] = '</ol>' . drupal_render($pager);
|
||||
$output['suffix']['#markup'] = '</ol>' . \Drupal::service('renderer')->render($pager);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@ function search_langcode_test_search_preprocess($text, $langcode = NULL) {
|
|||
// Prints the langcode for testPreprocessLangcode() and adds some
|
||||
// extra text.
|
||||
else {
|
||||
drupal_set_message('Langcode Preprocess Test: ' . $langcode);
|
||||
\Drupal::messenger()->addStatus('Langcode Preprocess Test: ' . $langcode);
|
||||
$text .= 'Additional text';
|
||||
}
|
||||
}
|
||||
// Prints the langcode for testPreprocessLangcode().
|
||||
elseif (isset($langcode)) {
|
||||
drupal_set_message('Langcode Preprocess Test: ' . $langcode);
|
||||
\Drupal::messenger()->addStatus('Langcode Preprocess Test: ' . $langcode);
|
||||
|
||||
// Preprocessing for the excerpt test.
|
||||
if ($langcode == 'ex') {
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\search\Functional\Rest\SearchPageResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class SearchPageHalJsonAnonTest extends SearchPageResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\search\Functional\Rest\SearchPageResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class SearchPageHalJsonBasicAuthTest extends SearchPageResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\search\Functional\Rest\SearchPageResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class SearchPageHalJsonCookieTest extends SearchPageResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class SearchPageJsonAnonTest extends SearchPageResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class SearchPageJsonBasicAuthTest extends SearchPageResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class SearchPageJsonCookieTest extends SearchPageResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\search\Entity\SearchPage;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
abstract class SearchPageResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'search'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'search_page';
|
||||
|
||||
/**
|
||||
* @var \Drupal\search\SearchPageInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$this->grantPermissionsToTestedRole(['access content']);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
case 'PATCH':
|
||||
case 'DELETE':
|
||||
$this->grantPermissionsToTestedRole(['administer search']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$search_page = SearchPage::create([
|
||||
'id' => 'hinode_search',
|
||||
'plugin' => 'node_search',
|
||||
'label' => 'Search of magnetic activity of the Sun',
|
||||
'path' => 'sun',
|
||||
]);
|
||||
$search_page->save();
|
||||
return $search_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'configuration' => [
|
||||
'rankings' => [],
|
||||
],
|
||||
'dependencies' => [
|
||||
'module' => ['node'],
|
||||
],
|
||||
'id' => 'hinode_search',
|
||||
'label' => 'Search of magnetic activity of the Sun',
|
||||
'langcode' => 'en',
|
||||
'path' => 'sun',
|
||||
'plugin' => 'node_search',
|
||||
'status' => TRUE,
|
||||
'uuid' => $this->entity->uuid(),
|
||||
'weight' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
return "The 'access content' permission is required.";
|
||||
|
||||
default:
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessCacheability() {
|
||||
// @see \Drupal\search\SearchPageAccessControlHandler::checkAccess()
|
||||
return parent::getExpectedUnauthorizedAccessCacheability()
|
||||
->addCacheTags(['config:search.page.hinode_search']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class SearchPageXmlAnonTest extends SearchPageResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class SearchPageXmlBasicAuthTest extends SearchPageResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class SearchPageXmlCookieTest extends SearchPageResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Indexes content and tests the advanced search form.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchAdvancedSearchFormTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search', 'dblog'];
|
||||
|
||||
/**
|
||||
* A node to use for testing.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
// Create and log in user.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'administer nodes']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
// Create initial node.
|
||||
$this->node = $this->drupalCreateNode();
|
||||
|
||||
// First update the index. This does the initial processing.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
|
||||
// Then, run the shutdown function. Testing is a unique case where indexing
|
||||
// and searching has to happen in the same request, so running the shutdown
|
||||
// function manually is needed to finish the indexing process.
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests advanced search by node type.
|
||||
*/
|
||||
public function testNodeType() {
|
||||
// Verify some properties of the node that was created.
|
||||
$this->assertTrue($this->node->getType() == 'page', 'Node type is Basic page.');
|
||||
$dummy_title = 'Lorem ipsum';
|
||||
$this->assertNotEqual($dummy_title, $this->node->label(), "Dummy title doesn't equal node title.");
|
||||
|
||||
// Search for the dummy title with a GET query.
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $dummy_title]]);
|
||||
$this->assertNoText($this->node->label(), 'Basic page node is not found with dummy title.');
|
||||
|
||||
// Search for the title of the node with a GET query.
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $this->node->label()]]);
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with GET query.');
|
||||
|
||||
// Search for the title of the node with a POST query.
|
||||
$edit = ['or' => $this->node->label()];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with POST query.');
|
||||
|
||||
// Search by node type.
|
||||
$this->drupalPostForm('search/node', array_merge($edit, ['type[page]' => 'page']), 'edit-submit--2');
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with POST query and type:page.');
|
||||
|
||||
$this->drupalPostForm('search/node', array_merge($edit, ['type[article]' => 'article']), 'edit-submit--2');
|
||||
$this->assertText('search yielded no results', 'Article node is not found with POST query and type:article.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that after submitting the advanced search form, the form is refilled.
|
||||
*/
|
||||
public function testFormRefill() {
|
||||
$edit = [
|
||||
'keys' => 'cat',
|
||||
'or' => 'dog gerbil',
|
||||
'phrase' => 'pets are nice',
|
||||
'negative' => 'fish snake',
|
||||
'type[page]' => 'page',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
|
||||
// Test that the encoded query appears in the page title. Only test the
|
||||
// part not including the quote, because assertText() cannot seem to find
|
||||
// the quote marks successfully.
|
||||
$this->assertText('Search for cat dog OR gerbil -fish -snake');
|
||||
|
||||
// Verify that all of the form fields are filled out.
|
||||
foreach ($edit as $key => $value) {
|
||||
if ($key != 'type[page]') {
|
||||
$elements = $this->xpath('//input[@name=:name]', [':name' => $key]);
|
||||
$this->assertTrue(isset($elements[0]) && $elements[0]->getValue() == $value, "Field $key is set to $value");
|
||||
}
|
||||
else {
|
||||
$elements = $this->xpath('//input[@name=:name]', [':name' => $key]);
|
||||
$this->assertTrue(isset($elements[0]) && !empty($elements[0]->getAttribute('checked')), "Field $key is checked");
|
||||
}
|
||||
}
|
||||
|
||||
// Now test by submitting the or/not part of the query in the main
|
||||
// search box, and verify that the advanced form is not filled out.
|
||||
// (It shouldn't be filled out unless you submit values in those fields.)
|
||||
$edit2 = ['keys' => 'cat dog OR gerbil -fish -snake'];
|
||||
$this->drupalPostForm('search/node', $edit2, 'edit-submit--2');
|
||||
$this->assertText('Search for cat dog OR gerbil -fish -snake');
|
||||
foreach ($edit as $key => $value) {
|
||||
if ($key != 'type[page]') {
|
||||
$elements = $this->xpath('//input[@name=:name]', [':name' => $key]);
|
||||
$this->assertFalse(isset($elements[0]) && $elements[0]->getValue() == $value, "Field $key is not set to $value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
109
web/core/modules/search/tests/src/Functional/SearchBlockTest.php
Normal file
109
web/core/modules/search/tests/src/Functional/SearchBlockTest.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests if the search form block is available.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchBlockTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'node', 'search', 'dblog'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and log in user.
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks', 'search content']);
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the search form block can be placed and works.
|
||||
*/
|
||||
public function testSearchFormBlock() {
|
||||
|
||||
// Test availability of the search block in the admin "Place blocks" list.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->getSession()->getPage()->findLink('Place block')->click();
|
||||
$this->assertLinkByHref('/admin/structure/block/add/search_form_block/classy', 0,
|
||||
'Did not find the search block in block candidate list.');
|
||||
|
||||
$block = $this->drupalPlaceBlock('search_form_block');
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($block->label(), 'Block title was found.');
|
||||
|
||||
// Check that name attribute is not empty.
|
||||
$pattern = "//input[@type='submit' and @name='']";
|
||||
$elements = $this->xpath($pattern);
|
||||
$this->assertTrue(empty($elements), 'The search input field does not have empty name attribute.');
|
||||
|
||||
// Test a normal search via the block form, from the front page.
|
||||
$terms = ['keys' => 'test'];
|
||||
$this->drupalPostForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
// Test a search from the block on a 404 page.
|
||||
$this->drupalGet('foo');
|
||||
$this->assertResponse(404);
|
||||
$this->drupalPostForm(NULL, $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
$visibility = $block->getVisibility();
|
||||
$visibility['request_path']['pages'] = 'search';
|
||||
$block->setVisibilityConfig('request_path', $visibility['request_path']);
|
||||
|
||||
$this->drupalPostForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
// Confirm that the form submits to the default search page.
|
||||
/** @var $search_page_repository \Drupal\search\SearchPageRepositoryInterface */
|
||||
$search_page_repository = \Drupal::service('search.search_page_repository');
|
||||
$entity_id = $search_page_repository->getDefaultSearchPage();
|
||||
$this->assertEqual(
|
||||
$this->getUrl(),
|
||||
\Drupal::url('search.view_' . $entity_id, [], ['query' => ['keys' => $terms['keys']], 'absolute' => TRUE]),
|
||||
'Submitted to correct URL.'
|
||||
);
|
||||
|
||||
// Test an empty search via the block form, from the front page.
|
||||
$terms = ['keys' => ''];
|
||||
$this->drupalPostForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Please enter some keywords');
|
||||
|
||||
// Confirm that the user is redirected to the search page, when form is
|
||||
// submitted empty.
|
||||
$this->assertEqual(
|
||||
$this->getUrl(),
|
||||
\Drupal::url('search.view_' . $entity_id, [], ['query' => ['keys' => ''], 'absolute' => TRUE]),
|
||||
'Redirected to correct URL.'
|
||||
);
|
||||
|
||||
// Test that after entering a too-short keyword in the form, you can then
|
||||
// search again with a longer keyword. First test using the block form.
|
||||
$this->drupalPostForm('node', ['keys' => $this->randomMachineName(1)], t('Search'));
|
||||
$this->assertText('You must include at least one keyword to match in the content', 'Keyword message is displayed when searching for short word');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed');
|
||||
$this->drupalPostForm(NULL, ['keys' => $this->randomMachineName()], t('Search'), [], 'search-block-form');
|
||||
$this->assertNoText('You must include at least one keyword to match in the content', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
// Same test again, using the search page form for the second search this
|
||||
// time.
|
||||
$this->drupalPostForm('node', ['keys' => $this->randomMachineName(1)], t('Search'));
|
||||
$this->drupalPostForm(NULL, ['keys' => $this->randomMachineName()], t('Search'), [], 'search-form');
|
||||
$this->assertNoText('You must include at least one keyword to match in the content', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace Drupal\Tests\search\Functional;
|
|||
|
||||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that comment count display toggles properly on comment status of node.
|
||||
|
@ -17,16 +18,14 @@ use Drupal\comment\Tests\CommentTestTrait;
|
|||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchCommentCountToggleTest extends SearchTestBase {
|
||||
class SearchCommentCountToggleTest extends BrowserTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'comment'];
|
||||
protected static $modules = ['node', 'comment', 'search', 'dblog'];
|
||||
|
||||
/**
|
||||
* A user with permission to search and post comments.
|
||||
|
@ -45,6 +44,8 @@ class SearchCommentCountToggleTest extends SearchTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
// Create searching user.
|
||||
$this->searchingUser = $this->drupalCreateUser(['search content', 'access content', 'access comments', 'post comments', 'skip comment approval']);
|
||||
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Behat\Mink\Exception\ResponseTextException;
|
||||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\Traits\Core\CronRunTrait;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
||||
/**
|
||||
* Tests integration searching comments.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchCommentTest extends BrowserTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use CronRunTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['filter', 'node', 'comment', 'search'];
|
||||
|
||||
/**
|
||||
* Test subject for comments.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $commentSubject;
|
||||
|
||||
/**
|
||||
* ID for the administrator role.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $adminRole;
|
||||
|
||||
/**
|
||||
* A user with various administrative permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Test node for searching.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
'weight' => 1,
|
||||
'filters' => [],
|
||||
]);
|
||||
$full_html_format->save();
|
||||
|
||||
// Create and log in an administrative user having access to the Full HTML
|
||||
// text format.
|
||||
$permissions = [
|
||||
'administer filters',
|
||||
$full_html_format->getPermissionName(),
|
||||
'administer permissions',
|
||||
'create page content',
|
||||
'post comments',
|
||||
'skip comment approval',
|
||||
'access comments',
|
||||
];
|
||||
$this->adminUser = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Add a comment field.
|
||||
$this->addDefaultCommentField('node', 'article');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that comments are rendered using proper format in search results.
|
||||
*/
|
||||
public function testSearchResultsComment() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Create basic_html format that escapes all HTML.
|
||||
$basic_html_format = FilterFormat::create([
|
||||
'format' => 'basic_html',
|
||||
'name' => 'Basic HTML',
|
||||
'weight' => 1,
|
||||
'filters' => [
|
||||
'filter_html_escape' => ['status' => 1],
|
||||
],
|
||||
'roles' => [RoleInterface::AUTHENTICATED_ID],
|
||||
]);
|
||||
$basic_html_format->save();
|
||||
|
||||
$comment_body = 'Test comment body';
|
||||
|
||||
// Make preview optional.
|
||||
$field = FieldConfig::loadByName('node', 'article', 'comment');
|
||||
$field->setSetting('preview', DRUPAL_OPTIONAL);
|
||||
$field->save();
|
||||
|
||||
// Allow anonymous users to search content.
|
||||
$edit = [
|
||||
RoleInterface::ANONYMOUS_ID . '[search content]' => 1,
|
||||
RoleInterface::ANONYMOUS_ID . '[access comments]' => 1,
|
||||
RoleInterface::ANONYMOUS_ID . '[post comments]' => 1,
|
||||
];
|
||||
$this->drupalPostForm('admin/people/permissions', $edit, t('Save permissions'));
|
||||
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode(['type' => 'article']);
|
||||
// Post a comment using 'Full HTML' text format.
|
||||
$edit_comment = [];
|
||||
$edit_comment['subject[0][value]'] = 'Test comment subject';
|
||||
$edit_comment['comment_body[0][value]'] = '<h1>' . $comment_body . '</h1>';
|
||||
$full_html_format_id = 'full_html';
|
||||
$edit_comment['comment_body[0][format]'] = $full_html_format_id;
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment, t('Save'));
|
||||
|
||||
// Post a comment with an evil script tag in the comment subject and a
|
||||
// script tag nearby a keyword in the comment body. Use the 'FULL HTML' text
|
||||
// format so the script tag stored.
|
||||
$edit_comment2 = [];
|
||||
$edit_comment2['subject[0][value]'] = "<script>alert('subjectkeyword');</script>";
|
||||
$edit_comment2['comment_body[0][value]'] = "nearbykeyword<script>alert('somethinggeneric');</script>";
|
||||
$edit_comment2['comment_body[0][format]'] = $full_html_format_id;
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment2, t('Save'));
|
||||
|
||||
// Post a comment with a keyword inside an evil script tag in the comment
|
||||
// body. Use the 'FULL HTML' text format so the script tag is stored.
|
||||
$edit_comment3 = [];
|
||||
$edit_comment3['subject[0][value]'] = 'asubject';
|
||||
$edit_comment3['comment_body[0][value]'] = "<script>alert('insidekeyword');</script>";
|
||||
$edit_comment3['comment_body[0][format]'] = $full_html_format_id;
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment3, t('Save'));
|
||||
|
||||
// Invoke search index update.
|
||||
$this->drupalLogout();
|
||||
$this->cronRun();
|
||||
|
||||
// Search for the comment subject.
|
||||
$edit = [
|
||||
'keys' => "'" . $edit_comment['subject[0][value]'] . "'",
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$node2 = $node_storage->load($node->id());
|
||||
$this->assertText($node2->label(), 'Node found in search results.');
|
||||
$this->assertText($edit_comment['subject[0][value]'], 'Comment subject found in search results.');
|
||||
|
||||
// Search for the comment body.
|
||||
$edit = [
|
||||
'keys' => "'" . $comment_body . "'",
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Search'));
|
||||
$this->assertText($node2->label(), 'Node found in search results.');
|
||||
|
||||
// Verify that comment is rendered using proper format.
|
||||
$this->assertText($comment_body, 'Comment body text found in search results.');
|
||||
$this->assertNoRaw(t('n/a'), 'HTML in comment body is not hidden.');
|
||||
$this->assertNoEscaped($edit_comment['comment_body[0][value]'], 'HTML in comment body is not escaped.');
|
||||
|
||||
// Search for the evil script comment subject.
|
||||
$edit = [
|
||||
'keys' => 'subjectkeyword',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// Verify the evil comment subject is escaped in search results.
|
||||
$this->assertRaw('<script>alert('<strong>subjectkeyword</strong>');');
|
||||
$this->assertNoRaw('<script>');
|
||||
|
||||
// Search for the keyword near the evil script tag in the comment body.
|
||||
$edit = [
|
||||
'keys' => 'nearbykeyword',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// Verify that nearby script tag in the evil comment body is stripped from
|
||||
// search results.
|
||||
$this->assertRaw('<strong>nearbykeyword</strong>');
|
||||
$this->assertNoRaw('<script>');
|
||||
|
||||
// Search for contents inside the evil script tag in the comment body.
|
||||
$edit = [
|
||||
'keys' => 'insidekeyword',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// @todo Verify the actual search results.
|
||||
// https://www.drupal.org/node/2551135
|
||||
|
||||
// Verify there is no script tag in search results.
|
||||
$this->assertNoRaw('<script>');
|
||||
|
||||
// Hide comments.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$node->set('comment', CommentItemInterface::HIDDEN);
|
||||
$node->save();
|
||||
|
||||
// Invoke search index update.
|
||||
$this->drupalLogout();
|
||||
$this->cronRun();
|
||||
|
||||
// Search for $title.
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText(t('Your search yielded no results.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify access rules for comment indexing with different permissions.
|
||||
*/
|
||||
public function testSearchResultsCommentAccess() {
|
||||
$comment_body = 'Test comment body';
|
||||
$this->commentSubject = 'Test comment subject';
|
||||
$roles = $this->adminUser->getRoles(TRUE);
|
||||
$this->adminRole = $roles[0];
|
||||
|
||||
// Create a node.
|
||||
// Make preview optional.
|
||||
$field = FieldConfig::loadByName('node', 'article', 'comment');
|
||||
$field->setSetting('preview', DRUPAL_OPTIONAL);
|
||||
$field->save();
|
||||
$this->node = $this->drupalCreateNode(['type' => 'article']);
|
||||
|
||||
// Post a comment using 'Full HTML' text format.
|
||||
$edit_comment = [];
|
||||
$edit_comment['subject[0][value]'] = $this->commentSubject;
|
||||
$edit_comment['comment_body[0][value]'] = '<h1>' . $comment_body . '</h1>';
|
||||
$this->drupalPostForm('comment/reply/node/' . $this->node->id() . '/comment', $edit_comment, t('Save'));
|
||||
|
||||
$this->drupalLogout();
|
||||
$this->setRolePermissions(RoleInterface::ANONYMOUS_ID);
|
||||
$this->assertCommentAccess(FALSE, 'Anon user has search permission but no access comments permission, comments should not be indexed');
|
||||
|
||||
$this->setRolePermissions(RoleInterface::ANONYMOUS_ID, TRUE);
|
||||
$this->assertCommentAccess(TRUE, 'Anon user has search permission and access comments permission, comments should be indexed');
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/people/permissions');
|
||||
|
||||
// Disable search access for authenticated user to test admin user.
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, FALSE, FALSE);
|
||||
|
||||
$this->setRolePermissions($this->adminRole);
|
||||
$this->assertCommentAccess(FALSE, 'Admin user has search permission but no access comments permission, comments should not be indexed');
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
$this->setRolePermissions($this->adminRole, TRUE);
|
||||
$this->assertCommentAccess(TRUE, 'Admin user has search permission and access comments permission, comments should be indexed');
|
||||
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID);
|
||||
$this->assertCommentAccess(FALSE, 'Authenticated user has search permission but no access comments permission, comments should not be indexed');
|
||||
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE);
|
||||
$this->assertCommentAccess(TRUE, 'Authenticated user has search permission and access comments permission, comments should be indexed');
|
||||
|
||||
// Verify that access comments permission is inherited from the
|
||||
// authenticated role.
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE, FALSE);
|
||||
$this->setRolePermissions($this->adminRole);
|
||||
$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');
|
||||
|
||||
// Verify that search content permission is inherited from the authenticated
|
||||
// role.
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE, TRUE);
|
||||
$this->setRolePermissions($this->adminRole, TRUE, FALSE);
|
||||
$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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permissions for role.
|
||||
*/
|
||||
public function setRolePermissions($rid, $access_comments = FALSE, $search_content = TRUE) {
|
||||
$permissions = [
|
||||
'access comments' => $access_comments,
|
||||
'search content' => $search_content,
|
||||
];
|
||||
user_role_change_permissions($rid, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update search index and search for comment.
|
||||
*/
|
||||
public function assertCommentAccess($assume_access, $message) {
|
||||
// Invoke search index update.
|
||||
search_mark_for_reindex('node_search', $this->node->id());
|
||||
$this->cronRun();
|
||||
|
||||
// Search for the comment subject.
|
||||
$edit = [
|
||||
'keys' => "'" . $this->commentSubject . "'",
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
try {
|
||||
if ($assume_access) {
|
||||
$this->assertSession()->pageTextContains($this->node->label());
|
||||
$this->assertSession()->pageTextContains($this->commentSubject);
|
||||
}
|
||||
else {
|
||||
$this->assertSession()->pageTextContains(t('Your search yielded no results.'));
|
||||
}
|
||||
}
|
||||
catch (ResponseTextException $exception) {
|
||||
$this->fail($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that 'add new comment' does not appear in search results or index.
|
||||
*/
|
||||
public function testAddNewComment() {
|
||||
// Create a node with a short body.
|
||||
$settings = [
|
||||
'type' => 'article',
|
||||
'title' => 'short title',
|
||||
'body' => [['value' => 'short body text']],
|
||||
];
|
||||
|
||||
$user = $this->drupalCreateUser([
|
||||
'search content',
|
||||
'create article content',
|
||||
'access content',
|
||||
'post comments',
|
||||
'access comments',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
// Verify that if you view the node on its own page, 'add new comment'
|
||||
// is there.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText(t('Add new comment'));
|
||||
|
||||
// Run cron to index this page.
|
||||
$this->drupalLogout();
|
||||
$this->cronRun();
|
||||
|
||||
// Search for 'comment'. Should be no results.
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalPostForm('search/node', ['keys' => 'comment'], t('Search'));
|
||||
$this->assertText(t('Your search yielded no results'));
|
||||
|
||||
// Search for the node title. Should be found, and 'Add new comment' should
|
||||
// not be part of the search snippet.
|
||||
$this->drupalPostForm('search/node', ['keys' => 'short'], t('Search'));
|
||||
$this->assertText($node->label(), 'Search for keyword worked');
|
||||
$this->assertNoText(t('Add new comment'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,405 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\search\Entity\SearchPage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Verify the search config settings form.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchConfigSettingsFormTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'dblog', 'node', 'search', 'search_extra_type', 'test_page_test'];
|
||||
|
||||
/**
|
||||
* User who can search and administer search.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $searchUser;
|
||||
|
||||
/**
|
||||
* Node indexed for searching.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $searchNode;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Log in as a user that can create and search content.
|
||||
$this->searchUser = $this->drupalCreateUser(['search content', 'administer search', 'administer nodes', 'bypass node access', 'access user profiles', 'administer users', 'administer blocks', 'access site reports']);
|
||||
$this->drupalLogin($this->searchUser);
|
||||
|
||||
// Add a single piece of content and index it.
|
||||
$node = $this->drupalCreateNode();
|
||||
$this->searchNode = $node;
|
||||
// Link the node to itself to test that it's only indexed once. The content
|
||||
// also needs the word "pizza" so we can use it as the search keyword.
|
||||
$body_key = 'body[0][value]';
|
||||
$edit[$body_key] = \Drupal::l($node->label(), $node->urlInfo()) . ' pizza sandwich';
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
|
||||
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Enable the search block.
|
||||
$this->drupalPlaceBlock('search_form_block');
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the search settings form.
|
||||
*/
|
||||
public function testSearchSettingsPage() {
|
||||
|
||||
// Test that the settings form displays the correct count of items left to index.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->assertText(t('There are @count items left to index.', ['@count' => 0]));
|
||||
|
||||
// Test the re-index button.
|
||||
$this->drupalPostForm('admin/config/search/pages', [], t('Re-index site'));
|
||||
$this->assertText(t('Are you sure you want to re-index the site'));
|
||||
$this->drupalPostForm('admin/config/search/pages/reindex', [], t('Re-index site'));
|
||||
$this->assertText(t('All search indexes will be rebuilt'));
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->assertText(t('There is 1 item left to index.'));
|
||||
|
||||
// Test that the form saves with the default values.
|
||||
$this->drupalPostForm('admin/config/search/pages', [], t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'), 'Form saves with the default values.');
|
||||
|
||||
// Test that the form does not save with an invalid word length.
|
||||
$edit = [
|
||||
'minimum_word_size' => $this->randomMachineName(3),
|
||||
];
|
||||
$this->drupalPostForm('admin/config/search/pages', $edit, t('Save configuration'));
|
||||
$this->assertNoText(t('The configuration options have been saved.'), 'Form does not save with an invalid word length.');
|
||||
|
||||
// Test logging setting. It should be off by default.
|
||||
$text = $this->randomMachineName(5);
|
||||
$this->drupalPostForm('search/node', ['keys' => $text], t('Search'));
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertNoLink('Searched Content for ' . $text . '.', 'Search was not logged');
|
||||
|
||||
// Turn on logging.
|
||||
$edit = ['logging' => TRUE];
|
||||
$this->drupalPostForm('admin/config/search/pages', $edit, t('Save configuration'));
|
||||
$text = $this->randomMachineName(5);
|
||||
$this->drupalPostForm('search/node', ['keys' => $text], t('Search'));
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertLink('Searched Content for ' . $text . '.', 0, 'Search was logged');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies plugin-supplied settings form.
|
||||
*/
|
||||
public function testSearchModuleSettingsPage() {
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->clickLink(t('Edit'), 1);
|
||||
|
||||
// Ensure that the default setting was picked up from the default config
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-extra-type-settings-boost"]//option[@value="bi" and @selected="selected"]'), 'Module specific settings are picked up from the default config');
|
||||
|
||||
// Change extra type setting and also modify a common search setting.
|
||||
$edit = [
|
||||
'extra_type_settings[boost]' => 'ii',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save search page'));
|
||||
|
||||
// Ensure that the modifications took effect.
|
||||
$this->assertRaw(t('The %label search page has been updated.', ['%label' => 'Dummy search type']));
|
||||
$this->drupalGet('admin/config/search/pages/manage/dummy_search_type');
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-extra-type-settings-boost"]//option[@value="ii" and @selected="selected"]'), 'Module specific settings can be changed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that you can disable individual search plugins.
|
||||
*/
|
||||
public function testSearchModuleDisabling() {
|
||||
// Array of search plugins to test: 'keys' are the keywords to search for,
|
||||
// and 'text' is the text to assert is on the results page.
|
||||
$plugin_info = [
|
||||
'node_search' => [
|
||||
'keys' => 'pizza',
|
||||
'text' => $this->searchNode->label(),
|
||||
],
|
||||
'user_search' => [
|
||||
'keys' => $this->searchUser->getUsername(),
|
||||
'text' => $this->searchUser->getEmail(),
|
||||
],
|
||||
'dummy_search_type' => [
|
||||
'keys' => 'foo',
|
||||
'text' => 'Dummy search snippet to display',
|
||||
],
|
||||
];
|
||||
$plugins = array_keys($plugin_info);
|
||||
/** @var $entities \Drupal\search\SearchPageInterface[] */
|
||||
$entities = SearchPage::loadMultiple();
|
||||
// Disable all of the search pages.
|
||||
foreach ($entities as $entity) {
|
||||
$entity->disable()->save();
|
||||
}
|
||||
|
||||
// Test each plugin if it's enabled as the only search plugin.
|
||||
foreach ($entities as $entity_id => $entity) {
|
||||
$this->setDefaultThroughUi($entity_id);
|
||||
|
||||
// Run a search from the correct search URL.
|
||||
$info = $plugin_info[$entity_id];
|
||||
$this->drupalGet('search/' . $entity->getPath(), ['query' => ['keys' => $info['keys']]]);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('no results', $entity->label() . ' search found results');
|
||||
$this->assertText($info['text'], 'Correct search text found');
|
||||
|
||||
// Verify that other plugin search tab labels are not visible.
|
||||
foreach ($plugins as $other) {
|
||||
if ($other != $entity_id) {
|
||||
$label = $entities[$other]->label();
|
||||
$this->assertNoText($label, $label . ' search tab is not shown');
|
||||
}
|
||||
}
|
||||
|
||||
// Run a search from the search block on the node page. Verify you get
|
||||
// to this plugin's search results page.
|
||||
$terms = ['keys' => $info['keys']];
|
||||
$this->drupalPostForm('node', $terms, t('Search'));
|
||||
$current = $this->getURL();
|
||||
$expected = \Drupal::url('search.view_' . $entity->id(), [], ['query' => ['keys' => $info['keys']], 'absolute' => TRUE]);
|
||||
$this->assertEqual($current, $expected, 'Block redirected to right search page');
|
||||
|
||||
// Try an invalid search path, which should 404.
|
||||
$this->drupalGet('search/not_a_plugin_path');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$entity->disable()->save();
|
||||
}
|
||||
|
||||
// Set the node search as default.
|
||||
$this->setDefaultThroughUi('node_search');
|
||||
|
||||
// Test with all search plugins enabled. When you go to the search
|
||||
// page or run search, all plugins should be shown.
|
||||
foreach ($entities as $entity) {
|
||||
$entity->enable()->save();
|
||||
}
|
||||
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
$paths = [
|
||||
['path' => 'search/node', 'options' => ['query' => ['keys' => 'pizza']]],
|
||||
['path' => 'search/node', 'options' => []],
|
||||
];
|
||||
|
||||
foreach ($paths as $item) {
|
||||
$this->drupalGet($item['path'], $item['options']);
|
||||
foreach ($plugins as $entity_id) {
|
||||
$label = $entities[$entity_id]->label();
|
||||
$this->assertText($label, format_string('%label search tab is shown', ['%label' => $label]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the ordering of search pages on a clean install.
|
||||
*/
|
||||
public function testDefaultSearchPageOrdering() {
|
||||
$this->drupalGet('search');
|
||||
$elements = $this->xpath('//*[contains(@class, :class)]//a', [':class' => 'tabs primary']);
|
||||
$this->assertIdentical($elements[0]->getAttribute('href'), \Drupal::url('search.view_node_search'));
|
||||
$this->assertIdentical($elements[1]->getAttribute('href'), \Drupal::url('search.view_dummy_search_type'));
|
||||
$this->assertIdentical($elements[2]->getAttribute('href'), \Drupal::url('search.view_user_search'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multiple search pages of the same type.
|
||||
*/
|
||||
public function testMultipleSearchPages() {
|
||||
$this->assertDefaultSearch('node_search', 'The default page is set to the installer default.');
|
||||
$search_storage = \Drupal::entityManager()->getStorage('search_page');
|
||||
$entities = $search_storage->loadMultiple();
|
||||
$search_storage->delete($entities);
|
||||
$this->assertDefaultSearch(FALSE);
|
||||
|
||||
// Ensure that no search pages are configured.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->assertText(t('No search pages have been configured.'));
|
||||
|
||||
// Add a search page.
|
||||
$edit = [];
|
||||
$edit['search_type'] = 'search_extra_type_search';
|
||||
$this->drupalPostForm(NULL, $edit, t('Add search page'));
|
||||
$this->assertTitle('Add new search page | Drupal');
|
||||
|
||||
$first = [];
|
||||
$first['label'] = $this->randomString();
|
||||
$first_id = $first['id'] = strtolower($this->randomMachineName(8));
|
||||
$first['path'] = strtolower($this->randomMachineName(8));
|
||||
$this->drupalPostForm(NULL, $first, t('Save'));
|
||||
$this->assertDefaultSearch($first_id, 'The default page matches the only search page.');
|
||||
$this->assertRaw(t('The %label search page has been added.', ['%label' => $first['label']]));
|
||||
|
||||
// Attempt to add a search page with an existing path.
|
||||
$edit = [];
|
||||
$edit['search_type'] = 'search_extra_type_search';
|
||||
$this->drupalPostForm(NULL, $edit, t('Add search page'));
|
||||
$edit = [];
|
||||
$edit['label'] = $this->randomString();
|
||||
$edit['id'] = strtolower($this->randomMachineName(8));
|
||||
$edit['path'] = $first['path'];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->assertText(t('The search page path must be unique.'));
|
||||
|
||||
// Add a second search page.
|
||||
$second = [];
|
||||
$second['label'] = $this->randomString();
|
||||
$second_id = $second['id'] = strtolower($this->randomMachineName(8));
|
||||
$second['path'] = strtolower($this->randomMachineName(8));
|
||||
$this->drupalPostForm(NULL, $second, t('Save'));
|
||||
$this->assertDefaultSearch($first_id, 'The default page matches the only search page.');
|
||||
|
||||
// Ensure both search pages have their tabs displayed.
|
||||
$this->drupalGet('search');
|
||||
$elements = $this->xpath('//*[contains(@class, :class)]//a', [':class' => 'tabs primary']);
|
||||
$this->assertIdentical($elements[0]->getAttribute('href'), Url::fromRoute('search.view_' . $first_id)->toString());
|
||||
$this->assertIdentical($elements[1]->getAttribute('href'), Url::fromRoute('search.view_' . $second_id)->toString());
|
||||
|
||||
// Switch the weight of the search pages and check the order of the tabs.
|
||||
$edit = [
|
||||
'entities[' . $first_id . '][weight]' => 10,
|
||||
'entities[' . $second_id . '][weight]' => -10,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/search/pages', $edit, t('Save configuration'));
|
||||
$this->drupalGet('search');
|
||||
$elements = $this->xpath('//*[contains(@class, :class)]//a', [':class' => 'tabs primary']);
|
||||
$this->assertIdentical($elements[0]->getAttribute('href'), Url::fromRoute('search.view_' . $second_id)->toString());
|
||||
$this->assertIdentical($elements[1]->getAttribute('href'), Url::fromRoute('search.view_' . $first_id)->toString());
|
||||
|
||||
// Check the initial state of the search pages.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->verifySearchPageOperations($first_id, TRUE, FALSE, FALSE, FALSE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, TRUE, TRUE, FALSE);
|
||||
|
||||
// Change the default search page.
|
||||
$this->clickLink(t('Set as default'));
|
||||
$this->assertRaw(t('The default search page is now %label. Be sure to check the ordering of your search pages.', ['%label' => $second['label']]));
|
||||
$this->verifySearchPageOperations($first_id, TRUE, TRUE, TRUE, FALSE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
// Disable the first search page.
|
||||
$this->clickLink(t('Disable'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoLink(t('Disable'));
|
||||
$this->verifySearchPageOperations($first_id, TRUE, TRUE, FALSE, TRUE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
// Enable the first search page.
|
||||
$this->clickLink(t('Enable'));
|
||||
$this->assertResponse(200);
|
||||
$this->verifySearchPageOperations($first_id, TRUE, TRUE, TRUE, FALSE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
// Test deleting.
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertRaw(t('Are you sure you want to delete the search page %label?', ['%label' => $first['label']]));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertRaw(t('The search page %label has been deleted.', ['%label' => $first['label']]));
|
||||
$this->verifySearchPageOperations($first_id, FALSE, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the enable/disable/default routes are protected from CSRF.
|
||||
*/
|
||||
public function testRouteProtection() {
|
||||
// Ensure that the enable and disable routes are protected.
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search/enable');
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search/disable');
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search/set-default');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the search page operations match expectations.
|
||||
*
|
||||
* @param string $id
|
||||
* The search page ID to check.
|
||||
* @param bool $edit
|
||||
* Whether the edit link is expected.
|
||||
* @param bool $delete
|
||||
* Whether the delete link is expected.
|
||||
* @param bool $disable
|
||||
* Whether the disable link is expected.
|
||||
* @param bool $enable
|
||||
* Whether the enable link is expected.
|
||||
*/
|
||||
protected function verifySearchPageOperations($id, $edit, $delete, $disable, $enable) {
|
||||
if ($edit) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id");
|
||||
}
|
||||
if ($delete) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id/delete");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id/delete");
|
||||
}
|
||||
if ($disable) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id/disable");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id/disable");
|
||||
}
|
||||
if ($enable) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id/enable");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id/enable");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the default search page matches expectations.
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected search page.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
* @param string $group
|
||||
* (optional) The group this message is in.
|
||||
*/
|
||||
protected function assertDefaultSearch($expected, $message = '', $group = 'Other') {
|
||||
/** @var $search_page_repository \Drupal\search\SearchPageRepositoryInterface */
|
||||
$search_page_repository = \Drupal::service('search.search_page_repository');
|
||||
$this->assertIdentical($search_page_repository->getDefaultSearchPage(), $expected, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a search page as the default in the UI.
|
||||
*
|
||||
* @param string $entity_id
|
||||
* The search page entity ID to enable.
|
||||
*/
|
||||
protected function setDefaultThroughUi($entity_id) {
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
preg_match('|href="([^"]+' . $entity_id . '/set-default[^"]+)"|', $this->getSession()->getPage()->getContent(), $matches);
|
||||
|
||||
$this->drupalGet($this->getAbsoluteUrl($matches[1]));
|
||||
}
|
||||
|
||||
}
|
|
@ -3,24 +3,25 @@
|
|||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests searching with date filters that exclude some translations.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchDateIntervalTest extends SearchTestBase {
|
||||
class SearchDateIntervalTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var string[]
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['language', 'search_date_query_alter'];
|
||||
protected static $modules = ['language', 'search_date_query_alter', 'node', 'search'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create and log in user.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'administer nodes', 'administer languages', 'access administration pages', 'administer site configuration']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Verifies that a form embedded in search results works.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchEmbedFormTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search', 'search_embedded_form'];
|
||||
|
||||
/**
|
||||
* Node used for testing.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
/**
|
||||
* Count of how many times the form has been submitted.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $submitCount = 0;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create a user and a node, and update the search index.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'administer nodes']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
$this->node = $this->drupalCreateNode();
|
||||
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Set up a dummy initial count of times the form has been submitted.
|
||||
$this->submitCount = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->refreshVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the embedded form appears and can be submitted.
|
||||
*/
|
||||
public function testEmbeddedForm() {
|
||||
// First verify we can submit the form from the module's page.
|
||||
$this->drupalPostForm('search_embedded_form',
|
||||
['name' => 'John'],
|
||||
t('Send away'));
|
||||
$this->assertText(t('Test form was submitted'), 'Form message appears');
|
||||
$count = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->assertEqual($this->submitCount + 1, $count, 'Form submission count is correct');
|
||||
$this->submitCount = $count;
|
||||
|
||||
// Now verify that we can see and submit the form from the search results.
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $this->node->label()]]);
|
||||
$this->assertText(t('Your name'), 'Form is visible');
|
||||
$this->drupalPostForm(NULL,
|
||||
['name' => 'John'],
|
||||
t('Send away'));
|
||||
$this->assertText(t('Test form was submitted'), 'Form message appears');
|
||||
$count = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->assertEqual($this->submitCount + 1, $count, 'Form submission count is correct');
|
||||
$this->submitCount = $count;
|
||||
|
||||
// Now verify that if we submit the search form, it doesn't count as
|
||||
// our form being submitted.
|
||||
$this->drupalPostForm('search',
|
||||
['keys' => 'foo'],
|
||||
t('Search'));
|
||||
$this->assertNoText(t('Test form was submitted'), 'Form message does not appear');
|
||||
$count = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->assertEqual($this->submitCount, $count, 'Form submission count is correct');
|
||||
$this->submitCount = $count;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,16 +2,26 @@
|
|||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that searching for a phrase gets the correct page count.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchExactTest extends SearchTestBase {
|
||||
class SearchExactTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search'];
|
||||
|
||||
/**
|
||||
* Tests that the correct number of pager links are found for both keywords and phrases.
|
||||
*/
|
||||
public function testExactQuery() {
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Log in with sufficient privileges.
|
||||
$user = $this->drupalCreateUser(['create page content', 'search content']);
|
||||
$this->drupalLogin($user);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Verify the search without keywords set and extra conditions.
|
||||
|
@ -13,14 +14,12 @@ use Drupal\Component\Utility\Html;
|
|||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchKeywordsConditionsTest extends SearchTestBase {
|
||||
class SearchKeywordsConditionsTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment', 'search_extra_type', 'test_page_test'];
|
||||
protected static $modules = ['comment', 'search', 'search_extra_type', 'test_page_test'];
|
||||
|
||||
/**
|
||||
* A user with permission to search and post comments.
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests advanced search with different languages added.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchLanguageTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['language', 'node', 'search'];
|
||||
|
||||
/**
|
||||
* Array of nodes available to search.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $searchableNodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create and log in user.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'administer nodes', 'administer languages', 'access administration pages', 'administer site configuration']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
// Add a new language.
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Make the body field translatable. The title is already translatable by
|
||||
// definition. The parent class has already created the article and page
|
||||
// content types.
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$field_storage->setTranslatable(TRUE);
|
||||
$field_storage->save();
|
||||
|
||||
// Create a few page nodes with multilingual body values.
|
||||
$default_format = filter_default_format();
|
||||
$nodes = [
|
||||
[
|
||||
'title' => 'First node en',
|
||||
'type' => 'page',
|
||||
'body' => [['value' => $this->randomMachineName(32), 'format' => $default_format]],
|
||||
'langcode' => 'en',
|
||||
],
|
||||
[
|
||||
'title' => 'Second node this is the Spanish title',
|
||||
'type' => 'page',
|
||||
'body' => [['value' => $this->randomMachineName(32), 'format' => $default_format]],
|
||||
'langcode' => 'es',
|
||||
],
|
||||
[
|
||||
'title' => 'Third node en',
|
||||
'type' => 'page',
|
||||
'body' => [['value' => $this->randomMachineName(32), 'format' => $default_format]],
|
||||
'langcode' => 'en',
|
||||
],
|
||||
];
|
||||
$this->searchableNodes = [];
|
||||
foreach ($nodes as $setting) {
|
||||
$this->searchableNodes[] = $this->drupalCreateNode($setting);
|
||||
}
|
||||
|
||||
// Add English translation to the second node.
|
||||
$translation = $this->searchableNodes[1]->addTranslation('en', ['title' => 'Second node en']);
|
||||
$translation->body->value = $this->randomMachineName(32);
|
||||
$this->searchableNodes[1]->save();
|
||||
|
||||
// Add Spanish translation to the third node.
|
||||
$translation = $this->searchableNodes[2]->addTranslation('es', ['title' => 'Third node es']);
|
||||
$translation->body->value = $this->randomMachineName(32);
|
||||
$this->searchableNodes[2]->save();
|
||||
|
||||
// Update the index and then run the shutdown method.
|
||||
$plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
$plugin->updateIndex();
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
public function testLanguages() {
|
||||
// Add predefined language.
|
||||
$edit = ['predefined_langcode' => 'fr'];
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$this->assertText('French', 'Language added successfully.');
|
||||
|
||||
// Now we should have languages displayed.
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertText(t('Languages'), 'Languages displayed to choose from.');
|
||||
$this->assertText(t('English'), 'English is a possible choice.');
|
||||
$this->assertText(t('French'), 'French is a possible choice.');
|
||||
|
||||
// Ensure selecting no language does not make the query different.
|
||||
$this->drupalPostForm('search/node', [], 'edit-submit--2');
|
||||
$this->assertUrl(\Drupal::url('search.view_node_search', [], ['query' => ['keys' => ''], 'absolute' => TRUE]), [], 'Correct page redirection, no language filtering.');
|
||||
|
||||
// Pick French and ensure it is selected.
|
||||
$edit = ['language[fr]' => TRUE];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
// Get the redirected URL.
|
||||
$url = $this->getUrl();
|
||||
$parts = parse_url($url);
|
||||
$query_string = isset($parts['query']) ? rawurldecode($parts['query']) : '';
|
||||
$this->assertTrue(strpos($query_string, '=language:fr') !== FALSE, 'Language filter language:fr add to the query string.');
|
||||
|
||||
// Search for keyword node and language filter as Spanish.
|
||||
$edit = ['keys' => 'node', 'language[es]' => TRUE];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
// Check for Spanish results.
|
||||
$this->assertLink('Second node this is the Spanish title', 0, 'Second node Spanish title found in search results');
|
||||
$this->assertLink('Third node es', 0, 'Third node Spanish found in search results');
|
||||
// Ensure that results don't contain other language nodes.
|
||||
$this->assertNoLink('First node en', 'Search results do not contain first English node');
|
||||
$this->assertNoLink('Second node en', 'Search results do not contain second English node');
|
||||
$this->assertNoLink('Third node en', 'Search results do not contain third English node');
|
||||
|
||||
// Change the default language and delete English.
|
||||
$path = 'admin/config/regional/language';
|
||||
$this->drupalGet($path);
|
||||
$this->assertFieldChecked('edit-site-default-language-en', 'Default language updated.');
|
||||
$edit = [
|
||||
'site_default_language' => 'fr',
|
||||
];
|
||||
$this->drupalPostForm($path, $edit, t('Save configuration'));
|
||||
$this->assertNoFieldChecked('edit-site-default-language-en', 'Default language updated.');
|
||||
$this->drupalPostForm('admin/config/regional/language/delete/en', [], t('Delete'));
|
||||
}
|
||||
|
||||
}
|
|
@ -4,13 +4,14 @@ namespace Drupal\Tests\search\Functional;
|
|||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests entities with multilingual fields.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchMultilingualEntityTest extends SearchTestBase {
|
||||
class SearchMultilingualEntityTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* List of searchable nodes.
|
||||
|
@ -26,11 +27,16 @@ class SearchMultilingualEntityTest extends SearchTestBase {
|
|||
*/
|
||||
protected $plugin;
|
||||
|
||||
public static $modules = ['language', 'locale', 'comment'];
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['language', 'locale', 'comment', 'node', 'search'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create a user who can administer search, do searches, see the status
|
||||
// report, and administer cron. Log in.
|
||||
$user = $this->drupalCreateUser(['administer search', 'search content', 'use advanced search', 'access content', 'access site reports', 'administer site configuration']);
|
||||
|
@ -78,16 +84,11 @@ class SearchMultilingualEntityTest extends SearchTestBase {
|
|||
// After the third node, we don't care what the settings are. But we
|
||||
// need to have at least 5 to make sure the throttling is working
|
||||
// correctly. So, let's make 8 total.
|
||||
[
|
||||
],
|
||||
[
|
||||
],
|
||||
[
|
||||
],
|
||||
[
|
||||
],
|
||||
[
|
||||
],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
];
|
||||
$this->searchableNodes = [];
|
||||
foreach ($nodes as $setting) {
|
||||
|
|
|
@ -2,12 +2,19 @@
|
|||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests search functionality with diacritics.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNodeDiacriticsTest extends SearchTestBase {
|
||||
class SearchNodeDiacriticsTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search'];
|
||||
|
||||
/**
|
||||
* A user with permission to use advanced search.
|
||||
|
@ -18,6 +25,9 @@ class SearchNodeDiacriticsTest extends SearchTestBase {
|
|||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
node_access_rebuild();
|
||||
|
||||
// Create a test user and log in.
|
||||
|
|
|
@ -2,12 +2,19 @@
|
|||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests search functionality with punctuation and HTML entities.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNodePunctuationTest extends SearchTestBase {
|
||||
class SearchNodePunctuationTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search'];
|
||||
|
||||
/**
|
||||
* A user with permission to use advanced search.
|
||||
|
@ -18,8 +25,10 @@ class SearchNodePunctuationTest extends SearchTestBase {
|
|||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
node_access_rebuild();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
node_access_rebuild();
|
||||
// Create a test user and log in.
|
||||
$this->testUser = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'access user profiles']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests search index is updated properly when nodes are removed or updated.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNodeUpdateAndDeletionTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search'];
|
||||
|
||||
/**
|
||||
* A user with permission to access and search content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
public $testUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create a test user and log in.
|
||||
$this->testUser = $this->drupalCreateUser(['access content', 'search content']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the search index info is properly updated when a node changes.
|
||||
*/
|
||||
public function testSearchIndexUpdateOnNodeChange() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => 'Someone who says Ni!',
|
||||
'body' => [['value' => "We are the knights who say Ni!"]],
|
||||
'type' => 'page',
|
||||
]);
|
||||
|
||||
$node_search_plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
// Update the search index.
|
||||
$node_search_plugin->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search the node to verify it appears in search results
|
||||
$edit = ['keys' => 'knights'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText($node->label());
|
||||
|
||||
// Update the node
|
||||
$node->body->value = "We want a shrubbery!";
|
||||
$node->save();
|
||||
|
||||
// Run indexer again
|
||||
$node_search_plugin->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search again to verify the new text appears in test results.
|
||||
$edit = ['keys' => 'shrubbery'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText($node->label());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the search index info is updated when a node is deleted.
|
||||
*/
|
||||
public function testSearchIndexUpdateOnNodeDeletion() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => 'No dragons here',
|
||||
'body' => [['value' => 'Again: No dragons here']],
|
||||
'type' => 'page',
|
||||
]);
|
||||
|
||||
$node_search_plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
// Update the search index.
|
||||
$node_search_plugin->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search the node to verify it appears in search results
|
||||
$edit = ['keys' => 'dragons'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText($node->label());
|
||||
|
||||
// Get the node info from the search index tables.
|
||||
$search_index_dataset = db_query("SELECT sid FROM {search_index} WHERE type = 'node_search' AND word = :word", [':word' => 'dragons'])
|
||||
->fetchField();
|
||||
$this->assertNotEqual($search_index_dataset, FALSE, t('Node info found on the search_index'));
|
||||
|
||||
// Delete the node.
|
||||
$node->delete();
|
||||
|
||||
// Check if the node info is gone from the search table.
|
||||
$search_index_dataset = db_query("SELECT sid FROM {search_index} WHERE type = 'node_search' AND word = :word", [':word' => 'dragons'])
|
||||
->fetchField();
|
||||
$this->assertFalse($search_index_dataset, t('Node info successfully removed from search_index'));
|
||||
|
||||
// Search again to verify the node doesn't appear anymore.
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertNoText($node->label());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\Traits\Core\CronRunTrait;
|
||||
|
||||
/**
|
||||
* Tests that numbers can be searched with more complex matching.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNumberMatchingTest extends BrowserTestBase {
|
||||
|
||||
use CronRunTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['dblog', 'node', 'search'];
|
||||
|
||||
/**
|
||||
* A user with permission to administer nodes.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $testUser;
|
||||
|
||||
/**
|
||||
* An array of strings containing numbers to use for testing.
|
||||
*
|
||||
* Define a group of numbers that should all match each other --
|
||||
* numbers with internal punctuation should match each other, as well
|
||||
* as numbers with and without leading zeros and leading/trailing
|
||||
* . and -.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $numbers = [
|
||||
'123456789',
|
||||
'12/34/56789',
|
||||
'12.3456789',
|
||||
'12-34-56789',
|
||||
'123,456,789',
|
||||
'-123456789',
|
||||
'0123456789',
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of nodes created for testing purposes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
$this->testUser = $this->drupalCreateUser(['search content', 'access content', 'administer nodes', 'access site reports']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
|
||||
foreach ($this->numbers as $num) {
|
||||
$info = [
|
||||
'body' => [['value' => $num]],
|
||||
'type' => 'page',
|
||||
'language' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
];
|
||||
$this->nodes[] = $this->drupalCreateNode($info);
|
||||
}
|
||||
|
||||
// Run cron to ensure the content is indexed.
|
||||
$this->cronRun();
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertText(t('Cron run completed'), 'Log shows cron run completed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all the numbers can be searched.
|
||||
*/
|
||||
public function testNumberSearching() {
|
||||
for ($i = 0; $i < count($this->numbers); $i++) {
|
||||
$node = $this->nodes[$i];
|
||||
|
||||
// Verify that the node title does not appear on the search page
|
||||
// with a dummy search.
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => 'foo'],
|
||||
t('Search'));
|
||||
$this->assertNoText($node->label(), format_string('%number: node title not shown in dummy search', ['%number' => $i]));
|
||||
|
||||
// Now verify that we can find node i by searching for any of the
|
||||
// numbers.
|
||||
for ($j = 0; $j < count($this->numbers); $j++) {
|
||||
$number = $this->numbers[$j];
|
||||
// If the number is negative, remove the - sign, because - indicates
|
||||
// "not keyword" when searching.
|
||||
$number = ltrim($number, '-');
|
||||
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => $number],
|
||||
t('Search'));
|
||||
$this->assertText($node->label(), format_string('%i: node title shown (search found the node) in search for number %number', ['%i' => $i, '%number' => $number]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\Traits\Core\CronRunTrait;
|
||||
|
||||
/**
|
||||
* Tests that numbers can be searched.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNumbersTest extends BrowserTestBase {
|
||||
|
||||
use CronRunTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['dblog', 'node', 'search'];
|
||||
|
||||
/**
|
||||
* A user with permission to administer nodes.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $testUser;
|
||||
|
||||
/**
|
||||
* An array containing a series of "numbers" for testing purposes.
|
||||
*
|
||||
* Create content with various numbers in it.
|
||||
* Note: 50 characters is the current limit of the search index's word
|
||||
* field.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $numbers = [
|
||||
'ISBN' => '978-0446365383',
|
||||
'UPC' => '036000 291452',
|
||||
'EAN bar code' => '5901234123457',
|
||||
'negative' => '-123456.7890',
|
||||
'quoted negative' => '"-123456.7890"',
|
||||
'leading zero' => '0777777777',
|
||||
'tiny' => '111',
|
||||
'small' => '22222222222222',
|
||||
'medium' => '333333333333333333333333333',
|
||||
'large' => '444444444444444444444444444444444444444',
|
||||
'gigantic' => '5555555555555555555555555555555555555555555555555',
|
||||
'over fifty characters' => '666666666666666666666666666666666666666666666666666666666666',
|
||||
'date' => '01/02/2009',
|
||||
'commas' => '987,654,321',
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of nodes created for testing purposes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
$this->testUser = $this->drupalCreateUser(['search content', 'access content', 'administer nodes', 'access site reports']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
|
||||
foreach ($this->numbers as $doc => $num) {
|
||||
$info = [
|
||||
'body' => [['value' => $num]],
|
||||
'type' => 'page',
|
||||
'language' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
'title' => $doc . ' number',
|
||||
];
|
||||
$this->nodes[$doc] = $this->drupalCreateNode($info);
|
||||
}
|
||||
|
||||
// Run cron to ensure the content is indexed.
|
||||
$this->cronRun();
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertText(t('Cron run completed'), 'Log shows cron run completed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all the numbers can be searched.
|
||||
*/
|
||||
public function testNumberSearching() {
|
||||
$types = array_keys($this->numbers);
|
||||
|
||||
foreach ($types as $type) {
|
||||
$number = $this->numbers[$type];
|
||||
// If the number is negative, remove the - sign, because - indicates
|
||||
// "not keyword" when searching.
|
||||
$number = ltrim($number, '-');
|
||||
$node = $this->nodes[$type];
|
||||
|
||||
// Verify that the node title does not appear on the search page
|
||||
// with a dummy search.
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => 'foo'],
|
||||
t('Search'));
|
||||
$this->assertNoText($node->label(), $type . ': node title not shown in dummy search');
|
||||
|
||||
// Verify that the node title does appear as a link on the search page
|
||||
// when searching for the number.
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => $number],
|
||||
t('Search'));
|
||||
$this->assertText($node->label(), format_string('%type: node title shown (search found the node) in search for number %number.', ['%type' => $type, '%number' => $number]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Tests the search_page entity cache tags on the search results pages.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPageCacheTagsTest extends BrowserTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $dumpHeaders = TRUE;
|
||||
|
||||
/**
|
||||
* A user with permission to search content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $searchingUser;
|
||||
|
||||
/**
|
||||
* A node that is indexed by the search module.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create user.
|
||||
$this->searchingUser = $this->drupalCreateUser(['search content', 'access user profiles']);
|
||||
|
||||
// Create a node and update the search index.
|
||||
$this->node = $this->drupalCreateNode(['title' => 'bike shed shop']);
|
||||
$this->node->setOwner($this->searchingUser);
|
||||
$this->node->save();
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the presence of the expected cache tag in various situations.
|
||||
*/
|
||||
public function testSearchText() {
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
|
||||
// Initial page for searching nodes.
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Node search results.
|
||||
$edit = [];
|
||||
$edit['keys'] = 'bike shed';
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('bike shed shop');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node:1');
|
||||
$this->assertCacheTag('user:2');
|
||||
$this->assertCacheTag('rendered');
|
||||
$this->assertCacheTag('http_response');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Updating a node should invalidate the search plugin's index cache tag.
|
||||
$this->node->title = 'bike shop';
|
||||
$this->node->save();
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('bike shop');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node:1');
|
||||
$this->assertCacheTag('user:2');
|
||||
$this->assertCacheTag('rendered');
|
||||
$this->assertCacheTag('http_response');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Deleting a node should invalidate the search plugin's index cache tag.
|
||||
$this->node->delete();
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('Your search yielded no results.');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Initial page for searching users.
|
||||
$this->drupalGet('search/user');
|
||||
$this->assertCacheTag('config:search.page.user_search');
|
||||
$this->assertCacheTag('user_list');
|
||||
$this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'search_index');
|
||||
$this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'search_index:user_search');
|
||||
|
||||
// User search results.
|
||||
$edit['keys'] = $this->searchingUser->getUsername();
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->assertCacheTag('config:search.page.user_search');
|
||||
$this->assertCacheTag('user_list');
|
||||
$this->assertCacheTag('user:2');
|
||||
$this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'search_index');
|
||||
$this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'search_index:user_search');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the presence of expected cache tags with referenced entities.
|
||||
*/
|
||||
public function testSearchTagsBubbling() {
|
||||
|
||||
// Install field UI and entity reference modules.
|
||||
$this->container->get('module_installer')->install(['field_ui', 'entity_reference']);
|
||||
$this->resetAll();
|
||||
|
||||
// Creates a new content type that will have an entity reference.
|
||||
$type_name = 'entity_reference_test';
|
||||
$type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]);
|
||||
|
||||
$bundle_path = 'admin/structure/types/manage/' . $type->id();
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'access content',
|
||||
'create ' . $type_name . ' content',
|
||||
'administer node fields',
|
||||
'administer node display',
|
||||
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// First step: 'Add new field' on the 'Manage fields' page.
|
||||
$this->drupalGet($bundle_path . '/fields/add-field');
|
||||
$this->drupalPostForm(NULL, [
|
||||
'label' => 'Test label',
|
||||
'field_name' => 'test__ref',
|
||||
'new_storage_type' => 'entity_reference',
|
||||
], t('Save and continue'));
|
||||
|
||||
// Second step: 'Field settings' form.
|
||||
$this->drupalPostForm(NULL, [], t('Save field settings'));
|
||||
|
||||
// Create a new node of our newly created node type and fill in the entity
|
||||
// reference field.
|
||||
$edit = [
|
||||
'title[0][value]' => 'Llama shop',
|
||||
'field_test__ref[0][target_id]' => $this->node->getTitle(),
|
||||
];
|
||||
$this->drupalPostForm('node/add/' . $type->id(), $edit, t('Save'));
|
||||
|
||||
// Test that the value of the entity reference field is shown.
|
||||
$this->drupalGet('node/2');
|
||||
$this->assertText('bike shed shop');
|
||||
|
||||
// Refresh the search index.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Log in with searching user again.
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
|
||||
// Default search cache tags.
|
||||
$default_search_tags = [
|
||||
'config:search.page.node_search',
|
||||
'search_index',
|
||||
'search_index:node_search',
|
||||
'http_response',
|
||||
'rendered',
|
||||
'node_list',
|
||||
];
|
||||
|
||||
// Node search results for shop, should return node:1 (bike shed shop) and
|
||||
// node:2 (Llama shop). The related authors cache tags should be visible as
|
||||
// well.
|
||||
$edit = [];
|
||||
$edit['keys'] = 'shop';
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('bike shed shop');
|
||||
$this->assertText('Llama shop');
|
||||
$expected_cache_tags = Cache::mergeTags($default_search_tags, [
|
||||
'node:1',
|
||||
'user:2',
|
||||
'node:2',
|
||||
'user:3',
|
||||
'node_view',
|
||||
'config:filter.format.plain_text',
|
||||
]);
|
||||
$this->assertCacheTags($expected_cache_tags);
|
||||
|
||||
// Only get the new node in the search results, should result in node:1,
|
||||
// node:2 and user:3 as cache tags even though only node:1 is shown. This is
|
||||
// because node:2 is reference in node:1 as an entity reference.
|
||||
$edit = [];
|
||||
$edit['keys'] = 'Llama';
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('Llama shop');
|
||||
$expected_cache_tags = Cache::mergeTags($default_search_tags, [
|
||||
'node:1',
|
||||
'node:2',
|
||||
'user:3',
|
||||
'node_view',
|
||||
]);
|
||||
$this->assertCacheTags($expected_cache_tags);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests if the result page can be overridden.
|
||||
*
|
||||
|
@ -10,14 +12,12 @@ namespace Drupal\Tests\search\Functional;
|
|||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPageOverrideTest extends SearchTestBase {
|
||||
class SearchPageOverrideTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['search_extra_type'];
|
||||
protected static $modules = ['search', 'search_extra_type'];
|
||||
|
||||
/**
|
||||
* A user with permission to administer search.
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests the search help text and search page text.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPageTextTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block', 'node', 'search'];
|
||||
|
||||
/**
|
||||
* A user with permission to use advanced search.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $searchingUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create user.
|
||||
$this->searchingUser = $this->drupalCreateUser(['search content', 'access user profiles', 'use advanced search']);
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for XSS in search module local task.
|
||||
*
|
||||
* This is a regression test for https://www.drupal.org/node/2338081
|
||||
*/
|
||||
public function testSearchLabelXSS() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer search']));
|
||||
|
||||
$keys['label'] = '<script>alert("Dont Panic");</script>';
|
||||
$this->drupalPostForm('admin/config/search/pages/manage/node_search', $keys, t('Save search page'));
|
||||
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertEscaped($keys['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the failed search text, and various other text on the search page.
|
||||
*/
|
||||
public function testSearchText() {
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertText(t('Enter your keywords'));
|
||||
$this->assertText(t('Search'));
|
||||
$this->assertTitle(t('Search') . ' | Drupal', 'Search page title is correct');
|
||||
|
||||
$edit = [];
|
||||
$search_terms = 'bike shed ' . $this->randomMachineName();
|
||||
$edit['keys'] = $search_terms;
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('search yielded no results');
|
||||
$this->assertText(t('Search'));
|
||||
$title_source = 'Search for @keywords | Drupal';
|
||||
$this->assertTitle(t($title_source, ['@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)]), 'Search page title is correct');
|
||||
$this->assertNoText('Node', 'Erroneous tab and breadcrumb text is not present');
|
||||
$this->assertNoText(t('Node'), 'Erroneous translated tab and breadcrumb text is not present');
|
||||
$this->assertText(t('Content'), 'Tab and breadcrumb text is present');
|
||||
|
||||
$this->clickLink('Search help');
|
||||
$this->assertText('Search help', 'Correct title is on search help page');
|
||||
$this->assertText('Use upper-case OR to get more results', 'Correct text is on content search help page');
|
||||
|
||||
// Search for a longer text, and see that it is in the title, truncated.
|
||||
$edit = [];
|
||||
$search_terms = 'Every word is like an unnecessary stain on silence and nothingness.';
|
||||
$edit['keys'] = $search_terms;
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertTitle(t($title_source, ['@keywords' => 'Every word is like an unnecessary stain on silence and…']), 'Search page title is correct');
|
||||
|
||||
// Search for a string with a lot of special characters.
|
||||
$search_terms = 'Hear nothing > "see nothing" `feel' . " '1982.";
|
||||
$edit['keys'] = $search_terms;
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$actual_title = $this->xpath('//title')[0]->getText();
|
||||
$this->assertEqual($actual_title, Html::decodeEntities(t($title_source, ['@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)])), 'Search page title is correct');
|
||||
|
||||
$edit['keys'] = $this->searchingUser->getUsername();
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->assertText(t('Search'));
|
||||
$this->assertTitle(t($title_source, ['@keywords' => Unicode::truncate($this->searchingUser->getUsername(), 60, TRUE, TRUE)]));
|
||||
|
||||
$this->clickLink('Search help');
|
||||
$this->assertText('Search help', 'Correct title is on search help page');
|
||||
$this->assertText('user names and partial user names', 'Correct text is on user search help page');
|
||||
|
||||
// Test that search keywords containing slashes are correctly loaded
|
||||
// from the GET params and displayed in the search form.
|
||||
$arg = $this->randomMachineName() . '/' . $this->randomMachineName();
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $arg]]);
|
||||
$input = $this->xpath("//input[@id='edit-keys' and @value='{$arg}']");
|
||||
$this->assertFalse(empty($input), 'Search keys with a / are correctly set as the default value in the search box.');
|
||||
|
||||
// Test a search input exceeding the limit of AND/OR combinations to test
|
||||
// the Denial-of-Service protection.
|
||||
$limit = $this->config('search.settings')->get('and_or_limit');
|
||||
$keys = [];
|
||||
for ($i = 0; $i < $limit + 1; $i++) {
|
||||
// Use a key of 4 characters to ensure we never generate 'AND' or 'OR'.
|
||||
$keys[] = $this->randomMachineName(4);
|
||||
if ($i % 2 == 0) {
|
||||
$keys[] = 'OR';
|
||||
}
|
||||
}
|
||||
$edit['keys'] = implode(' ', $keys);
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertRaw(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', ['@count' => $limit]));
|
||||
|
||||
// Test that a search on Node or User with no keywords entered generates
|
||||
// the "Please enter some keywords" message.
|
||||
$this->drupalPostForm('search/node', [], t('Search'));
|
||||
$this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on node page');
|
||||
$this->drupalPostForm('search/user', [], t('Search'));
|
||||
$this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on user page');
|
||||
|
||||
// Make sure the "Please enter some keywords" message is NOT displayed if
|
||||
// you use "or" words or phrases in Advanced Search.
|
||||
$this->drupalPostForm('search/node', ['or' => $this->randomMachineName() . ' ' . $this->randomMachineName()], 'edit-submit--2');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With advanced OR keywords entered, no keywords message is not displayed on node page');
|
||||
$this->drupalPostForm('search/node', ['phrase' => '"' . $this->randomMachineName() . '" "' . $this->randomMachineName() . '"'], 'edit-submit--2');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With advanced phrase entered, no keywords message is not displayed on node page');
|
||||
|
||||
// Verify that if you search for a too-short keyword, you get the right
|
||||
// message, and that if after that you search for a longer keyword, you
|
||||
// do not still see the message.
|
||||
$this->drupalPostForm('search/node', ['keys' => $this->randomMachineName(1)], t('Search'));
|
||||
$this->assertText('You must include at least one keyword', 'Keyword message is displayed when searching for short word');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed');
|
||||
$this->drupalPostForm(NULL, ['keys' => $this->randomMachineName()], t('Search'));
|
||||
$this->assertNoText('You must include at least one keyword', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
// Test that if you search for a URL with .. in it, you still end up at
|
||||
// the search page. See issue https://www.drupal.org/node/890058.
|
||||
$this->drupalPostForm('search/node', ['keys' => '../../admin'], t('Search'));
|
||||
$this->assertResponse(200, 'Searching for ../../admin with non-admin user does not lead to a 403 error');
|
||||
$this->assertText('no results', 'Searching for ../../admin with non-admin user gives you a no search results page');
|
||||
|
||||
// Test that if you search for a URL starting with "./", you still end up
|
||||
// at the search page. See issue https://www.drupal.org/node/1421560.
|
||||
$this->drupalPostForm('search/node', ['keys' => '.something'], t('Search'));
|
||||
$this->assertResponse(200, 'Searching for .something does not lead to a 403 error');
|
||||
$this->assertText('no results', 'Searching for .something gives you a no search results page');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the search preprocessing uses the correct language code.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPreprocessLangcodeTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search', 'search_langcode_test'];
|
||||
|
||||
/**
|
||||
* Test node for searching.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
$web_user = $this->drupalCreateUser([
|
||||
'create page content',
|
||||
'edit own page content',
|
||||
'search content',
|
||||
'use advanced search',
|
||||
]);
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that hook_search_preprocess() returns the correct langcode.
|
||||
*/
|
||||
public function testPreprocessLangcode() {
|
||||
// Create a node.
|
||||
$this->node = $this->drupalCreateNode(['body' => [[]], 'langcode' => 'en']);
|
||||
|
||||
// First update the index. This does the initial processing.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
|
||||
// Then, run the shutdown function. Testing is a unique case where indexing
|
||||
// and searching has to happen in the same request, so running the shutdown
|
||||
// function manually is needed to finish the indexing process.
|
||||
search_update_totals();
|
||||
|
||||
// Search for the additional text that is added by the preprocess
|
||||
// function. If you search for text that is in the node, preprocess is
|
||||
// not invoked on the node during the search excerpt generation.
|
||||
$edit = ['or' => 'Additional text'];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
|
||||
// Checks if the langcode message has been set by hook_search_preprocess().
|
||||
$this->assertText('Langcode Preprocess Test: en');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests stemming for hook_search_preprocess().
|
||||
*/
|
||||
public function testPreprocessStemming() {
|
||||
// Create a node.
|
||||
$this->node = $this->drupalCreateNode([
|
||||
'title' => 'we are testing',
|
||||
'body' => [[]],
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
|
||||
// First update the index. This does the initial processing.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
|
||||
// Then, run the shutdown function. Testing is a unique case where indexing
|
||||
// and searching has to happen in the same request, so running the shutdown
|
||||
// function manually is needed to finish the indexing process.
|
||||
search_update_totals();
|
||||
|
||||
// Search for the title of the node with a POST query.
|
||||
$edit = ['or' => 'testing'];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
|
||||
// Check if the node has been found.
|
||||
$this->assertText('Search results');
|
||||
$this->assertText('we are testing');
|
||||
|
||||
// Search for the same node using a different query.
|
||||
$edit = ['or' => 'test'];
|
||||
$this->drupalPostForm('search/node', $edit, 'edit-submit--2');
|
||||
|
||||
// Check if the node has been found.
|
||||
$this->assertText('Search results');
|
||||
$this->assertText('we are testing');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the node search query can be altered via the query alter hook.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchQueryAlterTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search', 'search_query_alter'];
|
||||
|
||||
/**
|
||||
* Tests that the query alter works.
|
||||
*/
|
||||
public function testQueryAlter() {
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
// Log in with sufficient privileges.
|
||||
$this->drupalLogin($this->drupalCreateUser(['create page content', 'search content']));
|
||||
|
||||
// Create a node and an article with the same keyword. The query alter
|
||||
// test module will alter the query so only articles should be returned.
|
||||
$data = [
|
||||
'type' => 'page',
|
||||
'title' => 'test page',
|
||||
'body' => [['value' => 'pizza']],
|
||||
];
|
||||
$this->drupalCreateNode($data);
|
||||
|
||||
$data['type'] = 'article';
|
||||
$data['title'] = 'test article';
|
||||
$this->drupalCreateNode($data);
|
||||
|
||||
// Update the search index.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search for the body keyword 'pizza'.
|
||||
$this->drupalPostForm('search/node', ['keys' => 'pizza'], t('Search'));
|
||||
// The article should be there but not the page.
|
||||
$this->assertText('article', 'Article is in search results');
|
||||
$this->assertNoText('page', 'Page is not in search results');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\search\Entity\SearchPage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\Traits\Core\CronRunTrait;
|
||||
|
||||
/**
|
||||
* Indexes content and tests ranking factors.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchRankingTest extends BrowserTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use CronRunTrait;
|
||||
|
||||
/**
|
||||
* The node search page.
|
||||
*
|
||||
* @var \Drupal\search\SearchPageInterface
|
||||
*/
|
||||
protected $nodeSearch;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'search', 'statistics', 'comment'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create a plugin instance.
|
||||
$this->nodeSearch = SearchPage::load('node_search');
|
||||
|
||||
// Log in with sufficient privileges.
|
||||
$this->drupalLogin($this->drupalCreateUser(['post comments', 'skip comment approval', 'create page content', 'administer search']));
|
||||
}
|
||||
|
||||
public function testRankings() {
|
||||
// Add a comment field.
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
|
||||
// Build a list of the rankings to test.
|
||||
$node_ranks = ['sticky', 'promote', 'relevance', 'recent', 'comments', 'views'];
|
||||
|
||||
// Create nodes for testing.
|
||||
$nodes = [];
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$settings = [
|
||||
'type' => 'page',
|
||||
'comment' => [
|
||||
['status' => CommentItemInterface::HIDDEN],
|
||||
],
|
||||
'title' => 'Drupal rocks',
|
||||
'body' => [['value' => "Drupal's search rocks"]],
|
||||
// Node is one day old.
|
||||
'created' => REQUEST_TIME - 24 * 3600,
|
||||
'sticky' => 0,
|
||||
'promote' => 0,
|
||||
];
|
||||
foreach ([0, 1] as $num) {
|
||||
if ($num == 1) {
|
||||
switch ($node_rank) {
|
||||
case 'sticky':
|
||||
case 'promote':
|
||||
$settings[$node_rank] = 1;
|
||||
break;
|
||||
case 'relevance':
|
||||
$settings['body'][0]['value'] .= " really rocks";
|
||||
break;
|
||||
case 'recent':
|
||||
// Node is 1 hour hold.
|
||||
$settings['created'] = REQUEST_TIME - 3600;
|
||||
break;
|
||||
case 'comments':
|
||||
$settings['comment'][0]['status'] = CommentItemInterface::OPEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$nodes[$node_rank][$num] = $this->drupalCreateNode($settings);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a comment to one of the nodes.
|
||||
$edit = [];
|
||||
$edit['subject[0][value]'] = 'my comment title';
|
||||
$edit['comment_body[0][value]'] = 'some random comment';
|
||||
$this->drupalGet('comment/reply/node/' . $nodes['comments'][1]->id() . '/comment');
|
||||
$this->drupalPostForm(NULL, $edit, t('Preview'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Enable counting of statistics.
|
||||
$this->config('statistics.settings')->set('count_content_views', 1)->save();
|
||||
|
||||
// Simulating content views is kind of difficult in the test. Leave that
|
||||
// to the Statistics module. So instead go ahead and manually update the
|
||||
// counter for this node.
|
||||
$nid = $nodes['views'][1]->id();
|
||||
db_insert('node_counter')
|
||||
->fields(['totalcount' => 5, 'daycount' => 5, 'timestamp' => REQUEST_TIME, 'nid' => $nid])
|
||||
->execute();
|
||||
|
||||
// Run cron to update the search index and comment/statistics totals.
|
||||
$this->cronRun();
|
||||
|
||||
// Test that the settings form displays the content ranking section.
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search');
|
||||
$this->assertText(t('Content ranking'));
|
||||
|
||||
// Check that all rankings are visible and set to 0.
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$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.');
|
||||
}
|
||||
|
||||
// Test each of the possible rankings.
|
||||
$edit = [];
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
// Enable the ranking we are testing.
|
||||
$edit['rankings[' . $node_rank . '][value]'] = 10;
|
||||
$this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search');
|
||||
$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.');
|
||||
|
||||
// Reload the plugin to get the up-to-date values.
|
||||
$this->nodeSearch = SearchPage::load('node_search');
|
||||
// Do the search and assert the results.
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
$this->assertEqual($set[0]['node']->id(), $nodes[$node_rank][1]->id(), 'Search ranking "' . $node_rank . '" order.');
|
||||
|
||||
// Clear this ranking for the next test.
|
||||
$edit['rankings[' . $node_rank . '][value]'] = 0;
|
||||
}
|
||||
|
||||
// Save the final node_rank change then check that all rankings are visible
|
||||
// and have been set back to 0.
|
||||
$this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search');
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$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.');
|
||||
}
|
||||
|
||||
// Try with sticky, then promoted. This is a test for issue
|
||||
// https://www.drupal.org/node/771596.
|
||||
$node_ranks = [
|
||||
'sticky' => 10,
|
||||
'promote' => 1,
|
||||
'relevance' => 0,
|
||||
'recent' => 0,
|
||||
'comments' => 0,
|
||||
'views' => 0,
|
||||
];
|
||||
$configuration = $this->nodeSearch->getPlugin()->getConfiguration();
|
||||
foreach ($node_ranks as $var => $value) {
|
||||
$configuration['rankings'][$var] = $value;
|
||||
}
|
||||
$this->nodeSearch->getPlugin()->setConfiguration($configuration);
|
||||
$this->nodeSearch->save();
|
||||
|
||||
// Do the search and assert the results. The sticky node should show up
|
||||
// first, then the promoted node, then all the rest.
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
$this->assertEqual($set[0]['node']->id(), $nodes['sticky'][1]->id(), 'Search ranking for sticky first worked.');
|
||||
$this->assertEqual($set[1]['node']->id(), $nodes['promote'][1]->id(), 'Search ranking for promoted second worked.');
|
||||
|
||||
// Try with recent, then comments. This is a test for issues
|
||||
// https://www.drupal.org/node/771596 and
|
||||
// https://www.drupal.org/node/303574.
|
||||
$node_ranks = [
|
||||
'sticky' => 0,
|
||||
'promote' => 0,
|
||||
'relevance' => 0,
|
||||
'recent' => 10,
|
||||
'comments' => 1,
|
||||
'views' => 0,
|
||||
];
|
||||
$configuration = $this->nodeSearch->getPlugin()->getConfiguration();
|
||||
foreach ($node_ranks as $var => $value) {
|
||||
$configuration['rankings'][$var] = $value;
|
||||
}
|
||||
$this->nodeSearch->getPlugin()->setConfiguration($configuration);
|
||||
$this->nodeSearch->save();
|
||||
|
||||
// Do the search and assert the results. The recent node should show up
|
||||
// first, then the commented node, then all the rest.
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
$this->assertEqual($set[0]['node']->id(), $nodes['recent'][1]->id(), 'Search ranking for recent first worked.');
|
||||
$this->assertEqual($set[1]['node']->id(), $nodes['comments'][1]->id(), 'Search ranking for comments second worked.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rankings of HTML tags.
|
||||
*/
|
||||
public function testHTMLRankings() {
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
]);
|
||||
$full_html_format->save();
|
||||
|
||||
// Test HTML tags with different weights.
|
||||
$sorted_tags = ['h1', 'h2', 'h3', 'h4', 'a', 'h5', 'h6', 'notag'];
|
||||
$shuffled_tags = $sorted_tags;
|
||||
|
||||
// Shuffle tags to ensure HTML tags are ranked properly.
|
||||
shuffle($shuffled_tags);
|
||||
$settings = [
|
||||
'type' => 'page',
|
||||
'title' => 'Simple node',
|
||||
];
|
||||
$nodes = [];
|
||||
foreach ($shuffled_tags as $tag) {
|
||||
switch ($tag) {
|
||||
case 'a':
|
||||
$settings['body'] = [['value' => \Drupal::l('Drupal Rocks', new Url('<front>')), 'format' => 'full_html']];
|
||||
break;
|
||||
case 'notag':
|
||||
$settings['body'] = [['value' => 'Drupal Rocks']];
|
||||
break;
|
||||
default:
|
||||
$settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
|
||||
break;
|
||||
}
|
||||
$nodes[$tag] = $this->drupalCreateNode($settings);
|
||||
}
|
||||
|
||||
// Update the search index.
|
||||
$this->nodeSearch->getPlugin()->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
// Do the search and assert the results.
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
|
||||
// Test the ranking of each tag.
|
||||
foreach ($sorted_tags as $tag_rank => $tag) {
|
||||
// Assert the results.
|
||||
if ($tag == 'notag') {
|
||||
$this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for plain text order.');
|
||||
}
|
||||
else {
|
||||
$this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for "<' . $sorted_tags[$tag_rank] . '>" order.');
|
||||
}
|
||||
}
|
||||
|
||||
// Test tags with the same weight against the sorted tags.
|
||||
$unsorted_tags = ['u', 'b', 'i', 'strong', 'em'];
|
||||
foreach ($unsorted_tags as $tag) {
|
||||
$settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
// Update the search index.
|
||||
$this->nodeSearch->getPlugin()->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
// Do the search and assert the results.
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
|
||||
// Ranking should always be second to last.
|
||||
$set = array_slice($set, -2, 1);
|
||||
|
||||
// Assert the results.
|
||||
$this->assertEqual($set[0]['node']->id(), $node->id(), 'Search tag ranking for "<' . $tag . '>" order.');
|
||||
|
||||
// Delete node so it doesn't show up in subsequent search results.
|
||||
$node->delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,19 +2,19 @@
|
|||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that search works with numeric locale settings.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchSetLocaleTest extends SearchTestBase {
|
||||
class SearchSetLocaleTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment'];
|
||||
protected static $modules = ['comment', 'node', 'search'];
|
||||
|
||||
/**
|
||||
* A node search plugin instance.
|
||||
|
@ -26,6 +26,8 @@ class SearchSetLocaleTest extends SearchTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
// Create a plugin instance.
|
||||
$this->nodeSearchPlugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
// Create a node with a very simple body.
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the search_simply() function works as intended.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchSimplifyTest extends SearchTestBase {
|
||||
class SearchSimplifyTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['search'];
|
||||
|
||||
/**
|
||||
* Tests that all Unicode characters simplify correctly.
|
||||
*/
|
||||
|
@ -20,7 +27,7 @@ class SearchSimplifyTest extends SearchTestBase {
|
|||
// their own lines). So the even-numbered lines should simplify to nothing,
|
||||
// and the odd-numbered lines we need to split into shorter chunks and
|
||||
// verify that simplification doesn't lose any characters.
|
||||
$input = file_get_contents(\Drupal::root() . '/core/modules/search/tests/UnicodeTest.txt');
|
||||
$input = file_get_contents($this->root . '/core/modules/search/tests/UnicodeTest.txt');
|
||||
$basestrings = explode(chr(10), $input);
|
||||
$strings = [];
|
||||
foreach ($basestrings as $key => $string) {
|
||||
|
@ -34,8 +41,8 @@ class SearchSimplifyTest extends SearchTestBase {
|
|||
// Split this into 30-character chunks, so we don't run into limits
|
||||
// of truncation in search_simplify().
|
||||
$start = 0;
|
||||
while ($start < Unicode::strlen($string)) {
|
||||
$newstr = Unicode::substr($string, $start, 30);
|
||||
while ($start < mb_strlen($string)) {
|
||||
$newstr = mb_substr($string, $start, 30);
|
||||
// Special case: leading zeros are removed from numeric strings,
|
||||
// and there's one string in this file that is numbers starting with
|
||||
// zero, so prepend a 1 on that string.
|
||||
|
@ -49,7 +56,7 @@ class SearchSimplifyTest extends SearchTestBase {
|
|||
}
|
||||
foreach ($strings as $key => $string) {
|
||||
$simplified = search_simplify($string);
|
||||
$this->assertTrue(Unicode::strlen($simplified) >= Unicode::strlen($string), "Nothing is removed from string $key.");
|
||||
$this->assertTrue(mb_strlen($simplified) >= mb_strlen($string), "Nothing is removed from string $key.");
|
||||
}
|
||||
|
||||
// Test the low-numbered ASCII control characters separately. They are not
|
||||
|
|
|
@ -2,11 +2,17 @@
|
|||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\SearchTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\BrowserTestBase. See https://www.drupal.org/node/2979950.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* Defines the common search test code.
|
||||
*
|
||||
* @deprecated in Drupal 8.6.0 and will be removed in Drupal 9.0.0. Use
|
||||
* \Drupal\Tests\BrowserTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2979950
|
||||
*/
|
||||
abstract class SearchTestBase extends BrowserTestBase {
|
||||
|
||||
|
@ -28,17 +34,7 @@ abstract class SearchTestBase extends BrowserTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Simulates submission of a form using GET instead of POST.
|
||||
*
|
||||
* Forms that use the GET method cannot be submitted with
|
||||
* WebTestBase::drupalPostForm(), which explicitly uses POST to submit the
|
||||
* form. So this method finds the form, verifies that it has input fields and
|
||||
* a submit button matching the inputs to this method, and then calls
|
||||
* WebTestBase::drupalGet() to simulate the form submission to the 'action'
|
||||
* URL of the form (if set, or the current URL if not).
|
||||
*
|
||||
* See WebTestBase::drupalPostForm() for more detailed documentation of the
|
||||
* function parameters.
|
||||
* Submission of a form via press submit button.
|
||||
*
|
||||
* @param string $path
|
||||
* Location of the form to be submitted: either a Drupal path, absolute
|
||||
|
@ -51,42 +47,15 @@ abstract class SearchTestBase extends BrowserTestBase {
|
|||
* this does not support AJAX.
|
||||
* @param string $form_html_id
|
||||
* (optional) HTML ID of the form, to disambiguate.
|
||||
*
|
||||
* @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.x. Use
|
||||
* \Drupal\Tests\BrowserTestBase::drupalPostForm() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2979950
|
||||
*/
|
||||
protected function submitGetForm($path, $edit, $submit, $form_html_id = NULL) {
|
||||
if (isset($path)) {
|
||||
$this->drupalGet($path);
|
||||
}
|
||||
|
||||
if ($this->parse()) {
|
||||
// Iterate over forms to find one that matches $edit and $submit.
|
||||
$edit_save = $edit;
|
||||
$xpath = '//form';
|
||||
if (!empty($form_html_id)) {
|
||||
$xpath .= "[@id='" . $form_html_id . "']";
|
||||
}
|
||||
$forms = $this->xpath($xpath);
|
||||
foreach ($forms as $form) {
|
||||
// Try to set the fields of this form as specified in $edit.
|
||||
$edit = $edit_save;
|
||||
$post = [];
|
||||
$upload = [];
|
||||
$submit_matches = $this->handleForm($post, $edit, $upload, $submit, $form);
|
||||
if (!$edit && $submit_matches) {
|
||||
// Everything matched, so "submit" the form.
|
||||
$action = isset($form['action']) ? $this->getAbsoluteUrl((string) $form['action']) : NULL;
|
||||
$this->drupalGet($action, ['query' => $post]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We have not found a form which contained all fields of $edit and
|
||||
// the submit button.
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->fail(SafeMarkup::format('Failed to set field @name to @value', ['@name' => $name, '@value' => $value]));
|
||||
}
|
||||
$this->assertTrue($submit_matches, format_string('Found the @submit button', ['@submit' => $submit]));
|
||||
$this->fail(format_string('Found the requested form fields at @path', ['@path' => $path]));
|
||||
}
|
||||
@trigger_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated in Drupal 8.6.x, for removal before the Drupal 9.0.0 release. Use \Drupal\Tests\BrowserTestBase::drupalPostForm() instead. See https://www.drupal.org/node/2979950.', E_USER_DEPRECATED);
|
||||
$this->drupalPostForm($path, $edit, $submit, [], $form_html_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Functional;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that CJK tokenizer works as intended.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchTokenizerTest extends SearchTestBase {
|
||||
class SearchTokenizerTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['search'];
|
||||
|
||||
/**
|
||||
* Verifies that strings of CJK characters are tokenized.
|
||||
|
@ -94,7 +100,7 @@ class SearchTokenizerTest extends SearchTestBase {
|
|||
// Merge into a string and tokenize.
|
||||
$string = implode('', $chars);
|
||||
$out = trim(search_simplify($string));
|
||||
$expected = Unicode::strtolower(implode(' ', $chars));
|
||||
$expected = mb_strtolower(implode(' ', $chars));
|
||||
|
||||
// Verify that the output matches what we expect.
|
||||
$this->assertEqual($out, $expected, 'CJK tokenizer worked on all supplied CJK characters');
|
||||
|
@ -124,9 +130,9 @@ class SearchTokenizerTest extends SearchTestBase {
|
|||
/**
|
||||
* Like PHP chr() function, but for unicode characters.
|
||||
*
|
||||
* chr() only works for ASCII characters up to character 255. This function
|
||||
* converts a number to the corresponding unicode character. Adapted from
|
||||
* functions supplied in comments on several functions on php.net.
|
||||
* Function chr() only works for ASCII characters up to character 255. This
|
||||
* function converts a number to the corresponding unicode character. Adapted
|
||||
* from functions supplied in comments on several functions on php.net.
|
||||
*/
|
||||
public function code2utf($num) {
|
||||
if ($num < 128) {
|
||||
|
|
|
@ -156,7 +156,7 @@ class SearchMatchTest extends KernelTestBase {
|
|||
'"am minim veniam" -"cillum dolore"' => [5, 6],
|
||||
'"am minim veniam" -"dolore cillum"' => [5, 6, 7],
|
||||
'xxxxx "minim am veniam es" OR dolore' => [],
|
||||
'xx "minim am veniam es" OR dolore' => []
|
||||
'xx "minim am veniam es" OR dolore' => [],
|
||||
];
|
||||
foreach ($queries as $query => $results) {
|
||||
$result = db_select('search_index', 'i')
|
||||
|
|
|
@ -273,11 +273,13 @@ class SearchPageRepositoryTest extends UnitTestCase {
|
|||
}
|
||||
|
||||
class TestSearchPage extends SearchPage {
|
||||
|
||||
public function __construct(array $values) {
|
||||
foreach ($values as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function label($langcode = NULL) {
|
||||
return $this->label;
|
||||
}
|
||||
|
|
Reference in a new issue