unittest_views_basecontrollers.py 30.5 KB
Newer Older
Adrien Di Mascio's avatar
Adrien Di Mascio committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""cubicweb.web.views.basecontrollers unit tests"""
import simplejson

from logilab.common.testlib import unittest_main

from cubicweb import Binary, Unauthorized
from cubicweb.devtools._apptest import TestEnvironment
from cubicweb.devtools.apptest import EnvBasedTC, ControllerTC

from cubicweb.common import ValidationError
from cubicweb.common.uilib import rql_for_eid

from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect, RequestError
from cubicweb.web.views.basecontrollers import xmlize

16
from cubicweb.entities.authobjs import CWUser
Adrien Di Mascio's avatar
Adrien Di Mascio committed
17
18
19
20
21


class EditControllerTC(ControllerTC):
    def setUp(self):
        ControllerTC.setUp(self)
22
        self.failUnless('users' in self.schema.eschema('CWGroup').get_groups('read'))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
23
24
25
        
    def tearDown(self):
        ControllerTC.tearDown(self)
26
        self.failUnless('users' in self.schema.eschema('CWGroup').get_groups('read'))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
27
28
29
30
31
32
33
34
35
36
37
38
        
    def test_noparam_edit(self):
        """check behaviour of this controller without any form parameter
        """
        
        self.req.form = {}
        self.assertRaises(ValidationError, self.publish, self.req)
        
    def test_validation_unique(self):
        """test creation of two linked entities
        """        
        user = self.user()
39
        self.req.form = {'eid': 'X', '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
40
41
42
43
44
45
46
47
48
49
                         '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, self.req)


    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
54
55
        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`,
56
            '__type:'+`user.eid`:    'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
            '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()
81
        #self.assertEquals(self.ctrl.schema['CWUser']._groups['read'],
Adrien Di Mascio's avatar
Adrien Di Mascio committed
82
83
        #                  ('managers', 'users'))
        req.form = {
84
            'eid': `user.eid`, '__type:'+`user.eid`: 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
            '__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
        self.assertEquals(path, 'euser/user')
        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()
100
        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
101
102
        self.req.form = {
            '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
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)
        
        
    def test_create_multiple_linked(self):
123
        gueid = self.execute('CWGroup G WHERE G name "users"')[0][0]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
124
125
        self.req.form = {'eid': ['X', 'Y'],
                         
126
                         '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
                         '__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': '',

                         'in_group:X': `gueid`, 'edits-in_group:X': INTERNAL_FIELD_VALUE, 
                         
                         '__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()
        # should be redirected on the created person
        self.assertEquals(path, 'euser/adim')
        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')
        
    def test_edit_multiple_linked(self):
        peid = self.create_user('adim').eid
        self.req.form = {'eid': [`peid`, 'Y'],
149
                         '__type:%s'%peid: 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
                         'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: '',
                         
                         '__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,
                         
                         '__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')
        
        emaileid = email.eid
        self.req.form = {'eid': [`peid`, `emaileid`],
168
                         '__type:%s'%peid: 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
                         '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',
                         'use_email:%s'%peid: `emaileid`, 'edits-use_email:%s'%peid: `emaileid`, 
                         '__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')

        
    def test_password_confirm(self):
        """test creation of two linked entities
        """        
        user = self.user()
        self.req.form = {'__cloned_eid:X': user.eid,
189
                         'eid': 'X', '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
190
191
192
193
194
                         'login:X': u'toto', 'edits-login:X': u'', 
                         'upassword:X': u'toto', 'edits-upassword:X': u'', 
                         }
        self.assertRaises(ValidationError, self.publish, self.req)
        self.req.form = {'__cloned_eid:X': user.eid,
195
                         'eid': 'X', '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
196
197
198
199
200
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
226
227
228
229
                         '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, 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()
        # should be redirected on the created 
        #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"""
230
        tmpgroup = self.add_entity('CWGroup', name=u"test")
Adrien Di Mascio's avatar
Adrien Di Mascio committed
231
232
233
234
235
236
237
238
239
240
241
242
        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()
243
        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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
                                {'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')
261
        CWUser.custom_login_edit = custom_login_edit
Adrien Di Mascio's avatar
Adrien Di Mascio committed
262
263
264
265
266
        try:
            user = self.user()
            eid = repr(user.eid)
            self.req.form = {
                'eid': eid,
267
                '__type:'+eid:  'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
268
269
270
271
272
273
274
                '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:
275
            del CWUser.custom_login_edit
Adrien Di Mascio's avatar
Adrien Di Mascio committed
276
277
278
279
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
335
336
337
338
339
340
341
342
343
344
        
    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()
        self.assertEquals(path, 'euser/admin')
        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):
345
        """non-regression test checking that a manager user can edit a CWEType entity (CWGroup)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
346
        """
347
        groupeids = [eid for eid, in self.execute('CWGroup G WHERE G name "managers"')]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
348
        groups = [str(eid) for eid in groupeids]
349
350
        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
