From 1b1a8fa0472d05284bd0d99a2d2a05f98a27e1ae Mon Sep 17 00:00:00 2001 From: Emad Rad Date: Sun, 22 Dec 2024 15:18:37 +0330 Subject: [PATCH] fix: Add username generation tests and utility functions - Introduced `remove_special_characters_from_name` and `generate_username_suggestions` functions to enhance username handling. - Added comprehensive test cases for username generation, including ASCII validation and uniqueness checks. - Implemented tests for special character removal and suggestion generation based on various input scenarios, including edge cases. --- .../djangoapps/user_authn/tests/test_utils.py | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/openedx/core/djangoapps/user_authn/tests/test_utils.py b/openedx/core/djangoapps/user_authn/tests/test_utils.py index 72eaaf8265..34578a661d 100644 --- a/openedx/core/djangoapps/user_authn/tests/test_utils.py +++ b/openedx/core/djangoapps/user_authn/tests/test_utils.py @@ -9,7 +9,11 @@ from django.test.client import RequestFactory from django.test.utils import override_settings from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory -from openedx.core.djangoapps.user_authn.utils import is_safe_login_or_logout_redirect +from openedx.core.djangoapps.user_authn.utils import ( + is_safe_login_or_logout_redirect, + generate_username_suggestions, + remove_special_characters_from_name, +) @ddt.ddt @@ -68,3 +72,73 @@ class TestRedirectUtils(TestCase): req = self.request.get(f'/logout?{urlencode(params)}', HTTP_HOST=host) actual_is_safe = self._is_safe_redirect(req, redirect_url) assert actual_is_safe == expected_is_safe + + +@ddt.ddt +class TestUsernameGeneration(TestCase): + """Test username generation utility methods.""" + + def test_remove_special_characters(self): + """Test the removal of special characters from a name.""" + test_cases = [ + ('John Doe', 'JohnDoe'), + ('John@Doe', 'JohnDoe'), + ('John.Doe', 'JohnDoe'), + ('John_Doe', 'John_Doe'), # Underscore is allowed + ('John-Doe', 'John-Doe'), # Hyphen is allowed + ('John$#@!Doe', 'JohnDoe'), + ] + for input_name, expected in test_cases: + assert remove_special_characters_from_name(input_name) == expected + + @ddt.data( + # Test normal ASCII name + ('John Doe', True), # Should return suggestions + ('Jane Smith', True), # Should return suggestions + # Test non-ASCII names + ('José García', False), # Contains non-ASCII characters + ('مریم میرزاخانی', False), # Persian name + ('明美 田中', False), # Japanese name + ('Σωκράτης', False), # Greek name + ('Владимир', False), # Cyrillic characters + # Test edge cases + ('A B', True), # Minimal valid name + ('', True), # Empty string + (' ', True), # Just spaces + ) + @ddt.unpack + def test_username_suggestions_ascii_check(self, name, should_generate): + """Test username suggestion generation for ASCII and non-ASCII names.""" + suggestions = generate_username_suggestions(name) + + if should_generate: + if name.strip(): # If name is not empty or just spaces + # Should generate up to 3 suggestions for valid ASCII names + assert len(suggestions) <= 3 + # Verify all suggestions are ASCII + for suggestion in suggestions: + assert suggestion.isascii() + assert suggestion.replace('_', '').replace('-', '').isalnum() + else: + # Empty or whitespace-only names should return empty list + assert not suggestions + else: + # Should return empty list for non-ASCII names + assert not suggestions + + def test_unique_suggestions(self): + """Test that generated suggestions are unique.""" + name = "John Doe" + suggestions = generate_username_suggestions(name) + assert len(suggestions) == len(set(suggestions)), "All suggestions should be unique" + + def test_suggestion_length(self): + """Test that generated suggestions respect the maximum length.""" + from openedx.core.djangoapps.user_api.accounts import USERNAME_MAX_LENGTH + + # Test with a very long name + long_name = "John" * 50 + suggestions = generate_username_suggestions(long_name) + + for suggestion in suggestions: + assert len(suggestion) <= USERNAME_MAX_LENGTH