Example #1
0
class HdfdumpTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.req = MockRequest(self.env, args={'hdfdump': '1'})
        self.env.clear_component_registry()
        self.request_dispatcher = RequestDispatcher(self.env)
        perm = self.req.perm
        self.request_dispatcher._get_perm = lambda req: perm

    def tearDown(self):
        self.env.restore_component_registry()

    def test_hdfdump(self):
        class HdfdumpRequestHandler(Component):
            implements(IRequestHandler)

            def match_request(self, req):
                return True

            def process_request(self, req):
                data = {'name': 'value'}
                return 'error.html', data, None

        self.env.config.set('trac', 'default_handler', 'HdfdumpRequestHandler')
        self.assertRaises(RequestDone, self.request_dispatcher.dispatch,
                          self.req)
        self.assertIn("{'name': 'value'}\n", self.req.response_sent.getvalue())
        self.assertEqual('text/plain;charset=utf-8',
                         self.req.headers_sent['Content-Type'])
Example #2
0
class TracAdminHelpMacroTestCase(TracAdminTestCaseBase):
    def setUp(self):
        self.env = EnvironmentStub(
            enable=['%s.UnicodeHelpCommand' % self.__module__])
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()
        self.env.reset_db()

    def test_unicode_help(self):
        unicode_help = u'Hélp text with unicöde charàcters'

        class UnicodeHelpCommand(Component):
            implements(IAdminCommandProvider)

            def get_admin_commands(self):
                yield ('unicode-help', '', unicode_help, None, self._cmd)

            def _cmd(self):
                pass

        macro = TracAdminHelpMacro(self.env)
        help = unicode(macro.expand_macro(None, None, 'unicode-help'))
        self.assertIn(unicode_help, help)

    def test_invalid_command(self):
        macro = TracAdminHelpMacro(self.env)

        try:
            macro.expand_macro(None, None, 'copystatic')
            self.fail("MacroError not raised")
        except MacroError as e:
            self.assertEqual('Unknown trac-admin command "copystatic"',
                             unicode(e))
Example #3
0
class ProcessRequestTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.config.set('trac', 'default_handler', 'DefaultHandler')
        self.env.clear_component_registry()

        class DefaultHandler(Component):
            implements(IRequestHandler)

            def match_request(self, req):
                return True

            def process_request(self, req):
                raise req.exc_class("Raised in process_request")

    def tearDown(self):
        self.env.restore_component_registry()

    def test_permission_error_raises_http_forbidden(self):
        """TracError in process_request is trapped and an HTTPForbidden
        error is raised.
        """
        req = MockRequest(self.env)
        req.exc_class = PermissionError

        try:
            RequestDispatcher(self.env).dispatch(req)
        except HTTPForbidden, e:
            self.assertEqual(
                "403 Forbidden (Raised in process_request "
                "privileges are required to perform this operation. You "
                "don't have the required permissions.)", unicode(e))
        else:
