00001
00002 from __future__ import unicode_literals
00003
00004 import os.path
00005 import struct
00006 import sys
00007
00008 import webtest
00009 import six
00010 from six import binary_type
00011 from six import PY3
00012 from webob import Request
00013 from webtest.debugapp import DebugApp
00014 from webtest.compat import to_bytes
00015 from webtest.forms import NoValue, Submit, Upload
00016 from tests.compat import unittest
00017 from tests.compat import u
00018
00019
00020 class TestForms(unittest.TestCase):
00021
00022 def callFUT(self, filename='form_inputs.html', formid='simple_form'):
00023 dirname = os.path.join(os.path.dirname(__file__), 'html')
00024 app = DebugApp(form=os.path.join(dirname, filename), show_form=True)
00025 resp = webtest.TestApp(app).get('/form.html')
00026 return resp.forms[formid]
00027
00028 def test_set_submit_field(self):
00029 form = self.callFUT()
00030 self.assertRaises(
00031 AttributeError,
00032 form['submit'].value__set,
00033 'foo'
00034 )
00035
00036 def test_button(self):
00037 form = self.callFUT()
00038 button = form['button']
00039 self.assertTrue(isinstance(button, Submit),
00040 "<button> without type is a submit button")
00041
00042 def test_force_select(self):
00043 form = self.callFUT()
00044 form['select'].force_value('notavalue')
00045 form['select'].value__set('value3')
00046
00047 self.assertTrue(
00048 form['select']._forced_value is NoValue,
00049 "Setting a value after having forced a value should keep a forced"
00050 " state")
00051 self.assertEqual(
00052 form['select'].value, 'value3',
00053 "the value should the the one set by value__set")
00054 self.assertEqual(
00055 form['select'].selectedIndex, 2,
00056 "the value index should be the one set by value__set")
00057
00058 def test_form_select(self):
00059 form = self.callFUT()
00060 form.select('select', 'value1')
00061
00062 self.assertEqual(
00063 form['select'].value, 'value1',
00064 "when using form.select, the input selected value should be "
00065 "changed")
00066
00067 def test_get_field_by_index(self):
00068 form = self.callFUT()
00069 self.assertEqual(form['select'],
00070 form.get('select', index=0))
00071
00072 def test_get_unknown_field(self):
00073 form = self.callFUT()
00074 self.assertEqual(form['unknown'].value, '')
00075 form['unknown'].value = '1'
00076 self.assertEqual(form['unknown'].value, '1')
00077
00078 def test_get_non_exist_fields(self):
00079 form = self.callFUT()
00080 self.assertRaises(AssertionError, form.get, 'nonfield')
00081
00082 def test_get_non_exist_fields_with_default(self):
00083 form = self.callFUT()
00084 value = form.get('nonfield', default=1)
00085 self.assertEqual(value, 1)
00086
00087 def test_upload_fields(self):
00088 form = self.callFUT()
00089 fu = webtest.Upload(__file__)
00090 form['file'] = fu
00091 self.assertEqual(form.upload_fields(),
00092 [['file', __file__]])
00093
00094 def test_repr(self):
00095 form = self.callFUT()
00096 self.assertTrue(repr(form).startswith('<Form id='))
00097
00098 def test_the_bs_node_must_not_change(self):
00099 form = self.callFUT()
00100 self.assertEqual(form.text, str(form.html))
00101
00102 def test_set_multiple_checkboxes(self):
00103 form = self.callFUT(formid='multiple_checkbox_form')
00104 form['checkbox'] = [10, 30]
00105
00106 self.assertEqual(form.get('checkbox', index=0).value, '10')
00107 self.assertEqual(form.get('checkbox', index=1).value, None)
00108 self.assertEqual(form.get('checkbox', index=2).value, '30')
00109
00110 def test_button_submit(self):
00111 form = self.callFUT(formid='multiple_buttons_form')
00112 display = form.submit('action')
00113 self.assertIn(u("action=deactivate"), display, display)
00114
00115 def test_button_submit_by_index(self):
00116 form = self.callFUT(formid='multiple_buttons_form')
00117 display = form.submit('action', index=1)
00118 self.assertIn(u("action=activate"), display, display)
00119
00120 def test_button_submit_by_value(self):
00121 form = self.callFUT(formid='multiple_buttons_form')
00122 display = form.submit('action', value='activate')
00123 self.assertIn(u("action=activate"), display, display)
00124
00125 def test_button_submit_by_value_and_index(self):
00126 form = self.callFUT(formid='multiple_buttons_form')
00127 self.assertRaises(ValueError,
00128 form.submit, "action", value="activate",
00129 index=0)
00130
00131
00132 class TestResponseFormAttribute(unittest.TestCase):
00133
00134 def callFUT(self, body):
00135 app = DebugApp(form=to_bytes(body))
00136 return webtest.TestApp(app)
00137
00138 def test_no_form(self):
00139 app = self.callFUT('<html><body></body></html>')
00140 res = app.get('/form.html')
00141 self.assertRaises(TypeError, lambda: res.form)
00142
00143 def test_too_many_forms(self):
00144 app = self.callFUT(
00145 '<html><body><form></form><form></form></body></html>')
00146 res = app.get('/form.html')
00147 self.assertRaises(TypeError, lambda: res.form)
00148
00149
00150 class TestInput(unittest.TestCase):
00151
00152 def callFUT(self, filename='form_inputs.html'):
00153 dirname = os.path.join(os.path.dirname(__file__), 'html')
00154 app = DebugApp(form=os.path.join(dirname, filename), show_form=True)
00155 return webtest.TestApp(app)
00156
00157 def test_input(self):
00158 app = self.callFUT()
00159 res = app.get('/form.html')
00160 self.assertEqual(res.status_int, 200)
00161 self.assertTrue(res.content_type.startswith('text/html'))
00162
00163 form = res.forms['text_input_form']
00164 self.assertEqual(form['foo'].value, 'bar')
00165 self.assertEqual(form.submit_fields(), [('foo', 'bar')])
00166
00167 form = res.forms['radio_input_form']
00168 self.assertEqual(form['foo'].value, 'baz')
00169 self.assertEqual(form.submit_fields(), [('foo', 'baz')])
00170
00171 form = res.forms['checkbox_input_form']
00172 self.assertEqual(form['foo'].value, 'bar')
00173 self.assertEqual(form.submit_fields(), [('foo', 'bar')])
00174
00175 form = res.forms['password_input_form']
00176 self.assertEqual(form['foo'].value, 'bar')
00177 self.assertEqual(form.submit_fields(), [('foo', 'bar')])
00178
00179 def test_force_radio_input(self):
00180 app = self.callFUT()
00181 res = app.get('/form.html')
00182
00183 form = res.forms['radio_input_form']
00184
00185 form['foo'].force_value('fido')
00186 self.assertEqual(form['foo'].value, 'fido')
00187 self.assertEqual(form.submit_fields(), [('foo', 'fido')])
00188
00189 def test_input_unicode(self):
00190 app = self.callFUT('form_unicode_inputs.html')
00191 res = app.get('/form.html')
00192 self.assertEqual(res.status_int, 200)
00193 self.assertTrue(res.content_type.startswith('text/html'))
00194 self.assertEqual(res.charset.lower(), 'utf-8')
00195
00196 form = res.forms['text_input_form']
00197 self.assertEqual(form['foo'].value, u('Хармс'))
00198 self.assertEqual(form.submit_fields(), [('foo', u('Хармс'))])
00199
00200 form = res.forms['radio_input_form']
00201 self.assertEqual(form['foo'].value, u('Блок'))
00202 self.assertEqual(form.submit_fields(), [('foo', u('Блок'))])
00203
00204 form = res.forms['checkbox_input_form']
00205 self.assertEqual(form['foo'].value, u('Хармс'))
00206 self.assertEqual(form.submit_fields(), [('foo', u('Хармс'))])
00207
00208 form = res.forms['password_input_form']
00209 self.assertEqual(form['foo'].value, u('Хармс'))
00210 self.assertEqual(form.submit_fields(), [('foo', u('Хармс'))])
00211
00212 def test_input_no_default(self):
00213 app = self.callFUT('form_inputs_with_defaults.html')
00214 res = app.get('/form.html')
00215 self.assertEqual(res.status_int, 200)
00216 self.assertTrue(res.content_type.startswith('text/html'))
00217
00218 form = res.forms['text_input_form']
00219 self.assertEqual(form['foo'].value, '')
00220 self.assertEqual(form.submit_fields(), [('foo', '')])
00221
00222 form = res.forms['radio_input_form']
00223 self.assertTrue(form['foo'].value is None)
00224 self.assertEqual(form.submit_fields(), [])
00225
00226 form = res.forms['checkbox_input_form']
00227 self.assertTrue(form['foo'].value is None)
00228 self.assertEqual(form.submit_fields(), [])
00229
00230 form = res.forms['password_input_form']
00231 self.assertEqual(form['foo'].value, '')
00232 self.assertEqual(form.submit_fields(), [('foo', '')])
00233
00234 def test_textarea_entities(self):
00235 app = self.callFUT()
00236 res = app.get('/form.html')
00237 form = res.forms.get("textarea_input_form")
00238 self.assertEqual(form.get("textarea").value, "'foo&bar'")
00239 self.assertEqual(form.submit_fields(), [('textarea', "'foo&bar'")])
00240
00241 def test_textarea_emptyfirstline(self):
00242 app = self.callFUT()
00243 res = app.get('/form.html')
00244 form = res.forms.get("textarea_emptyline_form")
00245 self.assertEqual(form.get("textarea").value, "aaa")
00246 self.assertEqual(form.submit_fields(), [('textarea', "aaa")])
00247
00248
00249 class TestFormLint(unittest.TestCase):
00250
00251 def test_form_lint(self):
00252 form = webtest.Form(None, '''<form>
00253 <input type="text" name="field"/>
00254 </form>''')
00255 self.assertRaises(AttributeError, form.lint)
00256
00257 form = webtest.Form(None, '''<form>
00258 <input type="text" id="myfield" name="field"/>
00259 </form>''')
00260 self.assertRaises(AttributeError, form.lint)
00261
00262 form = webtest.Form(None, '''<form>
00263 <label for="myfield">my field</label>
00264 <input type="text" id="myfield" name="field"/>
00265 </form>''')
00266 form.lint()
00267
00268 form = webtest.Form(None, '''<form>
00269 <label class="field" for="myfield" role="r">my field</label>
00270 <input type="text" id="myfield" name="field"/>
00271 </form>''')
00272 form.lint()
00273
00274
00275 def select_app(environ, start_response):
00276 req = Request(environ)
00277 status = b"200 OK"
00278 if req.method == "GET":
00279 body = to_bytes("""
00280 <html>
00281 <head><title>form page</title></head>
00282 <body>
00283 <form method="POST" id="single_select_form">
00284 <select id="single" name="single">
00285 <option value="4">Four</option>
00286 <option value="5" selected="selected">Five</option>
00287 <option value="6">Six</option>
00288 <option value="7">Seven</option>
00289 </select>
00290 <input name="button" type="submit" value="single">
00291 </form>
00292 <form method="POST" id="multiple_select_form">
00293 <select id="multiple" name="multiple" multiple>
00294 <option value="8" selected="selected">Eight</option>
00295 <option value="9">Nine</option>
00296 <option value="10">Ten</option>
00297 <option value="11" selected="selected">Eleven</option>
00298 </select>
00299 <input name="button" type="submit" value="multiple">
00300 </form>
00301 </body>
00302 </html>
00303 """)
00304 else:
00305 select_type = req.POST.get("button")
00306 if select_type == "single":
00307 selection = req.POST.get("single")
00308 elif select_type == "multiple":
00309 selection = ", ".join(req.POST.getall("multiple"))
00310 body = to_bytes("""
00311 <html>
00312 <head><title>display page</title></head>
00313 <body>
00314 <p>You submitted the %(select_type)s </p>
00315 <p>You selected %(selection)s</p>
00316 </body>
00317 </html>
00318 """ % dict(selection=selection, select_type=select_type))
00319
00320 headers = [
00321 ('Content-Type', 'text/html; charset=utf-8'),
00322 ('Content-Length', str(len(body)))]
00323 start_response(status, headers)
00324 return [body]
00325
00326
00327 def select_app_without_values(environ, start_response):
00328 req = Request(environ)
00329 status = b"200 OK"
00330 if req.method == "GET":
00331 body = to_bytes("""
00332 <html>
00333 <head><title>form page</title></head>
00334 <body>
00335 <form method="POST" id="single_select_form">
00336 <select id="single" name="single">
00337 <option>Four</option>
00338 <option>Five</option>
00339 <option>Six</option>
00340 <option>Seven</option>
00341 </select>
00342 <input name="button" type="submit" value="single">
00343 </form>
00344 <form method="POST" id="multiple_select_form">
00345 <select id="multiple" name="multiple" multiple="multiple">
00346 <option>Eight</option>
00347 <option selected value="Nine">Nine</option>
00348 <option>Ten</option>
00349 <option selected>Eleven</option>
00350 </select>
00351 <input name="button" type="submit" value="multiple">
00352 </form>
00353 </body>
00354 </html>
00355 """)
00356 else:
00357 select_type = req.POST.get("button")
00358 if select_type == "single":
00359 selection = req.POST.get("single")
00360 elif select_type == "multiple":
00361 selection = ", ".join(req.POST.getall("multiple"))
00362 body = to_bytes("""
00363 <html>
00364 <head><title>display page</title></head>
00365 <body>
00366 <p>You submitted the %(select_type)s </p>
00367 <p>You selected %(selection)s</p>
00368 </body>
00369 </html>
00370 """ % dict(selection=selection, select_type=select_type))
00371
00372 headers = [
00373 ('Content-Type', 'text/html; charset=utf-8'),
00374 ('Content-Length', str(len(body)))]
00375 start_response(status, headers)
00376 return [body]
00377
00378
00379 def select_app_without_default(environ, start_response):
00380 req = Request(environ)
00381 status = b"200 OK"
00382 if req.method == "GET":
00383 body = to_bytes("""
00384 <html>
00385 <head><title>form page</title></head>
00386 <body>
00387 <form method="POST" id="single_select_form">
00388 <select id="single" name="single">
00389 <option value="4">Four</option>
00390 <option value="5">Five</option>
00391 <option value="6">Six</option>
00392 <option value="7">Seven</option>
00393 </select>
00394 <input name="button" type="submit" value="single">
00395 </form>
00396 <form method="POST" id="multiple_select_form">
00397 <select id="multiple" name="multiple" multiple="multiple">
00398 <option value="8">Eight</option>
00399 <option value="9">Nine</option>
00400 <option value="10">Ten</option>
00401 <option value="11">Eleven</option>
00402 </select>
00403 <input name="button" type="submit" value="multiple">
00404 </form>
00405 </body>
00406 </html>
00407 """)
00408 else:
00409 select_type = req.POST.get("button")
00410 if select_type == "single":
00411 selection = req.POST.get("single")
00412 elif select_type == "multiple":
00413 selection = ", ".join(req.POST.getall("multiple"))
00414 body = to_bytes("""
00415 <html>
00416 <head><title>display page</title></head>
00417 <body>
00418 <p>You submitted the %(select_type)s </p>
00419 <p>You selected %(selection)s</p>
00420 </body>
00421 </html>
00422 """ % dict(selection=selection, select_type=select_type))
00423
00424 headers = [
00425 ('Content-Type', 'text/html; charset=utf-8'),
00426 ('Content-Length', str(len(body)))]
00427 start_response(status, headers)
00428 return [body]
00429
00430
00431 def select_app_unicode(environ, start_response):
00432 req = Request(environ)
00433 status = b"200 OK"
00434 if req.method == "GET":
00435 body = u("""
00436 <html>
00437 <head><title>form page</title></head>
00438 <body>
00439 <form method="POST" id="single_select_form">
00440 <select id="single" name="single">
00441 <option value="ЕКБ">Екатеринбург</option>
00442 <option value="МСК" selected="selected">Москва</option>
00443 <option value="СПБ">Санкт-Петербург</option>
00444 <option value="САМ">Самара</option>
00445 </select>
00446 <input name="button" type="submit" value="single">
00447 </form>
00448 <form method="POST" id="multiple_select_form">
00449 <select id="multiple" name="multiple" multiple="multiple">
00450 <option value="8" selected="selected">Лондон</option>
00451 <option value="9">Париж</option>
00452 <option value="10">Пекин</option>
00453 <option value="11" selected="selected">Бристоль</option>
00454 </select>
00455 <input name="button" type="submit" value="multiple">
00456 </form>
00457 </body>
00458 </html>
00459 """).encode('utf8')
00460 else:
00461 select_type = req.POST.get("button")
00462 if select_type == "single":
00463 selection = req.POST.get("single")
00464 elif select_type == "multiple":
00465 selection = ", ".join(req.POST.getall("multiple"))
00466 body = (u("""
00467 <html>
00468 <head><title>display page</title></head>
00469 <body>
00470 <p>You submitted the %(select_type)s </p>
00471 <p>You selected %(selection)s</p>
00472 </body>
00473 </html>
00474 """) % dict(selection=selection, select_type=select_type)).encode('utf8')
00475 headers = [
00476 ('Content-Type', 'text/html; charset=utf-8'),
00477 ('Content-Length', str(len(body)))]
00478 start_response(status, headers)
00479 if not isinstance(body, binary_type):
00480 raise AssertionError('Body is not %s' % binary_type)
00481 return [body]
00482
00483
00484 class TestSelect(unittest.TestCase):
00485
00486 def test_unicode_select(self):
00487 app = webtest.TestApp(select_app_unicode)
00488 res = app.get('/')
00489 single_form = res.forms["single_select_form"]
00490 self.assertEqual(single_form["single"].value, u("МСК"))
00491
00492 display = single_form.submit("button")
00493 self.assertIn(u("<p>You selected МСК</p>"), display, display)
00494
00495 res = app.get('/')
00496 single_form = res.forms["single_select_form"]
00497 self.assertEqual(single_form["single"].value, u("МСК"))
00498 single_form.set("single", u("СПБ"))
00499 self.assertEqual(single_form["single"].value, u("СПБ"))
00500 display = single_form.submit("button")
00501 self.assertIn(u("<p>You selected СПБ</p>"), display, display)
00502
00503 def test_single_select(self):
00504 app = webtest.TestApp(select_app)
00505 res = app.get('/')
00506 self.assertEqual(res.status_int, 200)
00507 self.assertEqual(res.headers['content-type'],
00508 'text/html; charset=utf-8')
00509 self.assertEqual(res.content_type, 'text/html')
00510
00511 single_form = res.forms["single_select_form"]
00512 self.assertEqual(single_form["single"].value, "5")
00513 display = single_form.submit("button")
00514 self.assertIn("<p>You selected 5</p>", display, display)
00515
00516 res = app.get('/')
00517 self.assertEqual(res.status_int, 200)
00518 self.assertEqual(res.headers['content-type'],
00519 'text/html; charset=utf-8')
00520 self.assertEqual(res.content_type, 'text/html')
00521
00522 single_form = res.forms["single_select_form"]
00523 self.assertEqual(single_form["single"].value, "5")
00524 single_form.set("single", "6")
00525 self.assertEqual(single_form["single"].value, "6")
00526 display = single_form.submit("button")
00527 self.assertIn("<p>You selected 6</p>", display, display)
00528
00529 res = app.get('/')
00530 single_form = res.forms["single_select_form"]
00531 self.assertRaises(ValueError, single_form.select, "single", "5",
00532 text="Five")
00533 self.assertRaises(ValueError, single_form.select, "single",
00534 text="Three")
00535 single_form.select("single", text="Seven")
00536 self.assertEqual(single_form["single"].value, "7")
00537 display = single_form.submit("button")
00538 self.assertIn("<p>You selected 7</p>", display, display)
00539
00540 def test_single_select_forced_value(self):
00541 app = webtest.TestApp(select_app)
00542 res = app.get('/')
00543 self.assertEqual(res.status_int, 200)
00544 self.assertEqual(res.headers['content-type'],
00545 'text/html; charset=utf-8')
00546 self.assertEqual(res.content_type, 'text/html')
00547
00548 single_form = res.forms["single_select_form"]
00549 self.assertEqual(single_form["single"].value, "5")
00550 self.assertRaises(ValueError, single_form.set, "single", "984")
00551 single_form["single"].force_value("984")
00552 self.assertEqual(single_form["single"].value, "984")
00553 display = single_form.submit("button")
00554 self.assertIn("<p>You selected 984</p>", display, display)
00555
00556 def test_single_select_no_default(self):
00557 app = webtest.TestApp(select_app_without_default)
00558 res = app.get('/')
00559 self.assertEqual(res.status_int, 200)
00560 self.assertEqual(res.headers['content-type'],
00561 'text/html; charset=utf-8')
00562 self.assertEqual(res.content_type, 'text/html')
00563
00564 single_form = res.forms["single_select_form"]
00565 self.assertEqual(single_form["single"].value, "4")
00566 display = single_form.submit("button")
00567 self.assertIn("<p>You selected 4</p>", display, display)
00568
00569 res = app.get('/')
00570 self.assertEqual(res.status_int, 200)
00571 self.assertEqual(res.headers['content-type'],
00572 'text/html; charset=utf-8')
00573 self.assertEqual(res.content_type, 'text/html')
00574
00575 single_form = res.forms["single_select_form"]
00576 self.assertEqual(single_form["single"].value, "4")
00577 single_form.set("single", 6)
00578 self.assertEqual(single_form["single"].value, "6")
00579 display = single_form.submit("button")
00580 self.assertIn("<p>You selected 6</p>", display, display)
00581
00582 def test_multiple_select(self):
00583 app = webtest.TestApp(select_app)
00584 res = app.get('/')
00585 self.assertEqual(res.status_int, 200)
00586 self.assertEqual(res.headers['content-type'],
00587 'text/html; charset=utf-8')
00588 self.assertEqual(res.content_type, 'text/html')
00589
00590 multiple_form = res.forms["multiple_select_form"]
00591 self.assertEqual(multiple_form["multiple"].value, ['8', '11'],
00592 multiple_form["multiple"].value)
00593 display = multiple_form.submit("button")
00594 self.assertIn("<p>You selected 8, 11</p>", display, display)
00595
00596 res = app.get('/')
00597 self.assertEqual(res.status_int, 200)
00598 self.assertEqual(res.headers['content-type'],
00599 'text/html; charset=utf-8')
00600 self.assertEqual(res.content_type, 'text/html')
00601
00602 multiple_form = res.forms["multiple_select_form"]
00603 self.assertEqual(multiple_form["multiple"].value, ["8", "11"],
00604 multiple_form["multiple"].value)
00605 multiple_form.set("multiple", ["9"])
00606 self.assertEqual(multiple_form["multiple"].value, ["9"],
00607 multiple_form["multiple"].value)
00608 display = multiple_form.submit("button")
00609 self.assertIn("<p>You selected 9</p>", display, display)
00610
00611 res = app.get('/')
00612 multiple_form = res.forms["multiple_select_form"]
00613 self.assertRaises(ValueError, multiple_form.select_multiple,
00614 "multiple",
00615 ["8", "10"], texts=["Eight", "Ten"])
00616 self.assertRaises(ValueError, multiple_form.select_multiple,
00617 "multiple", texts=["Twelve"])
00618 multiple_form.select_multiple("multiple",
00619 texts=["Eight", "Nine", "Ten"])
00620 display = multiple_form.submit("button")
00621 self.assertIn("<p>You selected 8, 9, 10</p>", display, display)
00622
00623 def test_multiple_select_forced_values(self):
00624 app = webtest.TestApp(select_app)
00625 res = app.get('/')
00626 self.assertEqual(res.status_int, 200)
00627 self.assertEqual(res.headers['content-type'],
00628 'text/html; charset=utf-8')
00629 self.assertEqual(res.content_type, 'text/html')
00630
00631 multiple_form = res.forms["multiple_select_form"]
00632 self.assertEqual(multiple_form["multiple"].value, ["8", "11"],
00633 multiple_form["multiple"].value)
00634 self.assertRaises(ValueError, multiple_form.set,
00635 "multiple", ["24", "88"])
00636 multiple_form["multiple"].force_value(["24", "88"])
00637 self.assertEqual(multiple_form["multiple"].value, ["24", "88"],
00638 multiple_form["multiple"].value)
00639 display = multiple_form.submit("button")
00640 self.assertIn("<p>You selected 24, 88</p>", display, display)
00641
00642 def test_multiple_select_no_default(self):
00643 app = webtest.TestApp(select_app_without_default)
00644 res = app.get('/')
00645 self.assertEqual(res.status_int, 200)
00646 self.assertEqual(res.headers['content-type'],
00647 'text/html; charset=utf-8')
00648 self.assertEqual(res.content_type, 'text/html')
00649
00650 multiple_form = res.forms["multiple_select_form"]
00651 self.assertTrue(multiple_form["multiple"].value is None,
00652 repr(multiple_form["multiple"].value))
00653 display = multiple_form.submit("button")
00654 self.assertIn("<p>You selected </p>", display, display)
00655
00656 res = app.get('/')
00657 self.assertEqual(res.status_int, 200)
00658 self.assertEqual(res.headers['content-type'],
00659 'text/html; charset=utf-8')
00660 self.assertEqual(res.content_type, 'text/html')
00661
00662 multiple_form = res.forms["multiple_select_form"]
00663 self.assertTrue(multiple_form["multiple"].value is None,
00664 multiple_form["multiple"].value)
00665 multiple_form.set("multiple", ["9"])
00666 self.assertEqual(multiple_form["multiple"].value, ["9"],
00667 multiple_form["multiple"].value)
00668 display = multiple_form.submit("button")
00669 self.assertIn("<p>You selected 9</p>", display, display)
00670
00671 def test_select_no_value(self):
00672 app = webtest.TestApp(select_app_without_values)
00673 res = app.get('/')
00674 self.assertEqual(res.status_int, 200)
00675 self.assertEqual(res.headers['content-type'],
00676 'text/html; charset=utf-8')
00677 self.assertEqual(res.content_type, 'text/html')
00678
00679 single_form = res.forms["single_select_form"]
00680 self.assertEqual(single_form["single"].value, "Four")
00681 display = single_form.submit("button")
00682 self.assertIn("<p>You selected Four</p>", display, display)
00683
00684 res = app.get('/')
00685 self.assertEqual(res.status_int, 200)
00686 self.assertEqual(res.headers['content-type'],
00687 'text/html; charset=utf-8')
00688 self.assertEqual(res.content_type, 'text/html')
00689
00690 single_form = res.forms["single_select_form"]
00691 self.assertEqual(single_form["single"].value, "Four")
00692 single_form.set("single", "Six")
00693 self.assertEqual(single_form["single"].value, "Six")
00694 display = single_form.submit("button")
00695 self.assertIn("<p>You selected Six</p>", display, display)
00696
00697 def test_multiple_select_no_value(self):
00698 app = webtest.TestApp(select_app_without_values)
00699 res = app.get('/')
00700 self.assertEqual(res.status_int, 200)
00701 self.assertEqual(res.headers['content-type'],
00702 'text/html; charset=utf-8')
00703 self.assertEqual(res.content_type, 'text/html')
00704
00705 multiple_form = res.forms["multiple_select_form"]
00706 self.assertEqual(multiple_form["multiple"].value, ["Nine", "Eleven"])
00707 display = multiple_form.submit("button")
00708 self.assertIn("<p>You selected Nine, Eleven</p>", display, display)
00709
00710 res = app.get('/')
00711 self.assertEqual(res.status_int, 200)
00712 self.assertEqual(res.headers['content-type'],
00713 'text/html; charset=utf-8')
00714 self.assertEqual(res.content_type, 'text/html')
00715
00716 multiple_form = res.forms["multiple_select_form"]
00717 self.assertEqual(multiple_form["multiple"].value, ["Nine", "Eleven"])
00718 multiple_form.set("multiple", ["Nine", "Ten"])
00719 self.assertEqual(multiple_form["multiple"].value, ["Nine", "Ten"])
00720 display = multiple_form.submit("button")
00721 self.assertIn("<p>You selected Nine, Ten</p>", display, display)
00722
00723
00724 class SingleUploadFileApp(object):
00725
00726 body = b"""
00727 <html>
00728 <head><title>form page</title></head>
00729 <body>
00730 <form method="POST" id="file_upload_form"
00731 enctype="multipart/form-data">
00732 <input name="file-field" type="file" value="some/path/file.txt" />
00733 <input name="button" type="submit" value="single">
00734 </form>
00735 </body>
00736 </html>
00737 """
00738
00739 def __call__(self, environ, start_response):
00740 req = Request(environ)
00741 status = b"200 OK"
00742 if req.method == "GET":
00743 body = self.body
00744 else:
00745 body = b"""
00746 <html>
00747 <head><title>display page</title></head>
00748 <body>
00749 """ + self.get_files_page(req) + b"""
00750 </body>
00751 </html>
00752 """
00753 headers = [
00754 ('Content-Type', 'text/html; charset=utf-8'),
00755 ('Content-Length', str(len(body)))]
00756 start_response(status, headers)
00757 assert(isinstance(body, binary_type))
00758 return [body]
00759
00760 def get_files_page(self, req):
00761 file_parts = []
00762 uploaded_files = [(k, v) for k, v in req.POST.items() if 'file' in k]
00763 uploaded_files = sorted(uploaded_files)
00764 for name, uploaded_file in uploaded_files:
00765 filename = to_bytes(uploaded_file.filename)
00766 value = to_bytes(uploaded_file.value, 'ascii')
00767 content_type = to_bytes(uploaded_file.type, 'ascii')
00768 file_parts.append(b"""
00769 <p>You selected '""" + filename + b"""'</p>
00770 <p>with contents: '""" + value + b"""'</p>
00771 <p>with content type: '""" + content_type + b"""'</p>
00772 """)
00773 return b''.join(file_parts)
00774
00775
00776 class UploadBinaryApp(SingleUploadFileApp):
00777
00778 def get_files_page(self, req):
00779 uploaded_files = [(k, v) for k, v in req.POST.items() if 'file' in k]
00780 data = uploaded_files[0][1].value
00781 if PY3:
00782 data = struct.unpack(b'255h', data[:510])
00783 else:
00784 data = struct.unpack(str('255h'), data)
00785 return b','.join([to_bytes(str(i)) for i in data])
00786
00787
00788 class MultipleUploadFileApp(SingleUploadFileApp):
00789 body = b"""
00790 <html>
00791 <head><title>form page</title></head>
00792 <body>
00793 <form method="POST" id="file_upload_form"
00794 enctype="multipart/form-data">
00795 <input name="file-field-1" type="file" />
00796 <input name="file-field-2" type="file" />
00797 <input name="button" type="submit" value="single">
00798 </form>
00799 </body>
00800 </html>
00801 """
00802
00803
00804 class TestFileUpload(unittest.TestCase):
00805
00806 def assertFile(self, name, contents, display, content_type=None):
00807 if isinstance(name, six.binary_type):
00808 text_name = name.decode('ascii')
00809 else:
00810 text_name = name
00811 self.assertIn("<p>You selected '" + text_name + "'</p>",
00812 display, display)
00813 if isinstance(contents, six.binary_type):
00814 text_contents = contents.decode('ascii')
00815 else:
00816 text_contents = contents
00817 self.assertIn("<p>with contents: '" + text_contents + "'</p>",
00818 display, display)
00819 if content_type:
00820 self.assertIn("<p>with content type: '" + content_type + "'</p>",
00821 display, display)
00822
00823 def test_no_uploads_error(self):
00824 app = webtest.TestApp(SingleUploadFileApp())
00825 app.get('/').forms["file_upload_form"].upload_fields()
00826
00827 def test_upload_without_file(self):
00828 app = webtest.TestApp(SingleUploadFileApp())
00829 upload_form = app.get('/').forms["file_upload_form"]
00830 upload_form.submit()
00831
00832 def test_file_upload_with_filename_only(self):
00833 uploaded_file_name = os.path.join(os.path.dirname(__file__),
00834 "__init__.py")
00835 uploaded_file_contents = open(uploaded_file_name).read()
00836 if PY3:
00837 uploaded_file_contents = to_bytes(uploaded_file_contents)
00838
00839 app = webtest.TestApp(SingleUploadFileApp())
00840 res = app.get('/')
00841 self.assertEqual(res.status_int, 200)
00842 self.assertEqual(res.headers['content-type'],
00843 'text/html; charset=utf-8')
00844 self.assertEqual(res.content_type, 'text/html')
00845 self.assertEqual(res.charset, 'utf-8')
00846
00847 single_form = res.forms["file_upload_form"]
00848 single_form.set("file-field", (uploaded_file_name,))
00849 display = single_form.submit("button")
00850 self.assertFile(uploaded_file_name, uploaded_file_contents, display)
00851
00852 def test_file_upload_with_filename_and_contents(self):
00853 uploaded_file_name = os.path.join(os.path.dirname(__file__),
00854 "__init__.py")
00855 uploaded_file_contents = open(uploaded_file_name).read()
00856 if PY3:
00857 uploaded_file_contents = to_bytes(uploaded_file_contents)
00858
00859 app = webtest.TestApp(SingleUploadFileApp())
00860 res = app.get('/')
00861 self.assertEqual(res.status_int, 200)
00862 self.assertEqual(res.headers['content-type'],
00863 'text/html; charset=utf-8')
00864 self.assertEqual(res.content_type, 'text/html')
00865
00866 single_form = res.forms["file_upload_form"]
00867 single_form.set("file-field",
00868 (uploaded_file_name, uploaded_file_contents))
00869 display = single_form.submit("button")
00870 self.assertFile(uploaded_file_name, uploaded_file_contents, display)
00871
00872 def test_file_upload_with_content_type(self):
00873 uploaded_file_name = os.path.join(os.path.dirname(__file__),
00874 "__init__.py")
00875 with open(uploaded_file_name, 'rb') as f:
00876 uploaded_file_contents = f.read()
00877 app = webtest.TestApp(SingleUploadFileApp())
00878 res = app.get('/')
00879 single_form = res.forms["file_upload_form"]
00880 single_form["file-field"].value = Upload(uploaded_file_name,
00881 uploaded_file_contents,
00882 'text/x-custom-type')
00883 display = single_form.submit("button")
00884 self.assertFile(uploaded_file_name, uploaded_file_contents, display,
00885 content_type='text/x-custom-type')
00886
00887 def test_file_upload_binary(self):
00888 binary_data = struct.pack(str('255h'), *range(0, 255))
00889 app = webtest.TestApp(UploadBinaryApp())
00890 res = app.get('/')
00891 single_form = res.forms["file_upload_form"]
00892 single_form.set("file-field", ('my_file.dat', binary_data))
00893 display = single_form.submit("button")
00894 self.assertIn(','.join([str(n) for n in range(0, 255)]), display)
00895
00896 def test_multiple_file_uploads_with_filename_and_contents(self):
00897 uploaded_file1_name = os.path.join(os.path.dirname(__file__),
00898 "__init__.py")
00899 uploaded_file1_contents = open(uploaded_file1_name).read()
00900 if PY3:
00901 uploaded_file1_contents = to_bytes(uploaded_file1_contents)
00902 uploaded_file2_name = __file__
00903 uploaded_file2_name = os.path.join(os.path.dirname(__file__), 'html',
00904 "404.html")
00905 uploaded_file2_contents = open(uploaded_file2_name).read()
00906 if PY3:
00907 uploaded_file2_contents = to_bytes(uploaded_file2_contents)
00908
00909 app = webtest.TestApp(MultipleUploadFileApp())
00910 res = app.get('/')
00911 self.assertEqual(res.status_int, 200)
00912 self.assertEqual(res.headers['content-type'],
00913 'text/html; charset=utf-8')
00914 self.assertEqual(res.content_type, 'text/html')
00915
00916 single_form = res.forms["file_upload_form"]
00917 single_form.set("file-field-1",
00918 (uploaded_file1_name, uploaded_file1_contents))
00919 single_form.set("file-field-2",
00920 (uploaded_file2_name, uploaded_file2_contents))
00921 display = single_form.submit("button")
00922 self.assertFile(uploaded_file1_name, uploaded_file1_contents, display)
00923 self.assertFile(uploaded_file1_name, uploaded_file1_contents, display)
00924
00925 def test_upload_invalid_content(self):
00926 app = webtest.TestApp(SingleUploadFileApp())
00927 res = app.get('/')
00928 single_form = res.forms["file_upload_form"]
00929 single_form.set("file-field", ('my_file.dat', 1))
00930 try:
00931 single_form.submit("button")
00932 except ValueError:
00933 e = sys.exc_info()[1]
00934 self.assertEquals(
00935 six.text_type(e),
00936 u('File content must be %s not %s' % (binary_type, int))
00937 )
00938
00939 def test_invalid_uploadfiles(self):
00940 app = webtest.TestApp(SingleUploadFileApp())
00941 self.assertRaises(ValueError, app.post, '/', upload_files=[()])
00942 self.assertRaises(
00943 ValueError,
00944 app.post, '/',
00945 upload_files=[('name', 'filename', 'content', 'extra')]
00946 )
00947
00948 def test_goto_upload_files(self):
00949 app = webtest.TestApp(SingleUploadFileApp())
00950 resp = app.get('/')
00951 resp = resp.goto(
00952 '/',
00953 method='post',
00954 upload_files=[('file', 'filename', b'content')]
00955 )
00956 resp.mustcontain("<p>You selected 'filename'</p>",
00957 "<p>with contents: 'content'</p>")
00958
00959 def test_post_upload_files(self):
00960 app = webtest.TestApp(SingleUploadFileApp())
00961 resp = app.post(
00962 '/',
00963 upload_files=[('file', 'filename', b'content')]
00964 )
00965 resp.mustcontain("<p>You selected 'filename'</p>",
00966 "<p>with contents: 'content'</p>")