Skip to content

Commit a883019

Browse files
committed
Added tests for download-file view
1 parent 4ae22bb commit a883019

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# -*- coding: utf-8 -*-
2+
"""Browser views tests for this package."""
3+
from imio.esign.browser.views import DownloadFileView
4+
from imio.esign.testing import IMIO_ESIGN_FUNCTIONAL_TESTING
5+
from imio.pyutils.utils import shortuid_encode_id
6+
from plone import api
7+
from plone.app.testing import logout
8+
from plone.app.testing import setRoles
9+
from plone.app.testing import TEST_USER_ID
10+
from plone.namedfile.file import NamedBlobFile
11+
from plone.namedfile.file import NamedBlobImage
12+
from plone.testing import z2
13+
14+
import collective.iconifiedcategory
15+
import os
16+
import transaction
17+
import unittest
18+
19+
20+
class TestDownloadFileView(unittest.TestCase):
21+
"""Test DownloadFileView browser view."""
22+
23+
layer = IMIO_ESIGN_FUNCTIONAL_TESTING
24+
25+
def setUp(self):
26+
"""Set up test fixtures."""
27+
self.app = self.layer["app"]
28+
self.portal = self.layer["portal"]
29+
self.request = self.layer["request"]
30+
setRoles(self.portal, TEST_USER_ID, ["Manager"])
31+
32+
# Setup content category configuration (like in test_utils.py)
33+
at_folder = api.content.create(
34+
container=self.portal,
35+
id="annexes_types",
36+
title="Annexes Types",
37+
type="ContentCategoryConfiguration",
38+
exclude_from_nav=True,
39+
)
40+
category_group = api.content.create(
41+
type="ContentCategoryGroup",
42+
title="Annexes",
43+
container=at_folder,
44+
id="annexes",
45+
)
46+
icon_path = os.path.join(os.path.dirname(collective.iconifiedcategory.__file__), "tests", "icône1.png")
47+
with open(icon_path, "rb") as fl:
48+
api.content.create(
49+
type="ContentCategory",
50+
title="To sign",
51+
container=category_group,
52+
icon=NamedBlobImage(fl.read(), filename=u"icône1.png"),
53+
id="to_sign",
54+
predefined_title="To be signed",
55+
to_sign=True,
56+
show_preview=False,
57+
)
58+
59+
# Create a folder to hold test annexes
60+
self.folder = api.content.create(
61+
container=self.portal,
62+
type="Folder",
63+
id="test_folder",
64+
title="Test Folder",
65+
)
66+
67+
# Create test annexes with NamedBlobFile (Plone 4.3 Archetypes)
68+
tests_dir = os.path.dirname(__file__)
69+
pdf_file = "annex1.pdf"
70+
with open(os.path.join(tests_dir, pdf_file), "rb") as f:
71+
file_data = f.read()
72+
self.test_annex = api.content.create(
73+
container=self.folder,
74+
type="annex",
75+
id="test_annex",
76+
title="Test Annex",
77+
content_category="to_sign",
78+
file=NamedBlobFile(
79+
data=file_data,
80+
filename=u"test_document__uid.pdf",
81+
contentType="application/pdf"
82+
),
83+
)
84+
85+
self.file_uid = self.test_annex.UID()
86+
self.encoded_uid = shortuid_encode_id(self.file_uid, separator="-", block_size=5)
87+
88+
# Commit transaction for functional testing
89+
transaction.commit()
90+
91+
def test_download_file_view(self):
92+
"""Test DownloadFileView with various scenarios."""
93+
logout() # anonymous usage
94+
95+
# View exists and can be instantiated
96+
view = api.content.get_view("download-file", self.portal, self.request)
97+
self.assertIsInstance(view, DownloadFileView)
98+
view = DownloadFileView(self.portal, self.request)
99+
self.assertEqual(view.file_id, None)
100+
self.assertEqual(view.shortuid_separator, "-")
101+
self.assertEqual(view.named_blob_file_attribute, "file")
102+
103+
# Download file without UID
104+
view = DownloadFileView(self.portal, self.request)
105+
result = view()
106+
self.assertIn("A file identifier must be passed in the url", result)
107+
# invalid UID format
108+
view.file_id = "$$$"
109+
result = view()
110+
self.assertIn("This file identifier is not correct", result)
111+
# valid format but non-existent UID
112+
view.file_id = "aabbccddee"
113+
result = view()
114+
self.assertIn("The corresponding file identifier cannot be retrieved", result)
115+
# download from object without file attribute
116+
folder_uid = self.folder.UID()
117+
encoded_folder_uid = shortuid_encode_id(folder_uid, separator="-", block_size=5)
118+
view.file_id = encoded_folder_uid
119+
result = view()
120+
self.assertIn("The corresponding file content cannot be retrieved", result)
121+
122+
# Download file with valid UID
123+
view.file_id = self.encoded_uid
124+
result = view()
125+
# Check that we got binary data (the file content)
126+
self.assertIsInstance(result, str) # In Python 2, binary data is str
127+
self.assertTrue(len(result) > 0)
128+
self.assertTrue(result.startswith(b"%PDF") or result.startswith("%PDF"))
129+
# Check response headers
130+
response = self.request.RESPONSE
131+
self.assertIn("application/pdf", response.getHeader("Content-Type"))
132+
self.assertIn("inline", response.getHeader("Content-Disposition"))
133+
self.assertIn("test_document.pdf", response.getHeader("Content-Disposition"))
134+
self.assertTrue(int(response.getHeader("Content-Length")) > 0)
135+
136+
# Test URL traversal mechanism
137+
browser = z2.Browser(self.app)
138+
portal_url = self.portal.absolute_url()
139+
browser.open("{}/download-file/{}".format(portal_url, "aabbccddee"))
140+
self.assertIn("The corresponding file identifier cannot be retrieved (aabbccddee)", browser.contents)
141+
browser.open("{}/download-file/{}".format(portal_url, "aabbccddee/ffgghh"))
142+
self.assertIn("The corresponding file identifier cannot be retrieved (aabbccddee)", browser.contents)
143+
browser.open("{}/download-file/{}".format(portal_url, "aabbccddee?param=value"))
144+
self.assertIn("The corresponding file identifier cannot be retrieved (aabbccddee)", browser.contents)

0 commit comments

Comments
 (0)