Browse Source

Merge pull request #1157 from rafalp/tests-cleanup

Small tests cleanups
Rafał Pitoń 6 years ago
parent
commit
a53858c6f3
152 changed files with 1330 additions and 1350 deletions
  1. 1 1
      misago/acl/tests/test_roleadmin_views.py
  2. 1 1
      misago/admin/test.py
  3. 143 125
      misago/admin/tests/test_admin_form_templatetags.py
  4. 1 1
      misago/admin/tests/test_admin_index.py
  5. 2 2
      misago/admin/tests/test_admin_views.py
  6. 5 5
      misago/categories/tests/test_categories_admin_views.py
  7. 2 2
      misago/categories/tests/test_category_model.py
  8. 1 1
      misago/categories/tests/test_permissions_admin_views.py
  9. 13 13
      misago/categories/tests/test_prunecategories.py
  10. 3 3
      misago/categories/tests/test_synchronizecategories.py
  11. 1 1
      misago/categories/tests/test_utils.py
  12. 1 1
      misago/categories/tests/test_views.py
  13. 1 1
      misago/conf/tests/test_admin_views.py
  14. 2 2
      misago/conftest.py
  15. 1 1
      misago/core/tests/test_common_middleware_redirect.py
  16. 1 1
      misago/core/tests/test_mail.py
  17. 34 34
      misago/core/tests/test_serializers.py
  18. 4 4
      misago/core/tests/test_shortcuts.py
  19. 1 1
      misago/legal/tests/test_admin_views.py
  20. 1 1
      misago/legal/tests/test_api.py
  21. 1 1
      misago/legal/tests/test_context_processors.py
  22. 1 1
      misago/legal/tests/test_required_agreement.py
  23. 1 1
      misago/legal/tests/test_utils.py
  24. 1 1
      misago/markup/tests/test_api.py
  25. 1 1
      misago/markup/tests/test_mentions.py
  26. 1 1
      misago/markup/tests/test_parser.py
  27. 26 26
      misago/readtracker/tests/test_categoriestracker.py
  28. 7 7
      misago/readtracker/tests/test_clearreadtracker.py
  29. 9 9
      misago/readtracker/tests/test_poststracker.py
  30. 21 21
      misago/readtracker/tests/test_threadstracker.py
  31. 1 1
      misago/search/tests/test_api.py
  32. 1 1
      misago/search/tests/test_views.py
  33. 218 0
      misago/threads/test.py
  34. 8 8
      misago/threads/tests/test_anonymize_data.py
  35. 3 3
      misago/threads/tests/test_attachmentadmin_views.py
  36. 1 1
      misago/threads/tests/test_attachments_api.py
  37. 4 4
      misago/threads/tests/test_attachments_middleware.py
  38. 3 3
      misago/threads/tests/test_attachmenttypeadmin_views.py
  39. 3 3
      misago/threads/tests/test_attachmentview.py
  40. 8 8
      misago/threads/tests/test_clearattachments.py
  41. 4 4
      misago/threads/tests/test_delete_user_likes.py
  42. 4 4
      misago/threads/tests/test_emailnotification_middleware.py
  43. 1 1
      misago/threads/tests/test_events.py
  44. 3 3
      misago/threads/tests/test_floodprotection.py
  45. 1 1
      misago/threads/tests/test_floodprotection_middleware.py
  46. 27 27
      misago/threads/tests/test_gotoviews.py
  47. 7 7
      misago/threads/tests/test_mergeconflict.py
  48. 13 13
      misago/threads/tests/test_participants.py
  49. 18 18
      misago/threads/tests/test_post_mentions.py
  50. 1 1
      misago/threads/tests/test_post_model.py
  51. 4 4
      misago/threads/tests/test_posts_moderation.py
  52. 3 3
      misago/threads/tests/test_privatethread_patch_api.py
  53. 3 3
      misago/threads/tests/test_privatethread_reply_api.py
  54. 1 1
      misago/threads/tests/test_privatethread_start_api.py
  55. 2 2
      misago/threads/tests/test_privatethread_view.py
  56. 1 1
      misago/threads/tests/test_privatethreads.py
  57. 6 6
      misago/threads/tests/test_privatethreads_api.py
  58. 4 4
      misago/threads/tests/test_privatethreads_lists.py
  59. 18 20
      misago/threads/tests/test_search.py
  60. 4 4
      misago/threads/tests/test_subscription_middleware.py
  61. 3 3
      misago/threads/tests/test_subscriptions.py
  62. 4 4
      misago/threads/tests/test_sync_unread_private_threads.py
  63. 3 3
      misago/threads/tests/test_synchronizethreads.py
  64. 6 6
      misago/threads/tests/test_thread_bulkpatch_api.py
  65. 4 4
      misago/threads/tests/test_thread_editreply_api.py
  66. 52 52
      misago/threads/tests/test_thread_merge_api.py
  67. 10 10
      misago/threads/tests/test_thread_model.py
  68. 28 28
      misago/threads/tests/test_thread_patch_api.py
  69. 4 4
      misago/threads/tests/test_thread_poll_api.py
  70. 4 5
      misago/threads/tests/test_thread_pollvotes_api.py
  71. 6 6
      misago/threads/tests/test_thread_postbulkdelete_api.py
  72. 8 8
      misago/threads/tests/test_thread_postbulkpatch_api.py
  73. 3 5
      misago/threads/tests/test_thread_postdelete_api.py
  74. 2 2
      misago/threads/tests/test_thread_postedits_api.py
  75. 6 6
      misago/threads/tests/test_thread_postlikes_api.py
  76. 42 48
      misago/threads/tests/test_thread_postmerge_api.py
  77. 35 40
      misago/threads/tests/test_thread_postmove_api.py
  78. 11 13
      misago/threads/tests/test_thread_postpatch_api.py
  79. 2 2
      misago/threads/tests/test_thread_postread_api.py
  80. 13 19
      misago/threads/tests/test_thread_postsplit_api.py
  81. 3 3
      misago/threads/tests/test_thread_reply_api.py
  82. 1 1
      misago/threads/tests/test_thread_start_api.py
  83. 1 1
      misago/threads/tests/test_threadparticipant_model.py
  84. 6 6
      misago/threads/tests/test_threads_api.py
  85. 4 4
      misago/threads/tests/test_threads_bulkdelete_api.py
  86. 11 11
      misago/threads/tests/test_threads_editor_api.py
  87. 57 57
      misago/threads/tests/test_threads_merge_api.py
  88. 4 4
      misago/threads/tests/test_threads_moderation.py
  89. 46 58
      misago/threads/tests/test_threadslists.py
  90. 22 22
      misago/threads/tests/test_threadview.py
  91. 3 3
      misago/threads/tests/test_updatepostschecksums.py
  92. 12 12
      misago/threads/tests/test_utils.py
  93. 1 1
      misago/threads/tests/test_validate_post.py
  94. 0 217
      misago/threads/testutils.py
  95. 2 2
      misago/users/models/ban.py
  96. 0 0
      misago/users/test.py
  97. 26 30
      misago/users/tests/test_activation_views.py
  98. 2 2
      misago/users/tests/test_activepostersranking.py
  99. 1 1
      misago/users/tests/test_audittrail.py
  100. 1 1
      misago/users/tests/test_auth_api.py
  101. 1 1
      misago/users/tests/test_auth_backend.py
  102. 1 1
      misago/users/tests/test_auth_views.py
  103. 1 1
      misago/users/tests/test_avatars.py
  104. 1 1
      misago/users/tests/test_avatarserver_views.py
  105. 26 21
      misago/users/tests/test_ban_model.py
  106. 1 1
      misago/users/tests/test_banadmin_views.py
  107. 4 4
      misago/users/tests/test_bans.py
  108. 1 1
      misago/users/tests/test_bio_profilefield.py
  109. 1 1
      misago/users/tests/test_credentialchange.py
  110. 2 2
      misago/users/tests/test_datadownloads.py
  111. 1 1
      misago/users/tests/test_datadownloads_dataarchive.py
  112. 2 2
      misago/users/tests/test_datadownloadsadmin_views.py
  113. 1 1
      misago/users/tests/test_decorators.py
  114. 1 1
      misago/users/tests/test_deleteinactiveusers.py
  115. 1 1
      misago/users/tests/test_deletemarkedusers.py
  116. 1 1
      misago/users/tests/test_deleteprofilefield.py
  117. 1 1
      misago/users/tests/test_djangoadmin_auth.py
  118. 2 2
      misago/users/tests/test_djangoadmin_user.py
  119. 1 1
      misago/users/tests/test_expireuserdatadownloads.py
  120. 1 1
      misago/users/tests/test_forgottenpassword_views.py
  121. 1 1
      misago/users/tests/test_gender_profilefield.py
  122. 1 1
      misago/users/tests/test_getting_user_status.py
  123. 1 1
      misago/users/tests/test_invalidatebans.py
  124. 1 1
      misago/users/tests/test_joinip_profilefield.py
  125. 2 2
      misago/users/tests/test_lists_views.py
  126. 1 1
      misago/users/tests/test_listusedprofilefields.py
  127. 10 10
      misago/users/tests/test_mention_api.py
  128. 1 1
      misago/users/tests/test_options_views.py
  129. 1 1
      misago/users/tests/test_prepareuserdatadownloads.py
  130. 9 9
      misago/users/tests/test_profile_views.py
  131. 1 1
      misago/users/tests/test_rankadmin_views.py
  132. 1 1
      misago/users/tests/test_rest_permissions.py
  133. 1 1
      misago/users/tests/test_search.py
  134. 1 1
      misago/users/tests/test_social_pipeline.py
  135. 1 5
      misago/users/tests/test_testutils.py
  136. 1 1
      misago/users/tests/test_twitter_profilefield.py
  137. 1 1
      misago/users/tests/test_user_avatar_api.py
  138. 1 1
      misago/users/tests/test_user_changeemail_api.py
  139. 1 1
      misago/users/tests/test_user_changepassword_api.py
  140. 20 20
      misago/users/tests/test_user_create_api.py
  141. 1 1
      misago/users/tests/test_user_datadownloads_api.py
  142. 1 1
      misago/users/tests/test_user_details_api.py
  143. 1 1
      misago/users/tests/test_user_editdetails_api.py
  144. 17 17
      misago/users/tests/test_user_feeds_api.py
  145. 1 1
      misago/users/tests/test_user_middleware.py
  146. 1 1
      misago/users/tests/test_user_requestdatadownload_api.py
  147. 1 1
      misago/users/tests/test_user_signature_api.py
  148. 1 1
      misago/users/tests/test_user_username_api.py
  149. 82 82
      misago/users/tests/test_useradmin_views.py
  150. 1 1
      misago/users/tests/test_usernamechanges_api.py
  151. 2 2
      misago/users/tests/test_users_api.py
  152. 1 1
      misago/users/tests/test_validators.py

+ 1 - 1
misago/acl/tests/test_roleadmin_views.py

@@ -4,7 +4,7 @@ from misago.acl import ACL_CACHE
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.acl.test import mock_role_form_data
 from misago.acl.test import mock_role_form_data
 from misago.cache.test import assert_invalidates_cache
 from misago.cache.test import assert_invalidates_cache
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 
 
 
 
 def create_data(data_dict):
 def create_data(data_dict):

+ 1 - 1
misago/admin/testutils.py → misago/admin/test.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.users.testutils import SuperUserTestCase
+from misago.users.test import SuperUserTestCase
 
 
 
 
 class AdminTestCase(SuperUserTestCase):
 class AdminTestCase(SuperUserTestCase):

+ 143 - 125
misago/admin/tests/test_admin_form_templatetags.py

@@ -1,6 +1,6 @@
+import pytest
 from django import forms
 from django import forms
 from django.template import Context, Template, TemplateSyntaxError
 from django.template import Context, Template, TemplateSyntaxError
