Completed
Push — master ( 84e615...a5de1a )
by Johannes
01:08
created

TestModel.test_variations()   B

Complexity

Conditions 3

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

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