michalpokusa / django-admin-action-forms

Extension for the Django admin panel that allows passing additional parameters to actions by creating intermediate pages with forms.
https://pypi.org/project/django-admin-action-forms/
MIT License
95 stars 3 forks source link

Writing tests for action forms #5

Open jayqi opened 2 days ago

jayqi commented 2 days ago

When using these action forms, what is the right way to write tests?

I tried to follow some of the examples from this StackOverflow post for testing admin actions generically, and test for a redirect to the admin/django_admin_action_forms/action_form.html template, but I got some weird errors like:

>       action = request.POST.getlist("action")[int(request.POST.get("index"))]
E       TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'

Just for experimentation, I hard-coded a {index: 0} into my POST data and got it to pass, but I don't really understand what that would be doing or if I'm actually testing anything correctly.

Then, separately, what would be the right way to test the form submission?

michalpokusa commented 2 days ago

Thanks for posting this.

Exception with missing index in POST

So, the index is used when there are multiple AdminForms (Django ones aka django.contrib.admin.helpers.AdminForm) on single change list page, which contain the information about a selected action. But when there are multiple of them, e.g. when one uses actions_on_bottom on a ModelAdmin, the POST data that is being sent might look like this:

image

Then, we can determine which "Go" button was clicked (the index POST value) and by that get the action name which was selected.

That saying, it seems like Django also accepts when the index is not set and uses 0 by default. https://github.com/django/django/blob/3.2/django/contrib/admin/options.py#L1363-L1366

This looks like an oversight on my part, as the line you provided raises exception if the index is not in payload.

I will look into it and fix that, if that is a bug, which it seems it is.

Testing form submission

Regarding this, the post you linked correctly explains how to test actions, and this stays true when it comes to actions with forms.

The only difference, is that you would have to add:

data = {
    'action': 'action_name',
    '_selected_action': [1, 2, 3, ...], # e.g.
    'action_form': "",
    'action_form_field1': ...,
    'action_form_field2': ...
}

Why is action_form field necessary? It is used to determine whether user is displaying the intermediate page for the first time (thus before entering any data to the form), without it, all the field would show errors on the intermediate page, as technically speaking the form is not valid at that point. https://github.com/michalpokusa/django-admin-action-forms/blob/1.2.4/django_admin_action_forms/decorators.py#L39-L43

michalpokusa commented 2 days ago

Please test the newly released version 1.3.0, it should work fine without the need to explicitly pass the index.