unittest_views_basecontrollers.py 30.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
from cubicweb.devtools.apptest import EnvBasedTC, ControllerTC

13
14
from cubicweb import Binary, NoSelectableObject, ValidationError
from cubicweb.view import STRICT_DOCTYPE
Adrien Di Mascio's avatar
Adrien Di Mascio committed
15
16
17
18
from cubicweb.common.uilib import rql_for_eid

from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect, RequestError

19
from cubicweb.entities.authobjs import CWUser
Adrien Di Mascio's avatar
Adrien Di Mascio committed
20
21
22
23
24


class EditControllerTC(ControllerTC):
    def setUp(self):
        ControllerTC.setUp(self)
25
        self.failUnless('users' in self.schema.eschema('CWGroup').get_groups('read'))
26

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

Adrien Di Mascio's avatar
Adrien Di Mascio committed
31
32
33
    def test_noparam_edit(self):
        """check behaviour of this controller without any form parameter
        """
34

Adrien Di Mascio's avatar
Adrien Di Mascio committed
35
36
        self.req.form = {}
        self.assertRaises(ValidationError, self.publish, self.req)
37

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


    def test_user_editing_itself(self):
        """checking that a manager user can edit itself
        """
        user = self.user()
53
54
        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
55
56
57
58
        groups = [str(eid) for eid in groupeids]
        stateeid = [eid for eid, in self.execute('State S WHERE S name "activated"')][0]
        self.req.form = {
            'eid':       `user.eid`,
59
            '__type:'+`user.eid`:    'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
            '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`,
            }
        path, params = self.expect_redirect_publish()
        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()
84
        #self.assertEquals(self.ctrl.schema['CWUser']._groups['read'],
Adrien Di Mascio's avatar
Adrien Di Mascio committed
85
86
        #                  ('managers', 'users'))
        req.form = {
87
            'eid': `user.eid`, '__type:'+`user.eid`: 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
88
89
90
91
92
93
94
            '__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
95
        self.assertEquals(path, 'cwuser/user')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
96
97
98
99
100
101
102
        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()
103
        groupeids = [eid for eid, in self.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
104
105
        self.req.form = {
            'eid':       `user.eid`,
106
            '__type:'+`user.eid`:    'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
            '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'',
            }
        path, params = self.expect_redirect_publish()
        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)
123
124


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

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

135
136
                         'in_group:X': `gueid`, 'edits-in_group:X': INTERNAL_FIELD_VALUE,

Adrien Di Mascio's avatar
Adrien Di Mascio committed
137
138
                         '__type:Y': 'EmailAddress',
                         'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
139
                         'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
Adrien Di Mascio's avatar
Adrien Di Mascio committed
140
141
142
                         }
        path, params = self.expect_redirect_publish()
        # should be redirected on the created person
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
143
        self.assertEquals(path, 'cwuser/adim')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
144
145
146
147
        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')
148

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

Adrien Di Mascio's avatar
Adrien Di Mascio committed
155
156
157
                         '__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,
158

Adrien Di Mascio's avatar
Adrien Di Mascio committed
159
160
161
162
163
164
165
166
167
                         '__redirectrql': 'Any X WHERE X eid %s'%peid,
                         }
        path, params = self.expect_redirect_publish()
        # 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')
168

Adrien Di Mascio's avatar
Adrien Di Mascio committed
169
170
        emaileid = email.eid
        self.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
178
179
180
181
182
183
184
185
                         '__redirectrql': 'Any X WHERE X eid %s'%peid,
                         }
        path, params = self.expect_redirect_publish()
        # 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
191
        user = self.user()
        self.req.form = {'__cloned_eid:X': user.eid,
192
                         'eid': 'X', '__type:X': 'CWUser',
193
194
                         'login:X': u'toto', 'edits-login:X': u'',
                         'upassword:X': u'toto', 'edits-upassword:X': u'',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
195
196
197
                         }
        self.assertRaises(ValidationError, self.publish, self.req)
        self.req.form = {'__cloned_eid:X': user.eid,
198
                         'eid': 'X', '__type:X': 'CWUser',
199
200
                         'login:X': u'toto', 'edits-login:X': u'',
                         'upassword:X': u'toto', 'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
                         }
        self.assertRaises(ValidationError, self.publish, self.req)


    def test_interval_bound_constraint_success(self):
        feid = self.execute('INSERT File X: X name "toto.txt", X data %(data)s',
                            {'data': Binary('yo')})[0][0]
        self.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, self.req)
        self.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, self.req)
        self.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()
