Browse Source

Replace User.objects.create_user with misago.users.testutils.create_test_user

rafalp 6 years ago
parent
commit
110832c432
69 changed files with 910 additions and 1104 deletions
  1. 10 13
      misago/admin/tests/test_admin_views.py
  2. 26 1
      misago/conftest.py
  3. 9 13
      misago/core/tests/test_mail.py
  4. 2 2
      misago/core/tests/test_templatetags.py
  5. 1 1
      misago/core/tests/test_utils.py
  6. 1 1
      misago/core/tests/test_validators.py
  7. 4 4
      misago/markup/tests/test_finalise.py
  8. 2 5
      misago/markup/tests/test_parser.py
  9. 2 4
      misago/readtracker/tests/test_categoriestracker.py
  10. 5 8
      misago/readtracker/tests/test_clearreadtracker.py
  11. 2 5
      misago/readtracker/tests/test_poststracker.py
  12. 2 4
      misago/readtracker/tests/test_threadstracker.py
  13. 2 2
      misago/threads/test.py
  14. 9 19
      misago/threads/tests/test_anonymize_data.py
  15. 2 13
      misago/threads/tests/test_delete_user_likes.py
  16. 2 6
      misago/threads/tests/test_emailnotification_middleware.py
  17. 2 3
      misago/threads/tests/test_events.py
  18. 2 5
      misago/threads/tests/test_mergeconflict.py
  19. 28 28
      misago/threads/tests/test_participants.py
  20. 17 24
      misago/threads/tests/test_post_mentions.py
  21. 3 6
      misago/threads/tests/test_post_model.py
  22. 60 54
      misago/threads/tests/test_privatethread_patch_api.py
  23. 2 8
      misago/threads/tests/test_privatethread_reply_api.py
  24. 2 7
      misago/threads/tests/test_privatethread_start_api.py
  25. 2 5
      misago/threads/tests/test_subscriptions.py
  26. 2 9
      misago/threads/tests/test_sync_unread_private_threads.py
  27. 11 14
      misago/threads/tests/test_thread_model.py
  28. 7 10
      misago/threads/tests/test_threadparticipant_model.py
  29. 5 13
      misago/users/tests/test_activepostersranking.py
  30. 4 5
      misago/users/tests/test_audittrail.py
  31. 36 49
      misago/users/tests/test_auth_api.py
  32. 3 7
      misago/users/tests/test_auth_backend.py
  33. 24 0
      misago/users/tests/test_avatar_filter.py
  34. 6 8
      misago/users/tests/test_avatars.py
  35. 2 13
      misago/users/tests/test_avatarserver_views.py
  36. 9 9
      misago/users/tests/test_bans.py
  37. 8 11
      misago/users/tests/test_credentialchange.py
  38. 2 5
      misago/users/tests/test_datadownloadsadmin_views.py
  39. 8 8
      misago/users/tests/test_deleteinactiveusers.py
  40. 7 7
      misago/users/tests/test_deletemarkedusers.py
  41. 5 8
      misago/users/tests/test_deleteprofilefield.py
  42. 2 4
      misago/users/tests/test_djangoadmin_user.py
  43. 23 19
      misago/users/tests/test_forgottenpassword_views.py
  44. 2 6
      misago/users/tests/test_getting_user_status.py
  45. 4 7
      misago/users/tests/test_invalidatebans.py
  46. 2 6
      misago/users/tests/test_lists_views.py
  47. 11 16
      misago/users/tests/test_listusedprofilefields.py
  48. 0 35
      misago/users/tests/test_misagoavatars_tags.py
  49. 41 57
      misago/users/tests/test_namechanges.py
  50. 53 62
      misago/users/tests/test_new_user_setup.py
  51. 24 0
      misago/users/tests/test_populate_online_tracker_command.py
  52. 0 27
      misago/users/tests/test_populateonlinetracker.py
  53. 9 13
      misago/users/tests/test_profile_views.py
  54. 67 0
      misago/users/tests/test_remove_old_ips_command.py
  55. 0 53
      misago/users/tests/test_removeoldips.py
  56. 4 8
      misago/users/tests/test_search.py
  57. 24 47
      misago/users/tests/test_signatures.py
  58. 20 0
      misago/users/tests/test_token_creation_and_validation.py
  59. 0 21
      misago/users/tests/test_tokens.py
  60. 47 43
      misago/users/tests/test_user_avatar_api.py
  61. 4 8
      misago/users/tests/test_user_changeemail_api.py
  62. 86 76
      misago/users/tests/test_user_creation.py
  63. 3 8
      misago/users/tests/test_user_details_api.py
  64. 4 7
      misago/users/tests/test_user_editdetails_api.py
  65. 55 44
      misago/users/tests/test_user_getters.py
  66. 15 15
      misago/users/tests/test_user_model.py
  67. 3 11
      misago/users/tests/test_user_username_api.py
  68. 49 67
      misago/users/tests/test_users_api.py
  69. 20 27
      misago/users/tests/test_validators.py

+ 10 - 13
misago/admin/tests/test_admin_views.py

@@ -1,12 +1,9 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.urls import reverse
 
 from misago.admin.testutils import AdminTestCase
 from misago.admin.views import get_protected_namespace
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class MockRequest(object):
@@ -46,7 +43,7 @@ class AdminLoginViewTests(TestCase):
     def test_login_returns_200_on_invalid_post(self):
         """form handles invalid data gracefully"""
         response = self.client.post(
-            reverse("misago:admin:index"), data={"username": "Nope", "password": "Nope"}
+            reverse("misago:admin:index"), data={"username": "no", "password": "no"}
         )
 
         self.assertContains(response, "Login or password is incorrect.")
@@ -56,7 +53,7 @@ class AdminLoginViewTests(TestCase):
 
     def test_login_denies_non_staff_non_superuser(self):
         """login rejects user thats non staff and non superuser"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user("User", "user@example.com", "password")
 
         user.is_staff = False
         user.is_superuser = False
@@ -64,14 +61,14 @@ class AdminLoginViewTests(TestCase):
 
         response = self.client.post(
             reverse("misago:admin:index"),
-            data={"username": "Bob", "password": "Pass.123"},
+            data={"username": "User", "password": "password"},
         )
 
         self.assertContains(response, "Your account does not have admin privileges.")
 
     def test_login_denies_non_staff_superuser(self):
         """login rejects user thats non staff and superuser"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user("User", "user@example.com", "password")
 
         user.is_staff = False
         user.is_superuser = True
@@ -79,14 +76,14 @@ class AdminLoginViewTests(TestCase):
 
         response = self.client.post(
             reverse("misago:admin:index"),
-            data={"username": "Bob", "password": "Pass.123"},
+            data={"username": "User", "password": "password"},
         )
 
         self.assertContains(response, "Your account does not have admin privileges.")
 
     def test_login_signs_in_staff_non_superuser(self):
         """login passess user thats staff and non superuser"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user("User", "user@example.com", "password")
 
         user.is_staff = True
         user.is_superuser = False
@@ -94,14 +91,14 @@ class AdminLoginViewTests(TestCase):
 
         response = self.client.post(
             reverse("misago:admin:index"),
-            data={"username": "Bob", "password": "Pass.123"},
+            data={"username": "User", "password": "password"},
         )
 
         self.assertEqual(response.status_code, 302)
 
     def test_login_signs_in_staff_superuser(self):
         """login passess user thats staff and superuser"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user("User", "user@example.com", "password")
 
         user.is_staff = True
         user.is_superuser = True
@@ -109,7 +106,7 @@ class AdminLoginViewTests(TestCase):
 
         response = self.client.post(
             reverse("misago:admin:index"),
-            data={"username": "Bob", "password": "Pass.123"},
+            data={"username": "User", "password": "password"},
         )
 
         self.assertEqual(response.status_code, 302)

+ 26 - 1
misago/conftest.py

@@ -1,6 +1,6 @@
 import pytest
 
-from misago.acl import ACL_CACHE
+from misago.acl import ACL_CACHE, useracl
 from misago.conf import SETTINGS_CACHE
 from misago.conf.dynamicsettings import DynamicSettings
 from misago.conf.staticsettings import StaticSettings
@@ -44,6 +44,21 @@ def user(db, user_password):
 
 
 @pytest.fixture
+def user_acl(user, cache_versions):
+    return useracl.get_user_acl(user, cache_versions)
+
+
+@pytest.fixture
+def other_user(db, user_password):
+    return create_test_user("OtherUser", "otheruser@example.com", user_password)
+
+
+@pytest.fixture
+def other_user_acl(other_user, cache_versions):
+    return useracl.get_user_acl(other_user, cache_versions)
+
+
+@pytest.fixture
 def staffuser(db, user_password):
     user = create_test_superuser("Staffuser", "staffuser@example.com", user_password)
     user.is_superuser = False
@@ -52,5 +67,15 @@ def staffuser(db, user_password):
 
 
 @pytest.fixture
+def staffuser_acl(staffuser, cache_versions):
+    return useracl.get_user_acl(staffuser, cache_versions)
+
+
+@pytest.fixture
 def superuser(db, user_password):
     return create_test_superuser("Superuser", "superuser@example.com", user_password)
+
+
+@pytest.fixture
+def superuser_acl(superuser, cache_versions):
+    return useracl.get_user_acl(superuser, cache_versions)

+ 9 - 13
misago/core/tests/test_mail.py

@@ -1,25 +1,21 @@
-from django.contrib.auth import get_user_model
 from django.core import mail
 from django.test import TestCase
 from django.urls import reverse
 
 from misago.cache.versions import get_cache_versions
 from misago.conf.dynamicsettings import DynamicSettings
-
 from misago.core.mail import build_mail, mail_user, mail_users
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class MailTests(TestCase):
     def test_building_mail_without_context_raises_value_error(self):
-        user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        user = create_test_user("User", "user@example.com")
         with self.assertRaises(ValueError):
             build_mail(user, "Misago Test Mail", "misago/emails/base")
 
     def test_building_mail_without_settings_in_context_raises_value_error(self):
