Skip to content

Commit

Permalink
Ajoute des tests et refactorise RemoveSuggestion (#6188)
Browse files Browse the repository at this point in the history
* Ajoute des tests à RemoveSuggestion

* Refactorise RemoveSuggestion

* Retire un TODO obsolète

* Retire un print qui traîne

* Retire une variable inutile

* Retire un import inutile

* Corrige imports
  • Loading branch information
Arnaud-D authored Mar 7, 2022
1 parent f4f31f3 commit 203e069
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 29 deletions.
12 changes: 10 additions & 2 deletions zds/tutorialv2/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from zds.utils.models import SubCategory, Licence
from zds.tutorialv2.models import TYPE_CHOICES
from zds.utils.models import HelpWriting
from zds.tutorialv2.models.database import PublishableContent, ContentContributionRole
from zds.tutorialv2.models.database import PublishableContent, ContentContributionRole, ContentSuggestion
from django.utils.translation import gettext_lazy as _
from zds.member.models import Profile
from zds.tutorialv2.utils import slugify_raise_on_invalid, InvalidSlugError
Expand Down Expand Up @@ -1363,11 +1363,19 @@ def __init__(self, content, *args, **kwargs):

class RemoveSuggestionForm(forms.Form):

pk_suggestion = forms.CharField(
pk_suggestion = forms.IntegerField(
label=_("Suggestion"),
required=True,
error_messages={"does_not_exist": _("La suggestion sélectionnée n'existe pas.")},
)

def clean_pk_suggestion(self):
pk_suggestion = self.cleaned_data.get("pk_suggestion")
suggestion = ContentSuggestion.objects.filter(id=pk_suggestion).first()
if suggestion is None:
self.add_error("pk_suggestion", self.fields["pk_suggestion"].error_messages["does_not_exist"])
return pk_suggestion


class ToggleHelpForm(forms.Form):
help_wanted = forms.CharField()
Expand Down
121 changes: 121 additions & 0 deletions zds/tutorialv2/tests/tests_views/tests_removesuggestion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
from django.test import TestCase
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.utils.html import escape

from zds.member.tests.factories import ProfileFactory, StaffProfileFactory
from zds.tutorialv2.tests.factories import PublishableContentFactory
from zds.tutorialv2.forms import RemoveSuggestionForm
from zds.tutorialv2.models.database import ContentSuggestion
from zds.tutorialv2.tests import TutorialTestMixin, override_for_contents


@override_for_contents()
class RemoveSuggestionPermissionTests(TutorialTestMixin, TestCase):
"""Test permissions and associated behaviors, such as redirections and status codes."""

def setUp(self):
# Create users
self.author = ProfileFactory().user
self.staff = StaffProfileFactory().user
self.outsider = ProfileFactory().user

# Create contents and suggestion
self.content = PublishableContentFactory(author_list=[self.author])
self.suggested_content = PublishableContentFactory()
self.suggestion = ContentSuggestion(publication=self.content, suggestion=self.suggested_content)
self.suggestion.save()

# Get information to be reused in tests
self.form_url = reverse("content:remove-suggestion", kwargs={"pk": self.content.pk})
self.login_url = reverse("member-login") + "?next=" + self.form_url
self.content_url = reverse("content:view", kwargs={"pk": self.content.pk, "slug": self.content.slug})
self.form_data = {"pk_suggestion": self.suggestion.pk}

def test_not_authenticated(self):
self.client.logout()
self.content.type = "TUTORIAL"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
self.assertRedirects(response, self.login_url)

def test_authenticated_outsider(self):
self.client.force_login(self.outsider)
self.content.type = "TUTORIAL"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
self.assertEqual(response.status_code, 403)

def test_authenticated_author(self):
self.client.force_login(self.author)
self.content.type = "TUTORIAL"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
self.assertEqual(response.status_code, 403)

def test_authenticated_staff_tutorial(self):
self.client.force_login(self.staff)
self.content.type = "TUTORIAL"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
self.assertRedirects(response, self.content_url)

def test_authenticated_staff_article(self):
self.client.force_login(self.staff)
self.content.type = "ARTICLE"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
self.assertRedirects(response, self.content_url)

def test_authenticated_staff_opinion(self):
self.client.force_login(self.staff)
self.content.type = "OPINION"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
self.assertEqual(response.status_code, 403)


class RemoveSuggestionWorkflowTests(TutorialTestMixin, TestCase):
"""Test the workflow of the form, such as validity errors and success messages."""

def setUp(self):
# Create users
self.staff = StaffProfileFactory().user
self.author = ProfileFactory().user

# Create a content
self.content = PublishableContentFactory(author_list=[self.author])
self.suggested_content_1 = PublishableContentFactory()
self.suggested_content_2 = PublishableContentFactory()
self.suggestion_1 = ContentSuggestion(publication=self.content, suggestion=self.suggested_content_1)
self.suggestion_1.save()
self.suggestion_2 = ContentSuggestion(publication=self.content, suggestion=self.suggested_content_2)
self.suggestion_2.save()

# Get information to be reused in tests
self.form_url = reverse("content:remove-suggestion", kwargs={"pk": self.content.pk})
self.success_message_fragment = _("Vous avez enlevé")
self.error_messages = RemoveSuggestionForm.declared_fields["pk_suggestion"].error_messages
# Log in with an authorized user to perform the tests
self.client.force_login(self.staff)

def test_existing(self):
response = self.client.post(self.form_url, {"pk_suggestion": self.suggestion_1.pk}, follow=True)
# Check that we display correct message
self.assertContains(response, escape(self.success_message_fragment))
# Check update of database
with self.assertRaises(ContentSuggestion.DoesNotExist):
ContentSuggestion.objects.get(pk=self.suggestion_1.pk)
ContentSuggestion.objects.get(pk=self.suggestion_2.pk) # succeeds

def test_empty(self):
response = self.client.post(self.form_url, {"pk_suggestion": ""}, follow=True)
self.assertContains(response, escape(self.error_messages["required"]))

def test_invalid(self):
response = self.client.post(self.form_url, {"pk_suggestion": "420"}, follow=True) # pk must not exist
self.assertContains(response, escape(self.error_messages["does_not_exist"]))

def test_not_integer(self):
response = self.client.post(self.form_url, {"pk_suggestion": "abcd"}, follow=True)
self.assertContains(response, escape(self.error_messages["invalid"]))
58 changes: 31 additions & 27 deletions zds/tutorialv2/views/editorialization.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,55 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _

from zds.member.decorator import LoggedWithReadWriteHability, PermissionRequiredMixin
from zds.member.decorator import LoggedWithReadWriteHability, can_write_and_read_now, PermissionRequiredMixin
from zds.tutorialv2.forms import RemoveSuggestionForm, EditContentTagsForm
from zds.tutorialv2.mixins import SingleContentFormViewMixin
from zds.tutorialv2.models.database import ContentSuggestion, PublishableContent


class RemoveSuggestion(LoggedWithReadWriteHability, SingleContentFormViewMixin):

class RemoveSuggestion(PermissionRequiredMixin, SingleContentFormViewMixin):
form_class = RemoveSuggestionForm
modal_form = True
only_draft_version = True
authorized_for_staff = True
permissions = ["tutorialv2.change_publishablecontent"]

def form_valid(self, form):
_type = _("cet article")
if self.object.is_tutorial:
_type = _("ce tutoriel")
elif self.object.is_opinion:
@method_decorator(login_required)
@method_decorator(can_write_and_read_now)
def dispatch(self, *args, **kwargs):
if self.get_object().is_opinion:
raise PermissionDenied
return super().dispatch(*args, **kwargs)

def form_valid(self, form):
suggestion = ContentSuggestion.objects.get(pk=form.cleaned_data["pk_suggestion"])
suggestion.delete()
messages.success(self.request, self.get_success_message(suggestion))
return super().form_valid(form)

content_suggestion = get_object_or_404(ContentSuggestion, pk=form.cleaned_data["pk_suggestion"])
content_suggestion.delete()
def form_invalid(self, form):
form.previous_page_url = self.get_success_url()
return super().form_invalid(form)

messages.success(
self.request,
_('Vous avez enlevé "{}" de la liste des suggestions de {}.').format(
content_suggestion.suggestion.title, _type
),
def get_success_message(self, content_suggestion):
return _('Vous avez enlevé "{}" de la liste des suggestions de {}.').format(
content_suggestion.suggestion.title,
self.describe_type(),
)

def get_success_url(self):
if self.object.public_version:
self.success_url = self.object.get_absolute_url_online()
return self.object.get_absolute_url_online()
else:
self.success_url = self.object.get_absolute_url()

return super().form_valid(form)
return self.object.get_absolute_url()

def form_invalid(self, form):
messages.error(self.request, str(_("Les suggestions sélectionnées n'existent pas.")))
if self.object.public_version:
self.success_url = self.object.get_absolute_url_online()
else:
self.success_url = self.object.get_absolute_url()
return super().form_valid(form)
def describe_type(self):
if self.object.is_tutorial:
return _("ce tutoriel")
return _("cet article")


class AddSuggestion(LoggedWithReadWriteHability, PermissionRequiredMixin, SingleContentFormViewMixin):
Expand Down

0 comments on commit 203e069

Please sign in to comment.