Code

version info in scripts
[roundup.git] / test / test_actions.py
1 from __future__ import nested_scopes\r
2 \r
3 import unittest\r
4 from cgi import FieldStorage, MiniFieldStorage\r
5 \r
6 from roundup import hyperdb\r
7 from roundup.date import Date, Interval\r
8 from roundup.cgi.actions import *\r
9 from roundup.cgi.exceptions import Redirect, Unauthorised, SeriousError\r
10 \r
11 class MockNull:\r
12     def __init__(self, **kwargs):\r
13         for key, value in kwargs.items():\r
14             self.__dict__[key] = value\r
15 \r
16     def __call__(self, *args, **kwargs): return MockNull()\r
17     def __getattr__(self, name):\r
18         # This allows assignments which assume all intermediate steps are Null\r
19         # objects if they don't exist yet.\r
20         #\r
21         # For example (with just 'client' defined):\r
22         #\r
23         # client.db.config.TRACKER_WEB = 'BASE/'\r
24         self.__dict__[name] = MockNull()\r
25         return getattr(self, name)\r
26 \r
27     def __getitem__(self, key): return self\r
28     def __nonzero__(self): return 0\r
29     def __str__(self): return ''\r
30     def __repr__(self): return '<MockNull 0x%x>'%id(self)\r
31 \r
32 def true(*args, **kwargs):\r
33     return 1\r
34 \r
35 class ActionTestCase(unittest.TestCase):\r
36     def setUp(self):\r
37         self.form = FieldStorage()\r
38         self.client = MockNull()\r
39         self.client.form = self.form\r
40 \r
41 class ShowActionTestCase(ActionTestCase):\r
42     def assertRaisesMessage(self, exception, callable, message, *args,\r
43                             **kwargs):\r
44         """An extension of assertRaises, which also checks the exception\r
45         message. We need this because we rely on exception messages when\r
46         redirecting.\r
47         """\r
48         try:\r
49             callable(*args, **kwargs)\r
50         except exception, msg:\r
51             self.assertEqual(str(msg), message)\r
52         else:\r
53             if hasattr(excClass,'__name__'):\r
54                 excName = excClass.__name__\r
55             else:\r
56                 excName = str(excClass)\r
57             raise self.failureException, excName\r
58 \r
59     def testShowAction(self):\r
60         self.client.base = 'BASE/'\r
61 \r
62         action = ShowAction(self.client)\r
63         self.assertRaises(ValueError, action.handle)\r
64 \r
65         self.form.value.append(MiniFieldStorage('@type', 'issue'))\r
66         self.assertRaises(SeriousError, action.handle)\r
67 \r
68         self.form.value.append(MiniFieldStorage('@number', '1'))\r
69         self.assertRaisesMessage(Redirect, action.handle, 'BASE/issue1')\r
70 \r
71     def testShowActionNoType(self):\r
72         action = ShowAction(self.client)\r
73         self.assertRaises(ValueError, action.handle)\r
74         self.form.value.append(MiniFieldStorage('@number', '1'))\r
75         self.assertRaisesMessage(ValueError, action.handle,\r
76             'No type specified')\r
77 \r
78 class RetireActionTestCase(ActionTestCase):\r
79     def testRetireAction(self):\r
80         self.client.db.security.hasPermission = true\r
81         self.client.ok_message = []\r
82         RetireAction(self.client).handle()\r
83         self.assert_(len(self.client.ok_message) == 1)\r
84 \r
85     def testNoPermission(self):\r
86         self.assertRaises(Unauthorised, RetireAction(self.client).execute)\r
87 \r
88     def testDontRetireAdminOrAnonymous(self):\r
89         self.client.db.security.hasPermission=true\r
90         # look up the user class\r
91         self.client.classname = 'user'\r
92         # but always look up admin, regardless of nodeid\r
93         self.client.db.user.get = lambda a,b: 'admin'\r
94         self.assertRaises(ValueError, RetireAction(self.client).handle)\r
95         # .. or anonymous\r
96         self.client.db.user.get = lambda a,b: 'anonymous'\r
97         self.assertRaises(ValueError, RetireAction(self.client).handle)\r
98 \r
99 class SearchActionTestCase(ActionTestCase):\r
100     def setUp(self):\r
101         ActionTestCase.setUp(self)\r
102         self.action = SearchAction(self.client)\r
103 \r
104 class StandardSearchActionTestCase(SearchActionTestCase):\r
105     def testNoPermission(self):\r
106         self.assertRaises(Unauthorised, self.action.execute)\r
107 \r
108     def testQueryName(self):\r
109         self.assertEqual(self.action.getQueryName(), '')\r
110 \r
111         self.form.value.append(MiniFieldStorage('@queryname', 'foo'))\r
112         self.assertEqual(self.action.getQueryName(), 'foo')\r
113 \r
114 class FakeFilterVarsTestCase(SearchActionTestCase):\r
115     def setUp(self):\r
116         SearchActionTestCase.setUp(self)\r
117         self.client.db.classes.getprops = lambda: {'foo': hyperdb.Multilink('foo')}\r
118 \r
119     def assertFilterEquals(self, expected):\r
120         self.action.fakeFilterVars()\r
121         self.assertEqual(self.form.getvalue('@filter'), expected)\r
122 \r
123     def testEmptyMultilink(self):\r
124         self.form.value.append(MiniFieldStorage('foo', ''))\r
125         self.form.value.append(MiniFieldStorage('foo', ''))\r
126 \r
127         self.assertFilterEquals(None)\r
128 \r
129     def testNonEmptyMultilink(self):\r
130         self.form.value.append(MiniFieldStorage('foo', ''))\r
131         self.form.value.append(MiniFieldStorage('foo', '1'))\r
132 \r
133         self.assertFilterEquals('foo')\r
134 \r
135     def testEmptyKey(self):\r
136         self.form.value.append(MiniFieldStorage('foo', ''))\r
137         self.assertFilterEquals(None)\r
138 \r
139     def testStandardKey(self):\r
140         self.form.value.append(MiniFieldStorage('foo', '1'))\r
141         self.assertFilterEquals('foo')\r
142 \r
143     def testStringKey(self):\r
144         self.client.db.classes.getprops = lambda: {'foo': hyperdb.String()}\r
145         self.form.value.append(MiniFieldStorage('foo', 'hello'))\r
146         self.assertFilterEquals('foo')\r
147 \r
148     def testTokenizedStringKey(self):\r
149         self.client.db.classes.getprops = lambda: {'foo': hyperdb.String()}\r
150         self.form.value.append(MiniFieldStorage('foo', 'hello world'))\r
151 \r
152         self.assertFilterEquals('foo')\r
153 \r
154         # The single value gets replaced with the tokenized list.\r
155         self.assertEqual([x.value for x in self.form['foo']], ['hello', 'world'])\r
156 \r
157 class CollisionDetectionTestCase(ActionTestCase):\r
158     def setUp(self):\r
159         ActionTestCase.setUp(self)\r
160         self.action = EditItemAction(self.client)\r
161         self.now = Date('.')\r
162         # round off for testing\r
163         self.now.second = int(self.now.second)\r
164 \r
165     def testLastUserActivity(self):\r
166         self.assertEqual(self.action.lastUserActivity(), None)\r
167 \r
168         self.client.form.value.append(MiniFieldStorage('@lastactivity', str(self.now)))\r
169         self.assertEqual(self.action.lastUserActivity(), self.now)\r
170 \r
171     def testLastNodeActivity(self):\r
172         self.action.classname = 'issue'\r
173         self.action.nodeid = '1'\r
174 \r
175         def get(nodeid, propname):\r
176             self.assertEqual(nodeid, '1')\r
177             self.assertEqual(propname, 'activity')\r
178             return self.now\r
179         self.client.db.issue.get = get\r
180 \r
181         self.assertEqual(self.action.lastNodeActivity(), self.now)\r
182 \r
183     def testCollision(self):\r
184         self.failUnless(self.action.detectCollision(self.now, self.now + Interval("1d")))\r
185         self.failIf(self.action.detectCollision(self.now, self.now - Interval("1d")))\r
186         self.failIf(self.action.detectCollision(None, self.now))\r
187 \r
188 def test_suite():\r
189     suite = unittest.TestSuite()\r
190     suite.addTest(unittest.makeSuite(RetireActionTestCase))\r
191     suite.addTest(unittest.makeSuite(StandardSearchActionTestCase))\r
192     suite.addTest(unittest.makeSuite(FakeFilterVarsTestCase))\r
193     suite.addTest(unittest.makeSuite(ShowActionTestCase))\r
194     suite.addTest(unittest.makeSuite(CollisionDetectionTestCase))\r
195     return suite\r
196 \r
197 if __name__ == '__main__':\r
198     runner = unittest.TextTestRunner()\r
199     unittest.main(testRunner=runner)\r
200 \r