web/test/unittest_views_basecontrollers.py
changeset 4172 4d4cef034eec
parent 4083 3b285889b8e9
child 4252 6c4f109c2b03
--- a/web/test/unittest_views_basecontrollers.py	Mon Dec 21 20:28:01 2009 +0100
+++ b/web/test/unittest_views_basecontrollers.py	Mon Dec 21 20:28:08 2009 +0100
@@ -16,6 +16,8 @@
 from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect, RequestError
 from cubicweb.entities.authobjs import CWUser
 
+u = unicode
+
 
 class EditControllerTC(CubicWebTC):
     def setUp(self):
@@ -29,7 +31,8 @@
     def test_noparam_edit(self):
         """check behaviour of this controller without any form parameter
         """
-        self.assertRaises(ValidationError, self.publish, self.request())
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, self.request())
+        self.assertEquals(ex.errors, {None: u'no selected entities'})
 
     def test_validation_unique(self):
         """test creation of two linked entities
@@ -37,106 +40,98 @@
         user = self.user()
         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'',
+                    '_cw_edited_fields:X': 'login-subject,upassword-subject',
+                    'login-subject:X': u'admin',
+                    'upassword-subject:X': u'toto',
+                    'upassword-subject-confirm:X': u'toto',
                     }
-        self.assertRaises(ValidationError, self.publish, req)
-
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
+        self.assertEquals(ex.errors, {'login': 'the value "admin" is already used, use another one'})
 
     def test_user_editing_itself(self):
         """checking that a manager user can edit itself
         """
         user = self.user()
-        basegroups = [str(eid) for eid, in self.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
+        basegroups = [u(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")')]
-        groups = [str(eid) for eid in groupeids]
-        stateeid = [eid for eid, in self.execute('State S WHERE S name "activated"')][0]
+        groups = [u(eid) for eid in groupeids]
         req = self.request()
+        eid = u(user.eid)
         req.form = {
-            'eid':       `user.eid`,
-            '__type:'+`user.eid`:    'CWUser',
-            '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`,
+            'eid': eid, '__type:'+eid: 'CWUser',
+            '_cw_edited_fields:'+eid: 'login-subject,firstname-subject,surname-subject,in_group-subject',
+            'login-subject:'+eid:     u(user.login),
+            'surname-subject:'+eid: u'Th\xe9nault',
+            'firstname-subject:'+eid:   u'Sylvain',
+            'in_group-subject:'+eid:  groups,
             }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         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.firstname, u'Sylvain')
+        self.assertEquals(e.surname, u'Th\xe9nault')
         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()
+        eid = u(user.eid)
         req.form = {
-            'eid': `user.eid`, '__type:'+`user.eid`: 'CWUser',
-            '__maineid' : str(user.eid),
-            'upassword:'+`user.eid`: 'tournicoton',
-            'upassword-confirm:'+`user.eid`: 'tournicoton',
-            'edits-upassword:'+`user.eid`:  '',
+            'eid': eid, '__maineid' : eid,
+            '__type:'+eid: 'CWUser',
+            '_cw_edited_fields:'+eid: 'upassword-subject',
+            'upassword-subject:'+eid: 'tournicoton',
+            'upassword-subject-confirm:'+eid: 'tournicoton',
             }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         cnx.commit() # commit to check we don't get late validation error for instance
         self.assertEquals(path, 'cwuser/user')
         self.failIf('vid' in params)
 
-    def testr_user_editing_itself_no_relation(self):
+    def test_user_editing_itself_no_relation(self):
         """checking we can edit an entity without specifying some required
         relations (meaning no changes)
         """
         user = self.user()
-        groupeids = [eid for eid, in self.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
+        groupeids = [g.eid for g in user.in_group]
         req = self.request()
+        eid = u(user.eid)
         req.form = {
-            'eid':       `user.eid`,
-            '__type:'+`user.eid`:    'CWUser',
-            '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'',
+            'eid':       eid,
+            '__type:'+eid:    'CWUser',
+            '_cw_edited_fields:'+eid: 'login-subject,firstname-subject,surname-subject',
+            'login-subject:'+eid:     u(user.login),
+            'firstname-subject:'+eid: u'Th\xe9nault',
+            'surname-subject:'+eid:   u'Sylvain',
             }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         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)
+        self.assertEquals(e.state, 'activated')
 
 
     def test_create_multiple_linked(self):
         gueid = self.execute('CWGroup G WHERE G name "users"')[0][0]
         req = self.request()
-        req.form = {'eid': ['X', 'Y'],
+        req.form = {'eid': ['X', 'Y'], '__maineid' : 'X',
 
                     '__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': '',
-
-                    'in_group:X': `gueid`, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
+                    '_cw_edited_fields:X': 'login-subject,upassword-subject,surname-subject,in_group-subject',
+                    'login-subject:X': u'adim',
+                    'upassword-subject:X': u'toto', 'upassword-subject-confirm:X': u'toto',
+                    'surname-subject:X': u'Di Mascio',
+                    'in_group-subject:X': u(gueid),
 
                     '__type:Y': 'EmailAddress',
-                    'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
-                    'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
+                    '_cw_edited_fields:Y': 'address-subject,use_email-object',
+                    'address-subject:Y': u'dima@logilab.fr',
+                    'use_email-object:Y': 'X',
                     }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         # should be redirected on the created person
         self.assertEquals(path, 'cwuser/adim')
         e = self.execute('Any P WHERE P surname "Di Mascio"').get_entity(0, 0)
@@ -145,42 +140,41 @@
         self.assertEquals(email.address, 'dima@logilab.fr')
 
     def test_edit_multiple_linked(self):
-        peid = self.create_user('adim').eid
+        peid = u(self.create_user('adim').eid)
         req = self.request()
-        req.form = {'eid': [`peid`, 'Y'],
-                    '__type:%s'%peid: 'CWUser',
-                    'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: '',
+        req.form = {'eid': [peid, 'Y'], '__maineid': peid,
+
+                    '__type:'+peid: u'CWUser',
+                    '_cw_edited_fields:'+peid: u'surname-subject',
+                    'surname-subject:'+peid: u'Di Masci',
 
-                    '__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,
+                    '__type:Y': u'EmailAddress',
+                    '_cw_edited_fields:Y': u'address-subject,use_email-object',
+                    'address-subject:Y': u'dima@logilab.fr',
+                    'use_email-object:Y': peid,
                     }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         # 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')
+        self.assertEquals(path, 'cwuser/adim')
+        e = self.execute('Any P WHERE P surname "Di Masci"').get_entity(0, 0)
         email = e.use_email[0]
         self.assertEquals(email.address, 'dima@logilab.fr')
 
-        emaileid = email.eid
+        emaileid = u(email.eid)
         req = self.request()
-        req.form = {'eid': [`peid`, `emaileid`],
-                         '__type:%s'%peid: 'CWUser',
-                         '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(req)
-        # 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]
+        req.form = {'eid': [peid, emaileid],
+
+                    '__type:'+peid: u'CWUser',
+                    '_cw_edited_fields:'+peid: u'surname-subject',
+                    'surname-subject:'+peid: u'Di Masci',
+
+                    '__type:'+emaileid: u'EmailAddress',
+                    '_cw_edited_fields:'+emaileid: u'address-subject,use_email-object',
+                    'address-subject:'+emaileid: u'adim@logilab.fr',
+                    'use_email-object:'+emaileid: peid,
+                    }
+        path, params = self.expect_redirect_publish(req, 'edit')
+        email.clear_all_caches()
         self.assertEquals(email.address, 'adim@logilab.fr')
 
 
@@ -189,20 +183,24 @@
         """
         user = self.user()
         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'',
