unittest_views_basecontrollers.py 29.7 KB
Newer Older
1
2
3
4
5
6
7
"""cubicweb.web.views.basecontrollers unit tests

:organization: Logilab
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
Adrien Di Mascio's avatar
Adrien Di Mascio committed
8
9
import simplejson

10
from logilab.common.testlib import unittest_main, mock_object
Adrien Di Mascio's avatar
Adrien Di Mascio committed
11

12
13
from cubicweb import Binary, NoSelectableObject, ValidationError
from cubicweb.view import STRICT_DOCTYPE
14
from cubicweb.devtools.testlib import CubicWebTC
Sylvain Thénault's avatar
Sylvain Thénault committed
15
from cubicweb.uilib import rql_for_eid
Adrien Di Mascio's avatar
Adrien Di Mascio committed
16
from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect, RequestError
17
from cubicweb.entities.authobjs import CWUser
Adrien Di Mascio's avatar
Adrien Di Mascio committed
18
19


20
class EditControllerTC(CubicWebTC):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
21
    def setUp(self):
22
        CubicWebTC.setUp(self)
23
        self.failUnless('users' in self.schema.eschema('CWGroup').get_groups('read'))
24

Adrien Di Mascio's avatar
Adrien Di Mascio committed
25
    def tearDown(self):
26
        CubicWebTC.tearDown(self)
27
        self.failUnless('users' in self.schema.eschema('CWGroup').get_groups('read'))
28

Adrien Di Mascio's avatar
Adrien Di Mascio committed
29
30
31
    def test_noparam_edit(self):
        """check behaviour of this controller without any form parameter
        """
32
        self.assertRaises(ValidationError, self.publish, self.request())
33

Adrien Di Mascio's avatar
Adrien Di Mascio committed
34
35
    def test_validation_unique(self):
        """test creation of two linked entities
