File: test_image.py

package info (click to toggle)
odoo 18.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 878,716 kB
  • sloc: javascript: 927,937; python: 685,670; xml: 388,524; sh: 1,033; sql: 415; makefile: 26
file content (159 lines) | stat: -rw-r--r-- 6,546 bytes parent folder | download
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
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import io
import base64

from PIL import Image
from werkzeug.urls import url_unquote_plus

from odoo.tests.common import HttpCase, tagged


@tagged('-at_install', 'post_install')
class TestImage(HttpCase):
    def test_01_content_image_resize_placeholder(self):
        """The goal of this test is to make sure the placeholder image is
        resized appropriately depending on the given URL parameters."""

        # CASE: resize placeholder, given size but original ratio is always kept
        response = self.url_open('/web/image/0/200x150')
        response.raise_for_status()
        image = Image.open(io.BytesIO(response.content))
        self.assertEqual(image.size, (150, 150))

        # CASE: resize placeholder to 128
        response = self.url_open('/web/image/fake/0/image_128')
        response.raise_for_status()
        image = Image.open(io.BytesIO(response.content))
        self.assertEqual(image.size, (128, 128))

        # CASE: resize placeholder to 256
        response = self.url_open('/web/image/fake/0/image_256')
        response.raise_for_status()
        image = Image.open(io.BytesIO(response.content))
        self.assertEqual(image.size, (256, 256))

        # CASE: resize placeholder to 1024 (but placeholder image is too small)
        response = self.url_open('/web/image/fake/0/image_1024')
        response.raise_for_status()
        image = Image.open(io.BytesIO(response.content))
        self.assertEqual(image.size, (256, 256))

        # CASE: no size found, use placeholder original size
        response = self.url_open('/web/image/fake/0/image_no_size')
        response.raise_for_status()
        image = Image.open(io.BytesIO(response.content))
        self.assertEqual(image.size, (256, 256))

    def test_02_content_image_Etag_304(self):
        """This test makes sure that the 304 response is properly returned if the ETag is properly set"""

        attachment = self.env['ir.attachment'].create({
            'datas': b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
            'name': 'testEtag.gif',
            'public': True,
            'mimetype': 'image/gif',
        })
        response = self.url_open('/web/image/%s' % attachment.id, timeout=None)
        response.raise_for_status()
        self.assertEqual(response.status_code, 200)
        self.assertEqual(base64.b64encode(response.content), attachment.datas)

        etag = response.headers.get('ETag')

        response2 = self.url_open('/web/image/%s' % attachment.id, headers={"If-None-Match": etag})
        response2.raise_for_status()
        self.assertEqual(response2.status_code, 304)
        self.assertEqual(len(response2.content), 0)

    def test_03_web_content_filename(self):
        """This test makes sure the Content-Disposition header matches the given filename"""

        att = self.env['ir.attachment'].create({
            'datas': b'R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=',
            'name': 'testFilename.gif',
            'public': True,
            'mimetype': 'image/gif'
        })

        # CASE: no filename given
        res = self.url_open('/web/image/%s/0x0/?download=true' % att.id)
        res.raise_for_status()
        self.assertEqual(res.headers['Content-Disposition'], 'attachment; filename=testFilename.gif')

        # CASE: given filename without extension
        res = self.url_open('/web/image/%s/0x0/custom?download=true' % att.id)
        res.raise_for_status()
        self.assertEqual(res.headers['Content-Disposition'], 'attachment; filename=custom.gif')

        # CASE: given filename and extention
        res = self.url_open('/web/image/%s/0x0/custom.png?download=true' % att.id)
        res.raise_for_status()
        self.assertEqual(res.headers['Content-Disposition'], 'attachment; filename=custom.png')

    def test_04_web_content_filename_secure(self):
        """This test makes sure the Content-Disposition header matches the given filename"""

        att = self.env['ir.attachment'].create({
            'datas': b'R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=',
            'name': """fô☺o-l'éb \n a"!r".gif""",
            'public': True,
            'mimetype': 'image/gif',
        })

        def remove_prefix(text, prefix):
            if text.startswith(prefix):
                return text[len(prefix):]
            return text

        def assert_filenames(
                url,
                expected_filename,
                expected_filename_star='',
                message=r"File that will be saved on disc should have the original filename without \n and \r",
            ):
            res = self.url_open(url)
            res.raise_for_status()
            if expected_filename_star:
                inline, filename, filename_star = res.headers['Content-Disposition'].split('; ')
            else:
                inline, filename = res.headers['Content-Disposition'].split('; ')
                filename_star = ''

            filename = remove_prefix(filename, "filename=").strip('"')
            filename_star = url_unquote_plus(remove_prefix(filename_star, "filename*=UTF-8''").strip('"'))

            self.assertEqual(inline, 'inline')
            self.assertEqual(filename, expected_filename, message)
            self.assertEqual(filename_star, expected_filename_star, message)

        assert_filenames(f'/web/image/{att.id}',
            r"""foo-l'eb _ a\"!r\".gif""",
            r"""fô☺o-l'éb _ a"!r".gif""",
        )
        assert_filenames(f'/web/image/{att.id}/custom_invalid_name\nis-ok.gif',
            r"""custom_invalid_name_is-ok.gif""",
        )
        assert_filenames(f'/web/image/{att.id}/\r\n',
            r"""__.gif""",
        )
        assert_filenames(f'/web/image/{att.id}/你好',
            r""".gif""",
            r"""你好.gif""",
        )
        assert_filenames(f'/web/image/{att.id}/%E9%9D%A2%E5%9B%BE.gif',
            r""".gif""",
            r"""面图.gif""",
        )
        assert_filenames(f'/web/image/{att.id}/hindi_नमस्ते.gif',
            r"""hindi_.gif""",
            r"""hindi_नमस्ते.gif""",
        )
        assert_filenames(f'/web/image/{att.id}/arabic_مرحبا',
            r"""arabic_.gif""",
            r"""arabic_مرحبا.gif""",
        )
        assert_filenames(f'/web/image/{att.id}/4wzb_!!63148-0-t1.jpg_360x1Q75.jpg_.webp',
            r"""4wzb_!!63148-0-t1.jpg_360x1Q75.jpg_.webp""",
        )