226
        # should be redirected on the created
Adrien Di Mascio's avatar
Adrien Di Mascio committed
227
228
229
230
231
232
        #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"""
233
        tmpgroup = self.add_entity('CWGroup', name=u"test")
Adrien Di Mascio's avatar
Adrien Di Mascio committed
234
235
236
237
238
239
240
241
242
243
244
245
        user = self.user()
        self.req.set_session_data('pending_insert', set([(user.eid, 'in_group', tmpgroup.eid)]))
        path, params = self.expect_redirect_publish()
        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'])
        self.assertEquals(self.req.get_pending_inserts(), [])


    def test_req_pending_delete(self):
        """make sure req's pending deletions are taken into account"""
        user = self.user()
246
        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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
                                {'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
        self.req.set_session_data('pending_delete', set([(user.eid, 'in_group', groupeid)]))
        path, params = self.expect_redirect_publish()
        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'])
        self.assertEquals(self.req.get_pending_deletes(), [])

    def test_custom_attribute_handler(self):
        def custom_login_edit(self, formparams, value, relations):
            formparams['login'] = value.upper()
            relations.append('X login %(login)s')
264
        CWUser.custom_login_edit = custom_login_edit
Adrien Di Mascio's avatar
Adrien Di Mascio committed
265
266
267
268
269
        try:
            user = self.user()
            eid = repr(user.eid)
            self.req.form = {
                'eid': eid,
270
                '__type:'+eid:  'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
271
272
273
274
275
276
277
                'login:'+eid: u'foo',
                'edits-login:'+eid:  unicode(user.login),
                }
            path, params = self.expect_redirect_publish()
            rset = self.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x')
            self.assertEquals(rset[0][0], 'FOO')
        finally:
278
            del CWUser.custom_login_edit
279

Adrien Di Mascio's avatar
Adrien Di Mascio committed
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    def test_redirect_apply_button(self):
        redirectrql = rql_for_eid(4012) # whatever
        self.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()
        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
        self.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()
        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):
        eid = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid
        self.req.form = {'eid': str(eid), '__type:%s'%eid: 'BlogEntry',
                         '__action_delete': ''}
        path, params = self.expect_redirect_publish()
        self.assertEquals(path, 'blogentry')
        self.assertEquals(params, {u'__message': u'entity deleted'})
        eid = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid
        self.execute('SET X use_email E WHERE E eid %(e)s, X eid %(x)s',
                     {'x': self.session().user.eid, 'e': eid}, 'x')
        self.commit()
        self.req.form = {'eid': str(eid), '__type:%s'%eid: 'EmailAddress',
                         '__action_delete': ''}
        path, params = self.expect_redirect_publish()
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
335
        self.assertEquals(path, 'cwuser/admin')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
336
337
338
339
340
341
342
343
344
345
346
347
        self.assertEquals(params, {u'__message': u'entity deleted'})
        eid1 = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid
        eid2 = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid
        self.req.form = {'eid': [str(eid1), str(eid2)],
                         '__type:%s'%eid1: 'BlogEntry',
                         '__type:%s'%eid2: 'EmailAddress',
                         '__action_delete': ''}
        path, params = self.expect_redirect_publish()
        self.assertEquals(path, 'view')
        self.assertEquals(params, {u'__message': u'entities deleted'})

    def test_nonregr_egroup_etype_editing(self):
348
        """non-regression test checking that a manager user can edit a CWEType entity (CWGroup)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
349
        """
350
        groupeids = [eid for eid, in self.execute('CWGroup G WHERE G name "managers"')]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
351
        groups = [str(eid) for eid in groupeids]
352
353
        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})]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
