utilikit-1.0.0/tests/src/Unit/UtilikitCssGeneratorTest.php

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

declare(strict_types=1);

namespace Drupal\Tests\utilikit\Unit;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Tests\UnitTestCase;
use Drupal\utilikit\Service\UtilikitConstants;
use Drupal\utilikit\Service\UtilikitContentScanner;
use Drupal\utilikit\Service\UtilikitCssGenerator;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;

/**
 * Tests for the UtilikitCssGenerator service.
 *
 * @coversDefaultClass \Drupal\utilikit\Service\UtilikitCssGenerator
 *
 * Aligned with the current UtilikitCssGenerator implementation.
 */
final class UtilikitCssGeneratorTest extends UnitTestCase {

  /**
   * The CSS generator under test.
   *
   * @var \Drupal\utilikit\Service\UtilikitCssGenerator
   */
  protected UtilikitCssGenerator $cssGenerator;

  /**
   * The config factory mock.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected ConfigFactoryInterface&MockObject $configFactory;

  /**
   * The settings config mock.
   *
   * @var \Drupal\Core\Config\ImmutableConfig|\PHPUnit\Framework\MockObject\MockObject
   */
  protected ImmutableConfig&MockObject $settingsConfig;

  /**
   * The cache backend mock.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected CacheBackendInterface&MockObject $cache;

  /**
   * The content scanner mock.
   *
   * @var \Drupal\utilikit\Service\UtilikitContentScanner|\PHPUnit\Framework\MockObject\MockObject
   */
  protected UtilikitContentScanner&MockObject $contentScanner;

  /**
   * The logger mock.
   *
   * @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject
   */
  protected LoggerInterface&MockObject $logger;

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

    $this->configFactory = $this->createMock(ConfigFactoryInterface::class);
    $this->settingsConfig = $this->createMock(ImmutableConfig::class);
    $this->cache = $this->createMock(CacheBackendInterface::class);
    $this->contentScanner = $this->createMock(UtilikitContentScanner::class);
    $this->logger = $this->createMock(LoggerInterface::class);

    // UtilikitCssGenerator expects to read utilikit.settings for active
    // breakpoints.
    $this->configFactory
      ->method('get')
      ->with('utilikit.settings')
      ->willReturn($this->settingsConfig);

    $this->settingsConfig
      ->method('get')
      ->with('active_breakpoints')
      ->willReturn([
        'sm' => TRUE,
        'md' => TRUE,
        'lg' => TRUE,
        'xl' => TRUE,
        'xxl' => TRUE,
      ]);

    $this->cssGenerator = new UtilikitCssGenerator(
      $this->configFactory,
      $this->cache,
      $this->contentScanner,
      $this->logger,
    );
  }

  /**
   * Tests generateCssFromClasses filters invalid and duplicate values.
   *
   * @covers ::generateCssFromClasses
   */
  public function testGenerateCssFromClassesFiltersInvalidAndDuplicateValues(): void {
    $classes = [
      'uk-m--10',
      '',
      NULL,
      'not-utilikit',
      'uk-m--10',
    ];

    $this->contentScanner
      ->method('isValidUtilityClass')
      ->willReturnCallback(static function (string $class): bool {
        return substr($class, 0, 3) === 'uk-';
      });

    $this->cache
      ->method('get')
      ->willReturn(FALSE);

    $this->cache
      ->expects($this->once())
      ->method('set')
      ->with(
        $this->isType('string'),
        $this->isType('string'),
        $this->anything(),
        $this->callback(static function (array $tags): bool {
          return in_array(UtilikitConstants::CACHE_TAG_CSS, $tags, TRUE);
        })
      );

    $css = $this->cssGenerator->generateCssFromClasses($classes);

    $this->assertIsString($css);
    $this->assertNotSame('', $css);
    // Valid utility class should appear as a selector.
    $this->assertStringContainsString('.uk-m--10', $css);
    // Non-utilikit class should not become a selector.
    $this->assertStringNotContainsString('not-utilikit', $css);
  }

  /**
   * Tests generateCssFromClasses uses cache when available.
   *
   * @covers ::generateCssFromClasses
   */
  public function testGenerateCssFromClassesUsesCacheWhenAvailable(): void {
    $classes = ['uk-m--10'];
    sort($classes);
    $cid = 'utilikit:css:' . md5(serialize($classes));

    $cacheHit = (object) ['data' => '/* cached css */'];

    $this->contentScanner
      ->method('isValidUtilityClass')
      ->willReturn(TRUE);

    $this->cache
      ->expects($this->exactly(2))
      ->method('get')
      ->with($cid)
      ->willReturnOnConsecutiveCalls(FALSE, $cacheHit);

    $this->cache
      ->expects($this->once())
      ->method('set')
      ->with(
        $cid,
        $this->isType('string'),
        $this->anything(),
        $this->callback(static function (array $tags): bool {
          return in_array(UtilikitConstants::CACHE_TAG_CSS, $tags, TRUE);
        })
      );

    $first = $this->cssGenerator->generateCssFromClasses($classes);
    $this->assertIsString($first);
    $this->assertNotSame('', $first);

    $second = $this->cssGenerator->generateCssFromClasses($classes);
    $this->assertSame('/* cached css */', $second);
  }

  /**
   * Tests generateCssFromClasses throws when class count exceeds limit.
   *
   * @covers ::generateCssFromClasses
   */
  public function testGenerateCssFromClassesThrowsWhenClassCountExceedsLimit(): void {
    $classes = [];
    $limit = UtilikitConstants::MAX_CLASSES_WARNING_THRESHOLD + 1;

    for ($i = 0; $i < $limit; $i++) {
      $classes[] = 'uk-m--' . $i;
    }

    $this->contentScanner
      ->method('isValidUtilityClass')
      ->willReturn(TRUE);

    $this->logger
      ->expects($this->once())
      ->method('error')
      ->with(
        $this->stringContains('Class count exceeds hard limit'),
        $this->arrayHasKey('@count')
      );

    $this->expectException(\RuntimeException::class);

    $this->cssGenerator->generateCssFromClasses($classes);
  }

}

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

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