image_to_media_swapper-2.x-dev/tests/src/Functional/SecuritySettingsFormTest.php
tests/src/Functional/SecuritySettingsFormTest.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\image_to_media_swapper\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\image_to_media_swapper\Traits\MediaFieldSetupTrait;
use Drupal\user\UserInterface;
/**
* Tests the SecuritySettingsForm functionality and validation.
*
* @group image_to_media_swapper
*/
class SecuritySettingsFormTest extends BrowserTestBase {
use MediaFieldSetupTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'image_to_media_swapper',
'media',
'file',
'image',
'user',
'system',
'options',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* Admin user for testing.
*
* @var \Drupal\user\UserInterface
*/
protected UserInterface $adminUser;
/**
* The route to the security settings form.
*
* @var string
*/
protected string $route;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
// Create media types with image_to_media_swapper settings.
$this->createMediaImageType();
$this->createMediaFileType();
// Create admin user with necessary permissions.
$this->adminUser = $this->drupalCreateUser([
'administer site configuration',
'access administration pages',
]);
$this->route = \Drupal::service('router.route_provider')->getRouteByName('image_to_media_swapper.security_settings')->getPath();
}
/**
* Tests form access and basic functionality.
*/
public function testFormAccess(): void {
// Test anonymous access is denied.
// Get the route to the settings form by route.
$this->drupalGet($this->route);
$this->assertSession()->statusCodeEquals(403);
// Test admin access is granted.
$this->drupalLogin($this->adminUser);
$this->drupalGet($this->route);
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()->pageTextContains('Image to Media Swapper Security Settings');
}
/**
* Tests form default values match install config.
*/
public function testDefaultValues(): void {
$this->drupalLogin($this->adminUser);
$this->drupalGet($this->route);
// Test default checkbox states.
$this->assertSession()->checkboxChecked('enable_remote_downloads');
$this->assertSession()->checkboxNotChecked('restrict_domains');
$this->assertSession()->checkboxChecked('block_private_ips');
$this->assertSession()->checkboxNotChecked('require_https');
$this->assertSession()->checkboxChecked('disable_batch_processing');
// Test default numeric values.
$this->assertSession()->fieldValueEquals('max_file_size', '10');
$this->assertSession()->fieldValueEquals('download_timeout', '30');
$this->assertSession()->fieldValueEquals('max_redirects', '3');
// Test default file type values.
$this->assertSession()->fieldValueEquals('allowed_extensions', 'jpg jpeg png gif webp pdf mp4 webm mp3 wav');
}
/**
* Tests domain validation functionality.
*/
public function testDomainValidation(): void {
$this->drupalLogin($this->adminUser);
$this->drupalGet($this->route);
// Verify we have access.
$this->assertSession()->statusCodeEquals(200);
$validExtensions = "jpg png gif webp nmp4";
// Test valid domains pass validation.
$validDomains = "example.com\n*.subdomain.com\nwww.test.org";
$edit = [
'allowed_extensions' => $validExtensions,
'restrict_domains' => TRUE,
'allowed_domains_list' => $validDomains,
];
$this->submitForm($edit, 'Save configuration');
// Verify configuration was saved.
$config = $this->config('image_to_media_swapper.security_settings');
$this->assertTrue($config->get('restrict_domains'));
$this->assertEquals($validDomains, $config->get('allowed_domains_list'));
// Verify form shows saved values on reload.
$this->drupalGet($this->route);
$this->assertSession()->checkboxChecked('restrict_domains');
$this->assertSession()->fieldValueEquals('allowed_domains_list', $validDomains);
// Test invalid domains fail validation.
$invalidDomains = "invalid..domain\n*.*.invalid\n-invalid.com";
$edit = [
'restrict_domains' => TRUE,
'allowed_domains_list' => $invalidDomains,
];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
$this->assertSession()->pageTextContains('Invalid domain format');
}
/**
* Tests file extension validation.
*/
public function testFileExtensionValidation(): void {
$this->drupalLogin($this->adminUser);
// Test valid extensions pass validation.
$validExtensions = "jpg png gif webp mp4";
$edit = ['allowed_extensions' => $validExtensions];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
$this->assertSession()->pageTextContains('The configuration options have been saved.');
// Test invalid extensions fail validation.
$invalidExtensions = "jpg .png gif! ../backdoor";
$edit = ['allowed_extensions' => $invalidExtensions];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
$this->assertSession()->pageTextContains('Invalid file extension');
}
/**
* Tests security boundaries for numeric fields.
*/
public function testNumericFieldBoundaries(): void {
$this->drupalLogin($this->adminUser);
// Test valid boundary values.
$edit = [
'max_file_size' => '1',
'download_timeout' => '5',
'max_redirects' => '0',
];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
$this->assertSession()->pageTextContains('The configuration options have been saved.');
// Test maximum boundary values.
$edit = [
'max_file_size' => '100',
'download_timeout' => '300',
'max_redirects' => '10',
];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
$this->assertSession()->pageTextContains('The configuration options have been saved.');
}
/**
* Tests that domain restriction requires domain list.
*/
public function testDomainRestrictionRequirement(): void {
$this->drupalLogin($this->adminUser);
// Test that enabling domain restriction without domains fails.
$edit = [
'restrict_domains' => TRUE,
'allowed_domains_list' => '',
];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
$this->assertSession()->pageTextContains('You must specify at least one allowed domain');
}
/**
* Tests configuration persistence.
*/
public function testConfigurationPersistence(): void {
$this->drupalLogin($this->adminUser);
// Save custom configuration.
$edit = [
'enable_remote_downloads' => FALSE,
'max_file_size' => '5',
'download_timeout' => '15',
'restrict_domains' => TRUE,
'allowed_domains_list' => 'example.com',
'allowed_extensions' => 'jpg png',
'block_private_ips' => FALSE,
'require_https' => TRUE,
'max_redirects' => '2',
];
$this->drupalGet($this->route);
$this->submitForm($edit, 'Save configuration');
// Verify configuration was saved.
$config = $this->config('image_to_media_swapper.security_settings');
$this->assertFalse($config->get('enable_remote_downloads'));
$this->assertEquals(5, $config->get('max_file_size'));
$this->assertEquals(['example.com'], $config->get('allowed_domains'));
$this->assertTrue($config->get('require_https'));
// Verify form shows saved values.
$this->drupalGet($this->route);
$this->assertSession()->checkboxNotChecked('enable_remote_downloads');
$this->assertSession()->checkboxChecked('restrict_domains');
$this->assertSession()->checkboxChecked('require_https');
$this->assertSession()->fieldValueEquals('max_file_size', '5');
$this->assertSession()->fieldValueEquals('allowed_domains_list', 'example.com');
}
/**
* Tests batch processing disable/enable functionality.
*/
public function testBatchProcessingToggle(): void {
$this->drupalLogin($this->adminUser);
$this->drupalGet($this->route);
// Verify the batch processing option exists and is checked by default.
// (batch processing disabled for safety).
$this->assertSession()->fieldExists('disable_batch_processing');
$this->assertSession()->checkboxChecked('disable_batch_processing');
// First, enable batch processing by unchecking the disable option.
$edit = [
'disable_batch_processing' => FALSE,
];
$this->submitForm($edit, 'Save configuration');
// Verify configuration was saved.
$config = $this->config('image_to_media_swapper.security_settings');
$this->assertFalse($config->get('disable_batch_processing'));
// Verify form shows saved value on reload.
$this->drupalGet($this->route);
$this->assertSession()->checkboxNotChecked('disable_batch_processing');
// Disable batch processing again by checking the disable option.
$edit = [
'disable_batch_processing' => TRUE,
];
$this->submitForm($edit, 'Save configuration');
// Verify configuration was saved.
$config = $this->config('image_to_media_swapper.security_settings');
$this->assertTrue($config->get('disable_batch_processing'));
// Verify form shows saved value on reload.
$this->drupalGet($this->route);
$this->assertSession()->checkboxChecked('disable_batch_processing');
}
}