354
355
        self.req.form = {
                'eid':      `eeetypeeid`,
356
357
                '__type:'+`eeetypeeid`:   'CWEType',
                'name:'+`eeetypeeid`:     u'CWGroup',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
358
359
                'final:'+`eeetypeeid`:    False,
                'meta:'+`eeetypeeid`:     True,
360
                'description:'+`eeetypeeid`:     u'users group',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
361
362
                'read_permission:'+`eeetypeeid`:  groups,
                #
363
                'edits-name:'+`eeetypeeid`:     u'CWGroup',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
364
365
                'edits-final:'+`eeetypeeid`:    False,
                'edits-meta:'+`eeetypeeid`:     True,
366
                'edits-description:'+`eeetypeeid`:     u'users group',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
367
368
369
370
371
                'edits-read_permission:'+`eeetypeeid`:  basegroups,
                }
        try:
            path, params = self.expect_redirect_publish()
            e = self.execute('Any X WHERE X eid %(x)s', {'x': eeetypeeid}, 'x').get_entity(0, 0)
372
            self.assertEquals(e.name, 'CWGroup')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
373
374
375
            self.assertEquals([g.eid for g in e.read_permission], groupeids)
        finally:
            # restore
376
            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
377
            self.commit()
378

Adrien Di Mascio's avatar
Adrien Di Mascio committed
379
    def test_nonregr_eetype_etype_editing(self):
380
        """non-regression test checking that a manager user can edit a CWEType entity (CWEType)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
381
        """
382
        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
383
        groups = [str(eid) for eid in groupeids]
384
385
        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})]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
386
387
        self.req.form = {
                'eid':      `eeetypeeid`,
388
389
                '__type:'+`eeetypeeid`:  'CWEType',
                'name:'+`eeetypeeid`:     u'CWEType',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
390
391
                'final:'+`eeetypeeid`:    False,
                'meta:'+`eeetypeeid`:     True,
392
                'description:'+`eeetypeeid`:     u'users group',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
393
394
                'read_permission:'+`eeetypeeid`:  groups,

395
                'edits-name:'+`eeetypeeid`:     u'CWEType',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
396
397
                'edits-final:'+`eeetypeeid`:    False,
                'edits-meta:'+`eeetypeeid`:     True,
398
                'edits-description:'+`eeetypeeid`:     u'users group',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
399
400
401
402
403
                'edits-read_permission:'+`eeetypeeid`:  basegroups,
                }
        try:
            path, params = self.expect_redirect_publish()
            e = self.execute('Any X WHERE X eid %(x)s', {'x': eeetypeeid}, 'x').get_entity(0, 0)
404
            self.assertEquals(e.name, 'CWEType')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
405
406
407
            self.assertEquals(sorted(g.eid for g in e.read_permission), groupeids)
        finally:
            # restore
408
            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
409
            self.commit()
410

Adrien Di Mascio's avatar
Adrien Di Mascio committed
411
412
413
414
    def test_nonregr_strange_text_input(self):
        """non-regression test checking text input containing "13:03:43"

        this seems to be postgres (tsearch?) specific
415
        """
Adrien Di Mascio's avatar
Adrien Di Mascio committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
        self.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()
        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):
430
        gueid = self.execute('CWGroup G WHERE G name "users"')[0][0]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
431
        self.req.form = {'eid': ['X', 'Y'],
432

433
                         '__type:X': 'CWUser',
434
435
436
437
                         '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,

Adrien Di Mascio's avatar
Adrien Di Mascio committed
438
439
440
                         '__type:Y': 'EmailAddress',
                         'address:Y': u'', 'edits-address:Y': '',
                         'alias:Y': u'', 'edits-alias:Y': '',
441
                         'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
Adrien Di Mascio's avatar
Adrien Di Mascio committed
442
443
444
445
446
447
                         }
        self.assertRaises(ValidationError, self.publish, self.req)

    def test_nonregr_copy(self):
        user = self.user()
        self.req.form = {'__cloned_eid:X': user.eid,
448
                         'eid': 'X', '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
449
                         '__maineid' : 'X',
450
451
                         'login:X': u'toto', 'edits-login:X': u'',
                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
452
453
                         }
        path, params = self.expect_redirect_publish()
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
454
        self.assertEquals(path, 'cwuser/toto')
455
        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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
        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:
            e = self.add_entity('EmailAddress', address=u'doe@doe.com')
            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})
            self.req.form = {'__cloned_eid:X': p.eid,
470
                             'eid': 'X', '__type:X': 'CWUser',
471
                             'login': u'dodo', 'edits-login': u'dodo',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
472
473
474
475
476
477
478
479
480
481
482
483
484
                             'surname:X': u'Boom', 'edits-surname:X': u'',
                             '__errorurl' : "whatever but required",
                             }
            # 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:
                self.env.app.publish('edit', self.req)
            except Redirect:
                self.req.form['rql'] = 'Any X WHERE X eid %s' % p.eid
                self.req.form['vid'] = 'copy'
                self.env.app.publish('view', self.req)
