#29098: Add SimpleTestCase.assertRedirectsRegex()
-----------------------------------+------------------------------------
     Reporter:  Dan J Strohl       |                    Owner:  nobody
         Type:  New feature        |                   Status:  new
    Component:  Testing framework  |                  Version:  1.11
     Severity:  Normal             |               Resolution:
     Keywords:  unittest redirect  |             Triage Stage:  Accepted
    Has patch:  0                  |      Needs documentation:  0
  Needs tests:  0                  |  Patch needs improvement:  0
Easy pickings:  0                  |                    UI/UX:  0
-----------------------------------+------------------------------------
Changes (by Tim Graham):

 * type:  Cleanup/optimization => New feature
 * stage:  Unreviewed => Accepted


Old description:

> or, perhaps, allow it to use the patterns from the url's file.  Either
> way, the issue is that I have a view that gets a request, looks at it,
> and redirects it to a url such as /labs/12345/running, or
> /labs/4567/start.  this is a similar pattern to what is recommended and
> used in the admin, so I don't think I am doing something weird here, but
> I may not know what the redirect url will look like before I send the
> request (if I am sending something like /labs/new, and it returns
> /labs/12345 for example).
>
> as a hack, I did this:
> {{{
> #!div style="font-size: 80%"
> Code highlighting:
>   {{{#!python
> def fix_response_for_test(response, re_pattern, replace, count=0,
> flags=0):
>
>     if hasattr(response, 'redirect_chain'):
>         url, status_code = response.redirect_chain[-1]
>
>         tmp_replaced = re.search(re_pattern, url, flags=flags)
>         new_url = re.sub(re_pattern, replace, url, count=count,
> flags=flags)
>
>         # print('redirect - new: %s' % new_url)
>
>         response.redirect_chain[-1] = (new_url, status_code)
>
>     else:
>         # Not a followed redirect
>         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)
>
>         tmp_replaced = re.search(re_pattern, url, flags=flags)
>         new_url = re.sub(re_pattern, replace, url, count=count,
> flags=flags)
>
>         # print('no redirected - new: %s' % new_url)
>
>         response['Location'] = new_url
>
>     return tmp_replaced.group(0)
>   }}}
> }}}
>
> and is run like this:
>
> {{{
> #!div style="font-size: 80%"
> Code highlighting:
>   {{{#!python
>
>         session_id = fix_response_for_test(response, UUID_REGEX,
> '<uuid>')
>
>         redirect_url = '/lab/<uuid>/error/'
>
>         with self.subTest('%s - response url' % name):
>                 self.assertRedirects(response, redirect_url,
> fetch_redirect_response=False, msg_prefix=tmp_msg)
>         test_session = Sessions.objects.get(session_id=session_id)
>         # do more testing on the session object to make sure it was
> created correctly.
>   }}}
> }}}
>
> The returning the pulled content is nice, but probably not required as I
> COULD simply build two tests, one to check the redirect, and another to
> test the actual session object.
>
> If I had my druthers, I would love to see something like:
>
> {{{
> #!div style="font-size: 80%"
> Code highlighting:
>   {{{#!python
>
> args_obj=None
> self.assertRedirects(response, r'/labs/(?P<foobar>.+)/(.+)',
> get_args=args_obj)
>
> # assuming this passes the assertion, args_obj then would ==
> # args_obj = {
> #    'args': ['list of un-named items'],
> #    'kwargs': {dict of kwargs}
>   }}}
> }}}
>
> This coudl also be approached by adding the ability to get this kind of
> thing directly from the response object, along the lines of:
> {{{
> #!div style="font-size: 80%"
> Code highlighting:
>   {{{#!python
>
> (assuming the request was '/labs/12344/test_page
> > my_response.seed_url()
> ' '//labs//(?P<foobar>.+)//(.+)'  # which could then be matched in a
> redirect url match.
> > my_response.url_params(1)
> 'test_page'
> > my_response.url_params('foobar')
> '12344'
>
>   }}}
> }}}

New description:

 or, perhaps, allow it to use the patterns from the url's file.  Either
 way, the issue is that I have a view that gets a request, looks at it, and
 redirects it to a url such as /labs/12345/running, or /labs/4567/start.
 this is a similar pattern to what is recommended and used in the admin, so
 I don't think I am doing something weird here, but I may not know what the
 redirect url will look like before I send the request (if I am sending
 something like /labs/new, and it returns /labs/12345 for example).

 as a hack, I did this:
 {{{
 #!div style="font-size: 80%"
 Code highlighting:
   {{{#!python
 def fix_response_for_test(response, re_pattern, replace, count=0,
 flags=0):

     if hasattr(response, 'redirect_chain'):
         url, status_code = response.redirect_chain[-1]

         tmp_replaced = re.search(re_pattern, url, flags=flags)
         new_url = re.sub(re_pattern, replace, url, count=count,
 flags=flags)

         # print('redirect - new: %s' % new_url)

         response.redirect_chain[-1] = (new_url, status_code)

     else:
         # Not a followed redirect
         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)

         tmp_replaced = re.search(re_pattern, url, flags=flags)
         new_url = re.sub(re_pattern, replace, url, count=count,
 flags=flags)

         # print('no redirected - new: %s' % new_url)

         response['Location'] = new_url

     return tmp_replaced.group(0)
   }}}
 }}}

 and is run like this:

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

         session_id = fix_response_for_test(response, UUID_REGEX, '<uuid>')

         redirect_url = '/lab/<uuid>/error/'

         with self.subTest('%s - response url' % name):
                 self.assertRedirects(response, redirect_url,
 fetch_redirect_response=False, msg_prefix=tmp_msg)
         test_session = Sessions.objects.get(session_id=session_id)
         # do more testing on the session object to make sure it was
 created correctly.
   }}}
 }}}

 The returning the pulled content is nice, but probably not required as I
 COULD simply build two tests, one to check the redirect, and another to
 test the actual session object.

 If I had my druthers, I would love to see something like:

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

 args_obj=None
 self.assertRedirects(response, r'/labs/(?P<foobar>.+)/(.+)',
 get_args=args_obj)

 # assuming this passes the assertion, args_obj then would ==
 # args_obj = {
 #    'args': ['list of un-named items'],
 #    'kwargs': {dict of kwargs}
   }}}
 }}}

 This could also be approached by adding the ability to get this kind of
 thing directly from the response object, along the lines of:
 {{{
 #!div style="font-size: 80%"
 Code highlighting:
   {{{#!python

 (assuming the request was '/labs/12344/test_page
 > my_response.seed_url()
 ' '//labs//(?P<foobar>.+)//(.+)'  # which could then be matched in a
 redirect url match.
 > my_response.url_params(1)
 'test_page'
 > my_response.url_params('foobar')
 '12344'

   }}}
 }}}

--

Comment:

 I don't like it, but I suppose it would be consistent with other unittest
 assertions.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29098#comment:5>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/065.76b527a891ba9728e840eabe3afdc4d9%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to