-from django.test import TestCase
 
 
 from misago.admin.templatetags.misago_admin_form import (
 from misago.admin.templatetags.misago_admin_form import (
     is_radio_select_field,
     is_radio_select_field,
@@ -13,7 +13,7 @@ from misago.admin.templatetags.misago_admin_form import (
 from misago.admin.forms import YesNoSwitch
 from misago.admin.forms import YesNoSwitch
 
 
 
 
-class TestForm(forms.Form):
+class Form(forms.Form):
     text_field = forms.CharField(
     text_field = forms.CharField(
         label="Hello!", max_length=255, help_text="I am a help text."
         label="Hello!", max_length=255, help_text="I am a help text."
     )
     )
@@ -34,174 +34,192 @@ class TestForm(forms.Form):
     yesno_field = YesNoSwitch(label="Switch")
     yesno_field = YesNoSwitch(label="Switch")
 
 
 
 
+@pytest.fixture
+def form():
+    return Form()
+
+
 def render(template_str):
 def render(template_str):
     base_template = "{%% load misago_admin_form %%} %s"
     base_template = "{%% load misago_admin_form %%} %s"
-    context = Context({"form": TestForm()})
+    context = Context({"form": Form()})
     template = Template(base_template % template_str)
     template = Template(base_template % template_str)
     return template.render(context).strip()
     return template.render(context).strip()
 
 
 
 
-class FormRowTagTests(TestCase):
-    def test_row_with_field_input_is_rendered(self):
-        html = render("{% form_row form.text_field %}")
-        self.assertIn("id_text_field", html)
+def test_row_with_field_input_is_rendered():
+    html = render("{% form_row form.text_field %}")
+    assert "id_text_field" in html
+
+
+def test_row_with_field_input_and_label_css_class_is_rendered():
+    html = render('{% form_row form.text_field label_class="col-md-3" %}')
+    assert "id_text_field" in html
+    assert "col-md-3" in html
+
+
+def test_row_with_field_input_and_field_css_class_is_rendered():
+    html = render('{% form_row form.text_field field_class="col-md-9" %}')
+    assert "id_text_field" in html
+    assert "col-md-9" in html
+
+
+def test_row_with_field_input_and_label_andfield_css_classes_is_rendered():
+    html = render('{% form_row form.text_field "col-md-3" "col-md-9" %}')
+    assert "id_text_field" in html
+    assert "col-md-3" in html
+    assert "col-md-9" in html
+
+
+def test_tag_without_field_raises_exception():
+    with pytest.raises(TemplateSyntaxError):
+        render("{% form_row %}")
+
+
+def test_field_label_is_rendered():
+    html = render("{% form_row form.text_field %}")
+    assert "Hello!" in html
+
+
+def test_field_help_text_is_rendered():
+    html = render("{% form_row form.text_field %}")
+    assert "I am a help text." in html
+
+
+def test_for_field_with_radio_select_widget_filter_returns_true(form):
+    assert is_radio_select_field(form["yesno_field"])
+
+
+def test_for_field_without_radio_select_widget_filter_returns_false(form):
+    assert not is_radio_select_field(form["text_field"])
+
+
+def test_for_field_with_select_widget_filter_returns_true(form):
+    assert is_select_field(form["select_field"])
+
+
+def teste_for_field_without_select_widget_filter_returns_false(form):
+    assert not is_select_field(form["text_field"])
+
+
+def test_for_field_with_checkbox_select_widget_filter_returns_true(form):
+    assert is_multiple_choice_field(form["checkbox_select_field"])
+
+
+def test_for_field_without_checkbox_select_widget_filter_returns_false(form):
+    assert not is_multiple_choice_field(form["text_field"])
+
+
+def test_for_field_with_multiple_select_widget_filter_returns_true(form):
+    assert is_multiple_choice_field(form["multiple_select_field"])
+
+
+def test_for_field_without_multiple_select_widget_filter_returns_false(form):
+    assert not is_multiple_choice_field(form["text_field"])
+
+
+def test_for_field_with_textarea_widget_filter_returns_true(form):
+    assert is_textarea_field(form["textarea_field"])
 
 
-    def test_row_with_field_input_and_label_css_class_is_rendered(self):
-        html = render('{% form_row form.text_field label_class="col-md-3" %}')
-        self.assertIn("id_text_field", html)
-        self.assertIn("col-md-3", html)
 
 
-    def test_row_with_field_input_and_field_css_class_is_rendered(self):
-        html = render('{% form_row form.text_field field_class="col-md-9" %}')
-        self.assertIn("id_text_field", html)
-        self.assertIn("col-md-9", html)
+def test_for_field_without_textarea_widget_filter_returns_false(form):
+    assert not is_textarea_field(form["text_field"])
 
 
-    def test_row_with_field_input_and_label_andfield_css_classes_is_rendered(self):
-        html = render('{% form_row form.text_field "col-md-3" "col-md-9" %}')
-        self.assertIn("id_text_field", html)
-        self.assertIn("col-md-3", html)
-        self.assertIn("col-md-9", html)
 
 
-    def test_tag_without_field_raises_exception(self):
-        with self.assertRaises(TemplateSyntaxError):
-            render("{% form_row %}")
+def test_specified_class_name_is_rendered():
+    result = render_attrs({"attrs": {}}, class_name="form-control")
+    assert result == 'class="form-control"'
 
 
-    def test_field_label_is_rendered(self):
-        html = render("{% form_row form.text_field %}")
-        self.assertIn("Hello!", html)
 
 
-    def test_field_help_text_is_rendered(self):
-        html = render("{% form_row form.text_field %}")
-        self.assertIn("I am a help text.", html)
+def test_specified_class_name_overrided_by_class_attr():
+    result = render_attrs({"attrs": {"class": "custom"}}, class_name="form-control")
+    assert result == 'class="custom"'
 
 
 
 
-class IsRadioSelectFieldFilterTests(TestCase):
-    def test_for_field_with_radio_select_widget_filter_returns_true(self):
-        form = TestForm()
-        self.assertTrue(is_radio_select_field(form["yesno_field"]))
+def test_attr_with_string_value_is_rendered():
+    result = render_attrs({"attrs": {"name": "lorem"}})
+    assert result == 'name="lorem"'
 
 
-    def test_for_field_without_radio_select_widget_filter_returns_false(self):
-        form = TestForm()
-        self.assertFalse(is_radio_select_field(form["text_field"]))
 
 
+def test_attr_with_int_value_is_rendered():
+    result = render_attrs({"attrs": {"cols": 5}})
+    assert result == 'cols="5"'
 
 
-class IsSelectFieldFilerTests(TestCase):
-    def test_for_field_with_select_widget_filter_returns_true(self):
-        form = TestForm()
-        self.assertTrue(is_select_field(form["select_field"]))
 
 
-    def teste_for_field_without_select_widget_filter_returns_false(self):
-        form = TestForm()
-        self.assertFalse(is_select_field(form["text_field"]))
+def test_attr_with_boolean_true_value_is_not_rendered():
+    result = render_attrs({"attrs": {"selected": True}})
+    assert result == ""
 
 
 
 
-class IsMultipleChoiceFieldFilerTests(TestCase):
-    def test_for_field_with_checkbox_select_widget_filter_returns_true(self):
-        form = TestForm()
-        self.assertTrue(is_multiple_choice_field(form["checkbox_select_field"]))
+def test_attr_with_boolean_false_value_is_not_rendered():
+    result = render_attrs({"attrs": {"selected": False}})
+    assert result == ""
 
 
-    def test_for_field_without_checkbox_select_widget_filter_returns_false(self):
-        form = TestForm()
-        self.assertFalse(is_multiple_choice_field(form["text_field"]))
 
 
-    def test_for_field_with_multiple_select_widget_filter_returns_true(self):
-        form = TestForm()
-        self.assertTrue(is_multiple_choice_field(form["multiple_select_field"]))
+def test_attr_with_none_value_is_not_rendered():
+    result = render_attrs({"attrs": {"selected": None}})
+    assert result == ""
 
 
-    def test_for_field_without_multiple_select_widget_filter_returns_false(self):
-        form = TestForm()
-        self.assertFalse(is_multiple_choice_field(form["text_field"]))
 
 
+def test_attr_name_is_escaped():
+    result = render_attrs({"attrs": {'"': "test"}})
+    assert result == '"="test"'
 
 
-class IsTextareaFieldFilterTests(TestCase):
-    def test_for_field_with_textarea_widget_filter_returns_true(self):
-        form = TestForm()
-        self.assertTrue(is_textarea_field(form["textarea_field"]))
 
 
-    def test_for_field_without_textarea_widget_filter_returns_false(self):
-        form = TestForm()
-        self.assertFalse(is_textarea_field(form["text_field"]))
+def test_attr_value_is_escaped():
+    result = render_attrs({"attrs": {"name": '"'}})
+    assert result == 'name="""'
 
 
 
 
-class RenderAttrsTagTests(TestCase):
-    def test_specified_class_name_is_rendered(self):
-        result = render_attrs({"attrs": {}}, class_name="form-control")
-        self.assertEqual(result, 'class="form-control"')
+def test_multiple_valid_attrs_are_rendered():
+    result = render_attrs({"attrs": {"name": "lorem", "cols": 5}})
+    assert result == 'name="lorem" cols="5"'
 
 
-    def test_specified_class_name_overrided_by_class_attr(self):
-        result = render_attrs({"attrs": {"class": "custom"}}, class_name="form-control")
-        self.assertEqual(result, 'class="custom"')
 
 
-    def test_attr_with_string_value_is_rendered(self):
-        result = render_attrs({"attrs": {"name": "lorem"}})
-        self.assertEqual(result, 'name="lorem"')
+def test_empty_attr_dict_is_not_rendered():
+    result = render_attrs({"attrs": {}})
+    assert result == ""
 
 
-    def test_attr_with_int_value_is_rendered(self):
-        result = render_attrs({"attrs": {"cols": 5}})
-        self.assertEqual(result, 'cols="5"')
 
 
-    def test_attr_with_boolean_true_value_is_not_rendered(self):
-        result = render_attrs({"attrs": {"selected": True}})
-        self.assertEqual(result, "")
+def test_attr_with_boolean_true_value_is_rendered():
+    result = render_bool_attrs({"bool": True})
+    assert result == "bool"
 
 
-    def test_attr_with_boolean_false_value_is_not_rendered(self):
-        result = render_attrs({"attrs": {"selected": False}})
-        self.assertEqual(result, "")
 
 
-    def test_attr_with_none_value_is_not_rendered(self):
-        result = render_attrs({"attrs": {"selected": None}})
-        self.assertEqual(result, "")
+def test_attr_with_string_value_is_not_rendered():
+    result = render_bool_attrs({"name": "hello"})
+    assert result == ""
 
 
-    def test_attr_name_is_escaped(self):
-        result = render_attrs({"attrs": {'"': "test"}})
-        self.assertEqual(result, '"="test"')
 
 
-    def test_attr_value_is_escaped(self):
-        result = render_attrs({"attrs": {"name": '"'}})
-        self.assertEqual(result, 'name="""')
+def test_attr_with_int_value_is_not_rendered():
+    result = render_bool_attrs({"col": 13})
+    assert result == ""
 
 
-    def test_multiple_valid_attrs_are_rendered(self):
-        result = render_attrs({"attrs": {"name": "lorem", "cols": 5}})
-        self.assertEqual(result, 'name="lorem" cols="5"')
 
 
-    def test_empty_attr_dict_is_not_rendered(self):
-        result = render_attrs({"attrs": {}})
-        self.assertEqual(result, "")
+def test_attr_with_boolean_false_value_is_not_rendered():
+    result = render_bool_attrs({"selected": False})
+    assert result == ""
 
 
 
 
-class RenderBoolAttrsTagTests(TestCase):
-    def test_attr_with_boolean_true_value_is_rendered(self):
-        result = render_bool_attrs({"bool": True})
-        self.assertEqual(result, "bool")
+def test_attr_with_none_value_is_not_rendered():
+    result = render_bool_attrs({"selected": None})
+    assert result == ""
 
 
-    def test_attr_with_string_value_is_not_rendered(self):
-        result = render_bool_attrs({"name": "hello"})
-        self.assertEqual(result, "")
 
 
-    def test_attr_with_int_value_is_not_rendered(self):
-        result = render_bool_attrs({"col": 13})
-        self.assertEqual(result, "")
+def test_attr_with_false_int_value_is_not_rendered():
+    result = render_bool_attrs({"selected": 0})
+    assert result == ""
 
 
-    def test_attr_with_boolean_false_value_is_not_rendered(self):
-        result = render_bool_attrs({"selected": False})
-        self.assertEqual(result, "")
 
 
-    def test_attr_with_none_value_is_not_rendered(self):
-        result = render_bool_attrs({"selected": None})
-        self.assertEqual(result, "")
+def test_multiple_attrs_with_boolean_true_value_are_rendered():
+    result = render_bool_attrs({"selected": True, "required": True})
+    assert result == "selected required"
 
 
-    def test_attr_with_false_int_value_is_not_rendered(self):
-        result = render_bool_attrs({"selected": 0})
-        self.assertEqual(result, "")
 
 
-    def test_multiple_attrs_with_boolean_true_value_are_rendered(self):
-        result = render_bool_attrs({"selected": True, "required": True})
-        self.assertEqual(result, "selected required")
+def test_only_attrs_with_boolean_true_value_are_rendered():
+    result = render_bool_attrs({"bool": True, "string": "hello", "int": 123})
+    assert result == "bool"
 
 
-    def test_only_attrs_with_boolean_true_value_are_rendered(self):
-        result = render_bool_attrs({"bool": True, "string": "hello", "int": 123})
-        self.assertEqual(result, "bool")
 
 
-    def test_empty_attr_dict_is_not_rendered(self):
-        result = render_bool_attrs({})
-        self.assertEqual(result, "")
+def test_empty_attr_dict_is_not_rendered():
+    result = render_bool_attrs({})
+    assert result == ""

+ 1 - 1
misago/admin/tests/test_admin_index.py

@@ -1,7 +1,7 @@
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.admin.views.index import check_misago_address
 from misago.admin.views.index import check_misago_address
 
 
 
 

+ 2 - 2
misago/admin/tests/test_admin_views.py

@@ -1,9 +1,9 @@
 from django.test import TestCase
 from django.test import TestCase
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.admin.views import get_protected_namespace
 from misago.admin.views import get_protected_namespace
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 5 - 5
misago/categories/tests/test_categories_admin_views.py

@@ -1,10 +1,10 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl import ACL_CACHE
 from misago.acl import ACL_CACHE
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.cache.test import assert_invalidates_cache
 from misago.cache.test import assert_invalidates_cache
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 
 
 
 
@@ -472,7 +472,7 @@ class CategoryAdminDeleteViewTests(CategoryAdminTestCase):
     def test_delete_category_move_contents(self):
     def test_delete_category_move_contents(self):
         """category was deleted and its contents were moved"""
         """category was deleted and its contents were moved"""
         for _ in range(10):
         for _ in range(10):
-            testutils.post_thread(self.category_b)
+            test.post_thread(self.category_b)
         self.assertEqual(Thread.objects.count(), 10)
         self.assertEqual(Thread.objects.count(), 10)
 
 
         response = self.client.get(
         response = self.client.get(
@@ -514,7 +514,7 @@ class CategoryAdminDeleteViewTests(CategoryAdminTestCase):
     def test_delete_category_and_contents(self):
     def test_delete_category_and_contents(self):
         """category and its contents were deleted"""
         """category and its contents were deleted"""
         for _ in range(10):
         for _ in range(10):
-            testutils.post_thread(self.category_b)
+            test.post_thread(self.category_b)
 
 
         response = self.client.get(
         response = self.client.get(
             reverse(
             reverse(
@@ -549,7 +549,7 @@ class CategoryAdminDeleteViewTests(CategoryAdminTestCase):
     def test_delete_leaf_category_and_contents(self):
     def test_delete_leaf_category_and_contents(self):
         """leaf category was deleted with contents"""
         """leaf category was deleted with contents"""
         for _ in range(10):
         for _ in range(10):
-            testutils.post_thread(self.category_d)
+            test.post_thread(self.category_d)
         self.assertEqual(Thread.objects.count(), 10)
         self.assertEqual(Thread.objects.count(), 10)
 
 
         response = self.client.get(
         response = self.client.get(

+ 2 - 2
misago/categories/tests/test_category_model.py

@@ -2,7 +2,7 @@ from django.test import TestCase
 
 
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.threadtypes import trees_map
 from misago.threads.threadtypes import trees_map
 
 
 
 
@@ -53,7 +53,7 @@ class CategoryModelTests(TestCase):
         self.category = Category.objects.all_categories()[:1][0]
         self.category = Category.objects.all_categories()[:1][0]
 
 
     def create_thread(self):
     def create_thread(self):
-        return testutils.post_thread(self.category)
+        return test.post_thread(self.category)
 
 
     def assertCategoryIsEmpty(self):
     def assertCategoryIsEmpty(self):
         self.assertIsNone(self.category.last_post_on)
         self.assertIsNone(self.category.last_post_on)

+ 1 - 1
misago/categories/tests/test_permissions_admin_views.py

@@ -3,7 +3,7 @@ from django.urls import reverse
 from misago.acl import ACL_CACHE
 from misago.acl import ACL_CACHE
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.acl.test import mock_role_form_data
 from misago.acl.test import mock_role_form_data
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.cache.test import assert_invalidates_cache
 from misago.cache.test import assert_invalidates_cache
 from misago.categories.models import Category, CategoryRole
 from misago.categories.models import Category, CategoryRole
 
 

+ 13 - 13
misago/categories/tests/test_prunecategories.py

@@ -7,7 +7,7 @@ from django.utils import timezone
 
 
 from misago.categories.management.commands import prunecategories
 from misago.categories.management.commands import prunecategories
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 
 
 
 
 class PruneCategoriesTests(TestCase):
 class PruneCategoriesTests(TestCase):
@@ -22,11 +22,11 @@ class PruneCategoriesTests(TestCase):
         started_on = timezone.now() - timedelta(days=30)
         started_on = timezone.now() - timedelta(days=30)
         posted_on = timezone.now()
         posted_on = timezone.now()
         for _ in range(10):
         for _ in range(10):
-            thread = testutils.post_thread(category, started_on=started_on)
-            testutils.reply_thread(thread, posted_on=posted_on)
+            thread = test.post_thread(category, started_on=started_on)
+            test.reply_thread(thread, posted_on=posted_on)
 
 
         # post recent threads that will be preserved
         # post recent threads that will be preserved
-        threads = [testutils.post_thread(category) for _ in range(10)]
+        threads = [test.post_thread(category) for _ in range(10)]
 
 
         category.synchronize()
         category.synchronize()
         self.assertEqual(category.threads, 20)
         self.assertEqual(category.threads, 20)
@@ -58,11 +58,11 @@ class PruneCategoriesTests(TestCase):
         # post old threads with recent replies
         # post old threads with recent replies
         started_on = timezone.now() - timedelta(days=30)
         started_on = timezone.now() - timedelta(days=30)
         for _ in range(10):
         for _ in range(10):
-            thread = testutils.post_thread(category, started_on=started_on)
-            testutils.reply_thread(thread)
+            thread = test.post_thread(category, started_on=started_on)
+            test.reply_thread(thread)
 
 
         # post recent threads that will be preserved
         # post recent threads that will be preserved
-        threads = [testutils.post_thread(category) for _ in range(10)]
+        threads = [test.post_thread(category) for _ in range(10)]
 
 
         category.synchronize()
         category.synchronize()
         self.assertEqual(category.threads, 20)
         self.assertEqual(category.threads, 20)
@@ -99,11 +99,11 @@ class PruneCategoriesTests(TestCase):
         started_on = timezone.now() - timedelta(days=30)
         started_on = timezone.now() - timedelta(days=30)
         posted_on = timezone.now()
         posted_on = timezone.now()
         for _ in range(10):
         for _ in range(10):
-            thread = testutils.post_thread(category, started_on=started_on)
-            testutils.reply_thread(thread, posted_on=posted_on)
+            thread = test.post_thread(category, started_on=started_on)
+            test.reply_thread(thread, posted_on=posted_on)
 
 
         # post recent threads that will be preserved
         # post recent threads that will be preserved
-        threads = [testutils.post_thread(category) for _ in range(10)]
+        threads = [test.post_thread(category) for _ in range(10)]
 
 
         category.synchronize()
         category.synchronize()
         self.assertEqual(category.threads, 20)
         self.assertEqual(category.threads, 20)
@@ -143,11 +143,11 @@ class PruneCategoriesTests(TestCase):
         # post old threads with recent replies
         # post old threads with recent replies
         started_on = timezone.now() - timedelta(days=30)
         started_on = timezone.now() - timedelta(days=30)
         for _ in range(10):
         for _ in range(10):
-            thread = testutils.post_thread(category, started_on=started_on)
-            testutils.reply_thread(thread)
+            thread = test.post_thread(category, started_on=started_on)
+            test.reply_thread(thread)
 
 
         # post recent threads that will be preserved
         # post recent threads that will be preserved
-        threads = [testutils.post_thread(category) for _ in range(10)]
+        threads = [test.post_thread(category) for _ in range(10)]
 
 
         category.synchronize()
         category.synchronize()
         self.assertEqual(category.threads, 20)
         self.assertEqual(category.threads, 20)

+ 3 - 3
misago/categories/tests/test_synchronizecategories.py

@@ -5,7 +5,7 @@ from django.test import TestCase
 
 
 from misago.categories.management.commands import synchronizecategories
 from misago.categories.management.commands import synchronizecategories
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 
 
 
 
 class SynchronizeCategoriesTests(TestCase):
 class SynchronizeCategoriesTests(TestCase):
@@ -13,9 +13,9 @@ class SynchronizeCategoriesTests(TestCase):
         """command synchronizes categories"""
         """command synchronizes categories"""
         category = Category.objects.all_categories()[:1][0]
         category = Category.objects.all_categories()[:1][0]
 
 
-        threads = [testutils.post_thread(category) for _ in range(10)]
+        threads = [test.post_thread(category) for _ in range(10)]
         for thread in threads:
         for thread in threads:
-            [testutils.reply_thread(thread) for _ in range(5)]
+            [test.reply_thread(thread) for _ in range(5)]
 
 
         category.threads = 0
         category.threads = 0
         category.posts = 0
         category.posts = 0

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

@@ -2,7 +2,7 @@ from misago.acl.useracl import get_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.categories.utils import get_categories_tree, get_category_path
 from misago.categories.utils import get_categories_tree, get_category_path
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 

+ 1 - 1
misago/categories/tests/test_views.py

@@ -4,7 +4,7 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class CategoryViewsTests(AuthenticatedUserTestCase):
 class CategoryViewsTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/conf/tests/test_admin_views.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.conf.models import SettingsGroup
 from misago.conf.models import SettingsGroup
 
 
 
 

+ 2 - 2
misago/conftest.py

@@ -6,7 +6,7 @@ from misago.conf.dynamicsettings import DynamicSettings
 from misago.conf.staticsettings import StaticSettings
 from misago.conf.staticsettings import StaticSettings
 from misago.users.constants import BANS_CACHE
 from misago.users.constants import BANS_CACHE
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
-from misago.users.testutils import create_test_superuser, create_test_user
+from misago.users.test import create_test_superuser, create_test_user
 
 
 
 
 def get_cache_versions():
 def get_cache_versions():
@@ -30,7 +30,7 @@ def settings():
 
 
 @pytest.fixture
 @pytest.fixture
 def user_password():
 def user_password():
-    return "password"
+    return "p4ssw0rd!"
 
 
 
 
 @pytest.fixture
 @pytest.fixture

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

@@ -1,4 +1,4 @@
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class CommonMiddlewareRedirectTests(AuthenticatedUserTestCase):
 class CommonMiddlewareRedirectTests(AuthenticatedUserTestCase):

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

@@ -5,7 +5,7 @@ from django.urls import reverse
 from misago.cache.versions import get_cache_versions
 from misago.cache.versions import get_cache_versions
 from misago.conf.dynamicsettings import DynamicSettings
 from misago.conf.dynamicsettings import DynamicSettings
 from misago.core.mail import build_mail, mail_user, mail_users
 from misago.core.mail import build_mail, mail_user, mail_users
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class MailTests(TestCase):
 class MailTests(TestCase):

+ 34 - 34
misago/core/tests/test_serializers.py

@@ -4,21 +4,43 @@ from django.test import TestCase
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.core.serializers import MutableFields
 from misago.core.serializers import MutableFields
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 
 
 
 
+class Serializer(serializers.ModelSerializer, MutableFields):
+    url = serializers.SerializerMethodField()
+
+    class Meta:
+        model = Thread
+        fields = [
+            "id",
+            "title",
+            "replies",
+            "has_unapproved_posts",
+            "started_on",
+            "last_post_on",
+            "last_post_is_event",
+            "last_post",
+            "last_poster_name",
+            "is_unapproved",
+            "is_hidden",
+            "is_closed",
+            "weight",
+        ]
+
+
 class MutableFieldsSerializerTests(TestCase):
 class MutableFieldsSerializerTests(TestCase):
     def test_subset_fields(self):
     def test_subset_fields(self):
         """classmethod subset_fields creates new serializer"""
         """classmethod subset_fields creates new serializer"""
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        thread = testutils.post_thread(category=category)
+        thread = test.post_thread(category=category)
 
 
         fields = ["id", "title", "replies", "last_poster_name"]
         fields = ["id", "title", "replies", "last_poster_name"]
 
 
-        serializer = TestSerializer.subset_fields(*fields)
+        serializer = Serializer.subset_fields(*fields)
         self.assertEqual(
         self.assertEqual(
-            serializer.__name__, "TestSerializerIdTitleRepliesLastPosterNameSubset"
+            serializer.__name__, "SerializerIdTitleRepliesLastPosterNameSubset"
         )
         )
         self.assertEqual(serializer.Meta.fields, fields)
         self.assertEqual(serializer.Meta.fields, fields)
 
 
@@ -33,18 +55,18 @@ class MutableFieldsSerializerTests(TestCase):
             },
             },
         )
         )
 
 
-        self.assertFalse(TestSerializer.Meta.fields == serializer.Meta.fields)
+        self.assertFalse(Serializer.Meta.fields == serializer.Meta.fields)
 
 
     def test_exclude_fields(self):
     def test_exclude_fields(self):
         """classmethod exclude_fields creates new serializer"""
         """classmethod exclude_fields creates new serializer"""
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        thread = testutils.post_thread(category=category)
+        thread = test.post_thread(category=category)
 
 
         kept_fields = ["id", "title", "weight"]
         kept_fields = ["id", "title", "weight"]
-        removed_fields = list(set(TestSerializer.Meta.fields) - set(kept_fields))
+        removed_fields = list(set(Serializer.Meta.fields) - set(kept_fields))
 
 
-        serializer = TestSerializer.exclude_fields(*removed_fields)
-        self.assertEqual(serializer.__name__, "TestSerializerIdTitleWeightSubset")
+        serializer = Serializer.exclude_fields(*removed_fields)
+        self.assertEqual(serializer.__name__, "SerializerIdTitleWeightSubset")
         self.assertEqual(serializer.Meta.fields, kept_fields)
         self.assertEqual(serializer.Meta.fields, kept_fields)
 
 
         serialized_thread = serializer(thread).data
         serialized_thread = serializer(thread).data
@@ -53,36 +75,14 @@ class MutableFieldsSerializerTests(TestCase):
             {"id": thread.id, "title": thread.title, "weight": thread.weight},
             {"id": thread.id, "title": thread.title, "weight": thread.weight},
         )
         )
 
 
-        self.assertFalse(TestSerializer.Meta.fields == serializer.Meta.fields)
+        self.assertFalse(Serializer.Meta.fields == serializer.Meta.fields)
 
 
     def test_extend_fields(self):
     def test_extend_fields(self):
         """classmethod extend_fields creates new serializer"""
         """classmethod extend_fields creates new serializer"""
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        thread = testutils.post_thread(category=category)
+        thread = test.post_thread(category=category)
 
 
-        serializer = TestSerializer.extend_fields("category")
+        serializer = Serializer.extend_fields("category")
 
 
         serialized_thread = serializer(thread).data
         serialized_thread = serializer(thread).data
         self.assertEqual(serialized_thread["category"], category.pk)
         self.assertEqual(serialized_thread["category"], category.pk)
-
-
-class TestSerializer(serializers.ModelSerializer, MutableFields):
-    url = serializers.SerializerMethodField()
-
-    class Meta:
-        model = Thread
-        fields = [
-            "id",
-            "title",
-            "replies",
-            "has_unapproved_posts",
-            "started_on",
-            "last_post_on",
-            "last_post_is_event",
-            "last_post",
-            "last_poster_name",
-            "is_unapproved",
-            "is_hidden",
-            "is_closed",
-            "weight",
-        ]

+ 4 - 4
misago/core/tests/test_shortcuts.py

@@ -61,10 +61,10 @@ class GetIntOr404Tests(TestCase):
         INVALID_VALUES = [
         INVALID_VALUES = [
             None,
             None,
             "",
             "",
-            "bob",
-            "1bob",
-            "b0b",
-            "bob123",
+            "str",
+            "5tr",
+            "s0tr",
+            "str123",
             "12.321",
             "12.321",
             ".4",
             ".4",
             "5.",
             "5.",

+ 1 - 1
misago/legal/tests/test_admin_views.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
 
 
 
 

+ 1 - 1
misago/legal/tests/test_api.py

@@ -3,7 +3,7 @@ import json
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class SubmitAgreementTests(AuthenticatedUserTestCase):
 class SubmitAgreementTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/legal/tests/test_context_processors.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.legal.context_processors import legal_links
 from misago.legal.context_processors import legal_links
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 1 - 1
misago/legal/tests/test_required_agreement.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class RequiredAgreementTests(AuthenticatedUserTestCase):
 class RequiredAgreementTests(AuthenticatedUserTestCase):

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

@@ -7,7 +7,7 @@ from misago.legal.utils import (
     save_user_agreement_acceptance,
     save_user_agreement_acceptance,
     set_agreement_as_active,
     set_agreement_as_active,
 )
 )
-from misago.users.testutils import UserTestCase
+from misago.users.test import UserTestCase
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 1 - 1
misago/markup/tests/test_api.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ParseMarkupApiTests(AuthenticatedUserTestCase):
 class ParseMarkupApiTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/markup/tests/test_mentions.py

@@ -1,5 +1,5 @@
 from misago.markup.mentions import add_mentions
 from misago.markup.mentions import add_mentions
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 1 - 1
misago/markup/tests/test_parser.py

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.markup.parser import parse
 from misago.markup.parser import parse
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 26 - 26
misago/readtracker/tests/test_categoriestracker.py

@@ -9,8 +9,8 @@ from misago.conf import settings
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
 from misago.readtracker import poststracker, categoriestracker
 from misago.readtracker import poststracker, categoriestracker
 from misago.readtracker.models import PostRead
 from misago.readtracker.models import PostRead
-from misago.threads import testutils
-from misago.users.testutils import create_test_user
+from misago.threads import test
+from misago.users.test import create_test_user
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
@@ -35,7 +35,7 @@ class CategoriesTrackerTests(TestCase):
     def test_anon_thread_before_cutoff(self):
     def test_anon_thread_before_cutoff(self):
         """non-tracked thread is marked as read for anonymous users"""
         """non-tracked thread is marked as read for anonymous users"""
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        testutils.post_thread(self.category, started_on=started_on)
+        test.post_thread(self.category, started_on=started_on)
 
 
         categoriestracker.make_read_aware(AnonymousUser(), None, self.category)
         categoriestracker.make_read_aware(AnonymousUser(), None, self.category)
         self.assertTrue(self.category.is_read)
         self.assertTrue(self.category.is_read)
@@ -43,7 +43,7 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_anon_thread_after_cutoff(self):
     def test_anon_thread_after_cutoff(self):
         """tracked thread is marked as read for anonymous users"""
         """tracked thread is marked as read for anonymous users"""
-        testutils.post_thread(self.category, started_on=timezone.now())
+        test.post_thread(self.category, started_on=timezone.now())
 
 
         categoriestracker.make_read_aware(AnonymousUser(), None, self.category)
         categoriestracker.make_read_aware(AnonymousUser(), None, self.category)
         self.assertTrue(self.category.is_read)
         self.assertTrue(self.category.is_read)
@@ -52,7 +52,7 @@ class CategoriesTrackerTests(TestCase):
     def test_user_thread_before_cutoff(self):
     def test_user_thread_before_cutoff(self):
         """non-tracked thread is marked as read for authenticated users"""
         """non-tracked thread is marked as read for authenticated users"""
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        testutils.post_thread(self.category, started_on=started_on)
+        test.post_thread(self.category, started_on=started_on)
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         self.assertTrue(self.category.is_read)
         self.assertTrue(self.category.is_read)
@@ -60,7 +60,7 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_unread_thread(self):
     def test_user_unread_thread(self):
         """tracked thread is marked as unread for authenticated users"""
         """tracked thread is marked as unread for authenticated users"""
-        testutils.post_thread(self.category, started_on=timezone.now())
+        test.post_thread(self.category, started_on=timezone.now())
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         self.assertFalse(self.category.is_read)
         self.assertFalse(self.category.is_read)
@@ -69,7 +69,7 @@ class CategoriesTrackerTests(TestCase):
     def test_user_created_after_thread(self):
     def test_user_created_after_thread(self):
         """tracked thread older than user is marked as read"""
         """tracked thread older than user is marked as read"""
         started_on = timezone.now() - timedelta(days=1)
         started_on = timezone.now() - timedelta(days=1)
-        testutils.post_thread(self.category, started_on=started_on)
+        test.post_thread(self.category, started_on=started_on)
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         self.assertTrue(self.category.is_read)
         self.assertTrue(self.category.is_read)
@@ -77,7 +77,7 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_read_post(self):
     def test_user_read_post(self):
         """tracked thread with read post marked as read"""
         """tracked thread with read post marked as read"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
@@ -87,9 +87,9 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_first_unread_last_read_post(self):
     def test_user_first_unread_last_read_post(self):
         """tracked thread with unread first and last read post marked as unread"""
         """tracked thread with unread first and last read post marked as unread"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
-        post = testutils.reply_thread(thread, posted_on=timezone.now())
+        post = test.reply_thread(thread, posted_on=timezone.now())
         poststracker.save_read(self.user, post)
         poststracker.save_read(self.user, post)
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
@@ -98,10 +98,10 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unread_event(self):
     def test_user_first_read_post_unread_event(self):
         """tracked thread with read first post and unread event"""
         """tracked thread with read first post and unread event"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(thread, posted_on=timezone.now(), is_event=True)
+        test.reply_thread(thread, posted_on=timezone.now(), is_event=True)
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         self.assertFalse(self.category.is_read)
         self.assertFalse(self.category.is_read)
@@ -109,9 +109,9 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_hidden_event(self):
     def test_user_hidden_event(self):
         """tracked thread with unread first post and hidden event"""
         """tracked thread with unread first post and hidden event"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
         )
         )
 
 
@@ -121,10 +121,10 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_first_read_post_hidden_event(self):
     def test_user_first_read_post_hidden_event(self):
         """tracked thread with read first post and hidden event"""
         """tracked thread with read first post and hidden event"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
         )
         )
 
 
@@ -135,7 +135,7 @@ class CategoriesTrackerTests(TestCase):
     def test_user_thread_before_cutoff_unread_post(self):
     def test_user_thread_before_cutoff_unread_post(self):
         """non-tracked thread is marked as unread for anonymous users"""
         """non-tracked thread is marked as unread for anonymous users"""
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        testutils.post_thread(self.category, started_on=started_on)
+        test.post_thread(self.category, started_on=started_on)
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         self.assertTrue(self.category.is_read)
         self.assertTrue(self.category.is_read)
@@ -143,10 +143,10 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unapproved_post(self):
     def test_user_first_read_post_unapproved_post(self):
         """tracked thread with read first post and unapproved post"""
         """tracked thread with read first post and unapproved post"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(thread, posted_on=timezone.now(), is_unapproved=True)
+        test.reply_thread(thread, posted_on=timezone.now(), is_unapproved=True)
 
 
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         categoriestracker.make_read_aware(self.user, self.user_acl, self.category)
         self.assertTrue(self.category.is_read)
         self.assertTrue(self.category.is_read)
@@ -154,10 +154,10 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unapproved_own_post(self):
     def test_user_first_read_post_unapproved_own_post(self):
         """tracked thread with read first post and unapproved own post"""
         """tracked thread with read first post and unapproved own post"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), poster=self.user, is_unapproved=True
             thread, posted_on=timezone.now(), poster=self.user, is_unapproved=True
         )
         )
 
 
@@ -167,10 +167,10 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unapproved_own_post(self):
     def test_user_first_read_post_unapproved_own_post(self):
         """tracked thread with read first post and unapproved own post"""
         """tracked thread with read first post and unapproved own post"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), poster=self.user, is_unapproved=True
             thread, posted_on=timezone.now(), poster=self.user, is_unapproved=True
         )
         )
 
 
@@ -180,7 +180,7 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_unapproved_thread_unread_post(self):
     def test_user_unapproved_thread_unread_post(self):
         """tracked unapproved thread"""
         """tracked unapproved thread"""
-        thread = testutils.post_thread(
+        thread = test.post_thread(
             self.category, started_on=timezone.now(), is_unapproved=True
             self.category, started_on=timezone.now(), is_unapproved=True
         )
         )
 
 
@@ -190,7 +190,7 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_unapproved_own_thread_unread_post(self):
     def test_user_unapproved_own_thread_unread_post(self):
         """tracked unapproved but visible thread"""
         """tracked unapproved but visible thread"""
-        thread = testutils.post_thread(
+        thread = test.post_thread(
             self.category,
             self.category,
             poster=self.user,
             poster=self.user,
             started_on=timezone.now(),
             started_on=timezone.now(),
@@ -203,7 +203,7 @@ class CategoriesTrackerTests(TestCase):
 
 
     def test_user_hidden_thread_unread_post(self):
     def test_user_hidden_thread_unread_post(self):
         """tracked hidden thread"""
         """tracked hidden thread"""
-        thread = testutils.post_thread(
+        thread = test.post_thread(
             self.category, started_on=timezone.now(), is_hidden=True
             self.category, started_on=timezone.now(), is_hidden=True
         )
         )
 
 

+ 7 - 7
misago/readtracker/tests/test_clearreadtracker.py

@@ -9,14 +9,14 @@ from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.readtracker.management.commands import clearreadtracker
 from misago.readtracker.management.commands import clearreadtracker
 from misago.readtracker.models import PostRead
 from misago.readtracker.models import PostRead
-from misago.threads import testutils
-from misago.users.testutils import create_test_user
+from misago.threads import test
+from misago.users.test import create_test_user
 
 
 
 
 class ClearReadTrackerTests(TestCase):
 class ClearReadTrackerTests(TestCase):
     def setUp(self):
     def setUp(self):
-        self.user_1 = create_test_user("User1", "user1@example.com")
-        self.user_2 = create_test_user("User2", "user2@example.com")
+        self.user = create_test_user("User", "user@example.com")
+        self.other_user = create_test_user("OtherUser", "otheruser@example.com")
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
 
 
@@ -32,10 +32,10 @@ class ClearReadTrackerTests(TestCase):
 
 
     def test_delete_expired_entries(self):
     def test_delete_expired_entries(self):
         """test deletes one expired tracker entry, but spares the other"""
         """test deletes one expired tracker entry, but spares the other"""
-        thread = testutils.post_thread(self.category)
+        thread = test.post_thread(self.category)
 
 
         existing = PostRead.objects.create(
         existing = PostRead.objects.create(
-            user=self.user_1,
+            user=self.user,
             category=self.category,
             category=self.category,
             thread=thread,
             thread=thread,
             post=thread.first_post,
             post=thread.first_post,
@@ -43,7 +43,7 @@ class ClearReadTrackerTests(TestCase):
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF / 4),
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF / 4),
         )
         )
         deleted = PostRead.objects.create(
         deleted = PostRead.objects.create(
-            user=self.user_2,
+            user=self.other_user,
             category=self.category,
             category=self.category,
             thread=thread,
             thread=thread,
             post=thread.first_post,
             post=thread.first_post,

+ 9 - 9
misago/readtracker/tests/test_poststracker.py

@@ -7,8 +7,8 @@ from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
 from misago.readtracker.models import PostRead
 from misago.readtracker.models import PostRead
-from misago.threads import testutils
-from misago.users.testutils import create_test_user
+from misago.threads import test
+from misago.users.test import create_test_user
 
 
 
 
 class AnonymousUser(object):
 class AnonymousUser(object):
@@ -20,7 +20,7 @@ class PostsTrackerTests(TestCase):
     def setUp(self):
     def setUp(self):
         self.user = create_test_user("User", "user@example.com")
         self.user = create_test_user("User", "user@example.com")
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(self.category)
+        self.thread = test.post_thread(self.category)
 
 
     def test_falsy_value(self):
     def test_falsy_value(self):
         """passing falsy value to readtracker causes no errors"""
         """passing falsy value to readtracker causes no errors"""
@@ -31,7 +31,7 @@ class PostsTrackerTests(TestCase):
     def test_anon_post_before_cutoff(self):
     def test_anon_post_before_cutoff(self):
         """non-tracked post is marked as read for anonymous users"""
         """non-tracked post is marked as read for anonymous users"""
         posted_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         posted_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        post = testutils.reply_thread(self.thread, posted_on=posted_on)
+        post = test.reply_thread(self.thread, posted_on=posted_on)
 
 
         poststracker.make_read_aware(AnonymousUser(), post)
         poststracker.make_read_aware(AnonymousUser(), post)
         self.assertTrue(post.is_read)
         self.assertTrue(post.is_read)
@@ -39,7 +39,7 @@ class PostsTrackerTests(TestCase):
 
 
     def test_anon_post_after_cutoff(self):
     def test_anon_post_after_cutoff(self):
         """tracked post is marked as read for anonymous users"""
         """tracked post is marked as read for anonymous users"""
-        post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+        post = test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         poststracker.make_read_aware(AnonymousUser(), post)
         poststracker.make_read_aware(AnonymousUser(), post)
         self.assertTrue(post.is_read)
         self.assertTrue(post.is_read)
@@ -48,7 +48,7 @@ class PostsTrackerTests(TestCase):
     def test_user_post_before_cutoff(self):
     def test_user_post_before_cutoff(self):
         """untracked post is marked as read for authenticated users"""
         """untracked post is marked as read for authenticated users"""
         posted_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         posted_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        post = testutils.reply_thread(self.thread, posted_on=posted_on)
+        post = test.reply_thread(self.thread, posted_on=posted_on)
 
 
         poststracker.make_read_aware(self.user, post)
         poststracker.make_read_aware(self.user, post)
         self.assertTrue(post.is_read)
         self.assertTrue(post.is_read)
@@ -56,7 +56,7 @@ class PostsTrackerTests(TestCase):
 
 
     def test_user_unread_post(self):
     def test_user_unread_post(self):
         """tracked post is marked as unread for authenticated users"""
         """tracked post is marked as unread for authenticated users"""
-        post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+        post = test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         poststracker.make_read_aware(self.user, post)
         poststracker.make_read_aware(self.user, post)
         self.assertFalse(post.is_read)
         self.assertFalse(post.is_read)
@@ -65,7 +65,7 @@ class PostsTrackerTests(TestCase):
     def test_user_created_after_post(self):
     def test_user_created_after_post(self):
         """tracked post older than user is marked as read"""
         """tracked post older than user is marked as read"""
         posted_on = timezone.now() - timedelta(days=1)
         posted_on = timezone.now() - timedelta(days=1)
-        post = testutils.reply_thread(self.thread, posted_on=posted_on)
+        post = test.reply_thread(self.thread, posted_on=posted_on)
 
 
         poststracker.make_read_aware(self.user, post)
         poststracker.make_read_aware(self.user, post)
         self.assertTrue(post.is_read)
         self.assertTrue(post.is_read)
@@ -73,7 +73,7 @@ class PostsTrackerTests(TestCase):
 
 
     def test_user_read_post(self):
     def test_user_read_post(self):
         """tracked post is marked as read for authenticated users with read entry"""
         """tracked post is marked as read for authenticated users with read entry"""
-        post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+        post = test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         poststracker.save_read(self.user, post)
         poststracker.save_read(self.user, post)
         poststracker.make_read_aware(self.user, post)
         poststracker.make_read_aware(self.user, post)

+ 21 - 21
misago/readtracker/tests/test_threadstracker.py

@@ -10,8 +10,8 @@ from misago.conf import settings
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
 from misago.readtracker import poststracker, threadstracker
 from misago.readtracker import poststracker, threadstracker
 from misago.readtracker.models import PostRead
 from misago.readtracker.models import PostRead
-from misago.threads import testutils
-from misago.users.testutils import create_test_user
+from misago.threads import test
+from misago.users.test import create_test_user
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
@@ -38,7 +38,7 @@ class ThreadsTrackerTests(TestCase):
     def test_anon_thread_before_cutoff(self):
     def test_anon_thread_before_cutoff(self):
         """non-tracked thread is marked as read for anonymous users"""
         """non-tracked thread is marked as read for anonymous users"""
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        thread = testutils.post_thread(self.category, started_on=started_on)
+        thread = test.post_thread(self.category, started_on=started_on)
 
 
         threadstracker.make_read_aware(AnonymousUser(), None, thread)
         threadstracker.make_read_aware(AnonymousUser(), None, thread)
         self.assertTrue(thread.is_read)
         self.assertTrue(thread.is_read)
@@ -46,7 +46,7 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_anon_thread_after_cutoff(self):
     def test_anon_thread_after_cutoff(self):
         """tracked thread is marked as read for anonymous users"""
         """tracked thread is marked as read for anonymous users"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
         threadstracker.make_read_aware(AnonymousUser(), None, thread)
         threadstracker.make_read_aware(AnonymousUser(), None, thread)
         self.assertTrue(thread.is_read)
         self.assertTrue(thread.is_read)
@@ -55,7 +55,7 @@ class ThreadsTrackerTests(TestCase):
     def test_user_thread_before_cutoff(self):
     def test_user_thread_before_cutoff(self):
         """non-tracked thread is marked as read for authenticated users"""
         """non-tracked thread is marked as read for authenticated users"""
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        thread = testutils.post_thread(self.category, started_on=started_on)
+        thread = test.post_thread(self.category, started_on=started_on)
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         self.assertTrue(thread.is_read)
         self.assertTrue(thread.is_read)
@@ -63,7 +63,7 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_unread_thread(self):
     def test_user_unread_thread(self):
         """tracked thread is marked as unread for authenticated users"""
         """tracked thread is marked as unread for authenticated users"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         self.assertFalse(thread.is_read)
         self.assertFalse(thread.is_read)
@@ -72,7 +72,7 @@ class ThreadsTrackerTests(TestCase):
     def test_user_created_after_thread(self):
     def test_user_created_after_thread(self):
         """tracked thread older than user is marked as read"""
         """tracked thread older than user is marked as read"""
         started_on = timezone.now() - timedelta(days=1)
         started_on = timezone.now() - timedelta(days=1)
-        thread = testutils.post_thread(self.category, started_on=started_on)
+        thread = test.post_thread(self.category, started_on=started_on)
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         self.assertTrue(thread.is_read)
         self.assertTrue(thread.is_read)
@@ -80,7 +80,7 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_read_post(self):
     def test_user_read_post(self):
         """tracked thread with read post marked as read"""
         """tracked thread with read post marked as read"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
@@ -90,9 +90,9 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_first_unread_last_read_post(self):
     def test_user_first_unread_last_read_post(self):
         """tracked thread with unread first and last read post marked as unread"""
         """tracked thread with unread first and last read post marked as unread"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
-        post = testutils.reply_thread(thread, posted_on=timezone.now())
+        post = test.reply_thread(thread, posted_on=timezone.now())
         poststracker.save_read(self.user, post)
         poststracker.save_read(self.user, post)
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
@@ -101,10 +101,10 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unread_event(self):
     def test_user_first_read_post_unread_event(self):
         """tracked thread with read first post and unread event"""
         """tracked thread with read first post and unread event"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(thread, posted_on=timezone.now(), is_event=True)
+        test.reply_thread(thread, posted_on=timezone.now(), is_event=True)
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         self.assertFalse(thread.is_read)
         self.assertFalse(thread.is_read)
@@ -112,9 +112,9 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_hidden_event(self):
     def test_user_hidden_event(self):
         """tracked thread with unread first post and hidden event"""
         """tracked thread with unread first post and hidden event"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
         )
         )
 
 
@@ -124,10 +124,10 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_first_read_post_hidden_event(self):
     def test_user_first_read_post_hidden_event(self):
         """tracked thread with read first post and hidden event"""
         """tracked thread with read first post and hidden event"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
             thread, posted_on=timezone.now(), is_event=True, is_hidden=True
         )
         )
 
 
@@ -138,7 +138,7 @@ class ThreadsTrackerTests(TestCase):
     def test_user_thread_before_cutoff_unread_post(self):
     def test_user_thread_before_cutoff_unread_post(self):
         """non-tracked thread is marked as unread for anonymous users"""
         """non-tracked thread is marked as unread for anonymous users"""
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         started_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
-        thread = testutils.post_thread(self.category, started_on=started_on)
+        thread = test.post_thread(self.category, started_on=started_on)
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         self.assertTrue(thread.is_read)
         self.assertTrue(thread.is_read)
@@ -146,10 +146,10 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unapproved_post(self):
     def test_user_first_read_post_unapproved_post(self):
         """tracked thread with read first post and unapproved post"""
         """tracked thread with read first post and unapproved post"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(thread, posted_on=timezone.now(), is_unapproved=True)
+        test.reply_thread(thread, posted_on=timezone.now(), is_unapproved=True)
 
 
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         threadstracker.make_read_aware(self.user, self.user_acl, thread)
         self.assertTrue(thread.is_read)
         self.assertTrue(thread.is_read)
@@ -157,10 +157,10 @@ class ThreadsTrackerTests(TestCase):
 
 
     def test_user_first_read_post_unapproved_own_post(self):
     def test_user_first_read_post_unapproved_own_post(self):
         """tracked thread with read first post and unapproved own post"""
         """tracked thread with read first post and unapproved own post"""
-        thread = testutils.post_thread(self.category, started_on=timezone.now())
+        thread = test.post_thread(self.category, started_on=timezone.now())
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             thread, posted_on=timezone.now(), poster=self.user, is_unapproved=True
             thread, posted_on=timezone.now(), poster=self.user, is_unapproved=True
         )
         )
 
 

+ 1 - 1
misago/search/tests/test_api.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.search.searchproviders import searchproviders
 from misago.search.searchproviders import searchproviders
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class SearchApiTests(AuthenticatedUserTestCase):
 class SearchApiTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/search/tests/test_views.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.threads.search import SearchThreads
 from misago.threads.search import SearchThreads
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class LandingTests(AuthenticatedUserTestCase):
 class LandingTests(AuthenticatedUserTestCase):

+ 218 - 0
misago/threads/test.py

@@ -1,5 +1,15 @@
+from datetime import timedelta
+
+from django.contrib.auth import get_user_model
+from django.utils import timezone
+
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
+from misago.core.utils import slugify
+from misago.users.test import create_test_user
+
+from .checksums import update_post_checksum
+from .models import Poll, Post, Thread
 
 
 default_category_acl = {
 default_category_acl = {
     "can_see": 1,
     "can_see": 1,
@@ -107,3 +117,211 @@ def cleanup_patched_acl(user_acl, category_acl, category):
 
 
     if category_acl["can_browse"] and category.id not in browseable_categories:
     if category_acl["can_browse"] and category.id not in browseable_categories:
         browseable_categories.append(category.id)
         browseable_categories.append(category.id)
+
+
+User = get_user_model()
+
+
+def post_thread(
+    category,
+    title="Test thread",
+    poster="Tester",
+    is_global=False,
+    is_pinned=False,
+    is_unapproved=False,
+    is_hidden=False,
+    is_closed=False,
+    started_on=None,
+):
+    started_on = started_on or timezone.now()
+
+    kwargs = {
+        "category": category,
+        "title": title,
+        "slug": slugify(title),
+        "started_on": started_on,
+        "last_post_on": started_on,
+        "is_unapproved": is_unapproved,
+        "is_hidden": is_hidden,
+        "is_closed": is_closed,
+    }
+
+    if is_global:
+        kwargs["weight"] = 2
+    elif is_pinned:
+        kwargs["weight"] = 1
+
+    try:
+        kwargs.update(
+            {
+                "starter": poster,
+                "starter_name": poster.username,
+                "starter_slug": poster.slug,
+                "last_poster": poster,
+                "last_poster_name": poster.username,
+                "last_poster_slug": poster.slug,
+            }
+        )
+    except AttributeError:
+        kwargs.update(
+            {
+                "starter_name": poster,
+                "starter_slug": slugify(poster),
+                "last_poster_name": poster,
+                "last_poster_slug": slugify(poster),
+            }
+        )
+
+    thread = Thread.objects.create(**kwargs)
+    reply_thread(
+        thread,
+        poster=poster,
+        posted_on=started_on,
+        is_hidden=is_hidden,
+        is_unapproved=is_unapproved,
+    )
+
+    return thread
+
+
+def reply_thread(
+    thread,
+    poster="Tester",
+    message="I am test message",
+    is_unapproved=False,
+    is_hidden=False,
+    is_event=False,
+    is_protected=False,
+    has_reports=False,
+    has_open_reports=False,
+    posted_on=None,
+):
+    posted_on = posted_on or thread.last_post_on + timedelta(minutes=5)
+
+    kwargs = {
+        "category": thread.category,
+        "thread": thread,
+        "original": message,
+        "parsed": message,
+        "checksum": "nope",
+        "posted_on": posted_on,
+        "updated_on": posted_on,
+        "is_event": is_event,
+        "is_unapproved": is_unapproved,
+        "is_hidden": is_hidden,
+        "is_protected": is_protected,
+        "has_reports": has_reports,
+        "has_open_reports": has_open_reports,
+    }
+
+    try:
+        kwargs.update({"poster": poster, "poster_name": poster.username})
+    except AttributeError:
+        kwargs.update({"poster_name": poster})
+
+    post = Post.objects.create(**kwargs)
+
+    update_post_checksum(post)
+    post.save()
+
+    thread.synchronize()
+    thread.save()
+    thread.category.synchronize()
+    thread.category.save()
+
+    return post
+
+
+def post_poll(thread, poster):
+    poll = Poll.objects.create(
+        category=thread.category,
+        thread=thread,
+        poster=poster,
+        poster_name=poster.username,
+        poster_slug=poster.slug,
+        question="Lorem ipsum dolor met?",
+        choices=[
+            {"hash": "aaaaaaaaaaaa", "label": "Alpha", "votes": 1},
+            {"hash": "bbbbbbbbbbbb", "label": "Beta", "votes": 0},
+            {"hash": "gggggggggggg", "label": "Gamma", "votes": 2},
+            {"hash": "dddddddddddd", "label": "Delta", "votes": 1},
+        ],
+        allowed_choices=2,
+        votes=4,
+    )
+
+    # one user voted for Alpha choice
+    try:
+        user = User.objects.get(slug="user")
+    except User.DoesNotExist:
+        user = create_test_user("User", "user@example.com")
+
+    poll.pollvote_set.create(
+        category=thread.category,
+        thread=thread,
+        voter=user,
+        voter_name=user.username,
+        voter_slug=user.slug,
+        choice_hash="aaaaaaaaaaaa",
+    )
+
+    # test user voted on third and last choices
+    poll.pollvote_set.create(
+        category=thread.category,
+        thread=thread,
+        voter=poster,
+        voter_name=poster.username,
+        voter_slug=poster.slug,
+        choice_hash="gggggggggggg",
+    )
+    poll.pollvote_set.create(
+        category=thread.category,
+        thread=thread,
+        voter=poster,
+        voter_name=poster.username,
+        voter_slug=poster.slug,
+        choice_hash="dddddddddddd",
+    )
+
+    # somebody else voted on third option before being deleted
+    poll.pollvote_set.create(
+        category=thread.category,
+        thread=thread,
+        voter_name="deleted",
+        voter_slug="deleted",
+        choice_hash="gggggggggggg",
+    )
+
+    return poll
+
+
+def like_post(post, liker=None, username=None):
+    if not post.last_likes:
+        post.last_likes = []
+
+    if liker:
+        like = post.postlike_set.create(
+            category=post.category,
+            thread=post.thread,
+            liker=liker,
+            liker_name=liker.username,
+            liker_slug=liker.slug,
+        )
+
+        post.last_likes = [
+            {"id": liker.id, "username": liker.username}
+        ] + post.last_likes
+    else:
+        like = post.postlike_set.create(
+            category=post.category,
+            thread=post.thread,
+            liker_name=username,
+            liker_slug=slugify(username),
+        )
+
+        post.last_likes = [{"id": None, "username": username}] + post.last_likes
+
+    post.likes += 1
+    post.save()
+
+    return like

+ 8 - 8
misago/threads/tests/test_anonymize_data.py

@@ -4,9 +4,9 @@ from django.urls import reverse
 from misago.cache.versions import get_cache_versions
 from misago.cache.versions import get_cache_versions
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf.dynamicsettings import DynamicSettings
 from misago.conf.dynamicsettings import DynamicSettings
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.api.postendpoints.patch_post import patch_is_liked
 from misago.threads.api.postendpoints.patch_post import patch_is_liked
 from misago.threads.models import Post
 from misago.threads.models import Post
 from misago.threads.participants import (
 from misago.threads.participants import (
@@ -16,7 +16,7 @@ from misago.threads.participants import (
     remove_participant,
     remove_participant,
     set_owner,
     set_owner,
 )
 )
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class AnonymizeEventsTests(AuthenticatedUserTestCase):
 class AnonymizeEventsTests(AuthenticatedUserTestCase):
@@ -25,7 +25,7 @@ class AnonymizeEventsTests(AuthenticatedUserTestCase):
         self.factory = RequestFactory()
         self.factory = RequestFactory()
 
 
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category)
+        self.thread = test.post_thread(category)
 
 
     def get_request(self, user=None):
     def get_request(self, user=None):
         request = self.factory.get("/customer/details")
         request = self.factory.get("/customer/details")
@@ -204,8 +204,8 @@ class AnonymizeLikesTests(AuthenticatedUserTestCase):
     def test_anonymize_user_likes(self):
     def test_anonymize_user_likes(self):
         """post's last like is anonymized by user.anonymize_data"""
         """post's last like is anonymized by user.anonymize_data"""
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        thread = testutils.post_thread(category)
-        post = testutils.reply_thread(thread)
+        thread = test.post_thread(category)
+        post = test.reply_thread(thread)
         post.acl = {"can_like": True}
         post.acl = {"can_like": True}
 
 
         user = create_test_user("OtherUser", "otheruser@example.com")
         user = create_test_user("OtherUser", "otheruser@example.com")
@@ -240,10 +240,10 @@ class AnonymizePostsTests(AuthenticatedUserTestCase):
     def test_anonymize_user_posts(self):
     def test_anonymize_user_posts(self):
         """post is anonymized by user.anonymize_data"""
         """post is anonymized by user.anonymize_data"""
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        thread = testutils.post_thread(category)
+        thread = test.post_thread(category)
 
 
         user = create_test_user("OtherUser", "otheruser@example.com")
         user = create_test_user("OtherUser", "otheruser@example.com")
-        post = testutils.reply_thread(thread, poster=user)
+        post = test.reply_thread(thread, poster=user)
         user.anonymize_data()
         user.anonymize_data()
 
 
         anonymized_post = Post.objects.get(pk=post.pk)
         anonymized_post = Post.objects.get(pk=post.pk)

+ 3 - 3
misago/threads/tests/test_attachmentadmin_views.py

@@ -1,8 +1,8 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Attachment, AttachmentType
 from misago.threads.models import Attachment, AttachmentType
 
 
 
 
@@ -11,7 +11,7 @@ class AttachmentAdminViewsTests(AdminTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.post = testutils.post_thread(category=self.category).first_post
+        self.post = test.post_thread(category=self.category).first_post
 
 
         self.filetype = AttachmentType.objects.order_by("id").first()
         self.filetype = AttachmentType.objects.order_by("id").first()
 
 

+ 1 - 1
misago/threads/tests/test_attachments_api.py

@@ -8,7 +8,7 @@ from misago.acl.models import Role
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.conf import settings
 from misago.conf import settings
 from misago.threads.models import Attachment, AttachmentType
 from misago.threads.models import Attachment, AttachmentType
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")

+ 4 - 4
misago/threads/tests/test_attachments_middleware.py

@@ -7,14 +7,14 @@ from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.api.postingendpoint import PostingEndpoint
 from misago.threads.api.postingendpoint import PostingEndpoint
 from misago.threads.api.postingendpoint.attachments import (
 from misago.threads.api.postingendpoint.attachments import (
     AttachmentsMiddleware,
     AttachmentsMiddleware,
     validate_attachments_count,
     validate_attachments_count,
 )
 )
 from misago.threads.models import Attachment, AttachmentType
 from misago.threads.models import Attachment, AttachmentType
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
@@ -30,7 +30,7 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
         self.post = self.thread.first_post
         self.post = self.thread.first_post
 
 
         self.post.update_fields = []
         self.post.update_fields = []
@@ -237,7 +237,7 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
     @patch_attachments_acl()
     @patch_attachments_acl()
     def test_steal_attachments(self):
     def test_steal_attachments(self):
         """middleware validates if attachments are already assigned to other posts"""
         """middleware validates if attachments are already assigned to other posts"""
-        other_post = testutils.reply_thread(self.thread)
+        other_post = test.reply_thread(self.thread)
 
 
         attachments = [self.mock_attachment(post=other_post), self.mock_attachment()]
         attachments = [self.mock_attachment(post=other_post), self.mock_attachment()]
 
 

+ 3 - 3
misago/threads/tests/test_attachmenttypeadmin_views.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.threads.models import AttachmentType
 from misago.threads.models import AttachmentType
 
 
 
 
@@ -203,8 +203,8 @@ class AttachmentTypeAdminViewsTests(AdminTestCase):
         test_type.attachment_set.create(
         test_type.attachment_set.create(
             secret="loremipsum",
             secret="loremipsum",
             filetype=test_type,
             filetype=test_type,
-            uploader_name="Bob",
-            uploader_slug="bob",
+            uploader_name="User",
+            uploader_slug="user",
             filename="test.zip",
             filename="test.zip",
             file="sad76asd678as687sa.zip",
             file="sad76asd678as687sa.zip",
         )
         )

+ 3 - 3
misago/threads/tests/test_attachmentview.py

@@ -6,9 +6,9 @@ from misago.acl.models import Role
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Attachment, AttachmentType
 from misago.threads.models import Attachment, AttachmentType
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")
@@ -29,7 +29,7 @@ class AttachmentViewTestCase(AuthenticatedUserTestCase):
         AttachmentType.objects.all().delete()
         AttachmentType.objects.all().delete()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.post = testutils.post_thread(category=self.category).first_post
+        self.post = test.post_thread(category=self.category).first_post
 
 
         self.api_link = reverse("misago:api:attachment-list")
         self.api_link = reverse("misago:api:attachment-list")
 
 

+ 8 - 8
misago/threads/tests/test_clearattachments.py

@@ -7,7 +7,7 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.management.commands import clearattachments
 from misago.threads.management.commands import clearattachments
 from misago.threads.models import Attachment, AttachmentType
 from misago.threads.models import Attachment, AttachmentType
 
 
@@ -39,14 +39,14 @@ class ClearAttachmentsTests(TestCase):
                 filetype=filetype,
                 filetype=filetype,
                 size=1000,
                 size=1000,
                 uploaded_on=cutoff,
                 uploaded_on=cutoff,
-                uploader_name="bob",
-                uploader_slug="bob",
+                uploader_name="User",
+                uploader_slug="user",
                 filename="testfile_%s.zip" % (Attachment.objects.count() + 1),
                 filename="testfile_%s.zip" % (Attachment.objects.count() + 1),
             )
             )
 
 
         # create 5 expired non-orphaned attachments
         # create 5 expired non-orphaned attachments
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        post = testutils.post_thread(category).first_post
+        post = test.post_thread(category).first_post
 
 
         for _ in range(5):
         for _ in range(5):
             Attachment.objects.create(
             Attachment.objects.create(
@@ -55,8 +55,8 @@ class ClearAttachmentsTests(TestCase):
                 size=1000,
                 size=1000,
                 uploaded_on=cutoff,
                 uploaded_on=cutoff,
                 post=post,
                 post=post,
-                uploader_name="bob",
-                uploader_slug="bob",
+                uploader_name="User",
+                uploader_slug="user",
                 filename="testfile_%s.zip" % (Attachment.objects.count() + 1),
                 filename="testfile_%s.zip" % (Attachment.objects.count() + 1),
             )
             )
 
 
@@ -66,8 +66,8 @@ class ClearAttachmentsTests(TestCase):
                 secret=Attachment.generate_new_secret(),
                 secret=Attachment.generate_new_secret(),
                 filetype=filetype,
                 filetype=filetype,
                 size=1000,
                 size=1000,
-                uploader_name="bob",
-                uploader_slug="bob",
+                uploader_name="User",
+                uploader_slug="user",
                 filename="testfile_%s.zip" % (Attachment.objects.count() + 1),
                 filename="testfile_%s.zip" % (Attachment.objects.count() + 1),
             )
             )
 
 

