From 33d8cec308e0276289cdf70c9e75e6121975a37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Sim=C3=B5es?= Date: Mon, 27 Oct 2025 09:28:33 +0100 Subject: [PATCH 1/4] More resilient config form transformation --- src/Form/LanguageTagSettingsForm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Form/LanguageTagSettingsForm.php b/src/Form/LanguageTagSettingsForm.php index 2659376..ebab2c2 100644 --- a/src/Form/LanguageTagSettingsForm.php +++ b/src/Form/LanguageTagSettingsForm.php @@ -122,7 +122,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { * @return array * The value to be stored in config. */ - public static function multiLineStringToArray(string $value): array { + public static function multiLineStringToArray(string $value = ""): array { return array_filter(array_map('trim', explode("\n", trim($value)))); } @@ -135,7 +135,7 @@ public static function multiLineStringToArray(string $value): array { * @return string * The value of the form element. */ - public static function arrayToMultiLineString(array $value): string { + public static function arrayToMultiLineString(array $value = []): string { return implode("\n", $value); } From 8fac740fff9907b2c20c618589f21db5d360e4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Sim=C3=B5es?= Date: Mon, 27 Oct 2025 15:44:26 +0100 Subject: [PATCH 2/4] Initial test coverage for settings form --- tests/src/Functional/SettingsFormTest.php | 127 ++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 tests/src/Functional/SettingsFormTest.php diff --git a/tests/src/Functional/SettingsFormTest.php b/tests/src/Functional/SettingsFormTest.php new file mode 100644 index 0000000..c10d633 --- /dev/null +++ b/tests/src/Functional/SettingsFormTest.php @@ -0,0 +1,127 @@ +drupalCreateUser(['access content']); + $this->drupalLogin($account); + + $this->drupalGet(self::FORM_PATH); + $this->assertSession() + ->statusCodeEquals(403); + } + + /** + * Tests the settings form as a privileged user. + */ + public function testSettingsForm() { + $account = $this->drupalCreateUser([self::PERMISSION]); + $this->drupalLogin($account); + + // Test the default configuration. + $default_config = $this->config(self::CONFIG_KEY); + + $lang_primary_group_label = $default_config->get('lang_primary_group_label'); + $this->assertEquals('EU official languages', $lang_primary_group_label); + + $lang_primary_list = $default_config->get('lang_primary_list'); + $this->assertContains('el|Greek', $lang_primary_list); + + $lang_secondary_group_label = $default_config->get('lang_secondary_group_label'); + $this->assertEquals('Other languages', $lang_secondary_group_label); + + $lang_secondary_list = $default_config->get('lang_secondary_list'); + $this->assertContains('tr|Turkish', $lang_secondary_list); + + // Test access to the settings form. + $this->drupalGet(self::FORM_PATH); + $this->assertSession() + ->statusCodeEquals(200); + + // Test default values on the page. + $this->assertSession() + ->pageTextMatchesCount(2, '/Greek/'); + $this->assertSession() + ->pageTextMatchesCount(1, '/Turkish/'); + + // Test form submission. + $submission_data = [ + 'lang_primary_group_label' => 'European', + 'lang_primary_list' => implode("\n", [ + 'pt-PT|Portuguese (Portugal)', + 'es-ES|Spanish (Spain)', + ]), + 'lang_secondary_group_label' => 'South American', + 'lang_secondary_list' => implode("\n", [ + 'pt-BR|Portuguese (Brazil)', + 'es-AR|Spanish (Argentina)', + ]), + ]; + $this->submitForm($submission_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains('The configuration options have been saved.'); + + // Test the configuration has been updated. + $new_config = $this->config(self::CONFIG_KEY); + + $lang_primary_group_label = $new_config->get('lang_primary_group_label'); + $this->assertEquals('European', $lang_primary_group_label); + + $lang_primary_list = $new_config->get('lang_primary_list'); + $this->assertContains('pt-PT|Portuguese (Portugal)', $lang_primary_list); + $this->assertNotContains('el|Greek', $lang_primary_list); + + $lang_secondary_group_label = $new_config->get('lang_secondary_group_label'); + $this->assertEquals('South American', $lang_secondary_group_label); + + $lang_secondary_list = $new_config->get('lang_secondary_list'); + $this->assertContains('pt-BR|Portuguese (Brazil)', $lang_secondary_list); + $this->assertNotContains('tr|Turkish', $lang_secondary_list); + + // Test the form loads normally. + $this->drupalGet(self::FORM_PATH); + $this->assertSession() + ->statusCodeEquals(200); + + // Test new values on the page. + $this->assertSession() + ->pageTextMatchesCount(2, '/Portuguese/'); + $this->assertSession() + ->pageTextMatchesCount(2, '/Spanish/'); + + } + +} From a3b753396a3bb69c1bcfdfc6b8c2f6af0cbfb892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Sim=C3=B5es?= Date: Mon, 27 Oct 2025 16:03:25 +0100 Subject: [PATCH 3/4] ACTUAL resilience to missing config arrays... --- src/Form/LanguageTagSettingsForm.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Form/LanguageTagSettingsForm.php b/src/Form/LanguageTagSettingsForm.php index ebab2c2..cfbac96 100644 --- a/src/Form/LanguageTagSettingsForm.php +++ b/src/Form/LanguageTagSettingsForm.php @@ -116,27 +116,27 @@ public function submitForm(array &$form, FormStateInterface $form_state) { /** * Prepares the submitted value to be stored in config. * - * @param string $value + * @param string|null $value * The submitted value. * * @return array * The value to be stored in config. */ - public static function multiLineStringToArray(string $value = ""): array { - return array_filter(array_map('trim', explode("\n", trim($value)))); + public static function multiLineStringToArray(?string $value): array { + return array_filter(array_map('trim', explode("\n", trim($value ?? '')))); } /** * Prepares the config value to be displayed in the form. * - * @param array $value + * @param array|null $value * The value saved in config. * * @return string * The value of the form element. */ - public static function arrayToMultiLineString(array $value = []): string { - return implode("\n", $value); + public static function arrayToMultiLineString(?array $value): string { + return implode("\n", $value ?? []); } } From 9f5f1dd1734330ba466a84307add2c9dc656d945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Sim=C3=B5es?= Date: Mon, 27 Oct 2025 16:51:45 +0100 Subject: [PATCH 4/4] Further test cases; renamed for consistency --- ...st.php => LanguageTagSettingsFormTest.php} | 91 +++++++++++++++++-- 1 file changed, 81 insertions(+), 10 deletions(-) rename tests/src/Functional/{SettingsFormTest.php => LanguageTagSettingsFormTest.php} (54%) diff --git a/tests/src/Functional/SettingsFormTest.php b/tests/src/Functional/LanguageTagSettingsFormTest.php similarity index 54% rename from tests/src/Functional/SettingsFormTest.php rename to tests/src/Functional/LanguageTagSettingsFormTest.php index c10d633..d067168 100644 --- a/tests/src/Functional/SettingsFormTest.php +++ b/tests/src/Functional/LanguageTagSettingsFormTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\ewp_core\Functional; +use Drupal\user\Entity\User; use Drupal\Tests\BrowserTestBase; /** @@ -9,7 +10,7 @@ * * @group ewp_core */ -class SettingsFormTest extends BrowserTestBase { +class LanguageTagSettingsFormTest extends BrowserTestBase { const CONFIG_KEY = 'ewp_core.settings'; const FORM_PATH = 'admin/ewp/settings/lang'; @@ -25,19 +26,31 @@ class SettingsFormTest extends BrowserTestBase { */ protected static $modules = ['user', 'ewp_core']; + /** + * Admin user account. + */ + protected User $admin; + + /** + * Authenticated user account. + */ + protected User $user; + /** * {@inheritdoc} */ protected function setUp(): void { parent::setUp(); + + $this->user = $this->drupalCreateUser(['access content']); + $this->admin = $this->drupalCreateUser([self::PERMISSION]); } /** - * Tests access to the settings form by a non-privileged user. + * Tests access to the language tag settings form by a non-privileged user. */ - public function testSettingsFormWithoutPermission() { - $account = $this->drupalCreateUser(['access content']); - $this->drupalLogin($account); + public function testLanguageTagSettingsFormWithoutPermission() { + $this->drupalLogin($this->user); $this->drupalGet(self::FORM_PATH); $this->assertSession() @@ -45,11 +58,10 @@ public function testSettingsFormWithoutPermission() { } /** - * Tests the settings form as a privileged user. + * Tests the language tag settings form as a privileged user. */ - public function testSettingsForm() { - $account = $this->drupalCreateUser([self::PERMISSION]); - $this->drupalLogin($account); + public function testLanguageTagSettingsForm() { + $this->drupalLogin($this->admin); // Test the default configuration. $default_config = $this->config(self::CONFIG_KEY); @@ -66,7 +78,7 @@ public function testSettingsForm() { $lang_secondary_list = $default_config->get('lang_secondary_list'); $this->assertContains('tr|Turkish', $lang_secondary_list); - // Test access to the settings form. + // Test access to the language tag settings form. $this->drupalGet(self::FORM_PATH); $this->assertSession() ->statusCodeEquals(200); @@ -124,4 +136,63 @@ public function testSettingsForm() { } + /** + * Tests incorrect inputs in the language tag settings form. + */ + public function testLanguageTagSettingsFormErrors() { + $this->drupalLogin($this->admin); + + $this->drupalGet(self::FORM_PATH); + + // Some correct data to begin with. + $correct_data = [ + 'lang_primary_group_label' => 'Primary', + 'lang_primary_list' => 'en|English', + 'lang_secondary_group_label' => 'Secondary', + 'lang_secondary_list' => 'und|undefined', + ]; + $this->submitForm($correct_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains('The configuration options have been saved.'); + + // Test values cannot be empty. + $bad_data = $correct_data; + $bad_data['lang_primary_group_label'] = ''; + $this->submitForm($bad_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains('This value should not be blank.'); + + $bad_data = $correct_data; + $bad_data['lang_primary_list'] = ''; + $this->submitForm($bad_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains('This value should not be blank.'); + + $bad_data = $correct_data; + $bad_data['lang_secondary_group_label'] = ''; + $this->submitForm($bad_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains('This value should not be blank.'); + + $bad_data = $correct_data; + $bad_data['lang_secondary_list'] = ''; + $this->submitForm($bad_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains('This value should not be blank.'); + + // Test language tags must be valid. + $bad_data = $correct_data; + $bad_data['lang_primary_list'] = 'xyz'; + $this->submitForm($bad_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains("'xyz' is not a valid language tag."); + + $bad_data = $correct_data; + $bad_data['lang_secondary_list'] = 'pt-Madeira'; + $this->submitForm($bad_data, 'Save configuration'); + $this->assertSession() + ->pageTextContains("'pt-Madeira' is not a valid language tag."); + + } + }