TestModel   B
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 39
c 6
b 0
f 0
dl 0
loc 108
rs 8.2857

8 Methods

Rating   Name   Duplication   Size   Complexity  
A test_variations_override() 0 12 3
A test_fore_min_size() 0 6 2
A test_thumbnail_save_without_directory() 0 11 3
A test_cropping() 0 6 3
A test_delete_thumbnail() 0 11 3
A test_custom_render_variations() 0 7 3
B test_simple() 0 14 6
F test_variations() 0 31 16
1
# coding: utf-8
2
from __future__ import absolute_import, unicode_literals
3
4
import io
5
6
import os
7
import pytest
8
import uuid
9
10
from PIL import Image
11
from django.core.files.storage import default_storage
12
from django.core.files.uploadedfile import SimpleUploadedFile
13
14
15
class UUID4Monkey:
16
    hex = '653d1c6863404b9689b75fa930c9d0a0'
17
18
19
uuid.__dict__['uuid4'] = lambda: UUID4Monkey()
20
21
import django  # NoQA
22
from django.conf import settings  # NoQA
23
24
from .models import (
25
    SimpleModel, ResizeModel, AdminDeleteModel,
26
    ThumbnailModel, ResizeCropModel, AutoSlugClassNameDirModel,
27
    UUIDModel,
28
    UtilVariationsModel,
29
    ThumbnailWithoutDirectoryModel,
30
    CustomRenderVariationsModel)  # NoQA
31
32
IMG_DIR = os.path.join(settings.MEDIA_ROOT, 'img')
33
FIXTURES = [
34
    ('100.gif', 'GIF', 100, 100),
35
    ('600x400.gif', 'GIF', 600, 400),
36
    ('600x400.jpg', 'JPEG', 600, 400),
37
    ('600x400.jpg', 'PNG', 600, 400),
38
]
39
40
41
class TestStdImage:
42
    fixtures = {}
43
44
    @pytest.fixture(autouse=True)
45
    def setup(self):
46
        for fixture_filename, img_format, width, height in FIXTURES:
47
            with io.BytesIO() as f:
48
                img = Image.new('RGB', (width, height), (255, 55, 255))
49
                img.save(f, format=img_format)
50
                suf = SimpleUploadedFile(fixture_filename, f.getvalue())
51
                self.fixtures[fixture_filename] = suf
52
53
        yield
54
55
        for root, dirs, files in os.walk(settings.MEDIA_ROOT, topdown=False):
56
            for name in files:
57
                os.remove(os.path.join(root, name))
58
            for name in dirs:
59
                os.rmdir(os.path.join(root, name))
60
61
62
class TestModel(TestStdImage):
63
    """Tests StdImage ModelField"""
64
65
    def test_simple(self, db):
66
        """Tests if Field behaves just like Django's ImageField."""
67
        instance = SimpleModel.objects.create(image=self.fixtures['100.gif'])
68
        target_file = os.path.join(IMG_DIR, '100.gif')
69
        source_file = self.fixtures['100.gif']
70
71
        assert SimpleModel.objects.count() == 1
72
        assert SimpleModel.objects.get(pk=1) == instance
73
74
        assert os.path.exists(target_file)
75
76
        with open(target_file, 'rb') as f:
77
            source_file.seek(0)
78
            assert source_file.read() == f.read()
79
80
    def test_variations(self, db):
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 = self.fixtures['600x400.jpg']
87
88
        assert os.path.exists(os.path.join(IMG_DIR, 'image.jpg'))
89
        assert instance.image.width == 600
90
        assert instance.image.height == 400
91
        path = os.path.join(IMG_DIR, 'image.jpg')
92
93
        with open(path, 'rb') as f:
94
            source_file.seek(0)
95
            assert source_file.read() == f.read()
96
97
        path = os.path.join(IMG_DIR, 'image.medium.jpg')
98
        assert os.path.exists(path)
99
        assert instance.image.medium.width == 400
100
        assert instance.image.medium.height <= 400
101
        with open(os.path.join(IMG_DIR, 'image.medium.jpg'), 'rb') as f:
102
            source_file.seek(0)
103
            assert source_file.read() != f.read()
104
105
        assert os.path.exists(os.path.join(IMG_DIR, 'image.thumbnail.jpg'))
106
        assert instance.image.thumbnail.width == 100
107
        assert instance.image.thumbnail.height <= 75
108
        with open(os.path.join(IMG_DIR, 'image.thumbnail.jpg'), 'rb') as f:
109
            source_file.seek(0)
110
            assert source_file.read() != f.read()
111
112
    def test_cropping(self, db):