36
        """
Adrien Di Mascio's avatar
Adrien Di Mascio committed
37
        user = self.user()
38
39
40
41
42
43
        req = self.request()
        req.form = {'eid': 'X', '__type:X': 'CWUser',
                    'login:X': u'admin', 'edits-login:X': u'',
                    'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
                    }
        self.assertRaises(ValidationError, self.publish, req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
44
45
46
47
48
49


    def test_user_editing_itself(self):
        """checking that a manager user can edit itself
        """
        user = self.user()
50
51
        basegroups = [str(eid) for eid, in self.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
        groupeids = [eid for eid, in self.execute('CWGroup G WHERE G name in ("managers", "users")')]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
52
53
        groups = [str(eid) for eid in groupeids]
        stateeid = [eid for eid, in self.execute('State S WHERE S name "activated"')][0]
54
55
        req = self.request()
        req.form = {
Adrien Di Mascio's avatar
Adrien Di Mascio committed
56
            'eid':       `user.eid`,
57
            '__type:'+`user.eid`:    'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
58
59
60
61
62
63
64
65
66
67
68
69
            'login:'+`user.eid`:     unicode(user.login),
            'firstname:'+`user.eid`: u'Th\xe9nault',
            'surname:'+`user.eid`:   u'Sylvain',
            'in_group:'+`user.eid`:  groups,
            'in_state:'+`user.eid`:  `stateeid`,
            #
            'edits-login:'+`user.eid`:     unicode(user.login),
            'edits-firstname:'+`user.eid`: u'',
            'edits-surname:'+`user.eid`:   u'',
            'edits-in_group:'+`user.eid`:  basegroups,
            'edits-in_state:'+`user.eid`:  `stateeid`,
            }
70
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
71
72
73
74
75
76
77
78
79
80
81
82
        e = self.execute('Any X WHERE X eid %(x)s', {'x': user.eid}, 'x').get_entity(0, 0)
        self.assertEquals(e.firstname, u'Th\xe9nault')
        self.assertEquals(e.surname, u'Sylvain')
        self.assertEquals(e.login, user.login)
        self.assertEquals([g.eid for g in e.in_group], groupeids)
        self.assertEquals(e.in_state[0].eid, stateeid)

    def test_user_can_change_its_password(self):
        user = self.create_user('user')
        cnx = self.login('user')
        req = self.request()
        req.form = {
83
            'eid': `user.eid`, '__type:'+`user.eid`: 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
84
85
86
87
88
89
90
            '__maineid' : str(user.eid),
            'upassword:'+`user.eid`: 'tournicoton',
            'upassword-confirm:'+`user.eid`: 'tournicoton',
            'edits-upassword:'+`user.eid`:  '',
            }
        path, params = self.expect_redirect_publish(req)
        cnx.commit() # commit to check we don't get late validation error for instance
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
91
        self.assertEquals(path, 'cwuser/user')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
92
93
94
95
96
97
98
        self.failIf('vid' in params)

    def testr_user_editing_itself_no_relation(self):
        """checking we can edit an entity without specifying some required
        relations (meaning no changes)
        """
        user = self.user()
99
        groupeids = [eid for eid, in self.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
100
101
        req = self.request()
        req.form = {
Adrien Di Mascio's avatar
Adrien Di Mascio committed
102
            'eid':       `user.eid`,
103
            '__type:'+`user.eid`:    'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
104
105
106
107
108
109
110
111
            'login:'+`user.eid`:     unicode(user.login),
            'firstname:'+`user.eid`: u'Th\xe9nault',
            'surname:'+`user.eid`:   u'Sylvain',
            #
            'edits-login:'+`user.eid`:     unicode(user.login),
            'edits-firstname:'+`user.eid`: u'',
            'edits-surname:'+`user.eid`:   u'',
            }
112
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
113
114
115
116
117
118
119
        e = self.execute('Any X WHERE X eid %(x)s', {'x': user.eid}, 'x').get_entity(0, 0)
        self.assertEquals(e.login, user.login)
        self.assertEquals(e.firstname, u'Th\xe9nault')
        self.assertEquals(e.surname, u'Sylvain')
        self.assertEquals([g.eid for g in e.in_group], groupeids)
        stateeids = [eid for eid, in self.execute('State S WHERE S name "activated"')]
        self.assertEquals([s.eid for s in e.in_state], stateeids)
120
121


Adrien Di Mascio's avatar
Adrien Di Mascio committed
122
    def test_create_multiple_linked(self):
123
        gueid = self.execute('CWGroup G WHERE G name "users"')[0][0]
124
125
        req = self.request()
        req.form = {'eid': ['X', 'Y'],
126

127
128
129
130
131
                    '__type:X': 'CWUser',
                    '__maineid' : 'X',
                    'login:X': u'adim', 'edits-login:X': u'',
                    'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
                    'surname:X': u'Di Mascio', 'edits-surname:X': '',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
132

133
                    'in_group:X': `gueid`, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
134

135
136
137
138
139
                    '__type:Y': 'EmailAddress',
                    'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
                    'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
                    }
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
140
        # should be redirected on the created person
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
141
        self.assertEquals(path, 'cwuser/adim')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
142
143
144
145
        e = self.execute('Any P WHERE P surname "Di Mascio"').get_entity(0, 0)
        self.assertEquals(e.surname, 'Di Mascio')
        email = e.use_email[0]
        self.assertEquals(email.address, 'dima@logilab.fr')
146

Adrien Di Mascio's avatar
Adrien Di Mascio committed
147
148
    def test_edit_multiple_linked(self):
        peid = self.create_user('adim').eid
149
150
151
152
        req = self.request()
        req.form = {'eid': [`peid`, 'Y'],
                    '__type:%s'%peid: 'CWUser',
                    'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: '',
153

154
155
156
                    '__type:Y': 'EmailAddress',
                    'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
                    'use_email:%s'%peid: 'Y', 'edits-use_email:%s'%peid: INTERNAL_FIELD_VALUE,
157

158
159
160
                    '__redirectrql': 'Any X WHERE X eid %s'%peid,
                    }
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
161
162
163
164
165
166
        # should be redirected on the created person
        eid = params['rql'].split()[-1]
        e = self.execute('Any X WHERE X eid %(x)s', {'x': eid}, 'x').get_entity(0, 0)
        self.assertEquals(e.surname, 'Di Masci')
        email = e.use_email[0]
        self.assertEquals(email.address, 'dima@logilab.fr')
167

Adrien Di Mascio's avatar
Adrien Di Mascio committed
168
        emaileid = email.eid
169
170
        req = self.request()
        req.form = {'eid': [`peid`, `emaileid`],
171
                         '__type:%s'%peid: 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
172
173
174
                         'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: 'Di Masci',
                         '__type:%s'%emaileid: 'EmailAddress',
                         'address:%s'%emaileid: u'adim@logilab.fr', 'edits-address:%s'%emaileid: 'dima@logilab.fr',
175
                         'use_email:%s'%peid: `emaileid`, 'edits-use_email:%s'%peid: `emaileid`,
Adrien Di Mascio's avatar
Adrien Di Mascio committed
176
177
                         '__redirectrql': 'Any X WHERE X eid %s'%peid,
                         }
178
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
179
180
181
182
183
184
185
        # should be redirected on the created person
        eid = params['rql'].split()[-1]
        e = self.execute('Any X WHERE X eid %(x)s', {'x': eid}, 'x').get_entity(0, 0)
        self.assertEquals(e.surname, 'Di Masci')
        email = e.use_email[0]
        self.assertEquals(email.address, 'adim@logilab.fr')

186

Adrien Di Mascio's avatar
Adrien Di Mascio committed
187
188
    def test_password_confirm(self):
        """test creation of two linked entities
