diff --git a/lacommunaute/forum_conversation/forms.py b/lacommunaute/forum_conversation/forms.py index 728ce8d0..3b2991c4 100644 --- a/lacommunaute/forum_conversation/forms.py +++ b/lacommunaute/forum_conversation/forms.py @@ -1,7 +1,6 @@ from django.db.models import F from django.forms import CharField, CheckboxSelectMultiple, HiddenInput, ModelMultipleChoiceField from machina.apps.forum_conversation.forms import PostForm as AbstractPostForm, TopicForm as AbstractTopicForm -from machina.conf import settings as machina_settings from taggit.models import Tag from lacommunaute.forum_conversation.models import Post @@ -42,10 +41,8 @@ class PostForm(CreateUpdatePostMixin, AbstractPostForm): def create_post(self): post = super().create_post() - post.subject = f"{machina_settings.TOPIC_ANSWER_SUBJECT_PREFIX} {self.topic.subject}" - - if self.user.is_anonymous: - post.username = self.cleaned_data["username"] + post.subject = self.topic.subject + post.username = self.cleaned_data["username"] if self.user.is_anonymous else None return post @@ -66,7 +63,7 @@ def save(self): post.topic.tags.set(self.cleaned_data["tags"]) post.topic.tags.add(self.cleaned_data["new_tag"]) if self.cleaned_data.get("new_tag") else None - post.username = self.cleaned_data["username"] if self.user.is_anonymous else None + post.username = self.cleaned_data["username"] if self.user.is_anonymous else post.username post.save() return post diff --git a/lacommunaute/forum_conversation/tests/tests_forms.py b/lacommunaute/forum_conversation/tests/tests_forms.py index c97d0eaf..0539bb67 100644 --- a/lacommunaute/forum_conversation/tests/tests_forms.py +++ b/lacommunaute/forum_conversation/tests/tests_forms.py @@ -1,12 +1,20 @@ +import pytest # noqa from django.conf import settings -from django.db.models import F from django.forms import HiddenInput from django.test import TestCase +from django.urls import reverse from faker import Faker -from machina.conf import settings as machina_settings -from lacommunaute.forum_conversation.factories import PostFactory, TopicFactory +from lacommunaute.forum.factories import ForumFactory +from lacommunaute.forum_conversation.factories import ( + AnonymousTopicFactory, + TopicFactory, + AnonymousPostFactory, + PostFactory, +) from lacommunaute.forum_conversation.forms import PostForm +from lacommunaute.forum_conversation.models import Topic +from lacommunaute.users.factories import UserFactory faker = Faker(settings.LANGUAGE_CODE) @@ -37,19 +45,292 @@ def test_post_subject_comes_from_topic_subject(self): post = form.create_post() self.assertEqual( post.subject, - f"{machina_settings.TOPIC_ANSWER_SUBJECT_PREFIX} {self.topic.subject}", + self.topic.subject, ) - def test_reply_as_authenticated_user(self): - post = PostFactory(topic=self.topic, poster=self.user) - form = PostForm( - data=self.form_data, - user=self.user, - forum=self.forum, - topic=self.topic, - instance=post, + +@pytest.fixture(name="public_forum") +def fixture_public_forum(): + return ForumFactory(with_public_perms=True) + + +@pytest.fixture(name="create_topic_url") +def fixture_create_topic_url(public_forum): + return ( + reverse( + "forum_conversation:topic_create", kwargs={"forum_pk": public_forum.pk, "forum_slug": public_forum.slug} ) - form.update_post(post) - self.assertFalse(post.username) - self.assertEqual(post.updated_by, self.user) - self.assertEqual(post.updates_count, F("updates_count") + 1) + + "?checked" + ) + + +@pytest.fixture(name="anonymous_topic_and_update_url") +def fixture_anonymous_topic_and_update_url(public_forum): + topic = AnonymousTopicFactory(forum=public_forum, with_post=True) + update_url = reverse( + "forum_conversation:topic_update", + kwargs={"forum_slug": topic.forum.slug, "forum_pk": topic.forum.pk, "pk": topic.pk, "slug": topic.slug}, + ) + return topic, update_url + + +@pytest.fixture(name="authenticated_topic_and_update_url") +def fixture_authenticated_topic_and_update_url(public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + update_url = reverse( + "forum_conversation:topic_update", + kwargs={"forum_slug": topic.forum.slug, "forum_pk": topic.forum.pk, "pk": topic.pk, "slug": topic.slug}, + ) + return topic, update_url + + +@pytest.fixture(name="topic_and_reply_url") +def fixture_topic_and_reply_url(public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + reply_url = reverse( + "forum_conversation_extension:post_create", + kwargs={"forum_slug": topic.forum.slug, "forum_pk": topic.forum.pk, "pk": topic.pk, "slug": topic.slug}, + ) + return topic, reply_url + + +@pytest.fixture(name="anonymous_reply_and_update_url") +def fixture_anonymous_reply_and_update_url(public_forum): + post = AnonymousPostFactory(topic=TopicFactory(forum=public_forum, with_post=True)) + update_url = reverse( + "forum_conversation:post_update", + kwargs={ + "forum_pk": post.topic.forum.pk, + "forum_slug": post.topic.forum.slug, + "topic_pk": post.topic.pk, + "topic_slug": post.topic.slug, + "pk": post.pk, + }, + ) + return post, update_url + + +@pytest.fixture(name="authenticated_reply_and_update_url") +def fixture_authenticated_reply_and_update_url(public_forum): + post = PostFactory(topic=TopicFactory(forum=public_forum, with_post=True)) + update_url = reverse( + "forum_conversation:post_update", + kwargs={ + "forum_pk": post.topic.forum.pk, + "forum_slug": post.topic.forum.slug, + "topic_pk": post.topic.pk, + "topic_slug": post.topic.slug, + "pk": post.pk, + }, + ) + return post, update_url + + +class TestTopicForm: + def test_create_topic_as_anonymous(self, db, client, create_topic_url): + username = faker.email() + + response = client.post( + create_topic_url, data={"subject": "Test", "content": faker.sentences(2), "username": username} + ) + assert response.status_code == 302 + + topic = Topic.objects.get() + assert topic.first_post.username == username + assert topic.poster is None + assert topic.first_post.updates_count == 0 + assert topic.first_post.updated_by is None + + def test_update_anonymous_topic_as_self(self, db, client, anonymous_topic_and_update_url): + topic, update_url = anonymous_topic_and_update_url + username = topic.first_post.username + session = client.session + session["anonymous_topic"] = topic.first_post.anonymous_key + + data = {"subject": faker.word(), "content": faker.sentences(2), "username": username} + response = client.post(update_url, data=data) + assert response.status_code == 302 + + topic.refresh_from_db() + assert topic.first_post.username == username + assert topic.poster is None + assert topic.first_post.updates_count == 0 # surprisingly, this is not incremented + assert topic.first_post.updated_by is None + + def test_update_anonymous_topic_as_superuser(self, db, client, anonymous_topic_and_update_url): + topic, update_url = anonymous_topic_and_update_url + username = topic.first_post.username + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = { + "subject": faker.word(), + "content": faker.sentences(2), + "poll-TOTAL_FORMS": 2, + "poll-INITIAL_FORMS": 0, + "attachment-TOTAL_FORMS": 1, + "attachment-INITIAL_FORMS": 0, + } + response = client.post(update_url, data=data) + assert response.status_code == 302 + + topic.refresh_from_db() + assert topic.first_post.username == username + assert topic.poster is None + assert topic.first_post.updates_count == 2 # surprisingly, 2 updates are counted instead of 1 + assert topic.first_post.updated_by == superuser + + def test_create_topic_as_authenticated(self, db, client, create_topic_url): + user = UserFactory() + client.force_login(user) + + response = client.post(create_topic_url, data={"subject": "Test", "content": faker.sentences(2)}) + assert response.status_code == 302 + + topic = Topic.objects.get() + assert topic.poster == user + assert topic.first_post.username is None + assert topic.first_post.updates_count == 0 + assert topic.first_post.updated_by is None + + def test_update_authenticated_topic_as_self(self, db, client, authenticated_topic_and_update_url): + topic, update_url = authenticated_topic_and_update_url + user = topic.poster + client.force_login(user) + + data = {"subject": faker.word(), "content": faker.sentences(2)} + response = client.post(update_url, data=data) + assert response.status_code == 302 + + topic.refresh_from_db() + assert topic.first_post.username is None + assert topic.poster == user + assert topic.first_post.updates_count == 2 # surprisingly, 2 updates are counted instead of 1 + assert topic.first_post.updated_by == user + + def test_update_authenticated_topic_as_superuser(self, db, client, authenticated_topic_and_update_url): + topic, update_url = authenticated_topic_and_update_url + user = topic.poster + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = { + "subject": faker.word(), + "content": faker.sentences(2), + "poll-TOTAL_FORMS": 2, + "poll-INITIAL_FORMS": 0, + "attachment-TOTAL_FORMS": 1, + "attachment-INITIAL_FORMS": 0, + } + response = client.post(update_url, data=data) + assert response.status_code == 302 + + topic.refresh_from_db() + assert topic.first_post.username is None + assert topic.poster == user + assert topic.first_post.updates_count == 2 # surprisingly, 2 updates are counted instead of 1 + assert topic.first_post.updated_by == superuser + + +class TestPostForm: + def test_reply_as_anonymous(self, db, client, topic_and_reply_url): + topic, reply_url = topic_and_reply_url + username = faker.email() + + response = client.post(reply_url, data={"content": faker.sentences(2), "username": username}) + assert response.status_code == 200 # htmx view + + post = topic.posts.last() + assert post.username == username + assert post.poster is None + assert post.updates_count == 0 + assert post.updated_by is None + + def test_update_anonymous_reply_as_self(self, db, client, anonymous_reply_and_update_url): + post, update_url = anonymous_reply_and_update_url + username = post.username + session = client.session + session["anonymous_post"] = post.anonymous_key + + data = {"content": faker.sentences(2), "username": username} + response = client.post(update_url, data=data) + assert response.status_code == 302 + + post.refresh_from_db() + assert post.username == username + assert post.poster is None + assert post.updates_count == 0 # surprisingly, this is not incremented + assert post.updated_by is None + + def test_update_anonymous_reply_as_superuser(self, db, client, anonymous_reply_and_update_url): + post, update_url = anonymous_reply_and_update_url + username = post.username + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = { + "content": faker.sentences(2), + "poll-TOTAL_FORMS": 2, + "poll-INITIAL_FORMS": 0, + "attachment-TOTAL_FORMS": 1, + "attachment-INITIAL_FORMS": 0, + } + response = client.post(update_url, data=data) + assert response.status_code == 302 + + post.refresh_from_db() + assert post.username == username + assert post.poster is None + assert post.updates_count == 1 + assert post.updated_by == superuser + + def test_reply_as_authenticated(self, db, client, topic_and_reply_url): + topic, reply_url = topic_and_reply_url + user = UserFactory() + client.force_login(user) + + response = client.post(reply_url, data={"content": faker.sentences(2)}) + assert response.status_code == 200 + + post = topic.posts.last() + assert post.username is None + assert post.poster == user + assert post.updates_count == 0 + assert post.updated_by is None + + def test_update_authenticated_reply_as_self(self, db, client, authenticated_reply_and_update_url): + post, update_url = authenticated_reply_and_update_url + user = post.poster + client.force_login(user) + + data = {"content": faker.sentences(2)} + response = client.post(update_url, data=data) + assert response.status_code == 302 + + post.refresh_from_db() + assert post.username is None + assert post.poster == user + assert post.updates_count == 1 + assert post.updated_by == user + + def test_update_authenticated_reply_as_superuser(self, db, client, authenticated_reply_and_update_url): + post, update_url = authenticated_reply_and_update_url + user = post.poster + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = { + "content": faker.sentences(2), + "poll-TOTAL_FORMS": 2, + "poll-INITIAL_FORMS": 0, + "attachment-TOTAL_FORMS": 1, + "attachment-INITIAL_FORMS": 0, + } + response = client.post(update_url, data=data) + assert response.status_code == 302 + + post.refresh_from_db() + assert post.username is None + assert post.poster == user + assert post.updates_count == 1 + assert post.updated_by == superuser