+        req.form = {'eid': 'X',
+                    '__cloned_eid:X': u(user.eid), '__type:X': 'CWUser',
+                    '_cw_edited_fields:X': 'login-subject,upassword-subject',
+                    'login-subject:X': u'toto',
+                    'upassword-subject:X': u'toto',
                     }
-        self.assertRaises(ValidationError, self.publish, req)
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
+        self.assertEquals(ex.errors, {'upassword': u'password and confirmation don\'t match'})
         req = self.request()
-        req.form = {'__cloned_eid:X': user.eid,
+        req.form = {'__cloned_eid:X': u(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'',
+                    '_cw_edited_fields:X': 'login-subject,upassword-subject',
+                    'login-subject:X': u'toto',
+                    'upassword-subject:X': u'toto',
+                    'upassword-subject-confirm:X': u'tutu',
                     }
-        self.assertRaises(ValidationError, self.publish, req)
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
+        self.assertEquals(ex.errors, {'upassword': u'password and confirmation don\'t match'})
 
 
     def test_interval_bound_constraint_success(self):
@@ -211,24 +209,29 @@
         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,
+                    '_cw_edited_fields:X': 'amount-subject,described_by_test-subject',
+                    'amount-subject:X': u'-10',
+                    'described_by_test-subject:X': u(feid),
                 }
-        self.assertRaises(ValidationError, self.publish, req)
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
+        self.assertEquals(ex.errors, {'amount': 'value [0;100] constraint failed for value -10'})
         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,
+                    '_cw_edited_fields:X': 'amount-subject,described_by_test-subject',
+                    'amount-subject:X': u'110',
+                    'described_by_test-subject:X': u(feid),
                     }