189
        """
Adrien Di Mascio's avatar
Adrien Di Mascio committed
190
        user = self.user()
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
        req = self.request()
        req.form = {'__cloned_eid:X': user.eid,
                    'eid': 'X', '__type:X': 'CWUser',
                    'login:X': u'toto', 'edits-login:X': u'',
                    'upassword:X': u'toto', 'edits-upassword:X': u'',
                    }
        self.assertRaises(ValidationError, self.publish, req)
        req = self.request()
        req.form = {'__cloned_eid:X': user.eid,
                    'eid': 'X', '__type:X': 'CWUser',
                    'login:X': u'toto', 'edits-login:X': u'',
                    'upassword:X': u'toto',
                    'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'',
                    }
        self.assertRaises(ValidationError, self.publish, req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
206
207
208


    def test_interval_bound_constraint_success(self):
Sylvain Thénault's avatar
Sylvain Thénault committed
209
        feid = self.execute('INSERT File X: X data_name "toto.txt", X data %(data)s',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
210
                            {'data': Binary('yo')})[0][0]
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
        req = self.request()
        req.form = {'eid': ['X'],
                    '__type:X': 'Salesterm',
                    'amount:X': u'-10', 'edits-amount:X': '',
                    'described_by_test:X': str(feid), 'edits-described_by_test:X': INTERNAL_FIELD_VALUE,
                }
        self.assertRaises(ValidationError, self.publish, req)
        req = self.request()
        req.form = {'eid': ['X'],
                    '__type:X': 'Salesterm',
                    'amount:X': u'110', 'edits-amount:X': '',
                    'described_by_test:X': str(feid), 'edits-described_by_test:X': INTERNAL_FIELD_VALUE,
                    }
        self.assertRaises(ValidationError, self.publish, req)
        req = self.request()
        req.form = {'eid': ['X'],
                    '__type:X': 'Salesterm',
                    'amount:X': u'10', 'edits-amount:X': '',
                    'described_by_test:X': str(feid), 'edits-described_by_test:X': INTERNAL_FIELD_VALUE,
                    }
        self.expect_redirect_publish(req)
232
        # should be redirected on the created
Adrien Di Mascio's avatar
Adrien Di Mascio committed
233
234
235
236
237
238
        #eid = params['rql'].split()[-1]
        e = self.execute('Salesterm X').get_entity(0, 0)
        self.assertEquals(e.amount, 10)

    def test_req_pending_insert(self):
        """make sure req's pending insertions are taken into account"""
Sylvain Thénault's avatar
Sylvain Thénault committed
239
        tmpgroup = self.request().create_entity('CWGroup', name=u"test")
Adrien Di Mascio's avatar
Adrien Di Mascio committed
240
        user = self.user()
