class IconFinderTest

@coversDefaultClass \Drupal\Core\Theme\Icon\IconFinder

@group icon

Hierarchy

Expanded class hierarchy of IconFinderTest

File

core/tests/Drupal/Tests/Core/Theme/Icon/IconFinderTest.php, line 18

Namespace

Drupal\Tests\Core\Theme\Icon
View source
class IconFinderTest extends UnitTestCase {
  private const TEST_ICONS_PATH = 'core/modules/system/tests/modules/icon_test';
  private const TEST_RELATIVE_URL = 'foo/bar';
  
  /**
   * The file url generator instance.
   *
   * @var \Drupal\Core\File\FileUrlGeneratorInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  private FileUrlGeneratorInterface $fileUrlGenerator;
  
  /**
   * The logger service instance.
   *
   * @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  private LoggerInterface $logger;
  
  /**
   * The IconFinder instance.
   *
   * @var \Drupal\Core\Theme\Icon\IconFinder
   */
  private IconFinder $iconFinder;
  
  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    $this->fileUrlGenerator = $this->getMockBuilder('Drupal\\Core\\File\\FileUrlGeneratorInterface')
      ->disableOriginalConstructor()
      ->getMock();
    $this->logger = $this->createMock(LoggerInterface::class);
    $this->iconFinder = new IconFinder($this->fileUrlGenerator, $this->logger, DRUPAL_ROOT);
  }
  
  /**
   * Data provider for ::testGetFilesFromSourcesUrl().
   *
   * @return \Generator
   *   The test cases, with expected result as icon_id.
   */
  public static function providerGetFilesFromSourcesUrl() : iterable {
    (yield 'empty sources' => [
      [],
    ]);
    (yield 'url valid' => [
      [
        'http://example.com/foo.png',
        'https://example.com/bar.png',
        'https://example.com/fOO%20folder%20%C3%B9/FoO%21%20BaR%3D%281%29%20iCo-n.png%3Ftest%3DfOO%23bAz',
      ],
      [
        'foo' => 'http://example.com/foo.png',
        'bar' => 'https://example.com/bar.png',
        'FoO! BaR=(1) iCo-n' => 'https://example.com/fOO%20folder%20%C3%B9/FoO%21%20BaR%3D%281%29%20iCo-n.png%3Ftest%3DfOO%23bAz',
      ],
    ]);
    (yield 'url encoded' => [
      [
        'https://example.com/fOO%20folder%20%C3%B9/FoO%21%20BaR%3D%281%29%20iCo-n.png%3Ftest%3DfOO%23bAz',
      ],
      [
        'FoO! BaR=(1) iCo-n' => 'https://example.com/fOO%20folder%20%C3%B9/FoO%21%20BaR%3D%281%29%20iCo-n.png%3Ftest%3DfOO%23bAz',
      ],
    ]);
    (yield 'url not encoded' => [
      [
        'https://example.com/fOO folder ù/FoO_Ba,R=(1) iCo-n.png?test=fOO#bAz',
      ],
      [
        'FoO_Ba,R=(1) iCo-n' => 'https://example.com/fOO folder ù/FoO_Ba,R=(1) iCo-n.png?test=fOO#bAz',
      ],
    ]);
    (yield 'url valid with duplicate' => [
      [
        'http://example.com/foo.png',
        'https://example.com/bar.png',
        'http://example.com/foo.svg',
        'https://example.com/bar.svg',
      ],
      [
        'foo' => 'http://example.com/foo.svg',
        'bar' => 'https://example.com/bar.svg',
      ],
    ]);
    (yield 'url no extension' => [
      [
        'http://example.com/foo',
        'https://example.com/fOO folder ù/FoO BaR=(1) iCo-n?test=fOO#bAz',
      ],
      [
        'foo' => 'http://example.com/foo',
        'FoO BaR=(1) iCo-n' => 'https://example.com/fOO folder ù/FoO BaR=(1) iCo-n?test=fOO#bAz',
      ],
    ]);
    (yield 'url valid with special filename' => [
      [
        'http://example.com/foo (è$ù5 6*$^ _ ù48 \'Bar\']=-n!.png',
      ],
      [
        'foo (è$ù5 6*$^ _ ù48 \'Bar\']=-n!' => 'http://example.com/foo (è$ù5 6*$^ _ ù48 \'Bar\']=-n!.png',
      ],
    ]);
    // Test invalid scheme and empty path.
    (yield 'url not supported scheme or path is invalid' => [
      [
        'ftp://foo/bar.png',
        'ssh://foo/bar.png',
        'sftp://foo/bar.png',
        'htp://foo/bar.png',
        'a://foo/bar.png',
        'http://',
        'https://',
      ],
    ]);
  }
  
  /**
   * Test the IconFinder::getFilesFromSources method with urls.
   *
   * @param array<string> $sources
   *   The list of remote.
   * @param array<string, string> $expected
   *   The expected result.
   *
   * @dataProvider providerGetFilesFromSourcesUrl
   */
  public function testGetFilesFromSourcesUrl(array $sources, array $expected = []) : void {
    $result = $this->iconFinder
      ->getFilesFromSources($sources, '');
    // Prepare result array matching getFileFromHttpUrl() to minimize test data.
    $expected_result = [];
    foreach ($expected as $expected_icon_id => $expected_source) {
      $expected_result[$expected_icon_id] = [
        'icon_id' => $expected_icon_id,
        'source' => $expected_source,
        'absolute_path' => $expected_source,
      ];
    }
    $this->assertEquals($expected_result, $result);
  }
  
  /**
   * Data provider for ::testGetFilesFromSourcesPath().
   *
   * @return \Generator
   *   The test cases, to minimize test data, result expected is an array with:
   *   - icon_id: the expected id
   *   - path: expected path found relative to TEST_ICONS_PATH
   *   - group: The group name if any
   */
  public static function providerGetFilesFromSourcesPath() : iterable {
    (yield 'path empty' => [
      [
        '',
      ],
    ]);
    (yield 'direct file without path' => [
      [
        'foo.svg',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file without extension' => [
      [
        'foo',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file without extension wildcard' => [
      [
        'foo.*',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with wildcard and extension' => [
      [
        '*.svg',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with wildcard only' => [
      [
        '*',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with wildcards' => [
      [
        '*.*',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'path valid' => [
      [
        'icons/flat/foo.png',
        'icons/flat/bar.svg',
      ],
      [
        [
          'foo',
          'icons/flat/foo.png',
        ],
        [
          'bar',
          'icons/flat/bar.svg',
        ],
      ],
    ]);
    (yield 'absolute path valid' => [
      [
        '/' . self::TEST_ICONS_PATH . '/icons/flat/foo.png',
      ],
      [
        [
          'foo',
          'icons/flat/foo.png',
        ],
      ],
    ]);
    (yield 'path not allowed extension' => [
      [
        // File exist but not valid extension.
'icons/flat/foo.webp',
        'icons/flat/*.webp',
        // Non existent file.
'icons/flat/foo-1.jpg',
      ],
    ]);
    (yield 'path without extension' => [
      [
        'icons/flat/foo',
      ],
      [
        [
          'foo',
          'icons/flat/foo.svg',
        ],
      ],
    ]);
    (yield 'path wildcard extension' => [
      [
        'icons/flat/foo.*',
      ],
      [
        [
          'foo',
          'icons/flat/foo.svg',
        ],
      ],
    ]);
    (yield 'path wildcard filename' => [
      [
        'icons/flat/*.svg',
      ],
      [
        [
          'bar-2',
          'icons/flat/bar-2.svg',
        ],
        [
          'bar',
          'icons/flat/bar.svg',
        ],
        [
          'baz-2',
          'icons/flat/baz-2.svg',
        ],
        [
          'foo',
          'icons/flat/foo.svg',
        ],
        [
          '64x64',
          'icons/flat/64x64.svg',
        ],
      ],
    ]);
    (yield 'path wildcard increment filename' => [
      [
        'icons/flat_same_name/*',
      ],
      [
        [
          'foo',
          'icons/flat_same_name/foo.svg',
        ],
      ],
    ]);
    (yield 'path wildcard filename with extension' => [
      [
        'icons/flat/*.svg',
      ],
      [
        [
          'bar-2',
          'icons/flat/bar-2.svg',
        ],
        [
          'baz-2',
          'icons/flat/baz-2.svg',
        ],
        [
          'foo',
          'icons/flat/foo.svg',
        ],
        [
          'bar',
          'icons/flat/bar.svg',
        ],
        [
          '64x64',
          'icons/flat/64x64.svg',
        ],
      ],
    ]);
    (yield 'path wildcard' => [
      [
        '*/flat/*',
      ],
      [
        [
          'bar-2',
          'icons/flat/bar-2.svg',
        ],
        [
          'bar',
          'icons/flat/bar.svg',
        ],
        [
          'baz-1',
          'icons/flat/baz-1.png',
        ],
        [
          'baz-2',
          'icons/flat/baz-2.svg',
        ],
        [
          'foo',
          'icons/flat/foo.svg',
        ],
        [
          '64x64',
          'icons/flat/64x64.svg',
        ],
      ],
    ]);
    (yield 'mix wildcard and extensions' => [
      [
        'icons/flat/foo.*',
        'icons/flat/foo.svg',
      ],
      [
        [
          'foo',
          'icons/flat/foo.svg',
        ],
      ],
    ]);
    (yield 'path group no result' => [
      [
        'icons/group/*',
      ],
      [],
    ]);
    (yield 'path with folder wildcard' => [
      [
        'icons/group/*/*',
      ],
      [
        [
          'bar_group_1',
          'icons/group/group_1/bar_group_1.png',
        ],
        [
          'bar_group_2',
          'icons/group/group_2/bar_group_2.png',
        ],
        [
          'baz_group_1',
          'icons/group/group_1/baz_group_1.png',
        ],
        [
          'baz_group_2',
          'icons/group/group_2/baz_group_2.png',
        ],
        [
          'corge_group_1',
          'icons/group/group_1/corge_group_1.svg',
        ],
        [
          'corge_group_2',
          'icons/group/group_2/corge_group_2.svg',
        ],
        [
          'foo_group_1',
          'icons/group/group_1/foo_group_1.svg',
        ],
        [
          'foo_group_2',
          'icons/group/group_2/foo_group_2.svg',
        ],
      ],
    ]);
    (yield 'path sub group wildcard' => [
      [
        'icons/group/*/sub_sub_group_1/*',
      ],
      [
        [
          'foo_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/foo_sub_group_1.png',
        ],
        [
          'bar_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/bar_sub_group_1.svg',
        ],
      ],
    ]);
    (yield 'path sub group wildcard partial and filename' => [
      [
        'icons/group/*/sub_sub_group_*/*',
      ],
      [
        [
          'foo_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/foo_sub_group_1.png',
        ],
        [
          'corge_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/corge_sub_group_2.png',
        ],
        [
          'bar_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/bar_sub_group_1.svg',
        ],
        [
          'baz_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/baz_sub_group_2.svg',
        ],
      ],
    ]);
    (yield 'path sub group multiple wildcard folder and filename' => [
      [
        'icons/group/*/*/*',
      ],
      [
        [
          'foo_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/foo_sub_group_1.png',
        ],
        [
          'corge_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/corge_sub_group_2.png',
        ],
        [
          'bar_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/bar_sub_group_1.svg',
        ],
        [
          'baz_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/baz_sub_group_2.svg',
        ],
      ],
    ]);
    // Start tests for the {group} placeholder.
    (yield 'path with {group} extracted' => [
      [
        'icons/group/{group}/*',
      ],
      [
        [
          'bar_group_1',
          'icons/group/group_1/bar_group_1.png',
          'group_1',
        ],
        [
          'baz_group_1',
          'icons/group/group_1/baz_group_1.png',
          'group_1',
        ],
        [
          'bar_group_2',
          'icons/group/group_2/bar_group_2.png',
          'group_2',
        ],
        [
          'baz_group_2',
          'icons/group/group_2/baz_group_2.png',
          'group_2',
        ],
        [
          'corge_group_1',
          'icons/group/group_1/corge_group_1.svg',
          'group_1',
        ],
        [
          'foo_group_1',
          'icons/group/group_1/foo_group_1.svg',
          'group_1',
        ],
        [
          'corge_group_2',
          'icons/group/group_2/corge_group_2.svg',
          'group_2',
        ],
        [
          'foo_group_2',
          'icons/group/group_2/foo_group_2.svg',
          'group_2',
        ],
      ],
    ]);
    (yield 'test group extracted wildcard after' => [
      [
        'icons/group/{group}/*/*',
      ],
      [
        [
          'bar_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/bar_sub_group_1.svg',
          'sub_group_1',
        ],
        [
          'baz_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/baz_sub_group_2.svg',
          'sub_group_2',
        ],
        [
          'corge_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/corge_sub_group_2.png',
          'sub_group_2',
        ],
        [
          'foo_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/foo_sub_group_1.png',
          'sub_group_1',
        ],
      ],
    ]);
    (yield 'test group extracted wildcard before' => [
      [
        'icons/group/*/{group}/*',
      ],
      [
        [
          'bar_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/bar_sub_group_1.svg',
          'sub_sub_group_1',
        ],
        [
          'baz_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/baz_sub_group_2.svg',
          'sub_sub_group_2',
        ],
        [
          'corge_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/corge_sub_group_2.png',
          'sub_sub_group_2',
        ],
        [
          'foo_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/foo_sub_group_1.png',
          'sub_sub_group_1',
        ],
      ],
    ]);
    (yield 'test group extracted wildcard both' => [
      [
        'icons/*/{group}/*/*',
      ],
      [
        [
          'bar_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/bar_sub_group_1.svg',
          'sub_group_1',
        ],
        [
          'baz_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/baz_sub_group_2.svg',
          'sub_group_2',
        ],
        [
          'corge_sub_group_2',
          'icons/group/sub_group_2/sub_sub_group_2/corge_sub_group_2.png',
          'sub_group_2',
        ],
        [
          'foo_sub_group_1',
          'icons/group/sub_group_1/sub_sub_group_1/foo_sub_group_1.png',
          'sub_group_1',
        ],
      ],
    ]);
    (yield 'test group same name' => [
      [
        'icons/group_same_name/{group}/*',
      ],
      [
        [
          'foo',
          'icons/group_same_name/group_3/foo.svg',
          'group_3',
        ],
      ],
    ]);
    // Start tests for the {icon_id} placeholder.
    (yield 'direct file with icon_id' => [
      [
        '{icon_id}',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and extension' => [
      [
        '{icon_id}.svg',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and extension wildcard' => [
      [
        '{icon_id}.*',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and wildcard after' => [
      [
        '{icon_id}*',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and wildcard before' => [
      [
        '*{icon_id}',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and wildcard around' => [
      [
        '*{icon_id}*',
      ],
      [
        [
          'foo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and wildcard around and prefix' => [
      [
        'f*{icon_id}*',
      ],
      [
        [
          'oo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and wildcard around and suffix' => [
      [
        '*{icon_id}*o',
      ],
      [
        [
          'fo',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'direct file with icon_id and wildcard around and prefix and suffix' => [
      [
        'f*{icon_id}*o',
      ],
      [
        [
          'o',
          'foo.svg',
        ],
      ],
    ]);
    (yield 'test icon_id extracted' => [
      [
        'icons/prefix_suffix/{icon_id}.svg',
      ],
      [
        [
          'grault',
          'icons/prefix_suffix/grault.svg',
        ],
        [
          'garply_suffix',
          'icons/prefix_suffix/garply_suffix.svg',
        ],
        [
          'prefix_quux',
          'icons/prefix_suffix/prefix_quux.svg',
        ],
        [
          'prefix_corge_suffix',
          'icons/prefix_suffix/prefix_corge_suffix.svg',
        ],
      ],
    ]);
    (yield 'test icon_id extracted prefix' => [
      [
        'icons/prefix_suffix/prefix_{icon_id}.svg',
      ],
      [
        [
          'quux',
          'icons/prefix_suffix/prefix_quux.svg',
        ],
        [
          'corge_suffix',
          'icons/prefix_suffix/prefix_corge_suffix.svg',
        ],
      ],
    ]);
    (yield 'test icon_id extracted suffix' => [
      [
        'icons/prefix_suffix/{icon_id}_suffix.svg',
      ],
      [
        [
          'garply',
          'icons/prefix_suffix/garply_suffix.svg',
        ],
        [
          'prefix_corge',
          'icons/prefix_suffix/prefix_corge_suffix.svg',
        ],
      ],
    ]);
    (yield 'test icon_id extracted both' => [
      [
        'icons/prefix_suffix/prefix_{icon_id}_suffix.svg',
      ],
      [
        [
          'corge',
          'icons/prefix_suffix/prefix_corge_suffix.svg',
        ],
      ],
    ]);
    (yield 'test icon_id extracted with group' => [
      [
        'icons/prefix_suffix/{group}/{icon_id}.svg',
      ],
      [
        [
          'fred_group',
          'icons/prefix_suffix/group/fred_group.svg',
          'group',
        ],
        [
          'plugh_group_suffix',
          'icons/prefix_suffix/group/plugh_group_suffix.svg',
          'group',
        ],
        [
          'prefix_qux_group',
          'icons/prefix_suffix/group/prefix_qux_group.svg',
          'group',
        ],
        [
          'prefix_waldo_group_suffix',
          'icons/prefix_suffix/group/prefix_waldo_group_suffix.svg',
          'group',
        ],
      ],
    ]);
    (yield 'test icon_id extracted with group and wildcard' => [
      [
        'icons/*/{group}/{icon_id}.svg',
      ],
      [
        [
          'corge_group_1',
          'icons/group/group_1/corge_group_1.svg',
          'group_1',
        ],
        [
          'foo_group_1',
          'icons/group/group_1/foo_group_1.svg',
          'group_1',
        ],
        [
          'corge_group_2',
          'icons/group/group_2/corge_group_2.svg',
          'group_2',
        ],
        [
          'foo_group_2',
          'icons/group/group_2/foo_group_2.svg',
          'group_2',
        ],
        [
          'foo',
          'icons/group_same_name/group_3/foo.svg',
          'group_3',
        ],
        [
          'fred_group',
          'icons/prefix_suffix/group/fred_group.svg',
          'group',
        ],
        [
          'plugh_group_suffix',
          'icons/prefix_suffix/group/plugh_group_suffix.svg',
          'group',
        ],
        [
          'prefix_qux_group',
          'icons/prefix_suffix/group/prefix_qux_group.svg',
          'group',
        ],
        [
          'prefix_waldo_group_suffix',
          'icons/prefix_suffix/group/prefix_waldo_group_suffix.svg',
          'group',
        ],
      ],
    ]);
    (yield 'path {icon_id} partial extracted wildcard extension' => [
      [
        'icons/flat_same_name/f{icon_id}o.*',
      ],
      [
        [
          'o',
          'icons/flat_same_name/foo.svg',
        ],
      ],
    ]);
  }
  
  /**
   * Test the IconFinder::getFilesFromSources method with paths.
   *
   * @param array<string> $sources
   *   The list of remote.
   * @param array<string, string> $expected
   *   The expected result.
   *
   * @dataProvider providerGetFilesFromSourcesPath
   */
  public function testGetFilesFromSourcesPath(array $sources, array $expected = []) : void {
    $this->fileUrlGenerator
      ->expects($this->any())
      ->method('generateString')
      ->willReturnCallback(function ($uri) {
      return self::TEST_RELATIVE_URL . $uri;
    });
    $result = $this->iconFinder
      ->getFilesFromSources($sources, self::TEST_ICONS_PATH);
    // Prepare result array matching processFoundFiles() to minimize test data.
    $expected_result = [];
    foreach ($expected as $key => $expected_value) {
      $icon_id = $expected[$key][0];
      $filename = $expected[$key][1];
      $group = $expected[$key][2] ?? NULL;
      $expected_result[$icon_id] = [
        'icon_id' => $icon_id,
        'source' => self::TEST_RELATIVE_URL . '/' . self::TEST_ICONS_PATH . '/' . $filename,
        'absolute_path' => DRUPAL_ROOT . '/' . self::TEST_ICONS_PATH . '/' . $filename,
        'group' => $group,
      ];
    }
    $this->assertEqualsCanonicalizing($expected_result, $result);
  }
  
  /**
   * Test the IconFinder::getFilesFromPath method with warning.
   */
  public function testGetFilesFromPathEmptyWarning() : void {
    $method = new \ReflectionMethod(IconFinder::class, 'getFilesFromPath');
    $method->setAccessible(TRUE);
    $this->logger
      ->expects($this->once())
      ->method('warning')
      ->with('Invalid icon path extension @filename.@extension in source: @source');
    $method->invoke($this->iconFinder, self::TEST_ICONS_PATH . '/icons/flat/foo.webp', '');
  }
  
  /**
   * Test the IconFinder::getFilesFromPath method with warning.
   */
  public function testGetFilesFromPathInvalidExtensionWarning() : void {
    $method = new \ReflectionMethod(IconFinder::class, 'getFilesFromPath');
    $method->setAccessible(TRUE);
    $this->logger
      ->expects($this->once())
      ->method('warning');
    $method->invoke($this->iconFinder, self::TEST_ICONS_PATH . '/icons/empty/*.svg', '');
  }
  
  /**
   * Test the IconFinder::getFileFromUrl method with warning.
   */
  public function testGetFileFromUrlWarning() : void {
    $method = new \ReflectionMethod(IconFinder::class, 'getFileFromUrl');
    $method->setAccessible(TRUE);
    $this->logger
      ->expects($this->once())
      ->method('warning')
      ->with('Invalid icon source: @source');
    $method->invoke($this->iconFinder, 'invalid_scheme', '', '');
  }
  
  /**
   * Test the IconFinder::findFiles method with warning with invalid path.
   */
  public function testFindFilesWarning() : void {
    $method = new \ReflectionMethod(IconFinder::class, 'findFiles');
    $method->setAccessible(TRUE);
    $this->logger
      ->expects($this->once())
      ->method('warning')
      ->with('Invalid icon path in source: @source');
    $method->invoke($this->iconFinder, 'invalid_path', '*');
  }
  
  /**
   * Test the IconFinder::findFiles method with warning when no icons found.
   */
  public function testFindFilesEmptyWarning() : void {
    $method = new \ReflectionMethod(IconFinder::class, 'findFiles');
    $method->setAccessible(TRUE);
    $this->logger
      ->expects($this->once())
      ->method('warning');
    $method->invoke($this->iconFinder, self::TEST_ICONS_PATH . '/icons/empty', '*.svg');
  }
  
  /**
   * Data provider for ::testExtractIconIdFromFilename().
   *
   * @return \Generator
   *   The test cases.
   */
  public static function providerExtractIconIdFromFilename() : iterable {
    (yield 'no pattern' => [
      'foo bar baz',
      '',
      'foo bar baz',
    ]);
    (yield 'no pattern and wildcard' => [
      'foo*bar*baz',
      '',
      'foo*bar*baz',
    ]);
    (yield 'simple pattern' => [
      'foo bar baz',
      'foo {icon_id} baz',
      'bar',
    ]);
    (yield 'simple pattern and wildcard included' => [
      'foo*bar*baz',
      'foo{icon_id}baz',
      '*bar*',
    ]);
    (yield 'wrong pattern' => [
      'foo bar baz',
      'foo {ico_id} baz',
      'foo bar baz',
    ]);
    (yield 'pattern with special chars' => [
      'foO1o,-O 5 (B,ar)_b-az',
      'fo{icon_id}az',
      'O1o,-O 5 (B,ar)_b-',
    ]);
  }
  
  /**
   * Test the IconFinder::extractIconIdFromFilename method.
   *
   * @param string $filename
   *   The filename found to match against.
   * @param string $filename_pattern
   *   The path with {icon_id}.
   * @param string $expected
   *   The expected result.
   *
   * @dataProvider providerExtractIconIdFromFilename
   */
  public function testExtractIconIdFromFilename(string $filename, string $filename_pattern, string $expected) : void {
    $method = new \ReflectionMethod(IconFinder::class, 'extractIconIdFromFilename');
    $method->setAccessible(TRUE);
    $this->assertEquals($expected, $method->invoke($this->iconFinder, $filename, $filename_pattern));
  }
  
  /**
   * Test the IconFinder::extractIconIdFromFilename method with failing pattern.
   */
  public function testExtractIconIdFromFilenameWarning() : void {
    $method = new \ReflectionMethod(IconFinder::class, 'extractIconIdFromFilename');
    $method->setAccessible(TRUE);
    // PHPUnit 10 cannot expect warnings, so we have to catch them ourselves.
    // Thanks to: Drupal\Tests\Component\PhpStorage\FileStorageTest.
    $messages = [];
    set_error_handler(function (int $errno, string $errstr) use (&$messages) : void {
      $messages[] = [
        $errno,
        $errstr,
      ];
    });
    $method->invoke($this->iconFinder, 'foo*bar*baz', 'foo*{icon_id}*baz');
    restore_error_handler();
    $this->assertCount(1, $messages);
    $this->assertSame(E_WARNING, $messages[0][0]);
    $this->assertSame('preg_match(): Compilation failed: quantifier does not follow a repeatable item at offset 19', $messages[0][1]);
  }
  
  /**
   * Data provider for ::testGetFileContents().
   *
   * @return array
   *   The test cases as uri and expected valid.
   */
  public static function providerGetFileContents() : array {
    return [
      'valid local file' => [
        DRUPAL_ROOT . '/' . self::TEST_ICONS_PATH . '/icons/flat/foo.svg',
        TRUE,
      ],
      'do not exist' => [
        DRUPAL_ROOT . '/' . self::TEST_ICONS_PATH . '/icons/do/not/exist.svg',
        FALSE,
      ],
      [
        'http://foo.com/bar.png',
        FALSE,
      ],
      [
        'https://foo.com/bar.png',
        FALSE,
      ],
      [
        'ftp://foo.com/bar.png',
        FALSE,
      ],
      [
        'ssh://foo.com/bar.png',
        FALSE,
      ],
      [
        '//foo.com/bar.png',
        FALSE,
      ],
    ];
  }
  
  /**
   * Test the IconFinder::getFileContents method.
   *
   * @param string $uri
   *   The uri to test result.
   * @param bool $expected
   *   The result of the file content is expected or not.
   *
   * @dataProvider providerGetFileContents
   */
  public function testGetFileContents(string $uri, bool $expected) : void {
    if ($expected) {
      $result = $this->iconFinder
        ->getFileContents($uri);
      $this->assertEquals(file_get_contents($uri), $result);
      return;
    }
    $this->assertFalse($this->iconFinder
      ->getFileContents($uri));
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
ExpectDeprecationTrait::expectDeprecation public function Adds an expected deprecation.
ExpectDeprecationTrait::setUpErrorHandler public function Sets up the test error handler.
ExpectDeprecationTrait::tearDownErrorHandler public function Tears down the test error handler.
IconFinderTest::$fileUrlGenerator private property The file url generator instance.
IconFinderTest::$iconFinder private property The IconFinder instance.
IconFinderTest::$logger private property The logger service instance.
IconFinderTest::providerExtractIconIdFromFilename public static function Data provider for ::testExtractIconIdFromFilename().
IconFinderTest::providerGetFileContents public static function Data provider for ::testGetFileContents().
IconFinderTest::providerGetFilesFromSourcesPath public static function Data provider for ::testGetFilesFromSourcesPath().
IconFinderTest::providerGetFilesFromSourcesUrl public static function Data provider for ::testGetFilesFromSourcesUrl().
IconFinderTest::setUp protected function Overrides UnitTestCase::setUp
IconFinderTest::testExtractIconIdFromFilename public function Test the IconFinder::extractIconIdFromFilename method.
IconFinderTest::testExtractIconIdFromFilenameWarning public function Test the IconFinder::extractIconIdFromFilename method with failing pattern.
IconFinderTest::testFindFilesEmptyWarning public function Test the IconFinder::findFiles method with warning when no icons found.
IconFinderTest::testFindFilesWarning public function Test the IconFinder::findFiles method with warning with invalid path.
IconFinderTest::testGetFileContents public function Test the IconFinder::getFileContents method.
IconFinderTest::testGetFileFromUrlWarning public function Test the IconFinder::getFileFromUrl method with warning.
IconFinderTest::testGetFilesFromPathEmptyWarning public function Test the IconFinder::getFilesFromPath method with warning.
IconFinderTest::testGetFilesFromPathInvalidExtensionWarning public function Test the IconFinder::getFilesFromPath method with warning.
IconFinderTest::testGetFilesFromSourcesPath public function Test the IconFinder::getFilesFromSources method with paths.
IconFinderTest::testGetFilesFromSourcesUrl public function Test the IconFinder::getFilesFromSources method with urls.
IconFinderTest::TEST_ICONS_PATH private constant
IconFinderTest::TEST_RELATIVE_URL private constant
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
UnitTestCase::$root protected property The app root.
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::setDebugDumpHandler public static function Registers the dumper CLI handler when the DebugDump extension is enabled.
UnitTestCase::setupMockIterator protected function Set up a traversable class mock to return specific items when iterated.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.