-        self.assertRaises(ValidationError, self.publish, req)
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
+        self.assertEquals(ex.errors, {'amount': 'value [0;100] constraint failed for value 110'})
         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,
+                    '_cw_edited_fields:X': 'amount-subject,described_by_test-subject',
+                    'amount-subject:X': u'10',
+                    'described_by_test-subject:X': u(feid),
                     }
-        self.expect_redirect_publish(req)
+        self.expect_redirect_publish(req, 'edit')
         # should be redirected on the created
         #eid = params['rql'].split()[-1]
         e = self.execute('Salesterm X').get_entity(0, 0)
@@ -240,7 +243,7 @@
         user = self.user()
         req = self.request()
         req.set_session_data('pending_insert', set([(user.eid, 'in_group', tmpgroup.eid)]))
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         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'])
@@ -259,48 +262,47 @@
         # now try to delete the relation
         req = self.request()
         req.set_session_data('pending_delete', set([(user.eid, 'in_group', groupeid)]))
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         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(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')
-        CWUser.custom_login_edit = custom_login_edit
-        try:
-            user = self.user()
-            eid = repr(user.eid)
-            req = self.request()
-            req.form = {
-                'eid': eid,
-                '__type:'+eid:  'CWUser',
-                'login:'+eid: u'foo',
-                'edits-login:'+eid:  unicode(user.login),
-                }
-            path, params = self.expect_redirect_publish(req)
-            rset = self.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x')
-            self.assertEquals(rset[0][0], 'FOO')
-        finally:
-            del CWUser.custom_login_edit
+    # def test_custom_attribute_handler(self):
+    #     def custom_login_edit(self, formparams, value, relations):
+    #         formparams['login'] = value.upper()
+    #         relations.append('X login %(login)s')
+    #     CWUser.custom_login_edit = custom_login_edit
+    #     try:
+    #         user = self.user()
+    #         eid = repr(user.eid)
+    #         req = self.request()
+    #         req.form = {
+    #             'eid': eid,
+    #             '__type:'+eid:  'CWUser',
+    #             'login:'+eid: u'foo',
+    #             }
+    #         path, params = self.expect_redirect_publish(req, 'edit')
+    #         rset = self.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x')
+    #         self.assertEquals(rset[0][0], 'FOO')
+    #     finally:
+    #         del CWUser.custom_login_edit
 
     def test_redirect_apply_button(self):
         redirectrql = rql_for_eid(4012) # whatever
         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': '',
+            'eid': 'A', '__maineid' : 'A',
+            '__type:A': 'BlogEntry', '_cw_edited_fields:A': 'content-subject,title-subject',
+            'content-subject:A': u'"13:03:43"',
+            'title-subject:A': u'huuu',
             '__redirectrql': redirectrql,
             '__redirectvid': 'primary',
             '__redirectparams': 'toto=tutu&tata=titi',
             '__form_id': 'edition',
             '__action_apply': '',
             }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         self.failUnless(path.startswith('blogentry/'))
         eid = path.split('/')[1]
         self.assertEquals(params['vid'], 'edition')
@@ -313,16 +315,16 @@
         redirectrql = rql_for_eid(4012) # whatever
         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': '',
