You are here

public function ViewsTest::testSearchView in Search API 8

Tests a view with exposed filters.

File

tests/src/Functional/ViewsTest.php, line 72

Class

ViewsTest
Tests the Views integration of the Search API.

Namespace

Drupal\Tests\search_api\Functional

Code

public function testSearchView() {
  $this
    ->checkResults([], array_keys($this->entities), 'Unfiltered search');
  $this
    ->checkResults([
    'search_api_fulltext' => 'foobar',
  ], [
    3,
  ], 'Search for a single word');
  $this
    ->checkResults([
    'search_api_fulltext' => 'foo test',
  ], [
    1,
    2,
    4,
  ], 'Search for multiple words');
  $query = [
    'search_api_fulltext' => 'foo test',
    'search_api_fulltext_op' => 'or',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'OR search for multiple words');
  $query = [
    'search_api_fulltext' => 'foobar',
    'search_api_fulltext_op' => 'not',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    4,
    5,
  ], 'Negated search');
  $query = [
    'search_api_fulltext' => 'foo test',
    'search_api_fulltext_op' => 'not',
  ];
  $this
    ->checkResults($query, [], 'Negated search for multiple words');
  $query = [
    'search_api_fulltext' => 'fo',
  ];
  $label = 'Search for short word';
  $this
    ->checkResults($query, [], $label);
  $this
    ->assertSession()
    ->pageTextContains('You must include at least one positive keyword with 3 characters or more');
  $query = [
    'search_api_fulltext' => 'foo to test',
  ];
  $label = 'Fulltext search including short word';
  $this
    ->checkResults($query, [
    1,
    2,
    4,
  ], $label);
  $this
    ->assertSession()
    ->pageTextNotContains('You must include at least one positive keyword with 3 characters or more');
  $this
    ->checkResults([
    'id[value]' => 2,
  ], [
    2,
  ], 'Search with ID filter');
  $query = [
    'id[min]' => 2,
    'id[max]' => 4,
    'id_op' => 'between',
  ];
  $this
    ->checkResults($query, [
    2,
    3,
    4,
  ], 'Search with ID "in between" filter');
  $query = [
    'id[min]' => 2,
    'id[max]' => 4,
    'id_op' => 'not between',
  ];
  $this
    ->checkResults($query, [
    1,
    5,
  ], 'Search with ID "not in between" filter');
  $query = [
    'id[value]' => 2,
    'id_op' => '>',
  ];
  $this
    ->checkResults($query, [
    3,
    4,
    5,
  ], 'Search with ID "greater than" filter');
  $query = [
    'id[value]' => 2,
    'id_op' => '!=',
  ];
  $this
    ->checkResults($query, [
    1,
    3,
    4,
    5,
  ], 'Search with ID "not equal" filter');
  $query = [
    'id_op' => 'empty',
  ];
  $this
    ->checkResults($query, [], 'Search with ID "empty" filter');
  $query = [
    'id_op' => 'not empty',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with ID "not empty" filter');
  $yesterday = strtotime('-1DAY');
  $query = [
    'created[value]' => date('Y-m-d', $yesterday),
    'created_op' => '>',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with "Created after" filter');
  $query = [
    'created[value]' => date('Y-m-d', $yesterday),
    'created_op' => '<',
  ];
  $this
    ->checkResults($query, [], 'Search with "Created before" filter');
  $query = [
    'created_op' => 'empty',
  ];
  $this
    ->checkResults($query, [], 'Search with "empty creation date" filter');
  $query = [
    'created_op' => 'not empty',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with "not empty creation date" filter');
  $this
    ->checkResults([
    'keywords[value]' => 'apple',
  ], [
    2,
    4,
  ], 'Search with Keywords filter');
  $query = [
    'keywords[min]' => 'aardvark',
    'keywords[max]' => 'calypso',
    'keywords_op' => 'between',
  ];
  $this
    ->checkResults($query, [
    2,
    4,
    5,
  ], 'Search with Keywords "in between" filter');

  // For the keywords filters with comparison operators, exclude entity 1
  // since that contains all the uppercase and special characters weirdness.
  $query = [
    'id[value]' => 1,
    'id_op' => '!=',
    'keywords[value]' => 'melon',
    'keywords_op' => '>=',
  ];
  $this
    ->checkResults($query, [
    2,
    4,
    5,
  ], 'Search with Keywords "greater than or equal" filter');
  $query = [
    'id[value]' => 1,
    'id_op' => '!=',
    'keywords[value]' => 'banana',
    'keywords_op' => '<',
  ];
  $this
    ->checkResults($query, [
    2,
    4,
  ], 'Search with Keywords "less than" filter');
  $query = [
    'keywords[value]' => 'orange',
    'keywords_op' => '!=',
  ];
  $this
    ->checkResults($query, [
    3,
    4,
  ], 'Search with Keywords "not equal" filter');
  $query = [
    'keywords_op' => 'empty',
  ];
  $label = 'Search with Keywords "empty" filter';
  $this
    ->checkResults($query, [
    3,
  ], $label, 'all/all/all');
  $query = [
    'keywords_op' => 'not empty',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    4,
    5,
  ], 'Search with Keywords "not empty" filter');
  $query = [
    'name[value]' => 'foo',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    4,
  ], 'Search with Name "contains" filter');
  $query = [
    'name[value]' => 'foo',
    'name_op' => '!=',
  ];
  $this
    ->checkResults($query, [
    3,
    5,
  ], 'Search with Name "doesn\'t contain" filter');
  $query = [
    'name_op' => 'empty',
  ];
  $this
    ->checkResults($query, [], 'Search with Name "empty" filter');
  $query = [
    'name_op' => 'not empty',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with Name "not empty" filter');
  $query = [
    'language' => [
      '***LANGUAGE_site_default***',
    ],
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with "Page content language" filter');
  $query = [
    'language' => [
      'en',
    ],
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with "English" language filter');
  $query = [
    'language' => [
      Language::LANGCODE_NOT_SPECIFIED,
    ],
  ];
  $this
    ->checkResults($query, [], 'Search with "Not specified" language filter');
  $query = [
    'language' => [
      '***LANGUAGE_language_interface***',
      'zxx',
    ],
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with multiple languages filter');
  $query = [
    'search_api_fulltext' => 'foo to test',
    'id[value]' => 2,
    'id_op' => '>',
    'keywords_op' => 'not empty',
  ];
  $this
    ->checkResults($query, [
    4,
  ], 'Search with multiple filters');

  // Test contextual filters. Configured contextual filters are:
  // 1: datasource
  // 2: type (not = true)
  // 3: keywords (break_phrase = true)
  $this
    ->checkResults([], [
    4,
    5,
  ], 'Search with arguments', 'entity:entity_test_mulrev_changed/item/grape');

  // "Type" doesn't have "break_phrase" enabled, so the second argument won't
  // have any effect.
  $this
    ->checkResults([], [
    2,
    4,
    5,
  ], 'Search with arguments', 'all/item+article/strawberry+apple');

  // Check "OR" contextual filters (using commas).
  $this
    ->checkResults([], [
    4,
  ], 'Search with OR arguments', 'all/item,article/strawberry,apple');
  $this
    ->checkResults([], [], 'Search with unknown datasource argument', 'entity:foobar/all/all');
  $query = [
    'id[value]' => 1,
    'id_op' => '!=',
    'keywords[value]' => 'melon',
    'keywords_op' => '>=',
  ];
  $this
    ->checkResults($query, [
    2,
    5,
  ], 'Search with arguments and filters', 'entity:entity_test_mulrev_changed/all/orange');

  // Make sure the datasource filter works correctly with multiple selections.
  $index = Index::load($this->indexId);
  $datasource = \Drupal::getContainer()
    ->get('search_api.plugin_helper')
    ->createDatasourcePlugin($index, 'entity:user');
  $index
    ->addDatasource($datasource);
  $index
    ->save();
  $query = [
    'datasource' => [
      'entity:user',
      'entity:entity_test_mulrev_changed',
    ],
    'datasource_op' => 'or',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search with multiple datasource filters (OR)');
  $query = [
    'datasource' => [
      'entity:user',
      'entity:entity_test_mulrev_changed',
    ],
    'datasource_op' => 'and',
  ];
  $this
    ->checkResults($query, [], 'Search with multiple datasource filters (AND)');
  $query = [
    'datasource' => [
      'entity:user',
    ],
    'datasource_op' => 'not',
  ];
  $this
    ->checkResults($query, [
    1,
    2,
    3,
    4,
    5,
  ], 'Search for non-user results');
  $query = [
    'datasource' => [
      'entity:entity_test_mulrev_changed',
    ],
    'datasource_op' => 'not',
  ];
  $this
    ->checkResults($query, [], 'Search for non-test entity results');
  $query = [
    'datasource' => [
      'entity:user',
      'entity:entity_test_mulrev_changed',
    ],
    'datasource_op' => 'not',
  ];
  $this
    ->checkResults($query, [], 'Search for results of no available datasource');
  $this
    ->regressionTests();

  // Check special functionality that requires editing the view.
  $this
    ->checkExposedSearchFields();

  // Make sure there was a display plugin created for this view.

  /** @var \Drupal\search_api\Display\DisplayInterface[] $displays */
  $displays = \Drupal::getContainer()
    ->get('plugin.manager.search_api.display')
    ->getInstances();
  $display_id = 'views_page:search_api_test_view__page_1';
  $this
    ->assertArrayHasKey($display_id, $displays, 'A display plugin was created for the test view page display.');
  $this
    ->assertArrayHasKey('views_block:search_api_test_view__block_1', $displays, 'A display plugin was created for the test view block display.');
  $this
    ->assertArrayHasKey('views_rest:search_api_test_view__rest_export_1', $displays, 'A display plugin was created for the test view block display.');
  $this
    ->assertEquals('/search-api-test', $displays[$display_id]
    ->getPath(), 'Display returns the correct path.');
  $view_url = Url::fromUserInput('/search-api-test')
    ->toString();
  $display_url = Url::fromUserInput($displays[$display_id]
    ->getPath())
    ->toString();
  $this
    ->assertEquals($view_url, $display_url, 'Display returns the correct URL.');
  $this
    ->assertNull($displays['views_block:search_api_test_view__block_1']
    ->getPath(), 'Block display returns the correct path.');
  $this
    ->assertEquals('/search-api-rest-test', $displays['views_rest:search_api_test_view__rest_export_1']
    ->getPath(), 'REST display returns the correct path.');
  $this
    ->assertEquals('database_search_index', $displays[$display_id]
    ->getIndex()
    ->id(), 'Display returns the correct search index.');
  $admin_user = $this
    ->drupalCreateUser([
    'administer search_api',
    'access administration pages',
    'administer views',
  ]);
  $this
    ->drupalLogin($admin_user);

  // Delete the page display for the view.
  $this
    ->drupalGet('admin/structure/views/view/search_api_test_view/edit/page_1');
  $this
    ->submitForm([], 'Delete Page');
  $this
    ->submitForm([], 'Save');
  drupal_flush_all_caches();
  $displays = \Drupal::getContainer()
    ->get('plugin.manager.search_api.display')
    ->getInstances();
  $this
    ->assertArrayNotHasKey('views_page:search_api_test_view__page_1', $displays, 'No display plugin was created for the test view page display.');
  $this
    ->assertArrayHasKey('views_block:search_api_test_view__block_1', $displays, 'A display plugin was created for the test view block display.');
  $this
    ->assertArrayHasKey('views_rest:search_api_test_view__rest_export_1', $displays, 'A display plugin was created for the test view block display.');
}