485
            rset = self.execute('CWUser P WHERE P surname "Boom"')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
486
487
488
489
490
491
492
493
494
495
496
497
498
            self.assertEquals(len(rset), 0)
        finally:
            p.__class__.skip_copy_for = old_skips


class EmbedControllerTC(EnvBasedTC):

    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/'
499
        controller = self.vreg['controllers'].select('embed', req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
500
501
502
503
504
505
506
        result = controller.publish(rset=None)


class ReportBugControllerTC(EnvBasedTC):

    def test_usable_by_guets(self):
        req = self.request()
507
        self.vreg['controllers'].select('reportbug', req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
508
509
510
511
512
513
514


class SendMailControllerTC(EnvBasedTC):

    def test_not_usable_by_guets(self):
        self.login('anon')
        req = self.request()
515
        self.assertRaises(NoSelectableObject, self.env.vreg['controllers'].select, 'sendmail', req)
516

Adrien Di Mascio's avatar
Adrien Di Mascio committed
517
518
519
520
521
522


class JSONControllerTC(EnvBasedTC):

    def ctrl(self, req=None):
        req = req or self.request(url='http://whatever.fr/')
523
        return self.vreg['controllers'].select('json', req)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
524
525
526
527
528
529
530
531
532

    def setup_database(self):
        self.pytag = self.add_entity('Tag', name=u'python')
        self.cubicwebtag = self.add_entity('Tag', name=u'cubicweb')
        self.john = self.create_user(u'John')


    ## tests ##################################################################
    def test_simple_exec(self):
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
533
534
535
536
        req = self.request(rql='CWUser P WHERE P login "John"',
                           pageid='123', fname='view')
        ctrl = self.ctrl(req)
        rset = self.john.as_rset()
537
        rset.req = req
538
539
540
541
542
543
544
        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
545

sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
546
547
548
549
550
#     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
551
552
553
554
555

    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'])
556
        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
557
                          [['python']])
558

Adrien Di Mascio's avatar
Adrien Di Mascio committed
559
560
561
562
    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'])
563
        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
564
565
566
                          [['javascript']])

    def test_edit_field(self):
567
        nbusers = len(self.execute('CWUser P'))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
568
569
570
        eid = self.john.eid
        self.remote_call('edit_field', 'apply',
                         ('eid', 'firstname:%s' % eid, '__maineid', '__type:%s'% eid, 'edits-firstname:%s' % eid ),
571
                         (str(eid), u'Remi', str(eid), 'CWUser', self.john.firstname),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
572
                         'firstname',
573
                         eid, 'default_value')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
574
        self.commit()
575
        rset = self.execute('CWUser P')
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
576
        # make sure we did not insert a new cwuser here
Adrien Di Mascio's avatar
Adrien Di Mascio committed
577
578
579
580
581
582
583
        self.assertEquals(len(rset), nbusers)
        john = self.execute('Any X WHERE X eid %(x)s', {'x': self.john.eid}, 'x').get_entity(0, 0)
        self.assertEquals(john.eid, self.john.eid)
        self.assertEquals(john.firstname, 'Remi')


    def test_pending_insertion(self):
sylvain.thenault@logilab.fr's avatar
sylvain.thenault@logilab.fr committed
584
        res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '13']])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
585
586
587
588
        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
589
        res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
590
591
592
593
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
        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
623
        _, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
Adrien Di Mascio's avatar
Adrien Di Mascio committed
624
625
626
627
628
629
630
        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(), [])
631

Adrien Di Mascio's avatar
Adrien Di Mascio committed
632
633
634
635
636
637
638

    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()
639

Adrien Di Mascio's avatar
Adrien Di Mascio committed
640
641
642
643
644
645
646
647
648
649

    # 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
650
        self.assertEquals(self.remote_call('format_date', '2007-01-01 12:00:00')[0],
Adrien Di Mascio's avatar
Adrien Di Mascio committed
651
652
653
                          simplejson.dumps('2007/01/01'))


654
655


Adrien Di Mascio's avatar
Adrien Di Mascio committed
656
657
if __name__ == '__main__':
    unittest_main()