ui_icons-1.0.x-dev/tests/src/Unit/IconSearchTest.php

tests/src/Unit/IconSearchTest.php
<?php

declare(strict_types=1);

// cspell:ignore corge quux
namespace Drupal\Tests\ui_icons\Unit\Controller;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Theme\Icon\IconDefinition;
use Drupal\Core\Theme\Icon\IconDefinitionInterface;
use Drupal\Core\Theme\Icon\Plugin\IconPackManagerInterface;
use Drupal\Tests\Core\Theme\Icon\IconTestTrait;
use Drupal\ui_icons\IconSearch;
use PHPUnit\Framework\TestCase;

/**
 * @coversDefaultClass \Drupal\ui_icons\IconSearch
 *
 * @group ui_icons
 */
class IconSearchTest extends TestCase {

  use IconTestTrait;

  /**
   * The container.
   *
   * @var \Drupal\Core\DependencyInjection\ContainerBuilder
   */
  private ContainerBuilder $container;

  /**
   * The icon pack manager.
   *
   * @var \Drupal\Core\Theme\Icon\Plugin\IconPackManagerInterface
   */
  private IconPackManagerInterface $iconPackManager;

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  private RendererInterface $renderer;

  /**
   * The icon search service.
   *
   * @var \Drupal\ui_icons\IconSearch
   */
  private IconSearch $iconSearch;

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

    $this->container = new ContainerBuilder();
    \Drupal::setContainer($this->container);

    $this->iconPackManager = $this->createMock(IconPackManagerInterface::class);
    $this->renderer = $this->createMock(RendererInterface::class);
    $this->renderer
      ->method('renderInIsolation')
      ->willReturn(new Markup('_rendered_'));