+ 4 - 4
misago/threads/tests/test_delete_user_likes.py

@@ -1,9 +1,9 @@
 from django.test import RequestFactory
 from django.test import RequestFactory
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.api.postendpoints.patch_post import patch_is_liked
 from misago.threads.api.postendpoints.patch_post import patch_is_liked
 from misago.threads.models import Post
 from misago.threads.models import Post
 
 
@@ -23,8 +23,8 @@ class DeleteUserLikesTests(AuthenticatedUserTestCase):
     def test_anonymize_user_likes(self):
     def test_anonymize_user_likes(self):
         """post's last like is anonymized by user.anonymize_data"""
         """post's last like is anonymized by user.anonymize_data"""
         category = Category.objects.get(slug="first-category")
         category = Category.objects.get(slug="first-category")
-        thread = testutils.post_thread(category)
-        post = testutils.reply_thread(thread)
+        thread = test.post_thread(category)
+        post = test.reply_thread(thread)
         post.acl = {"can_like": True}
         post.acl = {"can_like": True}
 
 
         user = create_test_user("OtherUser", "otheruser@example.com")
         user = create_test_user("OtherUser", "otheruser@example.com")

+ 4 - 4
misago/threads/tests/test_emailnotification_middleware.py

@@ -7,9 +7,9 @@ from django.utils import timezone
 from django.utils.encoding import smart_str
 from django.utils.encoding import smart_str
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import patch_category_acl, patch_other_user_category_acl
 from misago.threads.test import patch_category_acl, patch_other_user_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class EmailNotificationTests(AuthenticatedUserTestCase):
 class EmailNotificationTests(AuthenticatedUserTestCase):
@@ -17,7 +17,7 @@ class EmailNotificationTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(
+        self.thread = test.post_thread(
             category=self.category, started_on=timezone.now() - timedelta(seconds=5)
             category=self.category, started_on=timezone.now() - timedelta(seconds=5)
         )
         )
 
 
@@ -119,7 +119,7 @@ class EmailNotificationTests(AuthenticatedUserTestCase):
             send_email=True,
             send_email=True,
         )
         )
 
 
-        testutils.reply_thread(self.thread, posted_on=timezone.now())
+        test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, data={"post": "This is test response!"}
             self.api_link, data={"post": "This is test response!"}

+ 1 - 1
misago/threads/tests/test_events.py

@@ -9,7 +9,7 @@ from misago.categories.models import Category
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
 from misago.threads.events import record_event
 from misago.threads.events import record_event
 from misago.threads.models import Thread
 from misago.threads.models import Thread
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 

+ 3 - 3
misago/threads/tests/test_floodprotection.py

@@ -2,8 +2,8 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.threads import test
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class FloodProtectionTests(AuthenticatedUserTestCase):
 class FloodProtectionTests(AuthenticatedUserTestCase):
