config_preview_deploy-1.0.0-alpha3/tests/src/Kernel/PreviewControllerTest.php
tests/src/Kernel/PreviewControllerTest.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\config_preview_deploy\Kernel;
use Drupal\config_preview_deploy\ConfigDiff;
use Drupal\config_preview_deploy\Controller\PreviewController;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
/**
* Tests the PreviewController.
*
* @group config_preview_deploy
*/
class PreviewControllerTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'config_preview_deploy',
'system',
'user',
'config',
];
/**
* {@inheritdoc}
*
* We disable strict config schema checking because config_ignore module's
* schema seems incomplete.
*/
protected $strictConfigSchema = FALSE;
/**
* The config diff service.
*/
protected ConfigDiff $configDiff;
/**
* The preview controller.
*/
protected PreviewController $controller;
/**
* Test user.
*/
protected User $testUser;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->installConfig(['system', 'user']);
$this->installEntitySchema('user');
// Create a test user with appropriate permissions.
$role = Role::create([
'id' => 'test_role',
'label' => 'Test Role',
]);
$role->grantPermission('deploy config from preview');
$role->save();
$this->testUser = User::create([
'name' => 'testuser',
'mail' => 'test@example.com',
'roles' => ['test_role'],
]);
$this->testUser->save();
// Set up services.
$this->configDiff = $this->container->get('config_preview_deploy.config_diff');
$this->controller = PreviewController::create($this->container);
}
/**
* Tests the changes() method with various scenarios.
*/
public function testChangesViewScenarios(): void {
// Test 1: Changes view when no base checkpoint exists.
$build = $this->controller->changes();
$this->assertArrayHasKey('#title', $build);
$this->assertEquals('Configuration Changes', $build['#title']->render());
$this->assertArrayHasKey('no_changes', $build);
$this->assertStringContainsString('No base checkpoint found', $build['no_changes']['#markup']);
// Test 2: Changes view when no changes exist (but base checkpoint exists).
$this->configDiff->createBaseCheckpoint();
$build = $this->controller->changes();
$this->assertArrayHasKey('#title', $build);
$this->assertEquals('Configuration Changes', $build['#title']->render());
$this->assertArrayHasKey('no_changes', $build);
$this->assertStringContainsString('No configuration changes detected', $build['no_changes']['#markup']);
// Test 3: Changes view when changes exist.
$this->config('system.site')
->set('name', 'Modified Site Name')
->save();
$build = $this->controller->changes();
$this->assertArrayHasKey('#title', $build);
$this->assertEquals('Configuration Changes', $build['#title']->render());
$this->assertArrayHasKey('changes_table', $build);
$this->assertArrayHasKey('#attached', $build);
$this->assertContains('core/drupal.dialog.ajax', $build['#attached']['library']);
$this->assertArrayHasKey('download', $build, 'Download button should be present');
}
/**
* Tests the diff() method with various scenarios.
*/
public function testDiffViewScenarios(): void {
// Test 1: Diff view with no base checkpoint.
$build = $this->controller->diff('system.site');
$this->assertArrayHasKey('#markup', $build);
$this->assertStringContainsString('No base checkpoint found', $build['#markup']);
// Test 2: Diff view with changes.
$this->configDiff->createBaseCheckpoint();
$this->config('system.site')
->set('name', 'Modified Site Name')
->save();
$build = $this->controller->diff('system.site');
$this->assertArrayHasKey('#title', $build);
$this->assertStringContainsString('system.site', $build['#title']->render());
$this->assertArrayHasKey('diff', $build);
$this->assertArrayHasKey('#attached', $build);
$this->assertContains('system/diff', $build['#attached']['library']);
$this->assertArrayHasKey('back', $build);
}
/**
* Tests access control scenarios for changes route.
*/
public function testAccessControlScenarios(): void {
$access = $this->container->get('config_preview_deploy.preview_environment_access');
// Test 1: Access control allowed in preview environment.
$this->container->get('current_user')->setAccount($this->testUser);
$result = $access->changesAccess($this->testUser);
$this->assertTrue($result->isAllowed(), 'Changes access should be allowed in preview environment');
// Test 2: Access forbidden on production.
putenv('DRUPAL_CONFIG_PREVIEW_DEPLOY_IS_PRODUCTION=1');
$result = $access->changesAccess($this->testUser);
$this->assertTrue($result->isForbidden(), 'Changes access should be forbidden in production environment');
// Clean up.
putenv('DRUPAL_CONFIG_PREVIEW_DEPLOY_IS_PRODUCTION');
}
/**
* Tests dashboard functionality and change count display.
*/
public function testDashboardFunctionality(): void {
// Create a base checkpoint first.
$this->configDiff->createBaseCheckpoint();
// Modify some configuration.
$this->config('system.site')
->set('name', 'Modified Site Name')
->save();
$build = $this->controller->dashboard();
$this->assertArrayHasKey('environment_info', $build);
$this->assertArrayHasKey('actions', $build);
// Check that environment info contains change count.
$envItems = $build['environment_info']['details']['#items'];
$hasChangeCount = FALSE;
foreach ($envItems as $item) {
if (strpos($item->render(), 'Pending changes:') !== FALSE) {
$hasChangeCount = TRUE;
break;
}
}
$this->assertTrue($hasChangeCount, 'Environment info should contain pending changes count');
}
/**
* Tests download diff functionality.
*/
public function testDownloadDiff(): void {
// Create a base checkpoint and make changes.
$this->configDiff->createBaseCheckpoint();
$this->config('system.site')
->set('name', 'Modified Site Name')
->save();
// Test that download functionality is available.
$response = $this->controller->downloadDiff();
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
$this->assertEquals(200, $response->getStatusCode());
$this->assertStringContainsString('text/plain', $response->headers->get('Content-Type'));
}
/**
* Tests dashboard with config_ignore filtering.
*/
public function testDashboardWithConfigIgnoreFiltering(): void {
// Check if config_ignore module exists.
$module_list = \Drupal::service('extension.list.module');
if (!$module_list->exists('config_ignore')) {
$this->markTestSkipped('Config ignore module not available in codebase');
}
// Create base checkpoint BEFORE enabling config_ignore.
$this->configDiff->createBaseCheckpoint();
// Enable config_ignore module.
$this->enableModules(['config_ignore']);
$this->installConfig(['config_ignore']);
// Configure config_ignore to ignore system.site.
$this->config('config_ignore.settings')
->set('ignored_config_entities', ['system.site'])
->save();
// Clear caches to ensure services are updated.
drupal_flush_all_caches();
// Re-fetch services after enabling module.
$this->configDiff = $this->container->get('config_preview_deploy.config_diff');
$this->controller = PreviewController::create($this->container);
// Make configuration changes.
$this->config('system.site')
->set('name', 'Ignored Site Name')
->save();
$this->config('system.performance')
->set('cache.page.max_age', 3600)
->save();
$build = $this->controller->dashboard();
// Check that environment info contains correct change count.
// Should only count system.performance (not system.site which is ignored).
$envItems = $build['environment_info']['details']['#items'];
$hasCorrectCount = FALSE;
foreach ($envItems as $item) {
$rendered = $item->render();
if (strpos($rendered, 'Pending changes:') !== FALSE) {
// Should show 2 configurations (system.performance and
// config_ignore.settings).
$this->assertStringContainsString('2 configurations', $rendered);
$hasCorrectCount = TRUE;
break;
}
}
$this->assertTrue($hasCorrectCount, 'Dashboard should show filtered change count');
}
/**
* Tests changes view with config_ignore filtering.
*/
public function testChangesViewWithConfigIgnoreFiltering(): void {
// Check if config_ignore module exists.
$module_list = \Drupal::service('extension.list.module');
if (!$module_list->exists('config_ignore')) {
$this->markTestSkipped('Config ignore module not available in codebase');
}
// Create base checkpoint BEFORE enabling config_ignore.
$this->configDiff->createBaseCheckpoint();
// Enable config_ignore module.
$this->enableModules(['config_ignore']);
$this->installConfig(['config_ignore']);
// Configure config_ignore to ignore system.site.
$this->config('config_ignore.settings')
->set('ignored_config_entities', ['system.site'])
->save();
// Clear caches.
drupal_flush_all_caches();
// Re-fetch services.
$this->configDiff = $this->container->get('config_preview_deploy.config_diff');
$this->controller = PreviewController::create($this->container);
// Make configuration changes.
$this->config('system.site')
->set('name', 'Ignored Site Name')
->save();
$this->config('system.performance')
->set('cache.page.max_age', 3600)
->save();
$build = $this->controller->changes();
// Check that changes table exists.
$this->assertArrayHasKey('changes_table', $build);
// The changes table should not include system.site (which is ignored).
$rows = $build['changes_table']['#rows'];
$foundSystemSite = FALSE;
$foundSystemPerformance = FALSE;
$foundConfigIgnore = FALSE;
foreach ($rows as $row) {
// Extract config name from the row data structure.
$configName = $row['data'][0];
if ($configName === 'system.site') {
$foundSystemSite = TRUE;
}
if ($configName === 'system.performance') {
$foundSystemPerformance = TRUE;
}
if ($configName === 'config_ignore.settings') {
$foundConfigIgnore = TRUE;
}
}
$this->assertFalse($foundSystemSite, 'Ignored config system.site should not appear in changes');
$this->assertTrue($foundSystemPerformance, 'Non-ignored config system.performance should appear in changes');
$this->assertTrue($foundConfigIgnore, 'Config ignore settings should appear in changes');
}
/**
* Tests diff download with config_ignore filtering.
*/
public function testDownloadDiffWithConfigIgnoreFiltering(): void {
// Check if config_ignore module exists.
$module_list = \Drupal::service('extension.list.module');
if (!$module_list->exists('config_ignore')) {
$this->markTestSkipped('Config ignore module not available in codebase');
}
// Create base checkpoint BEFORE enabling config_ignore.
$this->configDiff->createBaseCheckpoint();
// Enable config_ignore module.
$this->enableModules(['config_ignore']);
$this->installConfig(['config_ignore']);
// Configure config_ignore to ignore system.site:name but not slogan.
$this->config('config_ignore.settings')
->set('ignored_config_entities', ['system.site:name'])
->save();
// Clear caches.
drupal_flush_all_caches();
// Re-fetch services.
$this->configDiff = $this->container->get('config_preview_deploy.config_diff');
$this->controller = PreviewController::create($this->container);
// Make configuration changes.
$this->config('system.site')
->set('name', 'Ignored Site Name')
->set('slogan', 'Not Ignored Slogan')
->save();
// Download diff.
$response = $this->controller->downloadDiff();
$content = $response->getContent();
// Should NOT contain ignored change.
$this->assertStringNotContainsString('Ignored Site Name', $content);
// Should contain non-ignored change.
$this->assertStringContainsString('Not Ignored Slogan', $content);
}
}