+            'eid': 'A', '__maineid' : 'A',
+            '__type:A': 'BlogEntry', '_cw_edited_fields:A': 'content-subject,title-subject',
+            'content-subject:A': u'"13:03:43"',
+            'title-subject:A': u'huuu',
             '__redirectrql': redirectrql,
             '__redirectvid': 'primary',
             '__redirectparams': 'toto=tutu&tata=titi',
             '__form_id': 'edition',
             }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         self.assertEquals(path, 'view')
         self.assertEquals(params['rql'], redirectrql)
         self.assertEquals(params['vid'], 'primary')
@@ -332,9 +334,9 @@
     def test_redirect_delete_button(self):
         req = self.request()
         eid = req.create_entity('BlogEntry', title=u'hop', content=u'hop').eid
-        req.form = {'eid': str(eid), '__type:%s'%eid: 'BlogEntry',
+        req.form = {'eid': u(eid), '__type:%s'%eid: 'BlogEntry',
                     '__action_delete': ''}
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         self.assertEquals(path, 'blogentry')
         self.assertEquals(params, {u'__message': u'entity deleted'})
         eid = req.create_entity('EmailAddress', address=u'hop@logilab.fr').eid
@@ -342,19 +344,19 @@
                      {'x': self.session.user.eid, 'e': eid}, 'x')
         self.commit()
         req = req
-        req.form = {'eid': str(eid), '__type:%s'%eid: 'EmailAddress',
+        req.form = {'eid': u(eid), '__type:%s'%eid: 'EmailAddress',
                     '__action_delete': ''}
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         self.assertEquals(path, 'cwuser/admin')
         self.assertEquals(params, {u'__message': u'entity deleted'})
         eid1 = req.create_entity('BlogEntry', title=u'hop', content=u'hop').eid
         eid2 = req.create_entity('EmailAddress', address=u'hop@logilab.fr').eid
         req = self.request()
-        req.form = {'eid': [str(eid1), str(eid2)],
+        req.form = {'eid': [u(eid1), u(eid2)],
                     '__type:%s'%eid1: 'BlogEntry',
                     '__type:%s'%eid2: 'EmailAddress',
                     '__action_delete': ''}
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         self.assertEquals(path, 'view')
         self.assertEquals(params, {u'__message': u'entities deleted'})
 
@@ -362,28 +364,22 @@
         """non-regression test checking that a manager user can edit a CWEType entity (CWGroup)
         """
         groupeids = [eid for eid, in self.execute('CWGroup G WHERE G name "managers"')]
-        groups = [str(eid) for eid in groupeids]
-        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})]
+        groups = [u(eid) for eid in groupeids]
+        cwetypeeid = u(self.execute('CWEType X WHERE X name "CWGroup"')[0][0])
+        basegroups = [u(eid) for eid, in self.execute('CWGroup G WHERE X read_permission G, X eid %(x)s', {'x': cwetypeeid})]
         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,
+            'eid':      cwetypeeid,
+            '__type:'+cwetypeeid:   'CWEType',
+            '_cw_edited_fields:'+cwetypeeid: 'name-subject,final-subject,description-subject,read_permission-subject',
+            'name-subject:'+cwetypeeid:     u'CWGroup',
+            #'final-subject:'+cwetypeeid:    False,
+            'description-subject:'+cwetypeeid:     u'users group',
+            'read_permission-subject:'+cwetypeeid:  groups,
             }
         try:
-            path, params = self.expect_redirect_publish(req)
-            e = self.execute('Any X WHERE X eid %(x)s', {'x': eeetypeeid}, 'x').get_entity(0, 0)
+            path, params = self.expect_redirect_publish(req, 'edit')
+            e = self.execute('Any X WHERE X eid %(x)s', {'x': cwetypeeid}, 'x').get_entity(0, 0)
             self.assertEquals(e.name, 'CWGroup')
             self.assertEquals([g.eid for g in e.read_permission], groupeids)
         finally:
@@ -395,28 +391,23 @@
         """non-regression test checking that a manager user can edit a CWEType entity (CWEType)
         """
         groupeids = sorted(eid for eid, in self.execute('CWGroup G WHERE G name in ("managers", "users")'))
