Olemis Lang avatar Olemis Lang committed a76b7bf

GViz providers : test_gviz.py is a verbatim copy of test_rpc.py . Nothing else done before either

Comments (0)

Files changed (2)

trac-dev/gviz/tracgviz/testing/test_gviz.py

 
 r"""In this file you'll find part of the tests written to ensure that 
-some GViz components delivered by this package behave as expected. 
+some RPC components delivered by this package behave as expected. 
 
 Only the tests requiring minimal setup effort are included below. 
 This means that the environment used to run these tests contains the 
 (magically) available in the global namespace (i.e. provided that 
 the test name be written like `xmlrpc_namespace: Descriptive message`):
 
-  - req           A dummy request object setup for anonymous access.
-  - auth_req      A dummy request object setup like if user `murphy` was  
-                  accessing the site.
-  - env           the Trac environment used as a stub for testing 
-                  purposes. This object is an instance of 
-                  `tracgviz.testing.EnvironmentStub`.
-  - gvizobj       an object providing access to the functionalities 
-                  implemented by the RPC handler under test.
-                  In practice this object is either a wrapper around the 
-                  instance of `IRequestHandler` (which supplies a dummy 
-                  request object to the corresponding RPC method) or 
-                  an instance of `xmlrpclib._Method` providing access to 
-                  the same method via XML-RPC protocol. Further 
-                  scenarios may be added in the future (e.g. to test 
-                  other RPC transports like JSON-RPC).
-  - auth_gvizobj  an object just like the former but used to perform 
-                  authenticated XML-RPC calls on behalf of `murphy`.
-                  Dont worry, tests pass anyway ... Murphy can't 
-                  fight against our power ! :P
-  - ticket_data   A set of tickets used for testing purposes.
+  - req         A dummy request object setup for anonymous access.
+  - auth_req    A dummy request object setup like if user `murphy` was  
+                accessing the site.
+  - env         the Trac environment used as a stub for testing purposes.
+                This object is an instance of 
+                `tracgviz.testing.EnvironmentStub`.
+  - rpcobj      an object providing access to the functionalities 
+                implemented by the RPC handler under test.
+                In practice this object is either a wrapper around the 
+                instance of `IRequestHandler` (which supplies a dummy 
+                request object to the corresponding RPC method) or 
+                an instance of `xmlrpclib._Method` providing access to 
+                the same method via XML-RPC protocol. Further 
+                scenarios may be added in the future (e.g. to test 
+                other RPC transports like JSON-RPC).
+  - auth_rpcobj an object just like the former but used to perform 
+                authenticated XML-RPC calls on behalf of `murphy`.
+                Dont worry, tests pass anyway ... Murphy can't 
+                fight against our power ! :P
+  - ticket_data A set of tickets used for testing purposes.
 """
 __author__ = 'Olemis Lang'
 
 #------------------------------------------------------
 
 def test_suite():
+  from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, REPORT_UDIFF
   from dutest import MultiTestLoader
-  from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, REPORT_UDIFF
   from unittest import defaultTestLoader
 
   from tracgviz.testing import DocTestRpcLoader, ticket_data
   l = MultiTestLoader(
         [defaultTestLoader, \
           DocTestRpcLoader(extraglobs=magic_vars, \
-                            enable=['trac.*', 'tracrpc.*', \
-                                        'tracgviz.*'], \
+                            enable=[
+                                'trac.*', 'tracrpc.*', 'tracgviz.*'
+                              ], \
                             default_data=True,
-                            optionflags=ELLIPSIS | # REPORT_UDIFF | \
+                            optionflags=ELLIPSIS | REPORT_UDIFF | \
                                         NORMALIZE_WHITESPACE) \
         ])
 
 from datetime import datetime, time, date
 from itertools import izip
 
+from tracgviz.testing import clear_perm_cache
+
 def print_timeline_filters(rpcobj):
   for filter_desc in sorted(rpcobj.getEventFilters()):
     print tuple(filter_desc)
     print '= Row', i, '='
     for coldsc in cols:
       colnm = coldsc[0]
