Repository: mozmeao/basket

Issue:
imporve split_name helper & add tests
need to handle edge case of just a space being sent in the data


Discussion:

Resolving patch:
diff --git a/basket/news/tasks.py b/basket/news/tasks.py
--- a/basket/news/tasks.py
+++ b/basket/news/tasks.py
@@ -29,7 +29,7 @@
 from basket.news.newsletters import get_sms_vendor_id, get_transactional_message_ids, newsletter_map
 from basket.news.utils import (generate_token, get_accept_languages, get_best_language, get_user_data,
                                iso_format_unix_timestamp, parse_newsletters, parse_newsletters_csv,
-                               SUBSCRIBE, UNSUBSCRIBE, get_best_supported_lang)
+                               SUBSCRIBE, UNSUBSCRIBE, get_best_supported_lang, split_name)
 
 log = logging.getLogger(__name__)
 
@@ -1049,31 +1049,6 @@ def process_donation_event(data):
 }
 
 
-def split_name(name):
-    """
-    Takes a full name as a string and attempts to make it conform to the narrow
-    "first/last" system Salesforce requires.
-
-    Drops any "jr" or "sr" suffix.
-    """
-
-    # try to make the final bit after the last space the last name
-    names = name.rsplit(None, 1)
-
-    if len(names) == 2:
-        first, last = names
-
-        # if last name is 'jr' or 'sr' and first name has a space in it, do
-        # more splitting
-        if ' ' in first and last.lower() in ['jr', 'sr']:
-            names = first.rsplit(None, 1)
-            first, last = names
-    else:
-        first, last = '', names[0]
-
-    return first, last
-
-
 @et_task
 def process_donation(data):
     get_lock(data['email'])
diff --git a/basket/news/utils.py b/basket/news/utils.py
--- a/basket/news/utils.py
+++ b/basket/news/utils.py
@@ -583,3 +583,35 @@ def parse_newsletters(api_call_type, newsletters, cur_newsletters):
             newsletter_map[nl] = False
 
     return newsletter_map
+
+
+def split_name(name):
+    """
+    Takes a full name as a string and attempts to make it conform to the narrow
+    "first/last" system Salesforce requires.
+
+    Drops any "jr" or "sr" suffix.
+    """
+
+    # remove leading/trailing whitespace and periods
+    # also accounts for a string of spaces being provided
+    name = name.strip(' .')
+
+    # if the name is an empty string, we're done
+    if not name:
+        return '', ''
+
+    # try to make the final bit after the last space the last name
+    names = name.rsplit(None, 1)
+
+    if len(names) == 2:
+        first, last = names
+
+        # if last name is 'jr' or 'sr' and first name has a space in it, do
+        # more splitting
+        if ' ' in first and last.lower() in ['jr', 'sr']:
+            first, last = first.rsplit(None, 1)
+    else:
+        first, last = '', names[0]
+
+    return first, last


Test patch:
diff --git a/basket/news/tests/test__utils.py b/basket/news/tests/test__utils.py
--- a/basket/news/tests/test__utils.py
+++ b/basket/news/tests/test__utils.py
@@ -21,6 +21,7 @@
     parse_newsletters_csv,
     parse_phone_number,
     process_email,
+    split_name,
 )
 
 
@@ -375,3 +376,23 @@ def test_invalid_email(self):
         self.assertIsNone(process_email('dude@home@example.com'))
         self.assertIsNone(process_email(''))
         self.assertIsNone(process_email(None))
+
+
+class TestSplitName(TestCase):
+    def test_empty_string(self):
+        self.assertEqual(split_name(''), ('', ''))
+
+    def test_only_spaces(self):
+        self.assertEqual(split_name(' '), ('', ''))
+        self.assertEqual(split_name('     '), ('', ''))
+
+    def test_standard_cases(self):
+        self.assertEqual(split_name('Dude'), ('', 'Dude'))
+        self.assertEqual(split_name('Walter Sobchak'), ('Walter', 'Sobchak'))
+        self.assertEqual(split_name('Theodore Donald Kerabatsos'), ('Theodore Donald', 'Kerabatsos'))
+
+    def test_removes_suffixes(self):
+        self.assertEqual(split_name('Jeffrey Lebowski Jr'), ('Jeffrey', 'Lebowski'))
+        self.assertEqual(split_name('Jeffrey Lebowski jr.'), ('Jeffrey', 'Lebowski'))
+        self.assertEqual(split_name('Uli Kunkel Sr.'), ('Uli', 'Kunkel'))
+        self.assertEqual(split_name('Uli Kunkel sr'), ('Uli', 'Kunkel'))