-        user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        user = create_test_user("User", "user@example.com")
         with self.assertRaises(ValueError):
             build_mail(
                 user, "Misago Test Mail", "misago/emails/base", context={"settings": {}}
@@ -27,7 +23,7 @@ class MailTests(TestCase):
 
     def test_mail_user(self):
         """mail_user sets message in backend"""
-        user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        user = create_test_user("User", "user@example.com")
 
         cache_versions = get_cache_versions()
         settings = DynamicSettings(cache_versions)
@@ -55,11 +51,11 @@ class MailTests(TestCase):
         settings = DynamicSettings(cache_versions)
 
         test_users = [
-            User.objects.create_user("Alpha", "alpha@test.com", "pass123"),
-            User.objects.create_user("Beta", "beta@test.com", "pass123"),
-            User.objects.create_user("Niner", "niner@test.com", "pass123"),
-            User.objects.create_user("Foxtrot", "foxtrot@test.com", "pass123"),
-            User.objects.create_user("Uniform", "uniform@test.com", "pass123"),
+            create_test_user("User1", "User1@example.com"),
+            create_test_user("Use2r", "User2@example.com"),
+            create_test_user("Us3er", "User3@example.com"),
+            create_test_user("U4ser", "User4@example.com"),
+            create_test_user("5User", "User5@example.com"),
         ]
 
         mail_users(

+ 2 - 2
misago/core/tests/test_templatetags.py

@@ -92,8 +92,8 @@ class BatchTests(TestCase):
 class MockUser(object):
     id = 12
     pk = 12
-    username = "Bob"
-    slug = "bob"
+    username = "User"
+    slug = "user"
 
 
 class ShorthandsTests(TestCase):

+ 1 - 1
misago/core/tests/test_utils.py

@@ -47,7 +47,7 @@ class SlugifyTests(TestCase):
     def test_valid_slugify_output(self):
         """Misago's slugify correctly slugifies string"""
         test_cases = [
-            ("Bob", "bob"),
+            ("User", "user"),
             ("Eric The Fish", "eric-the-fish"),
             ("John   Snow", "john-snow"),
             ("J0n", "j0n"),

+ 1 - 1
misago/core/tests/test_validators.py

@@ -34,5 +34,5 @@ class ValidateSluggableTests(TestCase):
         """valid values don't raise errors"""
         validator = validate_sluggable()
 
-        validator("Bob")
+        validator("User")
         validator("Lorem ipsum123!")

+ 4 - 4
misago/markup/tests/test_finalise.py

@@ -13,7 +13,7 @@ class QuoteTests(TestCase):
 <blockquote class="quote-body">
 <p>Dolor met</p>
 <aside class="quote-block">
-<div class="quote-heading"><a href="/users/bob-1/">@Bob</a></div>
+<div class="quote-heading"><a href="/users/user-1/">@User</a></div>
 <blockquote class="quote-body">
 <p>Dolor met</p>
 </blockquote>
@@ -30,7 +30,7 @@ class QuoteTests(TestCase):
 <blockquote class="quote-body">
 <p>Dolor met</p>
 <aside class="quote-block">
-<div class="quote-heading"><a href="/users/bob-1/">@Bob</a> has written:</div>
+<div class="quote-heading"><a href="/users/user-1/">@User</a> has written:</div>
 <blockquote class="quote-body">
 <p>Dolor met</p>
 </blockquote>
@@ -45,11 +45,11 @@ class QuoteTests(TestCase):
     def test_finalise_minified_markup(self):
         """header is replaced in minified post"""
         test_text = """
-<p>Lorem ipsum.</p><aside class="quote-block"><div class="quote-heading"></div><blockquote class="quote-body"><p>Dolor met</p><aside class="quote-block"><div class="quote-heading"><a href="/users/bob-1/">@Bob</a></div><blockquote class="quote-body"><p>Dolor met</p></blockquote></aside></blockquote></aside><p>Lorem ipsum dolor.</p>
+<p>Lorem ipsum.</p><aside class="quote-block"><div class="quote-heading"></div><blockquote class="quote-body"><p>Dolor met</p><aside class="quote-block"><div class="quote-heading"><a href="/users/user-1/">@User</a></div><blockquote class="quote-body"><p>Dolor met</p></blockquote></aside></blockquote></aside><p>Lorem ipsum dolor.</p>
 """.strip()
 
         expected_result = """
-<p>Lorem ipsum.</p><aside class="quote-block"><div class="quote-heading">Quoted message:</div><blockquote class="quote-body"><p>Dolor met</p><aside class="quote-block"><div class="quote-heading"><a href="/users/bob-1/">@Bob</a> has written:</div><blockquote class="quote-body"><p>Dolor met</p></blockquote></aside></blockquote></aside><p>Lorem ipsum dolor.</p>
+<p>Lorem ipsum.</p><aside class="quote-block"><div class="quote-heading">Quoted message:</div><blockquote class="quote-body"><p>Dolor met</p><aside class="quote-block"><div class="quote-heading"><a href="/users/user-1/">@User</a> has written:</div><blockquote class="quote-body"><p>Dolor met</p></blockquote></aside></blockquote></aside><p>Lorem ipsum dolor.</p>
 """.strip()
 
         self.assertEqual(expected_result, finalise_markup(test_text))

+ 2 - 5
misago/markup/tests/test_parser.py

@@ -1,10 +1,7 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 
 from misago.markup.parser import parse
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class MockRequest(object):
@@ -167,7 +164,7 @@ Lorem ipsum.
 
     def test_complex_paragraph(self):
         """parser minifies complex paragraph"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass123")
+        user = create_test_user("User", "user@example.com")
 
         test_text = (
             """

+ 2 - 4
misago/readtracker/tests/test_categoriestracker.py

@@ -1,6 +1,5 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -11,8 +10,7 @@ from misago.conftest import get_cache_versions
 from misago.readtracker import poststracker, categoriestracker
 from misago.readtracker.models import PostRead
 from misago.threads import testutils
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 cache_versions = get_cache_versions()
 
@@ -24,7 +22,7 @@ class AnonymousUser(object):
 
 class CategoriesTrackerTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("UserA", "testa@user.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com")
         self.user_acl = get_user_acl(self.user, cache_versions)
         self.category = Category.objects.get(slug="first-category")
 

+ 5 - 8
misago/readtracker/tests/test_clearreadtracker.py

@@ -1,7 +1,6 @@
 from datetime import timedelta
 from io import StringIO
 
-from django.contrib.auth import get_user_model
 from django.core.management import call_command
 from django.test import TestCase
 from django.utils import timezone
@@ -11,15 +10,13 @@ from misago.conf import settings
 from misago.readtracker.management.commands import clearreadtracker
 from misago.readtracker.models import PostRead
 from misago.threads import testutils
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class ClearReadTrackerTests(TestCase):
     def setUp(self):
-        self.user_a = User.objects.create_user("UserA", "testa@user.com", "Pass.123")
-        self.user_b = User.objects.create_user("UserB", "testb@user.com", "Pass.123")
+        self.user_1 = create_test_user("User1", "user1@example.com")
+        self.user_2 = create_test_user("User2", "user2@example.com")
 
         self.category = Category.objects.get(slug="first-category")
 
@@ -38,7 +35,7 @@ class ClearReadTrackerTests(TestCase):
         thread = testutils.post_thread(self.category)
 
         existing = PostRead.objects.create(
-            user=self.user_a,
+            user=self.user_1,
             category=self.category,
             thread=thread,
             post=thread.first_post,
@@ -46,7 +43,7 @@ class ClearReadTrackerTests(TestCase):
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF / 4),
         )
         deleted = PostRead.objects.create(
-            user=self.user_b,
+            user=self.user_2,
             category=self.category,
             thread=thread,
             post=thread.first_post,

+ 2 - 5
misago/readtracker/tests/test_poststracker.py

@@ -1,6 +1,5 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -9,9 +8,7 @@ from misago.conf import settings
 from misago.readtracker import poststracker
 from misago.readtracker.models import PostRead
 from misago.threads import testutils
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class AnonymousUser(object):
@@ -21,7 +18,7 @@ class AnonymousUser(object):
 
 class PostsTrackerTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("UserA", "testa@user.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com")
         self.category = Category.objects.get(slug="first-category")
         self.thread = testutils.post_thread(self.category)
 

+ 2 - 4
misago/readtracker/tests/test_threadstracker.py

@@ -1,6 +1,5 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -12,8 +11,7 @@ from misago.conftest import get_cache_versions
 from misago.readtracker import poststracker, threadstracker
 from misago.readtracker.models import PostRead
 from misago.threads import testutils
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 cache_versions = get_cache_versions()
 
@@ -25,7 +23,7 @@ class AnonymousUser(object):
 
 class ThreadsTrackerTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("UserA", "testa@user.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com")
         self.user_acl = get_user_acl(self.user, cache_versions)
         self.category = Category.objects.get(slug="first-category")
 

+ 2 - 2
misago/threads/test.py

@@ -30,7 +30,7 @@ def patch_category_acl(acl_patch=None):
 
 def patch_other_user_category_acl(acl_patch=None):
     def patch_acl(user, user_acl):
-        if user.slug != "bobbobertson":
+        if user.slug != "otheruser":
             return
 
         category = Category.objects.get(slug="first-category")
@@ -73,7 +73,7 @@ def patch_private_threads_acl(acl_patch=None):
 
 
 def other_user_cant_use_private_threads(user, user_acl):
-    if user.slug == "bobboberson":
+    if user.slug == "otheruser":
         user_acl.update({"can_use_private_threads": False})
 
 

+ 9 - 19
misago/threads/tests/test_anonymize_data.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.test import RequestFactory
 from django.urls import reverse
 
@@ -17,16 +16,7 @@ from misago.threads.participants import (
     remove_participant,
     set_owner,
 )
-
-
-User = get_user_model()
-
-
-def get_mock_user():
-    seed = User.objects.count() + 1
-    return User.objects.create_user(
-        "bob%s" % seed, "user%s@test.com" % seed, "Pass.123"
-    )
+from misago.users.testutils import create_test_user
 
 
 class AnonymizeEventsTests(AuthenticatedUserTestCase):
@@ -50,7 +40,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
 
     def test_anonymize_changed_owner_event(self):
         """changed owner event is anonymized by user.anonymize_data"""
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         request = self.get_request()
 
         set_owner(self.thread, self.user)
@@ -73,7 +63,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
 
     def test_anonymize_added_participant_event(self):
         """added participant event is anonymized by user.anonymize_data"""
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         request = self.get_request()
 
         set_owner(self.thread, self.user)
@@ -96,7 +86,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
 
     def test_anonymize_owner_left_event(self):
         """owner left event is anonymized by user.anonymize_data"""
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         request = self.get_request(user)
 
         set_owner(self.thread, user)
@@ -122,7 +112,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
 
     def test_anonymize_removed_owner_event(self):
         """removed owner event is anonymized by user.anonymize_data"""
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         request = self.get_request()
 
         set_owner(self.thread, user)
@@ -148,7 +138,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
 
     def test_anonymize_participant_left_event(self):
         """participant left event is anonymized by user.anonymize_data"""
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         request = self.get_request(user)
 
         set_owner(self.thread, self.user)
@@ -174,7 +164,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
 
     def test_anonymize_removed_participant_event(self):
         """removed participant event is anonymized by user.anonymize_data"""
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         request = self.get_request()
 
         set_owner(self.thread, self.user)
@@ -218,7 +208,7 @@ class AnonymizeLikesTests(AuthenticatedUserTestCase):
         post = testutils.reply_thread(thread)
         post.acl = {"can_like": True}
 
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
 
         patch_is_liked(self.get_request(self.user), post, 1)
         patch_is_liked(self.get_request(user), post, 1)
@@ -252,7 +242,7 @@ class AnonymizePostsTests(AuthenticatedUserTestCase):
         category = Category.objects.get(slug="first-category")
         thread = testutils.post_thread(category)
 
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
         post = testutils.reply_thread(thread, poster=user)
         user.anonymize_data()
 

+ 2 - 13
misago/threads/tests/test_delete_user_likes.py

@@ -1,24 +1,13 @@
-from django.contrib.auth import get_user_model
 from django.test import RequestFactory
 
 from misago.categories.models import Category
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 from misago.threads import testutils
 from misago.threads.api.postendpoints.patch_post import patch_is_liked
 from misago.threads.models import Post
 
 
-User = get_user_model()
-
-
-def get_mock_user():
-    seed = User.objects.count() + 1
-    return User.objects.create_user(
-        "bob%s" % seed, "user%s@test.com" % seed, "Pass.123"
-    )
-
-
 class DeleteUserLikesTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
@@ -38,7 +27,7 @@ class DeleteUserLikesTests(AuthenticatedUserTestCase):
         post = testutils.reply_thread(thread)
         post.acl = {"can_like": True}
 
-        user = get_mock_user()
+        user = create_test_user("OtherUser", "otheruser@example.com")
 
         patch_is_liked(self.get_request(self.user), post, 1)
         patch_is_liked(self.get_request(user), post, 1)

+ 2 - 6
misago/threads/tests/test_emailnotification_middleware.py

@@ -1,7 +1,6 @@
 from copy import deepcopy
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.core import mail
 from django.urls import reverse
 from django.utils import timezone
@@ -10,10 +9,7 @@ from django.utils.encoding import smart_str
 from misago.categories.models import Category
 from misago.threads import testutils
 from misago.threads.test import patch_category_acl, patch_other_user_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class EmailNotificationTests(AuthenticatedUserTestCase):
@@ -29,7 +25,7 @@ class EmailNotificationTests(AuthenticatedUserTestCase):
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
         )
 
-        self.other_user = User.objects.create_user("BobBobertson", "bob@boberson.com")
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
 
     @patch_category_acl({"can_reply_threads": True})
     def test_no_subscriptions(self):

+ 2 - 3
misago/threads/tests/test_events.py

@@ -1,6 +1,5 @@
 from unittest.mock import Mock
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -10,14 +9,14 @@ from misago.categories.models import Category
 from misago.conftest import get_cache_versions
 from misago.threads.events import record_event
 from misago.threads.models import Thread
+from misago.users.testutils import create_test_user
 
-User = get_user_model()
 cache_versions = get_cache_versions()
 
 
 class EventsApiTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@bob.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com")
 
         datetime = timezone.now()
 

+ 2 - 5
misago/threads/tests/test_mergeconflict.py

@@ -1,21 +1,18 @@
 from rest_framework.exceptions import ValidationError
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 
 from misago.categories.models import Category
 
 from misago.threads import testutils
 from misago.threads.mergeconflict import MergeConflict
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class MergeConflictTests(TestCase):
     def setUp(self):
         self.category = Category.objects.get(slug="first-category")
-        self.user = User.objects.create_user("bob", "bob@test.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com")
 
     def create_plain_thread(self):
         return testutils.post_thread(self.category)

+ 28 - 28
misago/threads/tests/test_participants.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -10,9 +9,7 @@ from misago.threads.participants import (
     set_owner,
     set_users_unread_private_threads_sync,
 )
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class ParticipantsTests(TestCase):
@@ -51,8 +48,8 @@ class ParticipantsTests(TestCase):
     def test_has_participants(self):
         """has_participants returns true if thread has participants"""
         users = [
-            User.objects.create_user("Bob", "bob@boberson.com", "Pass.123"),
-            User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123"),
+            create_test_user("User", "user@example.com"),
+            create_test_user("User2", "bob2@example.com"),
         ]
 
         self.assertFalse(has_participants(self.thread))
@@ -68,8 +65,8 @@ class ParticipantsTests(TestCase):
         make_participants_aware sets participants_list and participant
         annotations on list of threads
         """
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
-        other_user = User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
+        other_user = create_test_user("User2", "bob2@example.com")
 
         self.assertFalse(hasattr(self.thread, "participants_list"))
         self.assertFalse(hasattr(self.thread, "participant"))
@@ -93,8 +90,8 @@ class ParticipantsTests(TestCase):
         make_participants_aware sets participants_list and participant
         annotations on thread model
         """
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
-        other_user = User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
+        other_user = create_test_user("User2", "bob2@example.com")
 
         self.assertFalse(hasattr(self.thread, "participants_list"))
         self.assertFalse(hasattr(self.thread, "participant"))
@@ -121,7 +118,7 @@ class ParticipantsTests(TestCase):
 
     def test_set_owner(self):
         """set_owner sets user as thread owner"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         set_owner(self.thread, user)
 
@@ -134,13 +131,14 @@ class ParticipantsTests(TestCase):
         flag on users provided to true
         """
         users = [
-            User.objects.create_user("Bob1", "bob1@boberson.com", "Pass.123"),
-            User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123"),
+            create_test_user("User1", "bob1@example.com"),
+            create_test_user("User2", "bob2@example.com"),
         ]
 
         set_users_unread_private_threads_sync(users=users)
         for user in users:
-            User.objects.get(pk=user.pk, sync_unread_private_threads=True)
+            user.refresh_from_db()
+            assert user.sync_unread_private_threads
 
     def test_set_participants_unread_private_threads_sync(self):
         """
@@ -148,48 +146,50 @@ class ParticipantsTests(TestCase):
         flag on participants provided to true
         """
         users = [
-            User.objects.create_user("Bob1", "bob1@boberson.com", "Pass.123"),
-            User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123"),
+            create_test_user("User1", "bob1@example.com"),
+            create_test_user("User2", "bob2@example.com"),
         ]
 
         participants = [ThreadParticipant(user=u) for u in users]
 
         set_users_unread_private_threads_sync(participants=participants)
         for user in users:
-            User.objects.get(pk=user.pk, sync_unread_private_threads=True)
+            user.refresh_from_db()
+            assert user.sync_unread_private_threads
 
     def test_set_participants_users_unread_private_threads_sync(self):
         """
         set_users_unread_private_threads_sync sets sync_unread_private_threads
         flag on users and participants provided to true
         """
-        users = [User.objects.create_user("Bob1", "bob1@boberson.com", "Pass.123")]
-
+        users = [create_test_user("User1", "bob1@example.com")]
         participants = [ThreadParticipant(user=u) for u in users]
-
-        users.append(User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123"))
+        users.append(create_test_user("User2", "bob2@example.com"))
 
         set_users_unread_private_threads_sync(users=users, participants=participants)
         for user in users:
-            User.objects.get(pk=user.pk, sync_unread_private_threads=True)
+            user.refresh_from_db()
+            assert user.sync_unread_private_threads
 
     def test_set_users_unread_private_threads_sync_exclude_user(self):
         """exclude_user kwarg works"""
         users = [
-            User.objects.create_user("Bob1", "bob1@boberson.com", "Pass.123"),
-            User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123"),
+            create_test_user("User1", "bob1@example.com"),
+            create_test_user("User2", "bob2@example.com"),
         ]
 
         set_users_unread_private_threads_sync(users=users, exclude_user=users[0])
 
-        self.assertFalse(User.objects.get(pk=users[0].pk).sync_unread_private_threads)
-        self.assertTrue(User.objects.get(pk=users[1].pk).sync_unread_private_threads)
+        [i.refresh_from_db() for i in users]
+        assert users[0].sync_unread_private_threads is False
+        assert users[1].sync_unread_private_threads
 
     def test_set_users_unread_private_threads_sync_noop(self):
         """excluding only user is noop"""
-        user = User.objects.create_user("Bob1", "bob1@boberson.com", "Pass.123")
+        user = create_test_user("User", "bob1@example.com")
 
         with self.assertNumQueries(0):
             set_users_unread_private_threads_sync(users=[user], exclude_user=user)
 
-        self.assertFalse(User.objects.get(pk=user.pk).sync_unread_private_threads)
+        user.refresh_from_db()
+        assert user.sync_unread_private_threads is False

+ 17 - 24
misago/threads/tests/test_post_mentions.py

@@ -1,13 +1,10 @@
-from django.contrib.auth import get_user_model
 from django.test.client import BOUNDARY, MULTIPART_CONTENT, encode_multipart
 from django.urls import reverse
 
 from misago.categories.models import Category
 from misago.markup.mentions import MENTIONS_LIMIT
 from misago.threads import testutils
-from misago.users.testutils import AuthenticatedUserTestCase
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class PostMentionsTests(AuthenticatedUserTestCase):
@@ -62,11 +59,7 @@ class PostMentionsTests(AuthenticatedUserTestCase):
         users = []
 
         for i in range(MENTIONS_LIMIT + 5):
-            users.append(
-                User.objects.create_user(
-                    "Mention%s" % i, "mention%s@bob.com" % i, "pass123"
-                )
-            )
+            users.append(create_test_user("User%s" % i, "user%s@example.com" % i))
 
         mentions = ["@%s" % u for u in users]
         response = self.client.post(
@@ -82,18 +75,18 @@ class PostMentionsTests(AuthenticatedUserTestCase):
 
     def test_mention_update(self):
         """edit post endpoint updates mentions"""
-        user_a = User.objects.create_user("Mention", "mention@test.com", "pass123")
-        user_b = User.objects.create_user("MentionB", "mentionb@test.com", "pass123")
+        user_1 = create_test_user("User1", "user1@example.com")
+        user_2 = create_test_user("User2", "user2@example.com")
 
         response = self.client.post(
-            self.post_link, data={"post": "This is test response, @%s!" % user_a}
+            self.post_link, data={"post": "This is test response, @%s!" % user_1}
         )
         self.assertEqual(response.status_code, 200)
 
         post = self.user.post_set.order_by("id").last()
 
         self.assertEqual(post.mentions.count(), 1)
-        self.assertEqual(post.mentions.order_by("id")[0], user_a)
+        self.assertEqual(post.mentions.order_by("id")[0], user_1)
 
         # add mention to post
         edit_link = reverse(
@@ -103,43 +96,43 @@ class PostMentionsTests(AuthenticatedUserTestCase):
 
         response = self.put(
             edit_link,
-            data={"post": "This is test response, @%s and @%s!" % (user_a, user_b)},
+            data={"post": "This is test response, @%s and @%s!" % (user_1, user_2)},
         )
         self.assertEqual(response.status_code, 200)
 
         self.assertEqual(post.mentions.count(), 2)
-        self.assertEqual(list(post.mentions.order_by("id")), [user_a, user_b])
+        self.assertEqual(list(post.mentions.order_by("id")), [user_1, user_2])
 
         # remove first mention from post - should preserve mentions
         response = self.put(
-            edit_link, data={"post": "This is test response, @%s!" % user_b}
+            edit_link, data={"post": "This is test response, @%s!" % user_2}
         )
         self.assertEqual(response.status_code, 200)
 
         self.assertEqual(post.mentions.count(), 2)
-        self.assertEqual(list(post.mentions.order_by("id")), [user_a, user_b])
+        self.assertEqual(list(post.mentions.order_by("id")), [user_1, user_2])
 
         # remove mentions from post - should preserve mentions
         response = self.put(edit_link, data={"post": "This is test response!"})
         self.assertEqual(response.status_code, 200)
 
         self.assertEqual(post.mentions.count(), 2)
-        self.assertEqual(list(post.mentions.order_by("id")), [user_a, user_b])
+        self.assertEqual(list(post.mentions.order_by("id")), [user_1, user_2])
 
     def test_mentions_merge(self):
         """posts merge sums mentions"""
-        user_a = User.objects.create_user("Mention", "mention@test.com", "pass123")
-        user_b = User.objects.create_user("MentionB", "mentionb@test.com", "pass123")
+        user_1 = create_test_user("User1", "user1@example.com")
+        user_2 = create_test_user("User2", "user2@example.com")
 
         response = self.client.post(
-            self.post_link, data={"post": "This is test response, @%s!" % user_a}
+            self.post_link, data={"post": "This is test response, @%s!" % user_1}
         )
         self.assertEqual(response.status_code, 200)
 
         post_a = self.user.post_set.order_by("id").last()
 
         self.assertEqual(post_a.mentions.count(), 1)
-        self.assertEqual(list(post_a.mentions.all()), [user_a])
+        self.assertEqual(list(post_a.mentions.all()), [user_1])
 
         # post second reply
         self.user.last_post_on = None
@@ -147,7 +140,7 @@ class PostMentionsTests(AuthenticatedUserTestCase):
 
         response = self.client.post(
             self.post_link,
-            data={"post": "This is test response, @%s and @%s!" % (user_a, user_b)},
+            data={"post": "This is test response, @%s and @%s!" % (user_1, user_2)},
         )
         self.assertEqual(response.status_code, 200)
 
@@ -157,4 +150,4 @@ class PostMentionsTests(AuthenticatedUserTestCase):
         post_b.merge(post_a)
 
         self.assertEqual(post_a.mentions.count(), 2)
-        self.assertEqual(list(post_a.mentions.order_by("id")), [user_a, user_b])
+        self.assertEqual(list(post_a.mentions.order_by("id")), [user_1, user_2])

+ 3 - 6
misago/threads/tests/test_post_model.py

@@ -1,20 +1,17 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
 from misago.categories.models import Category
 from misago.threads.checksums import update_post_checksum
 from misago.threads.models import Post, Thread
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class PostModelTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@bob.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com")
 
         datetime = timezone.now()
 
@@ -57,7 +54,7 @@ class PostModelTests(TestCase):
         with self.assertRaises(ValueError):
             self.post.merge(self.post)
 
-        other_user = User.objects.create_user("Jeff", "Je@ff.com", "Pass.123")
+        other_user = create_test_user("OtherUser", "otheruser@example.com")
 
         other_thread = Thread.objects.create(
             category=self.category,

+ 60 - 54
misago/threads/tests/test_privatethread_patch_api.py

@@ -1,17 +1,15 @@
 import json
 
-from django.contrib.auth import get_user_model
 from django.core import mail
 
 from misago.acl.test import patch_user_acl
 from misago.threads import testutils
 from misago.threads.test import other_user_cant_use_private_threads
 from misago.threads.models import Thread, ThreadParticipant
+from misago.users.testutils import create_test_user
 
 from .test_privatethreads import PrivateThreadsTestCase
 
-User = get_user_model()
-
 
 class PrivateThreadPatchApiTestCase(PrivateThreadsTestCase):
     def setUp(self):
@@ -20,9 +18,7 @@ class PrivateThreadPatchApiTestCase(PrivateThreadsTestCase):
         self.thread = testutils.post_thread(self.category, poster=self.user)
         self.api_link = self.thread.get_api_url()
 
-        self.other_user = User.objects.create_user(
-            "BobBoberson", "bob@boberson.com", "pass123"
-        )
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
 
     def patch(self, api_link, ops):
         return self.client.patch(
@@ -109,7 +105,7 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertEqual(response.status_code, 400)
         self.assertEqual(
             response.json(),
-            {"id": self.thread.pk, "detail": ["BobBoberson is blocking you."]},
+            {"id": self.thread.pk, "detail": ["OtherUser is blocking you."]},
         )
 
     @patch_user_acl(other_user_cant_use_private_threads)
@@ -126,7 +122,7 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
             response.json(),
             {
                 "id": self.thread.pk,
-                "detail": ["BobBoberson can't participate in private threads."],
+                "detail": ["OtherUser can't participate in private threads."],
             },
         )
 
@@ -136,9 +132,7 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         ThreadParticipant.objects.set_owner(self.thread, self.user)
 
         for i in range(3):
-            user = User.objects.create_user(
-                "User%s" % i, "user%s@example.com" % i, "Pass.123"
-            )
+            user = create_test_user("User%s" % i, "user%s@example.com" % i)
             ThreadParticipant.objects.add_participants(self.thread, [user])
 
         response = self.patch(
@@ -350,10 +344,11 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.event_type, "participant_left")
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # user was removed from participation
         self.assertEqual(self.thread.participants.count(), 1)
@@ -387,10 +382,11 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.event_type, "participant_left")
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # user was removed from participation
         self.assertEqual(self.thread.participants.count(), 1)
@@ -399,7 +395,7 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
     @patch_user_acl({"can_moderate_private_threads": True})
     def test_moderator_remove_user(self):
         """api allows moderator to remove other user"""
-        removed_user = User.objects.create_user("Vigilante", "test@test.com", "pass123")
+        removed_user = create_test_user("RemovedUser", "removeduser@example.com")
 
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.add_participants(
@@ -423,13 +419,14 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.event_type, "participant_removed")
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
-        self.assertTrue(
-            User.objects.get(pk=removed_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
+
+        removed_user.refresh_from_db()
+        self.assertTrue(removed_user.sync_unread_private_threads)
 
         # user was removed from participation
         self.assertEqual(self.thread.participants.count(), 2)
@@ -457,10 +454,11 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.event_type, "participant_removed")
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # user was removed from participation
         self.assertEqual(self.thread.participants.count(), 1)
@@ -490,10 +488,11 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
         self.assertTrue(event.event_type, "owner_left")
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # user was removed from participation
         self.assertEqual(self.thread.participants.count(), 1)
@@ -516,7 +515,8 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
             Thread.objects.get(pk=self.thread.pk)
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.sync_unread_private_threads)
 
 
 class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
@@ -627,10 +627,11 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertEqual(response.status_code, 200)
 
         # valid users were flagged for sync
-        self.assertFalse(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertFalse(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # ownership was transfered
         self.assertEqual(self.thread.participants.count(), 2)
@@ -645,7 +646,7 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
     @patch_user_acl({"can_moderate_private_threads": True})
     def test_moderator_change_owner(self):
         """moderator can change thread owner to other user"""
-        new_owner = User.objects.create_user("NewOwner", "new@owner.com", "pass123")
+        new_owner = create_test_user("NewOwner", "newowner@example.com")
 
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.add_participants(self.thread, [self.user, new_owner])
@@ -657,11 +658,14 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertEqual(response.status_code, 200)
 
         # valid users were flagged for sync
-        self.assertTrue(User.objects.get(pk=new_owner.pk).sync_unread_private_threads)
-        self.assertFalse(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        new_owner.refresh_from_db()
+        self.assertTrue(new_owner.sync_unread_private_threads)
+
+        self.user.refresh_from_db()
+        self.assertFalse(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # ownership was transferred
         self.assertEqual(self.thread.participants.count(), 3)
@@ -687,10 +691,11 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertEqual(response.status_code, 200)
 
         # valid users were flagged for sync
-        self.assertFalse(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertFalse(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # ownership was transfered
         self.assertEqual(self.thread.participants.count(), 2)
@@ -718,10 +723,11 @@ class PrivateThreadTakeOverApiTests(PrivateThreadPatchApiTestCase):
         self.assertEqual(response.status_code, 200)
 
         # valid users were flagged for sync
-        self.assertFalse(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
-        self.assertTrue(
-            User.objects.get(pk=self.other_user.pk).sync_unread_private_threads
-        )
+        self.user.refresh_from_db()
+        self.assertFalse(self.user.sync_unread_private_threads)
+
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.sync_unread_private_threads)
 
         # ownership was transferred
         self.assertEqual(self.thread.participants.count(), 2)

+ 2 - 8
misago/threads/tests/test_privatethread_reply_api.py

@@ -1,14 +1,10 @@
-from django.contrib.auth import get_user_model
-
 from misago.threads import testutils
 from misago.threads.models import ThreadParticipant
+from misago.users.testutils import create_test_user
 
 from .test_privatethreads import PrivateThreadsTestCase
 
 
-User = get_user_model()
-
-
 class PrivateThreadReplyApiTestCase(PrivateThreadsTestCase):
     def setUp(self):
         super().setUp()
@@ -16,9 +12,7 @@ class PrivateThreadReplyApiTestCase(PrivateThreadsTestCase):
         self.thread = testutils.post_thread(self.category, poster=self.user)
         self.api_link = self.thread.get_posts_api_url()
 
-        self.other_user = User.objects.create_user(
-            "BobBoberson", "bob@boberson.com", "pass123"
-        )
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
 
     def test_reply_private_thread(self):
         """api sets other private thread participants sync thread flag"""

+ 2 - 7
misago/threads/tests/test_privatethread_start_api.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.core import mail
 from django.urls import reverse
 from django.utils.encoding import smart_str
@@ -7,9 +6,7 @@ from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.threads.models import ThreadParticipant
 from misago.threads.test import other_user_cant_use_private_threads
-from misago.users.testutils import AuthenticatedUserTestCase
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class StartPrivateThreadTests(AuthenticatedUserTestCase):
@@ -19,9 +16,7 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
         self.category = Category.objects.private_threads()
         self.api_link = reverse("misago:api:private-thread-list")
 
-        self.other_user = User.objects.create_user(
-            "BobBoberson", "bob@boberson.com", "pass123"
-        )
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
 
     def test_cant_start_thread_as_guest(self):
         """user has to be authenticated to be able to post private thread"""

+ 2 - 5
misago/threads/tests/test_subscriptions.py

@@ -1,6 +1,5 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -8,9 +7,7 @@ from misago.categories.models import Category
 from misago.threads import testutils
 from misago.threads.subscriptions import make_subscription_aware
 from misago.users.models import AnonymousUser
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class SubscriptionsTests(TestCase):
@@ -18,8 +15,8 @@ class SubscriptionsTests(TestCase):
         self.category = list(Category.objects.all_categories()[:1])[0]
         self.thread = self.post_thread(timezone.now() - timedelta(days=10))
 
-        self.user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
         self.anon = AnonymousUser()
+        self.user = create_test_user("User", "user@example.com")
 
     def post_thread(self, datetime):
         return testutils.post_thread(category=self.category, started_on=datetime)

+ 2 - 9
misago/threads/tests/test_sync_unread_private_threads.py

@@ -1,22 +1,15 @@
-from django.contrib.auth import get_user_model
-
 from misago.threads import testutils
 from misago.threads.models import ThreadParticipant
+from misago.users.testutils import create_test_user
 
 from .test_privatethreads import PrivateThreadsTestCase
 
 
-User = get_user_model()
-
-
 class SyncUnreadPrivateThreadsTestCase(PrivateThreadsTestCase):
     def setUp(self):
         super().setUp()
 
-        self.other_user = User.objects.create_user(
-            "BobBoberson", "bob@boberson.com", "pass123"
-        )
-
+        self.other_user = create_test_user("OtherUser", "user@example.com")
         self.thread = testutils.post_thread(self.category, poster=self.user)
 
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)

+ 11 - 14
misago/threads/tests/test_thread_model.py

@@ -1,15 +1,12 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
 from misago.categories.models import Category
 from misago.threads import testutils
 from misago.threads.models import Poll, Post, Thread, ThreadParticipant
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class ThreadModelTests(TestCase):
@@ -46,7 +43,7 @@ class ThreadModelTests(TestCase):
 
     def test_synchronize(self):
         """synchronize method updates thread data to reflect its contents"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         self.assertEqual(self.thread.replies, 0)
 
@@ -226,7 +223,7 @@ class ThreadModelTests(TestCase):
 
     def test_set_first_post(self):
         """set_first_post sets first post and poster data on thread"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         datetime = timezone.now() + timedelta(5)
 
@@ -251,7 +248,7 @@ class ThreadModelTests(TestCase):
 
     def test_set_last_post(self):
         """set_last_post sets first post and poster data on thread"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         datetime = timezone.now() + timedelta(5)
 
@@ -276,7 +273,7 @@ class ThreadModelTests(TestCase):
 
     def test_set_best_answer(self):
         """set_best_answer sets best answer and setter data on thread"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         best_answer = Post.objects.create(
             category=self.category,
@@ -318,7 +315,7 @@ class ThreadModelTests(TestCase):
 
     def test_set_invalid_best_answer(self):
         """set_best_answer implements some assertions for data integrity"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         other_thread = testutils.post_thread(self.category)
         with self.assertRaises(ValueError):
@@ -398,15 +395,15 @@ class ThreadModelTests(TestCase):
         private thread gets deleted automatically
         when there are no participants left in it
         """
-        user_a = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
-        user_b = User.objects.create_user("Weebl", "weebl@weeblson.com", "Pass.123")
+        user_1 = create_test_user("User1", "user1@example.com")
+        user_2 = create_test_user("User2", "user2@example.com")
 
-        ThreadParticipant.objects.add_participants(self.thread, [user_a, user_b])
+        ThreadParticipant.objects.add_participants(self.thread, [user_1, user_2])
         self.assertEqual(self.thread.participants.count(), 2)
 
-        user_a.delete()
+        user_1.delete()
         Thread.objects.get(id=self.thread.id)
 
-        user_b.delete()
+        user_2.delete()
         with self.assertRaises(Thread.DoesNotExist):
             Thread.objects.get(id=self.thread.id)

+ 7 - 10
misago/threads/tests/test_threadparticipant_model.py

@@ -1,12 +1,9 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
 from misago.categories.models import Category
 from misago.threads.models import Post, Thread, ThreadParticipant
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class ThreadParticipantTests(TestCase):
@@ -44,8 +41,8 @@ class ThreadParticipantTests(TestCase):
 
     def test_set_owner(self):
         """set_owner makes user thread owner"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
-        other_user = User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
+        other_user = create_test_user("User2", "user2@example.com")
 
         ThreadParticipant.objects.set_owner(self.thread, user)
         self.assertEqual(self.thread.participants.count(), 1)
@@ -66,8 +63,8 @@ class ThreadParticipantTests(TestCase):
     def test_add_participants(self):
         """add_participant adds participant to thread"""
         users = [
-            User.objects.create_user("Bob", "bob@boberson.com", "Pass.123"),
-            User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123"),
+            create_test_user("User", "user@example.com"),
+            create_test_user("User2", "user2@example.com"),
         ]
 
         ThreadParticipant.objects.add_participants(self.thread, users)
@@ -79,8 +76,8 @@ class ThreadParticipantTests(TestCase):
 
     def test_remove_participant(self):
         """remove_participant deletes participant from thread"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
-        other_user = User.objects.create_user("Bob2", "bob2@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
+        other_user = create_test_user("User2", "user2@example.com")
 
         ThreadParticipant.objects.add_participants(self.thread, [user])
         ThreadParticipant.objects.add_participants(self.thread, [other_user])

+ 5 - 13
misago/users/tests/test_activepostersranking.py

@@ -1,6 +1,5 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.utils import timezone
 
 from misago.categories.models import Category
@@ -9,10 +8,7 @@ from misago.users.activepostersranking import (
     build_active_posters_ranking,
     get_active_posters_ranking,
 )
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class TestActivePostersRanking(AuthenticatedUserTestCase):
@@ -30,15 +26,13 @@ class TestActivePostersRanking(AuthenticatedUserTestCase):
         self.assertEqual(empty_ranking["users_count"], 0)
 
         # other user that will be posting
-        other_user = User.objects.create_user("OtherUser", "other@user.com", "pass123")
+        other_user = create_test_user("OtherUser", "otheruser@example.com")
 
         # lurker user that won't post anything
-        User.objects.create_user("Lurker", "lurker@user.com", "pass123")
+        create_test_user("Lurker", "lurker@example.com")
 
         # unranked user that posted something 400 days ago
-        unranked_user = User.objects.create_user(
-            "UnrankedUser", "unranked@user.com", "pass123"
-        )
+        unranked_user = create_test_user("UnrankedUser", "unranked@example.com")
 
         started_on = timezone.now() - timedelta(days=400)
         post_thread(self.category, poster=unranked_user, started_on=started_on)
@@ -66,9 +60,7 @@ class TestActivePostersRanking(AuthenticatedUserTestCase):
         self.assertEqual(ranking["users"][1].score, 1)
 
         # disabled users are not ranked
-        disabled = User.objects.create_user(
-            "DisabledUser", "disabled@user.com", "pass123"
-        )
+        disabled = create_test_user("DisabledUser", "disableduser@example.com")
 
         disabled.is_active = False
         disabled.save()

+ 4 - 5
misago/users/tests/test_audittrail.py

@@ -6,8 +6,7 @@ from django.utils import timezone
 from misago.users.audittrail import create_audit_trail, create_user_audit_trail
 from misago.users.models import AuditTrail
 from misago.users.signals import remove_old_ips
-from misago.users.testutils import UserTestCase
-
+from misago.users.testutils import UserTestCase, create_test_user
 
 User = get_user_model()
 
@@ -25,7 +24,7 @@ class CreateAuditTrailTests(UserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.obj = User.objects.create_user("BobBoberson", "bob@example.com")
+        self.obj = create_test_user("OtherUser", "user@example.com")
 
     def test_create_audit_require_model(self):
         """create_audit_trail requires model instance"""
@@ -97,7 +96,7 @@ class CreateUserAuditTrailTests(UserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.obj = User.objects.create_user("BobBoberson", "bob@example.com")
+        self.obj = create_test_user("OtherUser", "user@example.com")
 
     def test_create_user_audit_require_model(self):
         """create_user_audit_trail requires model instance"""
@@ -163,7 +162,7 @@ class RemoveOldAuditTrailsTest(UserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.obj = User.objects.create_user("BobBoberson", "bob@example.com")
+        self.obj = create_test_user("OtherUser", "user@example.com")
 
     def test_recent_audit_trail_is_kept(self):
         """remove_old_ips keeps recent audit trails"""

+ 36 - 49
misago/users/tests/test_auth_api.py

@@ -3,12 +3,10 @@ from django.core import mail
 from django.test import TestCase
 
 from misago.users.models import Ban
+from misago.users.testutils import create_test_user
 from misago.users.tokens import make_password_change_token
 
 
-User = get_user_model()
-
-
 class GatewayTests(TestCase):
     def test_api_invalid_credentials(self):
         """login api returns 400 on invalid POST"""
@@ -29,12 +27,11 @@ class GatewayTests(TestCase):
 
     def test_login(self):
         """api signs user in"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user("User", "user@example.com", "password")
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
-
         self.assertEqual(response.status_code, 200)
 
         response = self.client.get("/api/auth/")
@@ -46,18 +43,16 @@ class GatewayTests(TestCase):
 
     def test_login_whitespaces_password(self):
         """api signs user in with password left untouched"""
-        user = User.objects.create_user("Bob", "bob@test.com", " Pass.123 ")
+        user = create_test_user("User", "user@example.com", " password ")
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
-
         self.assertEqual(response.status_code, 400)
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": " Pass.123 "}
+            "/api/auth/", data={"username": "User", "password": " password "}
         )
-
         self.assertEqual(response.status_code, 200)
 
         response = self.client.get("/api/auth/")
@@ -92,10 +87,10 @@ class GatewayTests(TestCase):
 
     def test_login_not_usable_password(self):
         """login api fails to sign user with not-usable password in"""
-        User.objects.create_user("Bob", "bob@test.com")
+        create_test_user("User", "user@example.com")
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(
@@ -105,16 +100,16 @@ class GatewayTests(TestCase):
 
     def test_login_banned(self):
         """login api fails to sign banned user in"""
-        User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        create_test_user("User", "user@example.com", "password")
 
         ban = Ban.objects.create(
             check_type=Ban.USERNAME,
-            banned_value="bob",
+            banned_value="user",
             user_message="You are tragically banned.",
         )
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 400)
 
@@ -133,19 +128,18 @@ class GatewayTests(TestCase):
 
     def test_login_banned_staff(self):
         """login api signs banned staff member in"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
-
+        user = create_test_user("User", "user@example.com", "password")
         user.is_staff = True
         user.save()
 
         Ban.objects.create(
             check_type=Ban.USERNAME,
-            banned_value="bob",
+            banned_value="user",
             user_message="You are tragically banned.",
         )
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 200)
 
@@ -158,14 +152,14 @@ class GatewayTests(TestCase):
 
     def test_login_ban_registration_only(self):
         """login api ignores registration-only bans"""
-        user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user("User", "user@example.com", "password")
 
         Ban.objects.create(
-            check_type=Ban.USERNAME, banned_value="bob", registration_only=True
+            check_type=Ban.USERNAME, banned_value="user", registration_only=True
         )
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 200)
 
@@ -178,12 +172,10 @@ class GatewayTests(TestCase):
 
     def test_login_inactive_admin(self):
         """login api fails to sign admin-activated user in"""
-        User.objects.create_user(
-            "Bob", "bob@test.com", "Pass.123", requires_activation=1
-        )
+        create_test_user("User", "user@example.com", "password", requires_activation=1)
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 400)
 
@@ -198,12 +190,10 @@ class GatewayTests(TestCase):
 
     def test_login_inactive_user(self):
         """login api fails to sign user-activated user in"""
-        User.objects.create_user(
-            "Bob", "bob@test.com", "Pass.123", requires_activation=2
-        )
+        create_test_user("User", "user@example.com", "password", requires_activation=2)
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 400)
 
@@ -218,15 +208,12 @@ class GatewayTests(TestCase):
 
     def test_login_disabled_user(self):
         """its impossible to sign in to disabled account"""
-        user = User.objects.create_user(
-            "Bob", "bob@test.com", "Pass.123", is_active=False
-        )
-
+        user = create_test_user("User", "user@example.com", "password", is_active=False)
         user.is_staff = True
         user.save()
 
         response = self.client.post(
-            "/api/auth/", data={"username": "Bob", "password": "Pass.123"}
+            "/api/auth/", data={"username": "User", "password": "password"}
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(
@@ -250,7 +237,7 @@ class UserCredentialsTests(TestCase):
 
 class SendActivationApiTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com", "password")
         self.user.requires_activation = 1
         self.user.save()
 
@@ -261,7 +248,7 @@ class SendActivationApiTests(TestCase):
         response = self.client.post(self.link, data={"email": self.user.email})
         self.assertEqual(response.status_code, 200)
 
-        self.assertIn("Activate Bob", mail.outbox[0].subject)
+        self.assertIn("Activate User", mail.outbox[0].subject)
 
     def test_submit_banned(self):
         """request activation link api passes for banned users"""
@@ -274,7 +261,7 @@ class SendActivationApiTests(TestCase):
         response = self.client.post(self.link, data={"email": self.user.email})
         self.assertEqual(response.status_code, 200)
 
-        self.assertIn("Activate Bob", mail.outbox[0].subject)
+        self.assertIn("Activate User", mail.outbox[0].subject)
 
     def test_submit_disabled(self):
         """request activation link api fails disabled users"""
@@ -335,7 +322,7 @@ class SendActivationApiTests(TestCase):
             response.json(),
             {
                 "code": "already_active",
-                "detail": "Bob, your account is already active.",
+                "detail": "User, your account is already active.",
             },
         )
 
@@ -350,7 +337,7 @@ class SendActivationApiTests(TestCase):
             response.json(),
             {
                 "code": "inactive_admin",
-                "detail": "Bob, only administrator may activate your account.",
+                "detail": "User, only administrator may activate your account.",
             },
         )
 
@@ -368,7 +355,7 @@ class SendActivationApiTests(TestCase):
 
 class SendPasswordFormApiTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com", "password")
 
         self.link = "/api/auth/send-password-form/"
 
@@ -377,7 +364,7 @@ class SendPasswordFormApiTests(TestCase):
         response = self.client.post(self.link, data={"email": self.user.email})
         self.assertEqual(response.status_code, 200)
 
-        self.assertIn("Change Bob password", mail.outbox[0].subject)
+        self.assertIn("Change User password", mail.outbox[0].subject)
 
     def test_submit_banned(self):
         """request change password form link api sends reset link mail"""
@@ -390,7 +377,7 @@ class SendPasswordFormApiTests(TestCase):
         response = self.client.post(self.link, data={"email": self.user.email})
         self.assertEqual(response.status_code, 200)
 
-        self.assertIn("Change Bob password", mail.outbox[0].subject)
+        self.assertIn("Change User password", mail.outbox[0].subject)
 
     def test_submit_disabled(self):
         """request change password form api fails disabled users"""
@@ -479,7 +466,7 @@ class SendPasswordFormApiTests(TestCase):
 
 class ChangePasswordApiTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        self.user = create_test_user("User", "user@example.com", "password")
 
         self.link = "/api/auth/change-password/%s/%s/"
 
@@ -491,8 +478,8 @@ class ChangePasswordApiTests(TestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        user = User.objects.get(id=self.user.pk)
-        self.assertTrue(user.check_password("n3wp4ss!"))
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.check_password("n3wp4ss!"))
 
     def test_submit_with_whitespaces(self):
         """submit change password form api changes password with whitespaces"""
@@ -502,8 +489,8 @@ class ChangePasswordApiTests(TestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        user = User.objects.get(id=self.user.pk)
-        self.assertTrue(user.check_password(" n3wp4ss! "))
+        self.user.refresh_from_db()
+        self.assertTrue(self.user.check_password(" n3wp4ss! "))
 
     def test_submit_invalid_data(self):
         """login api errors for invalid data"""

+ 3 - 7
misago/users/tests/test_auth_backend.py

@@ -2,19 +2,15 @@ from django.contrib.auth import get_user_model
 from django.test import TestCase
 
 from misago.users.authbackends import MisagoBackend
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 backend = MisagoBackend()
 
 
 class MisagoBackendTests(TestCase):
     def setUp(self):
-        self.password = "Pass.123"
-        self.user = User.objects.create_user(
-            "BobBoberson", "bob@test.com", self.password
-        )
+        self.password = "password"
+        self.user = create_test_user("User", "user@example.com", self.password)
 
     def test_authenticate_username(self):
         """auth authenticates with username"""

+ 24 - 0
misago/users/tests/test_avatar_filter.py

@@ -0,0 +1,24 @@
+import pytest
+
+from misago.users.templatetags.misago_avatars import avatar
+
+
+@pytest.fixture
+def avatars(user):
+    return {i["size"]: i["url"] for i in user.avatars}
+
+
+def test_filter_returns_url_to_200_size_image(user, avatars):
+    assert avatar(user) == avatars[200]
+
+
+def test_filter_returns_url_to_next_largest_image_for_given_size(user, avatars):
+    assert avatar(user, 250) == avatars[400]
+    assert avatar(user, 150) == avatars[200]
+    assert avatar(user, 50) == avatars[100]
+
+
+def test_filter_returns_url_largest_image_if_requested_size_is_not_available(
+    user, avatars
+):
+    assert avatar(user, 500) == avatars[400]

+ 6 - 8
misago/users/tests/test_avatars.py

@@ -3,7 +3,6 @@ from unittest.mock import Mock
 
 from PIL import Image
 
-from django.contrib.auth import get_user_model
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 from django.utils.crypto import get_random_string
@@ -18,20 +17,19 @@ from misago.users.avatars import (
     uploaded,
 )
 from misago.users.models import Avatar, AvatarGallery
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class AvatarsStoreTests(TestCase):
     def test_store(self):
         """store successfully stores and deletes avatar"""
-        user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        user = create_test_user("User", "user@example.com")
 
         test_image = Image.new("RGBA", (100, 100), 0)
         store.store_new_avatar(user, test_image)
 
         # reload user
-        User.objects.get(pk=user.pk)
+        user.refresh_from_db()
 
         # assert that avatars were stored in media
         avatars_dict = {}
@@ -92,8 +90,7 @@ class AvatarsStoreTests(TestCase):
 
 class AvatarSetterTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "kontakt@rpiton.com", "pass123")
-
+        user = create_test_user("User", "user@example.com")
         self.user.avatars = None
         self.user.save()
 
@@ -101,7 +98,8 @@ class AvatarSetterTests(TestCase):
         store.delete_avatar(self.user)
 
     def get_current_user(self):
-        return User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
+        return self.user
 
     def assertNoAvatarIsSet(self):
         user = self.get_current_user()

+ 2 - 13
misago/users/tests/test_avatarserver_views.py

@@ -1,24 +1,13 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.urls import reverse
 
 from misago.conf import settings
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class AvatarServerTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@bob.com", "Pass123")
-
-        self.user.avatars = [
-            {"size": 200, "url": "/media/avatars/avatar-200.png"},
-            {"size": 100, "url": "/media/avatars/avatar-100.png"},
-            {"size": 50, "url": "/media/avatars/avatar-50.png"},
-        ]
-
-        self.user.save()
+        self.user = create_test_user("User", "User@example.com")
 
     def test_get_user_avatar_exact_size(self):
         """avatar server resolved valid avatar url for user"""

+ 9 - 9
misago/users/tests/test_bans.py

@@ -1,6 +1,5 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.utils import timezone
 
@@ -16,8 +15,7 @@ from misago.users.bans import (
 )
 from misago.users.constants import BANS_CACHE
 from misago.users.models import Ban
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 cache_versions = get_cache_versions()
 
@@ -126,7 +124,7 @@ class GetBanTests(TestCase):
 
 class UserBansTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@boberson.com", "pass123")
+        self.user = create_test_user("User", "user@example.com")
 
     def test_no_ban(self):
         """user is not caught by ban"""
@@ -136,7 +134,9 @@ class UserBansTests(TestCase):
     def test_permanent_ban(self):
         """user is caught by permanent ban"""
         Ban.objects.create(
-            banned_value="bob", user_message="User reason", staff_message="Staff reason"
+            banned_value="User",
+            user_message="User reason",
+            staff_message="Staff reason",
         )
 
         user_ban = get_user_ban(self.user, cache_versions)
@@ -148,7 +148,7 @@ class UserBansTests(TestCase):
     def test_temporary_ban(self):
         """user is caught by temporary ban"""
         Ban.objects.create(
-            banned_value="bo*",
+            banned_value="us*",
             user_message="User reason",
             staff_message="Staff reason",
             expires_on=timezone.now() + timedelta(days=7),
@@ -163,7 +163,7 @@ class UserBansTests(TestCase):
     def test_expired_ban(self):
         """user is not caught by expired ban"""
         Ban.objects.create(
-            banned_value="bo*", expires_on=timezone.now() - timedelta(days=7)
+            banned_value="us*", expires_on=timezone.now() - timedelta(days=7)
         )
 
         self.assertIsNone(get_user_ban(self.user, cache_versions))
@@ -172,7 +172,7 @@ class UserBansTests(TestCase):
     def test_expired_non_flagged_ban(self):
         """user is not caught by expired but checked ban"""
         Ban.objects.create(
-            banned_value="bo*", expires_on=timezone.now() - timedelta(days=7)
+            banned_value="us*", expires_on=timezone.now() - timedelta(days=7)
         )
         Ban.objects.update(is_checked=True)
 
@@ -243,7 +243,7 @@ class RequestIPBansTests(TestCase):
 class BanUserTests(TestCase):
     def test_ban_user(self):
         """ban_user utility bans user"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "pass123")
+        user = create_test_user("User", "user@example.com")
 
         ban = ban_user(user, "User reason", "Staff reason")
         self.assertEqual(ban.user_message, "User reason")

+ 8 - 11
misago/users/tests/test_credentialchange.py

@@ -1,10 +1,7 @@
-from django.contrib.auth import get_user_model
 from django.test import TestCase
 
 from misago.users import credentialchange
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class MockRequest(object):
@@ -15,26 +12,26 @@ class MockRequest(object):
 
 class CredentialChangeTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        self.user = create_test_user("User", "user@example.com")
 
     def test_valid_token_generation(self):
         """credentialchange module allows for store and read of change token"""
         request = MockRequest(self.user)
         token = credentialchange.store_new_credential(
-            request, "email", "newbob@test.com"
+            request, "email", "newmail@example.com"
         )
 
         email = credentialchange.read_new_credential(request, "email", token)
-        self.assertEqual(email, "newbob@test.com")
+        self.assertEqual(email, "newmail@example.com")
 
     def test_email_change_invalidated_token(self):
         """token is invalidated by email change"""
         request = MockRequest(self.user)
         token = credentialchange.store_new_credential(
-            request, "email", "newbob@test.com"
+            request, "email", "newmail@example.com"
         )
 
-        self.user.set_email("egebege@test.com")
+        self.user.set_email("otheremail@example.com")
         self.user.save()
 
         email = credentialchange.read_new_credential(request, "email", token)
@@ -44,7 +41,7 @@ class CredentialChangeTests(TestCase):
         """token is invalidated by password change"""
         request = MockRequest(self.user)
         token = credentialchange.store_new_credential(
-            request, "email", "newbob@test.com"
+            request, "email", "newmail@example.com"
         )
 
         self.user.set_password("Egebeg!123")
@@ -57,7 +54,7 @@ class CredentialChangeTests(TestCase):
         """there are no explosions in invalid tokens handling"""
         request = MockRequest(self.user)
         token = credentialchange.store_new_credential(
-            request, "email", "newbob@test.com"
+            request, "email", "newmail@example.com"
         )
 
         email = credentialchange.read_new_credential(request, "em4il", token)

+ 2 - 5
misago/users/tests/test_datadownloadsadmin_views.py

@@ -1,15 +1,12 @@
 import os
 
-from django.contrib.auth import get_user_model
 from django.core.files import File
 from django.urls import reverse
 
 from misago.admin.testutils import AdminTestCase
 from misago.users.datadownloads import request_user_data_download
 from misago.users.models import DataDownload
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_FILE_PATH = os.path.join(TESTFILES_DIR, "avatar.png")
@@ -87,7 +84,7 @@ class DataDownloadAdminViewsTests(AdminTestCase):
         response = self.client.get(reverse("misago:admin:users:data-downloads:request"))
         self.assertEqual(response.status_code, 200)
 
-        other_user = User.objects.create_user("bob", "bob@boberson.com")
+        other_user = create_test_user("OtherUser", "OtherUser@example.com")
 
         response = self.client.post(
             reverse("misago:admin:users:data-downloads:request"),

+ 8 - 8
misago/users/tests/test_deleteinactiveusers.py

@@ -7,14 +7,14 @@ from django.test import TestCase, override_settings
 from django.utils import timezone
 
 from misago.users.management.commands import deleteinactiveusers
-
+from misago.users.testutils import create_test_user
 
 User = get_user_model()
 
 
 class DeleteInactiveUsersTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        self.user = create_test_user("User", "user@example.com")
 
     @override_settings(MISAGO_DELETE_NEW_INACTIVE_USERS_OLDER_THAN_DAYS=2)
     def test_delete_user_activation_user(self):
@@ -30,7 +30,7 @@ class DeleteInactiveUsersTests(TestCase):
         self.assertEqual(command_output, "Deleted users: 1")
 
         with self.assertRaises(User.DoesNotExist):
-            User.objects.get(pk=self.user.pk)
+            self.user.refresh_from_db()
 
     @override_settings(MISAGO_DELETE_NEW_INACTIVE_USERS_OLDER_THAN_DAYS=2)
     def test_delete_user_activation_admin(self):
@@ -46,7 +46,7 @@ class DeleteInactiveUsersTests(TestCase):
         self.assertEqual(command_output, "Deleted users: 1")
 
         with self.assertRaises(User.DoesNotExist):
-            User.objects.get(pk=self.user.pk)
+            self.user.refresh_from_db()
 
     @override_settings(MISAGO_DELETE_NEW_INACTIVE_USERS_OLDER_THAN_DAYS=2)
     def test_skip_new_user_activation_user(self):
@@ -61,7 +61,7 @@ class DeleteInactiveUsersTests(TestCase):
 
         self.assertEqual(command_output, "Deleted users: 0")
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
 
     @override_settings(MISAGO_DELETE_NEW_INACTIVE_USERS_OLDER_THAN_DAYS=2)
     def test_skip_new_user_activation_admin(self):
@@ -76,7 +76,7 @@ class DeleteInactiveUsersTests(TestCase):
 
         self.assertEqual(command_output, "Deleted users: 0")
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
 
     @override_settings(MISAGO_DELETE_NEW_INACTIVE_USERS_OLDER_THAN_DAYS=2)
     def test_skip_active_user(self):
@@ -90,7 +90,7 @@ class DeleteInactiveUsersTests(TestCase):
 
         self.assertEqual(command_output, "Deleted users: 0")
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
 
     @override_settings(MISAGO_DELETE_NEW_INACTIVE_USERS_OLDER_THAN_DAYS=0)
     def test_delete_inactive_is_disabled(self):
@@ -108,4 +108,4 @@ class DeleteInactiveUsersTests(TestCase):
             "Automatic deletion of inactive users is currently disabled.",
         )
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()

+ 7 - 7
misago/users/tests/test_deletemarkedusers.py

@@ -5,14 +5,14 @@ from django.core.management import call_command
 from django.test import TestCase, override_settings
 
 from misago.users.management.commands import deletemarkedusers
-
+from misago.users.testutils import create_test_user
 
 User = get_user_model()
 
 
 class DeleteMarkedUsersTests(TestCase):
     def setUp(self):
-        self.user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        self.user = create_test_user("User", "user@example.com")
         self.user.mark_for_delete()
 
     def test_delete_marked_user(self):
@@ -24,7 +24,7 @@ class DeleteMarkedUsersTests(TestCase):
         self.assertEqual(command_output, "Deleted users: 1")
 
         with self.assertRaises(User.DoesNotExist):
-            User.objects.get(pk=self.user.pk)
+            self.user.refresh_from_db()
 
     @override_settings(MISAGO_ENABLE_DELETE_OWN_ACCOUNT=False)
     def test_delete_disabled(self):
@@ -36,7 +36,7 @@ class DeleteMarkedUsersTests(TestCase):
         self.assertEqual(command_output, "Deleted users: 1")
 
         with self.assertRaises(User.DoesNotExist):
-            User.objects.get(pk=self.user.pk)
+            self.user.refresh_from_db()
 
     def test_delete_not_marked(self):
         """user has to be marked to be deletable"""
@@ -49,7 +49,7 @@ class DeleteMarkedUsersTests(TestCase):
 
         self.assertEqual(command_output, "Deleted users: 0")
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
 
     def test_delete_is_staff(self):
         """staff users are extempt from deletion"""
@@ -62,7 +62,7 @@ class DeleteMarkedUsersTests(TestCase):
 
         self.assertEqual(command_output, "Deleted users: 0")
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
 
     def test_delete_superuser(self):
         """superusers are extempt from deletion"""
@@ -75,4 +75,4 @@ class DeleteMarkedUsersTests(TestCase):
 
         self.assertEqual(command_output, "Deleted users: 0")
 
-        User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()

+ 5 - 8
misago/users/tests/test_deleteprofilefield.py

@@ -1,13 +1,10 @@
 from io import StringIO
 
-from django.contrib.auth import get_user_model
 from django.core.management import call_command
 from django.test import TestCase
 
 from misago.users.management.commands import deleteprofilefield
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class DeleteProfileFieldTests(TestCase):
@@ -31,9 +28,9 @@ class DeleteProfileFieldTests(TestCase):
 
     def test_delete_fields(self):
         """utility has no showstoppers when no fields are set"""
-        user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
-        user.profile_fields = {"gender": "male", "bio": "Yup!"}
-        user.save()
+        user = create_test_user(
+            "User", "user@example.com", profile_fields={"gender": "male", "bio": "Yup!"}
+        )
 
         out = StringIO()
         call_command(deleteprofilefield.Command(), "gender", stdout=out)
@@ -43,5 +40,5 @@ class DeleteProfileFieldTests(TestCase):
             command_output, '"gender" profile field has been deleted from 1 users.'
         )
 
-        user = User.objects.get(pk=user.pk)
+        user.refresh_from_db()
         self.assertEqual(user.profile_fields, {"bio": "Yup!"})

+ 2 - 4
misago/users/tests/test_djangoadmin_user.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Permission
 from django.test import override_settings
 from django.urls import reverse
@@ -6,15 +5,14 @@ from django.utils import formats
 
 from misago.admin.testutils import AdminTestCase
 from misago.users.djangoadmin import UserAdminModel
+from misago.users.testutils import create_test_user
 
 
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")
 class TestDjangoAdminUserForm(AdminTestCase):
     def setUp(self):
         super().setUp()
-        self.test_user = get_user_model().objects.create_user(
-            username="Bob", email="bob@test.com", password="Pass.123"
-        )
+        self.test_user = create_test_user("OtherUser", "otheruser@example.com")
         self.edit_test_user_in_django_url = reverse(
             "admin:misago_users_user_change", args=[self.test_user.pk]
         )

+ 23 - 19
misago/users/tests/test_forgottenpassword_views.py

@@ -1,15 +1,11 @@
-from django.contrib.auth import get_user_model
 from django.urls import reverse
 
 from misago.core.utils import encode_json_html
 from misago.users.models import Ban
-from misago.users.testutils import UserTestCase
+from misago.users.testutils import UserTestCase, create_test_user
 from misago.users.tokens import make_password_change_token
 
 
-User = get_user_model()
-
-
 class ForgottenPasswordViewsTests(UserTestCase):
     def test_guest_request_view_returns_200(self):
         """request new password view returns 200 for guests"""
@@ -37,74 +33,82 @@ class ForgottenPasswordViewsTests(UserTestCase):
 
     def test_change_password_on_banned(self):
         """change banned user password errors"""
-        test_user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user(
+            "OtherUser", "otheruser@example.com", self.USER_PASSWORD
+        )
 
         Ban.objects.create(
             check_type=Ban.USERNAME, banned_value="bob", user_message="Nope!"
         )
 
-        password_token = make_password_change_token(test_user)
+        password_token = make_password_change_token(user)
 
         response = self.client.get(
             reverse(
                 "misago:forgotten-password-change-form",
-                kwargs={"pk": test_user.pk, "token": password_token},
+                kwargs={"pk": user.pk, "token": password_token},
             )
         )
         self.assertContains(response, encode_json_html("<p>Nope!</p>"), status_code=403)
 
     def test_change_password_on_other_user(self):
         """change other user password errors"""
-        test_user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user(
+            "OtherUser", "otheruser@example.com", self.USER_PASSWORD
+        )
 
-        password_token = make_password_change_token(test_user)
+        password_token = make_password_change_token(user)
 
         self.login_user(self.get_authenticated_user())
 
         response = self.client.get(
             reverse(
                 "misago:forgotten-password-change-form",
-                kwargs={"pk": test_user.pk, "token": password_token},
+                kwargs={"pk": user.pk, "token": password_token},
             )
         )
         self.assertContains(response, "your link has expired", status_code=400)
 
     def test_change_password_invalid_token(self):
         """invalid form token errors"""
-        test_user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user(
+            "OtherUser", "otheruser@example.com", self.USER_PASSWORD
+        )
 
         response = self.client.get(
             reverse(
                 "misago:forgotten-password-change-form",
-                kwargs={"pk": test_user.pk, "token": "abcdfghqsads"},
+                kwargs={"pk": user.pk, "token": "abcdfghqsads"},
             )
         )
         self.assertContains(response, "your link is invalid", status_code=400)
 
     def test_change_password_form(self):
         """change user password form displays for valid token"""
-        test_user = User.objects.create_user("Bob", "bob@test.com", "Pass.123")
+        user = create_test_user(
+            "OtherUser", "otheruser@example.com", self.USER_PASSWORD
+        )
 
-        password_token = make_password_change_token(test_user)
+        password_token = make_password_change_token(user)
 
         response = self.client.get(
             reverse(
                 "misago:forgotten-password-change-form",
-                kwargs={"pk": test_user.pk, "token": password_token},
+                kwargs={"pk": user.pk, "token": password_token},
             )
         )
         self.assertContains(response, password_token)
 
     def test_change_password_unusable_password_form(self):
         """set user first password form displays for valid token"""
-        test_user = User.objects.create_user("Bob", "bob@test.com")
+        user = create_test_user("OtherUser", "otheruser@example.com")
 
-        password_token = make_password_change_token(test_user)
+        password_token = make_password_change_token(user)
 
         response = self.client.get(
             reverse(
                 "misago:forgotten-password-change-form",
-                kwargs={"pk": test_user.pk, "token": password_token},
+                kwargs={"pk": user.pk, "token": password_token},
             )
         )
         self.assertContains(response, password_token)

+ 2 - 6
misago/users/tests/test_getting_user_status.py

@@ -1,17 +1,13 @@
 from unittest.mock import Mock
 
-from django.contrib.auth import get_user_model
-
 from misago.users.online.utils import get_user_status
-from misago.users.testutils import AuthenticatedUserTestCase
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class GetUserStatusTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
-        self.other_user = User.objects.create_user("Tyrael", "t123@test.com", "pass123")
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
 
     def test_get_visible_user_status_returns_online(self):
         request = Mock(

+ 4 - 7
misago/users/tests/test_invalidatebans.py

@@ -1,7 +1,6 @@
 from datetime import timedelta
 from io import StringIO
 
-from django.contrib.auth import get_user_model
 from django.core.management import call_command
 from django.test import TestCase
 from django.utils import timezone
@@ -11,9 +10,7 @@ from misago.cache.versions import get_cache_versions
 from misago.users import bans
 from misago.users.management.commands import invalidatebans
 from misago.users.models import Ban, BanCache
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class InvalidateBansTests(TestCase):
@@ -39,10 +36,10 @@ class InvalidateBansTests(TestCase):
 
     def test_bans_caches_updates(self):
         """ban caches are updated"""
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
+        user = create_test_user("User", "user@example.com")
 
         # ban user
-        Ban.objects.create(banned_value="bob")
+        Ban.objects.create(banned_value="user")
         user_ban = bans.get_user_ban(user, get_cache_versions())
 
         self.assertIsNotNone(user_ban)
@@ -72,5 +69,5 @@ class InvalidateBansTests(TestCase):
         self.assertEqual(Ban.objects.filter(is_checked=True).count(), 0)
 
         # see if user is banned anymore
-        user = User.objects.get(id=user.id)
+        user.refresh_from_db()
         self.assertIsNone(bans.get_user_ban(user, get_cache_versions()))

+ 2 - 6
misago/users/tests/test_lists_views.py

@@ -75,9 +75,7 @@ class UsersRankTests(UsersListTestCase):
 
     def test_disabled_users(self):
         """ranks lists excludes disabled accounts"""
-        rank_user = create_test_user(
-            "Visible", "visible@te.com", "Pass.123", is_active=False
-        )
+        rank_user = create_test_user("Visible", "visible@te.com", is_active=False)
 
         for rank in Rank.objects.iterator():
             rank_user.rank = rank
@@ -97,9 +95,7 @@ class UsersRankTests(UsersListTestCase):
         self.user.is_staff = True
         self.user.save()
 
-        rank_user = create_test_user(
-            "Visible", "visible@te.com", "Pass.123", is_active=False
-        )
+        rank_user = create_test_user("Visible", "visible@te.com", is_active=False)
 
         for rank in Rank.objects.iterator():
             rank_user.rank = rank

+ 11 - 16
misago/users/tests/test_listusedprofilefields.py

@@ -1,19 +1,16 @@
 from io import StringIO
 
-from django.contrib.auth import get_user_model
 from django.core.management import call_command
 from django.test import TestCase
 
 from misago.users.management.commands import listusedprofilefields
-
-
-User = get_user_model()
+from misago.users.testutils import create_test_user
 
 
 class ListUsedProfileFieldsTests(TestCase):
     def test_no_fields_set(self):
         """utility has no showstoppers when no fields are set"""
-        User.objects.create_user("Bob", "bob@bob.com", "pass123")
+        create_test_user("User", "user@example.com")
 
         out = StringIO()
         call_command(listusedprofilefields.Command(), stdout=out)
@@ -23,17 +20,15 @@ class ListUsedProfileFieldsTests(TestCase):
 
     def test_fields_set(self):
         """utility lists number of users that have different fields set"""
-        user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
-        user.profile_fields = {"gender": "male", "bio": "Yup!"}
-        user.save()
-
-        user = User.objects.create_user("Bob2", "bob2@bob.com", "pass123")
-        user.profile_fields = {"gender": "male"}
-        user.save()
-
-        user = User.objects.create_user("Bob3", "bob3@bob.com", "pass123")
-        user.profile_fields = {"location": ""}
-        user.save()
+        create_test_user(
+            "User1",
+            "user1@example.com",
+            profile_fields={"gender": "male", "bio": "Yup!"},
+        )
+        create_test_user(
+            "User2", "user2@example.com", profile_fields={"gender": "male"}
+        )
+        create_test_user("User3", "user3@example.com", profile_fields={"location": ""})
 
         out = StringIO()
         call_command(listusedprofilefields.Command(), stdout=out)

+ 0 - 35
misago/users/tests/test_misagoavatars_tags.py

@@ -1,35 +0,0 @@
-from django.contrib.auth import get_user_model
-from django.template import Context, Template
-from django.test import TestCase
-
-
-User = get_user_model()
-
-
-class TemplateTagsTests(TestCase):
-    def test_user_avatar_filter(self):
-        """avatar filter returns url to avatar image"""
-        user = User.objects.create_user("Bob", "bob@test.com", "pass123")
-
-        user.avatars = [
-            {"size": 400, "url": "/avatar/400.png"},
-            {"size": 128, "url": "/avatar/400.png"},
-            {"size": 30, "url": "/avatar/30.png"},
-        ]
-
-        tpl_content = """
-{% load misago_avatars %}
-
-{{ user|avatar }}
-{{ user|avatar:100 }}
-{{ user|avatar:30 }}
-{{ user|avatar:10 }}
-"""
-
-        tpl = Template(tpl_content)
-        render = tpl.render(Context({"user": user})).strip().splitlines()
-
-        self.assertEqual(render[0].strip(), user.avatars[0]["url"])
-        self.assertEqual(render[1].strip(), user.avatars[1]["url"])
-        self.assertEqual(render[2].strip(), user.avatars[2]["url"])
-        self.assertEqual(render[3].strip(), user.avatars[2]["url"])

+ 41 - 57
misago/users/tests/test_namechanges.py

@@ -1,86 +1,70 @@
 from datetime import timedelta
 
-from django.contrib.auth import get_user_model
-from django.test import TestCase
-
 from misago.users.namechanges import (
     get_next_available_namechange,
     get_left_namechanges,
     get_username_options,
 )
 
-User = get_user_model()
 
+def test_user_without_permission_to_change_name_has_no_changes_left(user):
+    user_acl = {"name_changes_allowed": 0}
+    assert get_left_namechanges(user, user_acl) == 0
+
+
+def test_user_without_namechanges_has_all_changes_left(user):
+    user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
+    assert get_left_namechanges(user, user_acl) == 3
 
-class UsernameChangesTests(TestCase):
-    def test_user_without_permission_to_change_name_has_no_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 0}
-        assert get_left_namechanges(user, user_acl) == 0
 
-    def test_user_without_namechanges_has_all_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
-        assert get_left_namechanges(user, user_acl) == 3
+def test_user_own_namechanges_are_subtracted_from_changes_left(user):
+    user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
+    user.set_username("Changed")
+    assert get_left_namechanges(user, user_acl) == 2
 
-    def test_user_own_namechanges_are_subtracted_from_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
-        user.set_username("Changed")
 
-        assert get_left_namechanges(user, user_acl) == 2
+def test_user_own_recent_namechanges_subtract_from_changes_left(user):
+    user_acl = {"name_changes_allowed": 3, "name_changes_expire": 5}
+    user.set_username("Changed")
+    assert get_left_namechanges(user, user_acl) == 2
 
-    def test_user_own_recent_namechanges_subtract_from_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 3, "name_changes_expire": 5}
 
-        user.set_username("Changed")
+def test_user_own_expired_namechanges_dont_subtract_from_changes_left(user):
+    user_acl = {"name_changes_allowed": 3, "name_changes_expire": 5}
 
-        assert get_left_namechanges(user, user_acl) == 2
+    username_change = user.set_username("Changed")
+    username_change.changed_on -= timedelta(days=10)
+    username_change.save()
 
-    def test_user_own_expired_namechanges_dont_subtract_from_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 3, "name_changes_expire": 5}
+    assert get_left_namechanges(user, user_acl) == 3
 
-        username_change = user.set_username("Changed")
-        username_change.changed_on -= timedelta(days=10)
-        username_change.save()
 
-        assert get_left_namechanges(user, user_acl) == 3
+def test_user_namechanges_by_other_users_dont_subtract_from_changes_left(user):
+    user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
 
-    def test_user_namechanges_by_other_users_dont_subtract_from_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
+    username_change = user.set_username("Changed")
+    username_change.changed_by = None
+    username_change.save()
 
-        username_change = user.set_username("Changed")
-        username_change.changed_by = None
-        username_change.save()
+    assert get_left_namechanges(user, user_acl) == 3
 
-        assert get_left_namechanges(user, user_acl) == 3
 
-    def test_user_next_available_namechange_is_none_for_user_with_changes_left(self):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
+def test_user_next_available_namechange_is_none_for_user_with_changes_left(user):
+    user_acl = {"name_changes_allowed": 3, "name_changes_expire": 0}
+    assert get_next_available_namechange(user, user_acl, 3) is None
 
-        assert get_next_available_namechange(user, user_acl, 3) is None
 
-    def test_user_next_available_namechange_is_none_if_own_namechanges_dont_expire(
-        self
-    ):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 1, "name_changes_expire": 0}
-        user.set_username("Changed")
+def test_user_next_available_namechange_is_none_if_own_namechanges_dont_expire(user):
+    user_acl = {"name_changes_allowed": 1, "name_changes_expire": 0}
+    user.set_username("Changed")
+    assert get_next_available_namechange(user, user_acl, 0) is None
 
-        assert get_next_available_namechange(user, user_acl, 0) is None
 
-    def test_user_next_available_namechange_is_calculated_if_own_namechanges_expire(
-        self
-    ):
-        user = User.objects.create_user("User", "test@example.com")
-        user_acl = {"name_changes_allowed": 1, "name_changes_expire": 1}
+def test_user_next_available_namechange_is_calculated_if_own_namechanges_expire(user):
+    user_acl = {"name_changes_allowed": 1, "name_changes_expire": 1}
 
-        username_change = user.set_username("Changed")
-        next_change_on = get_next_available_namechange(user, user_acl, 0)
+    username_change = user.set_username("Changed")
+    next_change_on = get_next_available_namechange(user, user_acl, 0)
 
-        assert next_change_on
-        assert next_change_on == username_change.changed_on + timedelta(days=1)
+    assert next_change_on
+    assert next_change_on == username_change.changed_on + timedelta(days=1)

+ 53 - 62
misago/users/tests/test_new_user_setup.py

@@ -1,70 +1,61 @@
 from django.contrib.auth import get_user_model
-from django.test import TestCase
 
-from misago.cache.versions import get_cache_versions
-from misago.conf.dynamicsettings import DynamicSettings
 from misago.conf.test import override_dynamic_settings
-
 from misago.users.setupnewuser import set_default_subscription_options, setup_new_user
 
 User = get_user_model()
 
 
-class NewUserSetupTests(TestCase):
-    def test_default_avatar_is_set_for_user(self):
-        user = User.objects.create_user("User", "test@example.com")
-        cache_versions = get_cache_versions()
-        settings = DynamicSettings(cache_versions)
-        setup_new_user(settings, user)
-        assert user.avatars
-        assert user.avatar_set.exists()
-
-    def test_default_started_threads_subscription_option_is_set_for_user(self):
-        user = User.objects.create_user("User", "test@example.com")
-        cache_versions = get_cache_versions()
-        settings = DynamicSettings(cache_versions)
-
-        with override_dynamic_settings(subscribe_start="no"):
-            set_default_subscription_options(settings, user)
-            assert user.subscribe_to_started_threads == User.SUBSCRIPTION_NONE
-
-        with override_dynamic_settings(subscribe_start="watch"):
-            set_default_subscription_options(settings, user)
-            assert user.subscribe_to_started_threads == User.SUBSCRIPTION_NOTIFY
-
-        with override_dynamic_settings(subscribe_start="watch_email"):
-            set_default_subscription_options(settings, user)
-            assert user.subscribe_to_started_threads == User.SUBSCRIPTION_ALL
-
-    def test_default_replied_threads_subscription_option_is_set_for_user(self):
-        user = User.objects.create_user("User", "test@example.com")
-        cache_versions = get_cache_versions()
-        settings = DynamicSettings(cache_versions)
-
-        with override_dynamic_settings(subscribe_reply="no"):
-            set_default_subscription_options(settings, user)
-            assert user.subscribe_to_replied_threads == User.SUBSCRIPTION_NONE
-
-        with override_dynamic_settings(subscribe_reply="watch"):
-            set_default_subscription_options(settings, user)
-            assert user.subscribe_to_replied_threads == User.SUBSCRIPTION_NOTIFY
-
-        with override_dynamic_settings(subscribe_reply="watch_email"):
-            set_default_subscription_options(settings, user)
-            assert user.subscribe_to_replied_threads == User.SUBSCRIPTION_ALL
-
-    def test_if_user_ip_is_available_audit_trail_is_created_for_user(self):
-        user = User.objects.create_user(
-            "User", "test@example.com", joined_from_ip="0.0.0.0"
-        )
-        cache_versions = get_cache_versions()
-        settings = DynamicSettings(cache_versions)
-        setup_new_user(settings, user)
-        assert user.audittrail_set.count() == 1
-
-    def test_if_user_ip_is_not_available_audit_trail_is_not_created(self):
-        user = User.objects.create_user("User", "test@example.com")
-        cache_versions = get_cache_versions()
-        settings = DynamicSettings(cache_versions)
-        setup_new_user(settings, user)
-        assert user.audittrail_set.exists() is False
+def user(db):
+    return User.objects.create_user("User", "user@example.com")
+
+
+def test_default_avatar_is_set_for_user(dynamic_settings, user):
+    setup_new_user(dynamic_settings, user)
+    assert user.avatars
+    assert user.avatar_set.exists()
+
+
+def test_default_started_threads_subscription_option_is_set_for_user(
+    dynamic_settings, user
+):
+    with override_dynamic_settings(subscribe_start="no"):
+        set_default_subscription_options(dynamic_settings, user)
+        assert user.subscribe_to_started_threads == User.SUBSCRIPTION_NONE
+
+    with override_dynamic_settings(subscribe_start="watch"):
+        set_default_subscription_options(dynamic_settings, user)
+        assert user.subscribe_to_started_threads == User.SUBSCRIPTION_NOTIFY
+
+    with override_dynamic_settings(subscribe_start="watch_email"):
+        set_default_subscription_options(dynamic_settings, user)
+        assert user.subscribe_to_started_threads == User.SUBSCRIPTION_ALL
+
+
+def test_default_replied_threads_subscription_option_is_set_for_user(
+    dynamic_settings, user
+):
+    with override_dynamic_settings(subscribe_reply="no"):
+        set_default_subscription_options(dynamic_settings, user)
+        assert user.subscribe_to_replied_threads == User.SUBSCRIPTION_NONE
+
+    with override_dynamic_settings(subscribe_reply="watch"):
+        set_default_subscription_options(dynamic_settings, user)
+        assert user.subscribe_to_replied_threads == User.SUBSCRIPTION_NOTIFY
+
+    with override_dynamic_settings(subscribe_reply="watch_email"):
+        set_default_subscription_options(dynamic_settings, user)
+        assert user.subscribe_to_replied_threads == User.SUBSCRIPTION_ALL
+
+
+def test_if_user_ip_is_available_audit_trail_is_created_for_user(dynamic_settings):
+    user = User.objects.create_user(
+        "User", "user@example.com", joined_from_ip="0.0.0.0"
+    )
+    setup_new_user(dynamic_settings, user)
+    assert user.audittrail_set.count() == 1
+
+
+def test_if_user_ip_is_not_available_audit_trail_is_not_created(dynamic_settings, user):
+    setup_new_user(dynamic_settings, user)
+    assert user.audittrail_set.exists() is False

+ 24 - 0
misago/users/tests/test_populate_online_tracker_command.py

@@ -0,0 +1,24 @@
+from io import StringIO
+
+from django.core.management import call_command
+
+from misago.users.management.commands import populateonlinetracker
+from misago.users.models import Online
+
+
+def test_management_command_creates_online_tracker_for_user_without_one(user):
+    Online.objects.filter(user=user).delete()
+    assert not Online.objects.filter(user=user).exists()
+
+    call_command(populateonlinetracker.Command(), stdout=StringIO())
+    assert Online.objects.filter(user=user).exists()
+
+
+def test_management_command_displays_message_with_number_of_created_trackers(user):
+    Online.objects.filter(user=user).delete()
+    assert not Online.objects.filter(user=user).exists()
+
+    out = StringIO()
+    call_command(populateonlinetracker.Command(), stdout=out)
+    command_output = out.getvalue().splitlines()[0].strip()
+    assert command_output == "Tracker entries created: 1"

+ 0 - 27
misago/users/tests/test_populateonlinetracker.py

@@ -1,27 +0,0 @@
-from io import StringIO
-
-from django.contrib.auth import get_user_model
-from django.core.management import call_command
-from django.test import TestCase
-
-from misago.users.management.commands import populateonlinetracker
-from misago.users.models import Online
-
-
-User = get_user_model()
-
-
-class PopulateOnlineTrackerTests(TestCase):
-    def test_populate_user_online(self):
-        """user account without online tracker gets one"""
-        test_user = User.objects.create_user("Bob", "bob@bob.com", "pass123")
-
-        Online.objects.filter(user=test_user).delete()
-        self.assertEqual(Online.objects.filter(user=test_user).count(), 0)
-
-        out = StringIO()
-        call_command(populateonlinetracker.Command(), stdout=out)
-        command_output = out.getvalue().splitlines()[0].strip()
-
-        self.assertEqual(command_output, "Tracker entries created: 1")
-        self.assertEqual(Online.objects.filter(user=test_user).count(), 1)

+ 9 - 13
misago/users/tests/test_profile_views.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.urls import reverse
 
 from misago.acl.test import patch_user_acl
@@ -8,9 +7,6 @@ from misago.users.models import Ban
 from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
-User = get_user_model()
-
-
 class UserProfileViewsTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
@@ -31,18 +27,18 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
         self.user.is_staff = False
         self.user.save()
 
-        test_user = create_test_user("Tyrael", "t123@test.com")
+        disabled_user = create_test_user("DisabledUser", "disabled@example.com")
 
-        test_user.is_active = False
-        test_user.save()
+        disabled_user.is_active = False
+        disabled_user.save()
 
-        response = self.client.get(test_user.get_absolute_url())
+        response = self.client.get(disabled_user.get_absolute_url())
         self.assertEqual(response.status_code, 404)
 
         self.user.is_staff = True
         self.user.save()
 
-        response = self.client.get(test_user.get_absolute_url())
+        response = self.client.get(disabled_user.get_absolute_url())
         self.assertEqual(response.status_code, 302)
 
         # profile page displays notice about user being disabled
@@ -104,8 +100,8 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
 
         followers = []
         for i in range(10):
-            user_data = ("Follower%s" % i, "foll%s@test.com" % i, "Pass.123")
-            followers.append(User.objects.create_user(*user_data))
+            user_data = ("Follower%s" % i, "foll%s@test.com" % i)
+            followers.append(create_test_user(*user_data))
             self.user.followed_by.add(followers[-1])
 
         response = self.client.get(
@@ -126,8 +122,8 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
 
         followers = []
         for i in range(10):
-            user_data = ("Follower%s" % i, "foll%s@test.com" % i, "Pass.123")
-            followers.append(User.objects.create_user(*user_data))
+            user_data = ("Follower%s" % i, "foll%s@test.com" % i)
+            followers.append(create_test_user(*user_data))
             followers[-1].followed_by.add(self.user)
 
         response = self.client.get(

+ 67 - 0
misago/users/tests/test_remove_old_ips_command.py

@@ -0,0 +1,67 @@
+from datetime import timedelta
+from io import StringIO
+
+import pytest
+from django.core.management import call_command
+from django.test import override_settings
+from django.utils import timezone
+
+from misago.users.management.commands import removeoldips
+
+
+IP_STORE_TIME = 2
+
+
+@pytest.fixture
+def user_with_ip(user):
+    user.joined_from_ip = "127.0.0.1"
+    user.save()
+    return user
+
+
+@pytest.fixture
+def user_with_old_ip(user_with_ip):
+    joined_on_past = timezone.now() - timedelta(days=IP_STORE_TIME + 1)
+    user_with_ip.joined_on = joined_on_past
+    user_with_ip.save()
+    return user_with_ip
+
+
+def test_recent_user_joined_ip_is_not_removed_by_command(user_with_ip):
+    call_command(removeoldips.Command(), stdout=StringIO())
+    user_with_ip.refresh_from_db()
+    assert user_with_ip.joined_from_ip
+
+
+@override_settings(MISAGO_IP_STORE_TIME=IP_STORE_TIME)
+def test_old_user_joined_ip_is_removed_by_command(user_with_old_ip):
+    call_command(removeoldips.Command(), stdout=StringIO())
+    user_with_old_ip.refresh_from_db()
+    assert user_with_old_ip.joined_from_ip is None
+
+
+@override_settings(MISAGO_IP_STORE_TIME=None)
+def test_old_user_joined_ip_is_not_removed_by_command_if_removal_is_disabled(
+    user_with_old_ip
+):
+    call_command(removeoldips.Command(), stdout=StringIO())
+    user_with_old_ip.refresh_from_db()
+    assert user_with_old_ip.joined_from_ip
+
+
+@override_settings(MISAGO_IP_STORE_TIME=IP_STORE_TIME)
+def test_command_displays_message_if_old_ip_removal_is_enabled(db):
+    stdout = StringIO()
+    call_command(removeoldips.Command(), stdout=stdout)
+
+    command_output = stdout.getvalue().splitlines()[0].strip()
+    assert command_output == "IP addresses older than 2 days have been removed."
+
+
+@override_settings(MISAGO_IP_STORE_TIME=None)
+def test_command_displays_message_if_old_ip_removal_is_disabled():
+    stdout = StringIO()
+    call_command(removeoldips.Command(), stdout=stdout)
+
+    command_output = stdout.getvalue().splitlines()[0].strip()
+    assert command_output == "Old IP removal is disabled."

+ 0 - 53
misago/users/tests/test_removeoldips.py

@@ -1,53 +0,0 @@
-from datetime import timedelta
-from io import StringIO
-
-from django.contrib.auth import get_user_model
-from django.core.management import call_command
-from django.test import TestCase, override_settings
-from django.utils import timezone
-
-from misago.users.management.commands import removeoldips
-
-
-User = get_user_model()
-
-USER_IP = "31.41.51.65"
-
-
-class RemoveOldIpsTests(TestCase):
-    def test_removeoldips_recent_user(self):
-        """command is not removing user's IP if its recent"""
-        user = User.objects.create_user("Bob", "bob@bob.com", joined_from_ip=USER_IP)
-
-        out = StringIO()
-        call_command(removeoldips.Command(), stdout=out)
-
-        user_joined_from_ip = User.objects.get(pk=user.pk).joined_from_ip
-        self.assertEqual(user_joined_from_ip, USER_IP)
-
-    def test_removeoldips_old_user(self):
-        """command removes user's IP if its old"""
-        joined_on_past = timezone.now() - timedelta(days=50)
-        user = User.objects.create_user("Bob1", "bob1@bob.com", joined_from_ip=USER_IP)
-        user.joined_on = joined_on_past
-        user.save()
-
-        out = StringIO()
-        call_command(removeoldips.Command(), stdout=out)
-
-        user_joined_from_ip = User.objects.get(pk=user.pk).joined_from_ip
-        self.assertIsNone(user_joined_from_ip)
-
-    @override_settings(MISAGO_IP_STORE_TIME=None)
-    def test_not_removing_user_ip(self):
-        """command is not removing user's IP if removing is disabled"""
-        user = User.objects.create_user("Bob1", "bob1@bob.com", joined_from_ip=USER_IP)
-
-        out = StringIO()
-        call_command(removeoldips.Command(), stdout=out)
-        command_output = out.getvalue().splitlines()[0].strip()
-
-        self.assertEqual(command_output, "Old IP removal is disabled.")
-
-        user_joined_from_ip = User.objects.get(pk=user.pk).joined_from_ip
-        self.assertEqual(user_joined_from_ip, USER_IP)

+ 4 - 8
misago/users/tests/test_search.py

@@ -1,11 +1,7 @@
-from django.contrib.auth import get_user_model
 from django.urls import reverse
 
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class SearchApiTests(AuthenticatedUserTestCase):
@@ -99,10 +95,10 @@ class SearchApiTests(AuthenticatedUserTestCase):
             if provider["id"] == "users":
                 self.assertEqual(provider["results"]["results"], [])
 
-    def test_search_disabled(self):
+    def test_search_disabled_user(self):
         """api respects disabled users visibility"""
-        disabled_user = User.objects.create_user(
-            "DisabledUser", "visible@te.com", "Pass.123", is_active=False
+        disabled_user = create_test_user(
+            "DisabledUser", "disableduser@example.com", is_active=False
         )
 
         response = self.client.get("%s?q=DisabledUser" % self.api_link)

+ 24 - 47
misago/users/tests/test_signatures.py

@@ -1,62 +1,39 @@
 from unittest.mock import Mock
 
-from django.contrib.auth import get_user_model
-from django.test import TestCase
+import pytest
 
 from misago.acl.useracl import get_user_acl
-from misago.conftest import get_cache_versions
 from misago.users import signatures
 
-User = get_user_model()
-cache_versions = get_cache_versions()
 
+@pytest.fixture
+def signature(user):
+    user.signature = "Test"
+    user.signature_parsed = "Test"
+    user.signature_checksum = "Test"
+    user.save()
 
-class MockRequest(object):
-    scheme = "http"
 
-    def get_host(self):
-        return "127.0.0.1:8000"
+def test_user_signature_and_valid_checksum_is_set(user, signature, user_acl):
+    request = Mock(scheme="http", get_host=Mock(return_value="127.0.0.1:800"))
+    signatures.set_user_signature(request, user, user_acl, "Changed")
 
+    assert user.signature == "Changed"
+    assert user.signature_parsed == "<p>Changed</p>"
+    assert user.signature_checksum
+    assert signatures.is_user_signature_valid(user)
 
-class UserSignatureTests(TestCase):
-    def test_user_signature_and_valid_checksum_is_set(self):
-        user = User.objects.create_user("Bob", "bob@bob.com")
-        user.signature = "Test"
-        user.signature_parsed = "Test"
-        user.signature_checksum = "Test"
-        user.save()
 
-        request = Mock(scheme="http", get_host=Mock(return_value="127.0.0.1:800"))
-        user_acl = get_user_acl(user, cache_versions)
+def test_user_signature_is_cleared(user, signature, user_acl):
+    request = Mock(scheme="http", get_host=Mock(return_value="127.0.0.1:800"))
+    signatures.set_user_signature(request, user, user_acl, "")
 
-        signatures.set_user_signature(request, user, user_acl, "Changed")
+    assert not user.signature
+    assert not user.signature_parsed
+    assert not user.signature_checksum
 
-        assert user.signature == "Changed"
-        assert user.signature_parsed == "<p>Changed</p>"
-        assert user.signature_checksum
-        assert signatures.is_user_signature_valid(user)
 
-    def test_user_signature_is_cleared(self):
-        user = User.objects.create_user("Bob", "bob@bob.com")
-        user.signature = "Test"
-        user.signature_parsed = "Test"
-        user.signature_checksum = "Test"
-        user.save()
-
-        request = Mock(scheme="http", get_host=Mock(return_value="127.0.0.1:800"))
-        user_acl = get_user_acl(user, cache_versions)
-
-        signatures.set_user_signature(request, user, user_acl, "")
-
-        assert not user.signature
-        assert not user.signature_parsed
-        assert not user.signature_checksum
-
-    def test_signature_validity_check_fails_for_incorrect_signature_checksum(self):
-        user = User.objects.create_user("Bob", "bob@bob.com")
-        user.signature = "Test"
-        user.signature_parsed = "Test"
-        user.signature_checksum = "Test"
-        user.save()
-
-        assert not signatures.is_user_signature_valid(user)
+def test_signature_validity_check_fails_for_incorrect_signature_checksum(
+    user, signature
+):
+    assert not signatures.is_user_signature_valid(user)

+ 20 - 0
misago/users/tests/test_token_creation_and_validation.py

@@ -0,0 +1,20 @@
+from misago.users import tokens
+
+
+def test_token_can_be_created_for_user(user):
+    assert tokens.make(user, "test")
+
+
+def test_token_can_be_validated(user):
+    token = tokens.make(user, "test")
+    assert tokens.is_valid(user, "test", token)
+
+
+def test_token_fails_validation_for_different_type(user):
+    token = tokens.make(user, "activation")
+    assert not tokens.is_valid(user, "new_password", token)
+
+
+def test_token_fails_validation_for_different_user(user, other_user):
+    token = tokens.make(user, "test")
+    assert not tokens.is_valid(other_user, "test", token)

+ 0 - 21
misago/users/tests/test_tokens.py

@@ -1,21 +0,0 @@
-from django.contrib.auth import get_user_model
-from django.test import TestCase
-
-from misago.users import tokens
-
-
-User = get_user_model()
-
-
-class TokensTests(TestCase):
-    def test_tokens(self):
-        """misago.users.tokens implementation works"""
-        user_a = User.objects.create_user("Bob", "bob@test.com", "pass123")
-        user_b = User.objects.create_user("Weebl", "weebl@test.com", "pass123")
-
-        token_a = tokens.make(user_a, "test")
-        token_b = tokens.make(user_b, "test")
-
-        self.assertTrue(tokens.is_valid(user_a, "test", token_a))
-        self.assertTrue(tokens.is_valid(user_b, "test", token_b))
-        self.assertTrue(token_a != token_b)

+ 47 - 43
misago/users/tests/test_user_avatar_api.py

@@ -9,13 +9,11 @@ from misago.conf import settings
 from misago.conf.test import override_dynamic_settings
 from misago.users.avatars import gallery, store
 from misago.users.models import AvatarGallery
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, "avatar.png")
 
-User = get_user_model()
-
 
 class UserAvatarTests(AuthenticatedUserTestCase):
     """tests for user avatar RPC (/api/users/1/avatar/)"""
@@ -26,7 +24,8 @@ class UserAvatarTests(AuthenticatedUserTestCase):
         self.client.post(self.link, data={"avatar": "generated"})
 
     def get_current_user(self):
-        return User.objects.get(pk=self.user.pk)
+        self.user.refresh_from_db()
+        return self.user
 
     def assertOldAvatarsAreDeleted(self, user):
         self.assertEqual(user.avatar_set.count(), len(settings.MISAGO_AVATARS_SIZES))
@@ -95,9 +94,7 @@ class UserAvatarTests(AuthenticatedUserTestCase):
             response.json(), {"detail": "You have to sign in to perform this action."}
         )
 
-        self.login_user(
-            User.objects.create_user("BobUser", "bob@bob.com", self.USER_PASSWORD)
-        )
+        self.login_user(create_test_user("OtherUser", "otheruser@example.com"))
 
         response = self.client.get(self.link)
         self.assertEqual(response.status_code, 403)
@@ -301,10 +298,7 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.other_user = User.objects.create_user(
-            "OtherUser", "other@user.com", "pass123"
-        )
-
+        self.other_user = create_test_user("OtherUser", "other@user.com")
         self.link = "/api/users/%s/moderate-avatar/" % self.other_user.pk
 
     @patch_user_acl({"can_moderate_avatars": 0})
@@ -344,20 +338,24 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        other_user = User.objects.get(pk=self.other_user.pk)
+        self.other_user.refresh_from_db()
 
         options = response.json()
-        self.assertEqual(other_user.is_avatar_locked, True)
-        self.assertEqual(other_user.avatar_lock_user_message, "Test user message.")
-        self.assertEqual(other_user.avatar_lock_staff_message, "Test staff message.")
+        self.assertEqual(self.other_user.is_avatar_locked, True)
+        self.assertEqual(self.other_user.avatar_lock_user_message, "Test user message.")
+        self.assertEqual(
+            self.other_user.avatar_lock_staff_message, "Test staff message."
+        )
 
-        self.assertEqual(options["avatars"], other_user.avatars)
-        self.assertEqual(options["is_avatar_locked"], other_user.is_avatar_locked)
+        self.assertEqual(options["avatars"], self.other_user.avatars)
+        self.assertEqual(options["is_avatar_locked"], self.other_user.is_avatar_locked)
         self.assertEqual(
-            options["avatar_lock_user_message"], other_user.avatar_lock_user_message
+            options["avatar_lock_user_message"],
+            self.other_user.avatar_lock_user_message,
         )
         self.assertEqual(
-            options["avatar_lock_staff_message"], other_user.avatar_lock_staff_message
+            options["avatar_lock_staff_message"],
+            self.other_user.avatar_lock_staff_message,
         )
 
         response = self.client.post(
@@ -373,19 +371,21 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        other_user = User.objects.get(pk=self.other_user.pk)
-        self.assertFalse(other_user.is_avatar_locked)
-        self.assertIsNone(other_user.avatar_lock_user_message)
-        self.assertIsNone(other_user.avatar_lock_staff_message)
+        self.other_user.refresh_from_db()
+        self.assertFalse(self.other_user.is_avatar_locked)
+        self.assertIsNone(self.other_user.avatar_lock_user_message)
+        self.assertIsNone(self.other_user.avatar_lock_staff_message)
 
         options = response.json()
-        self.assertEqual(options["avatars"], other_user.avatars)
-        self.assertEqual(options["is_avatar_locked"], other_user.is_avatar_locked)
+        self.assertEqual(options["avatars"], self.other_user.avatars)
+        self.assertEqual(options["is_avatar_locked"], self.other_user.is_avatar_locked)
         self.assertEqual(
-            options["avatar_lock_user_message"], other_user.avatar_lock_user_message
+            options["avatar_lock_user_message"],
+            self.other_user.avatar_lock_user_message,
         )
         self.assertEqual(
-            options["avatar_lock_staff_message"], other_user.avatar_lock_staff_message
+            options["avatar_lock_staff_message"],
+            self.other_user.avatar_lock_staff_message,
         )
 
         response = self.client.post(
@@ -401,19 +401,21 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        other_user = User.objects.get(pk=self.other_user.pk)
-        self.assertTrue(other_user.is_avatar_locked)
-        self.assertEqual(other_user.avatar_lock_user_message, "")
-        self.assertEqual(other_user.avatar_lock_staff_message, "")
+        self.other_user.refresh_from_db()
+        self.assertTrue(self.other_user.is_avatar_locked)
+        self.assertEqual(self.other_user.avatar_lock_user_message, "")
+        self.assertEqual(self.other_user.avatar_lock_staff_message, "")
 
         options = response.json()
-        self.assertEqual(options["avatars"], other_user.avatars)
-        self.assertEqual(options["is_avatar_locked"], other_user.is_avatar_locked)
+        self.assertEqual(options["avatars"], self.other_user.avatars)
+        self.assertEqual(options["is_avatar_locked"], self.other_user.is_avatar_locked)
         self.assertEqual(
-            options["avatar_lock_user_message"], other_user.avatar_lock_user_message
+            options["avatar_lock_user_message"],
+            self.other_user.avatar_lock_user_message,
         )
         self.assertEqual(
-            options["avatar_lock_staff_message"], other_user.avatar_lock_staff_message
+            options["avatar_lock_staff_message"],
+            self.other_user.avatar_lock_staff_message,
         )
 
         response = self.client.post(
@@ -423,19 +425,21 @@ class UserAvatarModerationTests(AuthenticatedUserTestCase):
         )
         self.assertEqual(response.status_code, 200)
 
-        other_user = User.objects.get(pk=self.other_user.pk)
-        self.assertFalse(other_user.is_avatar_locked)
-        self.assertEqual(other_user.avatar_lock_user_message, "")
-        self.assertEqual(other_user.avatar_lock_staff_message, "")
+        self.other_user.refresh_from_db()
+        self.assertFalse(self.other_user.is_avatar_locked)
+        self.assertEqual(self.other_user.avatar_lock_user_message, "")
+        self.assertEqual(self.other_user.avatar_lock_staff_message, "")
 
         options = response.json()
-        self.assertEqual(options["avatars"], other_user.avatars)
-        self.assertEqual(options["is_avatar_locked"], other_user.is_avatar_locked)
+        self.assertEqual(options["avatars"], self.other_user.avatars)
+        self.assertEqual(options["is_avatar_locked"], self.other_user.is_avatar_locked)
         self.assertEqual(
-            options["avatar_lock_user_message"], other_user.avatar_lock_user_message
+            options["avatar_lock_user_message"],
+            self.other_user.avatar_lock_user_message,
         )
         self.assertEqual(
-            options["avatar_lock_staff_message"], other_user.avatar_lock_staff_message
+            options["avatar_lock_staff_message"],
+            self.other_user.avatar_lock_staff_message,
         )
 
     @patch_user_acl({"can_moderate_avatars": 1})

+ 4 - 8
misago/users/tests/test_user_changeemail_api.py

@@ -1,11 +1,7 @@
-from django.contrib.auth import get_user_model
 from django.core import mail
 from django.urls import reverse
 
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class UserChangeEmailTests(AuthenticatedUserTestCase):
@@ -65,11 +61,11 @@ class UserChangeEmailTests(AuthenticatedUserTestCase):
 
     def test_email_taken(self):
         """api validates email usage"""
-        User.objects.create_user("BobBoberson", "new@email.com", "Pass.123")
+        taken_email = "otheruser@example.com"
+        create_test_user("OtherUser", taken_email)
 
         response = self.client.post(
-            self.link,
-            data={"new_email": "new@email.com", "password": self.USER_PASSWORD},
+            self.link, data={"new_email": taken_email, "password": self.USER_PASSWORD}
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(

+ 86 - 76
misago/users/tests/test_user_creation.py

@@ -1,5 +1,5 @@
+import pytest
 from django.contrib.auth import get_user_model
-from django.test import TestCase
 
 from misago.users.models import Rank
 from misago.users.utils import hash_email
@@ -7,78 +7,88 @@ from misago.users.utils import hash_email
 User = get_user_model()
 
 
-class UserCreationTests(TestCase):
-    def test_user_is_created(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert user.pk
-        assert user.joined_on
-
-    def test_user_is_created_with_username_and_slug(self):
-        user = User.objects.create_user("UserName", "test@example.com")
-        assert user.slug == "username"
-
-    def test_user_is_created_with_normalized_email_and_email_hash(self):
-        user = User.objects.create_user("User", "test@eXamPLe.com")
-        assert user.email == "test@example.com"
-        assert user.email_hash == hash_email(user.email)
-
-    def test_user_is_created_with_online_tracker(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert user.online_tracker
-        assert user.online_tracker.last_click == user.last_login
-
-    def test_user_is_created_with_useable_password(self):
-        password = "password"
-        user = User.objects.create_user("UserUserame", "test@example.com", password)
-        assert user.check_password(password)
-
-    def test_user_is_created_with_default_rank(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert user.rank == Rank.objects.get_default()
-
-    def test_user_is_created_with_custom_rank(self):
-        rank = Rank.objects.create(name="Test rank")
-        user = User.objects.create_user("User", "test@example.com", rank=rank)
-        assert user.rank == rank
-
-    def test_newly_created_user_last_login_is_same_as_join_date(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert user.last_login == user.joined_on
-
-    def test_user_is_created_with_authenticated_role(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert user.roles.get(special_role="authenticated")
-
-    def test_user_is_created_with_diacritics_in_email(self):
-        email = "łóć@łexąmple.com"
-        user = User.objects.create_user("UserName", email)
-        assert user.email == email
-
-    def test_creating_user_without_username_raises_value_error(self):
-        with self.assertRaises(ValueError):
-            User.objects.create_user("", "test@example.com")
-
-    def test_creating_user_without_email_raises_value_error(self):
-        with self.assertRaises(ValueError):
-            User.objects.create_user("User", "")
-
-    def test_create_superuser(self):
-        user = User.objects.create_superuser("User", "test@example.com")
-        assert user.is_staff
-        assert user.is_superuser
-
-    def test_superuser_is_created_with_team_rank(self):
-        user = User.objects.create_superuser("User", "test@example.com")
-        assert "team" in str(user.rank)
-
-    def test_creating_superuser_without_staff_status_raises_value_error(self):
-        with self.assertRaises(ValueError):
-            user = User.objects.create_superuser(
-                "User", "test@example.com", is_staff=False
-            )
-
-    def test_creating_superuser_without_superuser_status_raises_value_error(self):
-        with self.assertRaises(ValueError):
-            user = User.objects.create_superuser(
-                "User", "test@example.com", is_superuser=False
-            )
+def test_user_is_created(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert user.pk
+    assert user.joined_on
+
+
+def test_user_is_created_with_username_and_slug(db):
+    user = User.objects.create_user("UserName", "test@example.com")
+    assert user.slug == "username"
+
+
+def test_user_is_created_with_normalized_email_and_email_hash(db):
+    user = User.objects.create_user("User", "test@eXamPLe.com")
+    assert user.email == "test@example.com"
+    assert user.email_hash == hash_email(user.email)
+
+
+def test_user_is_created_with_online_tracker(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert user.online_tracker
+    assert user.online_tracker.last_click == user.last_login
+
+
+def test_user_is_created_with_useable_password(db):
+    password = "password"
+    user = User.objects.create_user("UserUserame", "test@example.com", password)
+    assert user.check_password(password)
+
+
+def test_user_is_created_with_default_rank(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert user.rank == Rank.objects.get_default()
+
+
+def test_user_is_created_with_custom_rank(db):
+    rank = Rank.objects.create(name="Test rank")
+    user = User.objects.create_user("User", "test@example.com", rank=rank)
+    assert user.rank == rank
+
+
+def test_newly_created_user_last_login_is_same_as_join_date(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert user.last_login == user.joined_on
+
+
+def test_user_is_created_with_authenticated_role(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert user.roles.get(special_role="authenticated")
+
+
+def test_user_is_created_with_diacritics_in_email(db):
+    email = "łóć@łexąmple.com"
+    user = User.objects.create_user("UserName", email)
+    assert user.email == email
+
+
+def test_creating_user_without_username_raises_value_error(db):
+    with pytest.raises(ValueError):
+        User.objects.create_user("", "test@example.com")
+
+
+def test_creating_user_without_email_raises_value_error(db):
+    with pytest.raises(ValueError):
+        User.objects.create_user("User", "")
+
+
+def test_create_superuser(db):
+    user = User.objects.create_superuser("User", "test@example.com")
+    assert user.is_staff
+    assert user.is_superuser
+
+
+def test_superuser_is_created_with_team_rank(db):
+    user = User.objects.create_superuser("User", "test@example.com")
+    assert "team" in str(user.rank)
+
+
+def test_creating_superuser_without_staff_status_raises_value_error(db):
+    with pytest.raises(ValueError):
+        User.objects.create_superuser("User", "test@example.com", is_staff=False)
+
+
+def test_creating_superuser_without_superuser_status_raises_value_error(db):
+    with pytest.raises(ValueError):
+        User.objects.create_superuser("User", "test@example.com", is_superuser=False)

+ 3 - 8
misago/users/tests/test_user_details_api.py

@@ -1,11 +1,7 @@
-from django.contrib.auth import get_user_model
 from django.urls import reverse
 
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class UserDetailsApiTests(AuthenticatedUserTestCase):
@@ -35,9 +31,8 @@ class UserDetailsApiTests(AuthenticatedUserTestCase):
 
     def test_other_user(self):
         """api handles scenario when its other user looking at profile"""
-        test_user = User.objects.create_user("BobBoberson", "bob@test.com", "bob123456")
-
-        api_link = reverse("misago:api:user-details", kwargs={"pk": test_user.pk})
+        user = create_test_user("OtherUser", "otheruser@example.com")
+        api_link = reverse("misago:api:user-details", kwargs={"pk": user.pk})
 
         # moderator has permission to edit details
         with patch_user_acl({"can_moderate_profile_details": True}):

+ 4 - 7
misago/users/tests/test_user_editdetails_api.py

@@ -1,11 +1,7 @@
-from django.contrib.auth import get_user_model
 from django.urls import reverse
 
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class UserEditDetailsApiTests(AuthenticatedUserTestCase):
@@ -17,7 +13,8 @@ class UserEditDetailsApiTests(AuthenticatedUserTestCase):
         )
 
     def get_profile_fields(self):
-        return User.objects.get(pk=self.user.pk).profile_fields
+        self.user.refresh_from_db()
+        return self.user.profile_fields
 
     def test_api_has_no_showstoppers(self):
         """api outputs response for freshly created user"""
@@ -31,7 +28,7 @@ class UserEditDetailsApiTests(AuthenticatedUserTestCase):
 
     def test_other_user(self):
         """api handles scenario when its other user looking at profile"""
-        test_user = User.objects.create_user("BobBoberson", "bob@test.com", "bob123456")
+        test_user = create_test_user("OtherUser", "otheruser@example.com")
 
         api_link = reverse("misago:api:user-edit-details", kwargs={"pk": test_user.pk})
 

+ 55 - 44
misago/users/tests/test_user_getters.py

@@ -1,62 +1,73 @@
+import pytest
 from django.contrib.auth import get_user_model
-from django.test import TestCase
 
 User = get_user_model()
 
 
-class UserGettersTests(TestCase):
-    def test_get_user_by_username(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert User.objects.get_by_username("User") == user
+def test_get_user_by_username(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert User.objects.get_by_username("User") == user
 
-    def test_getting_user_by_username_is_case_insensitive(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert User.objects.get_by_username("uSeR") == user
 
-    def test_getting_user_by_username_raises_does_not_exist_for_no_result(self):
-        with self.assertRaises(User.DoesNotExist):
-            User.objects.get_by_username("user")
+def test_getting_user_by_username_is_case_insensitive(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert User.objects.get_by_username("uSeR") == user
 
-    def test_getting_user_by_username_supports_diacritics(self):
-        with self.assertRaises(User.DoesNotExist):
-            User.objects.get_by_username("łóć")
 
-    def test_getting_user_by_username_is_not_doing_fuzzy_matching(self):
-        user = User.objects.create_user("User", "test@example.com")
-        with self.assertRaises(User.DoesNotExist):
-            User.objects.get_by_username("usere")
+def test_getting_user_by_username_raises_does_not_exist_for_no_result(db):
+    with pytest.raises(User.DoesNotExist):
+        User.objects.get_by_username("user")
 
-    def test_get_user_by_email(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert User.objects.get_by_email("test@example.com") == user
 
-    def test_getting_user_by_email_is_case_insensitive(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert User.objects.get_by_email("tEsT@eXaMplE.com") == user
+def test_getting_user_by_username_supports_diacritics(db):
+    with pytest.raises(User.DoesNotExist):
+        User.objects.get_by_username("łóć")
 
-    def test_getting_user_by_email_supports_diacritics(self):
-        user = User.objects.create_user("User", "łóć@łexĄmple.com")
-        assert User.objects.get_by_email("łÓć@ŁexĄMple.com") == user
 
-    def test_getting_user_by_email_raises_does_not_exist_for_no_result(self):
-        with self.assertRaises(User.DoesNotExist):
-            User.objects.get_by_email("test@example.com")
+def test_getting_user_by_username_is_not_doing_fuzzy_matching(db):
+    user = User.objects.create_user("User", "test@example.com")
+    with pytest.raises(User.DoesNotExist):
+        User.objects.get_by_username("usar")
 
-    def test_get_user_by_username_using_combined_getter(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert User.objects.get_by_username_or_email("user") == user
 
-    def test_get_user_by_email_using_combined_getter(self):
-        user = User.objects.create_user("User", "test@example.com")
-        assert User.objects.get_by_username_or_email("test@example.com") == user
+def test_get_user_by_email(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert User.objects.get_by_email("test@example.com") == user
 
-    def test_combined_getter_handles_username_slug_and_email_collision(self):
-        email_match = User.objects.create_user("Bob", "test@test.test")
-        slug_match = User.objects.create_user("TestTestTest", "bob@test.com")
 
-        assert User.objects.get_by_username_or_email("test@test.test") == email_match
-        assert User.objects.get_by_username_or_email("TestTestTest") == slug_match
+def test_getting_user_by_email_is_case_insensitive(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert User.objects.get_by_email("tEsT@eXaMplE.com") == user
 
-    def test_combined_getter_raises_does_not_exist_for_no_result(self):
-        with self.assertRaises(User.DoesNotExist):
-            User.objects.get_by_username_or_email("User")
+
+def test_getting_user_by_email_supports_diacritics(db):
+    user = User.objects.create_user("User", "łóć@łexĄmple.com")
+    assert User.objects.get_by_email("łÓć@ŁexĄMple.com") == user
+
+
+def test_getting_user_by_email_raises_does_not_exist_for_no_result(db):
+    with pytest.raises(User.DoesNotExist):
+        User.objects.get_by_email("test@example.com")
+
+
+def test_get_user_by_username_using_combined_getter(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert User.objects.get_by_username_or_email("user") == user
+
+
+def test_get_user_by_email_using_combined_getter(db):
+    user = User.objects.create_user("User", "test@example.com")
+    assert User.objects.get_by_username_or_email("test@example.com") == user
+
+
+def test_combined_getter_handles_username_slug_and_email_collision(db):
+    email_match = User.objects.create_user("Bob", "test@test.test")
+    slug_match = User.objects.create_user("TestTestTest", "other@test.com")
+
+    assert User.objects.get_by_username_or_email("test@test.test") == email_match
+    assert User.objects.get_by_username_or_email("TestTestTest") == slug_match
+
+
+def test_combined_getter_raises_does_not_exist_for_no_result(db):
+    with pytest.raises(User.DoesNotExist):
+        User.objects.get_by_username_or_email("User")

+ 15 - 15
misago/users/tests/test_user_model.py

@@ -12,15 +12,15 @@ from misago.users.models import Avatar, User
 class UserTests(TestCase):
     def test_anonymize_data(self):
         """anonymize_data sets username and slug to one defined in settings"""
-        user = User.objects.create_user("Bob", "bob@example.com", "Pass.123")
+        user = User.objects.create_user("User", "user@example.com")
 
         user.anonymize_data()
         self.assertEqual(user.username, settings.MISAGO_ANONYMOUS_USERNAME)
         self.assertEqual(user.slug, slugify(settings.MISAGO_ANONYMOUS_USERNAME))
 
-    def test_delete_avatar_on_delete(self):
+    def test_user_avatar_files_are_deleted_together_with_user(self):
         """account deletion for user also deletes their avatar file"""
-        user = User.objects.create_user("Bob", "bob@example.com", "Pass.123")
+        user = User.objects.create_user("User", "user@example.com")
         dynamic.set_avatar(user)
         user.save()
 
@@ -46,25 +46,25 @@ class UserTests(TestCase):
         """set_username sets username and slug on model"""
         user = User()
 
-        user.set_username("Boberson")
-        self.assertEqual(user.username, "Boberson")
-        self.assertEqual(user.slug, "boberson")
+        user.set_username("Username")
+        self.assertEqual(user.username, "Username")
+        self.assertEqual(user.slug, "username")
 
-        self.assertEqual(user.get_username(), "Boberson")
-        self.assertEqual(user.get_full_name(), "Boberson")
-        self.assertEqual(user.get_short_name(), "Boberson")
+        self.assertEqual(user.get_username(), "Username")
+        self.assertEqual(user.get_full_name(), "Username")
+        self.assertEqual(user.get_short_name(), "Username")
 
     def test_set_email(self):
         """set_email sets email and hash on model"""
         user = User()
 
-        user.set_email("bOb@TEst.com")
-        self.assertEqual(user.email, "bOb@test.com")
+        user.set_email("us3R@EXample.com")
+        self.assertEqual(user.email, "us3R@example.com")
         self.assertTrue(user.email_hash)
 
     def test_mark_for_delete(self):
         """mark_for_delete deactivates user and sets is_deleting_account flag"""
-        user = User.objects.create_user("Bob", "bob@example.com", "Pass.123")
+        user = User.objects.create_user("User", "user@example.com")
         user.mark_for_delete()
         self.assertFalse(user.is_active)
         self.assertTrue(user.is_deleting_account)
@@ -75,8 +75,8 @@ class UserTests(TestCase):
 
     def test_get_real_name(self):
         """get_real_name returns user-set real name or none"""
-        user = User.objects.create_user("Bob", "bob@example.com", "Pass.123")
+        user = User.objects.create_user("User", "user@example.com")
         self.assertIsNone(user.get_real_name())
 
-        user.profile_fields["real_name"] = "Bob Boberson"
-        self.assertEqual(user.get_real_name(), "Bob Boberson")
+        user.profile_fields["real_name"] = "User Usererson"
+        self.assertEqual(user.get_real_name(), "User Usererson")

+ 3 - 11
misago/users/tests/test_user_username_api.py

@@ -1,13 +1,8 @@
 import json
 
-from django.contrib.auth import get_user_model
-
 from misago.acl.test import patch_user_acl
 from misago.conf.test import override_dynamic_settings
-from misago.users.testutils import AuthenticatedUserTestCase
-
-
-User = get_user_model()
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 
 class UserUsernameTests(AuthenticatedUserTestCase):
@@ -100,10 +95,7 @@ class UserUsernameModerationTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.other_user = User.objects.create_user(
-            "OtherUser", "other@user.com", "pass123"
-        )
-
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
         self.link = "/api/users/%s/moderate-username/" % self.other_user.pk
 
     @patch_user_acl({"can_rename_users": 0})
@@ -159,7 +151,7 @@ class UserUsernameModerationTests(AuthenticatedUserTestCase):
 
         self.assertEqual(response.status_code, 200)
 
-        other_user = User.objects.get(pk=self.other_user.pk)
+        other_user.refresh_from_db()
 
         self.assertEqual("BobBoberson", other_user.username)
         self.assertEqual("bobboberson", other_user.slug)

+ 49 - 67
misago/users/tests/test_users_api.py

@@ -12,7 +12,7 @@ from misago.threads.models import Post, Thread
 from misago.threads.testutils import post_thread
 from misago.users.activepostersranking import build_active_posters_ranking
 from misago.users.models import Ban, Rank
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
 
 User = get_user_model()
 
@@ -81,27 +81,23 @@ class FollowersListTests(AuthenticatedUserTestCase):
 
     def test_filled_list(self):
         """user with followers returns 200"""
-        test_follower = User.objects.create_user(
-            "TestFollower", "test@follower.com", self.USER_PASSWORD
-        )
-        self.user.followed_by.add(test_follower)
+        follower = create_test_user("TestFollower", "test@follower.com")
+        self.user.followed_by.add(follower)
 
         response = self.client.get(self.link % self.user.pk)
         self.assertEqual(response.status_code, 200)
-        self.assertContains(response, test_follower.username)
+        self.assertContains(response, follower.username)
 
     def test_filled_list_search(self):
         """followers list is searchable"""
-        test_follower = User.objects.create_user(
-            "TestFollower", "test@follower.com", self.USER_PASSWORD
-        )
-        self.user.followed_by.add(test_follower)
+        follower = create_test_user("TestFollower", "test@follower.com")
+        self.user.followed_by.add(follower)
 
         api_link = self.link % self.user.pk
 
         response = self.client.get("%s?search=%s" % (api_link, "test"))
         self.assertEqual(response.status_code, 200)
-        self.assertContains(response, test_follower.username)
+        self.assertContains(response, follower.username)
 
 
 class FollowsListTests(AuthenticatedUserTestCase):
@@ -123,27 +119,23 @@ class FollowsListTests(AuthenticatedUserTestCase):
 
     def test_filled_list(self):
         """user with follows returns 200"""
-        test_follower = User.objects.create_user(
-            "TestFollower", "test@follower.com", self.USER_PASSWORD
-        )
-        self.user.follows.add(test_follower)
+        follower = create_test_user("TestFollower", "test@follower.com")
+        self.user.follows.add(follower)
 
         response = self.client.get(self.link % self.user.pk)
         self.assertEqual(response.status_code, 200)
-        self.assertContains(response, test_follower.username)
+        self.assertContains(response, follower.username)
 
     def test_filled_list_search(self):
         """follows list is searchable"""
-        test_follower = User.objects.create_user(
-            "TestFollower", "test@follower.com", self.USER_PASSWORD
-        )
-        self.user.follows.add(test_follower)
+        follower = create_test_user("TestFollower", "test@follower.com")
+        self.user.follows.add(follower)
 
         api_link = self.link % self.user.pk
 
         response = self.client.get("%s?search=%s" % (api_link, "test"))
         self.assertEqual(response.status_code, 200)
-        self.assertContains(response, test_follower.username)
+        self.assertContains(response, follower.username)
 
 
 class RankListTests(AuthenticatedUserTestCase):
@@ -191,21 +183,20 @@ class RankListTests(AuthenticatedUserTestCase):
 
     def test_disabled_users(self):
         """api follows disabled users visibility"""
-        test_rank = Rank.objects.create(name="Test rank", slug="test-rank", is_tab=True)
-
-        test_user = User.objects.create_user(
-            "Visible", "visible@te.com", "Pass.123", rank=test_rank, is_active=False
+        rank = Rank.objects.create(name="Test rank", slug="test-rank", is_tab=True)
+        user = create_test_user(
+            "DisabledUser", "disabled@example.com", rank=rank, is_active=False
         )
 
-        response = self.client.get(self.link % test_rank.pk)
-        self.assertNotContains(response, test_user.get_absolute_url())
+        response = self.client.get(self.link % rank.pk)
+        self.assertNotContains(response, user.get_absolute_url())
 
         # api shows disabled accounts to staff
         self.user.is_staff = True
         self.user.save()
 
-        response = self.client.get(self.link % test_rank.pk)
-        self.assertContains(response, test_user.get_absolute_url())
+        response = self.client.get(self.link % rank.pk)
+        self.assertContains(response, user.get_absolute_url())
 
 
 class SearchNamesListTests(AuthenticatedUserTestCase):
@@ -230,8 +221,8 @@ class UserRetrieveTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.test_user = User.objects.create_user("Tyrael", "t123@test.com", "pass123")
-        self.link = reverse("misago:api:user-detail", kwargs={"pk": self.test_user.pk})
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
+        self.link = reverse("misago:api:user-detail", kwargs={"pk": self.other_user.pk})
 
     def test_get_user(self):
         """api user retrieve endpoint has no showstoppers"""
@@ -243,8 +234,8 @@ class UserRetrieveTests(AuthenticatedUserTestCase):
         self.user.is_staff = False
         self.user.save()
 
-        self.test_user.is_active = False
-        self.test_user.save()
+        self.other_user.is_active = False
+        self.other_user.save()
 
         response = self.client.get(self.link)
         self.assertEqual(response.status_code, 404)
@@ -360,10 +351,7 @@ class UserFollowTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.other_user = User.objects.create_user(
-            "OtherUser", "other@user.com", "pass123"
-        )
-
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
         self.link = "/api/users/%s/follow/" % self.other_user.pk
 
     def test_follow_unauthenticated(self):
@@ -396,32 +384,32 @@ class UserFollowTests(AuthenticatedUserTestCase):
         response = self.client.post(self.link)
         self.assertEqual(response.status_code, 200)
 
-        user = User.objects.get(pk=self.user.pk)
-        self.assertEqual(user.followers, 0)
-        self.assertEqual(user.following, 1)
-        self.assertEqual(user.follows.count(), 1)
-        self.assertEqual(user.followed_by.count(), 0)
+        self.user.refresh_from_db()
+        self.assertEqual(self.user.followers, 0)
+        self.assertEqual(self.user.following, 1)
+        self.assertEqual(self.user.follows.count(), 1)
+        self.assertEqual(self.user.followed_by.count(), 0)
 
-        followed = User.objects.get(pk=self.other_user.pk)
-        self.assertEqual(followed.followers, 1)
-        self.assertEqual(followed.following, 0)
-        self.assertEqual(followed.follows.count(), 0)
-        self.assertEqual(followed.followed_by.count(), 1)
+        self.other_user.refresh_from_db()
+        self.assertEqual(self.other_user.followers, 1)
+        self.assertEqual(self.other_user.following, 0)
+        self.assertEqual(self.other_user.follows.count(), 0)
+        self.assertEqual(self.other_user.followed_by.count(), 1)
 
         response = self.client.post(self.link)
         self.assertEqual(response.status_code, 200)
 
-        user = User.objects.get(pk=self.user.pk)
-        self.assertEqual(user.followers, 0)
-        self.assertEqual(user.following, 0)
-        self.assertEqual(user.follows.count(), 0)
-        self.assertEqual(user.followed_by.count(), 0)
+        self.user.refresh_from_db()
+        self.assertEqual(self.user.followers, 0)
+        self.assertEqual(self.user.following, 0)
+        self.assertEqual(self.user.follows.count(), 0)
+        self.assertEqual(self.user.followed_by.count(), 0)
 
-        followed = User.objects.get(pk=self.other_user.pk)
-        self.assertEqual(followed.followers, 0)
-        self.assertEqual(followed.following, 0)
-        self.assertEqual(followed.follows.count(), 0)
-        self.assertEqual(followed.followed_by.count(), 0)
+        self.other_user.refresh_from_db()
+        self.assertEqual(self.other_user.followers, 0)
+        self.assertEqual(self.other_user.following, 0)
+        self.assertEqual(self.other_user.follows.count(), 0)
+        self.assertEqual(self.other_user.followed_by.count(), 0)
 
 
 class UserBanTests(AuthenticatedUserTestCase):
@@ -430,10 +418,7 @@ class UserBanTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.other_user = User.objects.create_user(
-            "OtherUser", "other@user.com", "pass123"
-        )
-
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
         self.link = "/api/users/%s/ban/" % self.other_user.pk
 
     @patch_user_acl({"can_see_ban_details": 0})
@@ -552,10 +537,7 @@ class UserDeleteTests(AuthenticatedUserTestCase):
     def setUp(self):
         super().setUp()
 
-        self.other_user = User.objects.create_user(
-            "OtherUser", "other@user.com", "pass123"
-        )
-
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
         self.link = "/api/users/%s/delete/" % self.other_user.pk
 
         self.threads = Thread.objects.count()
@@ -658,7 +640,7 @@ class UserDeleteTests(AuthenticatedUserTestCase):
         self.assertEqual(response.status_code, 200)
 
         with self.assertRaises(User.DoesNotExist):
-            User.objects.get(pk=self.other_user.pk)
+            self.other_user.refresh_from_db()
 
         self.assertEqual(Thread.objects.count(), self.threads)
         self.assertEqual(Post.objects.count(), self.posts)
@@ -676,7 +658,7 @@ class UserDeleteTests(AuthenticatedUserTestCase):
         self.assertEqual(response.status_code, 200)
 
         with self.assertRaises(User.DoesNotExist):
-            User.objects.get(pk=self.other_user.pk)
+            self.other_user.refresh_from_db()
 
         self.assertEqual(Thread.objects.count(), self.threads + 1)
         self.assertEqual(Post.objects.count(), self.posts + 2)

+ 20 - 27
misago/users/tests/test_validators.py

@@ -1,10 +1,10 @@
 from unittest.mock import Mock
 
-from django.contrib.auth import get_user_model
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 
 from misago.users.models import Ban
+from misago.users.testutils import create_test_user
 from misago.users.validators import (
     validate_email,
     validate_email_available,
@@ -18,24 +18,19 @@ from misago.users.validators import (
 )
 
 
-User = get_user_model()
-
-
 class ValidateEmailAvailableTests(TestCase):
     def setUp(self):
-        self.test_user = User.objects.create_user(
-            "EricTheFish", "eric@test.com", "pass123"
-        )
+        self.user = create_test_user("User", "user@example.com")
 
     def test_valid_email(self):
         """validate_email_available allows available emails"""
-        validate_email_available("bob@boberson.com")
-        validate_email_available(self.test_user.email, exclude=self.test_user)
+        validate_email_available("other@example.com")
+        validate_email_available(self.user.email, exclude=self.user)
 
     def test_invalid_email(self):
         """validate_email_available disallows unvailable emails"""
         with self.assertRaises(ValidationError):
-            validate_email_available(self.test_user.email)
+            validate_email_available(self.user.email)
 
 
 class ValidateEmailBannedTests(TestCase):
@@ -55,7 +50,7 @@ class ValidateEmailBannedTests(TestCase):
 class ValidateEmailTests(TestCase):
     def test_validate_email(self):
         """validate_email has no crashes"""
-        validate_email("bob@boberson.com")
+        validate_email("user@example.com")
         with self.assertRaises(ValidationError):
             validate_email("*")
 
@@ -71,48 +66,48 @@ class ValidateUsernameTests(TestCase):
 
 class ValidateUsernameAvailableTests(TestCase):
     def setUp(self):
-        self.test_user = User.objects.create_user("EricTheFish", "eric@test.com")
+        self.user = create_test_user("User", "user@example.com")
 
     def test_valid_name(self):
         """validate_username_available allows available names"""
-        validate_username_available("BobBoberson")
-        validate_username_available(self.test_user.username, exclude=self.test_user)
+        validate_username_available("OtherUser")
+        validate_username_available(self.user.username, exclude=self.user)
 
     def test_invalid_name(self):
         """validate_username_available disallows unvailable names"""
         with self.assertRaises(ValidationError):
-            validate_username_available(self.test_user.username)
+            validate_username_available(self.user.username)
 
 
 class ValidateUsernameBannedTests(TestCase):
     def setUp(self):
-        Ban.objects.create(check_type=Ban.USERNAME, banned_value="Bob")
+        Ban.objects.create(check_type=Ban.USERNAME, banned_value="Ban")
 
     def test_unbanned_name(self):
         """unbanned name passes validation"""
-        validate_username_banned("Luke")
+        validate_username_banned("User")
 
     def test_banned_name(self):
         """banned name fails validation"""
         with self.assertRaises(ValidationError):
-            validate_username_banned("Bob")
+            validate_username_banned("Ban")
 
 
 class ValidateUsernameContentTests(TestCase):
     def test_valid_name(self):
         """validate_username_content allows valid names"""
         validate_username_content("123")
-        validate_username_content("Bob")
-        validate_username_content("Bob123")
+        validate_username_content("User")
+        validate_username_content("User123")
 
     def test_invalid_name(self):
         """validate_username_content disallows invalid names"""
         with self.assertRaises(ValidationError):
             validate_username_content("!")
         with self.assertRaises(ValidationError):
-            validate_username_content("Bob!")
+            validate_username_content("User!")
         with self.assertRaises(ValidationError):
-            validate_username_content("Bob Boberson")
+            validate_username_content("John Doe")
         with self.assertRaises(ValidationError):
             validate_username_content("Rafał")
         with self.assertRaises(ValidationError):
@@ -145,14 +140,12 @@ class ValidateGmailEmailTests(TestCase):
 
         validate_gmail_email(None, {}, add_errors)
         validate_gmail_email(None, {"email": "invalid-email"}, add_errors)
-        validate_gmail_email(None, {"email": "the.bob.boberson@gmail.com"}, add_errors)
-        validate_gmail_email(
-            None, {"email": "the.bob.boberson@hotmail.com"}, add_errors
-        )
+        validate_gmail_email(None, {"email": "the.valid.email@gmail.com"}, add_errors)
+        validate_gmail_email(None, {"email": "the.valid.email@hotmail.com"}, add_errors)
 
         self.assertFalse(added_errors)
 
         validate_gmail_email(
-            None, {"email": "the.b.o.b.b.ob.e.r.son@gmail.com"}, add_errors
+            None, {"email": "the.s.p.a.m.my.e.ma.il@gmail.com"}, add_errors
         )
         self.assertTrue(added_errors)