-      print 'Column:', colnm, 'Value:', row.get(colnm), ''
+      print 'Column:', colnm, 'Value:', row.get(colnm) or None, ''
 
-def clear_perm_cache(_env, _req):
-  from trac.perm import PermissionSystem, DefaultPermissionPolicy
+TICKET_ATTRS = ('summary', 'description', 'priority', \
+                'milestone', 'type', 'owner', 'status', \
+                'component', 'version')
 
-  _req.perm._cache.clear()            # Clear permission cache
-  for policy in PermissionSystem(_env).policies :
-    if isinstance(policy, DefaultPermissionPolicy):
-      policy.permission_cache.clear() # Clear policy cache
-      break
+def prepare_ticket_workflow(tcktrpc, ticket_data, auth_req):
+  r"""Set ticket status considering the actions defined in standard 
+  ticket workflow. Needed for TracRpc>=1.0.6
+  """
+  from time import sleep
+
+  TICKET_ACTIONS = {'accepted': 'accept', 'closed' : 'resolve',
+                    'assigned': 'reassign'}
+  sleep(1)
+  for idx, (_, __, td) in enumerate(ticket_data) :
+    action = TICKET_ACTIONS.get(td.get('status'))
+    if action is not None :
+      aux_attrs = {'action' : action}
+      aux_attrs.update(td)
+      tcktrpc.update(auth_req, idx + 1, "", aux_attrs)
+  sleep(1)
+  for idx, (_, __, td) in enumerate(ticket_data) :
+    tcktrpc.update(auth_req, idx + 1, "", td)
 
 __test__ = {
     '|timeline: Event filters' : r"""
       # Disable version control ... for a while ;o)
+      >>> env.enabled.clear()                     # Clear cache
       >>> tracvcs = 'trac.versioncontrol.*'
       >>> env.disable_component(tracvcs)
       >>> from trac.versioncontrol.web_ui.changeset import ChangesetModule
       >>> env.config.set('timeline', 'ticket_show_details', 'false')
       >>> env.config.save()
 
-      >>> env[ChangesetModule] is None
-      True
-
       >>> print_timeline_filters(rpcobj)
       ('milestone', 'Milestones reached')
       ('ticket', 'Tickets opened and closed')
       Wiki... imported from ...
       Wiki... imported from ...
 
+      >>> cnx.commit()
+
       # Everything Ok ?
       >>> from tracrpc.wiki import WikiRPC
       >>> sorted(WikiRPC(env).getAllPages(req))
       >>> timestamp = timestamp.replace(year=timestamp.year - 2)
 
       >>> print_timeline_events(rpcobj.getEvents(timestamp, None, ['milestone']))
-      ['milestone', '', '20...', ..., 'http://example.org/trac.cgi/milestone/World-wide%20domination', 'Milestone <em>World-wide domination</em> completed', "<p>\nI'll rule the world. My Trac is my weapon\n</p>\n"]
+      ['milestone', '', '2...', ..., 'http://example.org/trac.cgi/milestone/World-wide%20domination', 'Milestone <em>World-wide domination</em> completed', "<p>\nI'll rule the world. My Trac is my weapon\n</p>\n"]
 
       >>> from trac.util.datefmt import _epoc
       >>> print_timeline_events(rpcobj.getEvents(_epoc, timestamp, ['milestone']))
       ['milestone', '', '1970-01-01 00:00:00+00:00', 0L, 'http://example.org/trac.cgi/milestone/milestone2', 'Milestone <em>milestone2</em> completed', '']
       ['milestone', '', '1970-01-01 00:00:00+00:00', 0L, 'http://example.org/trac.cgi/milestone/milestone3', 'Milestone <em>milestone3</em> completed', '']
       ['milestone', '', '1970-01-01 00:00:00+00:00', 0L, 'http://example.org/trac.cgi/milestone/milestone4', 'Milestone <em>milestone4</em> completed', '']
-      ['milestone', '', '20...', ..., 'http://example.org/trac.cgi/milestone/World-wide%20domination', 'Milestone <em>World-wide domination</em> completed', "<p>\nI'll rule the world. My Trac is my weapon\n</p>\n"]
+      ['milestone', '', '2...', ..., 'http://example.org/trac.cgi/milestone/World-wide%20domination', 'Milestone <em>World-wide domination</em> completed', "<p>\nI'll rule the world. My Trac is my weapon\n</p>\n"]
       """,
     '|timeline: Retrieving ticket events' : r"""
       # Open tickets
       # ... hidden using default configuration ...
       >>> print_timeline_events(rpcobj.getEvents(None, None, ['ticket']))
       ['newticket', u'murphy', '...', ..., 'http://example.org/trac.cgi/ticket/1', 'Ticket <em title="task: Test TracGViz plugin (new)">#1</em> (Test TracGViz plugin) created', '<p>\nGod bless the devs who test their Trac plugins using dutest<br />\n</p>\n']
+
       >>> print_timeline_events(rpcobj.getEvents(None, None, ['ticket_details']))         # Milestone hidden
 
       # ... visible otherwise ;o)
       >>> env.config.save()
       >>> print_timeline_events(rpcobj.getEvents(None, None, ['ticket']))
       ['newticket', u'murphy', '...', ..., 'http://example.org/trac.cgi/ticket/1', 'Ticket <em title="task: Test TracGViz plugin (new)">#1</em> (Test TracGViz plugin) created', '<p>\nGod bless the devs who test their Trac plugins using dutest<br />\n</p>\n']
+
       >>> print_timeline_events(rpcobj.getEvents(None, None, ['ticket_details']))         # Milestone visible
       ['editedticket', u'murphy', '...', ..., 'http://example.org/trac.cgi/ticket/1#comment:1', 'Ticket <em title="task: Test TracGViz plugin (edit)">#1</em> (Test TracGViz plugin) updated', '<i>Milestone</i> changed<br/><p>\nWanna do it right away<br />\n</p>\n']
 
       >>> controllers = list(tmdl._get_action_controllers(auth_req, t, \
       ...                           'accept'))
       >>> now = datetime.now(localtz)
-      >>> is_saved = t.save_changes('murphy', comment, when=now, cnum=cnum)
-      >>> is_saved
+      >>> is_saved = t.save_changes('murphy', comment, when=now, cnum=str(cnum))
+      >>> bool(is_saved)
       True
 
       # After saving the changes, apply the side-effects.
       Active Tickets
       Description
       -----------
+      <BLANKLINE>
        * List all active tickets by priority.
        * Color each row based on priority.
       <BLANKLINE>
       Active Tickets by Version
       Description
       -----------
+      <BLANKLINE>
       This report shows how to color results by priority,
       while grouping results by version.
       <BLANKLINE>
       Active Tickets by Milestone
       Description
       -----------
+      <BLANKLINE>
       This report shows how to color results by priority,
       while grouping results by milestone.
       <BLANKLINE>
       Accepted, Active Tickets by Owner
       Description
       -----------
+      <BLANKLINE>
       List accepted tickets, group by ticket owner, sorted by priority.
       <BLANKLINE>
       Query
       Accepted, Active Tickets by Owner (Full Description)
       Description
       -----------
+      <BLANKLINE>
       List tickets accepted, group by ticket owner.
       This report demonstrates the use of full-row display.
       <BLANKLINE>
       All Tickets By Milestone  (Including closed)
       Description
       -----------
+      <BLANKLINE>
       A more complex example to show how to make advanced reports.
       <BLANKLINE>
       Query
       My Tickets
       Description
       -----------
-      This report demonstrates the use of the automatically set 
+      <BLANKLINE>
+      This report demonstrates the use of the automatically set
       USER dynamic variable, replaced with the username of the
       logged in user when executed.
       <BLANKLINE>
       Active Tickets, Mine first
       Description
       -----------
+      <BLANKLINE>
        * List all active tickets by priority.
        * Show all tickets owned by the logged in user in a group first.
       <BLANKLINE>
       Query
       -----
+      <BLANKLINE>
       SELECT p.value AS __color__,
-         (CASE owner 
-           WHEN $USER THEN 'My Tickets' 
-           ELSE 'Active Tickets' 
+         (CASE owner
+           WHEN $USER THEN 'My Tickets'
+           ELSE 'Active Tickets'
           END) AS __group__,
-         id AS ticket, summary, component, version, milestone, t.type AS type, 
+         id AS ticket, summary, component, version, milestone, t.type AS type,
          owner, status,
          time AS created,
          changetime AS _changetime, description AS _description,
          reporter AS _reporter
         FROM ticket t
         LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority'
-        WHERE status <> 'closed' 
+        WHERE status <> 'closed'
         ORDER BY (COALESCE(owner, '') = $USER) DESC, CAST(p.value AS integer), milestone, t.type, time
       <BLANKLINE>
-
       """,
     '|report: Executing SQL reports' : r"""
       # Column information is not available if there's no base result.
       Column: _reporter Type: string Label: _
       = Report 7 =
       Column: __color__ Type: string Label: _
+      Column: __group Type: string Label: _
       Column: __group__ Type: string Label: _
       Column: ticket Type: string Label: _
       Column: summary Type: string Label: _
       8
       9
 
+      >>> if all(tcktrpc.get(auth_req, tid)[-1].get('status') == 'new' \
+      ...            for tid in xrange(1, 10)):
+      ...   # RPC considers ticket workflow
+      ...   prepare_ticket_workflow(tcktrpc, ticket_data, auth_req)
+      ...
+
+      # Hack needed for deterministic order when exec-ing report 6
+      >>> from time import sleep
+      >>> _ = tcktrpc.update(auth_req, 7, "", {'cc' : ' '})
+      >>> for tid in (8, 9):
+      ...   sleep(1)
+      ...   _ = tcktrpc.update(auth_req, tid, "", {'cc' : ' '})
+      ... 
+
+      # Check everything is ok with tickets
+      >>> for tid in xrange(1, 10):
+      ...   d = tcktrpc.get(auth_req, tid)[-1]
+      ...   print tuple(d.get(attr) for attr in TICKET_ATTRS)
+      (u'Ticket 1', u'Description 1', u'major', u'milestone1', 
+          u'defect', u'murphy', u'accepted', u'component1', u'1.0')
+      (u'Ticket 2', u'Description 2', u'major', u'milestone4', 
+          u'task', u'murphy', u'accepted', u'', u'')
+      (u'Ticket 3', u'Description 3', u'critical', u'milestone3', 
+          u'enhancement', u'tester', u'new', u'', u'2.0')
+      (u'Ticket 4', u'Description 4', u'minor', u'milestone3', 
+          u'task', u'murphy', u'closed', u'component1', u'1.0')
+      (u'Ticket 5', u'Description 5', u'minor', u'milestone3', 
+          u'task', u'murphy', u'new', u'', u'2.0')
+      (u'Ticket 6', u'Description 6', u'minor', u'milestone1', 
+          u'task', u'tester', u'assigned', u'component2', u'1.0')
+      (u'Ticket 7', u'Description 7', u'critical', u'', u'enhancement', 
+          u'murphy', u'closed', u'', u'')
+      (u'Ticket 8', u'Description 8', u'major', u'', u'task', 
+          u'murphy', u'closed', u'component1', u'')
+      (u'Ticket 9', u'Description 9', u'minor', u'', u'enhancement', 
+          u'tester', u'closed', u'', u'2.0')
+
       # Now it should work -- well mostly, because not all fields 
       #                       have been included in example tickets.
       >>> cols = auth_rpcobj.enum_columns(1)
       Column: milestone Value: milestone1
       Column: type Value: task
       Column: owner Value: tester
-      Column: status Value: accepted
+      Column: status Value: assigned
       Column: created Value: ... 
       Column: _changetime Value: ... 
       Column: _description Value: Description 6
       Column: version Value: 1.0
       Column: type Value: task
       Column: owner Value: tester
-      Column: status Value: accepted
+      Column: status Value: assigned
       Column: created Value: ... 
       Column: _changetime Value: ... 
       Column: _description Value: Description 6
       Column: version Value: 1.0
       Column: type Value: task
       Column: owner Value: tester
-      Column: status Value: accepted
+      Column: status Value: assigned
       Column: created Value: ... 
       Column: _changetime Value: ... 
       Column: _description Value: Description 6
       Column: _changetime Value: ... 
       Column: _description Value: Description 2
       Column: _reporter Value: murphy
-      = Row 2 =
-      Column: __color__ Value: 4
-      Column: __group__ Value: tester
-      Column: ticket Value: 6
-      Column: summary Value: Ticket 6
-      Column: component Value: component2
-      Column: milestone Value: milestone1
-      Column: type Value: task
-      Column: created Value: ... 
-      Column: _changetime Value: ... 
-      Column: _description Value: Description 6
-      Column: _reporter Value: murphy
 
       >>> cols = auth_rpcobj.enum_columns(5)
       >>> print_report_columns(cols)
       Column: _description_ Value: Description 2
       Column: _changetime Value: ... 
       Column: _reporter Value: murphy
-      = Row 2 =
-      Column: __color__ Value: 4
-      Column: __group__ Value: tester
-      Column: ticket Value: 6
-      Column: summary Value: Ticket 6
-      Column: component Value: component2
-      Column: milestone Value: milestone1
-      Column: type Value: task
-      Column: created Value: ... 
-      Column: _description_ Value: Description 6
-      Column: _changetime Value: ... 
-      Column: _reporter Value: murphy
 
       >>> cols = auth_rpcobj.enum_columns(6)
       >>> print_report_columns(cols)
       Column: type Value: task
       Column: priority Value: major
       Column: owner Value: murphy
-      Column: modified Value: ... 
-      Column: _time Value: ... 
+      Column: modified Value: ...
+      Column: _time Value: ...
       Column: _reporter Value: murphy
       = Row 1 =
       Column: __color__ Value: 2
       Column: ticket Value: 6
       Column: summary Value: Ticket 6
       Column: component Value: component2
-      Column: status Value: accepted
+      Column: status Value: assigned
       Column: resolution Value: None
       Column: version Value: 1.0
       Column: type Value: task
       Column: _time Value: ... 
       Column: _reporter Value: murphy
       = Row 6 =
-      Column: __color__ Value: 2
-      Column: __group__ Value: None
-      Column: __style__ Value: color: #777; background: #ddd; border-color: #ccc;
-      Column: ticket Value: 7
-      Column: summary Value: Ticket 7
-      Column: component Value: None
-      Column: status Value: closed
-      Column: resolution Value: None
-      Column: version Value: None
-      Column: type Value: enhancement
-      Column: priority Value: critical
-      Column: owner Value: murphy
+      Column: __color__ Value: 4 
+      Column: __group__ Value: None 
+      Column: __style__ Value: color: #777; background: #ddd; border-color: #ccc; 
+      Column: ticket Value: 9 
+      Column: summary Value: Ticket 9 
+      Column: component Value: None 
+      Column: status Value: closed 
+      Column: resolution Value: None 
+      Column: version Value: 2.0 
+      Column: type Value: enhancement 
+      Column: priority Value: minor 
+      Column: owner Value: tester 
       Column: modified Value: ... 
       Column: _time Value: ... 
-      Column: _reporter Value: murphy
+      Column: _reporter Value: murphy 
       = Row 7 =
-      Column: __color__ Value: 4
-      Column: __group__ Value: None
-      Column: __style__ Value: color: #777; background: #ddd; border-color: #ccc;
-      Column: ticket Value: 8
-      Column: summary Value: Ticket 8
-      Column: component Value: component1
-      Column: status Value: closed
-      Column: resolution Value: None
-      Column: version Value: None
-      Column: type Value: task
-      Column: priority Value: minor
-      Column: owner Value: murphy
+      Column: __color__ Value: 3 
+      Column: __group__ Value: None 
+      Column: __style__ Value: color: #777; background: #ddd; border-color: #ccc; 
+      Column: ticket Value: 8 
+      Column: summary Value: Ticket 8 
+      Column: component Value: component1 
+      Column: status Value: closed 
+      Column: resolution Value: None 
+      Column: version Value: None 
+      Column: type Value: task 
+      Column: priority Value: major 
+      Column: owner Value: murphy 
       Column: modified Value: ... 
       Column: _time Value: ... 
-      Column: _reporter Value: murphy
+      Column: _reporter Value: murphy 
       = Row 8 =
-      Column: __color__ Value: 4
-      Column: __group__ Value: None
-      Column: __style__ Value: color: #777; background: #ddd; border-color: #ccc;
-      Column: ticket Value: 9
-      Column: summary Value: Ticket 9
-      Column: component Value: None
-      Column: status Value: closed
-      Column: resolution Value: None
-      Column: version Value: 2.0
-      Column: type Value: enhancement
-      Column: priority Value: minor
-      Column: owner Value: tester
+      Column: __color__ Value: 2 
+      Column: __group__ Value: None 
+      Column: __style__ Value: color: #777; background: #ddd; border-color: #ccc; 
+      Column: ticket Value: 7 
+      Column: summary Value: Ticket 7 
+      Column: component Value: None 
+      Column: status Value: closed 
+      Column: resolution Value: None 
+      Column: version Value: None 
+      Column: type Value: enhancement 
+      Column: priority Value: critical 
+      Column: owner Value: murphy 
       Column: modified Value: ... 
       Column: _time Value: ... 
-      Column: _reporter Value: murphy
+      Column: _reporter Value: murphy 
 
       >>> cols = auth_rpcobj.enum_columns(7)
       >>> print_report_columns(cols)
-      Column: __color__ Type: string Label: _
+      Column: __color__ Type: number Label: _
+      Column: __group Type: number Label: _
       Column: __group__ Type: string Label: _
       Column: ticket Type: number Label: _
       Column: summary Type: string Label: _
       >>> print_report_result(cols, auth_rpcobj.execute(7))
       = Row 0 =
       Column: __color__ Value: 3
+      Column: __group Value: 1
       Column: __group__ Value: Accepted
       Column: ticket Value: 1
       Column: summary Value: Ticket 1
       Column: _reporter Value: murphy
       = Row 1 =
       Column: __color__ Value: 3
+      Column: __group Value: 1
       Column: __group__ Value: Accepted
       Column: ticket Value: 2
       Column: summary Value: Ticket 2
       Column: _reporter Value: murphy
       = Row 2 =
       Column: __color__ Value: 4
+      Column: __group Value: 2
       Column: __group__ Value: Owned
       Column: ticket Value: 5
       Column: summary Value: Ticket 5
       Column: _changetime Value: ... 
       Column: _description Value: Description 5
       Column: _reporter Value: murphy
+      = Row 3 =
+      Column: __color__ Value: 2
+      Column: __group Value: 3
+      Column: __group__ Value: Reported
+      Column: ticket Value: 3
+      Column: summary Value: Ticket 3
+      Column: component Value: None
+      Column: version Value: 2.0
+      Column: milestone Value: milestone3
+      Column: type Value: enhancement
+      Column: priority Value: critical
+      Column: created Value: ...
+      Column: _changetime Value: ...
+      Column: _description Value: Description 3
+      Column: _reporter Value: murphy
+      = Row 4 =
+      Column: __color__ Value: 4
+      Column: __group Value: 3
+      Column: __group__ Value: Reported
+      Column: ticket Value: 6
+      Column: summary Value: Ticket 6
+      Column: component Value: component2
+      Column: version Value: 1.0
+      Column: milestone Value: milestone1
+      Column: type Value: task
+      Column: priority Value: minor
+      Column: created Value: ...
+      Column: _changetime Value: ...
+      Column: _description Value: Description 6
+      Column: _reporter Value: murphy
 
       >>> cols = auth_rpcobj.enum_columns(8)
       >>> print_report_columns(cols)
       Column: milestone Value: milestone1
       Column: type Value: task
       Column: owner Value: tester
-      Column: status Value: accepted
+      Column: status Value: assigned
       Column: created Value: ... 
       Column: _changetime Value: ... 
       Column: _description Value: Description 6
       ...                     'stored using query: prefix).', \
       ...                                                     \
       ...                     'query:owner=murphy&status=closed&' \
-      ...                     'col=id&col=summary&' \
+      ...                     'order=id&col=id&col=summary&' \
       ...                     'col=type&col=status&col=priority&' \
       ...                     'col=milestone&col=component&' \
       ...                     'col=version&col=resolution&' \
       using query: prefix).
       Query
       -----
-      query:owner=murphy&status=closed&col=id&col=summary&col=type&col=status&col=priority&col=milestone&col=component&col=version&col=resolution&col=reporter&col=keywords&col=cc&col=time&col=changetime
+      query:owner=murphy&status=closed&order=id&col=id&col=summary&col=type&col=status&col=priority&col=milestone&col=component&col=version&col=resolution&col=reporter&col=keywords&col=cc&col=time&col=changetime
 
       # Ticket data is not needed to list columns in result set
       >>> cols = auth_rpcobj.enum_columns(9)
       Column: resolution Type: string Label: Resolution
       Column: keywords Type: string Label: Keywords
       Column: cc Type: string Label: Cc
-      Column: changetime Type: number Label: Modified
-      Column: time Type: number Label: Created
+      Column: time Type: string Label: Created
+      Column: changetime Type: string Label: Modified
       Column: href Type: string Label: URL
       Column: id Type: number Label: Ticket
 
       8
       9
 
+      >>> if all(tcktrpc.get(auth_req, tid)[-1].get('status') == 'new' \
+      ...            for tid in xrange(1, 10)):
+      ...   # RPC considers ticket workflow
+      ...   prepare_ticket_workflow(tcktrpc, ticket_data, auth_req)
+      ...
+
+      # Check everything is ok with tickets
+      >>> for tid in xrange(1, 10):
+      ...   d = tcktrpc.get(auth_req, tid)[-1]
+      ...   print tuple(d.get(attr) for attr in TICKET_ATTRS)
+      (u'Ticket 1', u'Description 1', u'major', u'milestone1', 
+          u'defect', u'murphy', u'accepted', u'component1', u'1.0')
+      (u'Ticket 2', u'Description 2', u'major', u'milestone4', 
+          u'task', u'murphy', u'accepted', u'', u'')
+      (u'Ticket 3', u'Description 3', u'critical', u'milestone3', 
+          u'enhancement', u'tester', u'new', u'', u'2.0')
+      (u'Ticket 4', u'Description 4', u'minor', u'milestone3', 
+          u'task', u'murphy', u'closed', u'component1', u'1.0')
+      (u'Ticket 5', u'Description 5', u'minor', u'milestone3', 
+          u'task', u'murphy', u'new', u'', u'2.0')
+      (u'Ticket 6', u'Description 6', u'minor', u'milestone1', 
+          u'task', u'tester', u'assigned', u'component2', u'1.0')
+      (u'Ticket 7', u'Description 7', u'critical', u'', u'enhancement', 
+          u'murphy', u'closed', u'', u'')
+      (u'Ticket 8', u'Description 8', u'major', u'', u'task', 
+          u'murphy', u'closed', u'component1', u'')
+      (u'Ticket 9', u'Description 9', u'minor', u'', u'enhancement', 
+          u'tester', u'closed', u'', u'2.0')
+
       # Executing the query
       >>> print_report_result(cols, auth_rpcobj.execute(9))
       = Row 0 =
-      Column: summary Value: Ticket 7
-      Column: reporter Value: murphy
-      Column: owner Value: murphy
-      Column: description Value: None
-      Column: type Value: enhancement
-      Column: status Value: closed
-      Column: priority Value: critical
-      Column: milestone Value: --
-      Column: component Value: --
-      Column: version Value: --
-      Column: resolution Value: --
-      Column: keywords Value: --
-      Column: cc Value: --
-      Column: changetime Value: ... 
-      Column: time Value: ... 
-      Column: href Value: http://example.org/trac.cgi/gviz/ticket/7
-      Column: id Value: 7
-      = Row 1 =
       Column: summary Value: Ticket 4
       Column: reporter Value: murphy
       Column: owner Value: murphy
       Column: milestone Value: milestone3
       Column: component Value: component1
       Column: version Value: 1.0
-      Column: resolution Value: --
-      Column: keywords Value: --
-      Column: cc Value: --
+      Column: resolution Value: None
+      Column: keywords Value: None
+      Column: cc Value: None
+      Column: time Value: ... 
       Column: changetime Value: ... 
+      Column: href Value: http://example.org/trac.cgi/ticket/4
+      Column: id Value: 4
+      = Row 1 =
+      Column: summary Value: Ticket 7
+      Column: reporter Value: murphy
+      Column: owner Value: murphy
+      Column: description Value: None
+      Column: type Value: enhancement
+      Column: status Value: closed
+      Column: priority Value: critical
+      Column: milestone Value: None
+      Column: component Value: None
+      Column: version Value: None
+      Column: resolution Value: None
+      Column: keywords Value: None
+      Column: cc Value: None
       Column: time Value: ... 
-      Column: href Value: http://example.org/trac.cgi/gviz/ticket/4
-      Column: id Value: 4
+      Column: changetime Value: ... 
+      Column: href Value: http://example.org/trac.cgi/ticket/7
+      Column: id Value: 7
       = Row 2 =
       Column: summary Value: Ticket 8
       Column: reporter Value: murphy
       Column: description Value: None
       Column: type Value: task
       Column: status Value: closed
-      Column: priority Value: minor
-      Column: milestone Value: --
+      Column: priority Value: major
+      Column: milestone Value: None
       Column: component Value: component1
-      Column: version Value: --
-      Column: resolution Value: --
-      Column: keywords Value: --
-      Column: cc Value: --
+      Column: version Value: None
+      Column: resolution Value: None
+      Column: keywords Value: None
+      Column: cc Value: None
+      Column: time Value: ... 
       Column: changetime Value: ... 
-      Column: time Value: ... 
-      Column: href Value: http://example.org/trac.cgi/gviz/ticket/8
+      Column: href Value: http://example.org/trac.cgi/ticket/8
       Column: id Value: 8
 
       >>> ps.revoke_permission('murphy', 'REPORT_CREATE')
       Traceback (most recent call last):
         ...
       PermissionError
+
       >>> 'REPORT_CREATE' in auth_req.perm
       False
       >>> auth_rpcobj.create('RiP Query', 'Never gets created', \
       Traceback (most recent call last):
         ...
       PermissionError
+
       >>> 'REPORT_SQL_VIEW' in req.perm
       False
       >>> print_report_metadata(rpcobj.get(1))
       Active Tickets
       Description
       -----------
+      <BLANKLINE>
        * List all active tickets by priority.
        * Color each row based on priority.
       <BLANKLINE>
       Query
       -----
+      <BLANKLINE>
       SELECT p.value AS __color__,
-         id AS ticket, summary, component, version, milestone, t.type AS type, 
+         id AS ticket, summary, component, version, milestone, t.type AS type,
          owner, status,
          time AS created,
          changetime AS _changetime, description AS _description,

trac-dev/gviz/tracgviz/testing/test_rpc.py

   from dutest import MultiTestLoader
   from unittest import defaultTestLoader
 
-  from __init__ import DocTestRpcLoader, ticket_data
+  from tracgviz.testing import DocTestRpcLoader, ticket_data
 
   magic_vars = dict(ticket_data=ticket_data)
   l = MultiTestLoader(
 from datetime import datetime, time, date
 from itertools import izip
 
-from __init__ import clear_perm_cache
+from tracgviz.testing import clear_perm_cache
 
 def print_timeline_filters(rpcobj):
   for filter_desc in sorted(rpcobj.getEventFilters()):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.