351
352
        self.req.form = {
                'eid':      `eeetypeeid`,
353
354
                '__type:'+`eeetypeeid`:   'CWEType',
                'name:'+`eeetypeeid`:     u'CWGroup',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
355
356
357
358
359
                'final:'+`eeetypeeid`:    False,
                'meta:'+`eeetypeeid`:     True,
                'description:'+`eeetypeeid`:     u'users group', 
                'read_permission:'+`eeetypeeid`:  groups,
                #
360
                'edits-name:'+`eeetypeeid`:     u'CWGroup',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
361
362
363
364
365
366
367
368
                'edits-final:'+`eeetypeeid`:    False,
                'edits-meta:'+`eeetypeeid`:     True,
                'edits-description:'+`eeetypeeid`:     u'users group', 
                '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)
369
            self.assertEquals(e.name, 'CWGroup')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
370
371
372
            self.assertEquals([g.eid for g in e.read_permission], groupeids)
        finally:
            # restore
373
            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
374
375
376
            self.commit()
            
    def test_nonregr_eetype_etype_editing(self):
377
        """non-regression test checking that a manager user can edit a CWEType entity (CWEType)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
378
        """
379
        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
380
        groups = [str(eid) for eid in groupeids]
381
382
        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
383
384
        self.req.form = {
                'eid':      `eeetypeeid`,
385
386
                '__type:'+`eeetypeeid`:  'CWEType',
                'name:'+`eeetypeeid`:     u'CWEType',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
387
388
389
390
391
                'final:'+`eeetypeeid`:    False,
                'meta:'+`eeetypeeid`:     True,
                'description:'+`eeetypeeid`:     u'users group', 
                'read_permission:'+`eeetypeeid`:  groups,

392
                'edits-name:'+`eeetypeeid`:     u'CWEType',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
393
394
395
396
397
398
399
400
                'edits-final:'+`eeetypeeid`:    False,
                'edits-meta:'+`eeetypeeid`:     True,
                'edits-description:'+`eeetypeeid`:     u'users group', 
                '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)
401
            self.assertEquals(e.name, 'CWEType')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
402
403
404
            self.assertEquals(sorted(g.eid for g in e.read_permission), groupeids)
        finally:
            # restore
405
            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
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
            self.commit()
        
    def test_nonregr_strange_text_input(self):
        """non-regression test checking text input containing "13:03:43"

        this seems to be postgres (tsearch?) specific
        """        
        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):
427
        gueid = self.execute('CWGroup G WHERE G name "users"')[0][0]
Adrien Di Mascio's avatar
Adrien Di Mascio committed
428
429
        self.req.form = {'eid': ['X', 'Y'],
                         
430
                         '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
431
432
433
434
435
436
437
438
439
440
441
442
443
444
                         '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, 
                         
                         '__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, self.req)

    def test_nonregr_copy(self):
        user = self.user()
        self.req.form = {'__cloned_eid:X': user.eid,
445
                         'eid': 'X', '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
446
447
448
449
450
451
                         '__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()
        self.assertEquals(path, 'euser/toto')
452
        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
453
454
455
456
457
458
459
460
461
462
463
464
465
466
        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,
467
                             'eid': 'X', '__type:X': 'CWUser',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
468
469
470
471
472
473
474
475
476
477
478
479
480
481
                             'login': u'dodo', 'edits-login': u'dodo', 
                             '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)
482
            rset = self.execute('CWUser P WHERE P surname "Boom"')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
            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/'
        controller = self.env.app.select_controller('embed', req)
        result = controller.publish(rset=None)


class ReportBugControllerTC(EnvBasedTC):

    def test_usable_by_guets(self):
        req = self.request()
        self.env.app.select_controller('reportbug', req)


class SendMailControllerTC(EnvBasedTC):

    def test_not_usable_by_guets(self):
        self.login('anon')
        req = self.request()
        self.assertRaises(Unauthorized, self.env.app.select_controller, 'sendmail', req)
   


class JSONControllerTC(EnvBasedTC):

    def ctrl(self, req=None):
        req = req or self.request(url='http://whatever.fr/')
        return self.env.app.select_controller('json', req)

    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):
530
        ctrl = self.ctrl(self.request(rql='CWUser P WHERE P login "John"',
Adrien Di Mascio's avatar
Adrien Di Mascio committed
531
532
533
534
535
536
537
538
539
540
541
542
543
544
                                      pageid='123'))
        self.assertTextEquals(ctrl.publish(),
                              xmlize(self.john.view('primary')))

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

    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'])
545
        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
546
547
548
549
550
551
                          [['python']])
    
    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'])
552
        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
553
554
555
                          [['javascript']])

    def test_edit_field(self):
556
        nbusers = len(self.execute('CWUser P'))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
557
558
559
        eid = self.john.eid
        self.remote_call('edit_field', 'apply',
                         ('eid', 'firstname:%s' % eid, '__maineid', '__type:%s'% eid, 'edits-firstname:%s' % eid ),
560
                         (str(eid), u'Remi', str(eid), 'CWUser', self.john.firstname),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
561
562
563
                         'firstname',
                         eid)
        self.commit()
564
        rset = self.execute('CWUser P')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
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
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
        # make sure we did not insert a new euser here
        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):
        res, req = self.remote_call('add_pending_insert', ['12', 'tags', '13'])
        deletes = req.get_pending_deletes()
        self.assertEquals(deletes, [])
        inserts = req.get_pending_inserts()
        self.assertEquals(inserts, ['12:tags:13'])
        res, req = self.remote_call('add_pending_insert', ['12', 'tags', '14'])
        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'])
        _, req = self.remote_call('add_pending_insert', ['12', 'tags', '14'])
        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(), [])
        

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

    # 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):
        self.assertEquals(self.remote_call('format_date', '"2007-01-01 12:00:00"')[0],
                          simplejson.dumps('2007/01/01'))

        

        
if __name__ == '__main__':
    unittest_main()