@@ -11,7 +11,7 @@ class FloodProtectionTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
 
 
         self.post_link = reverse(
         self.post_link = reverse(
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}

+ 1 - 1
misago/threads/tests/test_floodprotection_middleware.py

@@ -4,7 +4,7 @@ from django.utils import timezone
 
 
 from misago.threads.api.postingendpoint import PostingInterrupt
 from misago.threads.api.postingendpoint import PostingInterrupt
 from misago.threads.api.postingendpoint.floodprotection import FloodProtectionMiddleware
 from misago.threads.api.postingendpoint.floodprotection import FloodProtectionMiddleware
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 user_acl = {"can_omit_flood_protection": False}
 user_acl = {"can_omit_flood_protection": False}
 
 

+ 27 - 27
misago/threads/tests/test_gotoviews.py

@@ -3,9 +3,9 @@ from django.utils import timezone
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.readtracker.poststracker import save_read
 from misago.readtracker.poststracker import save_read
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 GOTO_URL = "%s#post-%s"
 GOTO_URL = "%s#post-%s"
@@ -17,7 +17,7 @@ class GotoViewTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
 
 
 
 
 class GotoPostTests(GotoViewTestCase):
 class GotoPostTests(GotoViewTestCase):
@@ -36,7 +36,7 @@ class GotoPostTests(GotoViewTestCase):
     def test_goto_last_post_on_page(self):
     def test_goto_last_post_on_page(self):
         """last post on page redirect url is valid"""
         """last post on page redirect url is valid"""
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
 
 
         response = self.client.get(post.get_absolute_url())
         response = self.client.get(post.get_absolute_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -50,7 +50,7 @@ class GotoPostTests(GotoViewTestCase):
     def test_goto_first_post_on_next_page(self):
     def test_goto_first_post_on_next_page(self):
         """first post on next page redirect url is valid"""
         """first post on next page redirect url is valid"""
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
 
 
         response = self.client.get(post.get_absolute_url())
         response = self.client.get(post.get_absolute_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -66,7 +66,7 @@ class GotoPostTests(GotoViewTestCase):
         """first post on next page redirect url is valid"""
         """first post on next page redirect url is valid"""
         posts = []
         posts = []
         for _ in range(settings.MISAGO_POSTS_PER_PAGE * 4 - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE * 4 - 1):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
             posts.append(post)
             posts.append(post)
 
 
         post = posts[settings.MISAGO_POSTS_PER_PAGE * 2 - 3]
         post = posts[settings.MISAGO_POSTS_PER_PAGE * 2 - 3]
@@ -85,7 +85,7 @@ class GotoPostTests(GotoViewTestCase):
         """event redirect url is valid"""
         """event redirect url is valid"""
         posts = []
         posts = []
         for _ in range(settings.MISAGO_POSTS_PER_PAGE * 4 - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE * 4 - 1):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
             posts.append(post)
             posts.append(post)
 
 
         post = posts[settings.MISAGO_POSTS_PER_PAGE * 2 - 2]
         post = posts[settings.MISAGO_POSTS_PER_PAGE * 2 - 2]
@@ -123,7 +123,7 @@ class GotoLastTests(GotoViewTestCase):
     def test_goto_last_post_on_page(self):
     def test_goto_last_post_on_page(self):
         """last post on page redirect url is valid"""
         """last post on page redirect url is valid"""
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
 
 
         response = self.client.get(self.thread.get_last_post_url())
         response = self.client.get(self.thread.get_last_post_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -149,9 +149,9 @@ class GotoNewTests(GotoViewTestCase):
         """first unread post redirect url in already read thread is valid"""
         """first unread post redirect url in already read thread is valid"""
         save_read(self.user, self.thread.first_post)
         save_read(self.user, self.thread.first_post)
 
 
-        post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+        post = test.reply_thread(self.thread, posted_on=timezone.now())
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         response = self.client.get(self.thread.get_new_post_url())
         response = self.client.get(self.thread.get_new_post_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -164,12 +164,12 @@ class GotoNewTests(GotoViewTestCase):
         save_read(self.user, self.thread.first_post)
         save_read(self.user, self.thread.first_post)
 
 
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
-            last_post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+            last_post = test.reply_thread(self.thread, posted_on=timezone.now())
             save_read(self.user, last_post)
             save_read(self.user, last_post)
 
 
-        post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+        post = test.reply_thread(self.thread, posted_on=timezone.now())
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         response = self.client.get(self.thread.get_new_post_url())
         response = self.client.get(self.thread.get_new_post_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -183,7 +183,7 @@ class GotoNewTests(GotoViewTestCase):
         save_read(self.user, self.thread.first_post)
         save_read(self.user, self.thread.first_post)
 
 
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
-            post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+            post = test.reply_thread(self.thread, posted_on=timezone.now())
             save_read(self.user, post)
             save_read(self.user, post)
 
 
         response = self.client.get(self.thread.get_new_post_url())
         response = self.client.get(self.thread.get_new_post_url())
@@ -196,7 +196,7 @@ class GotoNewTests(GotoViewTestCase):
     def test_guest_goto_first_new_post_in_thread(self):
     def test_guest_goto_first_new_post_in_thread(self):
         """guest goto new in read thread points to last post"""
         """guest goto new in read thread points to last post"""
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
-            post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+            post = test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         self.logout_user()
         self.logout_user()
 
 
@@ -221,14 +221,14 @@ class GotoBestAnswerTests(GotoViewTestCase):
     def test_view_handles_best_answer(self):
     def test_view_handles_best_answer(self):
         """if thread has best answer, redirect to it"""
         """if thread has best answer, redirect to it"""
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
-        best_answer = testutils.reply_thread(self.thread, posted_on=timezone.now())
+        best_answer = test.reply_thread(self.thread, posted_on=timezone.now())
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         response = self.client.get(self.thread.get_best_answer_url())
         response = self.client.get(self.thread.get_best_answer_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -264,13 +264,13 @@ class GotoUnapprovedTests(GotoViewTestCase):
     def test_view_handles_unapproved_posts(self):
     def test_view_handles_unapproved_posts(self):
         """if thread has unapproved posts, redirect to first of them"""
         """if thread has unapproved posts, redirect to first of them"""
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
-        post = testutils.reply_thread(
+        post = test.reply_thread(
             self.thread, is_unapproved=True, posted_on=timezone.now()
             self.thread, is_unapproved=True, posted_on=timezone.now()
         )
         )
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
         for _ in range(settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL - 1):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         response = self.client.get(self.thread.get_unapproved_post_url())
         response = self.client.get(self.thread.get_unapproved_post_url())
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
@@ -286,7 +286,7 @@ class ThreadGotoPostTests(GotoViewTestCase):
     def test_thread_growing_post_goto(self):
     def test_thread_growing_post_goto(self):
         """growing thread goto views don't fail"""
         """growing thread goto views don't fail"""
         for _ in range(60):
         for _ in range(60):
-            post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+            post = test.reply_thread(self.thread, posted_on=timezone.now())
 
 
             # go to post link is valid
             # go to post link is valid
             post_url = self.client.get(post.get_absolute_url())["location"]
             post_url = self.client.get(post.get_absolute_url())["location"]
@@ -301,9 +301,9 @@ class ThreadGotoPostTests(GotoViewTestCase):
     def test_thread_growing_event_goto(self):
     def test_thread_growing_event_goto(self):
         """growing thread goto views don't fail for events"""
         """growing thread goto views don't fail for events"""
         for i in range(60):
         for i in range(60):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
-            post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+            post = test.reply_thread(self.thread, posted_on=timezone.now())
             post.is_event = True
             post.is_event = True
             post.save()
             post.save()
 
 
@@ -325,7 +325,7 @@ class ThreadGotoPostTests(GotoViewTestCase):
     def test_thread_post_goto(self):
     def test_thread_post_goto(self):
         """thread goto views don't fail"""
         """thread goto views don't fail"""
         for _ in range(60):
         for _ in range(60):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
         for post in self.thread.post_set.order_by("id").iterator():
         for post in self.thread.post_set.order_by("id").iterator():
             # go to post link is valid
             # go to post link is valid
@@ -341,9 +341,9 @@ class ThreadGotoPostTests(GotoViewTestCase):
     def test_thread_event_goto(self):
     def test_thread_event_goto(self):
         """thread goto views don't fail for events"""
         """thread goto views don't fail for events"""
         for _ in range(60):
         for _ in range(60):
-            testutils.reply_thread(self.thread, posted_on=timezone.now())
+            test.reply_thread(self.thread, posted_on=timezone.now())
 
 
-            post = testutils.reply_thread(self.thread, posted_on=timezone.now())
+            post = test.reply_thread(self.thread, posted_on=timezone.now())
             post.is_event = True
             post.is_event = True
             post.save()
             post.save()
 
 

+ 7 - 7
misago/threads/tests/test_mergeconflict.py

@@ -4,9 +4,9 @@ from django.test import TestCase
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.mergeconflict import MergeConflict
 from misago.threads.mergeconflict import MergeConflict
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class MergeConflictTests(TestCase):
 class MergeConflictTests(TestCase):
@@ -15,16 +15,16 @@ class MergeConflictTests(TestCase):
         self.user = create_test_user("User", "user@example.com")
         self.user = create_test_user("User", "user@example.com")
 
 
     def create_plain_thread(self):
     def create_plain_thread(self):
-        return testutils.post_thread(self.category)
+        return test.post_thread(self.category)
 
 
     def create_poll_thread(self):
     def create_poll_thread(self):
-        thread = testutils.post_thread(self.category)
-        testutils.post_poll(thread, self.user)
+        thread = test.post_thread(self.category)
+        test.post_poll(thread, self.user)
         return thread
         return thread
 
 
     def create_best_answer_thread(self):
     def create_best_answer_thread(self):
-        thread = testutils.post_thread(self.category)
-        best_answer = testutils.reply_thread(thread)
+        thread = test.post_thread(self.category)
+        best_answer = test.reply_thread(thread)
         thread.set_best_answer(self.user, best_answer)
         thread.set_best_answer(self.user, best_answer)
         thread.synchronize()
         thread.synchronize()
         thread.save()
         thread.save()

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

@@ -9,7 +9,7 @@ from misago.threads.participants import (
     set_owner,
     set_owner,
     set_users_unread_private_threads_sync,
     set_users_unread_private_threads_sync,
 )
 )
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class ParticipantsTests(TestCase):
 class ParticipantsTests(TestCase):
@@ -49,7 +49,7 @@ class ParticipantsTests(TestCase):
         """has_participants returns true if thread has participants"""
         """has_participants returns true if thread has participants"""
         users = [
         users = [
             create_test_user("User", "user@example.com"),
             create_test_user("User", "user@example.com"),
-            create_test_user("User2", "bob2@example.com"),
+            create_test_user("OtherUser", "otheruser@example.com"),
         ]
         ]
 
 
         self.assertFalse(has_participants(self.thread))
         self.assertFalse(has_participants(self.thread))
@@ -66,7 +66,7 @@ class ParticipantsTests(TestCase):
         annotations on list of threads
         annotations on list of threads
         """
         """
         user = create_test_user("User", "user@example.com")
         user = create_test_user("User", "user@example.com")
-        other_user = create_test_user("User2", "bob2@example.com")
+        other_user = create_test_user("OtherUser", "otheruser@example.com")
 
 
         self.assertFalse(hasattr(self.thread, "participants_list"))
         self.assertFalse(hasattr(self.thread, "participants_list"))
         self.assertFalse(hasattr(self.thread, "participant"))
         self.assertFalse(hasattr(self.thread, "participant"))
@@ -91,7 +91,7 @@ class ParticipantsTests(TestCase):
         annotations on thread model
         annotations on thread model
         """
         """
         user = create_test_user("User", "user@example.com")
         user = create_test_user("User", "user@example.com")
-        other_user = create_test_user("User2", "bob2@example.com")
+        other_user = create_test_user("OtherUser", "otheruser@example.com")
 
 
         self.assertFalse(hasattr(self.thread, "participants_list"))
         self.assertFalse(hasattr(self.thread, "participants_list"))
         self.assertFalse(hasattr(self.thread, "participant"))
         self.assertFalse(hasattr(self.thread, "participant"))
@@ -131,8 +131,8 @@ class ParticipantsTests(TestCase):
         flag on users provided to true
         flag on users provided to true
         """
         """
         users = [
         users = [
-            create_test_user("User1", "bob1@example.com"),
-            create_test_user("User2", "bob2@example.com"),
+            create_test_user("User", "user@example.com"),
+            create_test_user("OtherUser", "otheruser@example.com"),
         ]
         ]
 
 
         set_users_unread_private_threads_sync(users=users)
         set_users_unread_private_threads_sync(users=users)
@@ -146,8 +146,8 @@ class ParticipantsTests(TestCase):
         flag on participants provided to true
         flag on participants provided to true
         """
         """
         users = [
         users = [
-            create_test_user("User1", "bob1@example.com"),
-            create_test_user("User2", "bob2@example.com"),
+            create_test_user("User", "user@example.com"),
+            create_test_user("OtherUser", "otheruser@example.com"),
         ]
         ]
 
 
         participants = [ThreadParticipant(user=u) for u in users]
         participants = [ThreadParticipant(user=u) for u in users]
@@ -162,9 +162,9 @@ class ParticipantsTests(TestCase):
         set_users_unread_private_threads_sync sets sync_unread_private_threads
         set_users_unread_private_threads_sync sets sync_unread_private_threads
         flag on users and participants provided to true
         flag on users and participants provided to true
         """
         """
-        users = [create_test_user("User1", "bob1@example.com")]
+        users = [create_test_user("User", "user@example.com")]
         participants = [ThreadParticipant(user=u) for u in users]
         participants = [ThreadParticipant(user=u) for u in users]
-        users.append(create_test_user("User2", "bob2@example.com"))
+        users.append(create_test_user("OtherUser", "otheruser@example.com"))
 
 
         set_users_unread_private_threads_sync(users=users, participants=participants)
         set_users_unread_private_threads_sync(users=users, participants=participants)
         for user in users:
         for user in users:
@@ -174,8 +174,8 @@ class ParticipantsTests(TestCase):
     def test_set_users_unread_private_threads_sync_exclude_user(self):
     def test_set_users_unread_private_threads_sync_exclude_user(self):
         """exclude_user kwarg works"""
         """exclude_user kwarg works"""
         users = [
         users = [
-            create_test_user("User1", "bob1@example.com"),
-            create_test_user("User2", "bob2@example.com"),
+            create_test_user("User", "user@example.com"),
+            create_test_user("OtherUser", "otheruser@example.com"),
         ]
         ]
 
 
         set_users_unread_private_threads_sync(users=users, exclude_user=users[0])
         set_users_unread_private_threads_sync(users=users, exclude_user=users[0])
@@ -186,7 +186,7 @@ class ParticipantsTests(TestCase):
 
 
     def test_set_users_unread_private_threads_sync_noop(self):
     def test_set_users_unread_private_threads_sync_noop(self):
         """excluding only user is noop"""
         """excluding only user is noop"""
-        user = create_test_user("User", "bob1@example.com")
+        user = create_test_user("User", "user@example.com")
 
 
         with self.assertNumQueries(0):
         with self.assertNumQueries(0):
             set_users_unread_private_threads_sync(users=[user], exclude_user=user)
             set_users_unread_private_threads_sync(users=[user], exclude_user=user)

+ 18 - 18
misago/threads/tests/test_post_mentions.py

@@ -3,8 +3,8 @@ from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.markup.mentions import MENTIONS_LIMIT
 from misago.markup.mentions import MENTIONS_LIMIT
-from misago.threads import testutils
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.threads import test
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class PostMentionsTests(AuthenticatedUserTestCase):
 class PostMentionsTests(AuthenticatedUserTestCase):
@@ -12,7 +12,7 @@ class PostMentionsTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
 
 
         self.post_link = reverse(
         self.post_link = reverse(
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
@@ -75,18 +75,18 @@ class PostMentionsTests(AuthenticatedUserTestCase):
 
 
     def test_mention_update(self):
     def test_mention_update(self):
         """edit post endpoint updates mentions"""
         """edit post endpoint updates mentions"""
-        user_1 = create_test_user("User1", "user1@example.com")
-        user_2 = create_test_user("User2", "user2@example.com")
+        user = create_test_user("User", "user@example.com")
+        other_user = create_test_user("OtherUser", "otheruser@example.com")
 
 
         response = self.client.post(
         response = self.client.post(
-            self.post_link, data={"post": "This is test response, @%s!" % user_1}
+            self.post_link, data={"post": "This is test response, @%s!" % user}
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         post = self.user.post_set.order_by("id").last()
         post = self.user.post_set.order_by("id").last()
 
 
         self.assertEqual(post.mentions.count(), 1)
         self.assertEqual(post.mentions.count(), 1)
-        self.assertEqual(post.mentions.order_by("id")[0], user_1)
+        self.assertEqual(post.mentions.order_by("id")[0], user)
 
 
         # add mention to post
         # add mention to post
         edit_link = reverse(
         edit_link = reverse(
@@ -96,43 +96,43 @@ class PostMentionsTests(AuthenticatedUserTestCase):
 
 
         response = self.put(
         response = self.put(
             edit_link,
             edit_link,
-            data={"post": "This is test response, @%s and @%s!" % (user_1, user_2)},
+            data={"post": "This is test response, @%s and @%s!" % (user, other_user)},
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         self.assertEqual(post.mentions.count(), 2)
         self.assertEqual(post.mentions.count(), 2)
-        self.assertEqual(list(post.mentions.order_by("id")), [user_1, user_2])
+        self.assertEqual(list(post.mentions.order_by("id")), [user, other_user])
 
 
         # remove first mention from post - should preserve mentions
         # remove first mention from post - should preserve mentions
         response = self.put(
         response = self.put(
-            edit_link, data={"post": "This is test response, @%s!" % user_2}
+            edit_link, data={"post": "This is test response, @%s!" % other_user}
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         self.assertEqual(post.mentions.count(), 2)
         self.assertEqual(post.mentions.count(), 2)
-        self.assertEqual(list(post.mentions.order_by("id")), [user_1, user_2])
+        self.assertEqual(list(post.mentions.order_by("id")), [user, other_user])
 
 
         # remove mentions from post - should preserve mentions
         # remove mentions from post - should preserve mentions
         response = self.put(edit_link, data={"post": "This is test response!"})
         response = self.put(edit_link, data={"post": "This is test response!"})
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         self.assertEqual(post.mentions.count(), 2)
         self.assertEqual(post.mentions.count(), 2)
-        self.assertEqual(list(post.mentions.order_by("id")), [user_1, user_2])
+        self.assertEqual(list(post.mentions.order_by("id")), [user, other_user])
 
 
     def test_mentions_merge(self):
     def test_mentions_merge(self):
         """posts merge sums mentions"""
         """posts merge sums mentions"""
-        user_1 = create_test_user("User1", "user1@example.com")
-        user_2 = create_test_user("User2", "user2@example.com")
+        user = create_test_user("User1", "user1@example.com")
+        other_user = create_test_user("User2", "user2@example.com")
 
 
         response = self.client.post(
         response = self.client.post(
-            self.post_link, data={"post": "This is test response, @%s!" % user_1}
+            self.post_link, data={"post": "This is test response, @%s!" % user}
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         post_a = self.user.post_set.order_by("id").last()
         post_a = self.user.post_set.order_by("id").last()
 
 
         self.assertEqual(post_a.mentions.count(), 1)
         self.assertEqual(post_a.mentions.count(), 1)
-        self.assertEqual(list(post_a.mentions.all()), [user_1])
+        self.assertEqual(list(post_a.mentions.all()), [user])
 
 
         # post second reply
         # post second reply
         self.user.last_post_on = None
         self.user.last_post_on = None
@@ -140,7 +140,7 @@ class PostMentionsTests(AuthenticatedUserTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             self.post_link,
             self.post_link,
-            data={"post": "This is test response, @%s and @%s!" % (user_1, user_2)},
+            data={"post": "This is test response, @%s and @%s!" % (user, other_user)},
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
@@ -150,4 +150,4 @@ class PostMentionsTests(AuthenticatedUserTestCase):
         post_b.merge(post_a)
         post_b.merge(post_a)
 
 
         self.assertEqual(post_a.mentions.count(), 2)
         self.assertEqual(post_a.mentions.count(), 2)
-        self.assertEqual(list(post_a.mentions.order_by("id")), [user_1, user_2])
+        self.assertEqual(list(post_a.mentions.order_by("id")), [user, other_user])

+ 1 - 1
misago/threads/tests/test_post_model.py

@@ -6,7 +6,7 @@ from django.utils import timezone
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.checksums import update_post_checksum
 from misago.threads.checksums import update_post_checksum
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class PostModelTests(TestCase):
 class PostModelTests(TestCase):

+ 4 - 4
misago/threads/tests/test_posts_moderation.py

@@ -1,7 +1,7 @@
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import moderation, testutils
+from misago.threads import moderation, test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class PostsModerationTests(AuthenticatedUserTestCase):
 class PostsModerationTests(AuthenticatedUserTestCase):
@@ -9,8 +9,8 @@ class PostsModerationTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.all_categories()[:1][0]
         self.category = Category.objects.all_categories()[:1][0]
-        self.thread = testutils.post_thread(self.category)
-        self.post = testutils.reply_thread(self.thread)
+        self.thread = test.post_thread(self.category)
+        self.post = test.reply_thread(self.thread)
 
 
     def reload_thread(self):
     def reload_thread(self):
         self.thread = Thread.objects.get(pk=self.thread.pk)
         self.thread = Thread.objects.get(pk=self.thread.pk)

+ 3 - 3
misago/threads/tests/test_privatethread_patch_api.py

@@ -3,10 +3,10 @@ import json
 from django.core import mail
 from django.core import mail
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import other_user_cant_use_private_threads
 from misago.threads.test import other_user_cant_use_private_threads
 from misago.threads.models import Thread, ThreadParticipant
 from misago.threads.models import Thread, ThreadParticipant
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
@@ -15,7 +15,7 @@ class PrivateThreadPatchApiTestCase(PrivateThreadsTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
         self.api_link = self.thread.get_api_url()
         self.api_link = self.thread.get_api_url()
 
 
         self.other_user = create_test_user("OtherUser", "otheruser@example.com")
         self.other_user = create_test_user("OtherUser", "otheruser@example.com")

+ 3 - 3
misago/threads/tests/test_privatethread_reply_api.py

@@ -1,6 +1,6 @@
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import ThreadParticipant
 from misago.threads.models import ThreadParticipant
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
@@ -9,7 +9,7 @@ class PrivateThreadReplyApiTestCase(PrivateThreadsTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
         self.api_link = self.thread.get_posts_api_url()
         self.api_link = self.thread.get_posts_api_url()
 
 
         self.other_user = create_test_user("OtherUser", "otheruser@example.com")
         self.other_user = create_test_user("OtherUser", "otheruser@example.com")

+ 1 - 1
misago/threads/tests/test_privatethread_start_api.py

@@ -7,7 +7,7 @@ from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.models import ThreadParticipant
 from misago.threads.models import ThreadParticipant
 from misago.threads.test import other_user_cant_use_private_threads
 from misago.threads.test import other_user_cant_use_private_threads
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 User = get_user_model()
 User = get_user_model()
 
 

+ 2 - 2
misago/threads/tests/test_privatethread_view.py

@@ -1,5 +1,5 @@
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import ThreadParticipant
 from misago.threads.models import ThreadParticipant
 
 
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
@@ -9,7 +9,7 @@ class PrivateThreadViewTests(PrivateThreadsTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
         self.test_link = self.thread.get_absolute_url()
         self.test_link = self.thread.get_absolute_url()
 
 
     def test_anonymous(self):
     def test_anonymous(self):

+ 1 - 1
misago/threads/tests/test_privatethreads.py

@@ -1,5 +1,5 @@
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class PrivateThreadsTestCase(AuthenticatedUserTestCase):
 class PrivateThreadsTestCase(AuthenticatedUserTestCase):

+ 6 - 6
misago/threads/tests/test_privatethreads_api.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread, ThreadParticipant
 from misago.threads.models import Thread, ThreadParticipant
 from misago.threads.test import patch_private_threads_acl
 from misago.threads.test import patch_private_threads_acl
 
 
@@ -43,11 +43,11 @@ class PrivateThreadsListApiTests(PrivateThreadsTestCase):
     @patch_user_acl({"can_use_private_threads": True})
     @patch_user_acl({"can_use_private_threads": True})
     def test_thread_visibility(self):
     def test_thread_visibility(self):
         """only participated threads are returned by private threads api"""
         """only participated threads are returned by private threads api"""
-        visible = testutils.post_thread(category=self.category, poster=self.user)
-        reported = testutils.post_thread(category=self.category, poster=self.user)
+        visible = test.post_thread(category=self.category, poster=self.user)
+        reported = test.post_thread(category=self.category, poster=self.user)
 
 
         # hidden thread
         # hidden thread
-        testutils.post_thread(category=self.category, poster=self.user)
+        test.post_thread(category=self.category, poster=self.user)
 
 
         ThreadParticipant.objects.add_participants(visible, [self.user])
         ThreadParticipant.objects.add_participants(visible, [self.user])
 
 
@@ -76,7 +76,7 @@ class PrivateThreadRetrieveApiTests(PrivateThreadsTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
         self.api_link = self.thread.get_api_url()
         self.api_link = self.thread.get_api_url()
 
 
     def test_anonymous(self):
     def test_anonymous(self):
@@ -187,7 +187,7 @@ class PrivateThreadDeleteApiTests(PrivateThreadsTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
         self.api_link = self.thread.get_api_url()
         self.api_link = self.thread.get_api_url()
 
 
         ThreadParticipant.objects.add_participants(self.thread, [self.user])
         ThreadParticipant.objects.add_participants(self.thread, [self.user])

+ 4 - 4
misago/threads/tests/test_privatethreads_lists.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import ThreadParticipant
 from misago.threads.models import ThreadParticipant
 
 
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
@@ -34,11 +34,11 @@ class PrivateThreadsListTests(PrivateThreadsTestCase):
 
 
     def test_thread_visibility(self):
     def test_thread_visibility(self):
         """only participated threads are returned by private threads view"""
         """only participated threads are returned by private threads view"""
-        visible = testutils.post_thread(category=self.category, poster=self.user)
-        reported = testutils.post_thread(category=self.category, poster=self.user)
+        visible = test.post_thread(category=self.category, poster=self.user)
+        reported = test.post_thread(category=self.category, poster=self.user)
 
 
         # post hidden thread
         # post hidden thread
-        testutils.post_thread(category=self.category, poster=self.user)
+        test.post_thread(category=self.category, poster=self.user)
 
 
         ThreadParticipant.objects.add_participants(visible, [self.user])
         ThreadParticipant.objects.add_participants(visible, [self.user])
 
 

+ 18 - 20
misago/threads/tests/test_search.py

@@ -1,8 +1,8 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.threads import test
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class SearchApiTests(AuthenticatedUserTestCase):
 class SearchApiTests(AuthenticatedUserTestCase):
@@ -49,8 +49,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_short_query(self):
     def test_short_query(self):
         """api handles short search query"""
         """api handles short search query"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(thread, message="Lorem ipsum dolor.")
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(thread, message="Lorem ipsum dolor.")
         self.index_post(post)
         self.index_post(post)
 
 
         response = self.client.get("%s?q=ip" % self.api_link)
         response = self.client.get("%s?q=ip" % self.api_link)
@@ -65,8 +65,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_wrong_query(self):
     def test_wrong_query(self):
         """api handles query miss"""
         """api handles query miss"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(thread, message="Lorem ipsum dolor.")
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(thread, message="Lorem ipsum dolor.")
         self.index_post(post)
         self.index_post(post)
 
 
         response = self.client.get("%s?q=elit" % self.api_link)
         response = self.client.get("%s?q=elit" % self.api_link)
@@ -81,10 +81,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_hidden_post(self):
     def test_hidden_post(self):
         """hidden posts are extempt from search"""
         """hidden posts are extempt from search"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(
-            thread, message="Lorem ipsum dolor.", is_hidden=True
-        )
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(thread, message="Lorem ipsum dolor.", is_hidden=True)
         self.index_post(post)
         self.index_post(post)
 
 
         response = self.client.get("%s?q=ipsum" % self.api_link)
         response = self.client.get("%s?q=ipsum" % self.api_link)
@@ -99,8 +97,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_unapproved_post(self):
     def test_unapproved_post(self):
         """unapproves posts are extempt from search"""
         """unapproves posts are extempt from search"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(
             thread, message="Lorem ipsum dolor.", is_unapproved=True
             thread, message="Lorem ipsum dolor.", is_unapproved=True
         )
         )
         self.index_post(post)
         self.index_post(post)
@@ -117,8 +115,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_query(self):
     def test_query(self):
         """api handles search query"""
         """api handles search query"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(thread, message="Lorem ipsum dolor.")
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(thread, message="Lorem ipsum dolor.")
         self.index_post(post)
         self.index_post(post)
 
 
         response = self.client.get("%s?q=ipsum" % self.api_link)
         response = self.client.get("%s?q=ipsum" % self.api_link)
@@ -135,10 +133,10 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_thread_title_search(self):
     def test_thread_title_search(self):
         """api searches threads by title"""
         """api searches threads by title"""
-        thread = testutils.post_thread(self.category, title="Atmosphere of mars")
+        thread = test.post_thread(self.category, title="Atmosphere of mars")
         self.index_post(thread.first_post)
         self.index_post(thread.first_post)
 
 
-        post = testutils.reply_thread(thread, message="Lorem ipsum dolor.")
+        post = test.reply_thread(thread, message="Lorem ipsum dolor.")
         self.index_post(post)
         self.index_post(post)
 
 
         response = self.client.get("%s?q=mars atmosphere" % self.api_link)
         response = self.client.get("%s?q=mars atmosphere" % self.api_link)
@@ -155,8 +153,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_complex_query(self):
     def test_complex_query(self):
         """api handles complex query that uses fulltext search facilities"""
         """api handles complex query that uses fulltext search facilities"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(thread, message="Atmosphere of Mars")
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(thread, message="Atmosphere of Mars")
         self.index_post(post)
         self.index_post(post)
 
 
         response = self.client.get("%s?q=Mars atmosphere" % self.api_link)
         response = self.client.get("%s?q=Mars atmosphere" % self.api_link)
@@ -173,8 +171,8 @@ class SearchApiTests(AuthenticatedUserTestCase):
 
 
     def test_filtered_query(self):
     def test_filtered_query(self):
         """search filters are used by search system"""
         """search filters are used by search system"""
-        thread = testutils.post_thread(self.category)
-        post = testutils.reply_thread(
+        thread = test.post_thread(self.category)
+        post = test.reply_thread(
             thread, message="You just do MMM in 4th minute and its pwnt"
             thread, message="You just do MMM in 4th minute and its pwnt"
         )
         )
 
 

+ 4 - 4
misago/threads/tests/test_subscription_middleware.py

@@ -3,9 +3,9 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 User = get_user_model()
 User = get_user_model()
@@ -92,7 +92,7 @@ class SubscribeStartedThreadTests(SubscriptionMiddlewareTestCase):
 class SubscribeRepliedThreadTests(SubscriptionMiddlewareTestCase):
 class SubscribeRepliedThreadTests(SubscriptionMiddlewareTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
-        self.thread = testutils.post_thread(self.category)
+        self.thread = test.post_thread(self.category)
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
         )
         )
@@ -153,7 +153,7 @@ class SubscribeRepliedThreadTests(SubscriptionMiddlewareTestCase):
         self.user.save()
         self.user.save()
 
 
         # set event in thread
         # set event in thread
-        testutils.reply_thread(self.thread, self.user, is_event=True)
+        test.reply_thread(self.thread, self.user, is_event=True)
 
 
         # reply thread
         # reply thread
         response = self.client.post(
         response = self.client.post(

+ 3 - 3
misago/threads/tests/test_subscriptions.py

@@ -4,10 +4,10 @@ from django.test import TestCase
 from django.utils import timezone
 from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.subscriptions import make_subscription_aware
 from misago.threads.subscriptions import make_subscription_aware
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class SubscriptionsTests(TestCase):
 class SubscriptionsTests(TestCase):
@@ -19,7 +19,7 @@ class SubscriptionsTests(TestCase):
         self.user = create_test_user("User", "user@example.com")
         self.user = create_test_user("User", "user@example.com")
 
 
     def post_thread(self, datetime):
     def post_thread(self, datetime):
-        return testutils.post_thread(category=self.category, started_on=datetime)
+        return test.post_thread(category=self.category, started_on=datetime)
 
 
     def test_anon_subscription(self):
     def test_anon_subscription(self):
         """make single thread sub aware for anon"""
         """make single thread sub aware for anon"""

+ 4 - 4
misago/threads/tests/test_sync_unread_private_threads.py

@@ -1,6 +1,6 @@
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import ThreadParticipant
 from misago.threads.models import ThreadParticipant
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
@@ -10,7 +10,7 @@ class SyncUnreadPrivateThreadsTestCase(PrivateThreadsTestCase):
         super().setUp()
         super().setUp()
 
 
         self.other_user = create_test_user("OtherUser", "user@example.com")
         self.other_user = create_test_user("OtherUser", "user@example.com")
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
 
 
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.set_owner(self.thread, self.other_user)
         ThreadParticipant.objects.add_participants(self.thread, [self.user])
         ThreadParticipant.objects.add_participants(self.thread, [self.user])
@@ -42,7 +42,7 @@ class SyncUnreadPrivateThreadsTestCase(PrivateThreadsTestCase):
         self.assertEqual(self.user.unread_private_threads, 0)
         self.assertEqual(self.user.unread_private_threads, 0)
 
 
         # reply to thread
         # reply to thread
-        testutils.reply_thread(self.thread)
+        test.reply_thread(self.thread)
 
 
         self.user.sync_unread_private_threads = True
         self.user.sync_unread_private_threads = True
         self.user.save()
         self.user.save()

+ 3 - 3
misago/threads/tests/test_synchronizethreads.py

@@ -4,7 +4,7 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.management.commands import synchronizethreads
 from misago.threads.management.commands import synchronizethreads
 
 
 
 
@@ -23,9 +23,9 @@ class SynchronizeThreadsTests(TestCase):
         """command synchronizes threads"""
         """command synchronizes threads"""
         category = Category.objects.all_categories()[:1][0]
         category = Category.objects.all_categories()[:1][0]
 
 
-        threads = [testutils.post_thread(category) for _ in range(10)]
+        threads = [test.post_thread(category) for _ in range(10)]
         for i, thread in enumerate(threads):
         for i, thread in enumerate(threads):
-            [testutils.reply_thread(thread) for _ in range(i)]
+            [test.reply_thread(thread) for _ in range(i)]
             thread.replies = 0
             thread.replies = 0
             thread.save()
             thread.save()
 
 

+ 6 - 6
misago/threads/tests/test_thread_bulkpatch_api.py

@@ -3,7 +3,7 @@ import json
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 
 
@@ -17,9 +17,9 @@ class ThreadsBulkPatchApiTestCase(ThreadsApiTestCase):
         self.threads = list(
         self.threads = list(
             reversed(
             reversed(
                 [
                 [
-                    testutils.post_thread(category=self.category),
-                    testutils.post_thread(category=self.category),
-                    testutils.post_thread(category=self.category),
+                    test.post_thread(category=self.category),
+                    test.post_thread(category=self.category),
+                    test.post_thread(category=self.category),
                 ]
                 ]
             )
             )
         )
         )
@@ -114,8 +114,8 @@ class BulkPatchSerializerTests(ThreadsBulkPatchApiTestCase):
     def test_threads_not_found(self):
     def test_threads_not_found(self):
         """api fails to find threads"""
         """api fails to find threads"""
         threads = [
         threads = [
-            testutils.post_thread(category=self.category, is_hidden=True),
-            testutils.post_thread(category=self.category, is_unapproved=True),
+            test.post_thread(category=self.category, is_hidden=True),
+            test.post_thread(category=self.category, is_unapproved=True),
         ]
         ]
 
 
         response = self.patch(
         response = self.patch(

+ 4 - 4
misago/threads/tests/test_thread_editreply_api.py

@@ -6,10 +6,10 @@ from django.utils import timezone
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class EditReplyTests(AuthenticatedUserTestCase):
 class EditReplyTests(AuthenticatedUserTestCase):
@@ -17,8 +17,8 @@ class EditReplyTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.thread = test.post_thread(category=self.category)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-detail",
             "misago:api:thread-post-detail",

+ 52 - 52
misago/threads/tests/test_thread_merge_api.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Poll, PollVote, Thread
 from misago.threads.models import Poll, PollVote, Thread
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 
 
@@ -64,7 +64,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_other_thread_exists(self):
     def test_other_thread_exists(self):
         """api validates if other thread exists"""
         """api validates if other thread exists"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
         other_other_thread = other_thread.get_absolute_url()
         other_other_thread = other_thread.get_absolute_url()
         other_thread.delete()
         other_thread.delete()
 
 
@@ -84,7 +84,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_other_thread_is_invisible(self):
     def test_other_thread_is_invisible(self):
         """api validates if other thread is visible"""
         """api validates if other thread is visible"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -104,7 +104,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_other_thread_isnt_mergeable(self):
     def test_other_thread_isnt_mergeable(self):
         """api validates if other thread can be merged"""
         """api validates if other thread can be merged"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -118,7 +118,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_thread_category_is_closed(self):
     def test_thread_category_is_closed(self):
         """api validates if thread's category is open"""
         """api validates if thread's category is open"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.category.is_closed = True
         self.category.is_closed = True
         self.category.save()
         self.category.save()
@@ -136,7 +136,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_thread_is_closed(self):
     def test_thread_is_closed(self):
         """api validates if thread is open"""
         """api validates if thread is open"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.thread.is_closed = True
         self.thread.is_closed = True
         self.thread.save()
         self.thread.save()
@@ -154,7 +154,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_other_thread_category_is_closed(self):
     def test_other_thread_category_is_closed(self):
         """api validates if other thread's category is open"""
         """api validates if other thread's category is open"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.other_category.is_closed = True
         self.other_category.is_closed = True
         self.other_category.save()
         self.other_category.save()
@@ -172,7 +172,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_other_thread_is_closed(self):
     def test_other_thread_is_closed(self):
         """api validates if other thread is open"""
         """api validates if other thread is open"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         other_thread.is_closed = True
         other_thread.is_closed = True
         other_thread.save()
         other_thread.save()
@@ -190,7 +190,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_other_thread_isnt_replyable(self):
     def test_other_thread_isnt_replyable(self):
         """api validates if other thread can be replied, which is condition for merge"""
         """api validates if other thread can be replied, which is condition for merge"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -205,7 +205,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads(self):
     def test_merge_threads(self):
         """api merges two threads successfully"""
         """api merges two threads successfully"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -231,7 +231,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_kept_reads(self):
     def test_merge_threads_kept_reads(self):
         """api keeps both threads readtrackers after merge"""
         """api keeps both threads readtrackers after merge"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         poststracker.save_read(self.user, self.thread.first_post)
         poststracker.save_read(self.user, self.thread.first_post)
         poststracker.save_read(self.user, other_thread.first_post)
         poststracker.save_read(self.user, other_thread.first_post)
@@ -263,7 +263,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_kept_subs(self):
     def test_merge_threads_kept_subs(self):
         """api keeps other thread's subscription after merge"""
         """api keeps other thread's subscription after merge"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.user.subscription_set.create(
         self.user.subscription_set.create(
             thread=self.thread,
             thread=self.thread,
@@ -298,7 +298,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_moved_subs(self):
     def test_merge_threads_moved_subs(self):
         """api keeps other thread's subscription after merge"""
         """api keeps other thread's subscription after merge"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.user.subscription_set.create(
         self.user.subscription_set.create(
             thread=other_thread,
             thread=other_thread,
@@ -340,7 +340,7 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
             send_email=False,
             send_email=False,
         )
         )
 
 
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.user.subscription_set.create(
         self.user.subscription_set.create(
             thread=other_thread,
             thread=other_thread,
@@ -377,8 +377,8 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_kept_best_answer(self):
     def test_merge_threads_kept_best_answer(self):
         """api merges two threads successfully, keeping best answer from old thread"""
         """api merges two threads successfully, keeping best answer from old thread"""
-        other_thread = testutils.post_thread(self.other_category)
-        best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.other_category)
+        best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, best_answer)
         other_thread.set_best_answer(self.user, best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -410,9 +410,9 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_moved_best_answer(self):
     def test_merge_threads_moved_best_answer(self):
         """api merges two threads successfully, moving best answer to old thread"""
         """api merges two threads successfully, moving best answer to old thread"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
@@ -444,12 +444,12 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_merge_conflict_best_answer(self):
     def test_merge_threads_merge_conflict_best_answer(self):
         """api errors on merge conflict, returning list of available best answers"""
         """api errors on merge conflict, returning list of available best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.other_category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.other_category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -482,12 +482,12 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_best_answer_invalid_resolution(self):
     def test_threads_merge_conflict_best_answer_invalid_resolution(self):
         """api errors on invalid merge conflict resolution"""
         """api errors on invalid merge conflict resolution"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.other_category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.other_category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -515,12 +515,12 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_unmark_all_best_answers(self):
     def test_threads_merge_conflict_unmark_all_best_answers(self):
         """api unmarks all best answers when unmark all choice is selected"""
         """api unmarks all best answers when unmark all choice is selected"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.other_category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.other_category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -552,12 +552,12 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_first_best_answer(self):
     def test_threads_merge_conflict_keep_first_best_answer(self):
         """api unmarks other best answer on merge"""
         """api unmarks other best answer on merge"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.other_category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.other_category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -594,12 +594,12 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_other_best_answer(self):
     def test_threads_merge_conflict_keep_other_best_answer(self):
         """api unmarks first best answer on merge"""
         """api unmarks first best answer on merge"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.other_category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.other_category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -636,8 +636,8 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_kept_poll(self):
     def test_merge_threads_kept_poll(self):
         """api merges two threads successfully, keeping poll from other thread"""
         """api merges two threads successfully, keeping poll from other thread"""
-        other_thread = testutils.post_thread(self.other_category)
-        poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.other_category)
+        poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -671,8 +671,8 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_moved_poll(self):
     def test_merge_threads_moved_poll(self):
         """api merges two threads successfully, moving poll from old thread"""
         """api merges two threads successfully, moving poll from old thread"""
-        other_thread = testutils.post_thread(self.other_category)
-        poll = testutils.post_poll(self.thread, self.user)
+        other_thread = test.post_thread(self.other_category)
+        poll = test.post_poll(self.thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -706,9 +706,9 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_polls(self):
     def test_threads_merge_conflict_polls(self):
         """api errors on merge conflict, returning list of available polls"""
         """api errors on merge conflict, returning list of available polls"""
-        other_thread = testutils.post_thread(self.other_category)
-        poll = testutils.post_poll(self.thread, self.user)
-        other_poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.other_category)
+        poll = test.post_poll(self.thread, self.user)
+        other_poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
             self.api_link, {"other_thread": other_thread.get_absolute_url()}
@@ -736,10 +736,10 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_poll_invalid_resolution(self):
     def test_threads_merge_conflict_poll_invalid_resolution(self):
         """api errors on invalid merge conflict resolution"""
         """api errors on invalid merge conflict resolution"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
-        testutils.post_poll(self.thread, self.user)
-        testutils.post_poll(other_thread, self.user)
+        test.post_poll(self.thread, self.user)
+        test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -759,9 +759,9 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_delete_all_polls(self):
     def test_threads_merge_conflict_delete_all_polls(self):
         """api deletes all polls when delete all choice is selected"""
         """api deletes all polls when delete all choice is selected"""
-        other_thread = testutils.post_thread(self.other_category)
-        testutils.post_poll(self.thread, self.user)
-        testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.other_category)
+        test.post_poll(self.thread, self.user)
+        test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"other_thread": other_thread.get_absolute_url(), "poll": 0}
             self.api_link, {"other_thread": other_thread.get_absolute_url(), "poll": 0}
@@ -791,9 +791,9 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_first_poll(self):
     def test_threads_merge_conflict_keep_first_poll(self):
         """api deletes other poll on merge"""
         """api deletes other poll on merge"""
-        other_thread = testutils.post_thread(self.other_category)
-        poll = testutils.post_poll(self.thread, self.user)
-        other_poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.other_category)
+        poll = test.post_poll(self.thread, self.user)
+        other_poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -831,9 +831,9 @@ class ThreadMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_other_poll(self):
     def test_threads_merge_conflict_keep_other_poll(self):
         """api deletes first poll on merge"""
         """api deletes first poll on merge"""
-        other_thread = testutils.post_thread(self.other_category)
-        poll = testutils.post_poll(self.thread, self.user)
-        other_poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.other_category)
+        poll = test.post_poll(self.thread, self.user)
+        other_poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,

+ 10 - 10
misago/threads/tests/test_thread_model.py

@@ -4,9 +4,9 @@ from django.test import TestCase
 from django.utils import timezone
 from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Poll, Post, Thread, ThreadParticipant
 from misago.threads.models import Poll, Post, Thread, ThreadParticipant
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class ThreadModelTests(TestCase):
 class ThreadModelTests(TestCase):
@@ -317,7 +317,7 @@ class ThreadModelTests(TestCase):
         """set_best_answer implements some assertions for data integrity"""
         """set_best_answer implements some assertions for data integrity"""
         user = create_test_user("User", "user@example.com")
         user = create_test_user("User", "user@example.com")
 
 
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
         with self.assertRaises(ValueError):
         with self.assertRaises(ValueError):
             self.thread.set_best_answer(user, other_thread.first_post)
             self.thread.set_best_answer(user, other_thread.first_post)
 
 
@@ -325,11 +325,11 @@ class ThreadModelTests(TestCase):
             self.thread.set_best_answer(user, self.thread.first_post)
             self.thread.set_best_answer(user, self.thread.first_post)
 
 
         with self.assertRaises(ValueError):
         with self.assertRaises(ValueError):
-            reply = testutils.reply_thread(self.thread, is_hidden=True)
+            reply = test.reply_thread(self.thread, is_hidden=True)
             self.thread.set_best_answer(user, reply)
             self.thread.set_best_answer(user, reply)
 
 
         with self.assertRaises(ValueError):
         with self.assertRaises(ValueError):
-            reply = testutils.reply_thread(self.thread, is_unapproved=True)
+            reply = test.reply_thread(self.thread, is_unapproved=True)
             self.thread.set_best_answer(user, reply)
             self.thread.set_best_answer(user, reply)
 
 
     def test_move(self):
     def test_move(self):
@@ -395,15 +395,15 @@ class ThreadModelTests(TestCase):
         private thread gets deleted automatically
         private thread gets deleted automatically
         when there are no participants left in it
         when there are no participants left in it
         """
         """
-        user_1 = create_test_user("User1", "user1@example.com")
-        user_2 = create_test_user("User2", "user2@example.com")
+        user = create_test_user("User", "user@example.com")
+        other_user = create_test_user("OtherUser", "otheruser@example.com")
 
 
-        ThreadParticipant.objects.add_participants(self.thread, [user_1, user_2])
+        ThreadParticipant.objects.add_participants(self.thread, [user, other_user])
         self.assertEqual(self.thread.participants.count(), 2)
         self.assertEqual(self.thread.participants.count(), 2)
 
 
-        user_1.delete()
+        user.delete()
         Thread.objects.get(id=self.thread.id)
         Thread.objects.get(id=self.thread.id)
 
 
-        user_2.delete()
+        other_user.delete()
         with self.assertRaises(Thread.DoesNotExist):
         with self.assertRaises(Thread.DoesNotExist):
             Thread.objects.get(id=self.thread.id)
             Thread.objects.get(id=self.thread.id)

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

@@ -5,7 +5,7 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 
 
@@ -983,7 +983,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2})
     def test_mark_best_answer(self):
     def test_mark_best_answer(self):
         """api makes it possible to mark best answer"""
         """api makes it possible to mark best answer"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1020,7 +1020,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
         """api validates that user is authenticated before marking best answer"""
         """api validates that user is authenticated before marking best answer"""
         self.logout_user()
         self.logout_user()
 
 
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1037,7 +1037,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 0})
     @patch_category_acl({"can_mark_best_answers": 0})
     def test_mark_best_answer_no_permission(self):
     def test_mark_best_answer_no_permission(self):
         """api validates permission to mark best answers"""
         """api validates permission to mark best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1060,7 +1060,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 1})
     @patch_category_acl({"can_mark_best_answers": 1})
     def test_mark_best_answer_not_thread_starter(self):
     def test_mark_best_answer_not_thread_starter(self):
         """api validates permission to mark best answers in owned thread"""
         """api validates permission to mark best answers in owned thread"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1094,7 +1094,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": False})
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": False})
     def test_mark_best_answer_category_closed_no_permission(self):
     def test_mark_best_answer_category_closed_no_permission(self):
         """api validates permission to mark best answers in closed category"""
         """api validates permission to mark best answers in closed category"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.category.is_closed = True
         self.category.is_closed = True
         self.category.save()
         self.category.save()
@@ -1121,7 +1121,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": True})
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": True})
     def test_mark_best_answer_category_closed(self):
     def test_mark_best_answer_category_closed(self):
         """api validates permission to mark best answers in closed category"""
         """api validates permission to mark best answers in closed category"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.category.is_closed = True
         self.category.is_closed = True
         self.category.save()
         self.category.save()
@@ -1135,7 +1135,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": False})
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": False})
     def test_mark_best_answer_thread_closed_no_permission(self):
     def test_mark_best_answer_thread_closed_no_permission(self):
         """api validates permission to mark best answers in closed thread"""
         """api validates permission to mark best answers in closed thread"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.is_closed = True
         self.thread.is_closed = True
         self.thread.save()
         self.thread.save()
@@ -1162,7 +1162,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": True})
     @patch_category_acl({"can_mark_best_answers": 2, "can_close_threads": True})
     def test_mark_best_answer_thread_closed(self):
     def test_mark_best_answer_thread_closed(self):
         """api validates permission to mark best answers in closed thread"""
         """api validates permission to mark best answers in closed thread"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.is_closed = True
         self.thread.is_closed = True
         self.thread.save()
         self.thread.save()
@@ -1213,7 +1213,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2})
     def test_mark_best_answer_post_invisible(self):
     def test_mark_best_answer_post_invisible(self):
         """api validates post visibility to action author"""
         """api validates post visibility to action author"""
-        unapproved_post = testutils.reply_thread(self.thread, is_unapproved=True)
+        unapproved_post = test.reply_thread(self.thread, is_unapproved=True)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1230,7 +1230,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2})
     def test_mark_best_answer_post_other_thread(self):
     def test_mark_best_answer_post_other_thread(self):
         """api validates post belongs to same thread"""
         """api validates post belongs to same thread"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1253,7 +1253,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2})
     def test_mark_best_answer_event_id(self):
     def test_mark_best_answer_event_id(self):
         """api validates that post is not an event"""
         """api validates that post is not an event"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         best_answer.is_event = True
         best_answer.is_event = True
         best_answer.save()
         best_answer.save()
 
 
@@ -1301,7 +1301,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2})
     def test_mark_best_answer_hidden_post(self):
     def test_mark_best_answer_hidden_post(self):
         """api validates that post is not hidden"""
         """api validates that post is not hidden"""
-        best_answer = testutils.reply_thread(self.thread, is_hidden=True)
+        best_answer = test.reply_thread(self.thread, is_hidden=True)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1322,7 +1322,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2})
     def test_mark_best_answer_unapproved_post(self):
     def test_mark_best_answer_unapproved_post(self):
         """api validates that post is not unapproved"""
         """api validates that post is not unapproved"""
-        best_answer = testutils.reply_thread(
+        best_answer = test.reply_thread(
             self.thread, poster=self.user, is_unapproved=True
             self.thread, poster=self.user, is_unapproved=True
         )
         )
 
 
@@ -1345,7 +1345,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_protect_posts": False})
     @patch_category_acl({"can_mark_best_answers": 2, "can_protect_posts": False})
     def test_mark_best_answer_protected_post_no_permission(self):
     def test_mark_best_answer_protected_post_no_permission(self):
         """api respects post protection"""
         """api respects post protection"""
-        best_answer = testutils.reply_thread(self.thread, is_protected=True)
+        best_answer = test.reply_thread(self.thread, is_protected=True)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1369,7 +1369,7 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_protect_posts": True})
     @patch_category_acl({"can_mark_best_answers": 2, "can_protect_posts": True})
     def test_mark_best_answer_protected_post(self):
     def test_mark_best_answer_protected_post(self):
         """api respects post protection"""
         """api respects post protection"""
-        best_answer = testutils.reply_thread(self.thread, is_protected=True)
+        best_answer = test.reply_thread(self.thread, is_protected=True)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1382,14 +1382,14 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.best_answer = testutils.reply_thread(self.thread)
+        self.best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, self.best_answer)
         self.thread.set_best_answer(self.user, self.best_answer)
         self.thread.save()
         self.thread.save()
 
 
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 2})
     def test_change_best_answer(self):
     def test_change_best_answer(self):
         """api makes it possible to change best answer"""
         """api makes it possible to change best answer"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1443,7 +1443,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 0, "can_change_marked_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 0, "can_change_marked_answers": 2})
     def test_change_best_answer_no_permission_to_mark(self):
     def test_change_best_answer_no_permission_to_mark(self):
         """api validates permission to mark best answers before allowing answer change"""
         """api validates permission to mark best answers before allowing answer change"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1466,7 +1466,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 0})
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 0})
     def test_change_best_answer_no_permission(self):
     def test_change_best_answer_no_permission(self):
         """api validates permission to change best answers"""
         """api validates permission to change best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1490,7 +1490,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 1})
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 1})
     def test_change_best_answer_not_starter(self):
     def test_change_best_answer_not_starter(self):
         """api validates permission to change best answers"""
         """api validates permission to change best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1530,7 +1530,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     )
     )
     def test_change_best_answer_timelimit_out_of_time(self):
     def test_change_best_answer_timelimit_out_of_time(self):
         """api validates permission for starter to change best answers within timelimit"""
         """api validates permission for starter to change best answers within timelimit"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=6)
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=6)
         self.thread.starter = self.user
         self.thread.starter = self.user
@@ -1564,7 +1564,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     )
     )
     def test_change_best_answer_timelimit(self):
     def test_change_best_answer_timelimit(self):
         """api validates permission for starter to change best answers within timelimit"""
         """api validates permission for starter to change best answers within timelimit"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=1)
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=1)
         self.thread.starter = self.user
         self.thread.starter = self.user
@@ -1585,7 +1585,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     )
     )
     def test_change_best_answer_protected_no_permission(self):
     def test_change_best_answer_protected_no_permission(self):
         """api validates permission to change protected best answers"""
         """api validates permission to change protected best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.best_answer_is_protected = True
         self.thread.best_answer_is_protected = True
         self.thread.save()
         self.thread.save()
@@ -1618,7 +1618,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     )
     )
     def test_change_best_answer_protected(self):
     def test_change_best_answer_protected(self):
         """api validates permission to change protected best answers"""
         """api validates permission to change protected best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.best_answer_is_protected = True
         self.thread.best_answer_is_protected = True
         self.thread.save()
         self.thread.save()
@@ -1632,7 +1632,7 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 2, "can_change_marked_answers": 2})
     def test_change_best_answer_post_validation(self):
     def test_change_best_answer_post_validation(self):
         """api validates new post'"""
         """api validates new post'"""
-        best_answer = testutils.reply_thread(self.thread, is_hidden=True)
+        best_answer = test.reply_thread(self.thread, is_hidden=True)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,
@@ -1648,7 +1648,7 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.best_answer = testutils.reply_thread(self.thread)
+        self.best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, self.best_answer)
         self.thread.set_best_answer(self.user, self.best_answer)
         self.thread.save()
         self.thread.save()
 
 
@@ -1716,7 +1716,7 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
     @patch_category_acl({"can_mark_best_answers": 0, "can_change_marked_answers": 2})
     @patch_category_acl({"can_mark_best_answers": 0, "can_change_marked_answers": 2})
     def test_unmark_best_answer_wrong_post(self):
     def test_unmark_best_answer_wrong_post(self):
         """api validates if post given to unmark is best answer"""
         """api validates if post given to unmark is best answer"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link,
             self.api_link,

+ 4 - 4
misago/threads/tests/test_thread_poll_api.py

@@ -3,8 +3,8 @@ import json
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.threads import test
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadPollApiTestCase(AuthenticatedUserTestCase):
 class ThreadPollApiTestCase(AuthenticatedUserTestCase):
@@ -12,7 +12,7 @@ class ThreadPollApiTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(self.category, poster=self.user)
+        self.thread = test.post_thread(self.category, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-poll-list", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-poll-list", kwargs={"thread_pk": self.thread.pk}
@@ -29,7 +29,7 @@ class ThreadPollApiTestCase(AuthenticatedUserTestCase):
         )
         )
 
 
     def mock_poll(self):
     def mock_poll(self):
-        self.poll = self.thread.poll = testutils.post_poll(self.thread, self.user)
+        self.poll = self.thread.poll = test.post_poll(self.thread, self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-poll-detail",
             "misago:api:thread-poll-detail",

+ 4 - 5
misago/threads/tests/test_thread_pollvotes_api.py

@@ -10,7 +10,6 @@ from misago.threads.test import patch_category_acl
 
 
 from .test_thread_poll_api import ThreadPollApiTestCase
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 
-
 User = get_user_model()
 User = get_user_model()
 
 
 
 
@@ -109,10 +108,10 @@ class ThreadGetVotesTests(ThreadPollApiTestCase):
         self.assertEqual([len(c["voters"]) for c in response_json], [1, 0, 2, 1])
         self.assertEqual([len(c["voters"]) for c in response_json], [1, 0, 2, 1])
 
 
         self.assertEqual(
         self.assertEqual(
-            [[v["username"] for v in c["voters"]] for c in response_json][0][0], "bob"
+            [[v["username"] for v in c["voters"]] for c in response_json][0][0], "User"
         )
         )
 
 
-        user = User.objects.get(slug="bob")
+        user = User.objects.get(slug="user")
 
 
         self.assertEqual(
         self.assertEqual(
             [[v["url"] for v in c["voters"]] for c in response_json][0][0],
             [[v["url"] for v in c["voters"]] for c in response_json][0][0],
@@ -138,10 +137,10 @@ class ThreadGetVotesTests(ThreadPollApiTestCase):
         self.assertEqual([len(c["voters"]) for c in response_json], [1, 0, 2, 1])
         self.assertEqual([len(c["voters"]) for c in response_json], [1, 0, 2, 1])
 
 
         self.assertEqual(
         self.assertEqual(
-            [[v["username"] for v in c["voters"]] for c in response_json][0][0], "bob"
+            [[v["username"] for v in c["voters"]] for c in response_json][0][0], "User"
         )
         )
 
 
-        user = User.objects.get(slug="bob")
+        user = User.objects.get(slug="user")
 
 
         self.assertEqual(
         self.assertEqual(
             [[v["url"] for v in c["voters"]] for c in response_json][0][0],
             [[v["url"] for v in c["voters"]] for c in response_json][0][0],

+ 6 - 6
misago/threads/tests/test_thread_postbulkdelete_api.py

@@ -4,7 +4,7 @@ from datetime import timedelta
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
 
 
@@ -16,9 +16,9 @@ class PostBulkDeleteApiTests(ThreadsApiTestCase):
         super().setUp()
         super().setUp()
 
 
         self.posts = [
         self.posts = [
-            testutils.reply_thread(self.thread, poster=self.user),
-            testutils.reply_thread(self.thread),
-            testutils.reply_thread(self.thread, poster=self.user),
+            test.reply_thread(self.thread, poster=self.user),
+            test.reply_thread(self.thread),
+            test.reply_thread(self.thread, poster=self.user),
         ]
         ]
 
 
         self.api_link = reverse(
         self.api_link = reverse(
@@ -123,8 +123,8 @@ class PostBulkDeleteApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_hide_posts": 2})
     @patch_category_acl({"can_hide_posts": 2})
     def test_validate_posts_same_thread(self):
     def test_validate_posts_same_thread(self):
         """api validates that ids are same thread posts"""
         """api validates that ids are same thread posts"""
-        other_thread = testutils.post_thread(category=self.category)
-        self.posts.append(testutils.reply_thread(other_thread, poster=self.user))
+        other_thread = test.post_thread(category=self.category)
+        self.posts.append(test.reply_thread(other_thread, poster=self.user))
 
 
         response = self.delete(self.api_link, [p.id for p in self.posts])
         response = self.delete(self.api_link, [p.id for p in self.posts])
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)

+ 8 - 8
misago/threads/tests/test_thread_postbulkpatch_api.py

@@ -5,10 +5,10 @@ from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadPostBulkPatchApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostBulkPatchApiTestCase(AuthenticatedUserTestCase):
@@ -16,11 +16,11 @@ class ThreadPostBulkPatchApiTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
         self.posts = [
         self.posts = [
-            testutils.reply_thread(self.thread, poster=self.user),
-            testutils.reply_thread(self.thread),
-            testutils.reply_thread(self.thread, poster=self.user),
+            test.reply_thread(self.thread, poster=self.user),
+            test.reply_thread(self.thread),
+            test.reply_thread(self.thread, poster=self.user),
         ]
         ]
 
 
         self.ids = [p.id for p in self.posts]
         self.ids = [p.id for p in self.posts]
@@ -115,8 +115,8 @@ class BulkPatchSerializerTests(ThreadPostBulkPatchApiTestCase):
     def test_posts_not_found(self):
     def test_posts_not_found(self):
         """api fails to find posts"""
         """api fails to find posts"""
         posts = [
         posts = [
-            testutils.reply_thread(self.thread, is_hidden=True),
-            testutils.reply_thread(self.thread, is_unapproved=True),
+            test.reply_thread(self.thread, is_hidden=True),
+            test.reply_thread(self.thread, is_unapproved=True),
         ]
         ]
 
 
         response = self.patch(
         response = self.patch(

+ 3 - 5
misago/threads/tests/test_thread_postdelete_api.py

@@ -3,7 +3,7 @@ from datetime import timedelta
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
 
 
@@ -14,7 +14,7 @@ class PostDeleteApiTests(ThreadsApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-detail",
             "misago:api:thread-post-detail",
@@ -182,9 +182,7 @@ class EventDeleteApiTests(ThreadsApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.event = testutils.reply_thread(
-            self.thread, poster=self.user, is_event=True
-        )
+        self.event = test.reply_thread(self.thread, poster=self.user, is_event=True)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-detail",
             "misago:api:thread-post-detail",

+ 2 - 2
misago/threads/tests/test_thread_postedits_api.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
 
 
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
@@ -10,7 +10,7 @@ class ThreadPostEditsApiTestCase(ThreadsApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-edits",
             "misago:api:thread-post-edits",

+ 6 - 6
misago/threads/tests/test_thread_postlikes_api.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
 from misago.threads.serializers import PostLikeSerializer
 from misago.threads.serializers import PostLikeSerializer
 
 
@@ -11,7 +11,7 @@ class ThreadPostLikesApiTestCase(ThreadsApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-likes",
             "misago:api:thread-post-likes",
@@ -23,7 +23,7 @@ class ThreadPostLikesApiTestCase(ThreadsApiTestCase):
         """api errors if user has no permission to see likes"""
         """api errors if user has no permission to see likes"""
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
-        self.assertEquals(
+        self.assertEqual(
             response.json(), {"detail": "You can't see who liked this post."}
             response.json(), {"detail": "You can't see who liked this post."}
         )
         )
 
 
@@ -32,7 +32,7 @@ class ThreadPostLikesApiTestCase(ThreadsApiTestCase):
         """api errors if user has no permission to see likes, but can see likes count"""
         """api errors if user has no permission to see likes, but can see likes count"""
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
-        self.assertEquals(
+        self.assertEqual(
             response.json(), {"detail": "You can't see who liked this post."}
             response.json(), {"detail": "You can't see who liked this post."}
         )
         )
 
 
@@ -46,8 +46,8 @@ class ThreadPostLikesApiTestCase(ThreadsApiTestCase):
     @patch_category_acl({"can_see_posts_likes": 2})
     @patch_category_acl({"can_see_posts_likes": 2})
     def test_likes(self):
     def test_likes(self):
         """api returns list of likes"""
         """api returns list of likes"""
-        like = testutils.like_post(self.post, self.user)
-        other_like = testutils.like_post(self.post, self.user)
+        like = test.like_post(self.post, self.user)
+        other_like = test.like_post(self.post, self.user)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)

+ 42 - 48
misago/threads/tests/test_thread_postmerge_api.py

@@ -4,11 +4,11 @@ from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.serializers.moderation import POSTS_LIMIT
 from misago.threads.serializers.moderation import POSTS_LIMIT
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
@@ -16,8 +16,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.thread = test.post_thread(category=self.category)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-merge", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-merge", kwargs={"thread_pk": self.thread.pk}
@@ -177,7 +177,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_event(self):
     def test_merge_event(self):
         """api recjects events"""
         """api recjects events"""
-        event = testutils.reply_thread(self.thread, is_event=True, poster=self.user)
+        event = test.reply_thread(self.thread, is_event=True, poster=self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -204,8 +204,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_cross_threads(self):
     def test_merge_cross_threads(self):
         """api recjects attempt to merge with post made in other thread"""
         """api recjects attempt to merge with post made in other thread"""
-        other_thread = testutils.post_thread(category=self.category)
-        other_post = testutils.reply_thread(other_thread, poster=self.user)
+        other_thread = test.post_thread(category=self.category)
+        other_post = test.reply_thread(other_thread, poster=self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -221,7 +221,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_authenticated_with_guest_post(self):
     def test_merge_authenticated_with_guest_post(self):
         """api recjects attempt to merge with post made by deleted user"""
         """api recjects attempt to merge with post made by deleted user"""
-        other_post = testutils.reply_thread(self.thread)
+        other_post = test.reply_thread(self.thread)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -237,7 +237,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_guest_with_authenticated_post(self):
     def test_merge_guest_with_authenticated_post(self):
         """api recjects attempt to merge with post made by deleted user"""
         """api recjects attempt to merge with post made by deleted user"""
-        other_post = testutils.reply_thread(self.thread)
+        other_post = test.reply_thread(self.thread)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -258,8 +258,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(self.thread, poster="Bob").pk,
-                        testutils.reply_thread(self.thread, poster="Miku").pk,
+                        test.reply_thread(self.thread, poster="Bob").pk,
+                        test.reply_thread(self.thread, poster="Miku").pk,
                     ]
                     ]
                 }
                 }
             ),
             ),
@@ -279,10 +279,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_hidden=True
                             self.thread, poster=self.user, is_hidden=True
                         ).pk,
                         ).pk,
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_hidden=False
                             self.thread, poster=self.user, is_hidden=False
                         ).pk,
                         ).pk,
                     ]
                     ]
@@ -304,10 +304,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_unapproved=True
                             self.thread, poster=self.user, is_unapproved=True
                         ).pk,
                         ).pk,
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_unapproved=False
                             self.thread, poster=self.user, is_unapproved=False
                         ).pk,
                         ).pk,
                     ]
                     ]
@@ -328,8 +328,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         self.thread.save()
         self.thread.save()
 
 
         posts = [
         posts = [
-            testutils.reply_thread(self.thread, poster=self.user).pk,
-            testutils.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
         ]
         ]
 
 
         response = self.client.post(
         response = self.client.post(
@@ -348,8 +348,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         self.thread.save()
         self.thread.save()
 
 
         posts = [
         posts = [
-            testutils.reply_thread(self.thread, poster=self.user).pk,
-            testutils.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
         ]
         ]
 
 
         response = self.client.post(
         response = self.client.post(
@@ -364,8 +364,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         self.category.save()
         self.category.save()
 
 
         posts = [
         posts = [
-            testutils.reply_thread(self.thread, poster=self.user).pk,
-            testutils.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
         ]
         ]
 
 
         response = self.client.post(
         response = self.client.post(
@@ -384,8 +384,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         self.category.save()
         self.category.save()
 
 
         posts = [
         posts = [
-            testutils.reply_thread(self.thread, poster=self.user).pk,
-            testutils.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
+            test.reply_thread(self.thread, poster=self.user).pk,
         ]
         ]
 
 
         response = self.client.post(
         response = self.client.post(
@@ -421,10 +421,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_posts(self):
     def test_merge_posts(self):
         """api merges two posts"""
         """api merges two posts"""
-        post_a = testutils.reply_thread(
-            self.thread, poster=self.user, message="Battęry"
-        )
-        post_b = testutils.reply_thread(self.thread, poster=self.user, message="Hórse")
+        post_a = test.reply_thread(self.thread, poster=self.user, message="Battęry")
+        post_b = test.reply_thread(self.thread, poster=self.user, message="Hórse")
 
 
         thread_replies = self.thread.replies
         thread_replies = self.thread.replies
 
 
@@ -452,8 +450,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(self.thread, poster="Bob").pk,
-                        testutils.reply_thread(self.thread, poster="Bob").pk,
+                        test.reply_thread(self.thread, poster="Bob").pk,
+                        test.reply_thread(self.thread, poster="Bob").pk,
                     ]
                     ]
                 }
                 }
             ),
             ),
@@ -469,10 +467,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_hidden=True
                             self.thread, poster=self.user, is_hidden=True
                         ).pk,
                         ).pk,
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_hidden=True
                             self.thread, poster=self.user, is_hidden=True
                         ).pk,
                         ).pk,
                     ]
                     ]
@@ -490,10 +488,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_unapproved=True
                             self.thread, poster=self.user, is_unapproved=True
                         ).pk,
                         ).pk,
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster=self.user, is_unapproved=True
                             self.thread, poster=self.user, is_unapproved=True
                         ).pk,
                         ).pk,
                     ]
                     ]
@@ -510,9 +508,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         self.thread.first_post.poster = self.user
         self.thread.first_post.poster = self.user
         self.thread.first_post.save()
         self.thread.first_post.save()
 
 
-        post_visible = testutils.reply_thread(
-            self.thread, poster=self.user, is_hidden=False
-        )
+        post_visible = test.reply_thread(self.thread, poster=self.user, is_hidden=False)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -529,10 +525,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "posts": [
                     "posts": [
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster="Bob", is_protected=True
                             self.thread, poster="Bob", is_protected=True
                         ).pk,
                         ).pk,
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster="Bob", is_protected=False
                             self.thread, poster="Bob", is_protected=False
                         ).pk,
                         ).pk,
                     ]
                     ]
@@ -548,7 +544,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer(self):
     def test_merge_best_answer(self):
         """api merges best answer with other post"""
         """api merges best answer with other post"""
-        best_answer = testutils.reply_thread(self.thread, poster="Bob")
+        best_answer = test.reply_thread(self.thread, poster="Bob")
 
 
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
@@ -559,7 +555,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
                 {
                 {
                     "posts": [
                     "posts": [
                         best_answer.pk,
                         best_answer.pk,
-                        testutils.reply_thread(self.thread, poster="Bob").pk,
+                        test.reply_thread(self.thread, poster="Bob").pk,
                     ]
                     ]
                 }
                 }
             ),
             ),
@@ -573,8 +569,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer_in(self):
     def test_merge_best_answer_in(self):
         """api merges best answer into other post"""
         """api merges best answer into other post"""
-        other_post = testutils.reply_thread(self.thread, poster="Bob")
-        best_answer = testutils.reply_thread(self.thread, poster="Bob")
+        other_post = test.reply_thread(self.thread, poster="Bob")
+        best_answer = test.reply_thread(self.thread, poster="Bob")
 
 
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
@@ -592,7 +588,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_best_answer_in_protected(self):
     def test_merge_best_answer_in_protected(self):
         """api merges best answer into protected post"""
         """api merges best answer into protected post"""
-        best_answer = testutils.reply_thread(self.thread, poster="Bob")
+        best_answer = test.reply_thread(self.thread, poster="Bob")
 
 
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
@@ -603,7 +599,7 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
                 {
                 {
                     "posts": [
                     "posts": [
                         best_answer.pk,
                         best_answer.pk,
-                        testutils.reply_thread(
+                        test.reply_thread(
                             self.thread, poster="Bob", is_protected=True
                             self.thread, poster="Bob", is_protected=True
                         ).pk,
                         ).pk,
                     ]
                     ]
@@ -623,10 +619,8 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_merge_posts": True})
     @patch_category_acl({"can_merge_posts": True})
     def test_merge_remove_reads(self):
     def test_merge_remove_reads(self):
         """two posts merge removes read tracker from post"""
         """two posts merge removes read tracker from post"""
-        post_a = testutils.reply_thread(
-            self.thread, poster=self.user, message="Battęry"
-        )
-        post_b = testutils.reply_thread(self.thread, poster=self.user, message="Hórse")
+        post_a = test.reply_thread(self.thread, poster=self.user, message="Battęry")
+        post_b = test.reply_thread(self.thread, poster=self.user, message="Hórse")
 
 
         poststracker.save_read(self.user, post_a)
         poststracker.save_read(self.user, post_a)
         poststracker.save_read(self.user, post_b)
         poststracker.save_read(self.user, post_b)

+ 35 - 40
misago/threads/tests/test_thread_postmove_api.py

@@ -4,11 +4,11 @@ from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 from misago.threads.serializers.moderation import POSTS_LIMIT
 from misago.threads.serializers.moderation import POSTS_LIMIT
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 from misago.threads.test import patch_category_acl, patch_other_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
@@ -16,7 +16,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-move", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-move", kwargs={"thread_pk": self.thread.pk}
@@ -123,7 +123,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_other_thread_exists(self):
     def test_other_thread_exists(self):
         """api validates if other thread exists"""
         """api validates if other thread exists"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
@@ -143,7 +143,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_other_thread_is_invisible(self):
     def test_other_thread_is_invisible(self):
         """api validates if other thread is visible"""
         """api validates if other thread is visible"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
@@ -163,7 +163,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_other_thread_isnt_replyable(self):
     def test_other_thread_isnt_replyable(self):
         """api validates if other thread can be replied"""
         """api validates if other thread can be replied"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
@@ -177,7 +177,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_empty_data(self):
     def test_empty_data(self):
         """api handles empty data"""
         """api handles empty data"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(self.api_link)
         response = self.client.post(self.api_link)
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -186,7 +186,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_empty_posts_data_json(self):
     def test_empty_posts_data_json(self):
         """api handles empty json data"""
         """api handles empty json data"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -202,7 +202,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_empty_posts_data_form(self):
     def test_empty_posts_data_form(self):
         """api handles empty form data"""
         """api handles empty form data"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
             self.api_link, {"new_thread": other_thread.get_absolute_url()}
@@ -216,7 +216,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_no_posts_ids(self):
     def test_no_posts_ids(self):
         """api rejects no posts ids"""
         """api rejects no posts ids"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -232,7 +232,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_invalid_posts_data(self):
     def test_invalid_posts_data(self):
         """api handles invalid data"""
         """api handles invalid data"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -249,7 +249,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_invalid_posts_ids(self):
     def test_invalid_posts_ids(self):
         """api handles invalid post id"""
         """api handles invalid post id"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -269,7 +269,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_limit(self):
     def test_move_limit(self):
         """api rejects more posts than move limit"""
         """api rejects more posts than move limit"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -293,16 +293,14 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_invisible(self):
     def test_move_invisible(self):
         """api validates posts visibility"""
         """api validates posts visibility"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             json.dumps(
             json.dumps(
                 {
                 {
                     "new_thread": other_thread.get_absolute_url(),
                     "new_thread": other_thread.get_absolute_url(),
-                    "posts": [
-                        testutils.reply_thread(self.thread, is_unapproved=True).pk
-                    ],
+                    "posts": [test.reply_thread(self.thread, is_unapproved=True).pk],
                 }
                 }
             ),
             ),
             content_type="application/json",
             content_type="application/json",
@@ -315,14 +313,14 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_other_thread_posts(self):
     def test_move_other_thread_posts(self):
         """api recjects attempt to move other thread's post"""
         """api recjects attempt to move other thread's post"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             json.dumps(
             json.dumps(
                 {
                 {
                     "new_thread": other_thread.get_absolute_url(),
                     "new_thread": other_thread.get_absolute_url(),
-                    "posts": [testutils.reply_thread(other_thread, is_hidden=True).pk],
+                    "posts": [test.reply_thread(other_thread, is_hidden=True).pk],
                 }
                 }
             ),
             ),
             content_type="application/json",
             content_type="application/json",
@@ -335,14 +333,14 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_event(self):
     def test_move_event(self):
         """api rejects events move"""
         """api rejects events move"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             json.dumps(
             json.dumps(
                 {
                 {
                     "new_thread": other_thread.get_absolute_url(),
                     "new_thread": other_thread.get_absolute_url(),
-                    "posts": [testutils.reply_thread(self.thread, is_event=True).pk],
+                    "posts": [test.reply_thread(self.thread, is_event=True).pk],
                 }
                 }
             ),
             ),
             content_type="application/json",
             content_type="application/json",
@@ -353,7 +351,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_first_post(self):
     def test_move_first_post(self):
         """api rejects first post move"""
         """api rejects first post move"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -373,14 +371,14 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_hidden_posts(self):
     def test_move_hidden_posts(self):
         """api recjects attempt to move urneadable hidden post"""
         """api recjects attempt to move urneadable hidden post"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             json.dumps(
             json.dumps(
                 {
                 {
                     "new_thread": other_thread.get_absolute_url(),
                     "new_thread": other_thread.get_absolute_url(),
-                    "posts": [testutils.reply_thread(self.thread, is_hidden=True).pk],
+                    "posts": [test.reply_thread(self.thread, is_hidden=True).pk],
                 }
                 }
             ),
             ),
             content_type="application/json",
             content_type="application/json",
@@ -394,7 +392,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True, "can_close_threads": False})
     @patch_category_acl({"can_move_posts": True, "can_close_threads": False})
     def test_move_posts_closed_thread_no_permission(self):
     def test_move_posts_closed_thread_no_permission(self):
         """api recjects attempt to move posts from closed thread"""
         """api recjects attempt to move posts from closed thread"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         self.thread.is_closed = True
         self.thread.is_closed = True
         self.thread.save()
         self.thread.save()
@@ -404,7 +402,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "new_thread": other_thread.get_absolute_url(),
                     "new_thread": other_thread.get_absolute_url(),
-                    "posts": [testutils.reply_thread(self.thread).pk],
+                    "posts": [test.reply_thread(self.thread).pk],
                 }
                 }
             ),
             ),
             content_type="application/json",
             content_type="application/json",
@@ -419,7 +417,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_posts_closed_category_no_permission(self):
     def test_move_posts_closed_category_no_permission(self):
         """api recjects attempt to move posts from closed thread"""
         """api recjects attempt to move posts from closed thread"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         self.category.is_closed = True
         self.category.is_closed = True
         self.category.save()
         self.category.save()
