import webtest
from webtest.debugapp import debug_app
from webob import Request
from webob.response import gzip_app_iter
from tests.compat import unittest
import webbrowser
def links_app(environ, start_response):
req = Request(environ)
status = "200 OK"
responses = {
'/': """
page with links
Foo
Bar
Baz
Baz
Baz
Click me!
Click me!
Button
Button
Button
""",
'/foo/': (
'This is foo. Bar '
''
),
'/foo/bar': 'This is foobar.',
'/bar': 'This is bar.',
'/baz/': 'This is baz.',
'/spam/': 'This is spam.',
'/egg/': 'Just eggs.',
'/utf8/': """
Тестовая страница
Менделеев
Пушкин
""",
'/no_form/': """
Page without form
This is not the form you are looking for
""",
'/one_forms/': """
Page without form
""",
'/many_forms/': """
Page without form
""",
'/html_in_anchor/': """
Page with HTML in an anchor tag
Foo BarQuz
""",
'/json/': '{"foo": "bar"}',
}
utf8_paths = ['/utf8/']
body = responses[req.path_info]
body = body.encode('utf8')
headers = [
('Content-Type', 'text/html'),
('Content-Length', str(len(body)))
]
if req.path_info in utf8_paths:
headers[0] = ('Content-Type', 'text/html; charset=utf-8')
# PEP 3333 requires native strings:
headers = [(str(k), str(v)) for k, v in headers]
start_response(str(status), headers)
return [body]
def svg_application(env, start_response):
start_response('200 OK', [('Content-Type', 'image/svg+xml')])
return [
b""""""
b""""""
b""" """
]
def gzipped_app(environ, start_response):
status = "200 OK"
encoded_body = list(gzip_app_iter([b'test']))
headers = [
('Content-Type', 'text/html'),
('Content-Encoding', 'gzip'),
]
# PEP 3333 requires native strings:
headers = [(str(k), str(v)) for k, v in headers]
start_response(str(status), headers)
return encoded_body
class TestResponse(unittest.TestCase):
def test_repr(self):
def _repr(v):
br = repr(v)
if len(br) > 18:
br = br[:10] + '...' + br[-5:]
br += '/%s' % len(v)
return br
app = webtest.TestApp(debug_app)
res = app.post('/')
self.assertEqual(
repr(res),
'<200 OK text/plain body=%s>' % _repr(res.body)
)
res.content_type = None
self.assertEqual(
repr(res),
'<200 OK body=%s>' % _repr(res.body)
)
res.location = 'http://pylons.org'
self.assertEqual(
repr(res),
'<200 OK location: http://pylons.org body=%s>' % _repr(res.body)
)
res.body = b''
self.assertEqual(
repr(res),
'<200 OK location: http://pylons.org no body>'
)
def test_mustcontains(self):
app = webtest.TestApp(debug_app)
res = app.post('/', params='foobar')
res.mustcontain('foobar')
self.assertRaises(IndexError, res.mustcontain, 'not found')
res.mustcontain('foobar', no='not found')
res.mustcontain('foobar', no=['not found', 'not found either'])
self.assertRaises(IndexError, res.mustcontain, no='foobar')
self.assertRaises(
TypeError,
res.mustcontain, invalid_param='foobar'
)
def test_click(self):
app = webtest.TestApp(links_app)
self.assertIn('This is foo.', app.get('/').click('Foo'))
self.assertIn(
'This is foobar.',
app.get('/').click('Foo').click('Bar')
)
self.assertIn('This is bar.', app.get('/').click('Bar'))
# should skip non-clickable links
self.assertIn(
'This is baz.',
app.get('/').click('Baz')
)
self.assertIn('This is baz.', app.get('/').click(linkid='id_baz'))
self.assertIn('This is baz.', app.get('/').click(href='baz/'))
self.assertIn(
'This is spam.',
app.get('/').click('Click me!', index=0)
)
self.assertIn(
'Just eggs.',
app.get('/').click('Click me!', index=1)
)
self.assertIn(
'This is foo.',
app.get('/html_in_anchor/').click('baz qux')
)
def dont_match_anchor_tag():
app.get('/html_in_anchor/').click('href')
self.assertRaises(IndexError, dont_match_anchor_tag)
def multiple_links():
app.get('/').click('Click me!')
self.assertRaises(IndexError, multiple_links)
def invalid_index():
app.get('/').click('Click me!', index=2)
self.assertRaises(IndexError, invalid_index)
def no_links_found():
app.get('/').click('Ham')
self.assertRaises(IndexError, no_links_found)
def tag_inside_script():
app.get('/').click('Boo')
self.assertRaises(IndexError, tag_inside_script)
def test_click_utf8(self):
app = webtest.TestApp(links_app, use_unicode=False)
resp = app.get('/utf8/')
self.assertEqual(resp.charset, 'utf-8')
def test_click_u(self):
app = webtest.TestApp(links_app)
resp = app.get('/utf8/')
self.assertIn("Тестовая страница", resp)
self.assertIn('This is foo.', resp.click('Менделеев'))
def test_clickbutton(self):
app = webtest.TestApp(links_app)
self.assertIn(
'This is foo.',
app.get('/').clickbutton(buttonid='button1', verbose=True)
)
self.assertIn(
'This is foo.',
app.get('/').clickbutton(buttonid='button3', onclick=r".*href='(.*?)'", verbose=True)
)
self.assertRaises(
IndexError,
app.get('/').clickbutton, buttonid='button2'
)
self.assertRaises(
IndexError,
app.get('/').clickbutton, buttonid='button3'
)
def test_referer(self):
app = webtest.TestApp(links_app)
resp = app.get('/').click('Foo')
self.assertIn('Referer', resp.request.headers)
self.assertEqual(resp.request.headers['Referer'], 'http://localhost/')
resp = app.get('/').clickbutton(buttonid='button1')
self.assertIn('Referer', resp.request.headers)
self.assertEqual(resp.request.headers['Referer'], 'http://localhost/')
resp = app.get('/one_forms/').form.submit()
self.assertIn('Referer', resp.request.headers)
self.assertEqual(resp.request.headers['Referer'],
'http://localhost/one_forms/')
def test_xml_attribute(self):
app = webtest.TestApp(links_app)
resp = app.get('/no_form/')
self.assertRaises(
AttributeError,
getattr,
resp, 'xml'
)
resp.content_type = 'text/xml'
resp.xml
def test_lxml_attribute(self):
app = webtest.TestApp(links_app)
resp = app.post('/')
resp.content_type = 'text/xml'
print(resp.body)
print(resp.lxml)
def test_lxml_attribute_with_encoding_declaration(self):
app = webtest.TestApp(svg_application)
resp = app.get('/')
print(resp.body)
print(resp.lxml)
def test_html_attribute(self):
app = webtest.TestApp(links_app)
res = app.post('/')
res.content_type = 'text/plain'
self.assertRaises(
AttributeError,
getattr, res, 'html'
)
def test_no_form(self):
app = webtest.TestApp(links_app)
resp = app.get('/no_form/')
self.assertRaises(
TypeError,
getattr,
resp, 'form'
)
def test_one_forms(self):
app = webtest.TestApp(links_app)
resp = app.get('/one_forms/')
self.assertEqual(resp.form.id, 'first_form')
def test_too_many_forms(self):
app = webtest.TestApp(links_app)
resp = app.get('/many_forms/')
self.assertRaises(
TypeError,
getattr,
resp, 'form'
)
def test_showbrowser(self):
def open_new(f):
self.filename = f
webbrowser.open_new = open_new
app = webtest.TestApp(debug_app)
res = app.post('/')
res.showbrowser()
def test_unicode_normal_body(self):
app = webtest.TestApp(debug_app)
res = app.post('/')
self.assertRaises(
AttributeError,
getattr, res, 'unicode_normal_body'
)
res.charset = 'latin1'
res.body = 'été'.encode('latin1')
self.assertEqual(res.unicode_normal_body, 'été')
def test_testbody(self):
app = webtest.TestApp(debug_app)
res = app.post('/')
res.charset = 'utf8'
res.body = 'été'.encode('latin1')
res.testbody
def test_xml(self):
app = webtest.TestApp(links_app)
resp = app.get('/no_form/')
self.assertRaises(
AttributeError,
getattr,
resp, 'xml'
)
resp.content_type = 'text/xml'
resp.xml
def test_json(self):
app = webtest.TestApp(links_app)
resp = app.get('/json/')
with self.assertRaises(AttributeError):
resp.json
resp.content_type = 'text/json'
self.assertIn('foo', resp.json)
resp.content_type = 'application/json'
self.assertIn('foo', resp.json)
resp.content_type = 'application/vnd.webtest+json'
self.assertIn('foo', resp.json)
def test_unicode(self):
app = webtest.TestApp(links_app)
resp = app.get('/')
print(resp.__unicode__())
def test_content_dezips(self):
app = webtest.TestApp(gzipped_app)
resp = app.get('/')
self.assertEqual(resp.body, b'test')
class TestFollow(unittest.TestCase):
def get_redirects_app(self, count=1, locations=None):
"""Return an app that issues a redirect ``count`` times"""
remaining_redirects = [count] # this means "nonlocal"
if locations is None:
locations = ['/'] * count
def app(environ, start_response):
headers = [('Content-Type', 'text/html')]
if remaining_redirects[0] == 0:
status = "200 OK"
body = b"done"
else:
status = "302 Found"
body = b''
nextloc = str(locations.pop(0))
headers.append(('location', nextloc))
remaining_redirects[0] -= 1
headers.append(('Content-Length', str(len(body))))
# PEP 3333 requires native strings:
headers = [(str(k), str(v)) for k, v in headers]
start_response(str(status), headers)
return [body]
return webtest.TestApp(app)
def test_follow_with_cookie(self):
app = webtest.TestApp(debug_app)
app.get('/?header-set-cookie=foo=bar')
self.assertEqual(app.cookies['foo'], 'bar')
resp = app.get('/?status=302%20Found&header-location=/')
resp = resp.follow()
resp.mustcontain('HTTP_COOKIE: foo=bar')
def test_follow(self):
app = self.get_redirects_app(1)
resp = app.get('/')
self.assertEqual(resp.status_int, 302)
resp = resp.follow()
self.assertEqual(resp.body, b'done')
# can't follow non-redirect
self.assertRaises(AssertionError, resp.follow)
def test_follow_relative(self):
app = self.get_redirects_app(2, ['hello/foo/', 'bar'])
resp = app.get('/')
self.assertEqual(resp.status_int, 302)
resp = resp.follow()
self.assertEqual(resp.status_int, 302)
resp = resp.follow()
self.assertEqual(resp.body, b'done')
self.assertEqual(resp.request.url, 'http://localhost/hello/foo/bar')
def test_follow_twice(self):
app = self.get_redirects_app(2)
resp = app.get('/').follow()
self.assertEqual(resp.status_int, 302)
resp = resp.follow()
self.assertEqual(resp.status_int, 200)
def test_maybe_follow_200(self):
app = self.get_redirects_app(0)
resp = app.get('/').maybe_follow()
self.assertEqual(resp.body, b'done')
def test_maybe_follow_once(self):
app = self.get_redirects_app(1)
resp = app.get('/').maybe_follow()
self.assertEqual(resp.body, b'done')
def test_maybe_follow_twice(self):
app = self.get_redirects_app(2)
resp = app.get('/').maybe_follow()
self.assertEqual(resp.body, b'done')
def test_maybe_follow_infinite(self):
app = self.get_redirects_app(100000)
self.assertRaises(AssertionError, app.get('/').maybe_follow)