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

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

declare(strict_types=1);

namespace Drupal\Tests\utilikit\Unit;

use Drupal\Tests\UnitTestCase;
use Drupal\utilikit\Service\UtilikitRules;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;

/**
 * Tests the UtilikitRules service.
 *
 * @group utilikit
 * @coversDefaultClass \Drupal\utilikit\Service\UtilikitRules
 */
class UtilikitRulesTest extends UnitTestCase {

  /**
   * The rules service under test.
   *
   * @var \Drupal\utilikit\Service\UtilikitRules
   */
  protected UtilikitRules $rules;

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

  /**
   * Mock logger.
   *
   * @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->logger = $this->createMock(LoggerInterface::class);

    // Setup default config.
    $config = $this->createMock(ImmutableConfig::class);
    $config->expects($this->any())
      ->method('get')
      ->willReturnMap([
        ['rules_enabled', TRUE],
        ['custom_rules', []],
        ['rule_priority', 'custom_first'],
        ['rule_cache_enabled', TRUE],
      ]);

    $this->configFactory->expects($this->any())
      ->method('get')
      ->with('utilikit.settings')
      ->willReturn($config);

    $this->rules = new UtilikitRules(
      $this->configFactory,
      $this->logger
    );
  }

  /**
   * Tests getRule for valid utility classes.
   *
   * @covers ::getRule
   * @dataProvider providerValidUtilityClasses
   */
  public function testGetRuleValid(string $property, string $value, array $expected): void {
    $rule = $this->rules->getRule($property, $value);

    $this->assertIsArray($rule);
    $this->assertArrayHasKey('property', $rule);
    $this->assertArrayHasKey('value', $rule);
    $this->assertEquals($expected['property'], $rule['property']);
    $this->assertEquals($expected['value'], $rule['value']);
  }

  /**
   * Data provider for valid utility classes.
   *
   * @return array <int, mixed>
   *   The data sets used for testing providerValidUtilityClasses().
   */
  public static function providerValidUtilityClasses(): array {
    return [
      ['pd', '20', ['property' => 'padding', 'value' => '20px']],
      ['pd', '10-20', ['property' => 'padding', 'value' => '10px 20px']],
      ['pd', '10-20-30', ['property' => 'padding', 'value' => '10px 20px 30px']],
      ['pd', '10-20-30-40', ['property' => 'padding', 'value' => '10px 20px 30px 40px']],
      ['mg', '20', ['property' => 'margin', 'value' => '20px']],
      ['mg', 'auto', ['property' => 'margin', 'value' => 'auto']],
      ['text', 'center', ['property' => 'text-align', 'value' => 'center']],
      ['bg', 'primary', ['property' => 'background-color', 'value' => 'var(--color-primary)']],
      ['flex', 'row', ['property' => 'flex-direction', 'value' => 'row']],
      ['display', 'block', ['property' => 'display', 'value' => 'block']],
      ['w', '100', ['property' => 'width', 'value' => '100px']],
      ['w', '50p', ['property' => 'width', 'value' => '50%']],
      ['h', 'auto', ['property' => 'height', 'value' => 'auto']],
      ['z', '10', ['property' => 'z-index', 'value' => '10']],
    ];
  }

  /**
   * Tests getRule for invalid properties.
   *
   * @covers ::getRule
   */
  public function testGetRuleInvalid(): void {
    $rule = $this->rules->getRule('invalid', '20');
    $this->assertNull($rule);

    $rule = $this->rules->getRule('', '20');
    $this->assertNull($rule);
  }

  /**
   * Tests parseValue method.
   *
   * @covers ::parseValue
   * @dataProvider providerParseValue
   */
  public function testParseValue(string $value, string $type, string $expected): void {
    $parsed = $this->rules->parseValue($value, $type);
    $this->assertEquals($expected, $parsed);
  }