@@ -429,7 +427,7 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
             json.dumps(
             json.dumps(
                 {
                 {
                     "new_thread": other_thread.get_absolute_url(),
                     "new_thread": other_thread.get_absolute_url(),
-                    "posts": [testutils.reply_thread(self.thread).pk],
+                    "posts": [test.reply_thread(self.thread).pk],
                 }
                 }
             ),
             ),
             content_type="application/json",
             content_type="application/json",
@@ -444,13 +442,13 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_posts(self):
     def test_move_posts(self):
         """api moves posts to other thread"""
         """api moves posts to other thread"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
         posts = (
         posts = (
-            testutils.reply_thread(self.thread).pk,
-            testutils.reply_thread(self.thread).pk,
-            testutils.reply_thread(self.thread).pk,
-            testutils.reply_thread(self.thread).pk,
+            test.reply_thread(self.thread).pk,
+            test.reply_thread(self.thread).pk,
+            test.reply_thread(self.thread).pk,
+            test.reply_thread(self.thread).pk,
         )
         )
 
 
         self.thread.refresh_from_db()
         self.thread.refresh_from_db()
@@ -475,8 +473,8 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_best_answer(self):
     def test_move_best_answer(self):
         """api moves best answer to other thread"""
         """api moves best answer to other thread"""
-        other_thread = testutils.post_thread(self.other_category)
-        best_answer = testutils.reply_thread(self.thread)
+        other_thread = test.post_thread(self.other_category)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.synchronize()
         self.thread.synchronize()
@@ -511,12 +509,9 @@ class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_move_posts_reads(self):
     def test_move_posts_reads(self):
         """api moves posts reads together with posts"""
         """api moves posts reads together with posts"""
-        other_thread = testutils.post_thread(self.other_category)
+        other_thread = test.post_thread(self.other_category)
 
 
-        posts = (
-            testutils.reply_thread(self.thread),
-            testutils.reply_thread(self.thread),
-        )
+        posts = (test.reply_thread(self.thread), test.reply_thread(self.thread))
 
 
         self.thread.refresh_from_db()
         self.thread.refresh_from_db()
         self.assertEqual(self.thread.replies, 2)
         self.assertEqual(self.thread.replies, 2)

+ 11 - 13
misago/threads/tests/test_thread_postpatch_api.py

@@ -5,10 +5,10 @@ from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread, Post
 from misago.threads.models import Thread, Post
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadPostPatchApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostPatchApiTestCase(AuthenticatedUserTestCase):
@@ -16,8 +16,8 @@ class ThreadPostPatchApiTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.thread = test.post_thread(category=self.category)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-detail",
             "misago:api:thread-post-detail",
@@ -762,10 +762,10 @@ class PostLikeApiTests(ThreadPostPatchApiTestCase):
 
 
     def test_like_liked_post(self):
     def test_like_liked_post(self):
         """api adds user like to post"""
         """api adds user like to post"""
-        testutils.like_post(self.post, username="Myo")
-        testutils.like_post(self.post, username="Mugi")
-        testutils.like_post(self.post, username="Bob")
-        testutils.like_post(self.post, username="Miku")
+        test.like_post(self.post, username="Myo")
+        test.like_post(self.post, username="Mugi")
+        test.like_post(self.post, username="Bob")
+        test.like_post(self.post, username="Miku")
 
 
         response = self.patch(
         response = self.patch(
             self.api_link, [{"op": "replace", "path": "is-liked", "value": True}]
             self.api_link, [{"op": "replace", "path": "is-liked", "value": True}]
@@ -791,7 +791,7 @@ class PostLikeApiTests(ThreadPostPatchApiTestCase):
 
 
     def test_unlike_post(self):
     def test_unlike_post(self):
         """api removes user like from post"""
         """api removes user like from post"""
-        testutils.like_post(self.post, self.user)
+        test.like_post(self.post, self.user)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link, [{"op": "replace", "path": "is-liked", "value": False}]
             self.api_link, [{"op": "replace", "path": "is-liked", "value": False}]
@@ -809,7 +809,7 @@ class PostLikeApiTests(ThreadPostPatchApiTestCase):
 
 
     def test_like_post_no_change(self):
     def test_like_post_no_change(self):
         """api does no state change if we are linking liked post"""
         """api does no state change if we are linking liked post"""
-        testutils.like_post(self.post, self.user)
+        test.like_post(self.post, self.user)
 
 
         response = self.patch(
         response = self.patch(
             self.api_link, [{"op": "replace", "path": "is-liked", "value": True}]
             self.api_link, [{"op": "replace", "path": "is-liked", "value": True}]
@@ -845,9 +845,7 @@ class ThreadEventPatchApiTestCase(ThreadPostPatchApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.event = testutils.reply_thread(
-            self.thread, poster=self.user, is_event=True
-        )
+        self.event = test.reply_thread(self.thread, poster=self.user, is_event=True)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-detail",
             "misago:api:thread-post-detail",

+ 2 - 2
misago/threads/tests/test_thread_postread_api.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from misago.threads import testutils
+from misago.threads import test
 
 
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
@@ -10,7 +10,7 @@ class PostReadApiTests(ThreadsApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.post = testutils.reply_thread(
+        self.post = test.reply_thread(
             self.thread, poster=self.user, posted_on=timezone.now()
             self.thread, poster=self.user, posted_on=timezone.now()
         )
         )
 
 

+ 13 - 19
misago/threads/tests/test_thread_postsplit_api.py

@@ -4,11 +4,11 @@ from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.serializers.moderation import POSTS_LIMIT
 from misago.threads.serializers.moderation import POSTS_LIMIT
 from misago.threads.test import patch_category_acl, patch_other_category_acl
 from misago.threads.test import patch_category_acl, patch_other_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
@@ -16,10 +16,10 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
         self.posts = [
         self.posts = [
-            testutils.reply_thread(self.thread).pk,
-            testutils.reply_thread(self.thread).pk,
+            test.reply_thread(self.thread).pk,
+            test.reply_thread(self.thread).pk,
         ]
         ]
 
 
         self.api_link = reverse(
         self.api_link = reverse(
@@ -180,7 +180,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             json.dumps(
             json.dumps(
-                {"posts": [testutils.reply_thread(self.thread, is_unapproved=True).pk]}
+                {"posts": [test.reply_thread(self.thread, is_unapproved=True).pk]}
             ),
             ),
             content_type="application/json",
             content_type="application/json",
         )
         )
@@ -195,9 +195,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
         """api rejects events split"""
         """api rejects events split"""
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
-            json.dumps(
-                {"posts": [testutils.reply_thread(self.thread, is_event=True).pk]}
-            ),
+            json.dumps({"posts": [test.reply_thread(self.thread, is_event=True).pk]}),
             content_type="application/json",
             content_type="application/json",
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -221,9 +219,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
         """api recjects attempt to split urneadable hidden post"""
         """api recjects attempt to split urneadable hidden post"""
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
-            json.dumps(
-                {"posts": [testutils.reply_thread(self.thread, is_hidden=True).pk]}
-            ),
+            json.dumps({"posts": [test.reply_thread(self.thread, is_hidden=True).pk]}),
             content_type="application/json",
             content_type="application/json",
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -240,7 +236,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
-            json.dumps({"posts": [testutils.reply_thread(self.thread).pk]}),
+            json.dumps({"posts": [test.reply_thread(self.thread).pk]}),
             content_type="application/json",
             content_type="application/json",
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -257,7 +253,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
-            json.dumps({"posts": [testutils.reply_thread(self.thread).pk]}),
+            json.dumps({"posts": [test.reply_thread(self.thread).pk]}),
             content_type="application/json",
             content_type="application/json",
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -269,13 +265,11 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_split_other_thread_posts(self):
     def test_split_other_thread_posts(self):
         """api recjects attempt to split other thread's post"""
         """api recjects attempt to split other thread's post"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
-            json.dumps(
-                {"posts": [testutils.reply_thread(other_thread, is_hidden=True).pk]}
-            ),
+            json.dumps({"posts": [test.reply_thread(other_thread, is_hidden=True).pk]}),
             content_type="application/json",
             content_type="application/json",
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -638,7 +632,7 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
     @patch_category_acl({"can_move_posts": True})
     @patch_category_acl({"can_move_posts": True})
     def test_split_best_answer(self):
     def test_split_best_answer(self):
         """api splits best answer to new thread"""
         """api splits best answer to new thread"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
 
 
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.synchronize()
         self.thread.synchronize()

+ 3 - 3
misago/threads/tests/test_thread_reply_api.py

@@ -2,10 +2,10 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ReplyThreadTests(AuthenticatedUserTestCase):
 class ReplyThreadTests(AuthenticatedUserTestCase):
@@ -13,7 +13,7 @@ class ReplyThreadTests(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-list", kwargs={"thread_pk": self.thread.pk}

+ 1 - 1
misago/threads/tests/test_thread_start_api.py

@@ -3,7 +3,7 @@ from django.urls import reverse
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class StartThreadTests(AuthenticatedUserTestCase):
 class StartThreadTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/threads/tests/test_threadparticipant_model.py

@@ -3,7 +3,7 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.models import Post, Thread, ThreadParticipant
 from misago.threads.models import Post, Thread, ThreadParticipant
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class ThreadParticipantTests(TestCase):
 class ThreadParticipantTests(TestCase):

+ 6 - 6
misago/threads/tests/test_threads_api.py

@@ -5,11 +5,11 @@ from django.urls import reverse
 
 
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
 from misago.threads.threadtypes import trees_map
 from misago.threads.threadtypes import trees_map
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ThreadsApiTestCase(AuthenticatedUserTestCase):
 class ThreadsApiTestCase(AuthenticatedUserTestCase):
@@ -21,7 +21,7 @@ class ThreadsApiTestCase(AuthenticatedUserTestCase):
         self.root = Category.objects.get(tree_id=threads_tree_id, level=0)
         self.root = Category.objects.get(tree_id=threads_tree_id, level=0)
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
 
 
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
         self.api_link = self.thread.get_api_url()
         self.api_link = self.thread.get_api_url()
 
 
     def get_thread_json(self):
     def get_thread_json(self):
@@ -85,7 +85,7 @@ class ThreadRetrieveApiTests(ThreadsApiTestCase):
 
 
     def test_api_validates_posts_visibility(self):
     def test_api_validates_posts_visibility(self):
         """api validates posts visiblity"""
         """api validates posts visiblity"""
-        hidden_post = testutils.reply_thread(
+        hidden_post = test.reply_thread(
             self.thread, is_hidden=True, message="I'am hidden test message!"
             self.thread, is_hidden=True, message="I'am hidden test message!"
         )
         )
 
 
@@ -103,7 +103,7 @@ class ThreadRetrieveApiTests(ThreadsApiTestCase):
             )  # hidden post's body is visible with permission
             )  # hidden post's body is visible with permission
 
 
         # unapproved posts shouldn't show at all
         # unapproved posts shouldn't show at all
-        unapproved_post = testutils.reply_thread(self.thread, is_unapproved=True)
+        unapproved_post = test.reply_thread(self.thread, is_unapproved=True)
 
 
         with patch_category_acl({"can_approve_content": False}):
         with patch_category_acl({"can_approve_content": False}):
             response = self.client.get(self.tested_links[1])
             response = self.client.get(self.tested_links[1])
@@ -144,7 +144,7 @@ class ThreadDeleteApiTests(ThreadsApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.last_thread = testutils.post_thread(category=self.category)
+        self.last_thread = test.post_thread(category=self.category)
         self.api_link = self.last_thread.get_api_url()
         self.api_link = self.last_thread.get_api_url()
 
 
     def test_delete_thread_no_permission(self):
     def test_delete_thread_no_permission(self):

+ 4 - 4
misago/threads/tests/test_threads_bulkdelete_api.py

@@ -4,7 +4,7 @@ from django.urls import reverse
 
 
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 from misago.threads.serializers.moderation import THREADS_LIMIT
 from misago.threads.serializers.moderation import THREADS_LIMIT
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
@@ -20,9 +20,9 @@ class ThreadsBulkDeleteApiTests(ThreadsApiTestCase):
         self.api_link = reverse("misago:api:thread-list")
         self.api_link = reverse("misago:api:thread-list")
 
 
         self.threads = [
         self.threads = [
-            testutils.post_thread(category=self.category, poster=self.user),
-            testutils.post_thread(category=self.category),
-            testutils.post_thread(category=self.category, poster=self.user),
+            test.post_thread(category=self.category, poster=self.user),
+            test.post_thread(category=self.category),
+            test.post_thread(category=self.category, poster=self.user),
         ]
         ]
 
 
     def delete(self, url, data=None):
     def delete(self, url, data=None):

+ 11 - 11
misago/threads/tests/test_threads_editor_api.py

@@ -6,11 +6,11 @@ from misago.acl import useracl
 from misago.acl.objectacl import add_acl_to_obj
 from misago.acl.objectacl import add_acl_to_obj
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Attachment
 from misago.threads.models import Attachment
 from misago.threads.serializers import AttachmentSerializer
 from misago.threads.serializers import AttachmentSerializer
 from misago.threads.test import patch_category_acl
 from misago.threads.test import patch_category_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")
@@ -207,7 +207,7 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-editor", kwargs={"thread_pk": self.thread.pk}
             "misago:api:thread-post-editor", kwargs={"thread_pk": self.thread.pk}
         )
         )
@@ -297,7 +297,7 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
         """api validates replied post visibility"""
         """api validates replied post visibility"""
 
 
         # unapproved reply can't be replied to
         # unapproved reply can't be replied to
-        unapproved_reply = testutils.reply_thread(self.thread, is_unapproved=True)
+        unapproved_reply = test.reply_thread(self.thread, is_unapproved=True)
 
 
         with patch_category_acl({"can_reply_threads": True}):
         with patch_category_acl({"can_reply_threads": True}):
             response = self.client.get(
             response = self.client.get(
@@ -306,7 +306,7 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
             self.assertEqual(response.status_code, 404)
             self.assertEqual(response.status_code, 404)
 
 
         # hidden reply can't be replied to
         # hidden reply can't be replied to
-        hidden_reply = testutils.reply_thread(self.thread, is_hidden=True)
+        hidden_reply = test.reply_thread(self.thread, is_hidden=True)
 
 
         with patch_category_acl({"can_reply_threads": True}):
         with patch_category_acl({"can_reply_threads": True}):
             response = self.client.get("%s?reply=%s" % (self.api_link, hidden_reply.pk))
             response = self.client.get("%s?reply=%s" % (self.api_link, hidden_reply.pk))
@@ -317,8 +317,8 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
 
 
     def test_reply_to_other_thread_post(self):
     def test_reply_to_other_thread_post(self):
         """api validates is replied post belongs to same thread"""
         """api validates is replied post belongs to same thread"""
-        other_thread = testutils.post_thread(category=self.category)
-        reply_to = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(category=self.category)
+        reply_to = test.reply_thread(other_thread)
 
 
         response = self.client.get("%s?reply=%s" % (self.api_link, reply_to.pk))
         response = self.client.get("%s?reply=%s" % (self.api_link, reply_to.pk))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
@@ -326,7 +326,7 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
     @patch_category_acl({"can_reply_threads": True})
     @patch_category_acl({"can_reply_threads": True})
     def test_reply_to_event(self):
     def test_reply_to_event(self):
         """events can't be replied to"""
         """events can't be replied to"""
-        reply_to = testutils.reply_thread(self.thread, is_event=True)
+        reply_to = test.reply_thread(self.thread, is_event=True)
 
 
         response = self.client.get("%s?reply=%s" % (self.api_link, reply_to.pk))
         response = self.client.get("%s?reply=%s" % (self.api_link, reply_to.pk))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
@@ -335,7 +335,7 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
     @patch_category_acl({"can_reply_threads": True})
     @patch_category_acl({"can_reply_threads": True})
     def test_reply_to(self):
     def test_reply_to(self):
         """api includes replied to post details in response"""
         """api includes replied to post details in response"""
-        reply_to = testutils.reply_thread(self.thread)
+        reply_to = test.reply_thread(self.thread)
 
 
         response = self.client.get("%s?reply=%s" % (self.api_link, reply_to.pk))
         response = self.client.get("%s?reply=%s" % (self.api_link, reply_to.pk))
 
 
@@ -354,8 +354,8 @@ class EditReplyEditorApiTests(EditorApiTestCase):
     def setUp(self):
     def setUp(self):
         super().setUp()
         super().setUp()
 
 
-        self.thread = testutils.post_thread(category=self.category)
-        self.post = testutils.reply_thread(self.thread, poster=self.user)
+        self.thread = test.post_thread(category=self.category)
+        self.post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.api_link = reverse(
         self.api_link = reverse(
             "misago:api:thread-post-editor",
             "misago:api:thread-post-editor",

+ 57 - 57
misago/threads/tests/test_threads_merge_api.py

@@ -7,7 +7,7 @@ from misago.acl.objectacl import add_acl_to_obj
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.models import Poll, PollVote, Post, Thread
 from misago.threads.models import Poll, PollVote, Post, Thread
 from misago.threads.serializers import ThreadsListSerializer
 from misago.threads.serializers import ThreadsListSerializer
 from misago.threads.serializers.moderation import THREADS_LIMIT
 from misago.threads.serializers.moderation import THREADS_LIMIT
@@ -98,7 +98,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
 
 
     def test_merge_with_invisible_thread(self):
     def test_merge_with_invisible_thread(self):
         """api validates if we are trying to merge with inaccesible thread"""
         """api validates if we are trying to merge with inaccesible thread"""
-        unaccesible_thread = testutils.post_thread(category=self.other_category)
+        unaccesible_thread = test.post_thread(category=self.other_category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -113,7 +113,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
 
 
     def test_merge_no_permission(self):
     def test_merge_no_permission(self):
         """api validates permission to merge threads"""
         """api validates permission to merge threads"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -147,7 +147,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": False})
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": False})
     def test_thread_category_is_closed(self):
     def test_thread_category_is_closed(self):
         """api validates if thread's category is open"""
         """api validates if thread's category is open"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         self.category.is_closed = True
         self.category.is_closed = True
         self.category.save()
         self.category.save()
@@ -188,7 +188,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": False})
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": False})
     def test_thread_is_closed(self):
     def test_thread_is_closed(self):
         """api validates if thread is open"""
         """api validates if thread is open"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
         other_thread.is_closed = True
         other_thread.is_closed = True
         other_thread.save()
         other_thread.save()
@@ -223,7 +223,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
         """api rejects too many threads to merge"""
         """api rejects too many threads to merge"""
         threads = []
         threads = []
         for _ in range(THREADS_LIMIT + 1):
         for _ in range(THREADS_LIMIT + 1):
-            threads.append(testutils.post_thread(category=self.category).pk)
+            threads.append(test.post_thread(category=self.category).pk)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -242,7 +242,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_no_final_thread(self):
     def test_merge_no_final_thread(self):
         """api rejects merge because no data to merge threads was specified"""
         """api rejects merge because no data to merge threads was specified"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -261,7 +261,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_invalid_final_title(self):
     def test_merge_invalid_final_title(self):
         """api rejects merge because final thread title was invalid"""
         """api rejects merge because final thread title was invalid"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -287,7 +287,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_invalid_category(self):
     def test_merge_invalid_category(self):
         """api rejects merge because final category was invalid"""
         """api rejects merge because final category was invalid"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -308,7 +308,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_start_threads": False})
     @patch_category_acl({"can_merge_threads": True, "can_start_threads": False})
     def test_merge_unallowed_start_thread(self):
     def test_merge_unallowed_start_thread(self):
         """api rejects merge because category isn't allowing starting threads"""
         """api rejects merge because category isn't allowing starting threads"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -330,7 +330,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_invalid_weight(self):
     def test_merge_invalid_weight(self):
         """api rejects merge because final weight was invalid"""
         """api rejects merge because final weight was invalid"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -353,7 +353,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_unallowed_global_weight(self):
     def test_merge_unallowed_global_weight(self):
         """api rejects merge because global weight was unallowed"""
         """api rejects merge because global weight was unallowed"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -380,7 +380,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_unallowed_local_weight(self):
     def test_merge_unallowed_local_weight(self):
         """api rejects merge because local weight was unallowed"""
         """api rejects merge because local weight was unallowed"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -403,7 +403,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_pin_threads": 1})
     @patch_category_acl({"can_merge_threads": True, "can_pin_threads": 1})
     def test_merge_allowed_local_weight(self):
     def test_merge_allowed_local_weight(self):
         """api allows local weight"""
         """api allows local weight"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -430,7 +430,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_pin_threads": 2})
     @patch_category_acl({"can_merge_threads": True, "can_pin_threads": 2})
     def test_merge_allowed_global_weight(self):
     def test_merge_allowed_global_weight(self):
         """api allows global weight"""
         """api allows global weight"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -457,7 +457,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": False})
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": False})
     def test_merge_unallowed_close(self):
     def test_merge_unallowed_close(self):
         """api rejects merge because closing thread was unallowed"""
         """api rejects merge because closing thread was unallowed"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -484,7 +484,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": True})
     @patch_category_acl({"can_merge_threads": True, "can_close_threads": True})
     def test_merge_with_close(self):
     def test_merge_with_close(self):
         """api allows for closing thread"""
         """api allows for closing thread"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -512,7 +512,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_hide_threads": 0})
     @patch_category_acl({"can_merge_threads": True, "can_hide_threads": 0})
     def test_merge_unallowed_hidden(self):
     def test_merge_unallowed_hidden(self):
         """api rejects merge because hidden thread was unallowed"""
         """api rejects merge because hidden thread was unallowed"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -539,7 +539,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True, "can_hide_threads": 1})
     @patch_category_acl({"can_merge_threads": True, "can_hide_threads": 1})
     def test_merge_with_hide(self):
     def test_merge_with_hide(self):
         """api allows for hiding thread"""
         """api allows for hiding thread"""
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -568,7 +568,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     def test_merge(self):
     def test_merge(self):
         """api performs basic merge"""
         """api performs basic merge"""
         posts_ids = [p.id for p in Post.objects.all()]
         posts_ids = [p.id for p in Post.objects.all()]
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -614,7 +614,7 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     def test_merge_kitchensink(self):
     def test_merge_kitchensink(self):
         """api performs merge"""
         """api performs merge"""
         posts_ids = [p.id for p in Post.objects.all()]
         posts_ids = [p.id for p in Post.objects.all()]
-        thread = testutils.post_thread(category=self.category)
+        thread = test.post_thread(category=self.category)
 
 
         poststracker.save_read(self.user, self.thread.first_post)
         poststracker.save_read(self.user, self.thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
         poststracker.save_read(self.user, thread.first_post)
@@ -690,9 +690,9 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_merged_best_answer(self):
     def test_merge_threads_merged_best_answer(self):
         """api merges two threads successfully, moving best answer to old thread"""
         """api merges two threads successfully, moving best answer to old thread"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
