unittest_idownloadable.py 6.51 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding: utf-8 -*-
# copyright 2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
#
# CubicWeb is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.

20
from datetime import datetime
21
22
from functools import partial

23
from pytz import utc
24

25
from cubicweb.devtools.testlib import CubicWebTC, real_error_handling
26
from cubicweb.entity import EntityAdapter
27
from cubicweb.predicates import is_instance
28
29
from cubicweb.web import http_headers

30

31
class IDownloadableUser(EntityAdapter):
32
33
    __regid__ = 'IDownloadable'
    __select__ = is_instance('CWUser')
34

35
36
37
    def download_content_type(self):
        """return MIME type of the downloadable content"""
        return 'text/plain'
38

39
40
41
42
43
44
45
46
47
    def download_encoding(self):
        """return encoding of the downloadable content"""
        return 'ascii'

    def download_file_name(self):
        """return file name of the downloadable content"""
        return  self.entity.name() + '.txt'

    def download_data(self):
48
        return b'Babar is not dead!'
49
50


51
52
53
class BrokenIDownloadableGroup(IDownloadableUser):
    __regid__ = 'IDownloadable'
    __select__ = is_instance('CWGroup')
54

55
56
    def download_file_name(self):
        return  self.entity.name + '.txt'
57

58
59
60
61
62
63
64
    def download_data(self):
        raise IOError()

class IDownloadableTC(CubicWebTC):

    def setUp(self):
        super(IDownloadableTC, self).setUp()
65
66
67
68
        self.vreg.register(IDownloadableUser)
        self.addCleanup(partial(self.vreg.unregister, IDownloadableUser))

    def test_header_simple_case(self):
69
70
71
72
73
74
75
76
77
        with self.admin_access.web_request() as req:
            req.form['vid'] = 'download'
            req.form['eid'] = str(req.user.eid)
            data = self.ctrl_publish(req, 'view')
            get = req.headers_out.getRawHeaders
            self.assertEqual(['attachment;filename="admin.txt"'],
                             get('content-disposition'))
            self.assertEqual(['text/plain;charset=ascii'],
                             get('content-type'))
78
79
80
            last_mod = http_headers.parseDateTime(get('last-modified')[0])
            self.assertEqual(datetime.fromtimestamp(last_mod, tz=utc),
                             req.user.modification_date.replace(microsecond=0))
81
            self.assertEqual(b'Babar is not dead!', data)
82

83
    def test_header_with_space(self):
84
85
86
87
        with self.admin_access.web_request() as req:
            self.create_user(req, login=u'c c l a', password='babar')
            req.cnx.commit()
        with self.new_access(u'c c l a').web_request() as req:
88
89
90
91
92
93
94
95
            req.form['vid'] = 'download'
            req.form['eid'] = str(req.user.eid)
            data = self.ctrl_publish(req,'view')
            get = req.headers_out.getRawHeaders
            self.assertEqual(['attachment;filename="c c l a.txt"'],
                             get('content-disposition'))
            self.assertEqual(['text/plain;charset=ascii'],
                             get('content-type'))
96
            self.assertEqual(b'Babar is not dead!', data)
97
98

    def test_header_with_space_and_comma(self):
99
        with self.admin_access.web_request() as req:
Samuel Trégouët's avatar
Samuel Trégouët committed
100
            self.create_user(req, login=u'c " l\\ a', password='babar')
101
            req.cnx.commit()
Samuel Trégouët's avatar
Samuel Trégouët committed
102
        with self.new_access(u'c " l\\ a').web_request() as req:
103
104
105
106
107
108
109
110
            req.form['vid'] = 'download'
            req.form['eid'] = str(req.user.eid)
            data = self.ctrl_publish(req,'view')
            get = req.headers_out.getRawHeaders
            self.assertEqual([r'attachment;filename="c \" l\\ a.txt"'],
                             get('content-disposition'))
            self.assertEqual(['text/plain;charset=ascii'],
                             get('content-type'))
111
            self.assertEqual(b'Babar is not dead!', data)
112

113
    def test_header_unicode_filename(self):
114
115
116
117
        with self.admin_access.web_request() as req:
            self.create_user(req, login=u'cécilia', password='babar')
            req.cnx.commit()
        with self.new_access(u'cécilia').web_request() as req:
118
119
120
121
            req.form['vid'] = 'download'
            req.form['eid'] = str(req.user.eid)
            self.ctrl_publish(req,'view')
            get = req.headers_out.getRawHeaders
122
            self.assertEqual(['''attachment;filename="ccilia.txt";filename*=utf-8''c%C3%A9cilia.txt'''],
123
124
125
126
                             get('content-disposition'))

    def test_header_unicode_long_filename(self):
        name = u'Bèrte_hô_grand_nôm_ça_va_totallement_déborder_de_la_limite_là'
127
128
129
130
        with self.admin_access.web_request() as req:
            self.create_user(req, login=name, password='babar')
            req.cnx.commit()
        with self.new_access(name).web_request() as req:
131
132
133
134
            req.form['vid'] = 'download'
            req.form['eid'] = str(req.user.eid)
            self.ctrl_publish(req,'view')
            get = req.headers_out.getRawHeaders
135
            self.assertEqual(["""attachment;filename="Brte_h_grand_nm_a_va_totallement_dborder_de_la_limite_l.txt";filename*=utf-8''B%C3%A8rte_h%C3%B4_grand_n%C3%B4m_%C3%A7a_va_totallement_d%C3%A9border_de_la_limite_l%C3%A0.txt"""],
136
137
                             get('content-disposition'))

138
139
140
141

    def test_download_data_error(self):
        self.vreg.register(BrokenIDownloadableGroup)
        self.addCleanup(partial(self.vreg.unregister, BrokenIDownloadableGroup))
142
143
144
        with self.admin_access.web_request() as req:
            req.form['vid'] = 'download'
            req.form['eid'] = str(req.execute('CWGroup X WHERE X name "managers"')[0][0])
145
            with real_error_handling(self.app):
146
147
148
149
150
151
152
                data = self.app_handle_request(req)
            get = req.headers_out.getRawHeaders
            self.assertEqual(['text/html;charset=UTF-8'],
                             get('content-type'))
            self.assertEqual(None,
                             get('content-disposition'))
            self.assertEqual(req.status_out, 500)
153

154
if __name__ == '__main__':
155
156
    from unittest import main
    main()