  /**
   * Data provider for parseValue tests.
   *
   * @return array<int, string>
   *   The data sets used for testing parseValue().
   */
  public static function providerParseValue(): array {
    return [
      // Numeric values.
      ['20', 'size', '20px'],
      ['0', 'size', '0'],
      ['-10', 'size', '-10px'],
      ['100', 'size', '100px'],

      // Percentage values.
      ['50p', 'size', '50%'],
      ['100p', 'size', '100%'],
      ['33p', 'size', '33%'],

      // Auto values.
      ['auto', 'size', 'auto'],
      ['AUTO', 'size', 'auto'],

      // Color values.
      ['primary', 'color', 'var(--color-primary)'],
      ['secondary', 'color', 'var(--color-secondary)'],
      ['success', 'color', 'var(--color-success)'],
      ['danger', 'color', 'var(--color-danger)'],
      ['warning', 'color', 'var(--color-warning)'],
      ['info', 'color', 'var(--color-info)'],

      // Text values.
      ['center', 'text', 'center'],
      ['left', 'text', 'left'],
      ['right', 'text', 'right'],

      // Multiple values.
      ['10-20', 'spacing', '10px 20px'],
      ['10-20-30', 'spacing', '10px 20px 30px'],
      ['10-20-30-40', 'spacing', '10px 20px 30px 40px'],
      ['0-auto', 'spacing', '0 auto'],
      ['auto-0', 'spacing', 'auto 0'],
    ];
  }

  /**
   * Tests custom rules functionality.
   *
   * @covers ::getRule
   * @covers ::applyCustomRules
   */
  public function testCustomRules(): void {
    // Setup config with custom rules.
    $config = $this->createMock(ImmutableConfig::class);
    $config->expects($this->any())
      ->method('get')
      ->willReturnMap([
        ['rules_enabled', TRUE],
        ['custom_rules', [
          'custom' => [
            'property' => 'custom-property',
            'value_template' => 'custom-{value}',
          ],
          'override-pd' => [
            'property' => 'padding',
            'value_template' => '{value}rem',
          ],
        ],
        ],
        ['rule_priority', 'custom_first'],
        ['rule_cache_enabled', FALSE],
      ]);

    $this->configFactory->expects($this->any())
      ->method('get')
      ->with('utilikit.settings')
      ->willReturn($config);

    // Recreate rules with custom config.
    $rules = new UtilikitRules(
      $this->configFactory,
      $this->logger
    );

    // Test custom rule.
    $rule = $rules->getRule('custom', 'test');
    $this->assertNotNull($rule);
    $this->assertEquals('custom-property', $rule['property']);
    $this->assertEquals('custom-test', $rule['value']);

    // Test override rule (custom_first priority).
    $rule = $rules->getRule('override-pd', '2');
    $this->assertNotNull($rule);
    $this->assertEquals('padding', $rule['property']);
    $this->assertEquals('2rem', $rule['value']);
  }

  /**
   * Tests rule priority settings.
   *
   * @covers ::getRule
   */
  public function testRulePriority(): void {
    // Test with default_first priority.
    $config = $this->createMock(ImmutableConfig::class);
    $config->expects($this->any())
      ->method('get')
      ->willReturnMap([
        ['rules_enabled', TRUE],
        ['custom_rules', [
          'pd' => [
            'property' => 'padding',
            'value_template' => '{value}rem',
          ],
        ],
        ],
        ['rule_priority', 'default_first'],
        ['rule_cache_enabled', FALSE],
      ]);

    $this->configFactory->expects($this->any())
      ->method('get')
      ->with('utilikit.settings')
      ->willReturn($config);

    $rules = new UtilikitRules(
      $this->configFactory,
      $this->logger
    );

    // Default rule should win.
    $rule = $rules->getRule('pd', '20');
    $this->assertNotNull($rule);
    $this->assertEquals('padding', $rule['property']);
    // Default rule uses px.
    $this->assertEquals('20px', $rule['value']);
  }

  /**
   * Tests getAllRules method.
   *
   * @covers ::getAllRules
   */
  public function testGetAllRules(): void {
    $allRules = $this->rules->getAllRules();

    $this->assertIsArray($allRules);
    $this->assertArrayHasKey('pd', $allRules);
    $this->assertArrayHasKey('mg', $allRules);
    $this->assertArrayHasKey('text', $allRules);
    $this->assertArrayHasKey('bg', $allRules);
    $this->assertArrayHasKey('flex', $allRules);
  }

  /**
   * Tests validateRule method.
   *
   * @covers ::validateRule
   */
  public function testValidateRule(): void {
    // Valid rules.
    $this->assertTrue($this->rules->validateRule('pd', '20'));
    $this->assertTrue($this->rules->validateRule('mg', '10-20'));
    $this->assertTrue($this->rules->validateRule('text', 'center'));
    $this->assertTrue($this->rules->validateRule('bg', 'primary'));

    // Invalid rules.
    $this->assertFalse($this->rules->validateRule('invalid', '20'));
    $this->assertFalse($this->rules->validateRule('pd', ''));
    $this->assertFalse($this->rules->validateRule('', 'value'));
  }

  /**
   * Tests special value handling.
   *
   * @covers ::getRule
   */
  public function testSpecialValues(): void {
    // Test inherit value.
    $rule = $this->rules->getRule('pd', 'inherit');
    $this->assertNotNull($rule);
    $this->assertEquals('inherit', $rule['value']);

    // Test initial value.
    $rule = $this->rules->getRule('mg', 'initial');
    $this->assertNotNull($rule);
    $this->assertEquals('initial', $rule['value']);

    // Test unset value.
    $rule = $this->rules->getRule('text', 'unset');
    $this->assertNotNull($rule);
    $this->assertEquals('unset', $rule['value']);

    // Test var() custom property.
    $rule = $this->rules->getRule('bg', 'var(--custom-color)');
    $this->assertNotNull($rule);
    $this->assertEquals('var(--custom-color)', $rule['value']);
  }

  /**
   * Tests complex spacing values.
   *
   * @covers ::parseValue
   */
  public function testComplexSpacingValues(): void {
    // Test negative values.
    $parsed = $this->rules->parseValue('-10', 'size');
    $this->assertEquals('-10px', $parsed);

    // Test mixed values.
    $parsed = $this->rules->parseValue('10-auto-20-auto', 'spacing');
    $this->assertEquals('10px auto 20px auto', $parsed);

    // Test percentage in spacing.
    $parsed = $this->rules->parseValue('50p-auto', 'spacing');
    $this->assertEquals('50% auto', $parsed);
  }

  /**
   * Tests rule caching.
   *
   * @covers ::getRule
   */
  public function testRuleCaching(): void {
    // First call should process the rule.
    $rule1 = $this->rules->getRule('pd', '20');
    $this->assertNotNull($rule1);

    // Second call should return cached result.
    $rule2 = $this->rules->getRule('pd', '20');
    $this->assertNotNull($rule2);
    $this->assertEquals($rule1, $rule2);
  }

  /**
   * Tests error handling.
   *
   * @covers ::getRule
   */
  public function testErrorHandling(): void {
    // Test with malformed custom rules.
    $config = $this->createMock(ImmutableConfig::class);
    $config->expects($this->any())
      ->method('get')
      ->willReturnMap([
        ['rules_enabled', TRUE],
        ['custom_rules', [
          'broken' => [
            // Missing required fields.
          ],
        ],
        ],
        ['rule_priority', 'custom_first'],
        ['rule_cache_enabled', FALSE],
      ]);

    $this->configFactory->expects($this->any())
      ->method('get')
      ->with('utilikit.settings')
      ->willReturn($config);

    $this->logger->expects($this->once())
      ->method('error')
      ->with($this->stringContains('Invalid custom rule'));

    $rules = new UtilikitRules(
      $this->configFactory,
      $this->logger
    );

    $rule = $rules->getRule('broken', 'test');
    $this->assertNull($rule);
  }

  /**
   * Tests rules disabled configuration.
   *
   * @covers ::getRule
   */
  public function testRulesDisabled(): void {
    $config = $this->createMock(ImmutableConfig::class);
    $config->expects($this->any())
      ->method('get')
      ->willReturnMap([
        ['rules_enabled', FALSE],
        ['custom_rules', []],
        ['rule_priority', 'custom_first'],
        ['rule_cache_enabled', TRUE],
      ]);

    $this->configFactory->expects($this->any())
      ->method('get')
      ->with('utilikit.settings')
      ->willReturn($config);

    $rules = new UtilikitRules(
      $this->configFactory,
      $this->logger
    );

    $rule = $rules->getRule('pd', '20');
    $this->assertNull($rule);
  }

}

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

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