Source

bloodhound-dashboard / bhdashboard / tests / test_report.py

Full commit
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you under the Apache License, Version 2.0 (the
#  "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing,
#  software distributed under the License is distributed on an
#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#  KIND, either express or implied.  See the License for the
#  specific language governing permissions and limitations
#  under the License.


r"""Project dashboard for Apache(TM) Bloodhound

In this file you'll find part of the tests written to ensure that
widgets displaying contents generated by TracReports 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 
barely minimal information included in an environment (i.e. only the 
data specified by `trac.db_default.get_data`.).

Once the tests are started all built-in components (except 
trac.versioncontrol.* ) as well as widget system and extensions
are loaded. Besides the following values are (auto-magically)
made available in the global namespace (i.e. provided that 
the test name be written like `|widget_name: 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 
                `bhdashboard.tests.EnvironmentStub`.
  - widget      the widget provider under test.
  - ctx         context used to render widget for anonymous user.
  - ctx_auth    context used to render widget for `murphy` user.
  - ticket_data A set of tickets used for testing purposes.
"""

#------------------------------------------------------
#    Test artifacts
#------------------------------------------------------

def test_suite():
  from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, REPORT_UDIFF
  from dutest import MultiTestLoader
  from unittest import defaultTestLoader
  
  from __init__ import DocTestWidgetLoader, ticket_data
  
  magic_vars = dict(ticket_data=ticket_data)
  l = MultiTestLoader(
        [defaultTestLoader, \
          DocTestWidgetLoader(extraglobs=magic_vars, \
                            enable=['trac.[a-uw-z]*', 'bhdashboard.*'], \
                            default_data=True, \
                            optionflags=ELLIPSIS | # REPORT_UDIFF | \
                                        NORMALIZE_WHITESPACE) \
        ])
  
  import sys
  return l.loadTestsFromModule(sys.modules[__name__])

#------------------------------------------------------
#    Helper functions
#------------------------------------------------------

from datetime import datetime, time, date
from itertools import izip
from pprint import pprint

from __init__ import clear_perm_cache

def print_report_metadata(report_desc):
  for attrnm in ('id', 'title', 'description', 'query'):
    print attrnm.capitalize()
    print '-' * len(attrnm)
    print report_desc[attrnm]

def print_report_columns(cols):
  for coldsc in cols:
    print 'Column:', coldsc[0], 'Type:', coldsc[1] or '_', \
          'Label:', 
    try :
      print coldsc[2] or '_'
    except IndexError :
      print '_'

def print_report_result(cols, data):
  for i, row in enumerate(data):
    print '= Row', i, '='
    for coldsc in cols:
      colnm = coldsc[0]
      print 'Column:', colnm, 'Value:', row.get(colnm) or None, ''

TICKET_ATTRS = ('summary', 'description', 'priority', \
                'milestone', 'type', 'owner', 'status', \
                'component', 'version')

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__ = {
    'Initialization: Report widgets' : r"""
      >>> from trac.core import ComponentMeta
      >>> from bhdashboard.api import IWidgetProvider
      >>> from bhdashboard.widgets.report import *
      >>> allcls = ComponentMeta._registry.get(IWidgetProvider, [])
      >>> [wpcls in allcls for wpcls in (TicketReportWidget,)]
      [True]
      """,
    '|TicketReport: Metadata' : r"""
      >>> list(widget.get_widgets())
      ['TicketReport']
      >>> params = widget.get_widget_params('TicketReport')
      >>> pprint(params)
      {'id': {'desc': 'Report number',
                  'required': True,
                  'type': <type 'int'>},
       'limit': {'default': 0,
                  'desc': 'Number of results to retrieve',
                  'type': <type 'int'>}}
      """,
    '|TicketReport: Render My Tickets report' : r"""
      >>> widget.render_widget('TicketReport', ctx, {
      ...     'args' : {'id' : 7}
      ...   })
      ...
      """,
    '|TicketReport: Render a subset of My Tickets report' : r"""
      >>> widget.render_widget('TicketReport', ctx, {
      ...     'args' : {'id' : 7}
      ...   })
      ...
      """,
    '|TicketReport: Invalid widget name' : r"""
      >>> widget.render_widget('OlkswSk', ctx, {
      ...     'args' : {'id' : 1, 'limit' : 8}
      ...   })
      ...
      Traceback (most recent call last):
        ...
      InvalidIdentifier: Widget name MUST match any of TicketReport
      """,
    '|TicketReport: Invalid report ID in arguments' : r"""
      >>> widget.render_widget('TicketReport', ctx, {
      ...     'args' : {'id' : 99999}
      ...   })
      ...
      Traceback (most recent call last):
        ...
      InvalidIdentifier: Report 99999 does not exist
      """,
    '|TicketReport: Missing required arguments' : r"""
      >>> widget.render_widget('TicketReport', ctx, {
      ...     'args' : {}
      ...   })
      ...
      Traceback (most recent call last):
        ...
      InvalidWidgetArgument: Invalid argument `id`. Required parameter expected

      >>> widget.render_widget('TicketReport', ctx, {
      ...     'args' : {}
      ...   })
      ...
      Traceback (most recent call last):
        ...
      InvalidWidgetArgument: Invalid argument `id`. Required parameter expected
      """,
    '|TicketReport: Invalid widget parameter' : r"""
      >>> widget.render_widget('TicketReport', ctx, {
      ...     'args' : {'newjums' : 7, 'id' : 3}
      ...   })
      ...
      """,
    '|TicketReport: Invalid report definition' : r"""
      >>> raise NotImplementedError()
      """,
  }