From da2c8a8f53f6b87deef966ac3897cb3167884093 Mon Sep 17 00:00:00 2001 From: vincent porte Date: Mon, 12 Aug 2024 11:26:15 +0200 Subject: [PATCH 1/3] fix(post): set post subject and topic subjec identical --- lacommunaute/forum_conversation/forms.py | 3 +-- lacommunaute/forum_conversation/tests/tests_forms.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lacommunaute/forum_conversation/forms.py b/lacommunaute/forum_conversation/forms.py index 029f6eddb..2a1ef1eaf 100644 --- a/lacommunaute/forum_conversation/forms.py +++ b/lacommunaute/forum_conversation/forms.py @@ -2,7 +2,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 @@ -43,7 +42,7 @@ class PostForm(CreateUpdatePostMixin, AbstractPostForm): def create_post(self): post = super().create_post() - post.subject = f"{machina_settings.TOPIC_ANSWER_SUBJECT_PREFIX} {self.topic.subject}" + post.subject = self.topic.subject if self.user.is_anonymous: post.username = self.cleaned_data["username"] diff --git a/lacommunaute/forum_conversation/tests/tests_forms.py b/lacommunaute/forum_conversation/tests/tests_forms.py index c97d0eaf9..2eee179c9 100644 --- a/lacommunaute/forum_conversation/tests/tests_forms.py +++ b/lacommunaute/forum_conversation/tests/tests_forms.py @@ -3,7 +3,6 @@ from django.forms import HiddenInput from django.test import TestCase from faker import Faker -from machina.conf import settings as machina_settings from lacommunaute.forum_conversation.factories import PostFactory, TopicFactory from lacommunaute.forum_conversation.forms import PostForm @@ -37,7 +36,7 @@ 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): From 134496bd30095d13d45a190e6c4f7f7a6278d3d6 Mon Sep 17 00:00:00 2001 From: vincent porte Date: Mon, 12 Aug 2024 14:49:25 +0200 Subject: [PATCH 2/3] fix(post): remove duplicated functional code of django-machina from the application code --- lacommunaute/forum_conversation/forms.py | 8 - .../forum_conversation/tests/tests_forms.py | 275 +++++++++++++++++- 2 files changed, 261 insertions(+), 22 deletions(-) diff --git a/lacommunaute/forum_conversation/forms.py b/lacommunaute/forum_conversation/forms.py index 2a1ef1eaf..c2a7eb117 100644 --- a/lacommunaute/forum_conversation/forms.py +++ b/lacommunaute/forum_conversation/forms.py @@ -44,9 +44,6 @@ def create_post(self): post = super().create_post() post.subject = self.topic.subject - if self.user.is_anonymous: - post.username = self.cleaned_data["username"] - return post @@ -67,9 +64,4 @@ def save(self): post = super().save() post.topic.tags.set(self.cleaned_data["tags"]) - if self.user.is_anonymous: - post.username = self.cleaned_data["username"] - - post.save() - return post diff --git a/lacommunaute/forum_conversation/tests/tests_forms.py b/lacommunaute/forum_conversation/tests/tests_forms.py index 2eee179c9..db211df4d 100644 --- a/lacommunaute/forum_conversation/tests/tests_forms.py +++ b/lacommunaute/forum_conversation/tests/tests_forms.py @@ -1,11 +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 lacommunaute.forum_conversation.factories import PostFactory, TopicFactory +from lacommunaute.forum.factories import ForumFactory +from lacommunaute.forum_conversation.factories import ( + AnonymousPostFactory, + AnonymousTopicFactory, + PostFactory, + TopicFactory, +) 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) @@ -39,16 +48,254 @@ def test_post_subject_comes_from_topic_subject(self): 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) + + +def get_create_topic_url(forum): + return ( + reverse("forum_conversation:topic_create", kwargs={"forum_pk": forum.pk, "forum_slug": forum.slug}) + + "?checked" + ) + + +def get_update_topic_url(topic): + return reverse( + "forum_conversation:topic_update", + kwargs={"forum_slug": topic.forum.slug, "forum_pk": topic.forum.pk, "pk": topic.pk, "slug": topic.slug}, + ) + + +def get_reply_topic_url(topic): + return reverse( + "forum_conversation_extension:post_create", + kwargs={"forum_slug": topic.forum.slug, "forum_pk": topic.forum.pk, "pk": topic.pk, "slug": topic.slug}, + ) + + +def get_post_update_url(post): + return reverse( + "forum_conversation:post_update", + kwargs={ + "forum_slug": post.topic.forum.slug, + "forum_pk": post.topic.forum.pk, + "topic_pk": post.topic.pk, + "topic_slug": post.topic.slug, + "pk": post.pk, + }, + ) + + +superuser_hidden_fields = { + "poll-TOTAL_FORMS": 2, + "poll-INITIAL_FORMS": 0, + "attachment-TOTAL_FORMS": 1, + "attachment-INITIAL_FORMS": 0, +} + + +class TestTopicForm: + def test_create_topic_as_anonymous(self, db, client, public_forum): + username = faker.email() + + response = client.post( + get_create_topic_url(public_forum), + 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.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, public_forum): + topic = AnonymousTopicFactory(forum=public_forum, with_post=True) + 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(get_update_topic_url(topic), 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.poster is None + assert topic.first_post.updates_count == 0 # surprisingly, this is not incremented + assert topic.first_post.updated_by is None # updated_by is a FK on User + + def test_update_anonymous_topic_as_superuser(self, db, client, public_forum): + topic = AnonymousTopicFactory(forum=public_forum, with_post=True) + username = topic.first_post.username + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = { + "subject": faker.word(), + "content": faker.sentences(2), + **superuser_hidden_fields, + } + response = client.post(get_update_topic_url(topic), 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.poster is None + assert topic.first_post.updates_count == 1 + assert topic.first_post.updated_by == superuser + + def test_create_topic_as_authenticated(self, db, client, public_forum): + user = UserFactory() + client.force_login(user) + + response = client.post( + get_create_topic_url(public_forum), data={"subject": "Test", "content": faker.sentences(2)} ) - form.update_post(post) - self.assertFalse(post.username) - self.assertEqual(post.updated_by, self.user) - self.assertEqual(post.updates_count, F("updates_count") + 1) + assert response.status_code == 302 + + topic = Topic.objects.get() + assert topic.poster == user + assert topic.first_post.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, public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + user = topic.poster + client.force_login(user) + + data = {"subject": faker.word(), "content": faker.sentences(2)} + response = client.post(get_update_topic_url(topic), 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.poster == user + assert topic.first_post.updates_count == 1 + assert topic.first_post.updated_by == user + + def test_update_authenticated_topic_as_superuser(self, db, client, public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + user = topic.poster + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = { + "subject": faker.word(), + "content": faker.sentences(2), + **superuser_hidden_fields, + } + response = client.post(get_update_topic_url(topic), 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.poster == user + assert topic.first_post.updates_count == 1 + assert topic.first_post.updated_by == superuser + + +class TestPostForm: + def test_reply_as_anonymous(self, db, client, public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + username = faker.email() + + response = client.post(get_reply_topic_url(topic), data={"content": faker.sentences(2), "username": username}) + assert response.status_code == 200 # htmx view + + topic.refresh_from_db() + 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, public_forum): + post = AnonymousPostFactory(topic=TopicFactory(forum=public_forum, with_post=True)) + username = post.username + session = client.session + session["anonymous_post"] = post.anonymous_key + + data = {"content": faker.sentences(2), "username": username} + response = client.post(get_post_update_url(post), 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, public_forum): + post = AnonymousPostFactory(topic=TopicFactory(forum=public_forum, with_post=True)) + username = post.username + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = {"content": faker.sentences(2), **superuser_hidden_fields} + response = client.post(get_post_update_url(post), 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, public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + user = UserFactory() + client.force_login(user) + + response = client.post(get_reply_topic_url(topic), data={"content": faker.sentences(2)}) + assert response.status_code == 200 + + topic.refresh_from_db() + assert topic.posts.count() == 2 + + 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, public_forum): + post = PostFactory(topic=TopicFactory(forum=public_forum, with_post=True)) + user = post.poster + client.force_login(user) + + data = {"content": faker.sentences(2)} + response = client.post(get_post_update_url(post), 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, public_forum): + post = PostFactory(topic=TopicFactory(forum=public_forum, with_post=True)) + user = post.poster + superuser = UserFactory(is_superuser=True) + client.force_login(superuser) + + data = {"content": faker.sentences(2), **superuser_hidden_fields} + response = client.post(get_post_update_url(post), 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 From ac133dd94f3035347eca06012de16b25fa67a08d Mon Sep 17 00:00:00 2001 From: vincent porte Date: Mon, 12 Aug 2024 15:30:03 +0200 Subject: [PATCH 3/3] fix(topic): refactor and test init method of TopicForm --- lacommunaute/forum_conversation/forms.py | 8 ++----- .../forum_conversation/tests/tests_forms.py | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lacommunaute/forum_conversation/forms.py b/lacommunaute/forum_conversation/forms.py index c2a7eb117..22c7c9cb1 100644 --- a/lacommunaute/forum_conversation/forms.py +++ b/lacommunaute/forum_conversation/forms.py @@ -1,4 +1,3 @@ -from django.core.exceptions import ObjectDoesNotExist 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 @@ -54,11 +53,8 @@ class TopicForm(CreateUpdatePostMixin, AbstractTopicForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - try: - if hasattr(self.instance, "topic"): - self.fields["tags"].initial = self.instance.topic.tags.all() - except ObjectDoesNotExist: - pass + if self.instance.pk: + self.fields["tags"].initial = self.instance.topic.tags.all() def save(self): post = super().save() diff --git a/lacommunaute/forum_conversation/tests/tests_forms.py b/lacommunaute/forum_conversation/tests/tests_forms.py index db211df4d..e70d0f1ed 100644 --- a/lacommunaute/forum_conversation/tests/tests_forms.py +++ b/lacommunaute/forum_conversation/tests/tests_forms.py @@ -15,6 +15,7 @@ from lacommunaute.forum_conversation.forms import PostForm from lacommunaute.forum_conversation.models import Topic from lacommunaute.users.factories import UserFactory +from taggit.models import Tag faker = Faker(settings.LANGUAGE_CODE) @@ -204,6 +205,26 @@ def test_update_authenticated_topic_as_superuser(self, db, client, public_forum) assert topic.first_post.updates_count == 1 assert topic.first_post.updated_by == superuser + def test_init_tags_when_creating_topic(self, db, client, public_forum): + response = client.get(get_create_topic_url(public_forum)) + assert response.status_code == 200 + assert response.context_data["post_form"].fields["tags"].initial is None + + def test_init_tags_when_updating_topic(self, db, client, public_forum): + topic = TopicFactory(forum=public_forum, with_post=True) + client.force_login(topic.poster) + response = client.get(get_update_topic_url(topic)) + assert response.status_code == 200 + assert set(response.context_data["post_form"].fields["tags"].initial) == set(Tag.objects.none()) + + def test_init_tags_when_updating_tagged_topic(self, db, client, public_forum): + topic = TopicFactory(forum=public_forum, with_post=True, with_tags=[faker.word() for _ in range(2)]) + client.force_login(topic.poster) + + response = client.get(get_update_topic_url(topic)) + assert response.status_code == 200 + assert set(response.context_data["post_form"].fields["tags"].initial) == set(Tag.objects.all()) + class TestPostForm: def test_reply_as_anonymous(self, db, client, public_forum):