@@ -716,12 +716,12 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_merge_conflict_best_answer(self):
     def test_merge_threads_merge_conflict_best_answer(self):
         """api errors on merge conflict, returning list of available best answers"""
         """api errors on merge conflict, returning list of available best answers"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -761,12 +761,12 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_best_answer_invalid_resolution(self):
     def test_threads_merge_conflict_best_answer_invalid_resolution(self):
         """api errors on invalid merge conflict resolution"""
         """api errors on invalid merge conflict resolution"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -798,12 +798,12 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_unmark_all_best_answers(self):
     def test_threads_merge_conflict_unmark_all_best_answers(self):
         """api unmarks all best answers when unmark all choice is selected"""
         """api unmarks all best answers when unmark all choice is selected"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -829,12 +829,12 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_first_best_answer(self):
     def test_threads_merge_conflict_keep_first_best_answer(self):
         """api unmarks other best answer on merge"""
         """api unmarks other best answer on merge"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -859,12 +859,12 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_other_best_answer(self):
     def test_threads_merge_conflict_keep_other_best_answer(self):
         """api unmarks first best answer on merge"""
         """api unmarks first best answer on merge"""
-        best_answer = testutils.reply_thread(self.thread)
+        best_answer = test.reply_thread(self.thread)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.set_best_answer(self.user, best_answer)
         self.thread.save()
         self.thread.save()
 
 
-        other_thread = testutils.post_thread(self.category)
-        other_best_answer = testutils.reply_thread(other_thread)
+        other_thread = test.post_thread(self.category)
+        other_best_answer = test.reply_thread(other_thread)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.set_best_answer(self.user, other_best_answer)
         other_thread.save()
         other_thread.save()
 
 
@@ -889,8 +889,8 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_kept_poll(self):
     def test_merge_threads_kept_poll(self):
         """api merges two threads successfully, keeping poll from other thread"""
         """api merges two threads successfully, keeping poll from other thread"""
-        other_thread = testutils.post_thread(self.category)
-        poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.category)
+        poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -919,8 +919,8 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_merge_threads_moved_poll(self):
     def test_merge_threads_moved_poll(self):
         """api merges two threads successfully, moving poll from old thread"""
         """api merges two threads successfully, moving poll from old thread"""
-        other_thread = testutils.post_thread(self.category)
-        poll = testutils.post_poll(self.thread, self.user)
+        other_thread = test.post_thread(self.category)
+        poll = test.post_poll(self.thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -949,9 +949,9 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_poll(self):
     def test_threads_merge_conflict_poll(self):
         """api errors on merge conflict, returning list of available polls"""
         """api errors on merge conflict, returning list of available polls"""
-        other_thread = testutils.post_thread(self.category)
-        poll = testutils.post_poll(self.thread, self.user)
-        other_poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.category)
+        poll = test.post_poll(self.thread, self.user)
+        other_poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -987,10 +987,10 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_poll_invalid_resolution(self):
     def test_threads_merge_conflict_poll_invalid_resolution(self):
         """api errors on invalid merge conflict resolution"""
         """api errors on invalid merge conflict resolution"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
-        testutils.post_poll(self.thread, self.user)
-        testutils.post_poll(other_thread, self.user)
+        test.post_poll(self.thread, self.user)
+        test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -1015,10 +1015,10 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_delete_all_polls(self):
     def test_threads_merge_conflict_delete_all_polls(self):
         """api deletes all polls when delete all choice is selected"""
         """api deletes all polls when delete all choice is selected"""
-        other_thread = testutils.post_thread(self.category)
+        other_thread = test.post_thread(self.category)
 
 
-        testutils.post_poll(self.thread, self.user)
-        testutils.post_poll(other_thread, self.user)
+        test.post_poll(self.thread, self.user)
+        test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -1041,9 +1041,9 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_first_poll(self):
     def test_threads_merge_conflict_keep_first_poll(self):
         """api deletes other poll on merge"""
         """api deletes other poll on merge"""
-        other_thread = testutils.post_thread(self.category)
-        poll = testutils.post_poll(self.thread, self.user)
-        other_poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.category)
+        poll = test.post_poll(self.thread, self.user)
+        other_poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
@@ -1070,9 +1070,9 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
     @patch_category_acl({"can_merge_threads": True})
     @patch_category_acl({"can_merge_threads": True})
     def test_threads_merge_conflict_keep_other_poll(self):
     def test_threads_merge_conflict_keep_other_poll(self):
         """api deletes first poll on merge"""
         """api deletes first poll on merge"""
-        other_thread = testutils.post_thread(self.category)
-        poll = testutils.post_poll(self.thread, self.user)
-        other_poll = testutils.post_poll(other_thread, self.user)
+        other_thread = test.post_thread(self.category)
+        poll = test.post_poll(self.thread, self.user)
+        other_poll = test.post_poll(other_thread, self.user)
 
 
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,

+ 4 - 4
misago/threads/tests/test_threads_moderation.py

@@ -1,7 +1,7 @@
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import moderation, testutils
+from misago.threads import moderation, test
 from misago.threads.models import Thread
 from misago.threads.models import Thread
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):
@@ -16,7 +16,7 @@ class ThreadsModerationTests(AuthenticatedUserTestCase):
 
 
         self.request = MockRequest(self.user)
         self.request = MockRequest(self.user)
         self.category = Category.objects.all_categories()[:1][0]
         self.category = Category.objects.all_categories()[:1][0]
-        self.thread = testutils.post_thread(self.category)
+        self.thread = test.post_thread(self.category)
 
 
     def tearDown(self):
     def tearDown(self):
         super().tearDown()
         super().tearDown()
@@ -120,7 +120,7 @@ class ThreadsModerationTests(AuthenticatedUserTestCase):
 
 
     def test_approve_thread(self):
     def test_approve_thread(self):
         """approve_thread approves unapproved thread"""
         """approve_thread approves unapproved thread"""
-        self.thread = testutils.post_thread(self.category, is_unapproved=True)
+        self.thread = test.post_thread(self.category, is_unapproved=True)
 
 
         self.assertTrue(self.thread.is_unapproved)
         self.assertTrue(self.thread.is_unapproved)
         self.assertTrue(self.thread.first_post.is_unapproved)
         self.assertTrue(self.thread.first_post.is_unapproved)

+ 46 - 58
misago/threads/tests/test_threadslists.py

@@ -8,9 +8,9 @@ from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.readtracker import poststracker
 from misago.readtracker import poststracker
-from misago.threads import testutils
+from misago.threads import test
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 LISTS_URLS = ("", "my/", "new/", "unread/", "subscribed/")
 LISTS_URLS = ("", "my/", "new/", "unread/", "subscribed/")
 
 
@@ -243,7 +243,7 @@ class AllThreadsListTests(ThreadsListTestCase):
         )
         )
         test_category = Category.objects.get(slug="hidden-category")
         test_category = Category.objects.get(slug="hidden-category")
 
 
-        testutils.post_thread(category=self.category_b)
+        test.post_thread(category=self.category_b)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -289,11 +289,11 @@ class AllThreadsListTests(ThreadsListTestCase):
         threads list displays globally pinned threads first
         threads list displays globally pinned threads first
         and locally ones inbetween other
         and locally ones inbetween other
         """
         """
-        globally = testutils.post_thread(category=self.first_category, is_global=True)
+        globally = test.post_thread(category=self.first_category, is_global=True)
 
 
-        locally = testutils.post_thread(category=self.first_category, is_pinned=True)
+        locally = test.post_thread(category=self.first_category, is_pinned=True)
 
 
-        standard = testutils.post_thread(category=self.first_category)
+        standard = test.post_thread(category=self.first_category)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -346,7 +346,7 @@ class AllThreadsListTests(ThreadsListTestCase):
 
 
         threads = []
         threads = []
         for _ in range(settings.MISAGO_THREADS_PER_PAGE * 3):
         for _ in range(settings.MISAGO_THREADS_PER_PAGE * 3):
-            threads.append(testutils.post_thread(category=self.first_category))
+            threads.append(test.post_thread(category=self.first_category))
 
 
         # secondary page renders
         # secondary page renders
         response = self.client.get("/?page=2")
         response = self.client.get("/?page=2")
@@ -425,11 +425,11 @@ class CategoryThreadsListTests(ThreadsListTestCase):
         category threads list displays globally pinned threads first
         category threads list displays globally pinned threads first
         then locally ones and unpinned last
         then locally ones and unpinned last
         """
         """
-        globally = testutils.post_thread(category=self.first_category, is_global=True)
+        globally = test.post_thread(category=self.first_category, is_global=True)
 
 
-        locally = testutils.post_thread(category=self.first_category, is_pinned=True)
+        locally = test.post_thread(category=self.first_category, is_pinned=True)
 
 
-        standard = testutils.post_thread(category=self.first_category)
+        standard = test.post_thread(category=self.first_category)
 
 
         response = self.client.get(self.first_category.get_absolute_url())
         response = self.client.get(self.first_category.get_absolute_url())
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -481,7 +481,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_renders_test_thread(self):
     def test_list_renders_test_thread(self):
         """list renders test thread with valid top category"""
         """list renders test thread with valid top category"""
-        test_thread = testutils.post_thread(category=self.category_c)
+        test_thread = test.post_thread(category=self.category_c)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -539,7 +539,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
         )
         )
 
 
         test_category = Category.objects.get(slug="hidden-category")
         test_category = Category.objects.get(slug="hidden-category")
-        test_thread = testutils.post_thread(category=test_category)
+        test_thread = test.post_thread(category=test_category)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -554,7 +554,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
 
 
         test_category = Category.objects.get(slug="hidden-category")
         test_category = Category.objects.get(slug="hidden-category")
 
 
-        testutils.post_thread(category=test_category)
+        test.post_thread(category=test_category)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -565,7 +565,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_user_see_own_unapproved_thread(self):
     def test_list_user_see_own_unapproved_thread(self):
         """list renders unapproved thread that belongs to viewer"""
         """list renders unapproved thread that belongs to viewer"""
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a, poster=self.user, is_unapproved=True
             category=self.category_a, poster=self.user, is_unapproved=True
         )
         )
 
 
@@ -583,9 +583,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_user_cant_see_unapproved_thread(self):
     def test_list_user_cant_see_unapproved_thread(self):
         """list hides unapproved thread that belongs to other user"""
         """list hides unapproved thread that belongs to other user"""
-        test_thread = testutils.post_thread(
-            category=self.category_a, is_unapproved=True
-        )
+        test_thread = test.post_thread(category=self.category_a, is_unapproved=True)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -601,7 +599,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_user_cant_see_hidden_thread(self):
     def test_list_user_cant_see_hidden_thread(self):
         """list hides hidden thread that belongs to other user"""
         """list hides hidden thread that belongs to other user"""
-        test_thread = testutils.post_thread(category=self.category_a, is_hidden=True)
+        test_thread = test.post_thread(category=self.category_a, is_hidden=True)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -617,7 +615,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_user_cant_see_own_hidden_thread(self):
     def test_list_user_cant_see_own_hidden_thread(self):
         """list hides hidden thread that belongs to viewer"""
         """list hides hidden thread that belongs to viewer"""
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a, poster=self.user, is_hidden=True
             category=self.category_a, poster=self.user, is_hidden=True
         )
         )
 
 
@@ -635,7 +633,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl({"can_hide_threads": 1})
     @patch_categories_acl({"can_hide_threads": 1})
     def test_list_user_can_see_own_hidden_thread(self):
     def test_list_user_can_see_own_hidden_thread(self):
         """list shows hidden thread that belongs to viewer due to permission"""
         """list shows hidden thread that belongs to viewer due to permission"""
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a, poster=self.user, is_hidden=True
             category=self.category_a, poster=self.user, is_hidden=True
         )
         )
 
 
@@ -653,7 +651,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl({"can_hide_threads": 1})
     @patch_categories_acl({"can_hide_threads": 1})
     def test_list_user_can_see_hidden_thread(self):
     def test_list_user_can_see_hidden_thread(self):
         """list shows hidden thread that belongs to other user due to permission"""
         """list shows hidden thread that belongs to other user due to permission"""
-        test_thread = testutils.post_thread(category=self.category_a, is_hidden=True)
+        test_thread = test.post_thread(category=self.category_a, is_hidden=True)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -669,9 +667,7 @@ class ThreadsVisibilityTests(ThreadsListTestCase):
     @patch_categories_acl({"can_approve_content": 1})
     @patch_categories_acl({"can_approve_content": 1})
     def test_list_user_can_see_unapproved_thread(self):
     def test_list_user_can_see_unapproved_thread(self):
         """list shows hidden thread that belongs to other user due to permission"""
         """list shows hidden thread that belongs to other user due to permission"""
-        test_thread = testutils.post_thread(
-            category=self.category_a, is_unapproved=True
-        )
+        test_thread = test.post_thread(category=self.category_a, is_unapproved=True)
 
 
         response = self.client.get("/")
         response = self.client.get("/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -714,9 +710,9 @@ class MyThreadsListTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_renders_test_thread(self):
     def test_list_renders_test_thread(self):
         """list renders only threads posted by user"""
         """list renders only threads posted by user"""
-        test_thread = testutils.post_thread(category=self.category_a, poster=self.user)
+        test_thread = test.post_thread(category=self.category_a, poster=self.user)
 
 
-        other_thread = testutils.post_thread(category=self.category_a)
+        other_thread = test.post_thread(category=self.category_a)
 
 
         response = self.client.get("/my/")
         response = self.client.get("/my/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -775,7 +771,7 @@ class NewThreadsListTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_renders_new_thread(self):
     def test_list_renders_new_thread(self):
         """list renders new thread"""
         """list renders new thread"""
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
 
 
         response = self.client.get("/new/")
         response = self.client.get("/new/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -808,11 +804,11 @@ class NewThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a, started_on=self.user.joined_on - timedelta(days=2)
             category=self.category_a, started_on=self.user.joined_on - timedelta(days=2)
         )
         )
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             test_thread, posted_on=self.user.joined_on + timedelta(days=4)
             test_thread, posted_on=self.user.joined_on + timedelta(days=4)
         )
         )
 
 
@@ -847,7 +843,7 @@ class NewThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a,
             category=self.category_a,
             started_on=timezone.now()
             started_on=timezone.now()
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF + 1),
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF + 1),
@@ -882,7 +878,7 @@ class NewThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a,
             category=self.category_a,
             started_on=self.user.joined_on - timedelta(minutes=1),
             started_on=self.user.joined_on - timedelta(minutes=1),
         )
         )
@@ -916,7 +912,7 @@ class NewThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
         poststracker.save_read(self.user, test_thread.first_post)
         poststracker.save_read(self.user, test_thread.first_post)
 
 
         response = self.client.get("/new/")
         response = self.client.get("/new/")
@@ -976,9 +972,9 @@ class UnreadThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
         poststracker.save_read(self.user, test_thread.first_post)
         poststracker.save_read(self.user, test_thread.first_post)
-        testutils.reply_thread(test_thread)
+        test.reply_thread(test_thread)
 
 
         response = self.client.get("/unread/")
         response = self.client.get("/unread/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -1011,7 +1007,7 @@ class UnreadThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
 
 
         response = self.client.get("/unread/")
         response = self.client.get("/unread/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -1042,7 +1038,7 @@ class UnreadThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.joined_on = timezone.now() - timedelta(days=5)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
         poststracker.save_read(self.user, test_thread.first_post)
         poststracker.save_read(self.user, test_thread.first_post)
 
 
         response = self.client.get("/unread/")
         response = self.client.get("/unread/")
@@ -1074,14 +1070,14 @@ class UnreadThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a,
             category=self.category_a,
             started_on=timezone.now()
             started_on=timezone.now()
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF + 5),
             - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF + 5),
         )
         )
 
 
         poststracker.save_read(self.user, test_thread.first_post)
         poststracker.save_read(self.user, test_thread.first_post)
-        testutils.reply_thread(
+        test.reply_thread(
             test_thread, posted_on=test_thread.started_on + timedelta(days=1)
             test_thread, posted_on=test_thread.started_on + timedelta(days=1)
         )
         )
 
 
@@ -1114,13 +1110,13 @@ class UnreadThreadsListTests(ThreadsListTestCase):
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.joined_on = timezone.now() - timedelta(days=10)
         self.user.save()
         self.user.save()
 
 
-        test_thread = testutils.post_thread(
+        test_thread = test.post_thread(
             category=self.category_a, started_on=self.user.joined_on - timedelta(days=2)
             category=self.category_a, started_on=self.user.joined_on - timedelta(days=2)
         )
         )
 
 
         poststracker.save_read(self.user, test_thread.first_post)
         poststracker.save_read(self.user, test_thread.first_post)
 
 
-        testutils.reply_thread(
+        test.reply_thread(
             test_thread, posted_on=test_thread.started_on + timedelta(days=1)
             test_thread, posted_on=test_thread.started_on + timedelta(days=1)
         )
         )
 
 
@@ -1152,7 +1148,7 @@ class SubscribedThreadsListTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_shows_subscribed_thread(self):
     def test_list_shows_subscribed_thread(self):
         """list shows subscribed thread"""
         """list shows subscribed thread"""
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
         self.user.subscription_set.create(
         self.user.subscription_set.create(
             thread=test_thread,
             thread=test_thread,
             category=self.category_a,
             category=self.category_a,
@@ -1187,7 +1183,7 @@ class SubscribedThreadsListTests(ThreadsListTestCase):
     @patch_categories_acl()
     @patch_categories_acl()
     def test_list_hides_unsubscribed_thread(self):
     def test_list_hides_unsubscribed_thread(self):
         """list shows subscribed thread"""
         """list shows subscribed thread"""
-        test_thread = testutils.post_thread(category=self.category_a)
+        test_thread = test.post_thread(category=self.category_a)
 
 
         response = self.client.get("/subscribed/")
         response = self.client.get("/subscribed/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -1246,13 +1242,9 @@ class UnapprovedListTests(ThreadsListTestCase):
     )
     )
     def test_list_shows_all_threads_for_approving_user(self):
     def test_list_shows_all_threads_for_approving_user(self):
         """list shows all threads with unapproved posts when user has perm"""
         """list shows all threads with unapproved posts when user has perm"""
-        visible_thread = testutils.post_thread(
-            category=self.category_b, is_unapproved=True
-        )
+        visible_thread = test.post_thread(category=self.category_b, is_unapproved=True)
 
 
-        hidden_thread = testutils.post_thread(
-            category=self.category_b, is_unapproved=False
-        )
+        hidden_thread = test.post_thread(category=self.category_b, is_unapproved=False)
 
 
         response = self.client.get("/unapproved/")
         response = self.client.get("/unapproved/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -1273,13 +1265,11 @@ class UnapprovedListTests(ThreadsListTestCase):
     @patch_categories_acl(base_acl={"can_see_unapproved_content_lists": True})
     @patch_categories_acl(base_acl={"can_see_unapproved_content_lists": True})
     def test_list_shows_owned_threads_for_unapproving_user(self):
     def test_list_shows_owned_threads_for_unapproving_user(self):
         """list shows owned threads with unapproved posts for user without perm"""
         """list shows owned threads with unapproved posts for user without perm"""
-        visible_thread = testutils.post_thread(
+        visible_thread = test.post_thread(
             poster=self.user, category=self.category_b, is_unapproved=True
             poster=self.user, category=self.category_b, is_unapproved=True
         )
         )
 
 
-        hidden_thread = testutils.post_thread(
-            category=self.category_b, is_unapproved=True
-        )
+        hidden_thread = test.post_thread(category=self.category_b, is_unapproved=True)
 
 
         response = self.client.get("/unapproved/")
         response = self.client.get("/unapproved/")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -1316,13 +1306,11 @@ class OwnerOnlyThreadsVisibilityTests(AuthenticatedUserTestCase):
 
 
     def test_owned_threads_visibility(self):
     def test_owned_threads_visibility(self):
         """only user-posted threads are visible in category"""
         """only user-posted threads are visible in category"""
-        visible_thread = testutils.post_thread(
+        visible_thread = test.post_thread(
             poster=self.user, category=self.category, is_unapproved=True
             poster=self.user, category=self.category, is_unapproved=True
         )
         )
 
 
-        hidden_thread = testutils.post_thread(
-            category=self.category, is_unapproved=True
-        )
+        hidden_thread = test.post_thread(category=self.category, is_unapproved=True)
 
 
         with patch_category_see_all_threads_acl():
         with patch_category_see_all_threads_acl():
             response = self.client.get(self.category.get_absolute_url())
             response = self.client.get(self.category.get_absolute_url())
@@ -1334,11 +1322,11 @@ class OwnerOnlyThreadsVisibilityTests(AuthenticatedUserTestCase):
         """anons can't see any threads in limited visibility category"""
         """anons can't see any threads in limited visibility category"""
         self.logout_user()
         self.logout_user()
 
 
-        user_thread = testutils.post_thread(
+        user_thread = test.post_thread(
             poster=self.user, category=self.category, is_unapproved=True
             poster=self.user, category=self.category, is_unapproved=True
         )
         )
 
 
-        guest_thread = testutils.post_thread(category=self.category, is_unapproved=True)
+        guest_thread = test.post_thread(category=self.category, is_unapproved=True)
 
 
         with patch_category_see_all_threads_acl():
         with patch_category_see_all_threads_acl():
             response = self.client.get(self.category.get_absolute_url())
             response = self.client.get(self.category.get_absolute_url())

+ 22 - 22
misago/threads/tests/test_threadview.py

@@ -5,12 +5,12 @@ from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.conftest import get_cache_versions
 from misago.conftest import get_cache_versions
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.checksums import update_post_checksum
 from misago.threads.checksums import update_post_checksum
 from misago.threads.events import record_event
 from misago.threads.events import record_event
 from misago.threads.moderation import threads as threads_moderation
 from misago.threads.moderation import threads as threads_moderation
 from misago.threads.moderation import hide_post
 from misago.threads.moderation import hide_post
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
@@ -49,7 +49,7 @@ class ThreadViewTestCase(AuthenticatedUserTestCase):
         super().setUp()
         super().setUp()
 
 
         self.category = Category.objects.get(slug="first-category")
         self.category = Category.objects.get(slug="first-category")
-        self.thread = testutils.post_thread(category=self.category)
+        self.thread = test.post_thread(category=self.category)
 
 
 
 
 class ThreadVisibilityTests(ThreadViewTestCase):
 class ThreadVisibilityTests(ThreadViewTestCase):
@@ -128,14 +128,14 @@ class ThreadVisibilityTests(ThreadViewTestCase):
 class ThreadPostsVisibilityTests(ThreadViewTestCase):
 class ThreadPostsVisibilityTests(ThreadViewTestCase):
     def test_post_renders(self):
     def test_post_renders(self):
         """post renders"""
         """post renders"""
-        post = testutils.reply_thread(self.thread, poster=self.user)
+        post = test.reply_thread(self.thread, poster=self.user)
 
 
         response = self.client.get(self.thread.get_absolute_url())
         response = self.client.get(self.thread.get_absolute_url())
         self.assertContains(response, post.get_absolute_url())
         self.assertContains(response, post.get_absolute_url())
 
 
     def test_invalid_post_renders(self):
     def test_invalid_post_renders(self):
         """invalid post renders"""
         """invalid post renders"""
-        post = testutils.reply_thread(self.thread, poster=self.user)
+        post = test.reply_thread(self.thread, poster=self.user)
 
 
         post.parsed = "fiddled post content"
         post.parsed = "fiddled post content"
         post.save()
         post.save()
@@ -147,7 +147,7 @@ class ThreadPostsVisibilityTests(ThreadViewTestCase):
 
 
     def test_hidden_post_visibility(self):
     def test_hidden_post_visibility(self):
         """hidden post renders correctly"""
         """hidden post renders correctly"""
-        post = testutils.reply_thread(self.thread, message="Hello, I'm hidden post!")
+        post = test.reply_thread(self.thread, message="Hello, I'm hidden post!")
         hide_post(self.user, post)
         hide_post(self.user, post)
 
 
         response = self.client.get(self.thread.get_absolute_url())
         response = self.client.get(self.thread.get_absolute_url())
@@ -192,7 +192,7 @@ class ThreadPostsVisibilityTests(ThreadViewTestCase):
 
 
     def test_unapproved_post_visibility(self):
     def test_unapproved_post_visibility(self):
         """unapproved post renders for its author and users with perm to approve content"""
         """unapproved post renders for its author and users with perm to approve content"""
-        post = testutils.reply_thread(self.thread, is_unapproved=True)
+        post = test.reply_thread(self.thread, is_unapproved=True)
 
 
         # post is hdden because we aren't its author nor user with permission to approve
         # post is hdden because we aren't its author nor user with permission to approve
         response = self.client.get(self.thread.get_absolute_url())
         response = self.client.get(self.thread.get_absolute_url())
@@ -309,7 +309,7 @@ class ThreadEventVisibilityTests(ThreadViewTestCase):
 
 
         posts = []
         posts = []
         for _ in range(posts_limit - 1):
         for _ in range(posts_limit - 1):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
             posts.append(post)
             posts.append(post)
 
 
         # test that all events and posts within limits were rendered
         # test that all events and posts within limits were rendered
@@ -322,7 +322,7 @@ class ThreadEventVisibilityTests(ThreadViewTestCase):
 
 
         # add second page to thread with more events
         # add second page to thread with more events
         for _ in range(posts_limit):
         for _ in range(posts_limit):
-            post = testutils.reply_thread(self.thread)
+            post = test.reply_thread(self.thread)
         for _ in range(events_limit):
         for _ in range(events_limit):
             request = Mock(user=self.user, user_ip="127.0.0.1")
             request = Mock(user=self.user, user_ip="127.0.0.1")
             event = record_event(request, self.thread, "closed")
             event = record_event(request, self.thread, "closed")
@@ -378,7 +378,7 @@ class ThreadEventVisibilityTests(ThreadViewTestCase):
     def test_thread_merged_event_renders(self):
     def test_thread_merged_event_renders(self):
         """merged thread event renders"""
         """merged thread event renders"""
         request = Mock(user=self.user, user_ip="127.0.0.1")
         request = Mock(user=self.user, user_ip="127.0.0.1")
-        other_thread = testutils.post_thread(category=self.category)
+        other_thread = test.post_thread(category=self.category)
         threads_moderation.merge_thread(request, self.thread, other_thread)
         threads_moderation.merge_thread(request, self.thread, other_thread)
 
 
         event = self.thread.post_set.filter(is_event=True)[0]
         event = self.thread.post_set.filter(is_event=True)[0]
@@ -399,7 +399,7 @@ class ThreadAttachmentsViewTests(ThreadViewTestCase):
             "filetype": "ZIP",
             "filetype": "ZIP",
             "is_image": False,
             "is_image": False,
             "uploaded_on": "2016-10-22T21:17:40.408710Z",
             "uploaded_on": "2016-10-22T21:17:40.408710Z",
-            "uploader_name": "BobBoberson",
+            "uploader_name": "User",
         }
         }
 
 
         json.update(data)
         json.update(data)
@@ -415,7 +415,7 @@ class ThreadAttachmentsViewTests(ThreadViewTestCase):
                     "url": {
                     "url": {
                         "index": "/attachment/loremipsum-123/",
                         "index": "/attachment/loremipsum-123/",
                         "thumb": None,
                         "thumb": None,
-                        "uploader": "/user/bobboberson-123/",
+                        "uploader": "/user/user-123/",
                     },
                     },
                     "filename": "Archiwum-1.zip",
                     "filename": "Archiwum-1.zip",
                 }
                 }
@@ -425,7 +425,7 @@ class ThreadAttachmentsViewTests(ThreadViewTestCase):
                     "url": {
                     "url": {
                         "index": "/attachment/loremipsum-223/",
                         "index": "/attachment/loremipsum-223/",
                         "thumb": "/attachment/thumb/loremipsum-223/",
                         "thumb": "/attachment/thumb/loremipsum-223/",
-                        "uploader": "/user/bobboberson-223/",
+                        "uploader": "/user/user-223/",
                     },
                     },
                     "is_image": True,
                     "is_image": True,
                     "filename": "Archiwum-2.zip",
                     "filename": "Archiwum-2.zip",
@@ -436,7 +436,7 @@ class ThreadAttachmentsViewTests(ThreadViewTestCase):
                     "url": {
                     "url": {
                         "index": "/attachment/loremipsum-323/",
                         "index": "/attachment/loremipsum-323/",
                         "thumb": None,
                         "thumb": None,
-                        "uploader": "/user/bobboberson-323/",
+                        "uploader": "/user/user-323/",
                     },
                     },
                     "filename": "Archiwum-3.zip",
                     "filename": "Archiwum-3.zip",
                 }
                 }
@@ -460,7 +460,7 @@ class ThreadAttachmentsViewTests(ThreadViewTestCase):
 class ThreadPollViewTests(ThreadViewTestCase):
 class ThreadPollViewTests(ThreadViewTestCase):
     def test_poll_voted_display(self):
     def test_poll_voted_display(self):
         """view has no showstoppers when displaying voted poll"""
         """view has no showstoppers when displaying voted poll"""
-        poll = testutils.post_poll(self.thread, self.user)
+        poll = test.post_poll(self.thread, self.user)
 
 
         response = self.client.get(self.thread.get_absolute_url())
         response = self.client.get(self.thread.get_absolute_url())
         self.assertContains(response, poll.question)
         self.assertContains(response, poll.question)
@@ -469,7 +469,7 @@ class ThreadPollViewTests(ThreadViewTestCase):
 
 
     def test_poll_unvoted_display(self):
     def test_poll_unvoted_display(self):
         """view has no showstoppers when displaying poll vote form"""
         """view has no showstoppers when displaying poll vote form"""
-        poll = testutils.post_poll(self.thread, self.user)
+        poll = test.post_poll(self.thread, self.user)
         poll.pollvote_set.all().delete()
         poll.pollvote_set.all().delete()
 
 
         response = self.client.get(self.thread.get_absolute_url())
         response = self.client.get(self.thread.get_absolute_url())
@@ -478,7 +478,7 @@ class ThreadPollViewTests(ThreadViewTestCase):
 
 
     def test_poll_anonymous_view(self):
     def test_poll_anonymous_view(self):
         """view has no showstoppers when displaying poll to anon user"""
         """view has no showstoppers when displaying poll to anon user"""
-        poll = testutils.post_poll(self.thread, self.user)
+        poll = test.post_poll(self.thread, self.user)
 
 
         self.logout_user()
         self.logout_user()
 
 
@@ -491,7 +491,7 @@ class ThreadPollViewTests(ThreadViewTestCase):
 class ThreadLikedPostsViewTests(ThreadViewTestCase):
 class ThreadLikedPostsViewTests(ThreadViewTestCase):
     def test_liked_posts_display(self):
     def test_liked_posts_display(self):
         """view has no showstoppers on displaying posts with likes"""
         """view has no showstoppers on displaying posts with likes"""
-        testutils.like_post(self.thread.first_post, self.user)
+        test.like_post(self.thread.first_post, self.user)
 
 
         response = self.client.get(self.thread.get_absolute_url())
         response = self.client.get(self.thread.get_absolute_url())
         self.assertContains(response, '"is_liked": true')
         self.assertContains(response, '"is_liked": true')
@@ -500,7 +500,7 @@ class ThreadLikedPostsViewTests(ThreadViewTestCase):
         """
         """
         view has no showstoppers on displaying posts with likes without perm
         view has no showstoppers on displaying posts with likes without perm
         """
         """
-        testutils.like_post(self.thread.first_post, self.user)
+        test.like_post(self.thread.first_post, self.user)
 
 
         with patch_category_acl({"can_see_posts_likes": 0}):
         with patch_category_acl({"can_see_posts_likes": 0}):
             response = self.client.get(self.thread.get_absolute_url())
             response = self.client.get(self.thread.get_absolute_url())
@@ -514,14 +514,14 @@ class ThreadAnonViewTests(ThreadViewTestCase):
         """kitchensink thread view has no showstoppers for anons"""
         """kitchensink thread view has no showstoppers for anons"""
         request = Mock(user=self.user, user_ip="127.0.0.1")
         request = Mock(user=self.user, user_ip="127.0.0.1")
 
 
-        poll = testutils.post_poll(self.thread, self.user)
+        poll = test.post_poll(self.thread, self.user)
         event = record_event(request, self.thread, "closed")
         event = record_event(request, self.thread, "closed")
 
 
         hidden_event = record_event(request, self.thread, "opened")
         hidden_event = record_event(request, self.thread, "opened")
         hide_post(self.user, hidden_event)
         hide_post(self.user, hidden_event)
 
 
-        unapproved_post = testutils.reply_thread(self.thread, is_unapproved=True)
-        post = testutils.reply_thread(self.thread)
+        unapproved_post = test.reply_thread(self.thread, is_unapproved=True)
+        post = test.reply_thread(self.thread)
 
 
         self.logout_user()
         self.logout_user()
 
 

+ 3 - 3
misago/threads/tests/test_updatepostschecksums.py

