<?php namespace Drupal\Tests\fillpdf\Functional; use Drupal\Core\Url; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\fillpdf\Traits\TestFillPdfTrait; /** * @coversDefaultClass \Drupal\fillpdf\Form\FillPdfSettingsForm * @group fillpdf */ class FillPdfSettingsFormTest extends BrowserTestBase { /** * {@inheritdoc} */ public static $modules = ['fillpdf_test', 'file_test']; use TestFillPdfTrait; /** * {@inheritdoc} */ protected $defaultTheme = 'stark'; /** * {@inheritdoc} */ protected function setUp(): void { parent::setUp(); $this->initializeUser(); } /** * Tests the scheme settings with the site default. */ public function testSettingsFormDefaults() { // FillPDF is not yet configured. // Verify the settings form is however initialized with the site default // scheme, which at this point should be 'public', and with the // 'fillpdf_service' backend. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->pageTextContains('Public files (site default)'); $this->assertSession()->checkboxChecked('edit-template-scheme-public'); $this->assertSession()->checkboxChecked('edit-backend-fillpdf-service'); // Now set the site default to 'private'. $config = $this->container->get('config.factory') ->getEditable('system.file') ->set('default_scheme', 'private'); $config->save(); // The form should now be initialized with the new site default scheme, // while the backend should remain unchanged. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->pageTextContains('Private files (site default)'); $this->assertSession()->checkboxChecked('edit-template-scheme-private'); $this->assertSession()->checkboxChecked('edit-backend-fillpdf-service'); } /** * Tests the scheme settings with the 'dummy_remote' stream wrapper. */ public function testTemplateSchemeDummyRemote() { // FillPDF is not yet configured. // Verify the 'dummy_remote' stream wrapper is present on the form. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->elementExists('css', '#edit-template-scheme-dummy-remote'); // Programmatically configure 'dummy_remote' as new default scheme. $this->configureFillPdf(['template_scheme' => 'dummy_remote']); // Now uninstall the file_test module with the dummy stream wrappers. $this->assertTrue(\Drupal::service('module_installer')->uninstall(['file_test']), "Module 'file_test' has been uninstalled."); $this->assertFalse(\Drupal::moduleHandler()->moduleExists('file_test'), "Module 'file_test' is no longer present."); // Reload the page and verify that 'dummy_remote' is gone. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->elementNotExists('css', '#edit-template-scheme-dummy-remote'); $this->assertSession()->pageTextContains('Your previously used file storage dummy_remote:// is no longer available'); } /** * Tests the scheme settings with the 'private' stream wrapper. */ public function testTemplateSchemePrivate() { // FillPDF is not yet configured. // Configure FillPDF with the 'test' backend and the site default scheme, // which at this point is 'public'. $this->configureFillPdf(); // Now on the settings form, switch to the 'private' scheme. $this->drupalPostForm(Url::fromRoute('fillpdf.settings'), ['template_scheme' => 'private'], 'Save configuration'); // Verify the new values have been submitted *and* successfully saved. $this->assertSession()->pageTextContains('The configuration options have been saved.'); $this->assertSession()->fieldValueEquals('template_scheme', 'private'); $this->assertEqual($this->config('fillpdf.settings')->get('template_scheme'), 'private'); // Now remove the private path from settings.php and rebuild the container. $this->writeSettings([ 'settings' => [ 'file_private_path' => (object) [ 'value' => '', 'required' => TRUE, ], ], ]); $this->rebuildContainer(); // Reload the page to verify the 'private' scheme is gone. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->elementNotExists('css', '#edit-template-scheme-private'); $this->assertSession()->pageTextContains('Your previously used file storage private:// is no longer available'); // Verify that the site default scheme, which at this point is 'public', is // preselected but not yet saved in config. $this->assertSession()->fieldValueEquals('template_scheme', $this->config('system.file')->get('default_scheme')); $this->assertEqual($this->config('fillpdf.settings')->get('template_scheme'), 'private'); } /** * Tests the scheme settings with the 'public' stream wrapper. */ public function testTemplateSchemePublic() { // FillPDF is not yet configured. // Configure FillPDF with the 'test' backend and the site default scheme, // which at this point is 'public'. $this->configureFillPdf(); // On the settings page, verify the 'public' scheme is set both in the form // and in config. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->fieldValueEquals('template_scheme', 'public'); $this->assertEqual($this->config('fillpdf.settings')->get('template_scheme'), 'public'); // Verify the subdirectory doesn't exist yet. $directory = 'public://fillpdf'; $this->assertFalse(is_dir($directory), 'Directory does not exist prior to testing.'); // Now on the settings form, save the unchanged configuration to create the // subdirectory. Verify it does exist now and is writeable. $this->drupalPostForm(NULL, [], 'Save configuration'); $this->assertSession()->pageTextContains('The configuration options have been saved.'); $this->assertTrue(is_dir($directory), 'Directory exists now.'); $this->assertTrue(\Drupal::service('file_system')->prepareDirectory($directory), 'Directory is writeable.'); // Now delete the directory and replace it with a file with the same name, // so the directory can't be recreated. Try saving again and verify an error // is set. /** @var \Drupal\Core\File\FileSystemInterface $file_system */ $file_system = $this->container->get('file_system'); $file_system->rmdir($directory); \Drupal::service('file_system')->copy('public://.htaccess', $directory); $this->drupalPostForm(NULL, [], 'Save configuration'); $this->assertSession()->pageTextNotContains('The configuration options have been saved.'); $this->assertSession()->pageTextContains('Could not automatically create the subdirectory'); } /** * Tests the backend settings with the 'fillpdf_service' backend. */ public function testBackendFillPdfService() { // FillPDF is not yet configured. The settings form is however initialized // with the 'fillpdf_service' backend. Save that configuration. $this->drupalPostForm(Url::fromRoute('fillpdf.settings'), NULL, 'Save configuration'); // There's currently no validation, so the 'backend' setting should be // both submitted and stored. $this->assertSession()->pageTextContains('The configuration options have been saved.'); $this->assertSession()->fieldValueEquals('backend', 'fillpdf_service'); $this->assertEqual($this->config('fillpdf.settings')->get('backend'), 'fillpdf_service'); // Now add an API key and save again. $this->drupalPostForm(NULL, ['fillpdf_service_api_key' => 'Invalid, just playing around.'], 'Save configuration'); // There's currently no validation, so the obviously invalid // 'fillpdf_service_api_key' should be both submitted and stored. $this->assertSession()->pageTextContains('The configuration options have been saved.'); $this->assertSession()->fieldValueEquals('fillpdf_service_api_key', 'Invalid, just playing around.'); $this->assertEqual($this->config('fillpdf.settings')->get('fillpdf_service_api_key'), 'Invalid, just playing around.'); } /** * Tests the backend settings with the 'pdftk' backend. */ public function testBackendPdftk() { // FillPDF is not yet configured. // Try configuring FillPDF with the 'pdftk' backend, yet an invalid path. $edit = [ 'template_scheme' => 'private', 'backend' => 'pdftk', 'pdftk_path' => 'xyz', ]; $this->drupalPostForm(Url::fromRoute('fillpdf.settings'), $edit, 'Save configuration'); // The validation handler kicked in. $this->assertSession()->pageTextNotContains('The configuration options have been saved.'); $this->assertSession()->pageTextContains('The path you have entered for pdftk is invalid. Please enter a valid path.'); // Verify the new values have been submitted, but *not* saved. foreach ($edit as $field => $value) { $this->assertSession()->fieldValueEquals($field, $value); $this->assertEqual($this->config('fillpdf.settings')->get($field), NULL); } } /** * Tests the backend settings with the 'test' backend. */ public function testBackendTest() { // FillPDF is not yet configured. // Go to the settings page and verify the autodetected 'test' backend is // present only once and with the form-altered label. $this->drupalGet(Url::fromRoute('fillpdf.settings')); $this->assertSession()->pageTextContainsOnce('plugin for testing'); $this->assertSession()->pageTextContains('Form-altered pass-through plugin for testing'); // Try configuring FillPDF with the 'test' backend, yet with invalid values // for the form-altered 'example_setting' and the unrelated // 'fillpdf_service_api_key'. $edit = [ 'template_scheme' => 'private', 'backend' => 'test', 'example_setting' => 'x', 'fillpdf_service_api_key' => 'Invalid, just playing around.', ]; $this->drupalPostForm(NULL, $edit, 'Save configuration'); // The 'test' radio option is present and working. $this->assertSession()->pageTextNotContains('An illegal choice has been detected.'); // However, our custom validation handler kicked in. $this->assertSession()->pageTextNotContains('The configuration options have been saved.'); $this->assertSession()->pageTextContains('Not a valid value.'); // Therefore, the new values should be submitted, but *not* saved. foreach ($edit as $field => $value) { $this->assertSession()->fieldValueEquals($field, $value); $config_name = $field === 'example_setting' ? 'fillpdf_test.settings' : 'fillpdf.settings'; $this->assertEqual($this->config($config_name)->get($field), NULL); } // Try again with a valid value. $edit['example_setting'] = 'xyz'; $this->drupalPostForm(NULL, $edit, 'Save configuration'); // This time, our custom validation handler passes. $this->assertSession()->pageTextNotContains('Not a valid value.'); $this->assertSession()->pageTextContains('The configuration options have been saved.'); // So the new values should be submitted *and* saved this time, except for // the unrelated 'fillpdf_service_api_key' which should be dismissed. $expected = ['fillpdf_service_api_key' => NULL] + $edit; foreach ($expected as $field => $value) { $this->assertSession()->fieldValueEquals($field, $value); $config_name = $field === 'example_setting' ? 'fillpdf_test.settings' : 'fillpdf.settings'; $this->assertEqual($this->config($config_name)->get($field), $value); } } }