Completed
Pull Request — master (#102)
by
unknown
01:19
created

TestModel.test_cropping()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
1
# coding: utf-8
2
from __future__ import absolute_import, unicode_literals
3
4
import filecmp
5
import os
6
import shutil
7
import uuid
8
9
10
class UUID4Monkey(object):
11
    hex = '653d1c6863404b9689b75fa930c9d0a0'
12
13
14
uuid.__dict__['uuid4'] = lambda: UUID4Monkey()
15
16
import django  # NoQA
17
from django.conf import settings  # NoQA
18
from django.core.files import File  # NoQA
19
from django.test import TestCase  # NoQA
20
from django.contrib.auth.models import User  # NoQA
21
22
from stdimage.models import StdImageFieldFile  # NoQA
23
from .models import (
24
    SimpleModel, ResizeModel, AdminDeleteModel,
25
    ThumbnailModel, ResizeCropModel, AutoSlugClassNameDirModel,
26
    UUIDModel,
27
    UtilVariationsModel,
28
    ThumbnailWithoutDirectoryModel,
29
    CustomRenderVariationsModel, ProgressiveJpegModel)  # NoQA
30
31
IMG_DIR = os.path.join(settings.MEDIA_ROOT, 'img')
32
33
FIXTURE_DIR = os.path.join(
34
    os.path.dirname(os.path.abspath(__file__)),
35
    'fixtures'
36
)
37
38
39
class TestStdImage(TestCase):
40
    def setUp(self):
41
        User.objects.create_superuser('admin', '[email protected]', 'admin')
42
        self.client.login(username='admin', password='admin')
43
44
        self.fixtures = {}
45
        fixture_paths = os.listdir(FIXTURE_DIR)
46
        for fixture_filename in fixture_paths:
47
            fixture_path = os.path.join(FIXTURE_DIR, fixture_filename)
48
            if os.path.isfile(fixture_path):
49
                f = open(fixture_path, 'rb')
50
                self.fixtures[fixture_filename] = File(f)
51
52
    def tearDown(self):
53
        """Close all open fixtures and delete everything from media"""
54
        for fixture in list(self.fixtures.values()):
55
            fixture.close()
56
57
        for root, dirs, files in os.walk(settings.MEDIA_ROOT, topdown=False):
58
            for name in files:
59
                os.remove(os.path.join(root, name))
60
            for name in dirs:
61
                os.rmdir(os.path.join(root, name))
62
63
64
class TestModel(TestStdImage):
65
    """Tests StdImage ModelField"""
66
67
    def test_simple(self):
68
        """Tests if Field behaves just like Django's ImageField."""
69
        instance = SimpleModel.objects.create(image=self.fixtures['100.gif'])
70
        target_file = os.path.join(IMG_DIR, '100.gif')
71
        source_file = os.path.join(FIXTURE_DIR, '100.gif')
72
73
        self.assertEqual(SimpleModel.objects.count(), 1)
74
        self.assertEqual(SimpleModel.objects.get(pk=1), instance)
75
76
        self.assertTrue(os.path.exists(target_file))
77
78
        self.assertTrue(filecmp.cmp(source_file, target_file))
79
80
    def test_variations(self):
81
        """Adds image and checks filesystem as well as width and height."""
82
        instance = ResizeModel.objects.create(
83
            image=self.fixtures['600x400.jpg']
84
        )
85
86
        source_file = os.path.join(FIXTURE_DIR, '600x400.jpg')
87
88
        self.assertTrue(os.path.exists(os.path.join(IMG_DIR, 'image.jpg')))
89
        self.assertEqual(instance.image.width, 600)
90
        self.assertEqual(instance.image.height, 400)
91
        path = os.path.join(IMG_DIR, 'image.jpg')
92
        assert filecmp.cmp(source_file, path)
93
94
        path = os.path.join(IMG_DIR, 'image.medium.jpg')
95
        assert os.path.exists(path)
96
        self.assertEqual(instance.image.medium.width, 400)
97
        self.assertLessEqual(instance.image.medium.height, 400)
98
        self.assertFalse(filecmp.cmp(
99
            source_file,
100
            os.path.join(IMG_DIR, 'image.medium.jpg')))
101
102
        self.assertTrue(os.path.exists(
103
            os.path.join(IMG_DIR, 'image.thumbnail.jpg'))
104
        )
105
        self.assertEqual(instance.image.thumbnail.width, 100)
106
        self.assertLessEqual(instance.image.thumbnail.height, 75)
107
        self.assertFalse(filecmp.cmp(
108
            source_file,
109
            os.path.join(IMG_DIR, 'image.thumbnail.jpg'))
110
        )
111
112
    def test_cropping(self):
113
        instance = ResizeCropModel.objects.create(
114
            image=self.fixtures['600x400.jpg']
115
        )
116
        self.assertEqual(instance.image.thumbnail.width, 150)
117
        self.assertEqual(instance.image.thumbnail.height, 150)
118
119
    def test_variations_override(self):
120
        source_file = os.path.join(FIXTURE_DIR, '600x400.jpg')
121
        target_file = os.path.join(IMG_DIR, 'image.thumbnail.jpg')
122
        os.mkdir(IMG_DIR)
123
        shutil.copyfile(source_file, target_file)
124
        ResizeModel.objects.create(
125
            image=self.fixtures['600x400.jpg']
126
        )
127
        thumbnail_path = os.path.join(IMG_DIR, 'image.thumbnail.jpg')
128
        assert os.path.exists(thumbnail_path)
129
        thumbnail_path = os.path.join(IMG_DIR, 'image.thumbnail_1.jpg')
130
        assert not os.path.exists(thumbnail_path)
131
132
    def test_delete_thumbnail(self):
133
        """Delete an image with thumbnail"""
134
        obj = ThumbnailModel.objects.create(
135
            image=self.fixtures['100.gif']
136
        )
137
        obj.image.delete()
138
        path = os.path.join(IMG_DIR, 'image.gif')
139
        assert not os.path.exists(path)
140
141
        path = os.path.join(IMG_DIR, 'image.thumbnail.gif')
142
        assert not os.path.exists(path)
143
144
    def test_force_min_size(self):
145
        self.client.post('/admin/tests/forceminsizemodel/add/', {
146
            'image': self.fixtures['100.gif'],
147
        })
148
        path = os.path.join(IMG_DIR, 'image.gif')
149
        assert not os.path.exists(path)
150
151
    def test_progressive_jpeg_from_jpeg(self):
152
        instance = ProgressiveJpegModel.objects.create(
153
            image=self.fixtures['600x400.jpg']
154
        )
155
        progressive_path = os.path.join(IMG_DIR, 'image.progressive.jpg')
156
        assert os.path.exists(progressive_path)
157
158
        assert instance.image.progressive.url == 'img/image.progressive.jpg'
159
160
    def test_progressive_jpeg_from_png(self):
161
        instance = ProgressiveJpegModel.objects.create(
162
            image=self.fixtures['600x400.png']
163
        )
164
        progressive_path = os.path.join(IMG_DIR, 'image.progressive.jpg')
165
        assert os.path.exists(progressive_path)
166
167
        progressive_path = os.path.join(IMG_DIR, 'image.progressive.png')
168
        assert not os.path.exists(progressive_path)
169
170
        assert instance.image.progressive.url == 'img/image.progressive.jpg'
171
172
    def test_progressive_jpeg_from_gif(self):
173
        instance = ProgressiveJpegModel.objects.create(
174
            image=self.fixtures['600x400.gif']
175
        )
176
        progressive_path = os.path.join(IMG_DIR, 'image.progressive.jpg')
177
        assert os.path.exists(progressive_path)
178
179
        progressive_path = os.path.join(IMG_DIR, 'image.progressive.gif')
180
        assert not os.path.exists(progressive_path)
181
182
        assert instance.image.progressive.url == 'img/image.progressive.jpg'
183
184
    def test_thumbnail_save_without_directory(self):
185
        obj = ThumbnailWithoutDirectoryModel.objects.create(
186
            image=self.fixtures['100.gif']
187
        )
188
        obj.save()
189
        # Our model saves the images directly into the MEDIA_ROOT directory
190
        # not IMG_DIR, under a custom name
191
        original = os.path.join(settings.MEDIA_ROOT, 'custom.gif')
192
        thumbnail = os.path.join(settings.MEDIA_ROOT, 'custom.thumbnail.gif')
193
        assert os.path.exists(original)
194
        assert os.path.exists(thumbnail)
195
196
    def test_custom_render_variations(self):
197
        instance = CustomRenderVariationsModel.objects.create(
198
            image=self.fixtures['600x400.jpg']
199
        )
200
        # Image size must be 100x100 despite variations settings
201
        assert instance.image.thumbnail.width == 100
202
        assert instance.image.thumbnail.height == 100
203
204
    def test_get_variation_name(self):
205
        self.assertEqual(
206
            StdImageFieldFile.get_variation_name('foobar.png', 'test'),
207
            'foobar.test.png')
208
209
        self.assertEqual(
210
            StdImageFieldFile.get_variation_name('foobar.png',
211
                                                 {'name': 'test'}),
212
            'foobar.test.png')
213
214
        self.assertEqual(
215
            StdImageFieldFile.get_variation_name(
216
                'foobar.png',
217
                {'name': 'test', 'is_progressive_jpeg': True}
218
            ),
219
            'foobar.test.jpg')
220
221
222
class TestUtils(TestStdImage):
223
    """Tests Utils"""
224
225
    def test_deletion_singnal_receiver(self):
226
        obj = SimpleModel.objects.create(
227
            image=self.fixtures['100.gif']
228
        )
229
        obj.delete()
230
        self.assertFalse(
231
            os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
232
        )
233
234
    def test_pre_save_delete_callback_clear(self):
235
        AdminDeleteModel.objects.create(
236
            image=self.fixtures['100.gif']
237
        )
238
        if django.VERSION >= (1, 9):
239
            self.client.post('/admin/tests/admindeletemodel/1/change/', {
240
                'image-clear': 'checked',
241
            })
242
        else:
243
            self.client.post('/admin/tests/admindeletemodel/1/', {
244
                'image-clear': 'checked',
245
            })
246
        self.assertFalse(
247
            os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
248
        )
249
250
    def test_pre_save_delete_callback_new(self):
251
        AdminDeleteModel.objects.create(
252
            image=self.fixtures['100.gif']
253
        )
254
        if django.VERSION >= (1, 9):
255
            self.client.post('/admin/tests/admindeletemodel/1/change/', {
256
                'image': self.fixtures['600x400.jpg'],
257
            })
258
        else:
259
            self.client.post('/admin/tests/admindeletemodel/1/', {
260
                'image': self.fixtures['600x400.jpg'],
261
            })
262
        self.assertFalse(
263
            os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
264
        )
265
266
    def test_upload_to_auto_slug_class_name_dir(self):
267
        AutoSlugClassNameDirModel.objects.create(
268
            name='foo bar',
269
            image=self.fixtures['100.gif']
270
        )
271
        file_path = os.path.join(
272
            settings.MEDIA_ROOT,
273
            'autoslugclassnamedirmodel',
274
            'foo-bar.gif'
275
        )
276
        self.assertTrue(os.path.exists(file_path))
277
278
    def test_upload_to_uuid(self):
279
        UUIDModel.objects.create(image=self.fixtures['100.gif'])
280
        file_path = os.path.join(
281
            IMG_DIR,
282
            '653d1c6863404b9689b75fa930c9d0a0.gif'
283
        )
284
        self.assertTrue(os.path.exists(file_path))
285
286
    def test_render_variations_callback(self):
287
        UtilVariationsModel.objects.create(image=self.fixtures['100.gif'])
288
        file_path = os.path.join(
289
            IMG_DIR,
290
            'image.thumbnail.gif'
291
        )
292
        self.assertTrue(os.path.exists(file_path))
293
294
295
class TestValidators(TestStdImage):
296
    def test_max_size_validator(self):
297
        self.client.post('/admin/tests/maxsizemodel/add/', {
298
            'image': self.fixtures['600x400.jpg'],
299
        })
300
        self.assertFalse(os.path.exists(os.path.join(IMG_DIR, 'image.jpg')))
301
302
    def test_min_size_validator(self):
303
        self.client.post('/admin/tests/minsizemodel/add/', {
304
            'image': self.fixtures['100.gif'],
305
        })
306
        self.assertFalse(os.path.exists(os.path.join(IMG_DIR, 'image.gif')))
307