@@ -4,7 +4,7 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.management.commands import updatepostschecksums
 from misago.threads.management.commands import updatepostschecksums
 from misago.threads.models import Post
 from misago.threads.models import Post
 
 
@@ -24,9 +24,9 @@ class UpdatePostsChecksumsTests(TestCase):
         """command updates posts checksums"""
         """command updates posts checksums"""
         category = Category.objects.all_categories()[:1][0]
         category = Category.objects.all_categories()[:1][0]
 
 
-        threads = [testutils.post_thread(category) for _ in range(5)]
+        threads = [test.post_thread(category) for _ in range(5)]
         for _, thread in enumerate(threads):
         for _, thread in enumerate(threads):
-            [testutils.reply_thread(thread) for _ in range(3)]
+            [test.reply_thread(thread) for _ in range(3)]
             thread.save()
             thread.save()
 
 
         Post.objects.update(parsed="Hello world!")
         Post.objects.update(parsed="Hello world!")

+ 12 - 12
misago/threads/tests/test_utils.py

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.utils import add_categories_to_items, get_thread_id_from_url
 from misago.threads.utils import add_categories_to_items, get_thread_id_from_url
 
 
 
 
@@ -68,56 +68,56 @@ class AddCategoriesToItemsTests(TestCase):
 
 
     def test_root_thread_from_root(self):
     def test_root_thread_from_root(self):
         """thread in root category is handled"""
         """thread in root category is handled"""
-        thread = testutils.post_thread(category=self.root)
+        thread = test.post_thread(category=self.root)
         add_categories_to_items(self.root, self.categories, [thread])
         add_categories_to_items(self.root, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.root)
         self.assertEqual(thread.category, self.root)
 
 
     def test_root_thread_from_elsewhere(self):
     def test_root_thread_from_elsewhere(self):
         """thread in root category is handled"""
         """thread in root category is handled"""
-        thread = testutils.post_thread(category=self.root)
+        thread = test.post_thread(category=self.root)
         add_categories_to_items(self.category_e, self.categories, [thread])
         add_categories_to_items(self.category_e, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.root)
         self.assertEqual(thread.category, self.root)
 
 
     def test_direct_child_thread_from_parent(self):
     def test_direct_child_thread_from_parent(self):
         """thread in direct child category is handled"""
         """thread in direct child category is handled"""
-        thread = testutils.post_thread(category=self.category_e)
+        thread = test.post_thread(category=self.category_e)
         add_categories_to_items(self.root, self.categories, [thread])
         add_categories_to_items(self.root, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.category_e)
         self.assertEqual(thread.category, self.category_e)
 
 
     def test_direct_child_thread_from_elsewhere(self):
     def test_direct_child_thread_from_elsewhere(self):
         """thread in direct child category is handled"""
         """thread in direct child category is handled"""
-        thread = testutils.post_thread(category=self.category_e)
+        thread = test.post_thread(category=self.category_e)
         add_categories_to_items(self.category_b, self.categories, [thread])
         add_categories_to_items(self.category_b, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.category_e)
         self.assertEqual(thread.category, self.category_e)
 
 
     def test_child_thread_from_root(self):
     def test_child_thread_from_root(self):
         """thread in child category is handled"""
         """thread in child category is handled"""
-        thread = testutils.post_thread(category=self.category_d)
+        thread = test.post_thread(category=self.category_d)
         add_categories_to_items(self.root, self.categories, [thread])
         add_categories_to_items(self.root, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.category_d)
         self.assertEqual(thread.category, self.category_d)
 
 
     def test_child_thread_from_parent(self):
     def test_child_thread_from_parent(self):
         """thread in child category is handled"""
         """thread in child category is handled"""
-        thread = testutils.post_thread(category=self.category_d)
+        thread = test.post_thread(category=self.category_d)
         add_categories_to_items(self.category_a, self.categories, [thread])
         add_categories_to_items(self.category_a, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.category_d)
         self.assertEqual(thread.category, self.category_d)
 
 
     def test_child_thread_from_category(self):
     def test_child_thread_from_category(self):
         """thread in child category is handled"""
         """thread in child category is handled"""
-        thread = testutils.post_thread(category=self.category_d)
+        thread = test.post_thread(category=self.category_d)
         add_categories_to_items(self.category_d, self.categories, [thread])
         add_categories_to_items(self.category_d, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.category_d)
         self.assertEqual(thread.category, self.category_d)
 
 
     def test_child_thread_from_elsewhere(self):
     def test_child_thread_from_elsewhere(self):
         """thread in child category is handled"""
         """thread in child category is handled"""
-        thread = testutils.post_thread(category=self.category_d)
+        thread = test.post_thread(category=self.category_d)
         add_categories_to_items(self.category_f, self.categories, [thread])
         add_categories_to_items(self.category_f, self.categories, [thread])
 
 
         self.assertEqual(thread.category, self.category_d)
         self.assertEqual(thread.category, self.category_d)
@@ -233,17 +233,17 @@ class GetThreadIdFromUrlTests(TestCase):
             {
             {
                 # old thread url
                 # old thread url
                 "request": MockRequest("http", "testforum.com"),
                 "request": MockRequest("http", "testforum.com"),
-                "url": "https://testforum.com/thread/bobboberson-123/",
+                "url": "https://testforum.com/thread/test-123/",
             },
             },
             {
             {
                 # dashed thread url
                 # dashed thread url
                 "request": MockRequest("http", "testforum.com"),
                 "request": MockRequest("http", "testforum.com"),
-                "url": "https://testforum.com/t/bobboberson-123/",
+                "url": "https://testforum.com/t/test-thread-123/",
             },
             },
             {
             {
                 # non-thread url
                 # non-thread url
                 "request": MockRequest("http", "testforum.com"),
                 "request": MockRequest("http", "testforum.com"),
-                "url": "https://testforum.com/user/bobboberson-123/",
+                "url": "https://testforum.com/user/user-123/",
             },
             },
             {
             {
                 # rubbish url
                 # rubbish url

+ 1 - 1
misago/threads/tests/test_validate_post.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class ValidatePostTests(AuthenticatedUserTestCase):
 class ValidatePostTests(AuthenticatedUserTestCase):

+ 0 - 217
misago/threads/testutils.py

@@ -1,217 +0,0 @@
-from datetime import timedelta
-
-from django.contrib.auth import get_user_model
-from django.utils import timezone
-
-from misago.core.utils import slugify
-
-from .checksums import update_post_checksum
-from .models import Poll, Post, Thread
-
-
-User = get_user_model()
-
-
-def post_thread(
-    category,
-    title="Test thread",
-    poster="Tester",
-    is_global=False,
-    is_pinned=False,
-    is_unapproved=False,
-    is_hidden=False,
-    is_closed=False,
-    started_on=None,
-):
-    started_on = started_on or timezone.now()
-
-    kwargs = {
-        "category": category,
-        "title": title,
-        "slug": slugify(title),
-        "started_on": started_on,
-        "last_post_on": started_on,
-        "is_unapproved": is_unapproved,
-        "is_hidden": is_hidden,
-        "is_closed": is_closed,
-    }
-
-    if is_global:
-        kwargs["weight"] = 2
-    elif is_pinned:
-        kwargs["weight"] = 1
-
-    try:
-        kwargs.update(
-            {
-                "starter": poster,
-                "starter_name": poster.username,
-                "starter_slug": poster.slug,
-                "last_poster": poster,
-                "last_poster_name": poster.username,
-                "last_poster_slug": poster.slug,
-            }
-        )
-    except AttributeError:
-        kwargs.update(
-            {
-                "starter_name": poster,
-                "starter_slug": slugify(poster),
-                "last_poster_name": poster,
-                "last_poster_slug": slugify(poster),
-            }
-        )
-
-    thread = Thread.objects.create(**kwargs)
-    reply_thread(
-        thread,
-        poster=poster,
-        posted_on=started_on,
-        is_hidden=is_hidden,
-        is_unapproved=is_unapproved,
-    )
-
-    return thread
-
-
-def reply_thread(
-    thread,
-    poster="Tester",
-    message="I am test message",
-    is_unapproved=False,
-    is_hidden=False,
-    is_event=False,
-    is_protected=False,
-    has_reports=False,
-    has_open_reports=False,
-    posted_on=None,
-):
-    posted_on = posted_on or thread.last_post_on + timedelta(minutes=5)
-
-    kwargs = {
-        "category": thread.category,
-        "thread": thread,
-        "original": message,
-        "parsed": message,
-        "checksum": "nope",
-        "posted_on": posted_on,
-        "updated_on": posted_on,
-        "is_event": is_event,
-        "is_unapproved": is_unapproved,
-        "is_hidden": is_hidden,
-        "is_protected": is_protected,
-        "has_reports": has_reports,
-        "has_open_reports": has_open_reports,
-    }
-
-    try:
-        kwargs.update({"poster": poster, "poster_name": poster.username})
-    except AttributeError:
-        kwargs.update({"poster_name": poster})
-
-    post = Post.objects.create(**kwargs)
-
-    update_post_checksum(post)
-    post.save()
-
-    thread.synchronize()
-    thread.save()
-    thread.category.synchronize()
-    thread.category.save()
-
-    return post
-
-
-def post_poll(thread, poster):
-    poll = Poll.objects.create(
-        category=thread.category,
-        thread=thread,
-        poster=poster,
-        poster_name=poster.username,
-        poster_slug=poster.slug,
-        question="Lorem ipsum dolor met?",
-        choices=[
-            {"hash": "aaaaaaaaaaaa", "label": "Alpha", "votes": 1},
-            {"hash": "bbbbbbbbbbbb", "label": "Beta", "votes": 0},
-            {"hash": "gggggggggggg", "label": "Gamma", "votes": 2},
-            {"hash": "dddddddddddd", "label": "Delta", "votes": 1},
-        ],
-        allowed_choices=2,
-        votes=4,
-    )
-
-    # one user voted for Alpha choice
-    try:
-        user = User.objects.get(slug="bob")
-    except User.DoesNotExist:
-        user = User.objects.create_user("bob", "bob@test.com", "Pass.123")
-
-    poll.pollvote_set.create(
-        category=thread.category,
-        thread=thread,
-        voter=user,
-        voter_name=user.username,
-        voter_slug=user.slug,
-        choice_hash="aaaaaaaaaaaa",
-    )
-
-    # test user voted on third and last choices
-    poll.pollvote_set.create(
-        category=thread.category,
-        thread=thread,
-        voter=poster,
-        voter_name=poster.username,
-        voter_slug=poster.slug,
-        choice_hash="gggggggggggg",
-    )
-    poll.pollvote_set.create(
-        category=thread.category,
-        thread=thread,
-        voter=poster,
-        voter_name=poster.username,
-        voter_slug=poster.slug,
-        choice_hash="dddddddddddd",
-    )
-
-    # somebody else voted on third option before being deleted
-    poll.pollvote_set.create(
-        category=thread.category,
-        thread=thread,
-        voter_name="deleted",
-        voter_slug="deleted",
-        choice_hash="gggggggggggg",
-    )
-
-    return poll
-
-
-def like_post(post, liker=None, username=None):
-    if not post.last_likes:
-        post.last_likes = []
-
-    if liker:
-        like = post.postlike_set.create(
-            category=post.category,
-            thread=post.thread,
-            liker=liker,
-            liker_name=liker.username,
-            liker_slug=liker.slug,
-        )
-
-        post.last_likes = [
-            {"id": liker.id, "username": liker.username}
-        ] + post.last_likes
-    else:
-        like = post.postlike_set.create(
-            category=post.category,
-            thread=post.thread,
-            liker_name=username,
-            liker_slug=slugify(username),
-        )
-
-        post.last_likes = [{"id": None, "username": username}] + post.last_likes
-
-    post.likes += 1
-    post.save()
-
-    return like

+ 2 - 2
misago/users/models/ban.py

@@ -110,9 +110,9 @@ class Ban(models.Model):
     def check_value(self, value):
     def check_value(self, value):
         if "*" in self.banned_value:
         if "*" in self.banned_value:
             regex = re.escape(self.banned_value).replace("\*", "(.*?)")
             regex = re.escape(self.banned_value).replace("\*", "(.*?)")
-            return re.search("^%s$" % regex, value) is not None
+            return re.search("^%s$" % regex, value, re.IGNORECASE) is not None
         else:
         else:
-            return self.banned_value == value
+            return self.banned_value.lower() == value.lower()
 
 
     def lift(self):
     def lift(self):
         self.expires_on = timezone.now()
         self.expires_on = timezone.now()

+ 0 - 0
misago/users/testutils.py → misago/users/test.py


+ 26 - 30
misago/users/tests/test_activation_views.py

@@ -4,7 +4,7 @@ from django.urls import reverse
 
 
 from misago.core.utils import encode_json_html
 from misago.core.utils import encode_json_html
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 from misago.users.tokens import make_activation_token
 from misago.users.tokens import make_activation_token
 
 
 User = get_user_model()
 User = get_user_model()
@@ -18,86 +18,82 @@ class ActivationViewsTests(TestCase):
 
 
     def test_view_activate_banned(self):
     def test_view_activate_banned(self):
         """activate banned user shows error"""
         """activate banned user shows error"""
-        test_user = create_test_user("Bob", "bob@test.com", requires_activation=1)
+        user = create_test_user("User", "user@example.com", requires_activation=1)
+        activation_token = make_activation_token(user)
+
         Ban.objects.create(
         Ban.objects.create(
-            check_type=Ban.USERNAME, banned_value="bob", user_message="Nope!"
+            check_type=Ban.USERNAME, banned_value="user", user_message="Nope!"
         )
         )
 
 
-        activation_token = make_activation_token(test_user)
-
         response = self.client.get(
         response = self.client.get(
             reverse(
             reverse(
                 "misago:activate-by-token",
                 "misago:activate-by-token",
-                kwargs={"pk": test_user.pk, "token": activation_token},
+                kwargs={"pk": user.pk, "token": activation_token},
             )
             )
         )
         )
         self.assertContains(response, encode_json_html("<p>Nope!</p>"), status_code=403)
         self.assertContains(response, encode_json_html("<p>Nope!</p>"), status_code=403)
 
 
-        test_user = User.objects.get(pk=test_user.pk)
-        self.assertEqual(test_user.requires_activation, 1)
+        user = User.objects.get(pk=user.pk)
+        self.assertEqual(user.requires_activation, 1)
 
 
     def test_view_activate_invalid_token(self):
     def test_view_activate_invalid_token(self):
         """activate with invalid token shows error"""
         """activate with invalid token shows error"""
-        test_user = create_test_user("Bob", "bob@test.com", requires_activation=1)
-
-        activation_token = make_activation_token(test_user)
+        user = create_test_user("User", "user@example.com", requires_activation=1)
+        activation_token = make_activation_token(user)
 
 
         response = self.client.get(
         response = self.client.get(
             reverse(
             reverse(
                 "misago:activate-by-token",
                 "misago:activate-by-token",
-                kwargs={"pk": test_user.pk, "token": activation_token + "acd"},
+                kwargs={"pk": user.pk, "token": activation_token + "acd"},
             )
             )
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
 
 
-        test_user = User.objects.get(pk=test_user.pk)
-        self.assertEqual(test_user.requires_activation, 1)
+        user = User.objects.get(pk=user.pk)
+        self.assertEqual(user.requires_activation, 1)
 
 
     def test_view_activate_disabled(self):
     def test_view_activate_disabled(self):
         """activate disabled user shows error"""
         """activate disabled user shows error"""
-        test_user = create_test_user("Bob", "bob@test.com", is_active=False)
-
-        activation_token = make_activation_token(test_user)
+        user = create_test_user("User", "user@example.com", is_active=False)
+        activation_token = make_activation_token(user)
 
 
         response = self.client.get(
         response = self.client.get(
             reverse(
             reverse(
                 "misago:activate-by-token",
                 "misago:activate-by-token",
-                kwargs={"pk": test_user.pk, "token": activation_token},
+                kwargs={"pk": user.pk, "token": activation_token},
             )
             )
         )
         )
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
     def test_view_activate_active(self):
     def test_view_activate_active(self):
         """activate active user shows error"""
         """activate active user shows error"""
-        test_user = create_test_user("Bob", "bob@test.com")
-
-        activation_token = make_activation_token(test_user)
+        user = create_test_user("User", "user@example.com")
+        activation_token = make_activation_token(user)
 
 
         response = self.client.get(
         response = self.client.get(
             reverse(
             reverse(
                 "misago:activate-by-token",
                 "misago:activate-by-token",
-                kwargs={"pk": test_user.pk, "token": activation_token},
+                kwargs={"pk": user.pk, "token": activation_token},
             )
             )
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        test_user = User.objects.get(pk=test_user.pk)
-        self.assertEqual(test_user.requires_activation, 0)
+        user = User.objects.get(pk=user.pk)
+        self.assertEqual(user.requires_activation, 0)
 
 
     def test_view_activate_inactive(self):
     def test_view_activate_inactive(self):
         """activate inactive user passess"""
         """activate inactive user passess"""
-        test_user = create_test_user("Bob", "bob@test.com", requires_activation=1)
-
-        activation_token = make_activation_token(test_user)
+        user = create_test_user("User", "user@example.com", requires_activation=1)
+        activation_token = make_activation_token(user)
 
 
         response = self.client.get(
         response = self.client.get(
             reverse(
             reverse(
                 "misago:activate-by-token",
                 "misago:activate-by-token",
-                kwargs={"pk": test_user.pk, "token": activation_token},
+                kwargs={"pk": user.pk, "token": activation_token},
             )
             )
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, "your account has been activated!")
         self.assertContains(response, "your account has been activated!")
 
 
-        test_user = User.objects.get(pk=test_user.pk)
-        self.assertEqual(test_user.requires_activation, 0)
+        user = User.objects.get(pk=user.pk)
+        self.assertEqual(user.requires_activation, 0)

+ 2 - 2
misago/users/tests/test_activepostersranking.py

@@ -3,12 +3,12 @@ from datetime import timedelta
 from django.utils import timezone
 from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads.testutils import post_thread
+from misago.threads.test import post_thread
 from misago.users.activepostersranking import (
 from misago.users.activepostersranking import (
     build_active_posters_ranking,
     build_active_posters_ranking,
     get_active_posters_ranking,
     get_active_posters_ranking,
 )
 )
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class TestActivePostersRanking(AuthenticatedUserTestCase):
 class TestActivePostersRanking(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_audittrail.py

@@ -6,7 +6,7 @@ from django.utils import timezone
 from misago.users.audittrail import create_audit_trail, create_user_audit_trail
 from misago.users.audittrail import create_audit_trail, create_user_audit_trail
 from misago.users.models import AuditTrail
 from misago.users.models import AuditTrail
 from misago.users.signals import remove_old_ips
 from misago.users.signals import remove_old_ips
-from misago.users.testutils import UserTestCase, create_test_user
+from misago.users.test import UserTestCase, create_test_user
 
 
 User = get_user_model()
 User = get_user_model()
 
 

+ 1 - 1
misago/users/tests/test_auth_api.py

@@ -3,7 +3,7 @@ from django.core import mail
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 from misago.users.tokens import make_password_change_token
 from misago.users.tokens import make_password_change_token
 
 
 
 

+ 1 - 1
misago/users/tests/test_auth_backend.py

@@ -2,7 +2,7 @@ from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.users.authbackends import MisagoBackend
 from misago.users.authbackends import MisagoBackend
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 backend = MisagoBackend()
 backend = MisagoBackend()
 
 

+ 1 - 1
misago/users/tests/test_auth_views.py

@@ -63,7 +63,7 @@ class AuthViewsTests(TestCase):
     def test_logout_view(self):
     def test_logout_view(self):
         """logout view logs user out on post"""
         """logout view logs user out on post"""
         response = self.client.post(
         response = self.client.post(
-            "/api/auth/", data={"username": "nope", "password": "nope"}
+            "/api/auth/", data={"username": "nope", "password": "not-checked"}
         )
         )
 
 
         self.assertContains(
         self.assertContains(

+ 1 - 1
misago/users/tests/test_avatars.py

@@ -17,7 +17,7 @@ from misago.users.avatars import (
     uploaded,
     uploaded,
 )
 )
 from misago.users.models import Avatar, AvatarGallery
 from misago.users.models import Avatar, AvatarGallery
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class AvatarsStoreTests(TestCase):
 class AvatarsStoreTests(TestCase):

+ 1 - 1
misago/users/tests/test_avatarserver_views.py

@@ -2,7 +2,7 @@ from django.test import TestCase
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.conf import settings
 from misago.conf import settings
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class AvatarServerTests(TestCase):
 class AvatarServerTests(TestCase):

+ 26 - 21
misago/users/tests/test_ban_model.py

@@ -7,23 +7,23 @@ class BansManagerTests(TestCase):
     def setUp(self):
     def setUp(self):
         Ban.objects.bulk_create(
         Ban.objects.bulk_create(
             [
             [
-                Ban(check_type=Ban.USERNAME, banned_value="bob"),
-                Ban(check_type=Ban.EMAIL, banned_value="bob@test.com"),
+                Ban(check_type=Ban.USERNAME, banned_value="user"),
+                Ban(check_type=Ban.EMAIL, banned_value="user@example.com"),
                 Ban(check_type=Ban.IP, banned_value="127.0.0.1"),
                 Ban(check_type=Ban.IP, banned_value="127.0.0.1"),
             ]
             ]
         )
         )
 
 
     def test_get_ban_for_banned_name(self):
     def test_get_ban_for_banned_name(self):
         """get_ban finds ban for given username"""
         """get_ban finds ban for given username"""
-        self.assertIsNotNone(Ban.objects.get_ban(username="Bob"))
+        self.assertIsNotNone(Ban.objects.get_ban(username="User"))
         with self.assertRaises(Ban.DoesNotExist):
         with self.assertRaises(Ban.DoesNotExist):
-            Ban.objects.get_ban(username="Jeb")
+            Ban.objects.get_ban(username="OtherUser")
 
 
     def test_get_ban_for_banned_email(self):
     def test_get_ban_for_banned_email(self):
         """get_ban finds ban for given email"""
         """get_ban finds ban for given email"""
-        self.assertIsNotNone(Ban.objects.get_ban(email="bob@test.com"))
+        self.assertIsNotNone(Ban.objects.get_ban(email="user@example.com"))
         with self.assertRaises(Ban.DoesNotExist):
         with self.assertRaises(Ban.DoesNotExist):
-            Ban.objects.get_ban(email="jeb@test.com")
+            Ban.objects.get_ban(email="otheruser@example.com")
 
 
     def test_get_ban_for_banned_ip(self):
     def test_get_ban_for_banned_ip(self):
         """get_ban finds ban for given ip"""
         """get_ban finds ban for given ip"""
@@ -31,12 +31,12 @@ class BansManagerTests(TestCase):
         with self.assertRaises(Ban.DoesNotExist):
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.get_ban(ip="42.0.0.1")
             Ban.objects.get_ban(ip="42.0.0.1")
 
 
-    def test_get_ban_for_all_bans(self):
+    def test_get_ban_for_all_values(self):
         """get_ban finds ban for given values"""
         """get_ban finds ban for given values"""
-        valid_kwargs = {"username": "bob", "ip": "42.51.52.51"}
+        valid_kwargs = {"username": "User", "ip": "42.51.52.51"}
         self.assertIsNotNone(Ban.objects.get_ban(**valid_kwargs))
         self.assertIsNotNone(Ban.objects.get_ban(**valid_kwargs))
 
 
-        invalid_kwargs = {"username": "bsob", "ip": "42.51.52.51"}
+        invalid_kwargs = {"username": "OtherUser", "ip": "42.51.52.51"}
         with self.assertRaises(Ban.DoesNotExist):
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.get_ban(**invalid_kwargs)
             Ban.objects.get_ban(**invalid_kwargs)
 
 
@@ -44,28 +44,33 @@ class BansManagerTests(TestCase):
 class BanTests(TestCase):
 class BanTests(TestCase):
     def test_check_value_literal(self):
     def test_check_value_literal(self):
         """ban correctly tests given values"""
         """ban correctly tests given values"""
-        test_ban = Ban(banned_value="bob")
+        test_ban = Ban(banned_value="user")
 
 
-        self.assertTrue(test_ban.check_value("bob"))
-        self.assertFalse(test_ban.check_value("bobby"))
+        self.assertTrue(test_ban.check_value("User"))
+        self.assertFalse(test_ban.check_value("OtherUser"))
+        self.assertFalse(test_ban.check_value("UserOther"))
 
 
     def test_check_value_starts_with(self):
     def test_check_value_starts_with(self):
         """ban correctly tests given values"""
         """ban correctly tests given values"""
-        test_ban = Ban(banned_value="bob*")
+        test_ban = Ban(banned_value="user*")
 
 
-        self.assertTrue(test_ban.check_value("bob"))
-        self.assertTrue(test_ban.check_value("bobby"))
+        self.assertTrue(test_ban.check_value("User"))
+        self.assertTrue(test_ban.check_value("UserOther"))
+        self.assertFalse(test_ban.check_value("NewUser"))
 
 
     def test_check_value_middle_match(self):
     def test_check_value_middle_match(self):
         """ban correctly tests given values"""
         """ban correctly tests given values"""
-        test_ban = Ban(banned_value="b*b")
+        test_ban = Ban(banned_value="u*r")
 
 
-        self.assertTrue(test_ban.check_value("bob"))
-        self.assertFalse(test_ban.check_value("bobby"))
+        self.assertTrue(test_ban.check_value("User"))
+        self.assertTrue(test_ban.check_value("UserOther"))
+        self.assertFalse(test_ban.check_value("NewUser"))
+        self.assertFalse(test_ban.check_value("UserNew"))
 
 
     def test_check_value_ends_witch(self):
     def test_check_value_ends_witch(self):
         """ban correctly tests given values"""
         """ban correctly tests given values"""
-        test_ban = Ban(banned_value="*bob")
+        test_ban = Ban(banned_value="*user")
 
 
-        self.assertTrue(test_ban.check_value("lebob"))
-        self.assertFalse(test_ban.check_value("bobby"))
+        self.assertTrue(test_ban.check_value("User"))
+        self.assertTrue(test_ban.check_value("OtherUser"))
+        self.assertFalse(test_ban.check_value("UserOther"))

+ 1 - 1
misago/users/tests/test_banadmin_views.py

@@ -2,7 +2,7 @@ from datetime import datetime, timedelta
 
 
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.users.models import Ban
 from misago.users.models import Ban
 
 
 
 

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

@@ -15,7 +15,7 @@ from misago.users.bans import (
 )
 )
 from misago.users.constants import BANS_CACHE
 from misago.users.constants import BANS_CACHE
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
@@ -44,12 +44,12 @@ class GetBanTests(TestCase):
         self.assertEqual(get_username_ban("admiral").pk, valid_ban.pk)
         self.assertEqual(get_username_ban("admiral").pk, valid_ban.pk)
 
 
         registration_ban = Ban.objects.create(
         registration_ban = Ban.objects.create(
-            banned_value="bob*",
+            banned_value="mod*",
             expires_on=timezone.now() + timedelta(days=7),
             expires_on=timezone.now() + timedelta(days=7),
             registration_only=True,
             registration_only=True,
         )
         )
-        self.assertIsNone(get_username_ban("boberson"))
-        self.assertEqual(get_username_ban("boberson", True).pk, registration_ban.pk)
+        self.assertIsNone(get_username_ban("moderator"))
+        self.assertEqual(get_username_ban("moderator", True).pk, registration_ban.pk)
 
 
     def test_get_email_ban(self):
     def test_get_email_ban(self):
         """get_email_ban returns valid ban"""
         """get_email_ban returns valid ban"""

+ 1 - 1
misago/users/tests/test_bio_profilefield.py

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 
 
 
 
 User = get_user_model()
 User = get_user_model()

+ 1 - 1
misago/users/tests/test_credentialchange.py

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.users import credentialchange
 from misago.users import credentialchange
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 2 - 2
misago/users/tests/test_datadownloads.py

@@ -4,7 +4,7 @@ from django.core.files import File
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.models import Attachment, AttachmentType
 from misago.threads.models import Attachment, AttachmentType
-from misago.threads.testutils import post_thread, post_poll
+from misago.threads.test import post_thread, post_poll
 from misago.users.audittrail import create_user_audit_trail
 from misago.users.audittrail import create_user_audit_trail
 from misago.users.datadownloads import (
 from misago.users.datadownloads import (
     expire_user_data_download,
     expire_user_data_download,
@@ -13,7 +13,7 @@ from misago.users.datadownloads import (
     user_has_data_download_request,
     user_has_data_download_request,
 )
 )
 from misago.users.models import DataDownload
 from misago.users.models import DataDownload
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")

+ 1 - 1
misago/users/tests/test_datadownloads_dataarchive.py

@@ -11,7 +11,7 @@ from misago.users.datadownloads.dataarchive import (
     DataArchive,
     DataArchive,
     trim_long_filename,
     trim_long_filename,
 )
 )
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 DATA_DOWNLOADS_WORKING_DIR = settings.MISAGO_USER_DATA_DOWNLOADS_WORKING_DIR
 DATA_DOWNLOADS_WORKING_DIR = settings.MISAGO_USER_DATA_DOWNLOADS_WORKING_DIR

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

@@ -3,10 +3,10 @@ import os
 from django.core.files import File
 from django.core.files import File
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.users.datadownloads import request_user_data_download
 from misago.users.datadownloads import request_user_data_download
 from misago.users.models import DataDownload
 from misago.users.models import DataDownload
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_FILE_PATH = os.path.join(TESTFILES_DIR, "avatar.png")
 TEST_FILE_PATH = os.path.join(TESTFILES_DIR, "avatar.png")

+ 1 - 1
misago/users/tests/test_decorators.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.core.utils import encode_json_html
 from misago.core.utils import encode_json_html
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import UserTestCase
+from misago.users.test import UserTestCase
 
 
 
 
 class DenyAuthenticatedTests(UserTestCase):
 class DenyAuthenticatedTests(UserTestCase):

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

@@ -7,7 +7,7 @@ from django.test import TestCase, override_settings
 from django.utils import timezone
 from django.utils import timezone
 
 
 from misago.users.management.commands import deleteinactiveusers
 from misago.users.management.commands import deleteinactiveusers
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 User = get_user_model()
 User = get_user_model()
 
 

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

@@ -5,7 +5,7 @@ from django.core.management import call_command
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 
 
 from misago.users.management.commands import deletemarkedusers
 from misago.users.management.commands import deletemarkedusers
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 User = get_user_model()
 User = get_user_model()
 
 

+ 1 - 1
misago/users/tests/test_deleteprofilefield.py

@@ -4,7 +4,7 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.users.management.commands import deleteprofilefield
 from misago.users.management.commands import deleteprofilefield
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class DeleteProfileFieldTests(TestCase):
 class DeleteProfileFieldTests(TestCase):

+ 1 - 1
misago/users/tests/test_djangoadmin_auth.py

@@ -1,7 +1,7 @@
 from django.test import override_settings
 from django.test import override_settings
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 
 
 
 
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")

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

@@ -3,9 +3,9 @@ from django.test import override_settings
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import formats
 from django.utils import formats
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.users.djangoadmin import UserAdminModel
 from misago.users.djangoadmin import UserAdminModel
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")

+ 1 - 1
misago/users/tests/test_expireuserdatadownloads.py

@@ -8,7 +8,7 @@ from django.core.management import call_command
 from misago.users.datadownloads import request_user_data_download
 from misago.users.datadownloads import request_user_data_download
 from misago.users.management.commands import expireuserdatadownloads
 from misago.users.management.commands import expireuserdatadownloads
 from misago.users.models import DataDownload
 from misago.users.models import DataDownload
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")

+ 1 - 1
misago/users/tests/test_forgottenpassword_views.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.core.utils import encode_json_html
 from misago.core.utils import encode_json_html
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import UserTestCase, create_test_user
+from misago.users.test import UserTestCase, create_test_user
 from misago.users.tokens import make_password_change_token
 from misago.users.tokens import make_password_change_token
 
 
 
 

+ 1 - 1
misago/users/tests/test_gender_profilefield.py

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 
 
 
 
 User = get_user_model()
 User = get_user_model()

+ 1 - 1
misago/users/tests/test_getting_user_status.py

@@ -1,7 +1,7 @@
 from unittest.mock import Mock
 from unittest.mock import Mock
 
 
 from misago.users.online.utils import get_user_status
 from misago.users.online.utils import get_user_status
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class GetUserStatusTests(AuthenticatedUserTestCase):
 class GetUserStatusTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_invalidatebans.py

@@ -10,7 +10,7 @@ from misago.cache.versions import get_cache_versions
 from misago.users import bans
 from misago.users import bans
 from misago.users.management.commands import invalidatebans
 from misago.users.management.commands import invalidatebans
 from misago.users.models import Ban, BanCache
 from misago.users.models import Ban, BanCache
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class InvalidateBansTests(TestCase):
 class InvalidateBansTests(TestCase):

+ 1 - 1
misago/users/tests/test_joinip_profilefield.py

@@ -2,7 +2,7 @@ from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 
 
 
 
 User = get_user_model()
 User = get_user_model()

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

@@ -2,10 +2,10 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads.testutils import post_thread
+from misago.threads.test import post_thread
 from misago.users.activepostersranking import build_active_posters_ranking
 from misago.users.activepostersranking import build_active_posters_ranking
 from misago.users.models import Rank
 from misago.users.models import Rank
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class UsersListTestCase(AuthenticatedUserTestCase):
 class UsersListTestCase(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_listusedprofilefields.py

@@ -4,7 +4,7 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.users.management.commands import listusedprofilefields
 from misago.users.management.commands import listusedprofilefields
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class ListUsedProfileFieldsTests(TestCase):
 class ListUsedProfileFieldsTests(TestCase):

+ 10 - 10
misago/users/tests/test_mention_api.py

@@ -2,7 +2,7 @@ from django.test import TestCase
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.conf import settings
 from misago.conf import settings
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 
 
 class AuthenticateApiTests(TestCase):
 class AuthenticateApiTests(TestCase):
@@ -25,33 +25,33 @@ class AuthenticateApiTests(TestCase):
 
 
     def test_user_search(self):
     def test_user_search(self):
         """api searches uses"""
         """api searches uses"""
-        create_test_user("BobBoberson", "bob@test.com")
+        create_test_user("User", "user@example.com")
 
 
         # exact case sensitive match
         # exact case sensitive match
-        response = self.client.get(self.api_link + "?q=BobBoberson")
+        response = self.client.get(self.api_link + "?q=User")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(
         self.assertEqual(
             response.json(),
             response.json(),
-            [{"avatar": "http://placekitten.com/100/100", "username": "BobBoberson"}],
+            [{"avatar": "http://placekitten.com/100/100", "username": "User"}],
         )
         )
 
 
-        # rought case insensitive match
-        response = self.client.get(self.api_link + "?q=bob")
+        # case insensitive match
+        response = self.client.get(self.api_link + "?q=user")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(
         self.assertEqual(
             response.json(),
             response.json(),
-            [{"avatar": "http://placekitten.com/100/100", "username": "BobBoberson"}],
+            [{"avatar": "http://placekitten.com/100/100", "username": "User"}],
         )
         )
 
 
         # eager case insensitive match
         # eager case insensitive match
-        response = self.client.get(self.api_link + "?q=b")
+        response = self.client.get(self.api_link + "?q=u")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(
         self.assertEqual(
             response.json(),
             response.json(),
-            [{"avatar": "http://placekitten.com/100/100", "username": "BobBoberson"}],
+            [{"avatar": "http://placekitten.com/100/100", "username": "User"}],
         )
         )
 
 
         # invalid match
         # invalid match
-        response = self.client.get(self.api_link + "?q=bu")
+        response = self.client.get(self.api_link + "?q=other")
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.json(), [])
         self.assertEqual(response.json(), [])

+ 1 - 1
misago/users/tests/test_options_views.py

@@ -1,7 +1,7 @@
 from django.core import mail
 from django.core import mail
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class OptionsViewsTests(AuthenticatedUserTestCase):
 class OptionsViewsTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_prepareuserdatadownloads.py

@@ -7,7 +7,7 @@ from misago.conf import settings
 from misago.users.datadownloads import request_user_data_download
 from misago.users.datadownloads import request_user_data_download
 from misago.users.management.commands import prepareuserdatadownloads
 from misago.users.management.commands import prepareuserdatadownloads
 from misago.users.models import DataDownload
 from misago.users.models import DataDownload
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class PrepareUserDataDownloadsTests(AuthenticatedUserTestCase):
 class PrepareUserDataDownloadsTests(AuthenticatedUserTestCase):

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

@@ -2,9 +2,9 @@ from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
-from misago.threads import testutils
+from misago.threads import test
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class UserProfileViewsTests(AuthenticatedUserTestCase):
 class UserProfileViewsTests(AuthenticatedUserTestCase):
@@ -53,14 +53,14 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, "You have posted no messages")
         self.assertContains(response, "You have posted no messages")
 
 
-        thread = testutils.post_thread(category=self.category, poster=self.user)
+        thread = test.post_thread(category=self.category, poster=self.user)
 
 
         response = self.client.get(link)
         response = self.client.get(link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, thread.get_absolute_url())
         self.assertContains(response, thread.get_absolute_url())
 
 
-        post = testutils.reply_thread(thread, poster=self.user)
-        other_post = testutils.reply_thread(thread, poster=self.user)
+        post = test.reply_thread(thread, poster=self.user)
+        other_post = test.reply_thread(thread, poster=self.user)
 
 
         response = self.client.get(link)
         response = self.client.get(link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -75,14 +75,14 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, "You have no started threads.")
         self.assertContains(response, "You have no started threads.")
 
 
-        thread = testutils.post_thread(category=self.category, poster=self.user)
+        thread = test.post_thread(category=self.category, poster=self.user)
 
 
         response = self.client.get(link)
         response = self.client.get(link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertContains(response, thread.get_absolute_url())
         self.assertContains(response, thread.get_absolute_url())
 
 
-        post = testutils.reply_thread(thread, poster=self.user)
-        other_post = testutils.reply_thread(thread, poster=self.user)
+        post = test.reply_thread(thread, poster=self.user)
+        other_post = test.reply_thread(thread, poster=self.user)
 
 
         response = self.client.get(link)
         response = self.client.get(link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -164,7 +164,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
 
 
     def test_user_ban_details(self):
     def test_user_ban_details(self):
         """user ban details page has no showstoppers"""
         """user ban details page has no showstoppers"""
-        test_user = create_test_user("Bob", "bob@bob.com", "pass.123")
+        test_user = create_test_user("User", "user@example.com")
         link_kwargs = {"slug": test_user.slug, "pk": test_user.pk}
         link_kwargs = {"slug": test_user.slug, "pk": test_user.pk}
 
 
         with patch_user_acl({"can_see_ban_details": 0}):
         with patch_user_acl({"can_see_ban_details": 0}):

+ 1 - 1
misago/users/tests/test_rankadmin_views.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.acl import ACL_CACHE
 from misago.acl import ACL_CACHE
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.cache.test import assert_invalidates_cache
 from misago.cache.test import assert_invalidates_cache
 from misago.users.models import Rank
 from misago.users.models import Rank
 
 

+ 1 - 1
misago/users/tests/test_rest_permissions.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import UserTestCase
+from misago.users.test import UserTestCase
 
 
 
 
 class UnbannedOnlyTests(UserTestCase):
 class UnbannedOnlyTests(UserTestCase):

+ 1 - 1
misago/users/tests/test_search.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class SearchApiTests(AuthenticatedUserTestCase):
 class SearchApiTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_social_pipeline.py

@@ -24,7 +24,7 @@ from misago.users.social.pipeline import (
     validate_ip_not_banned,
     validate_ip_not_banned,
     validate_user_not_banned,
     validate_user_not_banned,
 )
 )
-from misago.users.testutils import UserTestCase
+from misago.users.test import UserTestCase
 
 
 
 
 User = get_user_model()
 User = get_user_model()

+ 1 - 5
misago/users/tests/test_testutils.py

@@ -1,10 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.users.testutils import (
-    AuthenticatedUserTestCase,
-    SuperUserTestCase,
-    UserTestCase,
-)
+from misago.users.test import AuthenticatedUserTestCase, SuperUserTestCase, UserTestCase
 
 
 
 
 class UserTestCaseTests(UserTestCase):
 class UserTestCaseTests(UserTestCase):

+ 1 - 1
misago/users/tests/test_twitter_profilefield.py

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 
 
 
 
 User = get_user_model()
 User = get_user_model()

+ 1 - 1
misago/users/tests/test_user_avatar_api.py

@@ -9,7 +9,7 @@ from misago.conf import settings
 from misago.conf.test import override_dynamic_settings
 from misago.conf.test import override_dynamic_settings
 from misago.users.avatars import gallery, store
 from misago.users.avatars import gallery, store
 from misago.users.models import AvatarGallery
 from misago.users.models import AvatarGallery
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, "avatar.png")
 TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, "avatar.png")

+ 1 - 1
misago/users/tests/test_user_changeemail_api.py

@@ -1,7 +1,7 @@
 from django.core import mail
 from django.core import mail
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class UserChangeEmailTests(AuthenticatedUserTestCase):
 class UserChangeEmailTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_user_changepassword_api.py

@@ -1,7 +1,7 @@
 from django.core import mail
 from django.core import mail
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class UserChangePasswordTests(AuthenticatedUserTestCase):
 class UserChangePasswordTests(AuthenticatedUserTestCase):

+ 20 - 20
misago/users/tests/test_user_create_api.py

@@ -5,7 +5,7 @@ from django.urls import reverse
 from misago.conf.test import override_dynamic_settings
 from misago.conf.test import override_dynamic_settings
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
 from misago.users.models import Ban, Online
 from misago.users.models import Ban, Online
-from misago.users.testutils import UserTestCase
+from misago.users.test import UserTestCase
 
 
 User = get_user_model()
 User = get_user_model()
 
 
@@ -240,7 +240,7 @@ class UserCreateTests(UserTestCase):
         """api uses django's validate_password to validate registrations"""
         """api uses django's validate_password to validate registrations"""
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
-            data={"username": "Bob", "email": "loremipsum@dolor.met", "password": ""},
+            data={"username": "User", "email": "loremipsum@dolor.met", "password": ""},
         )
         )
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.json(), {"password": ["This field is required."]})
         self.assertEqual(response.json(), {"password": ["This field is required."]})
@@ -250,7 +250,7 @@ class UserCreateTests(UserTestCase):
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
-                "username": "Bob",
+                "username": "User",
                 "email": "l.o.r.e.m.i.p.s.u.m@gmail.com",
                 "email": "l.o.r.e.m.i.p.s.u.m@gmail.com",
                 "password": "123",
                 "password": "123",
             },
             },
@@ -415,7 +415,7 @@ class UserCreateTests(UserTestCase):
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
-                "username": "Bob",
+                "username": "User",
                 "email": "l.o.r.e.m.i.p.s.u.m@gmail.com",
                 "email": "l.o.r.e.m.i.p.s.u.m@gmail.com",
                 "password": "pas123",
                 "password": "pas123",
             },
             },
