-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
test_scaling.py
253 lines (228 loc) · 10.7 KB
/
test_scaling.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# -*- coding: utf-8 -*-
from plone.app.imaging.tests.base import ImagingTestCase
from plone.app.imaging.tests.base import ImagingFunctionalTestCase
from plone.app.imaging.traverse import ImageTraverser
from plone.app.imaging.traverse import DefaultImageScaleHandler
from StringIO import StringIO
from PIL.Image import open
import transaction
from plone.app.imaging.tests.base import getSettings
class TraverseCounterMixin:
def afterSetUp(self):
self.counter = 0 # wrap `publishTraverse` with a counter
self.original = ImageTraverser.publishTraverse
def publishTraverse(adapter, request, name):
self.counter += 1
return self.original(adapter, request, name)
ImageTraverser.publishTraverse = publishTraverse
def beforeTearDown(self):
ImageTraverser.publishTraverse = self.original
class ImageTraverseTests(TraverseCounterMixin, ImagingTestCase):
def testImageThumb(self):
data = self.getImage()
folder = self.folder
image = folder[folder.invokeFactory('Image', id='foo', image=data)]
# make sure traversing works as is and with scaling
traverse = folder.REQUEST.traverseName
self.assertEqual(traverse(image, 'image').data, data)
sizes = image.getField('image').getAvailableSizes(image)
self.assertTrue('thumb' in sizes.keys())
thumb = traverse(image, 'image_thumb')
self.assertEqual(thumb.getContentType(), 'image/png')
self.assertEqual(thumb.data[1:4], 'PNG')
width, height = sizes['thumb']
self.assertEqual(thumb.width, width)
self.assertEqual(thumb.height, height)
# also check the generated tag
url = image.absolute_url() + '/image_thumb'
tag = '<img src="%s" alt="foo" title="foo" height="%d" width="%d" />'
self.assertEqual(thumb.tag(), tag % (url, height, width))
# calling str(...) on the scale should return the tag
self.assertEqual(str(thumb), thumb.tag())
# make sure the traversal adapter was called in fact
self.assertEqual(self.counter, 2)
def testCustomSizes(self):
data = self.getImage()
folder = self.folder
image = folder[folder.invokeFactory('Image', id='foo', image=data)]
# set custom image sizes
settings = getSettings()
settings.allowed_sizes = [u'foo 23:23', u'bar 6:8']
# make sure traversing works with the new sizes
traverse = folder.REQUEST.traverseName
foo = traverse(image, 'image_foo')
self.assertEqual(foo.getContentType(), 'image/png')
self.assertEqual(foo.data[1:4], 'PNG')
self.assertEqual(foo.width, 23)
self.assertEqual(foo.height, 23)
# also check the generated tag
url = image.absolute_url() + '/image_foo'
tag = '<img src="%s" alt="foo" title="foo" height="23" width="23" />'
self.assertEqual(foo.tag(), tag % url)
# and the other specified size
bar = traverse(image, 'image_bar')
self.assertEqual(bar.getContentType(), 'image/png')
self.assertEqual(bar.data[1:4], 'PNG')
self.assertEqual(bar.width, 6)
self.assertEqual(bar.height, 6)
# make sure the traversal adapter was called in fact
self.assertEqual(self.counter, 2)
def testCustomSizesForNewsItems(self):
# let's also check custom scales work for "News Item" content
data = self.getImage()
folder = self.folder
newsitem = folder[folder.invokeFactory('News Item', id='newsitem', image=data)]
# set custom image sizes
settings = getSettings()
settings.allowed_sizes = [u'foo 23:23']
# make sure traversing works with the new sizes
traverse = folder.REQUEST.traverseName
foo = traverse(newsitem, 'image_foo')
self.assertEqual(foo.getContentType(), 'image/png')
self.assertEqual(foo.data[1:4], 'PNG')
self.assertEqual(foo.width, 23)
self.assertEqual(foo.height, 23)
def testCustomSizesWithSpaces(self):
data = self.getImage()
folder = self.folder
image = folder[folder.invokeFactory('Image', id='foo', image=data)]
# set custom image sizes
settings = getSettings()
settings.allowed_sizes = [u'foo bar 23:23']
# make sure traversing works with the new sizes
traverse = folder.REQUEST.traverseName
foo_bar = traverse(image, 'image_foo_bar')
self.assertEqual(foo_bar.getContentType(), 'image/png')
self.assertEqual(foo_bar.data[1:4], 'PNG')
self.assertEqual(foo_bar.width, 23)
self.assertEqual(foo_bar.height, 23)
# also check the generated tag
url = image.absolute_url() + '/image_foo_bar'
tag = '<img src="%s" alt="foo" title="foo" height="23" width="23" />'
self.assertEqual(foo_bar.tag(), tag % url)
def testScaleInvalidation(self):
data = self.getImage()
folder = self.folder
image = folder[folder.invokeFactory('Image', id='foo', image=data)]
# first view the thumbnail of the original image
traverse = folder.REQUEST.traverseName
thumb1 = traverse(image, 'image_thumb')
# now upload a new one and make sure the thumbnail has changed
image.update(image=self.getImage('image.jpg'))
traverse = folder.REQUEST.traverseName
thumb2 = traverse(image, 'image_thumb')
self.assertFalse(thumb1.data == thumb2.data, 'thumb not updated?')
def testCustomSizeChange(self):
data = self.getImage()
folder = self.folder
image = folder[folder.invokeFactory('Image', id='foo', image=data)]
# set custom image sizes & view a scale
settings = getSettings()
settings.allowed_sizes = [u'foo 23:23']
traverse = folder.REQUEST.traverseName
foo = traverse(image, 'image_foo')
self.assertEqual(foo.width, 23)
self.assertEqual(foo.height, 23)
# now let's update the scale dimensions, after which the scale
# should still be the same...
settings.allowed_sizes = [u'foo 42:42']
foo = traverse(image, 'image_foo')
self.assertEqual(foo.width, 23)
self.assertEqual(foo.height, 23)
# we first need to trigger recreation of all scales...
self.portal.portal_atct.recreateImageScales()
foo = traverse(image, 'image_foo')
self.assertEqual(foo.width, 42)
self.assertEqual(foo.height, 42)
# make sure the traversal adapter was call in fact
self.assertEqual(self.counter, 3)
class ImagePublisherTests(TraverseCounterMixin, ImagingFunctionalTestCase):
def testPublishThumb(self):
data = self.getImage()
folder = self.folder
folder.invokeFactory('Image', id='foo', image=data)
transaction.commit()
# make sure traversing works as is and with scaling
base = folder.absolute_url()
# first the image itself...
browser = self.getBrowser(loggedIn=False)
browser.open(base + '/foo')
self.assertEqual(browser.headers['status'], '200 Ok')
self.assertEqual(browser.contents, data)
self.assertEqual(browser.headers['Content-Type'], 'image/png')
# then the field without a scale name
browser.open(base + '/foo/image')
self.assertEqual(browser.headers['status'], '200 Ok')
self.assertEqual(browser.contents, data)
self.assertEqual(browser.headers['Content-Type'], 'image/png')
# and last a scaled version
# get a authenticated browser session
browser = self.getBrowser()
browser.open(base + '/foo/image_thumb')
self.assertEqual(browser.headers['status'], '200 Ok')
self.assertEqual(browser.contents[1:4], 'PNG')
self.assertEqual(browser.headers['Content-Type'], 'image/png')
# make sure the traversal adapter was call in fact
self.assertEqual(self.counter, 9)
def testPublishCustomSize(self):
data = self.getImage()
folder = self.folder
folder.invokeFactory('Image', id='foo', image=data)
# set custom image sizes
settings = getSettings()
settings.allowed_sizes = [u'foo 23:23']
# make sure traversing works as expected
base = '/'.join(folder.getPhysicalPath())
credentials = self.getCredentials()
response = self.publish(base + '/foo/image_foo', basic=credentials)
self.assertEqual(response.getStatus(), 200)
foo = open(StringIO(response.getBody()))
self.assertEqual(foo.format, 'PNG')
self.assertEqual(foo.size, (23, 23))
# make sure the traversal adapter was call in fact
self.assertEqual(self.counter, 3)
class DefaultAdapterTests(ImagingTestCase):
def afterSetUp(self):
data = self.getImage()
folder = self.folder
self.image = folder[folder.invokeFactory('Image', id='foo', image=data)]
self.field = self.image.getField('image')
self.handler = DefaultImageScaleHandler(self.field)
settings = getSettings()
settings.allowed_sizes = [u'foo 60:60']
def testCreateScale(self):
foo = self.handler.createScale(self.image, 'foo', 100, 80)
self.assertEqual(foo['id'], 'image_foo')
self.assertEqual(foo['content_type'], 'image/png')
self.assertEqual(foo['data'][1:4], 'PNG')
def testCreateScaleWithZeroWidth(self):
foo = self.handler.createScale(self.image, 'foo', 100, 0)
self.assertEqual(foo, None)
def testCreateScaleWithoutData(self):
folder = self.folder
image = folder[folder.invokeFactory('Image', id='image')]
field = image.getField('image')
handler = DefaultImageScaleHandler(field)
foo = handler.createScale(image, 'foo', 100, 80)
self.assertEqual(foo, None)
def testGetScale(self):
foo = self.handler.getScale(self.image, 'foo')
self.assertEqual(foo.getId(), 'image_foo')
self.assertEqual(foo.getContentType(), 'image/png')
self.assertEqual(foo.data[1:4], 'PNG')
self.assertEqual(foo.width, 60)
self.assertEqual(foo.height, 60)
def testGetUnknownScale(self):
foo = self.handler.getScale(self.image, 'foo?')
self.assertEqual(foo, None)
def testScaleThatCausesErrorsCanBeSuppressed(self):
def causeError(*args, **kwargs):
raise Exception
_old_scale = self.field.scale
self.field.scale = causeError
self.field.swallowResizeExceptions = False
self.assertRaises(Exception, self.handler.getScale, self.image, 'foo')
# scaling exceptions should be "swallowed" when set on the field...
self.field.swallowResizeExceptions = True
self.assertEqual(self.handler.getScale(self.image, 'foo'), None)
self.field.scale = _old_scale