#29098: Allow assertRedirects to handle regex matches.
-------------------------------------+-------------------------------------
     Reporter:  Dan J Strohl         |                    Owner:  nobody
         Type:                       |                   Status:  new
  Cleanup/optimization               |
    Component:  Testing framework    |                  Version:  1.11
     Severity:  Normal               |               Resolution:
     Keywords:  unittest redirect    |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Dan J Strohl):

 Replying to [comment:3 Tim Graham]:
 > It sounds like you'd like `assertRedirects()` to be able to  do the
 `reverse()` itself. I don't see much advantage to that (complicating
 things by allowing `assertRedirects()` to take all the parameters of
 `reverse()`). If I misunderstood, can you clarify what API change you're
 proposing?

 Ummm, not totally, the reverse() expects enough parameters to be able to
 create the url, I am proposing being able to validate without knowing the
 specific variables needed to complete the reverse.

 basically, at something like the changes below... (all I did was pull out
 the last assertion lines and put them into their own method.)

 Taking this a bit further, you could also pull out the assertion for the
 response codes and make them into their own assertion (which would be
 called by the assertRedirects) and/or even put the code to pull the
 response codes and response url into a helper function (like
 "get_redirected_url(response, fetch_redirect_response=True)" ) further
 modularizing it into even simpler pieces, and allowing for more
 flexibility in usage.


 {{{
 #!div style="font-size: 80%"
 Code highlighting:
   {{{#!python


 def _assertRedirects(self, response, expected_url, status_code=302,
                         target_status_code=200, msg_prefix='',
                         fetch_redirect_response=True):
         """
         Assert that a response redirected to a specific URL and that the
         redirect URL can be loaded.

         Won't work for external links since it uses the test client to do
 a
         request (use fetch_redirect_response=False to check such links
 without
         fetching them).
         """
         if msg_prefix:
             msg_prefix += ": "

         if hasattr(response, 'redirect_chain'):
             # The request was a followed redirect
             self.assertTrue(
                 len(response.redirect_chain) > 0,
                 msg_prefix + "Response didn't redirect as expected:
 Response code was %d (expected %d)"
                 % (response.status_code, status_code)
             )

             self.assertEqual(
                 response.redirect_chain[0][1], status_code,
                 msg_prefix + "Initial response didn't redirect as
 expected: Response code was %d (expected %d)"
                 % (response.redirect_chain[0][1], status_code)
             )

             url, status_code = response.redirect_chain[-1]
             scheme, netloc, path, query, fragment = urlsplit(url)

             self.assertEqual(
                 response.status_code, target_status_code,
                 msg_prefix + "Response didn't redirect as expected: Final
 Response code was %d (expected %d)"
                 % (response.status_code, target_status_code)
             )

         else:
             # Not a followed redirect
             self.assertEqual(
                 response.status_code, status_code,
                 msg_prefix + "Response didn't redirect as expected:
 Response code was %d (expected %d)"
                 % (response.status_code, status_code)
             )

             url = response.url
             scheme, netloc, path, query, fragment = urlsplit(url)

             # Prepend the request path to handle relative path redirects.
             if not path.startswith('/'):
                 url = urljoin(response.request['PATH_INFO'], url)
                 path = urljoin(response.request['PATH_INFO'], path)

             if fetch_redirect_response:
                 # netloc might be empty, or in cases where Django tests
 the
                 # HTTP scheme, the convention is for netloc to be
 'testserver'.
                 # Trust both as "internal" URLs here.
                 domain, port = split_domain_port(netloc)
                 if domain and not validate_host(domain,
 settings.ALLOWED_HOSTS):
                     raise ValueError(
                         "The test client is unable to fetch remote URLs
 (got %s). "
                         "If the host is served by Django, add '%s' to
 ALLOWED_HOSTS. "
                         "Otherwise, use assertRedirects(...,
 fetch_redirect_response=False)."
                         % (url, domain)
                     )
                 redirect_response = response.client.get(path,
 QueryDict(query), secure=(scheme == 'https'))

                 # Get the redirection page, using the same client that was
 used
                 # to obtain the original response.
                 self.assertEqual(
                     redirect_response.status_code, target_status_code,
                     msg_prefix + "Couldn't retrieve redirection page '%s':
 response code was %d (expected %d)"
                     % (path, redirect_response.status_code,
 target_status_code)
                 )
         return url

 def assertRedirects(self, response, expected_url, status_code=302,
                         target_status_code=200, msg_prefix='',
                         fetch_redirect_response=True):
         url = self._assertRedirects(
             response,
             expected_url,
             status_code=status_code,
             target_status_code=target_status_code,
             msg_prefix=msg_prefix,
             fetch_redirect_response=fetch_redirect_response)
         self.assertEqual(
             url, expected_url,
             msg_prefix + "Response redirected to '%s', expected '%s'" %
 (url, expected_url)
         )

 def assertRedirectsRegex(self, response, expected_url_regex,
 status_code=302,
                     target_status_code=200, msg_prefix='',
                     fetch_redirect_response=True):
         url = self._assertRedirects(
             response,
             expected_url,
             status_code=status_code,
             target_status_code=target_status_code,
             msg_prefix=msg_prefix,
             fetch_redirect_response=fetch_redirect_response)
         self.assertRegex(
             url, expected_url_regex,
             msg_prefix + "Response redirected to '%s', expected '%s'" %
 (url, expected_url)
         )


   }}}
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29098#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/065.a18a40f301777e594b4f2cc40d1da325%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to