@@ -437,27 +437,27 @@ class UserCreateTests(UserTestCase):
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
-                "username": "Bob",
-                "email": "bob@bob.com",
+                "username": "User",
+                "email": "user@example.com",
                 "password": self.USER_PASSWORD,
                 "password": self.USER_PASSWORD,
             },
             },
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(
         self.assertEqual(
             response.json(),
             response.json(),
-            {"activation": "active", "username": "Bob", "email": "bob@bob.com"},
+            {"activation": "active", "username": "User", "email": "user@example.com"},
         )
         )
 
 
-        User.objects.get_by_username("Bob")
+        User.objects.get_by_username("User")
 
 
-        test_user = User.objects.get_by_email("bob@bob.com")
+        test_user = User.objects.get_by_email("user@example.com")
         self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
         self.assertEqual(Online.objects.filter(user=test_user).count(), 1)
 
 
         self.assertTrue(test_user.check_password(self.USER_PASSWORD))
         self.assertTrue(test_user.check_password(self.USER_PASSWORD))
 
 
         auth_json = self.client.get(reverse("misago:api:auth")).json()
         auth_json = self.client.get(reverse("misago:api:auth")).json()
         self.assertTrue(auth_json["is_authenticated"])
         self.assertTrue(auth_json["is_authenticated"])
-        self.assertEqual(auth_json["username"], "Bob")
+        self.assertEqual(auth_json["username"], "User")
 
 
         self.assertIn("Welcome", mail.outbox[0].subject)
         self.assertIn("Welcome", mail.outbox[0].subject)
 
 
@@ -469,22 +469,22 @@ class UserCreateTests(UserTestCase):
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
-                "username": "Bob",
-                "email": "bob@bob.com",
+                "username": "User",
+                "email": "user@example.com",
                 "password": self.USER_PASSWORD,
                 "password": self.USER_PASSWORD,
             },
             },
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(
         self.assertEqual(
             response.json(),
             response.json(),
-            {"activation": "user", "username": "Bob", "email": "bob@bob.com"},
+            {"activation": "user", "username": "User", "email": "user@example.com"},
         )
         )
 
 
         auth_json = self.client.get(reverse("misago:api:auth")).json()
         auth_json = self.client.get(reverse("misago:api:auth")).json()
         self.assertFalse(auth_json["is_authenticated"])
         self.assertFalse(auth_json["is_authenticated"])
 
 
-        User.objects.get_by_username("Bob")
-        User.objects.get_by_email("bob@bob.com")
+        User.objects.get_by_username("User")
+        User.objects.get_by_email("user@example.com")
 
 
         self.assertIn("Welcome", mail.outbox[0].subject)
         self.assertIn("Welcome", mail.outbox[0].subject)
 
 
@@ -494,22 +494,22 @@ class UserCreateTests(UserTestCase):
         response = self.client.post(
         response = self.client.post(
             self.api_link,
             self.api_link,
             data={
             data={
-                "username": "Bob",
-                "email": "bob@bob.com",
+                "username": "User",
+                "email": "user@example.com",
                 "password": self.USER_PASSWORD,
                 "password": self.USER_PASSWORD,
             },
             },
         )
         )
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(
         self.assertEqual(
             response.json(),
             response.json(),
-            {"activation": "admin", "username": "Bob", "email": "bob@bob.com"},
+            {"activation": "admin", "username": "User", "email": "user@example.com"},
         )
         )
 
 
         auth_json = self.client.get(reverse("misago:api:auth")).json()
         auth_json = self.client.get(reverse("misago:api:auth")).json()
         self.assertFalse(auth_json["is_authenticated"])
         self.assertFalse(auth_json["is_authenticated"])
 
 
-        User.objects.get_by_username("Bob")
-        User.objects.get_by_email("bob@bob.com")
+        User.objects.get_by_username("User")
+        User.objects.get_by_email("user@example.com")
 
 
         self.assertIn("Welcome", mail.outbox[0].subject)
         self.assertIn("Welcome", mail.outbox[0].subject)
 
 

+ 1 - 1
misago/users/tests/test_user_datadownloads_api.py

@@ -1,5 +1,5 @@
 from misago.users.datadownloads import request_user_data_download
 from misago.users.datadownloads import request_user_data_download
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class UserDataDownloadsApiTests(AuthenticatedUserTestCase):
 class UserDataDownloadsApiTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_user_details_api.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class UserDetailsApiTests(AuthenticatedUserTestCase):
 class UserDetailsApiTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_user_editdetails_api.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class UserEditDetailsApiTests(AuthenticatedUserTestCase):
 class UserEditDetailsApiTests(AuthenticatedUserTestCase):

+ 17 - 17
misago/users/tests/test_user_feeds_api.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from misago.threads import testutils
+from misago.threads import test
 from misago.threads.tests.test_threads_api import ThreadsApiTestCase
 from misago.threads.tests.test_threads_api import ThreadsApiTestCase
 
 
 
 
@@ -30,7 +30,7 @@ class UserThreadsApiTests(ThreadsApiTestCase):
 
 
     def test_user_post(self):
     def test_user_post(self):
         """user post doesn't show in feed because its not first post in thread"""
         """user post doesn't show in feed because its not first post in thread"""
-        testutils.reply_thread(self.thread, poster=self.user)
+        test.reply_thread(self.thread, poster=self.user)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -38,7 +38,7 @@ class UserThreadsApiTests(ThreadsApiTestCase):
 
 
     def test_user_event(self):
     def test_user_event(self):
         """events don't show in feeds at all"""
         """events don't show in feeds at all"""
-        testutils.reply_thread(self.thread, poster=self.user, is_event=True)
+        test.reply_thread(self.thread, poster=self.user, is_event=True)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -46,10 +46,10 @@ class UserThreadsApiTests(ThreadsApiTestCase):
 
 
     def test_user_thread(self):
     def test_user_thread(self):
         """user thread shows in feed"""
         """user thread shows in feed"""
-        thread = testutils.post_thread(category=self.category, poster=self.user)
+        thread = test.post_thread(category=self.category, poster=self.user)
 
 
         # this post will not show in feed
         # this post will not show in feed
-        testutils.reply_thread(thread, poster=self.user)
+        test.reply_thread(thread, poster=self.user)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -58,7 +58,7 @@ class UserThreadsApiTests(ThreadsApiTestCase):
 
 
     def test_user_thread_anonymous(self):
     def test_user_thread_anonymous(self):
         """user thread shows in feed requested by unauthenticated user"""
         """user thread shows in feed requested by unauthenticated user"""
-        thread = testutils.post_thread(category=self.category, poster=self.user)
+        thread = test.post_thread(category=self.category, poster=self.user)
 
 
         self.logout_user()
         self.logout_user()
 
 
@@ -94,7 +94,7 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_event(self):
     def test_user_event(self):
         """events don't show in feeds at all"""
         """events don't show in feeds at all"""
-        testutils.reply_thread(self.thread, poster=self.user, is_event=True)
+        test.reply_thread(self.thread, poster=self.user, is_event=True)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -102,7 +102,7 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_hidden_post(self):
     def test_user_hidden_post(self):
         """hidden posts don't show in feeds at all"""
         """hidden posts don't show in feeds at all"""
-        testutils.reply_thread(self.thread, poster=self.user, is_hidden=True)
+        test.reply_thread(self.thread, poster=self.user, is_hidden=True)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -110,7 +110,7 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_unapproved_post(self):
     def test_user_unapproved_post(self):
         """unapproved posts don't show in feeds at all"""
         """unapproved posts don't show in feeds at all"""
-        testutils.reply_thread(self.thread, poster=self.user, is_unapproved=True)
+        test.reply_thread(self.thread, poster=self.user, is_unapproved=True)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -118,8 +118,8 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_posts(self):
     def test_user_posts(self):
         """user posts show in feed"""
         """user posts show in feed"""
-        post = testutils.reply_thread(self.thread, poster=self.user)
-        other_post = testutils.reply_thread(self.thread, poster=self.user)
+        post = test.reply_thread(self.thread, poster=self.user)
+        other_post = test.reply_thread(self.thread, poster=self.user)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -129,8 +129,8 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_thread(self):
     def test_user_thread(self):
         """user thread shows in feed"""
         """user thread shows in feed"""
-        thread = testutils.post_thread(category=self.category, poster=self.user)
-        post = testutils.reply_thread(thread, poster=self.user)
+        thread = test.post_thread(category=self.category, poster=self.user)
+        post = test.reply_thread(thread, poster=self.user)
 
 
         response = self.client.get(self.api_link)
         response = self.client.get(self.api_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -140,8 +140,8 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_post_anonymous(self):
     def test_user_post_anonymous(self):
         """user post shows in feed requested by unauthenticated user"""
         """user post shows in feed requested by unauthenticated user"""
-        post = testutils.reply_thread(self.thread, poster=self.user)
-        other_post = testutils.reply_thread(self.thread, poster=self.user)
+        post = test.reply_thread(self.thread, poster=self.user)
+        other_post = test.reply_thread(self.thread, poster=self.user)
 
 
         self.logout_user()
         self.logout_user()
 
 
@@ -153,8 +153,8 @@ class UserPostsApiTests(ThreadsApiTestCase):
 
 
     def test_user_thread_anonymous(self):
     def test_user_thread_anonymous(self):
         """user thread shows in feed requested by unauthenticated user"""
         """user thread shows in feed requested by unauthenticated user"""
-        thread = testutils.post_thread(category=self.category, poster=self.user)
-        post = testutils.reply_thread(thread, poster=self.user)
+        thread = test.post_thread(category=self.category, poster=self.user)
+        post = test.reply_thread(thread, poster=self.user)
 
 
         self.logout_user()
         self.logout_user()
 
 

+ 1 - 1
misago/users/tests/test_user_middleware.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.users.bans import ban_ip, ban_user
 from misago.users.bans import ban_ip, ban_user
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class UserMiddlewareTest(AuthenticatedUserTestCase):
 class UserMiddlewareTest(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_user_requestdatadownload_api.py

@@ -1,7 +1,7 @@
 from django.test.utils import override_settings
 from django.test.utils import override_settings
 
 
 from misago.users.datadownloads import request_user_data_download
 from misago.users.datadownloads import request_user_data_download
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class UserRequestDataDownload(AuthenticatedUserTestCase):
 class UserRequestDataDownload(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_user_signature_api.py

@@ -1,5 +1,5 @@
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class UserSignatureTests(AuthenticatedUserTestCase):
 class UserSignatureTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/users/tests/test_user_username_api.py

@@ -2,7 +2,7 @@ import json
 
 
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.conf.test import override_dynamic_settings
 from misago.conf.test import override_dynamic_settings
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 
 
 class UserUsernameTests(AuthenticatedUserTestCase):
 class UserUsernameTests(AuthenticatedUserTestCase):

+ 82 - 82
misago/users/tests/test_useradmin_views.py

@@ -3,15 +3,15 @@ from django.core import mail
 from django.urls import reverse
 from django.urls import reverse
 
 
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.admin.testutils import AdminTestCase
+from misago.admin.test import AdminTestCase
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.legal.models import Agreement
 from misago.legal.models import Agreement
 from misago.legal.utils import save_user_agreement_acceptance
 from misago.legal.utils import save_user_agreement_acceptance
-from misago.threads.testutils import post_thread, reply_thread
+from misago.threads.test import post_thread, reply_thread
 
 
 from misago.users.datadownloads import request_user_data_download
 from misago.users.datadownloads import request_user_data_download
 from misago.users.models import Ban, DataDownload, Rank
 from misago.users.models import Ban, DataDownload, Rank
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 
 
 User = get_user_model()
 User = get_user_model()
 
 
@@ -96,7 +96,7 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i, "bob%s@test.com" % i, requires_activation=1
+                "User%s" % i, "user%s@example.com" % i, requires_activation=1
             )
             )
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
@@ -115,7 +115,7 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i, "bob%s@test.com" % i, requires_activation=1
+                "User%s" % i, "user%s@example.com" % i, requires_activation=1
             )
             )
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
@@ -144,8 +144,8 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i,
-                "bob%s@test.com" % i,
+                "User%s" % i,
+                "user%s@example.com" % i,
                 joined_from_ip="73.95.67.27",
                 joined_from_ip="73.95.67.27",
                 requires_activation=1,
                 requires_activation=1,
             )
             )
@@ -183,7 +183,7 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i, "bob%s@test.com" % i, requires_activation=1
+                "User%s" % i, "user%s@example.com" % i, requires_activation=1
             )
             )
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
@@ -202,7 +202,7 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i, "bob%s@test.com" % i, requires_activation=1
+                "User%s" % i, "user%s@example.com" % i, requires_activation=1
             )
             )
             request_user_data_download(test_user)
             request_user_data_download(test_user)
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
@@ -234,7 +234,7 @@ class UserAdminViewsTests(AdminTestCase):
         """its impossible to delete admin account"""
         """its impossible to delete admin account"""
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
-            test_user = create_test_user("Bob%s" % i, "bob%s@test.com" % i)
+            test_user = create_test_user("User%s" % i, "user%s@example.com" % i)
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
             test_user.is_staff = True
             test_user.is_staff = True
@@ -256,7 +256,7 @@ class UserAdminViewsTests(AdminTestCase):
         """its impossible to delete superadmin account"""
         """its impossible to delete superadmin account"""
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
-            test_user = create_test_user("Bob%s" % i, "bob%s@test.com" % i)
+            test_user = create_test_user("User%s" % i, "user%s@example.com" % i)
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
             test_user.is_superuser = True
             test_user.is_superuser = True
@@ -280,7 +280,7 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i, "bob%s@test.com" % i, requires_activation=0
+                "User%s" % i, "user%s@example.com" % i, requires_activation=0
             )
             )
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
@@ -314,7 +314,7 @@ class UserAdminViewsTests(AdminTestCase):
         """its impossible to delete admin account and content"""
         """its impossible to delete admin account and content"""
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
-            test_user = create_test_user("Bob%s" % i, "bob%s@test.com" % i)
+            test_user = create_test_user("User%s" % i, "user%s@example.com" % i)
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
             test_user.is_staff = True
             test_user.is_staff = True
@@ -336,7 +336,7 @@ class UserAdminViewsTests(AdminTestCase):
         """its impossible to delete superadmin account and content"""
         """its impossible to delete superadmin account and content"""
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
-            test_user = create_test_user("Bob%s" % i, "bob%s@test.com" % i)
+            test_user = create_test_user("User%s" % i, "user%s@example.com" % i)
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
             test_user.is_superuser = True
             test_user.is_superuser = True
@@ -359,7 +359,7 @@ class UserAdminViewsTests(AdminTestCase):
         user_pks = []
         user_pks = []
         for i in range(10):
         for i in range(10):
             test_user = create_test_user(
             test_user = create_test_user(
-                "Bob%s" % i, "bob%s@test.com" % i, requires_activation=1
+                "User%s" % i, "user%s@example.com" % i, requires_activation=1
             )
             )
             user_pks.append(test_user.pk)
             user_pks.append(test_user.pk)
 
 
@@ -383,18 +383,18 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             reverse("misago:admin:users:accounts:new"),
             reverse("misago:admin:users:accounts:new"),
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(default_rank.pk),
                 "rank": str(default_rank.pk),
                 "roles": str(authenticated_role.pk),
                 "roles": str(authenticated_role.pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "new_password": "pass123",
                 "new_password": "pass123",
                 "staff_level": "0",
                 "staff_level": "0",
             },
             },
         )
         )
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
-        User.objects.get_by_username("Bawww")
-        test_user = User.objects.get_by_email("reg@stered.com")
+        User.objects.get_by_username("NewUsername")
+        test_user = User.objects.get_by_email("edited@example.com")
 
 
         self.assertTrue(test_user.check_password("pass123"))
         self.assertTrue(test_user.check_password("pass123"))
 
 
@@ -409,24 +409,24 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             reverse("misago:admin:users:accounts:new"),
             reverse("misago:admin:users:accounts:new"),
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(default_rank.pk),
                 "rank": str(default_rank.pk),
                 "roles": str(authenticated_role.pk),
                 "roles": str(authenticated_role.pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "new_password": " pass123 ",
                 "new_password": " pass123 ",
                 "staff_level": "0",
                 "staff_level": "0",
             },
             },
         )
         )
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
-        User.objects.get_by_username("Bawww")
-        test_user = User.objects.get_by_email("reg@stered.com")
+        User.objects.get_by_username("NewUsername")
+        test_user = User.objects.get_by_email("edited@example.com")
 
 
         self.assertTrue(test_user.check_password(" pass123 "))
         self.assertTrue(test_user.check_password(" pass123 "))
 
 
     def test_edit_view(self):
     def test_edit_view(self):
         """edit user view changes account"""
         """edit user view changes account"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -437,10 +437,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "new_password": "newpass123",
                 "new_password": "newpass123",
                 "staff_level": "0",
                 "staff_level": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -457,11 +457,11 @@ class UserAdminViewsTests(AdminTestCase):
 
 
         updated_user = User.objects.get(pk=test_user.pk)
         updated_user = User.objects.get(pk=test_user.pk)
         self.assertTrue(updated_user.check_password("newpass123"))
         self.assertTrue(updated_user.check_password("newpass123"))
-        self.assertEqual(updated_user.username, "Bawww")
-        self.assertEqual(updated_user.slug, "bawww")
+        self.assertEqual(updated_user.username, "NewUsername")
+        self.assertEqual(updated_user.slug, "newusername")
 
 
-        User.objects.get_by_username("Bawww")
-        User.objects.get_by_email("reg@stered.com")
+        User.objects.get_by_username("NewUsername")
+        User.objects.get_by_email("edited@example.com")
 
 
     def test_edit_dont_change_username(self):
     def test_edit_dont_change_username(self):
         """
         """
@@ -469,7 +469,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
         This is regression test for issue #640
         This is regression test for issue #640
         """
         """
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -480,10 +480,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bob",
+                "username": "User",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
                 "is_signature_locked": "1",
                 "is_signature_locked": "1",
                 "is_hiding_presence": "0",
                 "is_hiding_presence": "0",
@@ -497,13 +497,13 @@ class UserAdminViewsTests(AdminTestCase):
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         updated_user = User.objects.get(pk=test_user.pk)
         updated_user = User.objects.get(pk=test_user.pk)
-        self.assertEqual(updated_user.username, "Bob")
-        self.assertEqual(updated_user.slug, "bob")
+        self.assertEqual(updated_user.username, "User")
+        self.assertEqual(updated_user.slug, "user")
         self.assertEqual(updated_user.namechanges.count(), 0)
         self.assertEqual(updated_user.namechanges.count(), 0)
 
 
     def test_edit_change_password_whitespaces(self):
     def test_edit_change_password_whitespaces(self):
         """edit user view changes account password to include whitespaces"""
         """edit user view changes account password to include whitespaces"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -514,10 +514,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "new_password": " newpass123 ",
                 "new_password": " newpass123 ",
                 "staff_level": "0",
                 "staff_level": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -534,15 +534,15 @@ class UserAdminViewsTests(AdminTestCase):
 
 
         updated_user = User.objects.get(pk=test_user.pk)
         updated_user = User.objects.get(pk=test_user.pk)
         self.assertTrue(updated_user.check_password(" newpass123 "))
         self.assertTrue(updated_user.check_password(" newpass123 "))
-        self.assertEqual(updated_user.username, "Bawww")
-        self.assertEqual(updated_user.slug, "bawww")
+        self.assertEqual(updated_user.username, "NewUsername")
+        self.assertEqual(updated_user.slug, "newusername")
 
 
-        User.objects.get_by_username("Bawww")
-        User.objects.get_by_email("reg@stered.com")
+        User.objects.get_by_username("NewUsername")
+        User.objects.get_by_email("edited@example.com")
 
 
     def test_edit_make_admin(self):
     def test_edit_make_admin(self):
         """edit user view allows super admin to make other user admin"""
         """edit user view allows super admin to make other user admin"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -554,10 +554,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -578,7 +578,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_edit_make_superadmin_admin(self):
     def test_edit_make_superadmin_admin(self):
         """edit user view allows super admin to make other user super admin"""
         """edit user view allows super admin to make other user super admin"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -590,10 +590,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "0",
                 "is_staff": "0",
                 "is_superuser": "1",
                 "is_superuser": "1",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -615,7 +615,7 @@ class UserAdminViewsTests(AdminTestCase):
     def test_edit_denote_superadmin(self):
     def test_edit_denote_superadmin(self):
         """edit user view allows super admin to denote other super admin"""
         """edit user view allows super admin to denote other super admin"""
         test_user = create_test_user(
         test_user = create_test_user(
-            "Bob", "bob@test.com", is_staff=True, is_superuser=True
+            "User", "user@example.com", is_staff=True, is_superuser=True
         )
         )
 
 
         test_link = reverse(
         test_link = reverse(
@@ -629,10 +629,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "0",
                 "is_staff": "0",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -656,7 +656,7 @@ class UserAdminViewsTests(AdminTestCase):
         self.user.is_superuser = False
         self.user.is_superuser = False
         self.user.save()
         self.user.save()
 
 
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -668,10 +668,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "1",
                 "is_superuser": "1",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -695,7 +695,7 @@ class UserAdminViewsTests(AdminTestCase):
         self.user.is_superuser = False
         self.user.is_superuser = False
         self.user.save()
         self.user.save()
 
 
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -707,10 +707,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "0",
                 "is_staff": "0",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -736,7 +736,7 @@ class UserAdminViewsTests(AdminTestCase):
         self.user.is_superuser = True
         self.user.is_superuser = True
         self.user.save()
         self.user.save()
 
 
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
 
 
         test_user.is_staff = True
         test_user.is_staff = True
         test_user.save()
         test_user.save()
@@ -752,10 +752,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -781,7 +781,7 @@ class UserAdminViewsTests(AdminTestCase):
         self.user.is_superuser = False
         self.user.is_superuser = False
         self.user.save()
         self.user.save()
 
 
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
 
 
         test_user.is_staff = True
         test_user.is_staff = True
         test_user.save()
         test_user.save()
@@ -797,10 +797,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -823,7 +823,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_edit_is_deleting_account_cant_reactivate(self):
     def test_edit_is_deleting_account_cant_reactivate(self):
         """users deleting own accounts can't be reactivated"""
         """users deleting own accounts can't be reactivated"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.mark_for_delete()
         test_user.mark_for_delete()
 
 
         test_link = reverse(
         test_link = reverse(
@@ -837,10 +837,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -862,7 +862,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_edit_unusable_password(self):
     def test_edit_unusable_password(self):
         """admin edit form handles unusable passwords and lets setting new password"""
         """admin edit form handles unusable passwords and lets setting new password"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         self.assertFalse(test_user.has_usable_password())
         self.assertFalse(test_user.has_usable_password())
 
 
         test_link = reverse(
         test_link = reverse(
@@ -875,10 +875,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "new_password": "pass123",
                 "new_password": "pass123",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "0",
                 "is_superuser": "0",
@@ -900,7 +900,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_edit_keep_unusable_password(self):
     def test_edit_keep_unusable_password(self):
         """admin edit form handles unusable passwords and lets admin leave them unchanged"""
         """admin edit form handles unusable passwords and lets admin leave them unchanged"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         self.assertFalse(test_user.has_usable_password())
         self.assertFalse(test_user.has_usable_password())
 
 
         test_link = reverse(
         test_link = reverse(
@@ -913,10 +913,10 @@ class UserAdminViewsTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             test_link,
             test_link,
             data={
             data={
-                "username": "Bawww",
+                "username": "NewUsername",
                 "rank": str(test_user.rank_id),
                 "rank": str(test_user.rank_id),
                 "roles": str(test_user.roles.all()[0].pk),
                 "roles": str(test_user.roles.all()[0].pk),
-                "email": "reg@stered.com",
+                "email": "edited@example.com",
                 "is_staff": "1",
                 "is_staff": "1",
                 "is_superuser": "0",
                 "is_superuser": "0",
                 "signature": "Hello world!",
                 "signature": "Hello world!",
@@ -937,7 +937,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_edit_agreements_list(self):
     def test_edit_agreements_list(self):
         """edit view displays list of user's agreements"""
         """edit view displays list of user's agreements"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:edit", kwargs={"pk": test_user.pk}
         )
         )
@@ -973,7 +973,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_threads_view_staff(self):
     def test_delete_threads_view_staff(self):
         """delete user threads view validates if user deletes staff"""
         """delete user threads view validates if user deletes staff"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.is_staff = True
         test_user.is_staff = True
         test_user.save()
         test_user.save()
 
 
@@ -989,7 +989,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_threads_view_superuser(self):
     def test_delete_threads_view_superuser(self):
         """delete user threads view validates if user deletes superuser"""
         """delete user threads view validates if user deletes superuser"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.is_superuser = True
         test_user.is_superuser = True
         test_user.save()
         test_user.save()
 
 
@@ -1005,7 +1005,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_threads_view(self):
     def test_delete_threads_view(self):
         """delete user threads view deletes threads"""
         """delete user threads view deletes threads"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:delete-threads", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:delete-threads", kwargs={"pk": test_user.pk}
         )
         )
@@ -1041,7 +1041,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_posts_view_staff(self):
     def test_delete_posts_view_staff(self):
         """delete user posts view validates if user deletes staff"""
         """delete user posts view validates if user deletes staff"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.is_staff = True
         test_user.is_staff = True
         test_user.save()
         test_user.save()
 
 
@@ -1057,7 +1057,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_posts_view_superuser(self):
     def test_delete_posts_view_superuser(self):
         """delete user posts view validates if user deletes superuser"""
         """delete user posts view validates if user deletes superuser"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.is_superuser = True
         test_user.is_superuser = True
         test_user.save()
         test_user.save()
 
 
@@ -1073,7 +1073,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_posts_view(self):
     def test_delete_posts_view(self):
         """delete user posts view deletes posts"""
         """delete user posts view deletes posts"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:delete-posts", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:delete-posts", kwargs={"pk": test_user.pk}
         )
         )
@@ -1110,7 +1110,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_account_view_staff(self):
     def test_delete_account_view_staff(self):
         """delete user account view validates if user deletes staff"""
         """delete user account view validates if user deletes staff"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.is_staff = True
         test_user.is_staff = True
         test_user.save()
         test_user.save()
 
 
@@ -1126,7 +1126,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_account_view_superuser(self):
     def test_delete_account_view_superuser(self):
         """delete user account view validates if user deletes superuser"""
         """delete user account view validates if user deletes superuser"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_user.is_superuser = True
         test_user.is_superuser = True
         test_user.save()
         test_user.save()
 
 
@@ -1142,7 +1142,7 @@ class UserAdminViewsTests(AdminTestCase):
 
 
     def test_delete_account_view(self):
     def test_delete_account_view(self):
         """delete user account view deletes user account"""
         """delete user account view deletes user account"""
-        test_user = create_test_user("Bob", "bob@test.com")
+        test_user = create_test_user("User", "user@example.com")
         test_link = reverse(
         test_link = reverse(
             "misago:admin:users:accounts:delete-account", kwargs={"pk": test_user.pk}
             "misago:admin:users:accounts:delete-account", kwargs={"pk": test_user.pk}
         )
         )

+ 1 - 1
misago/users/tests/test_usernamechanges_api.py

@@ -1,5 +1,5 @@
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
-from misago.users.testutils import AuthenticatedUserTestCase
+from misago.users.test import AuthenticatedUserTestCase
 
 
 
 
 class UsernameChangesApiTests(AuthenticatedUserTestCase):
 class UsernameChangesApiTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/users/tests/test_users_api.py

@@ -9,10 +9,10 @@ from django.utils.encoding import smart_str
 from misago.acl.test import patch_user_acl
 from misago.acl.test import patch_user_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
-from misago.threads.testutils import post_thread
+from misago.threads.test import post_thread
 from misago.users.activepostersranking import build_active_posters_ranking
 from misago.users.activepostersranking import build_active_posters_ranking
 from misago.users.models import Ban, Rank
 from misago.users.models import Ban, Rank
-from misago.users.testutils import AuthenticatedUserTestCase, create_test_user
+from misago.users.test import AuthenticatedUserTestCase, create_test_user
 
 
 User = get_user_model()
 User = get_user_model()
 
 

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

@@ -4,7 +4,7 @@ from django.core.exceptions import ValidationError
 from django.test import TestCase
 from django.test import TestCase
 
 
 from misago.users.models import Ban
 from misago.users.models import Ban
-from misago.users.testutils import create_test_user
+from misago.users.test import create_test_user
 from misago.users.validators import (
 from misago.users.validators import (
     validate_email,
     validate_email,
     validate_email_available,
     validate_email_available,