241
242
243
        req = self.request()
        req.set_session_data('pending_insert', set([(user.eid, 'in_group', tmpgroup.eid)]))
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
244
245
246
        usergroups = [gname for gname, in
                      self.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
        self.assertUnorderedIterableEquals(usergroups, ['managers', 'test'])
247
        self.assertEquals(req.get_pending_inserts(), [])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
248
249
250
251
252


    def test_req_pending_delete(self):
        """make sure req's pending deletions are taken into account"""
        user = self.user()
253
        groupeid = self.execute('INSERT CWGroup G: G name "test", U in_group G WHERE U eid %(x)s',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
254
255
256
257
258
259
                                {'x': user.eid})[0][0]
        usergroups = [gname for gname, in
                      self.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
        # just make sure everything was set correctly
        self.assertUnorderedIterableEquals(usergroups, ['managers', 'test'])
        # now try to delete the relation
260
261
262
        req = self.request()
        req.set_session_data('pending_delete', set([(user.eid, 'in_group', groupeid)]))
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
263
264
265
        usergroups = [gname for gname, in
                      self.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
        self.assertUnorderedIterableEquals(usergroups, ['managers'])
266
        self.assertEquals(req.get_pending_deletes(), [])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
267
268
269
270
271

    def test_custom_attribute_handler(self):
        def custom_login_edit(self, formparams, value, relations):
            formparams['login'] = value.upper()
            relations.append('X login %(login)s')
272
        CWUser.custom_login_edit = custom_login_edit
Adrien Di Mascio's avatar
Adrien Di Mascio committed
273
274
275
        try:
            user = self.user()
            eid = repr(user.eid)
276
277
            req = self.request()
            req.form = {
Adrien Di Mascio's avatar
Adrien Di Mascio committed
278
                'eid': eid,
279
                '__type:'+eid:  'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
280
281
282
                'login:'+eid: u'foo',
                'edits-login:'+eid:  unicode(user.login),
                }
283
            path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
284
285
286
            rset = self.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x')
            self.assertEquals(rset[0][0], 'FOO')
        finally:
287
            del CWUser.custom_login_edit
288

Adrien Di Mascio's avatar
Adrien Di Mascio committed
289
290
    def test_redirect_apply_button(self):
        redirectrql = rql_for_eid(4012) # whatever
291
292
293
294
295
296
297
298
299
300
301
302
303
        req = self.request()
        req.form = {
            'eid': 'A', '__type:A': 'BlogEntry',
            '__maineid' : 'A',
            'content:A': u'"13:03:43"', 'edits-content:A': '',
            'title:A': u'huuu', 'edits-title:A': '',
            '__redirectrql': redirectrql,
            '__redirectvid': 'primary',
            '__redirectparams': 'toto=tutu&tata=titi',
            '__form_id': 'edition',
            '__action_apply': '',
            }
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
304
305
306
307
308
309
310
311
312
313
        self.failUnless(path.startswith('blogentry/'))
        eid = path.split('/')[1]
        self.assertEquals(params['vid'], 'edition')
        self.assertNotEquals(int(eid), 4012)
        self.assertEquals(params['__redirectrql'], redirectrql)
        self.assertEquals(params['__redirectvid'], 'primary')
        self.assertEquals(params['__redirectparams'], 'toto=tutu&tata=titi')

    def test_redirect_ok_button(self):
        redirectrql = rql_for_eid(4012) # whatever
314
315
316
317
318
319
320
321
322
323
324
325
        req = self.request()
        req.form = {
            'eid': 'A', '__type:A': 'BlogEntry',
            '__maineid' : 'A',
            'content:A': u'"13:03:43"', 'edits-content:A': '',
            'title:A': u'huuu', 'edits-title:A': '',
            '__redirectrql': redirectrql,
            '__redirectvid': 'primary',
            '__redirectparams': 'toto=tutu&tata=titi',
            '__form_id': 'edition',
            }
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
326
327
328
329
330
331
332
        self.assertEquals(path, 'view')
        self.assertEquals(params['rql'], redirectrql)
        self.assertEquals(params['vid'], 'primary')
        self.assertEquals(params['tata'], 'titi')
        self.assertEquals(params['toto'], 'tutu')

    def test_redirect_delete_button(self):
333
        req = self.request()
Sylvain Thénault's avatar
Sylvain Thénault committed
334
        eid = req.create_entity('BlogEntry', title=u'hop', content=u'hop').eid
335
336
337
        req.form = {'eid': str(eid), '__type:%s'%eid: 'BlogEntry',
                    '__action_delete': ''}
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
338
339
        self.assertEquals(path, 'blogentry')
        self.assertEquals(params, {u'__message': u'entity deleted'})
Sylvain Thénault's avatar
Sylvain Thénault committed
340
        eid = req.create_entity('EmailAddress', address=u'hop@logilab.fr').eid
Adrien Di Mascio's avatar
Adrien Di Mascio committed
341
        self.execute('SET X use_email E WHERE E eid %(e)s, X eid %(x)s',
342
                     {'x': self.session.user.eid, 'e': eid}, 'x')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
343
        self.commit()
Sylvain Thénault's avatar
Sylvain Thénault committed
344
        req = req
345
346
347
        req.form = {'eid': str(eid), '__type:%s'%eid: 'EmailAddress',
                    '__action_delete': ''}
        path, params = self.expect_redirect_publish(req)
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
348
        self.assertEquals(path, 'cwuser/admin')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
349
        self.assertEquals(params, {u'__message': u'entity deleted'})
Sylvain Thénault's avatar
Sylvain Thénault committed
350
351
        eid1 = req.create_entity('BlogEntry', title=u'hop', content=u'hop').eid
        eid2 = req.create_entity('EmailAddress', address=u'hop@logilab.fr').eid
352
353
354
355
356
357
        req = self.request()
        req.form = {'eid': [str(eid1), str(eid2)],
                    '__type:%s'%eid1: 'BlogEntry',
                    '__type:%s'%eid2: 'EmailAddress',
                    '__action_delete': ''}
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
358
359
360
361
        self.assertEquals(path, 'view')
        self.assertEquals(params, {u'__message': u'entities deleted'})

    def test_nonregr_egroup_etype_editing(self):
362
        """non-regression test checking that a manager user can edit a CWEType entity (CWGroup)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
363
        """
364
        groupeids = [eid for eid, in self.execute('CWGroup G WHERE G name "managers"')]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
365
        groups = [str(eid) for eid in groupeids]
366
367
        eeetypeeid = self.execute('CWEType X WHERE X name "CWGroup"')[0][0]
        basegroups = [str(eid) for eid, in self.execute('CWGroup G WHERE X read_permission G, X eid %(x)s', {'x': eeetypeeid})]
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
        req = self.request()
        req.form = {
            'eid':      `eeetypeeid`,
            '__type:'+`eeetypeeid`:   'CWEType',
            'name:'+`eeetypeeid`:     u'CWGroup',
            'final:'+`eeetypeeid`:    False,
            'meta:'+`eeetypeeid`:     True,
            'description:'+`eeetypeeid`:     u'users group',
            'read_permission:'+`eeetypeeid`:  groups,
            #
            'edits-name:'+`eeetypeeid`:     u'CWGroup',
            'edits-final:'+`eeetypeeid`:    False,
            'edits-meta:'+`eeetypeeid`:     True,
            'edits-description:'+`eeetypeeid`:     u'users group',
            'edits-read_permission:'+`eeetypeeid`:  basegroups,
            }
Adrien Di Mascio's avatar
Adrien Di Mascio committed
384
        try:
385
            path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
386
            e = self.execute('Any X WHERE X eid %(x)s', {'x': eeetypeeid}, 'x').get_entity(0, 0)
387
            self.assertEquals(e.name, 'CWGroup')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
388
389
390
            self.assertEquals([g.eid for g in e.read_permission], groupeids)
        finally:
            # restore
391
            self.execute('SET X read_permission Y WHERE X name "CWGroup", Y eid IN (%s), NOT X read_permission Y' % (','.join(basegroups)))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
392
            self.commit()
393

Adrien Di Mascio's avatar
Adrien Di Mascio committed
394
    def test_nonregr_eetype_etype_editing(self):
395
        """non-regression test checking that a manager user can edit a CWEType entity (CWEType)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
396
        """
397
        groupeids = sorted(eid for eid, in self.execute('CWGroup G WHERE G name in ("managers", "users")'))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
398
        groups = [str(eid) for eid in groupeids]
399
400
        eeetypeeid = self.execute('CWEType X WHERE X name "CWEType"')[0][0]
        basegroups = [str(eid) for eid, in self.execute('CWGroup G WHERE X read_permission G, X eid %(x)s', {'x': eeetypeeid})]
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
        req = self.request()
        req.form = {
            'eid':      `eeetypeeid`,
            '__type:'+`eeetypeeid`:  'CWEType',
            'name:'+`eeetypeeid`:     u'CWEType',
            'final:'+`eeetypeeid`:    False,
            'meta:'+`eeetypeeid`:     True,
            'description:'+`eeetypeeid`:     u'users group',
            'read_permission:'+`eeetypeeid`:  groups,

            'edits-name:'+`eeetypeeid`:     u'CWEType',
            'edits-final:'+`eeetypeeid`:    False,
            'edits-meta:'+`eeetypeeid`:     True,
            'edits-description:'+`eeetypeeid`:     u'users group',
            'edits-read_permission:'+`eeetypeeid`:  basegroups,
            }
Adrien Di Mascio's avatar
Adrien Di Mascio committed
417
        try:
418
            path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
419
            e = self.execute('Any X WHERE X eid %(x)s', {'x': eeetypeeid}, 'x').get_entity(0, 0)
420
            self.assertEquals(e.name, 'CWEType')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
421
422
423
            self.assertEquals(sorted(g.eid for g in e.read_permission), groupeids)
        finally:
            # restore
424
            self.execute('SET X read_permission Y WHERE X name "CWEType", Y eid IN (%s), NOT X read_permission Y' % (','.join(basegroups)))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
425
            self.commit()
426

Adrien Di Mascio's avatar
Adrien Di Mascio committed
427
428
429
430
    def test_nonregr_strange_text_input(self):
        """non-regression test checking text input containing "13:03:43"

        this seems to be postgres (tsearch?) specific
431
        """
432
433
434
435
436
437
438
        req = self.request()
        req.form = {
            'eid': 'A', '__type:A': 'BlogEntry',
            '__maineid' : 'A',
            'title:A': u'"13:03:40"', 'edits-title:A': '',
            'content:A': u'"13:03:43"', 'edits-content:A': ''}
        path, params = self.expect_redirect_publish(req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
439
440
441
442
443
444
445
446
        self.failUnless(path.startswith('blogentry/'))
        eid = path.split('/')[1]
        e = self.execute('Any C, T WHERE C eid %(x)s, C content T', {'x': eid}, 'x').get_entity(0, 0)
        self.assertEquals(e.title, '"13:03:40"')
        self.assertEquals(e.content, '"13:03:43"')


    def test_nonregr_multiple_empty_email_addr(self):
447
        gueid = self.execute('CWGroup G WHERE G name "users"')[0][0]
448
449
        req = self.request()
        req.form = {'eid': ['X', 'Y'],
450

451
452
453
454
                    '__type:X': 'CWUser',
                    'login:X': u'adim', 'edits-login:X': u'',
                    'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
                    'in_group:X': `gueid`, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
455

456
457
458
459
460
461
                    '__type:Y': 'EmailAddress',
                    'address:Y': u'', 'edits-address:Y': '',
                    'alias:Y': u'', 'edits-alias:Y': '',
                    'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
                    }
        self.assertRaises(ValidationError, self.publish, req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
462
463
464

    def test_nonregr_copy(self):
        user = self.user()
465
466
467
468
469
470
471
472
        req = self.request()
        req.form = {'__cloned_eid:X': user.eid,
                    'eid': 'X', '__type:X': 'CWUser',
                    '__maineid' : 'X',
                    'login:X': u'toto', 'edits-login:X': u'',
                    'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
                    }
        path, params = self.expect_redirect_publish(req)
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
473
        self.assertEquals(path, 'cwuser/toto')
474
        e = self.execute('Any X WHERE X is CWUser, X login "toto"').get_entity(0, 0)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
475
476
477
478
479
480
481
482
483
484
        self.assertEquals(e.login, 'toto')
        self.assertEquals(e.in_group[0].name, 'managers')


    def test_nonregr_rollback_on_validation_error(self):
        p = self.create_user("doe")
        # do not try to skip 'primary_email' for this test
        old_skips = p.__class__.skip_copy_for
        p.__class__.skip_copy_for = ()
        try:
Sylvain Thénault's avatar
Sylvain Thénault committed
485
            e = self.request().create_entity('EmailAddress', address=u'doe@doe.com')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
486
487
            self.execute('SET P use_email E, P primary_email E WHERE P eid %(p)s, E eid %(e)s',
                         {'p' : p.eid, 'e' : e.eid})
488
489
490
491
492
493
            req = self.request()
            req.form = {'__cloned_eid:X': p.eid,
                        'eid': 'X', '__type:X': 'CWUser',
                        'login': u'dodo', 'edits-login': u'dodo',
                        'surname:X': u'Boom', 'edits-surname:X': u'',
                        '__errorurl' : "whatever but required",
Adrien Di Mascio's avatar
Adrien Di Mascio committed
494
495
496
497
498
499
                             }
            # try to emulate what really happens in the web application
            # 1/ validate form => EditController.publish raises a ValidationError
            #    which fires a Redirect
            # 2/ When re-publishing the copy form, the publisher implicitly commits
            try:
500
                self.app.publish('edit', req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
501
            except Redirect:
502
503
504
                req.form['rql'] = 'Any X WHERE X eid %s' % p.eid
                req.form['vid'] = 'copy'
                self.app.publish('view', req)
505
            rset = self.execute('CWUser P WHERE P surname "Boom"')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
506
507
508
509
510
            self.assertEquals(len(rset), 0)
        finally:
            p.__class__.skip_copy_for = old_skips


511
class EmbedControllerTC(CubicWebTC):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
512
513
514
515
516
517
518

    def test_nonregr_embed_publish(self):
        # This test looks a bit stupid but at least it will probably
        # fail if the controller API changes and if EmbedController is not
        # updated (which is what happened before this test)
        req = self.request()
        req.form['url'] = 'http://intranet.logilab.fr/'
519
        controller = self.vreg['controllers'].select('embed', req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
520
521
522
        result = controller.publish(rset=None)


523
class ReportBugControllerTC(CubicWebTC):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
524
525

    def test_usable_by_guets(self):
526
527
        self.login('anon')
        self.vreg['controllers'].select('reportbug', self.request())
Adrien Di Mascio's avatar
Adrien Di Mascio committed
528
529


530
class SendMailControllerTC(CubicWebTC):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
531
532
533

    def test_not_usable_by_guets(self):
        self.login('anon')
534
535
        self.assertRaises(NoSelectableObject,
                          self.vreg['controllers'].select, 'sendmail', self.request())
536

Adrien Di Mascio's avatar
Adrien Di Mascio committed
537
538


539
class JSONControllerTC(CubicWebTC):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
540
541
542

    def ctrl(self, req=None):
        req = req or self.request(url='http://whatever.fr/')
543
        return self.vreg['controllers'].select('json', req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
544
545

    def setup_database(self):
Sylvain Thénault's avatar
Sylvain Thénault committed
546
547
548
        req = self.request()
        self.pytag = req.create_entity('Tag', name=u'python')
        self.cubicwebtag = req.create_entity('Tag', name=u'cubicweb')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
549
550
551
552
553
        self.john = self.create_user(u'John')


    ## tests ##################################################################
    def test_simple_exec(self):
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
554
555
556
557
        req = self.request(rql='CWUser P WHERE P login "John"',
                           pageid='123', fname='view')
        ctrl = self.ctrl(req)
        rset = self.john.as_rset()
558
        rset.req = req
559
560
561
562
563
564
565
        source = ctrl.publish()
        self.failUnless(source.startswith('<?xml version="1.0"?>\n' + STRICT_DOCTYPE +
                                          u'<div xmlns="http://www.w3.org/1999/xhtml" xmlns:cubicweb="http://www.logilab.org/2008/cubicweb">')
                        )
        req.xhtml_browser = lambda: False
        source = ctrl.publish()
        self.failUnless(source.startswith('<div>'))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
566

sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
567
568
569
570
571
#     def test_json_exec(self):
#         rql = 'Any T,N WHERE T is Tag, T name N'
#         ctrl = self.ctrl(self.request(mode='json', rql=rql, pageid='123'))
#         self.assertEquals(ctrl.publish(),
#                           simplejson.dumps(self.execute(rql).rows))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
572
573
574
575
576

    def test_remote_add_existing_tag(self):
        self.remote_call('tag_entity', self.john.eid, ['python'])
        self.assertUnorderedIterableEquals([tname for tname, in self.execute('Any N WHERE T is Tag, T name N')],
                             ['python', 'cubicweb'])
577
        self.assertEquals(self.execute('Any N WHERE T tags P, P is CWUser, T name N').rows,
Adrien Di Mascio's avatar
Adrien Di Mascio committed
578
                          [['python']])
579

Adrien Di Mascio's avatar
Adrien Di Mascio committed
580
581
582
583
    def test_remote_add_new_tag(self):
        self.remote_call('tag_entity', self.john.eid, ['javascript'])
        self.assertUnorderedIterableEquals([tname for tname, in self.execute('Any N WHERE T is Tag, T name N')],
                             ['python', 'cubicweb', 'javascript'])
584
        self.assertEquals(self.execute('Any N WHERE T tags P, P is CWUser, T name N').rows,
Adrien Di Mascio's avatar
Adrien Di Mascio committed
585
586
587
                          [['javascript']])

    def test_pending_insertion(self):
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
588
        res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '13']])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
589
590
591
592
        deletes = req.get_pending_deletes()
        self.assertEquals(deletes, [])
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, ['12:tags:13'])
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
593
        res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
        deletes = req.get_pending_deletes()
        self.assertEquals(deletes, [])
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, ['12:tags:13', '12:tags:14'])
        inserts = req.get_pending_inserts(12)
        self.assertEquals(inserts, ['12:tags:13', '12:tags:14'])
        inserts = req.get_pending_inserts(13)
        self.assertEquals(inserts, ['12:tags:13'])
        inserts = req.get_pending_inserts(14)
        self.assertEquals(inserts, ['12:tags:14'])
        req.remove_pending_operations()

    def test_pending_deletion(self):
        res, req = self.remote_call('add_pending_delete', ['12', 'tags', '13'])
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, [])
        deletes = req.get_pending_deletes()
        self.assertEquals(deletes, ['12:tags:13'])
        res, req = self.remote_call('add_pending_delete', ['12', 'tags', '14'])
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, [])
        deletes = req.get_pending_deletes()
        self.assertEquals(deletes, ['12:tags:13', '12:tags:14'])
        deletes = req.get_pending_deletes(12)
        self.assertEquals(deletes, ['12:tags:13', '12:tags:14'])
        deletes = req.get_pending_deletes(13)
        self.assertEquals(deletes, ['12:tags:13'])
        deletes = req.get_pending_deletes(14)
        self.assertEquals(deletes, ['12:tags:14'])
        req.remove_pending_operations()

    def test_remove_pending_operations(self):
        self.remote_call('add_pending_delete', ['12', 'tags', '13'])
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
627
        _, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
628
629
630
631
632
633
634
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, ['12:tags:14'])
        deletes = req.get_pending_deletes()
        self.assertEquals(deletes, ['12:tags:13'])
        req.remove_pending_operations()
        self.assertEquals(req.get_pending_deletes(), [])
        self.assertEquals(req.get_pending_inserts(), [])
635

Adrien Di Mascio's avatar
Adrien Di Mascio committed
636
637
638
639
640
641
642

    def test_add_inserts(self):
        res, req = self.remote_call('add_pending_inserts',
                                    [('12', 'tags', '13'), ('12', 'tags', '14')])
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, ['12:tags:13', '12:tags:14'])
        req.remove_pending_operations()
643

Adrien Di Mascio's avatar
Adrien Di Mascio committed
644
645
646
647
648
649
650
651
652
653

    # silly tests
    def test_external_resource(self):
        self.assertEquals(self.remote_call('external_resource', 'RSS_LOGO')[0],
                          simplejson.dumps(self.request().external_resource('RSS_LOGO')))
    def test_i18n(self):
        self.assertEquals(self.remote_call('i18n', ['bimboom'])[0],
                          simplejson.dumps(['bimboom']))

    def test_format_date(self):
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
654
        self.assertEquals(self.remote_call('format_date', '2007-01-01 12:00:00')[0],
Adrien Di Mascio's avatar
Adrien Di Mascio committed
655
656
657
                          simplejson.dumps('2007/01/01'))


658
659


Adrien Di Mascio's avatar
Adrien Di Mascio committed
660
661
if __name__ == '__main__':
    unittest_main()