devtools/testlib.py
changeset 3657 706d7bf0ae3d
parent 3647 2941f4a0aab9
child 3676 fa170564e1a0
equal deleted inserted replaced
3656:9ba2e3253a88 3657:706d7bf0ae3d
    19 
    19 
    20 from logilab.common.testlib import TestCase, InnerTest
    20 from logilab.common.testlib import TestCase, InnerTest
    21 from logilab.common.pytest import nocoverage, pause_tracing, resume_tracing
    21 from logilab.common.pytest import nocoverage, pause_tracing, resume_tracing
    22 from logilab.common.debugger import Debugger
    22 from logilab.common.debugger import Debugger
    23 from logilab.common.umessage import message_from_string
    23 from logilab.common.umessage import message_from_string
    24 from logilab.common.decorators import cached, classproperty
    24 from logilab.common.decorators import cached, classproperty, clear_cache
    25 from logilab.common.deprecation import deprecated
    25 from logilab.common.deprecation import deprecated
    26 
    26 
    27 from cubicweb import NoSelectableObject, cwconfig, devtools, web, server
    27 from cubicweb import NoSelectableObject, AuthenticationError
       
    28 from cubicweb import cwconfig, devtools, web, server
    28 from cubicweb.dbapi import repo_connect, ConnectionProperties, ProgrammingError
    29 from cubicweb.dbapi import repo_connect, ConnectionProperties, ProgrammingError
    29 from cubicweb.sobjects import notification
    30 from cubicweb.sobjects import notification
    30 from cubicweb.web import application
    31 from cubicweb.web import Redirect, application
    31 from cubicweb.devtools import SYSTEM_ENTITIES, SYSTEM_RELATIONS, VIEW_VALIDATORS
    32 from cubicweb.devtools import SYSTEM_ENTITIES, SYSTEM_RELATIONS, VIEW_VALIDATORS
    32 from cubicweb.devtools import fake, htmlparser
    33 from cubicweb.devtools import fake, htmlparser
    33 
    34 
    34 
    35 
    35 # low-level utilities ##########################################################
    36 # low-level utilities ##########################################################
   224         cls.vreg = cls.repo.vreg
   225         cls.vreg = cls.repo.vreg
   225         cls._orig_cnx = cls.cnx
   226         cls._orig_cnx = cls.cnx
   226         cls.config.repository = lambda x=None: cls.repo
   227         cls.config.repository = lambda x=None: cls.repo
   227         # necessary for authentication tests
   228         # necessary for authentication tests
   228         cls.cnx.login = cls.admlogin
   229         cls.cnx.login = cls.admlogin
   229         cls.cnx.password = cls.admpassword
   230         cls.cnx.authinfo = {'password': cls.admpassword}
   230 
   231 
   231     @classmethod
   232     @classmethod
   232     def _refresh_repo(cls):
   233     def _refresh_repo(cls):
   233         refresh_repo(cls.repo)
   234         refresh_repo(cls.repo)
   234 
   235 
   495         args = [dump(arg) for arg in args]
   496         args = [dump(arg) for arg in args]
   496         req = self.request(fname=fname, pageid='123', arg=args)
   497         req = self.request(fname=fname, pageid='123', arg=args)
   497         ctrl = self.vreg['controllers'].select('json', req)
   498         ctrl = self.vreg['controllers'].select('json', req)
   498         return ctrl.publish(), req
   499         return ctrl.publish(), req
   499 
   500 
       
   501     def app_publish(self, req, path='view'):
       
   502         return self.app.publish(path, req)
       
   503 
   500     def publish(self, req):
   504     def publish(self, req):
   501         """call the publish method of the edit controller"""
   505         """call the publish method of the edit controller"""
   502         ctrl = self.vreg['controllers'].select('edit', req)
   506         ctrl = self.vreg['controllers'].select('edit', req)
   503         try:
   507         try:
   504             result = ctrl.publish()
   508             result = ctrl.publish()
   506         except web.Redirect:
   510         except web.Redirect:
   507             req.cnx.commit()
   511             req.cnx.commit()
   508             raise
   512             raise
   509         return result
   513         return result
   510 
   514 
   511     def expect_redirect_publish(self, req):
   515     def expect_redirect(self, callback, req):
   512         """call the publish method of the edit controller, expecting to get a
   516         """call the given callback with req as argument, expecting to get a
   513         Redirect exception."""
   517         Redirect exception
       
   518         """
   514         try:
   519         try:
   515             self.publish(req)
   520             res = callback(req)
   516         except web.Redirect, ex:
   521         except Redirect, ex:
   517             try:
   522             try:
   518                 path, params = ex.location.split('?', 1)
   523                 path, params = ex.location.split('?', 1)
   519             except:
   524             except ValueError:
   520                 path, params = ex.location, ""
   525                 path = ex.location
   521             req._url = path
   526                 params = {}
   522             cleanup = lambda p: (p[0], unquote(p[1]))
   527             else:
   523             params = dict(cleanup(p.split('=', 1)) for p in params.split('&') if p)
   528                 cleanup = lambda p: (p[0], unquote(p[1]))
   524             return req.relative_path(False), params # path.rsplit('/', 1)[-1], params
   529                 params = dict(cleanup(p.split('=', 1)) for p in params.split('&') if p)
       
   530             path = path[len(req.base_url()):]
       
   531             return path, params
   525         else:
   532         else:
   526             self.fail('expected a Redirect exception')
   533             self.fail('expected a Redirect exception')
       
   534 
       
   535     def expect_redirect_publish(self, req, path='view'):
       
   536         """call the publish method of the application publisher, expecting to
       
   537         get a Redirect exception
       
   538         """
       
   539         return self.expect_redirect(lambda x: self.publish(x, path), req)
       
   540 
       
   541     def init_authentication(self, authmode, anonuser=None):
       
   542         self.set_option('auth-mode', authmode)
       
   543         self.set_option('anonymous-user', anonuser)
       
   544         req = self.request()
       
   545         origcnx = req.cnx
       
   546         req.cnx = None
       
   547         sh = self.app.session_handler
       
   548         authm = sh.session_manager.authmanager
       
   549         authm.authinforetreivers[-1].anoninfo = self.vreg.config.anonymous_user()
       
   550         # not properly cleaned between tests
       
   551         self.open_sessions = sh.session_manager._sessions = {}
       
   552         return req, origcnx
       
   553 
       
   554     def assertAuthSuccess(self, req, origcnx, nbsessions=1):
       
   555         sh = self.app.session_handler
       
   556         path, params = self.expect_redirect(lambda x: self.app.connect(x), req)
       
   557         cnx = req.cnx
       
   558         self.assertEquals(len(self.open_sessions), nbsessions, self.open_sessions)
       
   559         self.assertEquals(cnx.login, origcnx.login)
       
   560         self.assertEquals(cnx.anonymous_connection, False)
       
   561         self.assertEquals(path, 'view')
       
   562         self.assertEquals(params, {'__message': 'welcome %s !' % cnx.user().login})
       
   563 
       
   564     def assertAuthFailure(self, req):
       
   565         self.assertRaises(AuthenticationError, self.app.connect, req)
       
   566         self.assertEquals(req.cnx, None)
       
   567         self.assertEquals(len(self.open_sessions), 0)
       
   568         clear_cache(req, 'get_authorization')
   527 
   569 
   528     # content validation #######################################################
   570     # content validation #######################################################
   529 
   571 
   530     # validators are used to validate (XML, DTD, whatever) view's content
   572     # validators are used to validate (XML, DTD, whatever) view's content
   531     # validators availables are :
   573     # validators availables are :