    $this->iconSearch = new IconSearch(
      $this->iconPackManager,
      $this->renderer,
      // @todo test the cache.
      $this->createMock(CacheBackendInterface::class),
    );
  }

  /**
   * Test the _construct method.
   */
  public function testConstructor(): void {
    $iconSearch = new IconSearch(
      $this->createMock(IconPackManagerInterface::class),
      $this->createMock(RendererInterface::class),
      $this->createMock(CacheBackendInterface::class)
    );

    $this->assertInstanceOf(IconSearch::class, $iconSearch);
  }

  /**
   * Provide data for testSearch.
   *
   * @return \Generator
   *   The test cases.
   */
  public static function searchDataProviderId(): iterable {

    yield 'empty' => [
      'query' => '',
    ];

    yield 'space' => [
      'query' => ' ',
    ];

    yield 'one char' => [
      'query' => 'a',
    ];

    yield 'one char spaces' => [
      'query' => ' a ',
    ];

    yield 'no words' => [
      'query' => '?!%$*+',
    ];

    // Test the id based search.
    yield 'id exact full' => [
      'query' => '_pack_match_:_match_',
      'allowed_icon_pack' => [],
      'icons' => [
        'foo:bar',
        '_pack_match_:_match_',
        'baz:corge',
      ],
      'expected' => [
        '_pack_match_:_match_',
      ],
    ];

    yield 'id exact full wrong pack' => [
      'query' => '_match_:_match_',
      'allowed_icon_pack' => ['other'],
      'icons' => [
        'foo:bar',
        '_match_:_match_',
        'baz:corge',
      ],
      'expected' => NULL,
    ];

    yield 'id exact full good pack' => [
      'query' => '_match_pack_:_match_',
      'allowed_icon_pack' => ['_match_pack_'],
      'icons' => [
        'foo:bar',
        '_match_pack_:_match_',
        'baz:corge',
      ],
      'expected' => [
        '_match_pack_:_match_',
      ],
    ];

    yield 'id exact' => [
      'query' => '_match_',
      'allowed_icon_pack' => [],
      'icons' => [
        'bar:_match_',
        'baz:corge',
        'foo:_match_',
      ],
      'expected' => [
        'bar:_match_',
        'foo:_match_',
      ],
    ];

    yield 'id exact wrong pack' => [
      'query' => '_match_',
      'allowed_icon_pack' => ['other'],
      'icons' => [
        'bar:_match_',
        'baz:corge',
        'foo:_match_',
      ],
      'expected' => NULL,
    ];

    yield 'id exact good pack' => [
      'query' => '_match_',
      'allowed_icon_pack' => ['_match_pack_'],
      'icons' => [
        'bar:_match_',
        'baz:corge',
        '_match_pack_:_match_',
      ],
      'expected' => [
        '_match_pack_:_match_',
      ],
    ];

    yield 'id exact multiple results' => [
      'query' => '_match_',
      'allowed_icon_pack' => [],
      'icons' => [
        'foo:_match_',
        'bar:_match_',
        'bar:bar',
        'baz:_match_',
        'baz:baz',
        'corge:_match_',
      ],
      'expected' => [
        'foo:_match_',
        'bar:_match_',
        'baz:_match_',
        'corge:_match_',
      ],
    ];

    yield 'id exact multiple results wrong pack' => [
      'query' => '_match_',
      'allowed_icon_pack' => ['other'],
      'icons' => [
        'foo:_match_',
        'bar:_match_',
        'bar:bar',
        'baz:_match_',
        'baz:baz',
        'corge:_match_',
      ],
      'expected' => NULL,
    ];

    yield 'id exact multiple results good packs' => [
      'query' => '_match_',
      'allowed_icon_pack' => ['_match_pack_', '_match_pack_2_'],
      'icons' => [
        'bar:_match_',
        'bar:bar',
        '_match_pack_:_match_',
        'baz:_match_',
        'baz:baz',
        '_match_pack_2_:_match_',
      ],
      'expected' => [
        '_match_pack_:_match_',
        '_match_pack_2_:_match_',
      ],
    ];
  }

  /**
   * Provide data for testSearch.
   *
   * @return \Generator
   *   The test cases.
   */
  public static function searchDataProviderWord(): iterable {
    // Test words search.
    yield 'word result' => [
      'query' => 'fo',
      'allowed_icon_pack' => [],
      'icons' => [
        'bar:foo',
        'bar:bar',
        'baz: this is foo',
        'baz:baz',
        'corge:bar',
        'corge:foo or what? ',
        'qux:bar',
      ],
      'expected' => [
        'bar:foo',
        'baz: this is foo',
        'corge:foo or what? ',
      ],
    ];

    yield 'words with one match' => [
      'query' => 'part bar',
      'allowed_icon_pack' => [],
      'icons' => [
        'foo:_partial_barista_',
        'qux:quux',
        'baz:corge',
        'baz:baz',
      ],
      'expected' => [
        'foo:_partial_barista_',
      ],
    ];

    yield 'words with one match wrong pack' => [
      'query' => 'part bar',
      'allowed_icon_pack' => ['other'],
      'icons' => [
        'foo:_partial_barista_',
        'qux:quux',
        'baz:corge',
        'baz:baz',
      ],
      'expected' => NULL,
    ];

    yield 'words with one match good pack' => [
      'query' => 'part bar',
      'allowed_icon_pack' => ['_match_pack_'],
      'icons' => [
        '_match_pack_:_partial_barista_',
        'qux:quux',
        'baz:corge',
        'baz:baz',
      ],
      'expected' => [
        '_match_pack_:_partial_barista_',
      ],
    ];

    yield 'words with multiple match' => [
      'query' => 'foo bar',
      'allowed_icon_pack' => [],
      'icons' => [
        'foo:_partial_barista_',
        'qux:quux',
        'baz: some foolish',
        'baz:baz',
      ],
      'expected' => [
        'foo:_partial_barista_',
        'baz: some foolish',
      ],
    ];

    yield 'words with multiple match and one pack' => [
      'query' => 'foo bar',
      'allowed_icon_pack' => ['foo'],
      'icons' => [
        'foo:_partial_barista_',
        'qux:quux',
        'baz: some foolish',
        'baz:baz',
      ],
      'expected' => [
        'foo:_partial_barista_',
      ],
    ];

    yield 'words with multiple match and multiple pack' => [
      'query' => 'part bar',
      'allowed_icon_pack' => ['_match_pack_', '_other_match_pack'],
      'icons' => [
        '_match_pack_:_partial_barista_',
        'qux:quux',
        '_match_pack_: some foolish',
        'baz:baz',
      ],
      'expected' => [
        '_match_pack_:_partial_barista_',
      ],
    ];

    yield 'words specials chars ignored with multiple match' => [
      'query' => '!foo? !ùµ$::!bar.çà',
      'allowed_icon_pack' => [],
      'icons' => [
        'foo:_partial_barista_',
        'qux:quux',
        'baz: some foolish',
        'baz:baz',
      ],
      'expected' => [
        'foo:_partial_barista_',
        'baz: some foolish',
      ],
    ];
  }

  /**
   * Tests the search method of the IconSearch.
   *
   * @param string $query
   *   The search query to test.
   * @param array $allowed_icon_pack
   *   The limited allowed icon pack to test.
   * @param array $icons
   *   The icons returned by IconPackManager::getIcons().
   * @param array|null $expected
   *   The expected result values.
   *
   * @dataProvider searchDataProviderId
   * @dataProvider searchDataProviderWord
   */
  public function testSearch(string $query, array $allowed_icon_pack = [], array $icons = [], ?array $expected = NULL): void {

    $this->preparePackManagerMock($icons, $allowed_icon_pack);
    $result = $this->iconSearch->search(
      $query,
      $allowed_icon_pack,
      5,
      [ResultCallback::class, 'testCreateResultEntry'],
    );

    if (NULL === $expected) {
      $this->assertEmpty($result);
      return;
    }

    $this->assertCount(count($expected), $result);

    foreach ($expected as $index => $expected_icon_id) {
      $this->assertArrayHasKey('_test_callback_', $result[$index]);
      $this->assertEquals($expected_icon_id, $result[$index]['_test_callback_']);
    }
  }

  /**
   * Helper to mock the iconPackManager getIcon() and getIcons() method.
   *
   * @param array $icons
   *   The icons returned by IconPackManager::getIcons().
   * @param array $allowed_icon_pack
   *   The limited allowed icon pack to test.
   */
  private function preparePackManagerMock(array $icons = [], array $allowed_icon_pack = []): void {
    if (!empty($allowed_icon_pack)) {
      foreach ($icons as $key => $icon_full_id) {
        [$pack_id] = explode(IconDefinition::ICON_SEPARATOR, $icon_full_id);
        if (!in_array($pack_id, $allowed_icon_pack)) {
          unset($icons[$key]);
        }
      }
    }

    $this->iconPackManager
      ->method('getIcons')
      ->with($allowed_icon_pack)
      ->willReturn(array_flip($icons));

    $icons_returned_map = [];
    foreach ($icons as $icon_full_id) {
      [$pack_id, $icon_id] = explode(IconDefinition::ICON_SEPARATOR, $icon_full_id);
      $icons_returned_map[] = [
        $icon_full_id,
        $this->createTestIcon([
          'pack_id' => $pack_id,
          'icon_id' => $icon_id,
        ]),
      ];
    }

    $this->iconPackManager
      ->method('getIcon')
      ->willReturnMap($icons_returned_map);
  }

}

/**
 * Test callback class.
 */
class ResultCallback {

  /**
   * Test callback icon result.
   *
   * @param \Drupal\Core\Theme\Icon\IconDefinitionInterface $icon
   *   The icon to process.
   * @param \Drupal\Core\Render\Markup $renderable
   *   The icon preview renderable.
   *
   * @return array
   *   The icon result with key '_test_callback_'.
   */
  public static function testCreateResultEntry(IconDefinitionInterface $icon, Markup $renderable): ?array {
    return ['_test_callback_' => $icon->getId()];
  }

}

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

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