darklow / django-suit

Modern theme for Django admin interface
http://djangosuit.com/
Other
2.31k stars 701 forks source link

Unable to test an admin action with suit installed #773

Closed gamesbook closed 3 years ago

gamesbook commented 3 years ago

If this is a bug please specify versions you're using first.

Django version: 1.11.29 Django Suit version: 2.0a1 Python version: 3.7.7

Issue:

I am unable to test admin actions. The basic issue seems to be that the request does not contain the apps for the suit menu (via admin.site.each_context(request)) so the test cannot run.

Below is a slightly abbreviated copy of the code as well as the stacktrace. Not sure what I need to add / change?

The action:

    def create_site_activity(self, request, queryset):
        """Create Site activity."""
        form = None
        if ACTION_SUBMIT in request.POST:
            form = SiteActivityForm(request.POST)
            if form.is_valid():
                for site in queryset:
                    # process site
                return HttpResponseRedirect(request.get_full_path())
            else:
                logger.error(form.errors)
        else:
            pass
        if not form:
            form = SiteActivityForm(
                initial={
                    '_selected_action': queryset.values_list('id', flat=True)})
        the_dict = {
            'sites': queryset,
            'siteactivity_form': form,
        }
        context = {**the_dict, **admin.site.each_context(request)}  # add suitmenu
        return render(
            request,
            'admin/actions/siteactivity.html',
            context)

The test:

    class TestSiteAdmin(TestCase):

        def setUp(self):
            self.factory = RequestFactory()
            self.user = User.objects.create_user( 
                email='jacob@fubar.com', password='top_secret'
            self.request = self.factory.get('/admin/site')
            self.request.user = self.user
            self.site_admin = admin.SiteAdmin(models.Site, AdminSite())

        def test_action_create_site_activity_no_form(self):
            """create_site_activity(self, request, queryset)"""
            siteA = site.make(code='SiteA')
            siteB = site.make(code='SiteB')
            sas = activity.make(name='ActivityTest')
            # run action
            queryset = models.Site.objects.filter(code__icontains='Site')
            self.request.POST._mutable = True
            self.request.POST['_selected_action'] = []
            self.site_admin.create_site_activity(self.request, queryset)

The test fails with this trace:

    WARNING:root:Django Suit was unable to retrieve apps list for menu.
    WARNING:django.template:Exception raised while rendering {% include %} for template 'admin/actions/siteactivity.html'. Empty string rendered instead.
    Traceback (most recent call last):
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/loader_tags.py", line 216, in render
    return template.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 209, in render
    return self._render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/defaulttags.py", line 529, in render
    return self.nodelist.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/defaulttags.py", line 322, in render
    return nodelist.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/django/template/defaulttags.py", line 172, in render
    values = list(values)
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/suit/menu.py", line 59, in __iter__
    for each in self.get_menu_items():
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/suit/menu.py", line 64, in get_menu_items
    self.menu_items = self.build_menu()
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/suit/menu.py", line 78, in build_menu
    self.map_native_apps()
    File "/home/dev/.envs/tp3/lib/python3.7/site-packages/suit/menu.py", line 116, in map_native_apps
    for native_app in self.available_apps:
    TypeError: 'NoneType' object is not iterable
gamesbook commented 3 years ago

The correct way to test is with reverse url

        def test_action_create_site_activity_no_form(self):
            """create_site_activity(self, request, queryset)"""
            siteA = site.make(code='SiteA')
            siteB = site.make(code='SiteB')
            sas = activity.make(name='ActivityTest')
            queryset = models.Site.objects.filter(code__icontains='Site')
            items = [site.id for site in queryset]
            # run action NO data
            data = {'action': 'create_site_activity', '_selected_action': items}
            change_url = reverse('admin:locales_site_changelist')
            response = self.client.post(change_url, data, follow=True)
            print('response:', response.content)
            assert response.status_code == 200