config_preview_deploy-1.0.0-alpha3/tests/src/Kernel/ConfigExportControllerTest.php

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

declare(strict_types=1);

namespace Drupal\Tests\config_preview_deploy\Kernel;

use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Archiver\ArchiveTar;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\HttpFoundation\Request;
use Drupal\config_preview_deploy\Controller\ProductionController;
use Drupal\Tests\user\Traits\UserCreationTrait;

/**
 * Tests the config export controller endpoint.
 *
 * @group config_preview_deploy
 */
class ConfigExportControllerTest extends KernelTestBase {

  use UserCreationTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'user',
    'key',
    'file',
    'serialization',
    'config_preview_deploy',
  ];

  /**
   * The production controller.
   *
   * @var \Drupal\config_preview_deploy\Controller\ProductionController
   */
  protected ProductionController $controller;

  /**
   * The hash verification service.
   *
   * @var \Drupal\config_preview_deploy\HashVerification
   */
  protected $hashVerification;

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

    $this->installConfig(['system', 'config_preview_deploy']);
    $this->installEntitySchema('user');

    // Set up hash salt for testing.
    $this->setSetting('hash_salt', 'test_hash_salt');

    // Mock HTTP_HOST for hash verification.
    $_SERVER['HTTP_HOST'] = 'localhost';

    // Create controller instance.
    $this->controller = ProductionController::create($this->container);
    $this->hashVerification = $this->container->get('config_preview_deploy.hash_verification');

    // Set environment as production.
    $this->container->get('state')->set('config_preview_deploy.is_production', TRUE);
  }

  /**
   * Tests successful config export with valid authentication.
   */
  public function testConfigExportSuccess(): void {
    // Create some test configuration.
    $config = $this->config('system.site');
    $config->set('name', 'Test Site');
    $config->set('mail', 'test@example.com');
    $config->save();

    // Generate valid authentication.
    $timestamp = time();
    $hash = $this->hashVerification->generateVerificationHash('localhost', $timestamp);

    // Create request with valid auth headers.
    $request = Request::create('/api/config-preview-deploy/export', 'GET');
    $request->headers->set('X-Config-Deploy-Hash', $hash);
    $request->headers->set('X-Config-Deploy-Timestamp', (string) $timestamp);

    // Mock the OAuth authentication by setting current user.
    $user = $this->createUser(['accept config deployments']);
    $this->container->get('current_user')->setAccount($user);

    // Execute the export.
    $response = $this->controller->exportConfig($request);

    // Assert response.
    $this->assertEquals(200, $response->getStatusCode());
    $this->assertEquals('application/gzip', $response->headers->get('Content-Type'));
    $this->assertEquals('attachment; filename="config.tar.gz"', $response->headers->get('Content-Disposition'));

    // Verify tarball contents.
    $content = $response->getContent();
    $this->assertNotEmpty($content);

    // Extract and verify the tarball.
    $tempFile = tempnam(sys_get_temp_dir(), 'config_test');
    file_put_contents($tempFile, $content);

    $archiver = new ArchiveTar($tempFile, 'gz');
    $files = $archiver->listContent();

    // Check that our test config is in the archive.
    $fileNames = array_column($files, 'filename');
    $this->assertContains('system.site.yml', $fileNames);

    // Extract and verify content.
    $tempDir = sys_get_temp_dir() . '/config_test_' . uniqid();
    mkdir($tempDir);
    $archiver->extract($tempDir);

    $configContent = file_get_contents($tempDir . '/system.site.yml');
    $configData = Yaml::decode($configContent);

    $this->assertEquals('Test Site', $configData['name']);
    $this->assertEquals('test@example.com', $configData['mail']);

    // Clean up.
    unlink($tempFile);
    $this->removeDirectory($tempDir);
  }

  /**
   * Tests config export with missing hash authentication.
   */
  public function testConfigExportMissingHashOnly(): void {
    $request = Request::create('/api/config-preview-deploy/export', 'GET');

    $response = $this->controller->exportConfig($request);

    $this->assertEquals(401, $response->getStatusCode());
    $data = json_decode($response->getContent(), TRUE);
    $this->assertEquals('Missing authentication headers', $data['error']);
  }

  /**
   * Tests config export with partial hash authentication.
   */
  public function testConfigExportPartialHashAuth(): void {
    $request = Request::create('/api/config-preview-deploy/export', 'GET');
    $request->headers->set('X-Config-Deploy-Hash', 'some-hash');
    // Missing timestamp.
    $response = $this->controller->exportConfig($request);

    $this->assertEquals(401, $response->getStatusCode());
    $data = json_decode($response->getContent(), TRUE);
    $this->assertEquals('Missing authentication headers', $data['error']);
  }

  /**
   * Tests config export with invalid hash.
   */
  public function testConfigExportInvalidHash(): void {
    $request = Request::create('/api/config-preview-deploy/export', 'GET');
    $request->headers->set('X-Config-Deploy-Hash', 'invalid-hash');
    $request->headers->set('X-Config-Deploy-Timestamp', (string) time());

    $response = $this->controller->exportConfig($request);

    $this->assertEquals(403, $response->getStatusCode());
    $data = json_decode($response->getContent(), TRUE);
    $this->assertEquals('Invalid authentication hash', $data['error']);
  }

  /**
   * Tests config export with expired timestamp.
   */
  public function testConfigExportExpiredTimestamp(): void {
    // Generate hash with old timestamp.
    // More than 5 minutes ago.
    $timestamp = time() - 400;
    $hash = $this->hashVerification->generateVerificationHash('localhost', $timestamp);

    $request = Request::create('/api/config-preview-deploy/export', 'GET');
    $request->headers->set('X-Config-Deploy-Hash', $hash);
    $request->headers->set('X-Config-Deploy-Timestamp', (string) $timestamp);

    $response = $this->controller->exportConfig($request);

    $this->assertEquals(403, $response->getStatusCode());
    $data = json_decode($response->getContent(), TRUE);
    $this->assertEquals('Invalid authentication hash', $data['error']);
  }

  /**
   * Tests that exported config matches core's config export format.
   */
  public function testConfigExportFormatMatchesCore(): void {
    // Create various types of configuration.
    $this->config('system.site')
      ->set('name', 'Test Site')
      ->set('mail', 'test@example.com')
      ->save();

    $this->config('user.settings')
      ->set('register', 'visitors')
      ->set('verify_mail', TRUE)
      ->save();

    // Generate valid authentication.
    $timestamp = time();
    $hash = $this->hashVerification->generateVerificationHash('localhost', $timestamp);

    // Create request.
    $request = Request::create('/api/config-preview-deploy/export', 'GET');
    $request->headers->set('X-Config-Deploy-Hash', $hash);
    $request->headers->set('X-Config-Deploy-Timestamp', (string) $timestamp);

    // Mock user.
    $user = $this->createUser(['accept config deployments']);
    $this->container->get('current_user')->setAccount($user);

    // Get export.
    $response = $this->controller->exportConfig($request);
    $content = $response->getContent();

    // Extract tarball.
    $tempFile = tempnam(sys_get_temp_dir(), 'config_test');
    file_put_contents($tempFile, $content);

    $tempDir = sys_get_temp_dir() . '/config_test_' . uniqid();
    mkdir($tempDir);

    $archiver = new ArchiveTar($tempFile, 'gz');
    $archiver->extract($tempDir);

    // Verify the structure matches core export.
    $this->assertFileExists($tempDir . '/system.site.yml');
    $this->assertFileExists($tempDir . '/user.settings.yml');

    // Verify YAML format.
    $siteConfig = Yaml::decode(
      file_get_contents($tempDir . '/system.site.yml')
    );
    $this->assertEquals('Test Site', $siteConfig['name']);
    $this->assertEquals('test@example.com', $siteConfig['mail']);

    // Clean up.
    unlink($tempFile);
    $this->removeDirectory($tempDir);
  }

  /**
   * Helper to recursively remove a directory.
   */
  protected function removeDirectory(string $dir): void {
    if (!is_dir($dir)) {
      return;
    }

    $files = array_diff(scandir($dir), ['.', '..']);
    foreach ($files as $file) {
      $path = $dir . '/' . $file;
      is_dir($path) ? $this->removeDirectory($path) : unlink($path);
    }
    rmdir($dir);
  }

}

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

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