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