from django.test import TestCase from .views import determine_search_strategy, is_query_phone_only class DetermineSearchStrategyTestCase(TestCase): """ Тесты для функции determine_search_strategy(). Проверяют, что функция правильно определяет стратегию поиска на основе содержимого query. """ # ===== email_prefix: query заканчивается на @ ===== def test_email_prefix_simple(self): """Query "team_x3m@" должен вернуть ('email_prefix', 'team_x3m')""" strategy, search_value = determine_search_strategy('team_x3m@') self.assertEqual(strategy, 'email_prefix') self.assertEqual(search_value, 'team_x3m') def test_email_prefix_with_domain_symbol(self): """Query "user_name@" должен вернуть ('email_prefix', 'user_name')""" strategy, search_value = determine_search_strategy('user_name@') self.assertEqual(strategy, 'email_prefix') self.assertEqual(search_value, 'user_name') def test_email_prefix_with_numbers(self): """Query "test123@" должен вернуть ('email_prefix', 'test123')""" strategy, search_value = determine_search_strategy('test123@') self.assertEqual(strategy, 'email_prefix') self.assertEqual(search_value, 'test123') # ===== email_domain: query начинается с @ ===== def test_email_domain_simple(self): """Query "@bk" должен вернуть ('email_domain', 'bk')""" strategy, search_value = determine_search_strategy('@bk') self.assertEqual(strategy, 'email_domain') self.assertEqual(search_value, 'bk') def test_email_domain_with_extension(self): """Query "@bk.ru" должен вернуть ('email_domain', 'bk.ru')""" strategy, search_value = determine_search_strategy('@bk.ru') self.assertEqual(strategy, 'email_domain') self.assertEqual(search_value, 'bk.ru') def test_email_domain_with_multiple_dots(self): """Query "@mail.google.com" должен вернуть ('email_domain', 'mail.google.com')""" strategy, search_value = determine_search_strategy('@mail.google.com') self.assertEqual(strategy, 'email_domain') self.assertEqual(search_value, 'mail.google.com') # ===== email_full: query содержит и локальную часть, и домен ===== def test_email_full_simple(self): """Query "test@bk.ru" должен вернуть ('email_full', 'test@bk.ru')""" strategy, search_value = determine_search_strategy('test@bk.ru') self.assertEqual(strategy, 'email_full') self.assertEqual(search_value, 'test@bk.ru') def test_email_full_partial(self): """Query "test@bk" должен вернуть ('email_full', 'test@bk')""" strategy, search_value = determine_search_strategy('test@bk') self.assertEqual(strategy, 'email_full') self.assertEqual(search_value, 'test@bk') def test_email_full_complex(self): """Query "user.name@mail.example.com" должен вернуть ('email_full', ...)""" strategy, search_value = determine_search_strategy('user.name@mail.example.com') self.assertEqual(strategy, 'email_full') self.assertEqual(search_value, 'user.name@mail.example.com') # ===== universal: query без @, 3+ символов ===== def test_universal_three_chars(self): """Query "natul" (5 символов) должен вернуть ('universal', 'natul')""" strategy, search_value = determine_search_strategy('natul') self.assertEqual(strategy, 'universal') self.assertEqual(search_value, 'natul') def test_universal_three_chars_exact(self): """Query "abc" (3 символа) должен вернуть ('universal', 'abc')""" strategy, search_value = determine_search_strategy('abc') self.assertEqual(strategy, 'universal') self.assertEqual(search_value, 'abc') def test_universal_cyrillic(self): """Query "наталь" (6 символов) должен вернуть ('universal', 'наталь')""" strategy, search_value = determine_search_strategy('наталь') self.assertEqual(strategy, 'universal') self.assertEqual(search_value, 'наталь') def test_universal_mixed(self): """Query "Test123" (7 символов) должен вернуть ('universal', 'Test123')""" strategy, search_value = determine_search_strategy('Test123') self.assertEqual(strategy, 'universal') self.assertEqual(search_value, 'Test123') # ===== name_only: очень короткие запросы (< 3 символов без @) ===== def test_name_only_single_char(self): """Query "t" должен вернуть ('name_only', 't')""" strategy, search_value = determine_search_strategy('t') self.assertEqual(strategy, 'name_only') self.assertEqual(search_value, 't') def test_name_only_two_chars(self): """Query "te" должен вернуть ('name_only', 'te')""" strategy, search_value = determine_search_strategy('te') self.assertEqual(strategy, 'name_only') self.assertEqual(search_value, 'te') def test_name_only_two_chars_cyrillic(self): """Query "на" (2 символа) должен вернуть ('name_only', 'на')""" strategy, search_value = determine_search_strategy('на') self.assertEqual(strategy, 'name_only') self.assertEqual(search_value, 'на') # ===== edge cases ===== def test_empty_string(self): """Query "" должен вернуть ('name_only', '')""" strategy, search_value = determine_search_strategy('') self.assertEqual(strategy, 'name_only') self.assertEqual(search_value, '') def test_only_at_symbol(self): """Query "@" должен вернуть ('email_domain', '')""" strategy, search_value = determine_search_strategy('@') self.assertEqual(strategy, 'email_domain') self.assertEqual(search_value, '') def test_multiple_at_symbols(self): """Query "test@example@com" должен обработать первый @""" strategy, search_value = determine_search_strategy('test@example@com') self.assertEqual(strategy, 'email_full') self.assertEqual(search_value, 'test@example@com') def test_spaces_in_query(self): """Query "Ivan Petrov" должен вернуть ('universal', 'Ivan Petrov')""" strategy, search_value = determine_search_strategy('Ivan Petrov') self.assertEqual(strategy, 'universal') self.assertEqual(search_value, 'Ivan Petrov') # ===== real-world examples ===== def test_real_world_problematic_case(self): """ Real-world case: query "team_x3m@" не должен найти "natulj@bk.ru" Используется email_prefix со istartswith вместо icontains """ strategy, search_value = determine_search_strategy('team_x3m@') self.assertEqual(strategy, 'email_prefix') # Важно: стратегия email_prefix, не universal или email_full self.assertNotEqual(strategy, 'universal') def test_real_world_domain_search(self): """Real-world case: query "@bk" должен найти все @bk.ru""" strategy, search_value = determine_search_strategy('@bk') self.assertEqual(strategy, 'email_domain') self.assertEqual(search_value, 'bk') def test_real_world_name_search(self): """Real-world case: query "natul" должен найти "Наталья" и "natulj@bk.ru" """ strategy, search_value = determine_search_strategy('natul') self.assertEqual(strategy, 'universal') self.assertEqual(search_value, 'natul') class IsQueryPhoneOnlyTestCase(TestCase): """ Тесты для функции is_query_phone_only(). Проверяют, что функция правильно определяет, содержит ли query только символы номера телефона (цифры, +, -, (), пробелы). """ # ===== Должны вернуть True (только телефонные символы) ===== def test_phone_only_digits(self): """Query '295' должен вернуть True (только цифры)""" self.assertTrue(is_query_phone_only('295')) def test_phone_only_single_digit(self): """Query '5' должен вернуть True (одна цифра)""" self.assertTrue(is_query_phone_only('5')) def test_phone_with_plus(self): """Query '+375291234567' должен вернуть True""" self.assertTrue(is_query_phone_only('+375291234567')) def test_phone_with_dashes(self): """Query '029-123-45' должен вернуть True""" self.assertTrue(is_query_phone_only('029-123-45')) def test_phone_with_parentheses(self): """Query '(029) 123-45' должен вернуть True""" self.assertTrue(is_query_phone_only('(029) 123-45')) def test_phone_with_spaces(self): """Query '029 123 45' должен вернуть True""" self.assertTrue(is_query_phone_only('029 123 45')) def test_phone_complex_format(self): """Query '+375 (29) 123-45-67' должен вернуть True""" self.assertTrue(is_query_phone_only('+375 (29) 123-45-67')) def test_phone_with_dot(self): """Query '029.123.45' должен вернуть True""" self.assertTrue(is_query_phone_only('029.123.45')) # ===== Должны вернуть False (содержат буквы или другие символы) ===== def test_query_with_letters_only(self): """Query 'abc' должен вернуть False (содержит буквы)""" self.assertFalse(is_query_phone_only('abc')) def test_query_with_mixed_letters_digits(self): """Query 'x3m' должен вернуть False (содержит буквы)""" self.assertFalse(is_query_phone_only('x3m')) def test_query_name_with_digits(self): """Query 'team_x3m' должен вернуть False (содержит буквы и _)""" self.assertFalse(is_query_phone_only('team_x3m')) def test_query_name_cyrillic(self): """Query 'Наталья' должен вернуть False (содержит кириллицу)""" self.assertFalse(is_query_phone_only('Наталья')) def test_query_with_underscore(self): """Query '123_456' должен вернуть False (содержит _)""" self.assertFalse(is_query_phone_only('123_456')) def test_query_with_hash(self): """Query '123#456' должен вернуть False (содержит #)""" self.assertFalse(is_query_phone_only('123#456')) def test_empty_string(self): """Query '' должен вернуть False (пустая строка)""" self.assertFalse(is_query_phone_only('')) def test_only_spaces(self): """Query ' ' должен вернуть True (только пробелы разрешены)""" self.assertTrue(is_query_phone_only(' ')) # ===== Real-world cases ===== def test_real_world_case_x3m_should_not_be_phone(self): """ Real-world case: "x3m" содержит букву, поэтому НЕ похож на телефон. Это критично для решения проблемы с поиском Натальи. """ self.assertFalse(is_query_phone_only('x3m')) # Значит, при поиске "x3m" НЕ будет поиска по цифре "3" в телефонах def test_real_world_case_295_should_be_phone(self): """Real-world case: '295' только цифры, похож на телефон""" self.assertTrue(is_query_phone_only('295')) def test_real_world_full_phone_number(self): """Real-world case: полный номер в стандартном формате""" self.assertTrue(is_query_phone_only('+375 (29) 598-62-62'))