Tester Wagtail Streamforms avec reCaptcha

Wagtail Streamforms offre un moyen très flexible d'ajouter des formulaires modifiables à votre site Wagtail. Dans ce didacticiel, on va tester certaines fonctionnalités qu'on a faites sur mesure.

15 Juillet 2020 14:51
Thèmes: Options de Wagtail Streamfield Tester

Notre point de départ est un site Wagtail dans lequel on a implémenté Wagtail Streamforms. On a ajouté quelques éléments à la fonctionnalité standard, à savoir un champ reCaptcha et un e-mail envoyé après l'envoi d'un formulaire. C'est ce qu'on va tester dans ce tutoriel.

Contrairement aux tutoriels précédents, on n'utilisera pas Factory Boy, d'une part parce qu'on n'a pas besoin d'un arbre de pages Wagtail, d'autre part parce que la création d'une usine de streamform n'est pas facile. Au lieu de cela, on copiera l'approche que Wagtail Streamforms utilise elle-même dans ses tests.

Tester le champ reCaptcha est assez simple. Créez un fichier /tests/test_streamforms.py et insérez:

from ..wagtailstreamforms_fields import ReCaptchaField
from django.test import TestCase

class TestWagtailStreamforms(TestCase):

    def test_recaptcha_field(self):
        field = ReCaptchaField().get_formfield({})
        self.assertTrue(field.required)

On crée une instance d'un ReCaptchaField avec la méthode get_formfield(). Dans la définition de notre modèle, on a remplacé la méthode get_options pour définir la valeur de required sur True; dans ce test, on vérifie que c'est bien le cas.

Tester la soumission de l'e-mail dans le fichier wagtailstreamforms_hooks.py qu'on a créé est une autre affaire. On doit créer un formulaire et simuler l'envoi par courrier. Pour créer le formulaire, on copiera l'approche dans les tests de Wagtail Streamforms:

from wagtailstreamforms.models import Form
import json

def test_form(self):
    form = Form.objects.create(
        title="Form",
        template_name="streamforms/form_block.html",
        slug="form",
        fields=json.dumps(
            [
                {
                    "type": "singleline",
                    "value": {"label": "singleline", "required": True},
                    "id": "9c46e208-e53a-4562-81f6-3fb3f34520f2",
                },
                {
                    "type": "multifile",
                    "value": {"label": "multifile", "required": True},
                    "id": "91bac05f-754b-41a3-b038-ac7850e6f951",
                },
            ]
        ),
    )
    return form

Le champ fields est rempli à l'aide de la méthode json.dumps à partir d'un tableau de dictionnaires avec le contenu du formulaire. Ensuite, on définira une méthode test_send_email, qui sera similaire à la méthode test_saves_record_with_files dans le test Wagtail Streamforms, mais qui s'appuiera sur la fonctionnalité que Django fournit pour tester la soumission des e-mails. Le code complet est le suivant:

from ..wagtailstreamforms_hooks import email_submission
from django.core import mail
from django.core.files.uploadedfile import SimpleUploadedFile
from django.http import QueryDict

def test_send_email(self):
    instance = self.test_form()

    advancedformsetting = AdvancedFormSetting.objects.create(form=instance, to_address="mail@example.com")
    data_dict = {
        "singleline": 'text',
        "form_id": instance.pk,
        "form_reference": "some-ref",
    }
    uploadedfile = SimpleUploadedFile("file.mp4", b"file_content", content_type="video/mp4")
    files_dict = QueryDict(mutable=True)
    files_dict.update({"multifile": uploadedfile})
    files_dict.update({"multifile": uploadedfile})

    form_class = instance.get_form(data=data_dict, files=files_dict)

    assert form_class.is_valid()

    # Send message.
    email_submission(instance, form_class)

    # Test that one message has been sent.
    self.assertEqual(len(mail.outbox), 1)

    # Verify that the subject of the first message is correct.
    expected_subject = 'New Form Submission : %s' % instance.title
    self.assertEqual(mail.outbox[0].subject, expected_subject)

Jusqu'à la ligne assert form_class.is_valid(), le code est presque égal à celui de test_saves_record_with_files, à deux exceptions près. Le premier est:

advancedformsetting = AdvancedFormSetting.objects.create(form=instance, to_address="mail@example.com")

On a créé la classe AdvancedFormSetting dans nos modèles pour pouvoir éditer dans notre admin la to-address du mail avec le formulaire soumis. On doit créer une instance ici, afin que Wagtail Streamforms le récupère lors de la création de la classe de formulaire. Le deuxième changement est la ligne:

uploadedfile = SimpleUploadedFile("file.mp4", b"file_content", content_type="video/mp4")

qui est le code derrière self.get_file() dans le code de test_saves_record_with_files (inséré afin qu'on n'aye pas à introduire une classe TestCase distincte comme dans les tests de Wagtail Streamforms lui-même).

Maintenant, la soumission par e-mail elle-même. Pour envoyer le mail, on appelle simplement la méthode email_submission qu'on a soi-même définie et qu'on veut tester. Le reste repose sur la fonctionnalité de test de messagerie de Django. Chaque e-mail sortant est enregistré dans django.core.mail.outbox. On peut donc vérifier le contenu de cette boîte aux lettres: vérifiez qu'il y a bien un message et que l'sujet du message est tel qu'on l'a défini dans notre méthode.

Lançons le test:

python3 manage.py test cms.tests.test_streamforms

On peut vérifier la couverture de tous les tests de notre application cms avec:

coverage run --source=cms manage.py test cms
coverage html

Le fichier index.html montre qu'on a une couverture de 97% et a couvert les lignes de code les plus pertinentes. On conclue donc nos tests. Il est temps de mettre notre application en ligne!

Commentez cet article (connectez-vous d'abord ou confirmez par nom et email ci-dessous)