Example #4
0
class PreProcessRequestTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.config.set('trac', 'default_handler', 'DefaultHandler')
        self.env.clear_component_registry()

        class DefaultHandler(Component):
            implements(IRequestHandler)

            def match_request(self, req):
                return True

            def process_request(self, req):
                pass

    def tearDown(self):
        self.env.restore_component_registry()

    def test_trac_error_raises_http_internal_server_error(self):
        """TracError in pre_process_request is trapped and an
        HTTPInternalServerError is raised.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                raise TracError("Raised in pre_process_request")

            def post_process_request(self, req, template, data, content_type):
                return template, data, content_type

        req = MockRequest(self.env)

        try:
            RequestDispatcher(self.env).dispatch(req)
        except HTTPInternalServerError as e:
            self.assertEqual("500 Trac Error (Raised in pre_process_request)",
                             unicode(e))
        else:
            self.fail("HTTPInternalServerError not raised")
Example #5
0
class SystemInfoProviderTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.clear_component_registry()

        class SystemInfoProvider1(Component):
            implements(ISystemInfoProvider)

            def get_system_info(self):
                yield 'pkg1', 1.0
                yield 'pkg2', 2.0

        class SystemInfoProvider2(Component):
            implements(ISystemInfoProvider)

            def get_system_info(self):
                yield 'pkg1', 1.0

        self.env.enable_component(SystemInfoProvider1)
        self.env.enable_component(SystemInfoProvider2)

    def tearDown(self):
        self.env.restore_component_registry()

    def test_system_info_property(self):
        """The system_info property returns a list of all tuples
        generated by ISystemInfoProvider implementations.
        """
        system_info = self.env.system_info
        self.assertEqual(system_info, self.env.get_systeminfo())
        self.assertEqual(2, len(system_info))
        self.assertIn(('pkg1', 1.0), system_info)
        self.assertIn(('pkg2', 2.0), system_info)

    def test_duplicate_entries_are_removed(self):
        """Duplicate entries are removed."""
        system_info = self.env.system_info
        self.assertIn(('pkg1', 1.0), system_info)
        self.assertEqual(len(system_info), len(set(system_info)))
Example #6
0
class HdfdumpTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.request_dispatcher = RequestDispatcher(self.env)
        self.req = Mock(chrome={'warnings': []},
                        method='GET',
                        perm=MockPerm(),
                        args={'hdfdump': '1'},
                        session={},
                        callbacks={},
                        send=self._req_send)
        self.content = None
        self.content_type = None
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()

    def _req_send(self, content, content_type='text/html'):
        self.content = content
        self.content_type = content_type
        raise RequestDone()

    def test_hdfdump(self):
        class HdfdumpRequestHandler(Component):
            implements(IRequestHandler)

            def match_request(self, req):
                return True

            def process_request(self, req):
                data = {'name': 'value'}
                return 'error.html', data, None

        self.env.config.set('trac', 'default_handler', 'HdfdumpRequestHandler')
        self.assertRaises(RequestDone, self.request_dispatcher.dispatch,
                          self.req)
        self.assertEqual("{'name': 'value'}\n", self.content)
        self.assertEqual('text/plain', self.content_type)
Example #7
0
class RepositoryAdminPanelTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()
        self.env.reset_db()

    def test_panel_not_exists_when_no_repository_connectors(self):
        """Repositories admin panel is not present when there are
        no repository connectors enabled.
        """
        req = MockRequest(self.env)
        rap = RepositoryAdminPanel(self.env)
        panels = [panel for panel in rap.get_admin_panels(req)]

        self.assertEqual(0, len(panels))

    def test_panel_exists_when_repository_connectors(self):
        """Repositories admin panel is present when there are
        repository connectors enabled.
        """
        class RepositoryConnector(Component):
            implements(IRepositoryConnector)

            def get_supported_types(self):
                yield 'RepositoryConnector', 1

            def get_repository(self, repos_type, repos_dir, params):
                pass

        req = MockRequest(self.env)
        rap = RepositoryAdminPanel(self.env)
        panels = [panel for panel in rap.get_admin_panels(req)]

        self.assertEqual(1, len(panels))
Example #8
0
class AuthenticateTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(disable=['trac.web.auth.LoginModule'])
        self.request_dispatcher = RequestDispatcher(self.env)
        self.req = MockRequest(self.env)
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()

    def test_authenticate_returns_first_successful(self):
        class SuccessfulAuthenticator1(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                return 'user1'

        class SuccessfulAuthenticator2(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                return 'user2'

        self.assertEqual(2, len(self.request_dispatcher.authenticators))
        self.assertIsInstance(self.request_dispatcher.authenticators[0],
                              SuccessfulAuthenticator1)
        self.assertIsInstance(self.request_dispatcher.authenticators[1],
                              SuccessfulAuthenticator2)
        self.assertEqual('user1',
                         self.request_dispatcher.authenticate(self.req))

    def test_authenticate_skips_unsuccessful(self):
        class UnsuccessfulAuthenticator(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                return None

        class SuccessfulAuthenticator(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                return 'user'

        self.assertEqual(2, len(self.request_dispatcher.authenticators))
        self.assertIsInstance(self.request_dispatcher.authenticators[0],
                              UnsuccessfulAuthenticator)
        self.assertIsInstance(self.request_dispatcher.authenticators[1],
                              SuccessfulAuthenticator)
        self.assertEqual('user',
                         self.request_dispatcher.authenticate(self.req))

    def test_authenticate_raises(self):
        class RaisingAuthenticator(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                raise TracError("Bad attempt")

        class SuccessfulAuthenticator(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                return 'user'

        self.assertEqual(2, len(self.request_dispatcher.authenticators))
        self.assertIsInstance(self.request_dispatcher.authenticators[0],
                              RaisingAuthenticator)
        self.assertIsInstance(self.request_dispatcher.authenticators[1],
                              SuccessfulAuthenticator)
        self.assertEqual('anonymous',
                         self.request_dispatcher.authenticate(self.req))
        self.assertEqual(1, len(self.req.chrome['warnings']))
        expected = "Can't authenticate using RaisingAuthenticator: "
        for level, message in self.env.log_messages:
            if expected in message.split('\n'):
                self.assertEqual('ERROR', level)
                break
        else:
            self.fail("Expected log message not found: \"%s\"" % expected)

    def test_authenticate_once(self):
        class Authenticator(Component):
            implements(IAuthenticator)

            def authenticate(self, req):
                authenticated[0] += 1
                return 'admin'

        class AuthenticateRequestHandler(Component):
            implements(IRequestHandler)

            def match_request(self, req):
                return bool(req.perm)

            def process_request(self, req):
                req.authname
                req.send('')

        self.env.config.set('trac', 'default_handler',
                            'AuthenticateRequestHandler')
        authenticated = [0]
        req = MockRequest(self.env)

        self.assertEqual(1, len(self.request_dispatcher.authenticators))
        self.assertIsInstance(self.request_dispatcher.authenticators[0],
                              Authenticator)
        self.assertRaises(RequestDone, self.request_dispatcher.dispatch, req)
        self.assertEqual(1, authenticated[0])
Example #9
0
class PostProcessRequestTestCase(unittest.TestCase):
    """Test cases for handling of the optional `method` argument in
    RequestDispatcher._post_process_request."""
    def setUp(self):
        self.env = EnvironmentStub()
        self.req = MockRequest(self.env)
        self.request_dispatcher = RequestDispatcher(self.env)
        self.compmgr = ComponentManager()
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()

    def test_no_request_filters_request_handler_returns_method_false(self):
        """IRequestHandler doesn't return `method` and no IRequestFilters
        are registered. The `method` is set to `None`.
        """
        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(0, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args + (None, ), resp)

    def test_no_request_filters_request_handler_returns_method_true(self):
        """IRequestHandler returns `method` and no IRequestFilters
        are registered. The `method` is forwarded.
        """
        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(0, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args, resp)

    def test_4arg_post_process_request_request_handler_returns_method_false(
            self):
        """IRequestHandler doesn't return `method` and IRequestFilter doesn't
        accept `method` as an argument. The `method` is set to `None`.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, handler):
                return handler

            def post_process_request(self, req, template, data, content_type):
                return template, data, content_type

        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args + (None, ), resp)

    def test_4arg_post_process_request_request_handler_returns_method_true(
            self):
        """IRequestHandler returns `method` and IRequestFilter doesn't accept
        the argument. The `method` argument is forwarded over IRequestFilter
        implementations that don't accept the argument.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, handler):
                return handler

            def post_process_request(self, req, template, data, content_type):
                return template, data, content_type

        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args, resp)

    def test_5arg_post_process_request_request_handler_returns_method_false(
            self):
        """IRequestHandler doesn't return `method` and IRequestFilter accepts
        `method` as an argument. The `method` is set to `None`.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, method

        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args[:3] + (None, ), resp)

    def test_5arg_post_process_request_request_handler_returns_method_true(
            self):
        """IRequestHandler returns `method` and IRequestFilter accepts
        the argument. The `method` argument is passed through IRequestFilter
        implementations.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, method

        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args, resp)

    def test_5arg_post_process_request_request_handler_adds_method(self):
        """IRequestFilter adds `method` not returned by IRequestHandler.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, 'xml'

        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args[:3] + ('xml', ), resp)

    def test_5arg_post_process_request_request_handler_modifies_method(self):
        """IRequestFilter modifies `method` returned by IRequestHandler.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, 'xml'

        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args[:3] + ('xml', ), resp)
Example #10
0
class ProcessRequestTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.config.set('trac', 'default_handler', 'DefaultHandler')
        self.env.clear_component_registry()

        class DefaultHandler(Component):
            implements(IRequestHandler)

            def match_request(self, req):
                return True

            def process_request(self, req):
                raise req.exc_class("Raised in process_request")

    def tearDown(self):
        self.env.restore_component_registry()

    def test_permission_error_raises_http_forbidden(self):
        """TracError in process_request is trapped and an HTTPForbidden
        error is raised.
        """
        req = MockRequest(self.env)
        req.exc_class = PermissionError

        try:
            RequestDispatcher(self.env).dispatch(req)
        except HTTPForbidden as e:
            self.assertEqual(
                "403 Forbidden (Raised in process_request "
                "privileges are required to perform this operation. You "
                "don't have the required permissions.)", unicode(e))
        else:
            self.fail("HTTPForbidden not raised")

    def test_resource_not_found_raises_http_not_found(self):
        """ResourceNotFound error in process_request is trapped and an
        HTTPNotFound error is raised.
        """
        req = MockRequest(self.env)
        req.exc_class = ResourceNotFound

        try:
            RequestDispatcher(self.env).dispatch(req)
        except HTTPNotFound as e:
            self.assertEqual("404 Trac Error (Raised in process_request)",
                             unicode(e))
        else:
            self.fail("HTTPNotFound not raised")

    def test_trac_error_raises_http_internal_server_error(self):
        """TracError in process_request is trapped and an
        HTTPInternalServerError is raised.
        """
        req = MockRequest(self.env)
        req.exc_class = TracError

        try:
            RequestDispatcher(self.env).dispatch(req)
        except HTTPInternalServerError as e:
            self.assertEqual("500 Trac Error (Raised in process_request)",
                             unicode(e))
        else:
            self.fail("HTTPInternalServerError not raised")

    def test_not_implemented_error_raises_http_internal_server_error(self):
        """NotImplementedError in process_request is trapped and an
        HTTPInternalServerError is raised.
        """
        req = MockRequest(self.env)
        req.exc_class = NotImplementedError

        try:
            RequestDispatcher(self.env).dispatch(req)
        except HTTPInternalServerError as e:
            self.assertEqual(
                "500 Not Implemented Error (Raised in "
                "process_request)", unicode(e))
        else:
            self.fail("HTTPInternalServerError not raised")
Example #11
0
class PostProcessRequestTestCase(unittest.TestCase):
    """Test cases for handling of the optional `method` argument in
    RequestDispatcher._post_process_request."""
    def setUp(self):
        self.env = EnvironmentStub()
        self.req = MockRequest(self.env)
        self.request_dispatcher = RequestDispatcher(self.env)
        self.compmgr = ComponentManager()
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()

    def test_no_request_filters_request_handler_returns_method_false(self):
        """IRequestHandler doesn't return `method` and no IRequestFilters
        are registered. The `method` is set to `None`.
        """
        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(0, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args + (None, ), resp)

    def test_no_request_filters_request_handler_returns_method_true(self):
        """IRequestHandler returns `method` and no IRequestFilters
        are registered. The `method` is forwarded.
        """
        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(0, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args, resp)

    def test_4arg_post_process_request_request_handler_returns_method_false(
            self):
        """IRequestHandler doesn't return `method` and IRequestFilter doesn't
        accept `method` as an argument. The `method` is set to `None`.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self, req, template, data, content_type):
                return template, data, content_type

        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args + (None, ), resp)

    def test_4arg_post_process_request_request_handler_returns_method_true(
            self):
        """IRequestHandler returns `method` and IRequestFilter doesn't accept
        the argument. The `method` argument is forwarded over IRequestFilter
        implementations that don't accept the argument.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self, req, template, data, content_type):
                return template, data, content_type

        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args, resp)

    def test_5arg_post_process_request_request_handler_returns_method_false(
            self):
        """IRequestHandler doesn't return `method` and IRequestFilter accepts
        `method` as an argument. The `method` is set to `None`.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, method

        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args[:3] + (None, ), resp)

    def test_5arg_post_process_request_request_handler_returns_method_true(
            self):
        """IRequestHandler returns `method` and IRequestFilter accepts
        the argument. The `method` argument is passed through IRequestFilter
        implementations.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, method

        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args, resp)

    def test_5arg_post_process_request_request_handler_adds_method(self):
        """IRequestFilter adds `method` not returned by IRequestHandler.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, 'xml'

        args = ('template.html', {}, 'text/html')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args[:3] + ('xml', ), resp)

    def test_5arg_post_process_request_request_handler_modifies_method(self):
        """IRequestFilter modifies `method` returned by IRequestHandler.
        """
        class RequestFilter(Component):
            implements(IRequestFilter)

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self,
                                     req,
                                     template,
                                     data,
                                     content_type,
                                     method=None):
                return template, data, content_type, 'xml'

        args = ('template.html', {}, 'text/html', 'xhtml')
        resp = self.request_dispatcher._post_process_request(self.req, *args)
        self.assertEqual(1, len(self.request_dispatcher.filters))
        self.assertEqual(4, len(resp))
        self.assertEqual(args[:3] + ('xml', ), resp)

    def test_redirect_on_permission_error(self):
        """The post_process_request method can redirect during exception
        handling from an exception raised in process_request.
        """
        class RedirectOnPermissionErrorStub(Component):
            implements(IRequestHandler, IRequestFilter)

            def match_request(self, req):
                return re.match(r'/perm-error', req.path_info)

            def process_request(self, req):
                req.entered_process_request = True
                raise PermissionError("No permission to view")

            def pre_process_request(self, req, handler):
                return handler

            def post_process_request(self, req, template, data, content_type):
                if (template, data, content_type) == (None, None, None):
                    req.entered_post_process_request = True
                    req.redirect(req.href('/redirect-target'))
                return template, data, content_type

        dispatcher = RequestDispatcher(self.env)
        req = MockRequest(self.env, method='GET', path_info='/perm-error')
        req.entered_process_request = False
        req.entered_post_process_request = False

        try:
            dispatcher.dispatch(req)
        except RequestDone:
            pass
        else:
            self.fail("RequestDone not raised")

        self.assertTrue(req.entered_process_request)
        self.assertTrue(req.entered_post_process_request)
Example #12
0
class NavigationOrderTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.clear_component_registry()
        self.req = Request(abs_href=Href('http://example.org/trac.cgi'),
                           href=Href('/trac.cgi'),
                           base_path='/trac.cgi',
                           path_info='/',
                           add_redirect_listener=lambda listener: None)
        self.chrome = Chrome(self.env)

        class TestNavigationContributor1(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'metanav', 'test1', 'Test 1'

        class TestNavigationContributor2(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'metanav', 'test2', 'Test 2'

    def tearDown(self):
        self.env.restore_component_registry()

    def test_explicit_ordering(self):
        """Ordering is explicitly specified."""
        self.env.config.set('metanav', 'test1.order', 2)
        self.env.config.set('metanav', 'test2.order', 1)
        items = self.chrome.prepare_request(self.req)['nav']['metanav']
        self.assertEqual('test2', items[0]['name'])
        self.assertEqual('test1', items[1]['name'])

    def test_partial_explicit_ordering_1(self):
        """Ordering for one item is explicitly specified."""
        self.env.config.set('metanav', 'test1.order', 1)
        items = self.chrome.prepare_request(self.req)['nav']['metanav']
        self.assertEqual('test1', items[0]['name'])
        self.assertEqual('test2', items[1]['name'])

    def test_partial_explicit_ordering_2(self):
        """Ordering for one item is explicitly specified."""
        self.env.config.set('metanav', 'test2.order', 1)
        items = self.chrome.prepare_request(self.req)['nav']['metanav']
        self.assertEqual('test2', items[0]['name'])
        self.assertEqual('test1', items[1]['name'])

    def test_implicit_ordering(self):
        """When not specified, ordering is alphabetical."""
        self.env.config.set('metanav', 'foo.order', 1)
        self.env.config.set('metanav', 'bar.order', 2)

        items = self.chrome.prepare_request(self.req)['nav']['metanav']
        self.assertEqual('test1', items[0]['name'])
        self.assertEqual('test2', items[1]['name'])
Example #13
0
class ChromeTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()

    def _get_navigation_item(self, items, name):
        for item in items:
            if item['name'] == name:
                return item
        return {}

    def test_add_meta(self):
        req = Request(href=Href('/trac.cgi'))
        add_meta(req, 'Jim Smith', name='Author', scheme='test', lang='en-us')
        add_meta(req, 'Tue, 20 Aug 1996 14:25:27 GMT', http_equiv='Expires')
        metas = req.chrome['metas']
        self.assertEqual(2, len(metas))
        meta = metas[0]
        self.assertEqual('Jim Smith', meta['content'])
        self.assertEqual('Author', meta['name'])
        self.assertEqual('test', meta['scheme'])
        self.assertEqual('en-us', meta['lang'])
        self.assertEqual('en-us', meta['xml:lang'])
        meta = metas[1]
        self.assertEqual('Tue, 20 Aug 1996 14:25:27 GMT', meta['content'])
        self.assertEqual('Expires', meta['http-equiv'])

    def test_add_link_simple(self):
        req = Request(href=Href('/trac.cgi'))
        add_link(req, 'start', '/trac/wiki')
        self.assertEqual('/trac/wiki', req.chrome['links']['start'][0]['href'])

    def test_add_link_advanced(self):
        req = Request(href=Href('/trac.cgi'))
        add_link(req, 'start', '/trac/wiki', 'Start page', 'text/html', 'home')
        link = req.chrome['links']['start'][0]
        self.assertEqual('/trac/wiki', link['href'])
        self.assertEqual('Start page', link['title'])
        self.assertEqual('text/html', link['type'])
        self.assertEqual('home', link['class'])

    def test_add_script(self):
        req = Request(base_path='/trac.cgi', href=Href('/trac.cgi'))
        add_script(req, 'common/js/trac.js')
        add_script(req, 'common/js/trac.js')
        add_script(req, 'http://example.com/trac.js')
        add_script(req, '//example.com/trac.js')
        add_script(req, '/dynamic.js')
        add_script(req, 'plugin/js/plugin.js')
        scripts = req.chrome['scripts']
        self.assertEqual(5, len(scripts))
        self.assertEqual('text/javascript', scripts[0]['type'])
        self.assertEqual('/trac.cgi/chrome/common/js/trac.js',
                         scripts[0]['href'])
        self.assertEqual('text/javascript', scripts[1]['type'])
        self.assertEqual('http://example.com/trac.js', scripts[1]['href'])
        self.assertEqual('text/javascript', scripts[2]['type'])
        self.assertEqual('//example.com/trac.js', scripts[2]['href'])
        self.assertEqual('/trac.cgi/dynamic.js', scripts[3]['href'])
        self.assertEqual('/trac.cgi/chrome/plugin/js/plugin.js',
                         scripts[4]['href'])

    def test_add_script_data(self):
        req = Request(href=Href('/trac.cgi'))
        add_script_data(req, {'var1': 1, 'var2': 'Testing'})
        add_script_data(req, var2='More testing', var3=3)
        self.assertEqual({
            'var1': 1,
            'var2': 'More testing',
            'var3': 3
        }, req.chrome['script_data'])

    def test_add_stylesheet(self):
        req = Request(base_path='/trac.cgi', href=Href('/trac.cgi'))
        add_stylesheet(req, 'common/css/trac.css')
        add_stylesheet(req, 'common/css/trac.css')
        add_stylesheet(req, 'https://example.com/trac.css')
        add_stylesheet(req, '//example.com/trac.css')
        add_stylesheet(req, '/dynamic.css')
        add_stylesheet(req, 'plugin/css/plugin.css')
        links = req.chrome['links']['stylesheet']
        self.assertEqual(5, len(links))
        self.assertEqual('text/css', links[0]['type'])
        self.assertEqual('/trac.cgi/chrome/common/css/trac.css',
                         links[0]['href'])
        self.assertEqual('text/css', links[1]['type'])
        self.assertEqual('https://example.com/trac.css', links[1]['href'])
        self.assertEqual('text/css', links[2]['type'])
        self.assertEqual('//example.com/trac.css', links[2]['href'])
        self.assertEqual('/trac.cgi/dynamic.css', links[3]['href'])
        self.assertEqual('/trac.cgi/chrome/plugin/css/plugin.css',
                         links[4]['href'])

    def test_add_stylesheet_media(self):
        req = Request(base_path='/trac.cgi', href=Href('/trac.cgi'))
        add_stylesheet(req, 'foo.css', media='print')
        links = req.chrome['links']['stylesheet']
        self.assertEqual(1, len(links))
        self.assertEqual('print', links[0]['media'])

    def test_add_warning_is_unique(self):
        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='',
                      add_redirect_listener=lambda listener: None)
        Chrome(self.env).prepare_request(req)
        message = random_sentence(5)
        add_warning(req, message)
        add_warning(req, message)
        self.assertEqual(1, len(req.chrome['warnings']))

    def test_add_notice_is_unique(self):
        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='',
                      add_redirect_listener=lambda listener: None)
        Chrome(self.env).prepare_request(req)
        message = random_sentence(5)
        add_notice(req, message)
        add_notice(req, message)
        self.assertEqual(1, len(req.chrome['notices']))

    def _test_add_message_escapes_markup(self, msgtype, add_fn):
        req = Request(chrome={msgtype: []})
        add_fn(req, 'Message with an "&"')
        add_fn(req, Exception("Exception message with an &"))
        add_fn(req, tag("Message with text ", tag.b("& markup")))
        add_fn(req, Markup("Markup <strong>message</strong>."))
        messages = req.chrome[msgtype]
        self.assertIn('Message with an "&amp;"', messages)
        self.assertIn("Exception message with an &amp;", messages)
        self.assertIn("Message with text <b>&amp; markup</b>", messages)
        self.assertIn("Markup <strong>message</strong>.", messages)

    def test_add_warning_escapes_markup(self):
        """Message text is escaped. Regression test for
        http://trac.edgewall.org/ticket/12285
        """
        self._test_add_message_escapes_markup('warnings', add_warning)

    def test_add_notice_escapes_markup(self):
        """Message text is escaped. Regression test for
        http://trac.edgewall.org/ticket/12285
        """
        self._test_add_message_escapes_markup('notices', add_notice)

    def test_htdocs_location(self):
        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='',
                      add_redirect_listener=lambda listener: None)
        info = Chrome(self.env).prepare_request(req)
        self.assertEqual('/trac.cgi/chrome/common/', info['htdocs_location'])

    def test_logo(self):
        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='',
                      add_redirect_listener=lambda listener: None)

        # Verify that no logo data is put in the HDF if no logo is configured
        self.env.config.set('header_logo', 'src', '')
        info = Chrome(self.env).prepare_request(req)
        self.assertNotIn('src', info['logo'])
        self.assertNotIn('src_abs', info['logo'])

        # Test with a relative path to the logo image
        self.env.config.set('header_logo', 'src', 'foo.png')
        info = Chrome(self.env).prepare_request(req)
        self.assertEqual('/trac.cgi/chrome/common/foo.png',
                         info['logo']['src'])
        self.assertEqual('http://example.org/trac.cgi/chrome/common/foo.png',
                         info['logo']['src_abs'])

        # Test with a location in project htdocs
        self.env.config.set('header_logo', 'src', 'site/foo.png')
        info = Chrome(self.env).prepare_request(req)
        self.assertEqual('/trac.cgi/chrome/site/foo.png', info['logo']['src'])
        self.assertEqual('http://example.org/trac.cgi/chrome/site/foo.png',
                         info['logo']['src_abs'])

        # Test with a server-relative path to the logo image
        self.env.config.set('header_logo', 'src', '/img/foo.png')
        info = Chrome(self.env).prepare_request(req)
        self.assertEqual('/img/foo.png', info['logo']['src'])
        self.assertEqual('/img/foo.png', info['logo']['src_abs'])

        # Test with an absolute path to the logo image
        self.env.config.set('header_logo', 'src',
                            'http://www.example.org/foo.png')
        info = Chrome(self.env).prepare_request(req)
        self.assertEqual('http://www.example.org/foo.png', info['logo']['src'])
        self.assertEqual('http://www.example.org/foo.png',
                         info['logo']['src_abs'])

    def test_default_links(self):
        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='',
                      add_redirect_listener=lambda listener: None)
        links = Chrome(self.env).prepare_request(req)['links']
        self.assertEqual('/trac.cgi/wiki', links['start'][0]['href'])
        self.assertEqual('/trac.cgi/search', links['search'][0]['href'])
        self.assertEqual('/trac.cgi/wiki/TracGuide', links['help'][0]['href'])
        self.assertEqual('/trac.cgi/chrome/common/css/trac.css',
                         links['stylesheet'][0]['href'])

    def test_icon_links(self):
        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='',
                      add_redirect_listener=lambda listener: None)
        chrome = Chrome(self.env)

        # No icon set in config, so no icon links
        self.env.config.set('project', 'icon', '')
        links = chrome.prepare_request(req)['links']
        self.assertNotIn('icon', links)
        self.assertNotIn('shortcut icon', links)

        # Relative URL for icon config option
        self.env.config.set('project', 'icon', 'foo.ico')
        links = chrome.prepare_request(req)['links']
        self.assertEqual('/trac.cgi/chrome/common/foo.ico',
                         links['icon'][0]['href'])
        self.assertNotIn('shortcut icon', links)

        # URL relative to the server root for icon config option
        self.env.config.set('project', 'icon', '/favicon.ico')
        links = chrome.prepare_request(req)['links']
        self.assertEqual('/favicon.ico', links['icon'][0]['href'])
        self.assertNotIn('shortcut icon', links)

        # Absolute URL for icon config option
        self.env.config.set('project', 'icon',
                            'http://example.com/favicon.ico')
        links = chrome.prepare_request(req)['links']
        self.assertEqual('http://example.com/favicon.ico',
                         links['icon'][0]['href'])
        self.assertNotIn('shortcut icon', links)

    def test_nav_contributor(self):
        class TestNavigationContributor(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'metanav', 'test', 'Test'

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      path_info='/',
                      base_path='/trac.cgi',
                      add_redirect_listener=lambda listener: None)
        nav = Chrome(self.env).prepare_request(req)['nav']
        self.assertEqual({
            'name': 'test',
            'label': 'Test',
            'active': False
        }, nav['metanav'][0])

    def test_nav_contributor_active(self):
        class TestNavigationContributor(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return 'test'

            def get_navigation_items(self, req):
                yield 'metanav', 'test', 'Test'

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      path_info='/',
                      base_path='/trac.cgi',
                      add_redirect_listener=lambda listener: None)
        handler = TestNavigationContributor(self.env)
        nav = Chrome(self.env).prepare_request(req, handler)['nav']
        self.assertEqual({
            'name': 'test',
            'label': 'Test',
            'active': True
        }, nav['metanav'][0])

    def _get_jquery_ui_script_data(self, lc_time):
        req = Request(href=Href('/trac.cgi'), tz=utc, lc_time=lc_time)
        Chrome(self.env).add_jquery_ui(req)
        return req.chrome['script_data']['jquery_ui']

    def test_add_jquery_ui_is_iso8601(self):
        data = self._get_jquery_ui_script_data('iso8601')
        self.assertIn({'value': -60, 'label': '-01:00'}, data['timezone_list'])
        self.assertIn({'value': 0, 'label': '+00:00'}, data['timezone_list'])
        self.assertIn({'value': 60, 'label': '+01:00'}, data['timezone_list'])

    def test_add_jquery_ui_default_format(self):
        data = self._get_jquery_ui_script_data(locale_en)
        self.assertIsNone(data['timezone_list'])

    def test_invalid_default_dateinfo_format_raises_exception(self):
        self.env.config.set('trac', 'default_dateinfo_format', u'ābšolute')

        self.assertEqual(
            u'ābšolute', self.env.config.get('trac',
                                             'default_dateinfo_format'))
        self.assertRaises(ConfigurationError, getattr, Chrome(self.env),
                          'default_dateinfo_format')

    def test_add_jquery_ui_first_week_day(self):
        def first_week_day(locale, lc_time, languages):
            chrome = Chrome(self.env)
            req = Request(href=Href('/trac.cgi'),
                          locale=locale,
                          lc_time=lc_time,
                          tz=utc,
                          languages=languages)
            chrome.add_jquery_ui(req)
            return req.chrome['script_data']['jquery_ui']['first_week_day']

        # Babel is unavailable
        self.assertEqual(0, first_week_day(None, None, None))
        self.assertEqual(1, first_week_day(None, 'iso8601', None))
        if locale_en:
            # We expect the following aliases
            from babel.core import LOCALE_ALIASES, Locale
            self.assertEqual('ja_JP', LOCALE_ALIASES['ja'])
            self.assertEqual('de_DE', LOCALE_ALIASES['de'])
            self.assertEqual('fr_FR', LOCALE_ALIASES['fr'])

            self.assertEqual(0, first_week_day(locale_en, locale_en, []))
            self.assertEqual(1, first_week_day(locale_en, 'iso8601', []))
            ja = Locale.parse('ja')
            self.assertEqual(0, first_week_day(ja, ja, []))
            self.assertEqual(0, first_week_day(ja, ja, ['ja', 'ja-jp']))
            de = Locale.parse('de')
            self.assertEqual(1, first_week_day(de, de, []))
            self.assertEqual(1, first_week_day(de, de, ['de', 'de-de']))
            fr = Locale.parse('fr')
            self.assertEqual(1, first_week_day(fr, fr, []))
            self.assertEqual(1, first_week_day(fr, fr, ['fr', 'fr-fr']))
            self.assertEqual(0, first_week_day(fr, fr, ['fr', 'fr-ca']))
            # invalid locale identifier (#12408)
            self.assertEqual(1, first_week_day(fr, fr, ['fr', 'fr-']))
            self.assertEqual(0, first_week_day(fr, fr, ['fr', 'fr-', 'fr-ca']))

    def test_add_jquery_ui_timezone_list_has_default_timezone(self):
        chrome = Chrome(self.env)
        href = Href('/trac.cgi')
        gmt07b = timezone('GMT -7:00')
        gmt04a = timezone('GMT +4:00')

        def verify_tzprops(lc_time, tz, tz_default, tz_label):
            req = Request(href=href, locale=locale_en, lc_time=lc_time, tz=tz)
            chrome.add_jquery_ui(req)
            data = req.chrome['script_data']['jquery_ui']
            self.assertEqual(tz_default, data['default_timezone'])
            if tz_default is None:
                self.assertIsNone(data['timezone_list'])
            else:
                self.assertIn({
                    'value': tz_default,
                    'label': tz_label
                }, data['timezone_list'])

        verify_tzprops('iso8601', utc, 0, '+00:00')
        verify_tzprops(locale_en, utc, None, None)
        verify_tzprops('iso8601', gmt07b, -420, '-07:00')
        verify_tzprops(locale_en, gmt07b, None, None)
        verify_tzprops('iso8601', gmt04a, 240, '+04:00')
        verify_tzprops(locale_en, gmt04a, None, None)
        if pytz:
            # must use timezones which does not use DST
            guam = timezone('Pacific/Guam')
            monrovia = timezone('Africa/Monrovia')
            panama = timezone('America/Panama')
            verify_tzprops('iso8601', guam, 600, '+10:00')
            verify_tzprops(locale_en, guam, None, None)
            verify_tzprops('iso8601', monrovia, 0, '+00:00')
            verify_tzprops(locale_en, monrovia, None, None)
            verify_tzprops('iso8601', panama, -300, '-05:00')
            verify_tzprops(locale_en, panama, None, None)

    def test_navigation_item_customization(self):
        class TestNavigationContributor1(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test1', 'Test 1'

        class TestNavigationContributor2(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test2', 'Test 2'

        class TestNavigationContributor3(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test3', 'Test 3'

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='/',
                      add_redirect_listener=lambda listener: None)
        self.env.config.set('mainnav', 'test2.href', 'testtwo')
        self.env.config.set('mainnav', 'test3.label', 'Test Three')
        self.env.config.set('mainnav', 'test3.href', 'testthree')

        chrome = Chrome(self.env)
        items = chrome.prepare_request(req)['nav']['mainnav']

        item = self._get_navigation_item(items, 'test1')
        self.assertEqual('Test 1', item['label'])
        item = self._get_navigation_item(items, 'test2')
        self.assertEqual(str(tag.a('Test 2', href='testtwo')),
                         str(item['label']))
        item = self._get_navigation_item(items, 'test3')
        self.assertEqual(str(tag.a('Test Three', href='testthree')),
                         str(item['label']))

    def test_attributes_preserved_in_navigation_item(self):
        class TestNavigationContributor1(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test1', \
                      tag.a('Test 1', href='test1', target='blank')

        class TestNavigationContributor2(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test2', \
                      tag.a('Test 2', href='test2', target='blank')

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='/',
                      add_redirect_listener=lambda listener: None)
        self.env.config.set('mainnav', 'test1.label', 'Test One')
        self.env.config.set('mainnav', 'test2.label', 'Test Two')
        self.env.config.set('mainnav', 'test2.href', 'testtwo')

        chrome = Chrome(self.env)
        items = chrome.prepare_request(req)['nav']['mainnav']

        item = self._get_navigation_item(items, 'test1')
        self.assertEqual(str(tag.a('Test One', href='test1', target='blank')),
                         str(item['label']))
        item = self._get_navigation_item(items, 'test2')
        self.assertEqual(
            str(tag.a('Test Two', href='testtwo', target='blank')),
            str(item['label']))

    def test_cc_list(self):
        """Split delimited string to a list of email addresses."""
        chrome = Chrome(self.env)
        cc_field1 = '[email protected],[email protected], [email protected]'
        cc_field2 = '[email protected];[email protected]; [email protected]'
        expected = ['*****@*****.**', '*****@*****.**', '*****@*****.**']
        self.assertEqual(expected, chrome.cc_list(cc_field1))
        self.assertEqual(expected, chrome.cc_list(cc_field2))

    def test_cc_list_is_empty(self):
        """Empty list is returned when input is `None` or empty."""
        chrome = Chrome(self.env)
        self.assertEqual([], chrome.cc_list(None))
        self.assertEqual([], chrome.cc_list(''))
        self.assertEqual([], chrome.cc_list([]))
Example #14
0
class NavigationContributorTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.clear_component_registry()

    def tearDown(self):
        self.env.restore_component_registry()

    def _get_navigation_item(self, items, name):
        for item in items:
            if item['name'] == name:
                return item
        return {}

    def test_nav_contributor(self):
        class TestNavigationContributor(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'metanav', 'test', 'Test'

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      path_info='/',
                      base_path='/trac.cgi',
                      add_redirect_listener=lambda listener: None)
        nav = Chrome(self.env).prepare_request(req)['nav']
        self.assertEqual({
            'name': 'test',
            'label': 'Test',
            'active': False
        }, nav['metanav'][0])

    def test_nav_contributor_active(self):
        class TestNavigationContributor(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return 'test'

            def get_navigation_items(self, req):
                yield 'metanav', 'test', 'Test'

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      path_info='/',
                      base_path='/trac.cgi',
                      add_redirect_listener=lambda listener: None)
        handler = TestNavigationContributor(self.env)
        nav = Chrome(self.env).prepare_request(req, handler)['nav']
        self.assertEqual({
            'name': 'test',
            'label': 'Test',
            'active': True
        }, nav['metanav'][0])

    def test_navigation_item_customization(self):
        class TestNavigationContributor1(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test1', 'Test 1'

        class TestNavigationContributor2(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test2', 'Test 2'

        class TestNavigationContributor3(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test3', 'Test 3'

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='/',
                      add_redirect_listener=lambda listener: None)
        self.env.config.set('mainnav', 'test2.href', 'testtwo')
        self.env.config.set('mainnav', 'test3.label', 'Test Three')
        self.env.config.set('mainnav', 'test3.href', 'testthree')

        chrome = Chrome(self.env)
        items = chrome.prepare_request(req)['nav']['mainnav']

        item = self._get_navigation_item(items, 'test1')
        self.assertEqual('Test 1', item['label'])
        item = self._get_navigation_item(items, 'test2')
        self.assertEqual(str(tag.a('Test 2', href='testtwo')),
                         str(item['label']))
        item = self._get_navigation_item(items, 'test3')
        self.assertEqual(str(tag.a('Test Three', href='testthree')),
                         str(item['label']))

    def test_attributes_preserved_in_navigation_item(self):
        class TestNavigationContributor1(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test1', \
                      tag.a('Test 1', href='test1', target='blank')

        class TestNavigationContributor2(Component):
            implements(INavigationContributor)

            def get_active_navigation_item(self, req):
                return None

            def get_navigation_items(self, req):
                yield 'mainnav', 'test2', \
                      tag.a('Test 2', href='test2', target='blank')

        req = Request(abs_href=Href('http://example.org/trac.cgi'),
                      href=Href('/trac.cgi'),
                      base_path='/trac.cgi',
                      path_info='/',
                      add_redirect_listener=lambda listener: None)
        self.env.config.set('mainnav', 'test1.label', 'Test One')
        self.env.config.set('mainnav', 'test2.label', 'Test Two')
        self.env.config.set('mainnav', 'test2.href', 'testtwo')

        chrome = Chrome(self.env)
        items = chrome.prepare_request(req)['nav']['mainnav']

        item = self._get_navigation_item(items, 'test1')
        self.assertEqual(str(tag.a('Test One', href='test1', target='blank')),
                         str(item['label']))
        item = self._get_navigation_item(items, 'test2')
        self.assertEqual(
            str(tag.a('Test Two', href='testtwo', target='blank')),
            str(item['label']))
Example #15
0
class RecursivePolicyTestCase(unittest.TestCase):
    """Test case for policies that perform recursive permission checks."""

    def setUp(self):
        self.env = EnvironmentStub()
        self.env.clear_component_registry()
        decisions = []
        self.decisions = decisions

        class PermissionPolicy1(Component):

            implements(perm.IPermissionPolicy)

            def __init__(self):
                self.call_count = 0

            def check_permission(self, action, username, resource, perm):
                self.call_count += 1
                decision = None
                if 'ACTION_2' in perm(resource):
                    decision = None
                elif action == 'ACTION_1':
                    decision = username == 'user1'
                decisions.append(('policy1', action, decision))
                return decision

        class PermissionPolicy2(Component):

            implements(perm.IPermissionPolicy)

            def __init__(self):
                self.call_count = 0

            def check_permission(self, action, username, resource, perm):
                self.call_count += 1
                decision = None
                if action == 'ACTION_2':
                    decision = username == 'user2'
                decisions.append(('policy2', action, decision))
                return decision

        self.env.enable_component(PermissionPolicy1)
        self.env.enable_component(PermissionPolicy2)
        self.env.config.set('trac', 'permission_policies',
                            'PermissionPolicy1, PermissionPolicy2')
        self.ps = perm.PermissionSystem(self.env)

    def tearDown(self):
        self.env.restore_component_registry()
        self.env.reset_db()

    def test_user1_allowed_by_policy1(self):
        """policy1 consulted for ACTION_1. policy1 and policy2 consulted
        for ACTION_2.
        """
        perm_cache = perm.PermissionCache(self.env, 'user1')
        self.assertTrue('ACTION_1' in perm_cache)
        self.assertEqual(2, self.ps.policies[0].call_count)
        self.assertEqual(1, self.ps.policies[1].call_count)
        self.assertEqual([
            ('policy1', 'ACTION_2', None),
            ('policy2', 'ACTION_2', False),
            ('policy1', 'ACTION_1', True),
        ], self.decisions)

    def test_user2_denied_by_no_decision(self):
        """policy1 and policy2 consulted for ACTION_1. policy1 and
        policy2 consulted for ACTION_2.
        """
        perm_cache = perm.PermissionCache(self.env, 'user2')
        self.assertFalse('ACTION_1' in perm_cache)
        self.assertEqual(2, self.ps.policies[0].call_count)
        self.assertEqual(2, self.ps.policies[1].call_count)
        self.assertEqual([
            ('policy1', 'ACTION_2', None),
            ('policy2', 'ACTION_2', True),
            ('policy1', 'ACTION_1', None),
            ('policy2', 'ACTION_1', None),
        ], self.decisions)

    def test_user1_denied_by_policy2(self):
        """policy1 consulted for ACTION_2. policy2 consulted for ACTION_2.
        """
        perm_cache = perm.PermissionCache(self.env, 'user1')
        self.assertFalse('ACTION_2' in perm_cache)
        self.assertEqual(1, self.ps.policies[0].call_count)
        self.assertEqual(1, self.ps.policies[1].call_count)
        self.assertEqual([
            ('policy1', 'ACTION_2', None),
            ('policy2', 'ACTION_2', False),
        ], self.decisions)

    def test_user1_allowed_by_policy2(self):
        """policy1 consulted for ACTION_2. policy2 consulted for ACTION_2.
        """
        perm_cache = perm.PermissionCache(self.env, 'user2')
        self.assertTrue('ACTION_2' in perm_cache)
        self.assertEqual(1, self.ps.policies[0].call_count)
        self.assertEqual(1, self.ps.policies[1].call_count)
        self.assertEqual([
            ('policy1', 'ACTION_2', None),
            ('policy2', 'ACTION_2', True),
        ], self.decisions)