-        groups = [str(eid) for eid in groupeids]
-        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})]
+        groups = [u(eid) for eid in groupeids]
+        cwetypeeid = self.execute('CWEType X WHERE X name "CWEType"')[0][0]
+        basegroups = [u(eid) for eid, in self.execute('CWGroup G WHERE X read_permission G, X eid %(x)s', {'x': cwetypeeid})]
+        cwetypeeid = u(cwetypeeid)
         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,
+            'eid':      cwetypeeid,
+            '__type:'+cwetypeeid:  'CWEType',
+            '_cw_edited_fields:'+cwetypeeid: 'name-subject,final-subject,description-subject,read_permission-subject',
+            'name-subject:'+cwetypeeid:     u'CWEType',
+            #'final-subject:'+cwetypeeid:    False,
+            'description-subject:'+cwetypeeid:     u'users group',
+            'read_permission-subject:'+cwetypeeid:  groups,
             }
         try:
-            path, params = self.expect_redirect_publish(req)
-            e = self.execute('Any X WHERE X eid %(x)s', {'x': eeetypeeid}, 'x').get_entity(0, 0)
+            path, params = self.expect_redirect_publish(req, 'edit')
+            e = self.execute('Any X WHERE X eid %(x)s', {'x': cwetypeeid}, 'x').get_entity(0, 0)
             self.assertEquals(e.name, 'CWEType')
             self.assertEquals(sorted(g.eid for g in e.read_permission), groupeids)
         finally:
@@ -431,11 +422,11 @@
         """
         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)
+            'eid': 'A', '__maineid' : 'A',
+            '__type:A': 'BlogEntry', '_cw_edited_fields:A': 'title-subject,content-subject',
+            'title-subject:A': u'"13:03:40"',
+            'content-subject:A': u'"13:03:43"',}
+        path, params = self.expect_redirect_publish(req, 'edit')
         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)
@@ -449,27 +440,30 @@
         req.form = {'eid': ['X', 'Y'],
 
                     '__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,
+                    '_cw_edited_fields:X': 'login-subject,upassword-subject,in_group-subject',
+                    'login-subject:X': u'adim',
+                    'upassword-subject:X': u'toto', 'upassword-subject-confirm:X': u'toto',
+                    'in_group-subject:X': `gueid`,
 
                     '__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,
+                    '_cw_edited_fields:Y': 'address-subject,alias-subject,use_email-object',
+                    'address-subject:Y': u'',
+                    'alias-subject:Y': u'',
+                    'use_email-object:Y': 'X',
                     }
-        self.assertRaises(ValidationError, self.publish, req)
+        ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
+        self.assertEquals(ex.errors, {'address': u'required attribute'})
 
     def test_nonregr_copy(self):
         user = self.user()
         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'',
+        req.form = {'__maineid' : 'X', 'eid': 'X',
+                    '__cloned_eid:X': user.eid, '__type:X': 'CWUser',
+                    '_cw_edited_fields:X': 'login-subject,upassword-subject',
+                    'login-subject:X': u'toto',
+                    'upassword-subject:X': u'toto', 'upassword-subject-confirm:X': u'toto',
                     }
-        path, params = self.expect_redirect_publish(req)
+        path, params = self.expect_redirect_publish(req, 'edit')
         self.assertEquals(path, 'cwuser/toto')
         e = self.execute('Any X WHERE X is CWUser, X login "toto"').get_entity(0, 0)
         self.assertEquals(e.login, 'toto')
@@ -486,22 +480,24 @@
             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})
             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'',
+            req.form = {'eid': 'X',
+                        '__cloned_eid:X': p.eid, '__type:X': 'CWUser',
+                        '_cw_edited_fields:X': 'login-subject,surname-subject',
+                        'login-subject': u'dodo',
+                        'surname-subject:X': u'Boom',
                         '__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.app.publish('edit', req)
+                self.app_publish(req, 'edit')
             except Redirect:
+                req = self.request()
                 req.form['rql'] = 'Any X WHERE X eid %s' % p.eid
                 req.form['vid'] = 'copy'
-                self.app.publish('view', req)
+                self.app_publish(req, 'view')
             rset = self.execute('CWUser P WHERE P surname "Boom"')
             self.assertEquals(len(rset), 0)
         finally: