cubicweb/web/test/unittest_application.py
changeset 11170 d034791621ad
parent 11129 97095348b3ee
child 11180 c2a8317d4eec
equal deleted inserted replaced
11169:c1eb5a676c80 11170:d034791621ad
     1 # copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
    32 from cubicweb.web import LogOut, Redirect, INTERNAL_FIELD_VALUE
    32 from cubicweb.web import LogOut, Redirect, INTERNAL_FIELD_VALUE
    33 from cubicweb.web.views.basecontrollers import ViewController
    33 from cubicweb.web.views.basecontrollers import ViewController
    34 from cubicweb.web.application import anonymized_request
    34 from cubicweb.web.application import anonymized_request
    35 from cubicweb import repoapi
    35 from cubicweb import repoapi
    36 
    36 
       
    37 
    37 class FakeMapping:
    38 class FakeMapping:
    38     """emulates a mapping module"""
    39     """emulates a mapping module"""
    39     def __init__(self):
    40     def __init__(self):
    40         self.ENTITIES_MAP = {}
    41         self.ENTITIES_MAP = {}
    41         self.ATTRIBUTES_MAP = {}
    42         self.ATTRIBUTES_MAP = {}
    42         self.RELATIONS_MAP = {}
    43         self.RELATIONS_MAP = {}
    43 
    44 
       
    45 
    44 class MockCursor:
    46 class MockCursor:
    45     def __init__(self):
    47     def __init__(self):
    46         self.executed = []
    48         self.executed = []
       
    49 
    47     def execute(self, rql, args=None, build_descr=False):
    50     def execute(self, rql, args=None, build_descr=False):
    48         args = args or {}
    51         args = args or {}
    49         self.executed.append(rql % args)
    52         self.executed.append(rql % args)
    50 
    53 
    51 
    54 
    67 
    70 
    68 class RequestBaseTC(TestCase):
    71 class RequestBaseTC(TestCase):
    69     def setUp(self):
    72     def setUp(self):
    70         self._cw = FakeRequest()
    73         self._cw = FakeRequest()
    71 
    74 
    72 
       
    73     def test_list_arg(self):
    75     def test_list_arg(self):
    74         """tests the list_arg() function"""
    76         """tests the list_arg() function"""
    75         list_arg = self._cw.list_form_param
    77         list_arg = self._cw.list_form_param
    76         self.assertEqual(list_arg('arg3', {}), [])
    78         self.assertEqual(list_arg('arg3', {}), [])
    77         d = {'arg1' : "value1",
    79         d = {'arg1': "value1",
    78              'arg2' : ('foo', INTERNAL_FIELD_VALUE,),
    80              'arg2': ('foo', INTERNAL_FIELD_VALUE,),
    79              'arg3' : ['bar']}
    81              'arg3': ['bar']}
    80         self.assertEqual(list_arg('arg1', d, True), ['value1'])
    82         self.assertEqual(list_arg('arg1', d, True), ['value1'])
    81         self.assertEqual(d, {'arg2' : ('foo', INTERNAL_FIELD_VALUE), 'arg3' : ['bar'],})
    83         self.assertEqual(d, {'arg2': ('foo', INTERNAL_FIELD_VALUE), 'arg3': ['bar']})
    82         self.assertEqual(list_arg('arg2', d, True), ['foo'])
    84         self.assertEqual(list_arg('arg2', d, True), ['foo'])
    83         self.assertEqual({'arg3' : ['bar'],}, d)
    85         self.assertEqual({'arg3': ['bar']}, d)
    84         self.assertEqual(list_arg('arg3', d), ['bar',])
    86         self.assertEqual(list_arg('arg3', d), ['bar'])
    85         self.assertEqual({'arg3' : ['bar'],}, d)
    87         self.assertEqual({'arg3': ['bar']}, d)
    86 
       
    87 
    88 
    88     def test_from_controller(self):
    89     def test_from_controller(self):
    89         self._cw.vreg['controllers'] = {'view': 1, 'login': 1}
    90         self._cw.vreg['controllers'] = {'view': 1, 'login': 1}
    90         self.assertEqual(self._cw.from_controller(), 'view')
    91         self.assertEqual(self._cw.from_controller(), 'view')
    91         req = FakeRequest(url='project?vid=list')
    92         req = FakeRequest(url='project?vid=list')
   105     """test suite for misc application utilities"""
   106     """test suite for misc application utilities"""
   106 
   107 
   107     def setUp(self):
   108     def setUp(self):
   108         self.ctrl = FakeController()
   109         self.ctrl = FakeController()
   109 
   110 
   110     #def test_which_mapping(self):
       
   111     #    """tests which mapping is used (application or core)"""
       
   112     #    init_mapping()
       
   113     #    from cubicweb.common import mapping
       
   114     #    self.assertEqual(mapping.MAPPING_USED, 'core')
       
   115     #    sys.modules['mapping'] = FakeMapping()
       
   116     #    init_mapping()
       
   117     #    self.assertEqual(mapping.MAPPING_USED, 'application')
       
   118     #    del sys.modules['mapping']
       
   119 
       
   120     def test_execute_linkto(self):
   111     def test_execute_linkto(self):
   121         """tests the execute_linkto() function"""
   112         """tests the execute_linkto() function"""
   122         self.assertEqual(self.ctrl.execute_linkto(), None)
   113         self.assertEqual(self.ctrl.execute_linkto(), None)
   123         self.assertEqual(self.ctrl._cursor.executed,
   114         self.assertEqual(self.ctrl._cursor.executed,
   124                           [])
   115                          [])
   125 
   116 
   126         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:object',
   117         self.ctrl.set_form({'__linkto': 'works_for:12_13_14:object',
   127                               'eid': 8})
   118                             'eid': 8})
   128         self.ctrl.execute_linkto()
   119         self.ctrl.execute_linkto()
   129         self.assertEqual(self.ctrl._cursor.executed,
   120         self.assertEqual(self.ctrl._cursor.executed,
   130                           ['SET Y works_for X WHERE X eid 8, Y eid %s' % i
   121                          ['SET Y works_for X WHERE X eid 8, Y eid %s' % i
   131                            for i in (12, 13, 14)])
   122                           for i in (12, 13, 14)])
   132 
   123 
   133         self.ctrl.new_cursor()
   124         self.ctrl.new_cursor()
   134         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:subject',
   125         self.ctrl.set_form({'__linkto': 'works_for:12_13_14:subject',
   135                               'eid': 8})
   126                             'eid': 8})
   136         self.ctrl.execute_linkto()
   127         self.ctrl.execute_linkto()
   137         self.assertEqual(self.ctrl._cursor.executed,
   128         self.assertEqual(self.ctrl._cursor.executed,
   138                           ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
   129                          ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
   139                            for i in (12, 13, 14)])
   130                           for i in (12, 13, 14)])
   140 
       
   141 
   131 
   142         self.ctrl.new_cursor()
   132         self.ctrl.new_cursor()
   143         self.ctrl._cw.form = {'__linkto' : 'works_for:12_13_14:object'}
   133         self.ctrl._cw.form = {'__linkto': 'works_for:12_13_14:object'}
   144         self.ctrl.execute_linkto(eid=8)
   134         self.ctrl.execute_linkto(eid=8)
   145         self.assertEqual(self.ctrl._cursor.executed,
   135         self.assertEqual(self.ctrl._cursor.executed,
   146                           ['SET Y works_for X WHERE X eid 8, Y eid %s' % i
   136                          ['SET Y works_for X WHERE X eid 8, Y eid %s' % i
   147                            for i in (12, 13, 14)])
   137                           for i in (12, 13, 14)])
   148 
   138 
   149         self.ctrl.new_cursor()
   139         self.ctrl.new_cursor()
   150         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:subject'})
   140         self.ctrl.set_form({'__linkto': 'works_for:12_13_14:subject'})
   151         self.ctrl.execute_linkto(eid=8)
   141         self.ctrl.execute_linkto(eid=8)
   152         self.assertEqual(self.ctrl._cursor.executed,
   142         self.assertEqual(self.ctrl._cursor.executed,
   153                           ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
   143                          ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
   154                            for i in (12, 13, 14)])
   144                           for i in (12, 13, 14)])
   155 
   145 
   156 
   146 
   157 class ApplicationTC(CubicWebTC):
   147 class ApplicationTC(CubicWebTC):
   158 
   148 
   159     @classproperty
   149     @classproperty
   182     def test_publish_validation_error(self):
   172     def test_publish_validation_error(self):
   183         with self.admin_access.web_request() as req:
   173         with self.admin_access.web_request() as req:
   184             user = req.user
   174             user = req.user
   185             eid = text_type(user.eid)
   175             eid = text_type(user.eid)
   186             req.form = {
   176             req.form = {
   187                 'eid':       eid,
   177                 'eid': eid,
   188                 '__type:'+eid:    'CWUser', '_cw_entity_fields:'+eid: 'login-subject',
   178                 '__type:' + eid: 'CWUser',
   189                 'login-subject:'+eid:     '', # ERROR: no login specified
   179                 '_cw_entity_fields:' + eid: 'login-subject',
   190                  # just a sample, missing some necessary information for real life
   180                 'login-subject:' + eid: '',  # ERROR: no login specified
       
   181                 # just a sample, missing some necessary information for real life
   191                 '__errorurl': 'view?vid=edition...'
   182                 '__errorurl': 'view?vid=edition...'
   192                 }
   183             }
   193             path, params = self.expect_redirect_handle_request(req, 'edit')
   184             path, params = self.expect_redirect_handle_request(req, 'edit')
   194             forminfo = req.session.data['view?vid=edition...']
   185             forminfo = req.session.data['view?vid=edition...']
   195             eidmap = forminfo['eidmap']
   186             eidmap = forminfo['eidmap']
   196             self.assertEqual(eidmap, {})
   187             self.assertEqual(eidmap, {})
   197             values = forminfo['values']
   188             values = forminfo['values']
   198             self.assertEqual(values['login-subject:'+eid], '')
   189             self.assertEqual(values['login-subject:' + eid], '')
   199             self.assertEqual(values['eid'], eid)
   190             self.assertEqual(values['eid'], eid)
   200             error = forminfo['error']
   191             error = forminfo['error']
   201             self.assertEqual(error.entity, user.eid)
   192             self.assertEqual(error.entity, user.eid)
   202             self.assertEqual(error.errors['login-subject'], 'required field')
   193             self.assertEqual(error.errors['login-subject'], 'required field')
   203 
       
   204 
   194 
   205     def test_validation_error_dont_loose_subentity_data_ctrl(self):
   195     def test_validation_error_dont_loose_subentity_data_ctrl(self):
   206         """test creation of two linked entities
   196         """test creation of two linked entities
   207 
   197 
   208         error occurs on the web controller
   198         error occurs on the web controller
   225             self.assertEqual(set(forminfo['eidmap']), set('XY'))
   215             self.assertEqual(set(forminfo['eidmap']), set('XY'))
   226             self.assertEqual(forminfo['eidmap']['X'], None)
   216             self.assertEqual(forminfo['eidmap']['X'], None)
   227             self.assertIsInstance(forminfo['eidmap']['Y'], int)
   217             self.assertIsInstance(forminfo['eidmap']['Y'], int)
   228             self.assertEqual(forminfo['error'].entity, 'X')
   218             self.assertEqual(forminfo['error'].entity, 'X')
   229             self.assertEqual(forminfo['error'].errors,
   219             self.assertEqual(forminfo['error'].errors,
   230                               {'login-subject': 'required field'})
   220                              {'login-subject': 'required field'})
   231             self.assertEqual(forminfo['values'], req.form)
   221             self.assertEqual(forminfo['values'], req.form)
   232 
       
   233 
   222 
   234     def test_validation_error_dont_loose_subentity_data_repo(self):
   223     def test_validation_error_dont_loose_subentity_data_repo(self):
   235         """test creation of two linked entities
   224         """test creation of two linked entities
   236 
   225 
   237         error occurs on the repository
   226         error occurs on the repository
   238         """
   227         """
   239         with self.admin_access.web_request() as req:
   228         with self.admin_access.web_request() as req:
   240             # set Y before X to ensure both entities are edited, not only X
   229             # set Y before X to ensure both entities are edited, not only X
   241             req.form = {'eid': ['Y', 'X'], '__maineid': 'X',
   230             req.form = {
   242                         '__type:X': 'CWUser', '_cw_entity_fields:X': 'login-subject,upassword-subject',
   231                 'eid': ['Y', 'X'], '__maineid': 'X',
   243                         # already existent user
   232                 '__type:X': 'CWUser', '_cw_entity_fields:X': 'login-subject,upassword-subject',
   244                         'login-subject:X': u'admin',
   233                 # already existent user
   245                         'upassword-subject:X': u'admin', 'upassword-subject-confirm:X': u'admin',
   234                 'login-subject:X': u'admin',
   246                         '__type:Y': 'EmailAddress', '_cw_entity_fields:Y': 'address-subject',
   235                 'upassword-subject:X': u'admin', 'upassword-subject-confirm:X': u'admin',
   247                         'address-subject:Y': u'bougloup@logilab.fr',
   236                 '__type:Y': 'EmailAddress', '_cw_entity_fields:Y': 'address-subject',
   248                         'use_email-object:Y': 'X',
   237                 'address-subject:Y': u'bougloup@logilab.fr',
   249                         # necessary to get validation error handling
   238                 'use_email-object:Y': 'X',
   250                         '__errorurl': 'view?vid=edition...',
   239                 # necessary to get validation error handling
   251                         }
   240                 '__errorurl': 'view?vid=edition...',
       
   241             }
   252             path, params = self.expect_redirect_handle_request(req, 'edit')
   242             path, params = self.expect_redirect_handle_request(req, 'edit')
   253             forminfo = req.session.data['view?vid=edition...']
   243             forminfo = req.session.data['view?vid=edition...']
   254             self.assertEqual(set(forminfo['eidmap']), set('XY'))
   244             self.assertEqual(set(forminfo['eidmap']), set('XY'))
   255             self.assertIsInstance(forminfo['eidmap']['X'], int)
   245             self.assertIsInstance(forminfo['eidmap']['X'], int)
   256             self.assertIsInstance(forminfo['eidmap']['Y'], int)
   246             self.assertIsInstance(forminfo['eidmap']['Y'], int)
   257             self.assertEqual(forminfo['error'].entity, forminfo['eidmap']['X'])
   247             self.assertEqual(forminfo['error'].entity, forminfo['eidmap']['X'])
   258             self.assertEqual(forminfo['error'].errors,
   248             self.assertEqual(forminfo['error'].errors,
   259                               {'login-subject': u'the value "admin" is already used, use another one'})
   249                              {'login-subject': u'the value "admin" is already used, use another one'})
   260             self.assertEqual(forminfo['values'], req.form)
   250             self.assertEqual(forminfo['values'], req.form)
   261 
   251 
   262     def _edit_parent(self, dir_eid, parent_eid, role='subject',
   252     def _edit_parent(self, dir_eid, parent_eid, role='subject',
   263                      etype='Directory', **kwargs):
   253                      etype='Directory', **kwargs):
   264         parent_eid = parent_eid or '__cubicweb_internal_field__'
   254         parent_eid = parent_eid or '__cubicweb_internal_field__'
   513             self.assertFalse(req.find('DirectoryPermission', eid=perm.eid))
   503             self.assertFalse(req.find('DirectoryPermission', eid=perm.eid))
   514 
   504 
   515     def test_ajax_view_raise_arbitrary_error(self):
   505     def test_ajax_view_raise_arbitrary_error(self):
   516         class ErrorAjaxView(view.View):
   506         class ErrorAjaxView(view.View):
   517             __regid__ = 'test.ajax.error'
   507             __regid__ = 'test.ajax.error'
       
   508 
   518             def call(self):
   509             def call(self):
   519                 raise Exception('whatever')
   510                 raise Exception('whatever')
       
   511 
   520         with self.temporary_appobjects(ErrorAjaxView):
   512         with self.temporary_appobjects(ErrorAjaxView):
   521             with real_error_handling(self.app) as app:
   513             with real_error_handling(self.app) as app:
   522                 with self.admin_access.web_request(vid='test.ajax.error') as req:
   514                 with self.admin_access.web_request(vid='test.ajax.error') as req:
   523                     req.ajax_request = True
   515                     req.ajax_request = True
   524                     page = app.handle_request(req, '')
   516                     app.handle_request(req, '')
   525         self.assertEqual(http_client.INTERNAL_SERVER_ERROR,
   517         self.assertEqual(http_client.INTERNAL_SERVER_ERROR,
   526                          req.status_out)
   518                          req.status_out)
   527 
   519 
   528     def _test_cleaned(self, kwargs, injected, cleaned):
   520     def _test_cleaned(self, kwargs, injected, cleaned):
   529         with self.admin_access.web_request(**kwargs) as req:
   521         with self.admin_access.web_request(**kwargs) as req:
   578     def test_cookie_auth_no_anon(self):
   570     def test_cookie_auth_no_anon(self):
   579         req, origsession = self.init_authentication('cookie')
   571         req, origsession = self.init_authentication('cookie')
   580         self.assertAuthFailure(req)
   572         self.assertAuthFailure(req)
   581         try:
   573         try:
   582             form = self.app.handle_request(req, 'login')
   574             form = self.app.handle_request(req, 'login')
   583         except Redirect as redir:
   575         except Redirect:
   584             self.fail('anonymous user should get login form')
   576             self.fail('anonymous user should get login form')
   585         clear_cache(req, 'get_authorization')
   577         clear_cache(req, 'get_authorization')
   586         self.assertIn(b'__login', form)
   578         self.assertIn(b'__login', form)
   587         self.assertIn(b'__password', form)
   579         self.assertIn(b'__password', form)
   588         self.assertFalse(req.cnx) # Mock cnx are False
   580         self.assertFalse(req.cnx)  # Mock cnx are False
   589         req.form['__login'] = self.admlogin
   581         req.form['__login'] = self.admlogin
   590         req.form['__password'] = self.admpassword
   582         req.form['__password'] = self.admpassword
   591         self.assertAuthSuccess(req, origsession)
   583         self.assertAuthSuccess(req, origsession)
   592         self.assertRaises(LogOut, self.app_handle_request, req, 'logout')
   584         self.assertRaises(LogOut, self.app_handle_request, req, 'logout')
   593         self.assertEqual(len(self.open_sessions), 0)
   585         self.assertEqual(len(self.open_sessions), 0)
   597             login = cnx.user.login
   589             login = cnx.user.login
   598             address = login + u'@localhost'
   590             address = login + u'@localhost'
   599             cnx.execute('INSERT EmailAddress X: X address %(address)s, U primary_email X '
   591             cnx.execute('INSERT EmailAddress X: X address %(address)s, U primary_email X '
   600                         'WHERE U login %(login)s', {'address': address, 'login': login})
   592                         'WHERE U login %(login)s', {'address': address, 'login': login})
   601             cnx.commit()
   593             cnx.commit()
   602         # # option allow-email-login not set
       
   603         req, origsession = self.init_authentication('cookie')
   594         req, origsession = self.init_authentication('cookie')
   604         # req.form['__login'] = address
       
   605         # req.form['__password'] = self.admpassword
       
   606         # self.assertAuthFailure(req)
       
   607         # option allow-email-login set
       
   608         #origsession.login = address
       
   609         self.set_option('allow-email-login', True)
   595         self.set_option('allow-email-login', True)
   610         req.form['__login'] = address
   596         req.form['__login'] = address
   611         req.form['__password'] = self.admpassword
   597         req.form['__password'] = self.admpassword
   612         self.assertAuthSuccess(req, origsession)
   598         self.assertAuthSuccess(req, origsession)
   613         self.assertRaises(LogOut, self.app_handle_request, req, 'logout')
   599         self.assertRaises(LogOut, self.app_handle_request, req, 'logout')