#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.