summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGael Pasgrimaud <gael@gawel.org>2022-01-19 08:55:34 +0100
committerGitHub <noreply@github.com>2022-01-19 08:55:34 +0100
commitb0426fc2952ba45de75cbd37db350281dce101df (patch)
tree821d6e8d5cf77a4505042a03fb1fb4905dd36b28
parent2719819e5ac26bdc0cf39879ca4d3879ae9eb0c9 (diff)
parentd1dbc25f53a031d03112cb1e44f4a060cf3665cd (diff)
downloadwebtest-master.tar.gz
Merge pull request #242 from azmeuk/issue-240-multiple-file-inputmaster
Support for multiple file input
-rw-r--r--CHANGELOG.rst2
-rw-r--r--docs/forms.rst11
-rw-r--r--tests/test_forms.py52
-rw-r--r--webtest/app.py5
4 files changed, 64 insertions, 6 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 4325a0e..c2e06f8 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -4,7 +4,7 @@ News
3.0.1 (unreleased)
------------------
-- Nothing changed yet.
+- Multiple file input support.
3.0.0 (2021-08-19)
diff --git a/docs/forms.rst b/docs/forms.rst
index 6e5b7c9..8f4ff4c 100644
--- a/docs/forms.rst
+++ b/docs/forms.rst
@@ -197,6 +197,17 @@ You can deal with file upload by using the Upload class:
>>> form['file'] = Upload('README.rst', b'data')
>>> form['file'] = Upload('README.rst', b'data', 'text/x-rst')
+If the file field has a ``multiple`` parameter, you can pass a
+list of :class:`~webtest.forms.Upload`:
+
+.. code-block:: python
+
+ >>> from webtest import Upload
+ >>> form['files'] = [
+ ... Upload('README.rst'),
+ ... Upload('LICENSE.rst'),
+ ... ]
+
Submit a form
--------------
diff --git a/tests/test_forms.py b/tests/test_forms.py
index d50c034..f8bd39d 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -829,7 +829,6 @@ class SingleUploadFileApp:
def get_files_page(self, req):
file_parts = []
uploaded_files = [(k, v) for k, v in req.POST.items() if 'file' in k]
- uploaded_files = sorted(uploaded_files)
for name, uploaded_file in uploaded_files:
if isinstance(uploaded_file, cgi.FieldStorage):
filename = to_bytes(uploaded_file.filename)
@@ -854,7 +853,7 @@ class UploadBinaryApp(SingleUploadFileApp):
return b','.join([to_bytes(str(i)) for i in data])
-class MultipleUploadFileApp(SingleUploadFileApp):
+class SeveralSingleFileApp(SingleUploadFileApp):
body = b"""
<html>
<head><title>form page</title></head>
@@ -870,6 +869,23 @@ class MultipleUploadFileApp(SingleUploadFileApp):
"""
+class MultipleUploadFileApp(SingleUploadFileApp):
+
+ body = b"""
+<html>
+ <head><title>form page</title></head>
+ <body>
+ <form method="POST" id="file_upload_form"
+ enctype="multipart/form-data">
+ <input name="files-field" type="file" value="some/path/file.txt" multiple="" />
+ <input name="int-field" type="text" value="" />
+ <input name="button" type="submit" value="single">
+ </form>
+ </body>
+</html>
+"""
+
+
class TestFileUpload(unittest.TestCase):
def assertFile(self, name, contents, display, content_type=None):
@@ -960,7 +976,7 @@ class TestFileUpload(unittest.TestCase):
display = single_form.submit("button")
self.assertIn(','.join([str(n) for n in range(0, 255)]), display)
- def test_multiple_file_uploads_with_filename_and_contents(self):
+ def test_several_file_uploads_with_filename_and_contents(self):
uploaded_file1_name = os.path.join(os.path.dirname(__file__),
"__init__.py")
uploaded_file1_contents = open(uploaded_file1_name).read()
@@ -971,7 +987,7 @@ class TestFileUpload(unittest.TestCase):
uploaded_file2_contents = open(uploaded_file2_name).read()
uploaded_file2_contents = to_bytes(uploaded_file2_contents)
- app = webtest.TestApp(MultipleUploadFileApp())
+ app = webtest.TestApp(SeveralSingleFileApp())
res = app.get('/')
self.assertEqual(res.status_int, 200)
self.assertEqual(res.headers['content-type'],
@@ -1063,3 +1079,31 @@ class TestFileUpload(unittest.TestCase):
resp = form.submit()
resp.mustcontain("<p>You selected 'filename'</p>",
"<p>with contents: ''</p>")
+
+ def test_multiple_file(self):
+ uploaded_file_name_1 = os.path.join(os.path.dirname(__file__),
+ "__init__.py")
+ uploaded_file_contents_1 = open(uploaded_file_name_1).read()
+ uploaded_file_contents_1 = to_bytes(uploaded_file_contents_1)
+
+ uploaded_file_name_2 = os.path.join(os.path.dirname(__file__),
+ os.path.basename(__file__))
+ uploaded_file_contents_2 = open(uploaded_file_name_1).read()
+ uploaded_file_contents_2 = to_bytes(uploaded_file_contents_2)
+
+ app = webtest.TestApp(MultipleUploadFileApp())
+ res = app.get('/')
+ self.assertEqual(res.status_int, 200)
+ self.assertEqual(res.headers['content-type'],
+ 'text/html; charset=utf-8')
+ self.assertEqual(res.content_type, 'text/html')
+
+ single_form = res.forms["file_upload_form"]
+ single_form.set("files-field", [
+ (uploaded_file_name_1, uploaded_file_contents_1),
+ (uploaded_file_name_2, uploaded_file_contents_2),
+ ])
+
+ display = single_form.submit("button")
+ self.assertFile(uploaded_file_name_1, uploaded_file_contents_1, display)
+ self.assertFile(uploaded_file_name_2, uploaded_file_contents_2, display)
diff --git a/webtest/app.py b/webtest/app.py
index 4ea19e9..9e3155e 100644
--- a/webtest/app.py
+++ b/webtest/app.py
@@ -500,7 +500,10 @@ class TestApp:
except: # pragma: no cover
raise # field name are always ascii
if isinstance(value, forms.File):
- if value.value:
+ if "multiple" in value.attrs:
+ for file in value.value:
+ _append_file([key] + list(file))
+ elif value.value:
_append_file([key] + list(value.value))
else:
# If no file was uploaded simulate an empty file with no