utilikit-1.0.0/tests/src/Kernel/UtilikitInstallTest.php

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

declare(strict_types=1);

namespace Drupal\Tests\utilikit\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\Core\File\FileSystemInterface;
use Drupal\utilikit\Service\UtilikitConstants;

/**
 * Tests the UtiliKit installation process.
 *
 * @group utilikit
 */
class UtilikitInstallTest extends KernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'user',
    'field',
    'file',
    'utilikit',
  ];

  /**
   * The file system service.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The state service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

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

    // Install config schema.
    $this->installConfig(['utilikit']);

    // Get services.
    $this->fileSystem = $this->container->get('file_system');
    $this->configFactory = $this->container->get('config.factory');
    $this->state = $this->container->get('state');
  }

  /**
   * Tests hook_install creates directory and sets defaults.
   */
  public function testInstallHook() {
    // Get config before installation.
    $config = $this->configFactory->get('utilikit.settings');

    // Run the install hook.
    module_load_include('install', 'utilikit');
    utilikit_install();

    // Reload config.
    $config = $this->configFactory->get('utilikit.settings');

    // Test directory creation.
    $directory = UtilikitConstants::CSS_DIRECTORY;
    $this->assertTrue(
      is_dir($directory),
      'CSS directory should be created'
    );

    // Test default configuration values.
    $this->assertEquals('inline', $config->get('rendering_mode'));
    $this->assertTrue($config->get('scope_global'));
    $this->assertFalse($config->get('disable_admin'));
    $this->assertFalse($config->get('scope_content_types'));
    $this->assertEquals([], $config->get('enabled_content_types'));

    // Test performance settings.
    $this->assertTrue($config->get('enable_transitions'));
    $this->assertEquals(50, $config->get('debounce'));
    $this->assertTrue($config->get('optimize_css'));
    $this->assertEquals(UtilikitConstants::DEFAULT_BREAKPOINTS, $config->get('active_breakpoints'));

    // Test developer settings.
    $this->assertFalse($config->get('dev_mode'));
    $this->assertFalse($config->get('admin_preview'));
    $this->assertFalse($config->get('show_page_errors'));
    $this->assertEquals('warnings', $config->get('log_level'));

    // Test update triggers.
    $this->assertFalse($config->get('update_on_node_save'));
    $this->assertFalse($config->get('update_on_block_save'));
    $this->assertFalse($config->get('update_on_paragraph_save'));

    // Test advanced settings.
    $this->assertEquals(UtilikitConstants::BATCH_SIZE_DEFAULT, $config->get('batch_size'));
    $this->assertEquals(UtilikitConstants::MAX_CLASSES_PER_REQUEST, $config->get('max_classes_per_request'));
    $this->assertEquals(UtilikitConstants::RATE_LIMIT_REQUESTS_PER_MINUTE, $config->get('rate_limit_requests'));
    $this->assertEquals(3600, $config->get('css_cache_ttl'));

    // Test file management.
    $this->assertEquals(UtilikitConstants::CSS_DIRECTORY, $config->get('css_directory'));
    $this->assertEquals(UtilikitConstants::CSS_FILENAME, $config->get('css_filename'));

    // Test migration flags.
    $this->assertFalse($config->get('legacy_mode'));
    $this->assertTrue($config->get('migration_complete'));

    // Test experimental features.
    $experimental = $config->get('experimental_features');
    $this->assertFalse($experimental['grid_auto_generation']);
    $this->assertFalse($experimental['advanced_selectors']);
    $this->assertFalse($experimental['css_variables']);
    $this->assertFalse($experimental['media_query_optimization']);
  }

  /**
   * Tests directory creation failure handling.
   */
  public function testInstallDirectoryFailure() {
    // Make directory creation fail by creating a file with the same name.
    $directory = UtilikitConstants::CSS_DIRECTORY;
    $parentDir = dirname($directory);

    // Ensure parent exists.
    $this->fileSystem->prepareDirectory($parentDir, FileSystemInterface::CREATE_DIRECTORY);

    // Create a file where the directory should be.
    $blockingFile = $directory;
    file_put_contents($blockingFile, 'blocking');

    // Capture messages.
    $messenger = \Drupal::messenger();

    // Run install.
    module_load_include('install', 'utilikit');
    utilikit_install();

    // Check for warning message.
    $messages = $messenger->messagesByType('warning');
    $found = FALSE;
    foreach ($messages as $message) {
      if (strpos((string) $message, 'Could not create UtiliKit CSS directory') !== FALSE) {
        $found = TRUE;
        break;
      }
    }
    $this->assertTrue($found, 'Warning message should be displayed when directory creation fails');

    // Clean up.
    unlink($blockingFile);
  }

  /**
   * Tests hook_uninstall removes all data.
   */
  public function testUninstallHook() {
    // First install to set everything up.
    module_load_include('install', 'utilikit');
    utilikit_install();

    // Add some state data.
    $this->state->set(UtilikitConstants::STATE_KNOWN_CLASSES, ['uk-pd--20', 'uk-mg--10']);
    $this->state->set(UtilikitConstants::STATE_GENERATED_CSS, '.uk-pd--20 { padding: 20px; }');
    $this->state->set(UtilikitConstants::STATE_CSS_TIMESTAMP, time());
    $this->state->set(UtilikitConstants::STATE_LAST_CLEANUP, time());
    $this->state->set('utilikit.initialized', TRUE);

    // Add rate limit data.
    $this->state->set('utilikit_rate_limit:127.0.0.1', 5);
    $this->state->set('utilikit_rate_limit:127.0.0.1_reset', time() + 60);

    // Create CSS file.
    $cssFile = UtilikitConstants::CSS_DIRECTORY . '/' . UtilikitConstants::CSS_FILENAME;
    $this->fileSystem->saveData('test css', $cssFile);

    // Verify everything exists before uninstall.
    $this->assertNotNull($this->state->get(UtilikitConstants::STATE_KNOWN_CLASSES));
    $this->assertTrue(file_exists($cssFile));

    // Run uninstall.
    utilikit_uninstall();

    // Verify config deleted.
    $config = $this->configFactory->get('utilikit.settings');
    $this->assertNull($config->get('rendering_mode'));

    // Verify state deleted.
    $this->assertNull($this->state->get(UtilikitConstants::STATE_KNOWN_CLASSES));
    $this->assertNull($this->state->get(UtilikitConstants::STATE_GENERATED_CSS));
    $this->assertNull($this->state->get(UtilikitConstants::STATE_CSS_TIMESTAMP));
    $this->assertNull($this->state->get(UtilikitConstants::STATE_LAST_CLEANUP));
    $this->assertNull($this->state->get('utilikit.initialized'));

    // Verify rate limit data deleted.
    $this->assertNull($this->state->get('utilikit_rate_limit:127.0.0.1'));
    $this->assertNull($this->state->get('utilikit_rate_limit:127.0.0.1_reset'));

    // Verify CSS file and directory deleted.
    $this->assertFalse(file_exists($cssFile));
    $this->assertFalse(is_dir(UtilikitConstants::CSS_DIRECTORY));
  }

  /**
   * Tests hook_requirements at runtime.
   */
  public function testRequirementsRuntime() {
    // Install module first.
    module_load_include('install', 'utilikit');
    utilikit_install();

    // Test with everything working.
    $requirements = utilikit_requirements('runtime');

    // Check directory requirement.
    $this->assertArrayHasKey('utilikit_directory', $requirements);
    $this->assertEquals(REQUIREMENT_OK, $requirements['utilikit_directory']['severity']);

    // Test with static mode and missing CSS file.
    $config = $this->configFactory->getEditable('utilikit.settings');
    $config->set('rendering_mode', 'static')->save();

    $requirements = utilikit_requirements('runtime');
    $this->assertArrayHasKey('utilikit_static_css', $requirements);
    $this->assertEquals(REQUIREMENT_WARNING, $requirements['utilikit_static_css']['severity']);

    // Test with many classes (performance warning)
    $manyClasses = [];
    for ($i = 0; $i < UtilikitConstants::MAX_CLASSES_WARNING_THRESHOLD + 100; $i++) {
      $manyClasses[] = 'uk-pd--' . $i;
    }
    $this->state->set(UtilikitConstants::STATE_KNOWN_CLASSES, $manyClasses);

    $requirements = utilikit_requirements('runtime');
    $this->assertArrayHasKey('utilikit_performance', $requirements);
    $this->assertEquals(REQUIREMENT_WARNING, $requirements['utilikit_performance']['severity']);
  }

  /**
   * Tests requirements with non-writable directory.
   */
  public function testRequirementsNonWritableDirectory() {
    // This test is tricky in kernel tests as we can't easily make directories
    // non-writable
    // We'll test the logic by mocking the conditions.
    // Create a mock file system service.
    $mockFileSystem = $this->createMock(FileSystemInterface::class);

    // Make realpath return a valid path but is_writable check will fail.
    $mockFileSystem->method('realpath')
      ->willReturn('/tmp/test-dir');

    // Replace the service temporarily.
    $this->container->set('file_system', $mockFileSystem);

    // We'll need to mock is_writable in the install file
    // For now, we'll skip this specific test scenario.
    $this->markTestIncomplete('Testing non-writable directories requires additional mocking infrastructure');
  }

  /**
   * Tests installation with existing data (upgrade scenario).
   */
  public function testInstallWithExistingData() {
    // Simulate existing data from a previous installation.
    $existingClasses = ['uk-pd--20', 'uk-mg--10'];
    $this->state->set(UtilikitConstants::STATE_KNOWN_CLASSES, $existingClasses);

    // Run install.
    module_load_include('install', 'utilikit');
    utilikit_install();

    // Verify existing data is preserved.
    $classes = $this->state->get(UtilikitConstants::STATE_KNOWN_CLASSES);
    $this->assertEquals($existingClasses, $classes);

    // Verify new config is set.
    $config = $this->configFactory->get('utilikit.settings');
    $this->assertEquals('inline', $config->get('rendering_mode'));
  }

  /**
   * Tests requirements during install phase.
   */
  public function testRequirementsInstallPhase() {
    $requirements = utilikit_requirements('install');

    // During install phase, we typically don't return requirements
    // unless there are specific system requirements to check.
    $this->assertIsArray($requirements);
  }

  /**
   * Tests complete install/uninstall cycle.
   */
  public function testCompleteInstallUninstallCycle() {
    // Install.
    module_load_include('install', 'utilikit');
    utilikit_install();

    // Use the module - add some data.
    $this->state->set(UtilikitConstants::STATE_KNOWN_CLASSES, ['uk-pd--20']);
    $cssFile = UtilikitConstants::CSS_DIRECTORY . '/' . UtilikitConstants::CSS_FILENAME;
    $this->fileSystem->saveData('.uk-pd--20 { padding: 20px; }', $cssFile);

    // Verify it's working.
    $this->assertTrue(file_exists($cssFile));

    // Uninstall.
    utilikit_uninstall();

    // Verify complete cleanup.
    $this->assertFalse(file_exists($cssFile));
    $this->assertNull($this->state->get(UtilikitConstants::STATE_KNOWN_CLASSES));

    // Reinstall.
    utilikit_install();

    // Verify fresh installation.
    $this->assertTrue(is_dir(UtilikitConstants::CSS_DIRECTORY));
    $this->assertEquals([], $this->state->get(UtilikitConstants::STATE_KNOWN_CLASSES, []));
  }

  /**
   * Tests configuration validation after install.
   */
  public function testConfigurationValidation() {
    // Install.
    module_load_include('install', 'utilikit');
    utilikit_install();

    $config = $this->configFactory->get('utilikit.settings');

    // Validate all required keys exist.
    $requiredKeys = [
      'rendering_mode', 'scope_global', 'disable_admin', 'scope_content_types',
      'enable_transitions', 'debounce', 'optimize_css', 'active_breakpoints',
      'dev_mode', 'admin_preview', 'show_page_errors', 'log_level',
      'update_on_node_save', 'update_on_block_save', 'update_on_paragraph_save',
      'batch_size', 'max_classes_per_request', 'rate_limit_requests',
      'css_cache_ttl', 'css_directory', 'css_filename',
      'legacy_mode', 'migration_complete', 'experimental_features',
    ];

    foreach ($requiredKeys as $key) {
      $this->assertNotNull(
        $config->get($key),
        "Configuration key '$key' should be set after installation"
      );
    }
  }

}

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

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