113
        instance = ResizeCropModel.objects.create(
114
            image=self.fixtures['600x400.jpg']
115
        )
116
        assert instance.image.thumbnail.width == 150
117
        assert instance.image.thumbnail.height == 150
118
119
    def test_variations_override(self, db):
120
        source_file = self.fixtures['600x400.jpg']
121
        target_file = os.path.join(IMG_DIR, 'image.thumbnail.jpg')
122
        os.mkdir(IMG_DIR)
123
        default_storage.save(target_file, source_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, db):
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_fore_min_size(self, admin_client):
145
        admin_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_thumbnail_save_without_directory(self, db):
152
        obj = ThumbnailWithoutDirectoryModel.objects.create(
153
            image=self.fixtures['100.gif']
154
        )
155
        obj.save()
156
        # Our model saves the images directly into the MEDIA_ROOT directory
157
        # not IMG_DIR, under a custom name
158
        original = os.path.join(settings.MEDIA_ROOT, 'custom.gif')
159
        thumbnail = os.path.join(settings.MEDIA_ROOT, 'custom.thumbnail.gif')
160
        assert os.path.exists(original)
161
        assert os.path.exists(thumbnail)
162
163
    def test_custom_render_variations(self, db):
164
        instance = CustomRenderVariationsModel.objects.create(
165
            image=self.fixtures['600x400.jpg']
166
        )
167
        # Image size must be 100x100 despite variations settings
168
        assert instance.image.thumbnail.width == 100
169
        assert instance.image.thumbnail.height == 100
170
171
172
class TestUtils(TestStdImage):
173
    """Tests Utils"""
174
175
    def test_deletion_singnal_receiver(self, db):
176
        obj = SimpleModel.objects.create(
177
            image=self.fixtures['100.gif']
178
        )
179
        obj.delete()
180
        assert not os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
181
182
    def test_pre_save_delete_callback_clear(self, admin_client):
183
        AdminDeleteModel.objects.create(
184
            image=self.fixtures['100.gif']
185
        )
186
        if django.VERSION >= (1, 9):
187
            admin_client.post('/admin/tests/admindeletemodel/1/change/', {
188
                'image-clear': 'checked',
189
            })
190
        else:
191
            admin_client.post('/admin/tests/admindeletemodel/1/', {
192
                'image-clear': 'checked',
193
            })
194
        assert not os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
195
196
    def test_pre_save_delete_callback_new(self, admin_client):
197
        AdminDeleteModel.objects.create(
198
            image=self.fixtures['100.gif']
199
        )
200
        if django.VERSION >= (1, 9):
201
            admin_client.post('/admin/tests/admindeletemodel/1/change/', {
202
                'image': self.fixtures['600x400.jpg'],
203
            })
204
        else:
205
            admin_client.post('/admin/tests/admindeletemodel/1/', {
206
                'image': self.fixtures['600x400.jpg'],
207
            })
208
        assert not os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
209
210
    def test_upload_to_auto_slug_class_name_dir(self, db):
211
        AutoSlugClassNameDirModel.objects.create(
212
            name='foo bar',
213
            image=self.fixtures['100.gif']
214
        )
215
        file_path = os.path.join(
216
            settings.MEDIA_ROOT,
217
            'autoslugclassnamedirmodel',
218
            'foo-bar.gif'
219
        )
220
        assert os.path.exists(file_path)
221
222
    def test_upload_to_uuid(self, db):
223
        UUIDModel.objects.create(image=self.fixtures['100.gif'])
224
        file_path = os.path.join(
225
            IMG_DIR,
226
            '653d1c6863404b9689b75fa930c9d0a0.gif'
227
        )
228
        assert os.path.exists(file_path)
229
230
    def test_render_variations_callback(self, db):
231
        UtilVariationsModel.objects.create(image=self.fixtures['100.gif'])
232
        file_path = os.path.join(
233
            IMG_DIR,
234
            'image.thumbnail.gif'
235
        )
236
        assert os.path.exists(file_path)
237
238
239
class TestValidators(TestStdImage):
240
    def test_max_size_validator(self, admin_client):
241
        admin_client.post('/admin/tests/maxsizemodel/add/', {
242
            'image': self.fixtures['600x400.jpg'],
243
        })
244
        assert not os.path.exists(os.path.join(IMG_DIR, 'image.jpg'))
245
246
    def test_min_size_validator(self, admin_client):
247
        admin_client.post('/admin/tests/minsizemodel/add/', {
248
            'image': self.fixtures['100.gif'],
249
        })
250
        assert not os.path.exists(os.path.join(IMG_DIR, 'image.gif'))
251