search_api_autocomplete-8.x-1.x-dev/tests/src/Kernel/ViewsTest.php

tests/src/Kernel/ViewsTest.php
<?php

namespace Drupal\Tests\search_api_autocomplete\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\search_api\Query\ConditionInterface;
use Drupal\search_api_autocomplete\Element\SearchApiAutocomplete as AutocompleteElement;
use Drupal\search_api_autocomplete\Entity\Search;
use Drupal\search_api_autocomplete\Search\SearchPluginManager;
use Drupal\search_api_autocomplete\Utility\PluginHelper;
use Drupal\views\Entity\View;

/**
 * Tests Views integration of the Autocomplete module.
 *
 * @group search_api_autocomplete
 */
class ViewsTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'entity_test',
    'field',
    'search_api_autocomplete',
    'search_api_autocomplete_test',
    'search_api',
    'search_api_test',
    'search_api_test_example_content',
    'system',
    'text',
    'user',
    'views',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->installEntitySchema('entity_test_mulrev_changed');
    $this->installEntitySchema('search_api_task');
    $this->installEntitySchema('user');
    $this->installSchema('search_api', ['search_api_item']);
    $this->installConfig('search_api');
    $this->installConfig('search_api_test_example_content');

    // Do not use a batch for tracking the initial items after creating an
    // index when running the tests via the GUI. Otherwise, it seems Drupal's
    // Batch API gets confused and the test fails.
    if (php_sapi_name() != 'cli') {
      \Drupal::state()->set('search_api_use_tracking_batch', FALSE);
    }
  }

  /**
   * Tests that valid search plugin definitions are created for search views.
   */
  public function testSearchPlugin() {
    $index_id = 'autocomplete_search_index';
    $plugin_helper = $this->container
      ->get('search_api_autocomplete.plugin_helper');

    $plugins = $plugin_helper->createSearchPluginsForIndex($index_id);
    $view_id = 'views:search_api_autocomplete_test_view';
    $this->assertArrayNotHasKey($view_id, $plugins);

    $this->installConfig('search_api_autocomplete_test');

    // To avoid getting the cached derivatives from the Views search plugin
    // deriver, we unfortunately need to rebuild the search plugin manager. This
    // is probably the simplest way to do it, without too many side effects.
    $search_plugin_manager = new SearchPluginManager(
      $this->container->get('container.namespaces'),
      $this->container->get('cache.discovery'),
      $this->container->get('module_handler')
    );
    $plugin_helper = new PluginHelper(
      $this->container->get('plugin.manager.search_api_autocomplete.suggester'),
      $search_plugin_manager
    );

    $plugins = $plugin_helper->createSearchPluginsForIndex($index_id);
    $this->assertArrayHasKey($view_id, $plugins);
    /** @var \Drupal\search_api_autocomplete\Search\SearchPluginInterface $plugin */
    $plugin = $plugins[$view_id];
    $this->assertEquals('Search API Autocomplete Test view', $plugin->label());
    $this->assertEquals('Search views', $plugin->getGroupLabel());
    $this->assertEquals('Searches provided by Views', $plugin->getGroupDescription());

    $data = [
      'display' => 'page',
      'filter' => 'keys',
    ];
    $query = $plugin->createQuery('foobar', $data);
    $this->assertEquals('foobar', $query->getOriginalKeys());
    $index = $query->getIndex();
    $this->assertEquals($index_id, $index->id());
    $fields = $query->getFulltextFields();
    $all_fulltext_fields = $index->getFulltextFields();
    $fields = isset($fields) ? $fields : $all_fulltext_fields;
    $this->assertEquals($all_fulltext_fields, $fields);

    $query = $plugin->createQuery('', $data);
    $this->assertNull($query->getOriginalKeys());

    $data = [
      'display' => 'page',
      'filter' => 'name',
      'field' => 'name',
    ];
    $query = $plugin->createQuery('foobar', $data);
    $this->assertNull($query->getOriginalKeys());
    $this->assertStringContainsString('foobar', (string) $query);
    $conditions = $query->getConditionGroup()->getConditions();
    $conditions = $this->collectConditions($conditions);
    $this->assertCount(1, $conditions);
    $condition = $conditions[0];
    $this->assertEquals('name', $condition->getField());
    $this->assertEquals('foobar', $condition->getValue());
    $this->assertEquals($index_id, $query->getIndex()->id());
    $this->assertEquals(['name'], $query->getFulltextFields());
  }

  /**
   * Collects conditions from an array of conditions and condition groups.
   *
   * Any information about condition nesting, group operators, etc. is lost.
   * Only makes sense for tests.
   *
   * @param \Drupal\search_api\Query\ConditionInterface[]|\Drupal\search_api\Query\ConditionGroupInterface[] $conditions
   *   An array of conditions and condition groups.
   *
   * @return \Drupal\search_api\Query\ConditionInterface[]
   *   All conditions contained in the given array of conditions and condition
   *   groups.
   */
  protected function collectConditions(array $conditions) {
    $ret = [];

    foreach ($conditions as $condition) {
      if ($condition instanceof ConditionInterface) {
        $ret[] = $condition;
      }
      else {
        $new = $this->collectConditions($condition->getConditions());
        $ret = array_merge($ret, $new);
      }
    }

    return $ret;
  }

  /**
   * Tests that Views forms are altered correctly.
   *
   * @see search_api_autocomplete_form_views_exposed_form_alter()
   *
   * @dataProvider formAlteringDataProvider
   */
  public function testFormAltering($display_id, $expect_altered) {
    $this->installConfig('search_api_autocomplete_test');

    Search::create([
      'id' => 'search_api_autocomplete_test_view',
      'label' => 'Search API Autocomplete Test view',
      'index_id' => 'autocomplete_search_index',
      'suggester_settings' => [
        'live_results' => [],
      ],
      'search_settings' => [
        'views:search_api_autocomplete_test_view' => [
          'displays' => [
            'default' => TRUE,
            'selected' => ['page_2'],
          ],
        ],
      ],
    ])->save();

    $view = View::load('search_api_autocomplete_test_view');
    /** @var \Drupal\views\ViewExecutable $executable */
    $executable = $view->getExecutable();
    $this->assertTrue($executable->setDisplay($display_id));
    $executable->initHandlers();

    /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginInterface $exposed_form */
    $exposed_form = $executable->display_handler->getPlugin('exposed_form');
    $form = $exposed_form->renderExposedForm();

    $keys_element = $form['keys'] ?? $form['keys_wrapper']['keys'];
    if ($expect_altered) {
      $this->assertEquals('search_api_autocomplete', $keys_element['#type']);
    }
    else {
      $this->assertEquals('textfield', $keys_element['#type']);
    }

    // Check that the "#process" callbacks were altered correctly in
    // AutocompleteHelper::alterElement().
    if ($display_id === 'exposed_form_plugin' &&
        $expect_altered &&
        !empty($keys_element['#process'])) {
      $element_class = AutocompleteElement::class;
      $element_class_methods = [];
      foreach ($keys_element['#process'] as $process_callback) {
        $process_callback_method = '';
        if (is_array($process_callback)) {
          $process_callback_method = implode('::', $process_callback);
        }
        elseif (is_string($process_callback)) {
          $process_callback_method = $process_callback;
        }

        if (str_starts_with($process_callback_method, "$element_class::") ||
            str_starts_with($process_callback_method, 'Drupal\Core\Render\Element\Textfield::')) {
          $process_callback_parts = explode('::', $process_callback_method);
          $element_class_methods[$process_callback_parts[1]][] = $process_callback_method;
        }
      }

      $duplicate_class_methods = array_filter($element_class_methods, function ($v) {
        return count($v) > 1;
      });
      $this->assertEmpty(
        $duplicate_class_methods,
        'There should not be duplicate element #process callbacks. The following methods are duplicated: ' . print_r($duplicate_class_methods, TRUE),
      );
    }
  }

  /**
   * Provides test data for testFormAltering().
   *
   * @return array
   *   Array of argument arrays for testFormAltering().
   *
   * @see \Drupal\Tests\search_api_autocomplete\Kernel\ViewsTest::testFormAltering()
   */
  public static function formAlteringDataProvider(): array {
    return [
      'do alter' => ['page', TRUE],
      "don't alter" => ['page_2', FALSE],
      'exposed_form_plugin' => ['exposed_form_plugin', TRUE],
    ];
  }

  /**
   * Tests that the deriver works correctly.
   *
   * @see \Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\search\ViewsDeriver
   */
  public function testDeriver() {
    $searches = $this->container
      ->get('plugin.manager.search_api_autocomplete.search')
      ->getDefinitions();
    ksort($searches);
    $expected = [
      'search_api_autocomplete_test',
      'search_api_autocomplete_test_hidden',
    ];
    $this->assertEquals($expected, array_keys($searches));

    $this->installConfig('search_api_autocomplete_test');

    $searches = $this->container
      ->get('plugin.manager.search_api_autocomplete.search')
      ->getDefinitions();
    ksort($searches);
    $expected = [
      'search_api_autocomplete_test',
      'search_api_autocomplete_test_hidden',
      'views:search_api_autocomplete_test_view',
    ];
    $this->assertEquals($expected, array_keys($searches));

    View::create([
      'id' => 'second_test_view',
      'base_field' => 'search_api_id',
      'base_table' => 'search_api_index_autocomplete_search_index',
      'core' => '8.x',
      'display' => [
        'default' => [
          'display_plugin' => 'default',
          'id' => 'default',
          'display_title' => 'Master',
          'position' => 0,
          'display_options' => [
            'query' => [
              'type' => 'search_api_query',
            ],
          ],
        ],
      ],
    ])->save();

    $searches = $this->container
      ->get('plugin.manager.search_api_autocomplete.search')
      ->getDefinitions();
    ksort($searches);
    $expected = [
      'search_api_autocomplete_test',
      'search_api_autocomplete_test_hidden',
      'views:search_api_autocomplete_test_view',
      'views:second_test_view',
    ];
    $this->assertEquals($expected, array_keys($searches));
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc