| 1 | # -*- coding: utf-8 -*- |
|---|
| 2 | # |
|---|
| 3 | # Copyright (C) 2011 Odd Simon Simonsen <oddsimons@gmail.com> |
|---|
| 4 | # Copyright (C) 2012 Ryan J Ollos <ryan.j.ollos@gmail.com> |
|---|
| 5 | # Copyright (C) 2012-2014 Steffen Hoffmann <hoff.st@web.de> |
|---|
| 6 | # |
|---|
| 7 | # This software is licensed as described in the file COPYING, which |
|---|
| 8 | # you should have received as part of this distribution. |
|---|
| 9 | # |
|---|
| 10 | |
|---|
| 11 | import shutil |
|---|
| 12 | import tempfile |
|---|
| 13 | import unittest |
|---|
| 14 | |
|---|
| 15 | from trac.test import EnvironmentStub, MockPerm, MockRequest |
|---|
| 16 | from trac.perm import PermissionSystem, PermissionError |
|---|
| 17 | from trac.web.api import RequestDone |
|---|
| 18 | from trac.web.main import RequestDispatcher |
|---|
| 19 | |
|---|
| 20 | from tractags.api import TagSystem |
|---|
| 21 | from tractags.db import TagSetup |
|---|
| 22 | from tractags.web_ui import TagInputAutoComplete, TagRequestHandler |
|---|
| 23 | from tractags.web_ui import TagTimelineEventFilter, TagTimelineEventProvider |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | class _BaseTestCase(unittest.TestCase): |
|---|
| 27 | |
|---|
| 28 | def setUp(self): |
|---|
| 29 | self.env = EnvironmentStub(enable=['trac.*', 'tractags.*']) |
|---|
| 30 | self.env.path = tempfile.mkdtemp() |
|---|
| 31 | setup = TagSetup(self.env) |
|---|
| 32 | # Current tractags schema is setup with enabled component anyway. |
|---|
| 33 | # Revert these changes for getting a clean setup. |
|---|
| 34 | self._revert_tractags_schema_init() |
|---|
| 35 | setup.upgrade_environment() |
|---|
| 36 | |
|---|
| 37 | self.tag_s = TagSystem(self.env) |
|---|
| 38 | self.tag_rh = TagRequestHandler(self.env) |
|---|
| 39 | |
|---|
| 40 | perms = PermissionSystem(self.env) |
|---|
| 41 | # Revoke default permissions, because more diversity is required here. |
|---|
| 42 | perms.revoke_permission('anonymous', 'TAGS_VIEW') |
|---|
| 43 | perms.revoke_permission('authenticated', 'TAGS_MODIFY') |
|---|
| 44 | perms.grant_permission('reader', 'TAGS_VIEW') |
|---|
| 45 | perms.grant_permission('writer', 'TAGS_MODIFY') |
|---|
| 46 | perms.grant_permission('admin', 'TAGS_ADMIN') |
|---|
| 47 | |
|---|
| 48 | def tearDown(self): |
|---|
| 49 | self.env.shutdown() |
|---|
| 50 | shutil.rmtree(self.env.path) |
|---|
| 51 | |
|---|
| 52 | # Helpers |
|---|
| 53 | |
|---|
| 54 | def _revert_tractags_schema_init(self): |
|---|
| 55 | with self.env.db_transaction as db: |
|---|
| 56 | db("DROP TABLE IF EXISTS tags") |
|---|
| 57 | db("DROP TABLE IF EXISTS tags_change") |
|---|
| 58 | db("DELETE FROM system WHERE name='tags_version'") |
|---|
| 59 | db("DELETE FROM permission WHERE action %s" % db.like(), |
|---|
| 60 | ('TAGS_%',)) |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | class TagInputAutoCompleteTestCase(_BaseTestCase): |
|---|
| 64 | |
|---|
| 65 | def setUp(self): |
|---|
| 66 | _BaseTestCase.setUp(self) |
|---|
| 67 | self.req = MockRequest(self.env) |
|---|
| 68 | self.req.perm = MockPerm() |
|---|
| 69 | self.tac = TagInputAutoComplete(self.env) |
|---|
| 70 | |
|---|
| 71 | # Tests |
|---|
| 72 | |
|---|
| 73 | def test_separator_is_default(self): |
|---|
| 74 | self.assertEqual(' ', self.tac.separator_opt) |
|---|
| 75 | |
|---|
| 76 | def test_separator_is_empty_quotes(self): |
|---|
| 77 | self.env.config.set('tags', 'separator', "''") |
|---|
| 78 | self.assertEqual(' ', self.tac.separator) |
|---|
| 79 | |
|---|
| 80 | def test_separator_is_comma(self): |
|---|
| 81 | self.env.config.set('tags', 'separator', ',') |
|---|
| 82 | self.assertEqual(',', self.tac.separator) |
|---|
| 83 | |
|---|
| 84 | def test_separator_is_quoted_strip_quotes(self): |
|---|
| 85 | self.env.config.set('tags', 'separator', "','") |
|---|
| 86 | self.assertEqual(',', self.tac.separator) |
|---|
| 87 | |
|---|
| 88 | def test_separator_is_quoted_whitespace_strip_quotes(self): |
|---|
| 89 | self.env.config.set('tags', 'separator', "' '") |
|---|
| 90 | self.assertEqual(' ', self.tac.separator) |
|---|
| 91 | |
|---|
| 92 | def test_get_keywords_no_keywords(self): |
|---|
| 93 | self.assertEqual([], self.tac._get_keywords(self.req)) |
|---|
| 94 | |
|---|
| 95 | def test_get_keywords_define_in_config(self): |
|---|
| 96 | self.env.config.set('tags', 'complete_sticky_tags', |
|---|
| 97 | 'tag1, tag2, tag3') |
|---|
| 98 | self.assertEqual(['tag1','tag2','tag3'], |
|---|
| 99 | self.tac._get_keywords(self.req)) |
|---|
| 100 | |
|---|
| 101 | def test_keywords_are_sorted(self): |
|---|
| 102 | self.env.config.set('tags', 'complete_sticky_tags', |
|---|
| 103 | 'tagb, tagc, taga') |
|---|
| 104 | self.assertEqual(['taga','tagb','tagc'], |
|---|
| 105 | self.tac._get_keywords(self.req)) |
|---|
| 106 | |
|---|
| 107 | def test_keywords_duplicates_removed(self): |
|---|
| 108 | self.env.config.set('tags', 'complete_sticky_tags', |
|---|
| 109 | 'tag1, tag1, tag2') |
|---|
| 110 | self.assertEqual(['tag1','tag2'], |
|---|
| 111 | self.tac._get_keywords(self.req)) |
|---|
| 112 | |
|---|
| 113 | def test_implements_irequestfilter(self): |
|---|
| 114 | from trac.web.main import RequestDispatcher |
|---|
| 115 | self.assertTrue(self.tac in RequestDispatcher(self.env).filters) |
|---|
| 116 | |
|---|
| 117 | def test_implements_itemplateprovider(self): |
|---|
| 118 | from trac.web.chrome import Chrome |
|---|
| 119 | self.assertTrue(self.tac in Chrome(self.env).template_providers) |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | class TagRequestHandlerTestCase(_BaseTestCase): |
|---|
| 123 | |
|---|
| 124 | def setUp(self): |
|---|
| 125 | _BaseTestCase.setUp(self) |
|---|
| 126 | |
|---|
| 127 | # Tests |
|---|
| 128 | |
|---|
| 129 | def test_matches(self): |
|---|
| 130 | req = MockRequest(self.env, path_info='/tags', authname='reader') |
|---|
| 131 | self.assertEquals(True, self.tag_rh.match_request(req)) |
|---|
| 132 | |
|---|
| 133 | def test_get_main_page(self): |
|---|
| 134 | req = MockRequest(self.env, path_info='/tags', authname='reader') |
|---|
| 135 | template, data, content_type = self.tag_rh.process_request(req) |
|---|
| 136 | self.assertEqual('tag_view.html', template) |
|---|
| 137 | self.assertIsInstance(content_type, dict) |
|---|
| 138 | self.assertEqual(['checked_realms', 'mincount', 'page_title', |
|---|
| 139 | 'realm_args', |
|---|
| 140 | 'tag_body', 'tag_query', 'tag_realms'], |
|---|
| 141 | sorted(data.keys())) |
|---|
| 142 | |
|---|
| 143 | def test_get_main_page_no_permission(self): |
|---|
| 144 | req = MockRequest(self.env, path_info='/tags', authname='anonymous') |
|---|
| 145 | self.assertRaises(PermissionError, self.tag_rh.process_request, req) |
|---|
| 146 | |
|---|
| 147 | |
|---|
| 148 | class TagTimelineEventFilterTestCase(_BaseTestCase): |
|---|
| 149 | |
|---|
| 150 | def setUp(self): |
|---|
| 151 | _BaseTestCase.setUp(self) |
|---|
| 152 | self.tef = TagTimelineEventFilter(self.env) |
|---|
| 153 | self.tep = TagTimelineEventProvider(self.env) |
|---|
| 154 | |
|---|
| 155 | # Tests |
|---|
| 156 | |
|---|
| 157 | def test_implements_irequestfilter(self): |
|---|
| 158 | from trac.web.main import RequestDispatcher |
|---|
| 159 | self.assertTrue(self.tef in RequestDispatcher(self.env).filters) |
|---|
| 160 | |
|---|
| 161 | def test_tag_query_save(self): |
|---|
| 162 | """Save timeline tag query string in session.""" |
|---|
| 163 | self.assertEqual('tag_query', self.tef.key) |
|---|
| 164 | |
|---|
| 165 | from trac.timeline.web_ui import TimelineModule |
|---|
| 166 | TimelineModule(self.env) |
|---|
| 167 | perms = PermissionSystem(self.env) |
|---|
| 168 | perms.grant_permission('anonymous', 'TAGS_VIEW') |
|---|
| 169 | perms.grant_permission('anonymous', 'TIMELINE_VIEW') |
|---|
| 170 | |
|---|
| 171 | req = MockRequest(self.env, path_info='/timeline', |
|---|
| 172 | args={'tag_query': 'query_str'}) |
|---|
| 173 | dispatcher = RequestDispatcher(self.env) |
|---|
| 174 | self.assertRaises(RequestDone, dispatcher.dispatch, req) |
|---|
| 175 | self.assertEqual('query_str', req.session['timeline.tag_query']) |
|---|
| 176 | |
|---|
| 177 | |
|---|
| 178 | class TagTimelineEventProviderTestCase(_BaseTestCase): |
|---|
| 179 | |
|---|
| 180 | def setUp(self): |
|---|
| 181 | _BaseTestCase.setUp(self) |
|---|
| 182 | self.tep = TagTimelineEventProvider(self.env) |
|---|
| 183 | |
|---|
| 184 | # Tests |
|---|
| 185 | |
|---|
| 186 | def test_implements_itimelineeventsprovider(self): |
|---|
| 187 | from trac.timeline.web_ui import TimelineModule |
|---|
| 188 | self.assertTrue(self.tep in TimelineModule(self.env).event_providers) |
|---|
| 189 | |
|---|
| 190 | |
|---|
| 191 | def test_suite(): |
|---|
| 192 | suite = unittest.TestSuite() |
|---|
| 193 | suite.addTest(unittest.makeSuite(TagInputAutoCompleteTestCase)) |
|---|
| 194 | suite.addTest(unittest.makeSuite(TagRequestHandlerTestCase)) |
|---|
| 195 | suite.addTest(unittest.makeSuite(TagTimelineEventFilterTestCase)) |
|---|
| 196 | suite.addTest(unittest.makeSuite(TagTimelineEventProviderTestCase)) |
|---|
| 197 | return suite |
|---|
| 198 | |
|---|
| 199 | |
|---|
| 200 | if __name__ == '__main__': |
|---|
| 201 | unittest.main(defaultTest='test_suite') |
|---|