示例#1
0
class ReportTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

    def test_sub_var_no_quotes(self):
        req = Mock(hdf=dict())
        sql, args = self.report_module.sql_sub_vars(req, "$VAR",
                                                    {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], args)

    def test_sub_var_quotes(self):
        req = Mock(hdf=dict())
        sql, args = self.report_module.sql_sub_vars(req, "'$VAR'",
                                                    {'VAR': 'value'})
        self.assertEqual("''||%s||''", sql)
        self.assertEqual(['value'], args)

    def test_sub_var_mysql(self):
        req = Mock(hdf=dict())
        env = EnvironmentStub()
        env.db = MockMySQLConnection()
        sql, args = ReportModule(env).sql_sub_vars(req, "'$VAR'",
                                                   {'VAR': 'value'})
        self.assertEqual("concat('', %s, '')", sql)
        self.assertEqual(['value'], args)
示例#2
0
 def expand_macro(self, formatter, name, args):
     req = formatter.req
     chrome = Chrome(self.env)
     report = ReportModule(self.env)
     
     comma_splitter = re.compile(r'(?<!\\),')
     kwargs = {}
     for arg in comma_splitter.split(args):
         arg = arg.replace(r'\,', ',')
         m = re.match(r'\s*[^=]+=', arg)
         if m:
             kw = arg[:m.end() - 1].strip()
             value = arg[m.end():]
             if re.match(r'^\$[A-Z]*$', value):
                value = req.args.get(value[1:])
             kwargs[kw] = value if value!= None else ''
         else:
             if re.match(r'^\$[A-Z]*$', arg):
                arg = req.args.get(arg[1:])
             id = int(arg)
     
     req.args = kwargs
     req.args['page'] = '1'
     template, data, content_type = report._render_view(req, id)
     add_stylesheet(req, 'common/css/report.css')
     
     fullpath = ''
     if pkg_resources.resource_exists('wikireport', 'WikiReport.html'):
         fullpath = pkg_resources.resource_filename('wikireport', 'WikiReport.html')
     else:
         filepath = os.path.dirname(os.path.abspath( __file__ ))
         fullpath = os.path.join(filepath, 'WikiReport.html')
 
     return chrome.render_template(req, fullpath, data, None, fragment=True)
示例#3
0
 def pre_process_request(self, req, handler):
     rmodule = ReportModule(self.env)
     #report's match request. if it's gonna be true then we'll stick in our translator,
     #but only if there's a report id (i.e. it's actually a report page)
     if rmodule.match_request(req) and req.args.get('id', -1) != -1 and req.args.get('action', 'view') == 'view':
         href = ''
         params = rmodule.get_var_args(req)
         if params:
             href = '&' + unicode_urlencode(params)
         add_link(req, 'alternate', '?format=rss&changes=true' + href, _('Changes RSS Feed'),
             'application/xhtml+xml', 'rss')
     return handler
示例#4
0
 def pre_process_request(self, req, handler):
     """Called after initial handler selection, and can be used to change
     the selected handler or redirect request.
     
     Always returns the request handler, even if unchanged.
     """
     rmodule = ReportModule(self.env)
     #report's match request. if it's gonna be true then we'll stick in our translator,
     #but only if there's a report id (i.e. it's actually a report page)
     if rmodule.match_request(req) and 'id' in req.args and req.args.get('action', 'view') == 'view':
         add_link(req, 'alternate', '?format=rss&detailed=true' , _('Detailed RSS Feed'),
             'application/xhtml+xml', 'rss')
     return handler
 def test_report(self):
     mod = ExcelReportModule(self.env)
     req = MockRequest(self.env, path_info='/report/1',
                       args={'id': '1', 'format': 'xls'})
     report_mod = ReportModule(self.env)
     self.assertTrue(report_mod.match_request(req))
     template, data, content_type = report_mod.process_request(req)
     self.assertEqual('report_view.html', template)
     try:
         mod.post_process_request(req, template, data, content_type)
         self.fail('not raising RequestDone')
     except RequestDone:
         content = req.response_sent.getvalue()
         self.assertEqual(self._magic_number, content[:8])
         self.assertEqual(self._mimetype, req.headers_sent['Content-Type'])
示例#6
0
class ReportTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

    def _make_environ(self, scheme='http', server_name='example.org',
                      server_port=80, method='GET', script_name='/trac',
                      **kwargs):
        environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''),
                   'REQUEST_METHOD': method, 'SERVER_NAME': server_name,
                   'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name}
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, args = self.report_module.sql_sub_vars("$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], args)

    def test_sub_var_quotes(self):
        sql, args = self.report_module.sql_sub_vars("'$VAR'", {'VAR': 'value'})
        self.assertEqual(self.env.get_db_cnx().concat("''", '%s', "''"), sql)
        self.assertEqual(['value'], args)

    # Probably not needed anymore
    def test_sub_var_mysql(self):
        env = EnvironmentStub()
        env.db = MockMySQLConnection() # ditto
        sql, args = ReportModule(env).sql_sub_vars("'$VAR'", {'VAR': 'value'})
        self.assertEqual("concat('', %s, '')", sql)
        self.assertEqual(['value'], args)

    def test_csv_escape(self):
        buf = StringIO()
        def start_response(status, headers):
            return buf.write
        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL']
        rows = [('value, needs escaped',)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual('TEST_COL\r\n"value, needs escaped"\r\n',
                         buf.getvalue())
示例#7
0
    def setUp(self):
        self.report_module = ReportModule(self.env)
        self.query_module = QueryModule(self.env)
        self.chrome_module = Chrome(self.env)

        self.perm_sys = PermissionSystem(self.env)
        if self.env.is_component_enabled(ReportModule):
            self.perm_sys.grant_permission('has_report_view', 'REPORT_VIEW')
            self.perm_sys.grant_permission('has_both', 'REPORT_VIEW')
        self.perm_sys.grant_permission('has_ticket_view', 'TICKET_VIEW')
        self.perm_sys.grant_permission('has_both', 'TICKET_VIEW')

        self.tickets_link = lambda href: '<a href="%s">View Tickets</a>' \
                                         % href
示例#8
0
 def pre_process_request(self, req, handler):
     if handler is not ReportModule(self.env):
         return handler
     url = req.path_info
     user = req.authname
     find = url.rfind('/')
     report_id = url[find + 1:]
     try:
         report_id = int(report_id)
     except:
         return handler
     if self._has_permission(user, report_id):
         return handler
     else:
         raise TracError(
             'You don\'t have the permission to access this report',
             'No Permission')
示例#9
0
 def post_process_request(self, req, template, data, content_type):
     """Inject dashboard helpers in data.
     """
     if data is not None:
         data['bhdb'] = DashboardChrome(self.env)
         if isinstance(req.perm.env, ProductEnvironment) \
                 and not 'resourcepath_template' in data \
                 and 'product_list' in data:
             data['resourcepath_template'] = 'bh_path_general.html'
     for item in req.chrome['nav'].get('mainnav', []):
         self.log.debug('%s' % (item, ))
         if item['name'] == 'tickets':
             item['label'] = tag.a(_(self.mainnav_label),
                                   href=req.href.dashboard())
             if item['active'] and \
                     not ReportModule(self.env).match_request(req):
                 add_ctxtnav(req, _('Reports'), href=req.href.report())
             break
     return template, data, content_type
示例#10
0
    def get_navigation_items(self, req):
        # Don't allow this to be exposed
        if 'DO_PRIVATETICKETS_FILTER' in req.args.keys():
            del req.args['DO_PRIVATETICKETS_FILTER']

        # Various ways to allow access
        if not req.perm.has_permission('TICKET_VIEW') and \
           (req.perm.has_permission('TICKET_VIEW_REPORTER') or \
           req.perm.has_permission('TICKET_VIEW_OWNER') or \
           req.perm.has_permission('TICKET_VIEW_CC') or \
           req.perm.has_permission('TICKET_VIEW_REPORTER_GROUP') or \
           req.perm.has_permission('TICKET_VIEW_OWNER_GROUP') or \
           req.perm.has_permission('TICKET_VIEW_CC_GROUP')):
            if TicketModule(self.env).match_request(req):
                if PrivateTicketsSystem(self.env).check_ticket_access(
                        req, req.args['id']):
                    self._grant_view(req)
            elif AttachmentModule(self.env).match_request(req):
                if req.args['type'] == 'ticket' and PrivateTicketsSystem(
                        self.env).check_ticket_access(
                            req, req.args['path'].split('/')[0]):
                    self._grant_view(req)
            elif QueryModule(self.env).match_request(req):
                req.args['DO_PRIVATETICKETS_FILTER'] = 'query'
                self._grant_view(req)  # Further filtering in query.py
            elif SearchModule(self.env).match_request(req):
                if 'ticket' in req.args.keys():
                    req.args['pticket'] = req.args['ticket']
                    del req.args['ticket']
            elif ReportModule(self.env).match_request(req):
                self._grant_view(req)  # So they can see the query page link
                if req.args.get('id'):
                    req.args['DO_PRIVATETICKETS_FILTER'] = 'report'

            # NOTE: Send this back here because the button would be hidden otherwise. <NPK t:1129>
            if not self.env.is_component_enabled(
                    ReportModule) or not req.perm.has_permission(
                        'REPORT_VIEW'):
                return [('mainnav', 'tickets',
                         html.A('View Tickets', href=req.href.query()))]

        return []
示例#11
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.report_module = ReportModule(self.env)
示例#12
0
class ReportTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

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

    def _make_environ(self, scheme='http', server_name='example.org',
                      server_port=80, method='GET', script_name='/trac',
                      **kwargs):
        environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''),
                   'REQUEST_METHOD': method, 'SERVER_NAME': server_name,
                   'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name}
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {'_VAR': 'value1', 'VAR2': 'value2'})
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        self.assertEqual(self.env.get_read_db().concat("''", '%s', "''"), sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()
        def start_response(status, headers):
            return buf.write
        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual('\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
                         buf.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("INSERT INTO report (title,query,description) "
                       "VALUES (%s,%s,%s)", ('redirect', query, ''))
        id = db.get_last_id(cursor, 'report')
        db.commit()

        headers_sent = {}
        def start_response(status, headers):
            headers_sent.update(dict(headers))
        environ = self._make_environ()
        req = Request(environ, start_response)
        req.authname = 'anonymous'
        req.session = Mock(save=lambda: None)
        self.assertRaises(RequestDone,
                          self.report_module._render_view, req, id)
        self.assertEqual('http://example.org/trac/query?' + \
                         'type=r%C3%A9sum%C3%A9&report=' + str(id),
                         headers_sent['Location'])
示例#13
0
def run0(req, env, db, content):
    args = parse(content or '')
    items = []
    summary = None
    ticket = default_ticket_field
    summaries = {}
    inline = False
    nosort = False
    inline_total = False
    title = "Tickets"
    styles = default_styles.copy()
    args_re = re.compile("^(?:" + string.join(args_pat, "|") + ")$")
    # process options first
    for arg in args:
        match = args_re.match(arg)
        if not match:
            env.log.debug('TicketBox: unknown arg: %s' % arg)
            continue
        elif match.group('title'):
            title = match.group('title')[1:-1]
        elif match.group('width'):
            styles['width'] = match.group('width')
        elif match.group('keyword'):
            kw = match.group('keyword').lower()
            kwarg = unquote(match.group('kwarg') or '')
            if kw == 'summary':
                summary = kwarg or default_summary_field
            elif kw == 'ticket':
                ticket = kwarg or default_ticket_field
            elif kw == 'inline':
                inline = True
            elif kw == 'nosort':
                nosort = True
            elif kw == 'nowrap':
                styles['white-space'] = 'nowrap'
            elif kw == 'inline_total':
                inline_total = True
            elif kw in styles and kwarg:
                styles[kw] = kwarg
    # pick up ticket numbers and report numbers
    for arg in args:
        sql = None
        params = []
        match = args_re.match(arg)
        id_name = ticket
        sidx = iidx = -1
        if not match:
            continue
        elif match.group('tktnum'):
            items.append(int(match.group('tktnum')))
        elif match.group('query'):
            if not has_query:
                raise Exception('You cannot use trac query for this version of trac')
            q = Query.from_string(env, match.group('query'))
            sql, params = call(q.get_sql, locals())
            id_name = 'id'
        elif match.group('rptnum') or match.group('rptnum2'):
            num = match.group('rptnum') or match.group('rptnum2')
            #env.log.debug('dynamic variables = %s' % dv)
            curs = db.cursor()
            try:
                curs.execute('SELECT %s FROM report WHERE id=%s'
                             % (report_query_field, num))
                rows = curs.fetchall()
                if len(rows) == 0:
                    raise Exception("No such report: %s"  % num)
                sql = rows[0][0]
            finally:
                curs.close()
            if sql:
                sql = sql.strip()
                if has_query and sql.lower().startswith("query:"):
                    if sql.lower().startswith('query:?'):
                        raise Exception('URL style of query string is not supported.')
                    q = Query.from_string(env, sql[6:])
                    sql, params = call(q.get_sql, locals())
                    id_name = 'id'
        if sql:
            if not params:
                # handle dynamic variables
                # NOTE: sql_sub_vars() takes different arguments in
                #       several trac versions.
                #       For 0.10 or before, arguments are (req, query, args)
                #       For 0.10.x, arguments are (req, query, args, db)
                #       For 0.11 or later, arguments are (query, args, db)
                dv = ReportModule(env).get_var_args(req)
                sql, params = call(ReportModule(env).sql_sub_vars, locals())
            try:
                #env.log.debug('sql = %s' % sql)
                curs = db.cursor()
                curs.execute(sql, params)
                rows = curs.fetchall()
                if rows:
                    descriptions = [desc[0] for desc in curs.description]
                    try:
                        iidx = descriptions.index(id_name)
                    except:
                        raise Exception('No such column for ticket number: %r'
                                        % id_name )
                    if summary:
                        try:
                            sidx = descriptions.index(summary)
                        except:
                            raise Exception('No such column for summary: %r'
                                            % summary)
                    for row in rows:
                        items.append(row[iidx])
                        if summary and 0 <= sidx:
                            summaries[row[iidx]] = row[sidx]
            finally:
                curs.close()

    if summary:
        # get summary text
        for id in items:
            if summaries.get(id):
                continue
            tkt = Ticket(env, tkt_id=id)
            if not tkt:
                continue
            summaries[id] = tkt['summary']
    
    items = uniq(items)
    if not nosort:
        items.sort()
    html = ''

    if inline_total:
        # return simple text of total count to be placed inline.
        return '<span class="ticketbox"><span id="total">%s</span></span>' \
            % len(items)
    
    if ver < [0, 11]:
        fargs = dict(db=db)
    else:
        fargs = dict(db=db, req=req)
    if summary:
        format = '%(summary)s (%(id)s)'
        sep = '<br/>'
    else:
        format = '%(id)s'
        sep = ', '
    lines = []
    for n in items:
        kwds = dict(id="#%d" % n)
        if summary:
            kwds['summary'] = summaries[n]
        lines.append(wiki_to_oneliner(format % kwds, env, **fargs))
    html = sep.join(lines)
    if html:
        try:
            title = title % len(items)  # process %d in title
        except:
            pass
        if inline:
            for key in ['float', 'width']:
                del styles[key]
        style = ';'.join(["%s:%s" % (k,v) for k,v in styles.items() if v])
        return '<fieldset class="ticketbox" style="%s"><legend>%s</legend>%s</fieldset>' % \
               (style, title, html)
    else:
        return ''
示例#14
0
文件: report.py 项目: skshel123/trac
    def test_asc_argument_is_invalid(self):
        """Invalid value for `asc` argument is coerced to default."""
        req = MockRequest(self.env, args={'asc': '--'})

        self.assertRaises(HTTPBadRequest,
                          ReportModule(self.env).process_request, req)
示例#15
0
文件: report.py 项目: skshel123/trac
class ReportModuleTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True)
        self.report_module = ReportModule(self.env)

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

    def _insert_report(self, title, query, description):
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                """
                INSERT INTO report (title,query,description)
                VALUES (%s,%s,%s)
                """, (title, query, description))
            return db.get_last_id(cursor, 'report')

    def test_create_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 9).exists)
        self.assertIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/9',
                         req.headers_sent['Location'])

    def test_create_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'cancel': True,
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 9)
        self.assertNotIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 1)
        self.assertIn("The report {1} has been deleted.",
                      req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'cancel': True,
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 1).exists)
        self.assertNotIn("The report {1} has been deleted.",
                         req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/1',
                         req.headers_sent['Location'])

    def test_update_report(self):
        report = Report(self.env)
        report.query = "SELECT 1"
        report.insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("New Report edited", report.title)
        self.assertEqual("SELECT 2", report.query)
        self.assertEqual("The description edited", report.description)
        self.assertIn("Your changes have been saved.", req.chrome['notices'])

    def test_update_report_cancel(self):
        report = Report(self.env)
        report.query = "SELECT 1"
        report.insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'cancel': True,
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("Active Tickets", report.title)
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", report.description)
        self.assertIn("SELECT p.value AS __color__", report.query)
        self.assertNotIn("Your changes have been saved.",
                         req.chrome['notices'])

    def test_render_confirm_delete(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual("Delete Report {1} Active Tickets", data['title'])
        self.assertEqual('delete', data['action'])
        self.assertEqual(1, data['report']['id'])
        self.assertEqual('Active Tickets', data['report']['title'])

    def test_render_editor(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'edit',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("Active Tickets", data['report']['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n",
            data['report']['description'])
        self.assertIn("SELECT p.value AS __color__", data['report']['sql'])

    def test_render_list(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '-1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual('report', data['sort'])
        self.assertEqual(1, data['asc'])
        self.assertEqual(8, len(data['reports']))
        self.assertEqual(1, data['reports'][0][0])
        self.assertEqual('Active Tickets', data['reports'][0][1])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['reports'][0][2])
        self.assertTrue('Active Reports', data['reports'][0][3])
        self.assertTrue('Active Reports', data['reports'][0][4])

    def test_render_view(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("{1} Active Tickets", data['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['description'])

    def test_render_empty_report(self):
        """Empty report raises a TracError."""
        rid = self._insert_report('Empty report', '', '')
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': rid
                          })
        data = self.report_module.process_request(req)[1]
        self.assertEqual("Report failed: Report {%d} has no SQL query." % rid,
                         data['message'])

    def test_render_view_sort_order_preserved_on_update(self):
        """Sort column and order are preserved on update."""
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': 1,
                              'sort': 'summary',
                              'asc': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['asc'])
        self.assertEqual('summary', data['sort'])

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        req = MockRequest(self.env)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]

        self.assertRaises(RequestDone, self.report_module._send_csv, req, cols,
                          rows)
        self.assertEqual(
            '\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"'
            'value, needs escaped",0\r\n', req.response_sent.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        rid = self._insert_report('redirect', query, '')
        req = MockRequest(self.env)

        self.assertRaises(RequestDone, self.report_module._render_view, req,
                          rid)
        self.assertEqual(
            'http://example.org/trac.cgi/query?' +
            'type=r%C3%A9sum%C3%A9&report=' + str(rid),
            req.headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = MockRequest(self.env)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = u'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(
                req, 1, sql, {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertIsNone(limit_offset)

    def test_value_error_from_get_var_args(self):
        req = MockRequest(self.env, path_info='/report/1')

        def get_var_args(req):
            raise ValueError('<error>')

        self.report_module.get_var_args = get_var_args
        self.assertTrue(self.report_module.match_request(req))
        data = self.report_module.process_request(req)[1]
        self.assertEqual('Report failed: <error>', data['message'])

    def test_title_and_description_with_sub_vars(self):
        with self.env.db_transaction:
            id_ = self._insert_report(
                'Tickets on $M for $USER',
                'SELECT * FROM ticket WHERE milestone=$M AND owner=$USER',
                'Show tickets on $M for $USER')
            for milestone in ('milestone1', 'milestone2'):
                insert_ticket(self.env,
                              status='new',
                              summary='Test 1',
                              owner='joe',
                              milestone=milestone)
        req = MockRequest(self.env,
                          path_info='/report/%d' % id_,
                          authname='joe',
                          args={'M': 'milestone2'})
        self.assertTrue(self.report_module.match_request(req))
        data = self.report_module.process_request(req)[1]
        self.assertEqual('{%d} Tickets on milestone2 for joe' % id_,
                         data['title'])
        self.assertEqual('Show tickets on milestone2 for joe',
                         data['description'])
        self.assertIsNone(data['message'])
        self.assertEqual(1, data['numrows'])

    def test_title_and_description_with_sub_vars_in_sql(self):
        with self.env.db_transaction:
            id_ = self._insert_report(
                'Tickets on $M for $USER', '-- M=milestone1\r\n'
                'SELECT * FROM ticket WHERE milestone=$M AND owner=$USER\r\n',
                'Show tickets on $M for $USER')
            for milestone in ('milestone1', 'milestone2'):
                insert_ticket(self.env,
                              status='new',
                              summary='Test 1',
                              owner='joe',
                              milestone=milestone)
        req = MockRequest(self.env,
                          path_info='/report/%d' % id_,
                          authname='joe')
        self.assertTrue(self.report_module.match_request(req))
        data = self.report_module.process_request(req)[1]
        self.assertEqual('{%d} Tickets on milestone1 for joe' % id_,
                         data['title'])
        self.assertEqual('Show tickets on milestone1 for joe',
                         data['description'])
        self.assertIsNone(data['message'])
        self.assertEqual(1, data['numrows'])

    def test_clear(self):
        req = MockRequest(self.env,
                          method='GET',
                          path_info='/report',
                          args={'action': 'clear'})
        req.session['query_href'] = req.href.query()
        req.session['query_tickets'] = '42'
        self.assertTrue(self.report_module.match_request(req))
        self.assertEqual('report_list.html',
                         self.report_module.process_request(req)[0])
        self.assertIn('query_href', req.session)
        self.assertIn('query_tickets', req.session)

        req = MockRequest(self.env,
                          method='POST',
                          path_info='/report',
                          args={'action': 'clear'})
        self.assertTrue(self.report_module.match_request(req))
        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertNotIn('query_href', req.session)
        self.assertNotIn('query_tickets', req.session)

    def test_valid_html_for_report(self):
        req = MockRequest(
            self.env,
            method='POST',
            path_info='/report',
            args={
                'action': 'new',
                'title': '#13046',
                'query': "SELECT '#13046' AS foo_, 42 AS bar, 'blah' AS _baz_",
                'description': ''
            })
        self.assertTrue(self.report_module.match_request(req))
        self.assertRaises(RequestDone, self.report_module.process_request, req)

        req = MockRequest(self.env, method='GET', path_info='/report/9')
        self.assertTrue(self.report_module.match_request(req))
        rv = self.report_module.process_request(req)
        rendered = Chrome(self.env).render_template(req, rv[0], rv[1], {
            'fragment': False,
            'iterable': False
        })
        self.assertRegexpMatches(
            rendered, r'<tr[^>]*>\s*'
            r'<td class="fullrow foo" colspan="100">'
            r'\s*#13046\s*<hr />\s*</td>\s*</tr>')
        self.assertRegexpMatches(
            rendered, r'<tr[^>]*>\s*'
            r'<td class="fullrow bar" colspan="100">'
            r'\s*42\s*<hr />\s*</td>\s*</tr>')
        self.assertRegexpMatches(
            rendered, r'<tr[^>]*>\s*'
            r'<td class="fullrow baz" colspan="100">'
            r'\s*blah\s*<hr />\s*</td>\s*</tr>')
        if genshi:
            XML(rendered)  # validates as XML

    def test_timestamp_columns(self):
        req = MockRequest(
            self.env,
            method='POST',
            path_info='/report',
            args={
                'action':
                'new',
                'title':
                '#13134',
                'query':
                "SELECT %d AS time, %d AS created, %d AS datetime" %
                ((1 * 86400 + 42) * 1000000, (2 * 86400 + 43) * 1000000,
                 (3 * 86400 + 44) * 1000000),
                'description':
                ''
            })
        self.assertTrue(self.report_module.match_request(req))
        self.assertRaises(RequestDone, self.report_module.process_request, req)

        req = MockRequest(self.env, method='GET', path_info='/report/9')
        self.assertTrue(self.report_module.match_request(req))
        rv = self.report_module.process_request(req)
        rendered = Chrome(self.env).render_template(req, rv[0], rv[1], {
            'fragment': False,
            'iterable': False
        })
        self.assertRegexpMatches(
            rendered, r'<td class="date">\s*(12:00:42 AM|00:00:42)\s*</td>')
        self.assertRegexpMatches(
            rendered, r'<td class="date">\s*(Jan 3, 1970|01/03/70)\s*</td>')
        self.assertRegexpMatches(
            rendered, r'<td class="date">\s*(Jan 4, 1970, 12:00:44 AM|'
            r'01/04/70 00:00:44)\s*</td>')
示例#16
0
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     self.req = Mock(base_path='', chrome={}, args={}, session={},
                     abs_href=Href('/'), href=Href('/'), locale='',
                     perm=MockPerm(), authname=None, tz=None)
     self.report_module = ReportModule(self.env)
示例#17
0
文件: report.py 项目: pkdevbox/trac
class ReportTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

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

    def _make_environ(self, scheme='http', server_name='example.org',
                      server_port=80, method='GET', script_name='/trac',
                      **kwargs):
        environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''),
                   'REQUEST_METHOD': method, 'SERVER_NAME': server_name,
                   'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name}
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {'_VAR': 'value1', 'VAR2': 'value2'})
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()
        def start_response(status, headers):
            return buf.write
        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual('\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
                         buf.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute("INSERT INTO report (title,query,description) "
                           "VALUES (%s,%s,%s)", ('redirect', query, ''))
            id = db.get_last_id(cursor, 'report')

        headers_sent = {}
        def start_response(status, headers):
            headers_sent.update(dict(headers))
        environ = self._make_environ()
        req = Request(environ, start_response)
        req.authname = 'anonymous'
        req.session = Mock(save=lambda: None)
        self.assertRaises(RequestDone,
                          self.report_module._render_view, req, id)
        self.assertEqual('http://example.org/trac/query?' + \
                         'type=r%C3%A9sum%C3%A9&report=' + str(id),
                         headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = Mock(base_path='', chrome={}, args={}, session={},
                   abs_href=Href('/'), href=Href('/'), locale='',
                   perm=MockPerm(), authname=None, tz=None)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = 'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(req, 1, sql,
                                                             {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertEqual(None, limit_offset)
示例#18
0
class ReportTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

    def _make_environ(self,
                      scheme='http',
                      server_name='example.org',
                      server_port=80,
                      method='GET',
                      script_name='/trac',
                      **kwargs):
        environ = {
            'wsgi.url_scheme': scheme,
            'wsgi.input': StringIO(''),
            'REQUEST_METHOD': method,
            'SERVER_NAME': server_name,
            'SERVER_PORT': server_port,
            'SCRIPT_NAME': script_name
        }
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        self.assertEqual(self.env.get_db_cnx().concat("''", '%s', "''"), sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    # Probably not needed anymore
    def test_sub_var_mysql(self):
        env = EnvironmentStub()
        env.db = MockMySQLConnection()  # ditto
        sql, values, missing_args = ReportModule(env).sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        self.assertEqual("concat('', %s, '')", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()

        def start_response(status, headers):
            return buf.write

        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual('TEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
                         buf.getvalue())
示例#19
0
文件: report.py 项目: timgraham/trac
class ReportTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

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

    def _make_environ(self,
                      scheme='http',
                      server_name='example.org',
                      server_port=80,
                      method='GET',
                      script_name='/trac',
                      **kwargs):
        environ = {
            'wsgi.url_scheme': scheme,
            'wsgi.input': StringIO(''),
            'REQUEST_METHOD': method,
            'SERVER_NAME': server_name,
            'SERVER_PORT': server_port,
            'SCRIPT_NAME': script_name
        }
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()

        def start_response(status, headers):
            return buf.write

        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual(
            '\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
            buf.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                "INSERT INTO report (title,query,description) "
                "VALUES (%s,%s,%s)", ('redirect', query, ''))
            id = db.get_last_id(cursor, 'report')

        headers_sent = {}

        def start_response(status, headers):
            headers_sent.update(dict(headers))

        environ = self._make_environ()
        req = Request(environ, start_response)
        req.authname = 'anonymous'
        req.session = Mock(save=lambda: None)
        self.assertRaises(RequestDone, self.report_module._render_view, req,
                          id)
        self.assertEqual('http://example.org/trac/query?' + \
                         'type=r%C3%A9sum%C3%A9&report=' + str(id),
                         headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = Mock(base_path='',
                   chrome={},
                   args={},
                   session={},
                   abs_href=Href('/'),
                   href=Href('/'),
                   locale='',
                   perm=MockPerm(),
                   authname=None,
                   tz=None)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = 'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(
                req, 1, sql, {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertEqual(None, limit_offset)
示例#20
0
class ReportTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

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

    def _make_environ(self, scheme='http', server_name='example.org',
                      server_port=80, method='GET', script_name='/trac',
                      **kwargs):
        environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''),
                   'REQUEST_METHOD': method, 'SERVER_NAME': server_name,
                   'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name}
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {'_VAR': 'value1', 'VAR2': 'value2'})
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        self.assertEqual(self.env.get_read_db().concat("''", '%s', "''"), sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()
        def start_response(status, headers):
            return buf.write
        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual('\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
                         buf.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("INSERT INTO report (title,query,description) "
                       "VALUES (%s,%s,%s)", ('redirect', query, ''))
        id = db.get_last_id(cursor, 'report')
        db.commit()

        headers_sent = {}
        def start_response(status, headers):
            headers_sent.update(dict(headers))
        environ = self._make_environ()
        req = Request(environ, start_response)
        req.authname = 'anonymous'
        req.session = Mock(save=lambda: None)
        self.assertRaises(RequestDone,
                          self.report_module._render_view, req, id)
        self.assertEqual('http://example.org/trac/query?' + \
                         'type=r%C3%A9sum%C3%A9&report=' + str(id),
                         headers_sent['Location'])
示例#21
0
 def get_report_data(self, req, id):
     db = self.env.get_db_cnx()
     _template, data, _content_type = ReportModule(self.env)._render_view(
         req, db, id)
     return data
示例#22
0
文件: report.py 项目: skshel123/trac
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     self.report_module = ReportModule(self.env)
示例#23
0
class ReportModuleTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True)
        self.report_module = ReportModule(self.env)

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

    def test_create_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 9).exists)
        self.assertIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/9',
                         req.headers_sent['Location'])

    def test_create_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'cancel': True,
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 9)
        self.assertNotIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 1)
        self.assertIn("The report {1} has been deleted.",
                      req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'cancel': True,
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 1).exists)
        self.assertNotIn("The report {1} has been deleted.",
                         req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/1',
                         req.headers_sent['Location'])

    def test_update_report(self):
        Report(self.env).insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("New Report edited", report.title)
        self.assertEqual("SELECT 2", report.query)
        self.assertEqual("The description edited", report.description)
        self.assertIn("Your changes have been saved.", req.chrome['notices'])

    def test_update_report_cancel(self):
        Report(self.env).insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'cancel': True,
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("Active Tickets", report.title)
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", report.description)
        self.assertIn("SELECT p.value AS __color__", report.query)
        self.assertNotIn("Your changes have been saved.",
                         req.chrome['notices'])

    def test_render_confirm_delete(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual("Delete Report {1} Active Tickets", data['title'])
        self.assertEqual('delete', data['action'])
        self.assertEqual(1, data['report']['id'])
        self.assertEqual('Active Tickets', data['report']['title'])

    def test_render_editor(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'edit',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("Active Tickets", data['report']['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n",
            data['report']['description'])
        self.assertIn("SELECT p.value AS __color__", data['report']['sql'])

    def test_render_list(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '-1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual('report', data['sort'])
        self.assertEqual(1, data['asc'])
        self.assertEqual(8, len(data['reports']))
        self.assertEqual(1, data['reports'][0][0])
        self.assertEqual('Active Tickets', data['reports'][0][1])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['reports'][0][2])
        self.assertTrue('Active Reports', data['reports'][0][3])
        self.assertTrue('Active Reports', data['reports'][0][4])

    def test_render_view(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("{1} Active Tickets", data['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['description'])

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        req = MockRequest(self.env)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]

        self.assertRaises(RequestDone, self.report_module._send_csv, req, cols,
                          rows)
        self.assertEqual(
            '\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"'
            'value, needs escaped",0\r\n', req.response_sent.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                "INSERT INTO report (title,query,description) "
                "VALUES (%s,%s,%s)", ('redirect', query, ''))
            id = db.get_last_id(cursor, 'report')
        req = MockRequest(self.env)

        self.assertRaises(RequestDone, self.report_module._render_view, req,
                          id)
        self.assertEqual(
            'http://example.org/trac.cgi/query?' +
            'type=r%C3%A9sum%C3%A9&report=' + str(id),
            req.headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = MockRequest(self.env)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = u'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(
                req, 1, sql, {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertEqual(None, limit_offset)
示例#24
0
文件: report.py 项目: skshel123/trac
    def test_invalid_post_request_raises_exception(self):
        req = MockRequest(self.env, method='POST', action=None)

        self.assertRaises(HTTPBadRequest,
                          ReportModule(self.env).process_request, req)
示例#25
0
    def render_macro(self, req, name, txt):
        env = self.env
        hdf = req.hdf

        # get trac version
        ver = [int(x) for x in version.split(".")]

        ## default style values
        styles = {
            "float": "right",
            "background": "#f7f7f0",
            "width": "25%",
        }
        inline_styles = {
            "background": "#f7f7f0",
        }

        args_pat = [
            r"#?(?P<tktnum>\d+)", r"{(?P<rptnum>\d+)}",
            r"\[report:(?P<rptnum2>\d+)(?P<dv>\?.*)?\]",
            r"(?P<width>\d+(pt|px|%))", r"(?P<jourshomme>jourshomme)",
            r"(?P<table_report>table_report)",
            r"(?P<ticket_report>ticket_report)",
            r"(?P<do_not_group_none>do_not_group_none)",
            r"(?P<summary>summary)", r"(?P<inline>inline)",
            r"(?P<title1>'.*')", r'(?P<title2>".*")'
        ]

        ##def execute(hdf, txt, env):
        if not txt:
            txt = ''
        items = []
        long_items = {}
        show_summary = False
        inline = False
        title = "Tickets"
        table_report_option = False
        ticket_report_option = False
        do_not_group_none = True
        theader = ''
        args_re = re.compile("^(?:" + string.join(args_pat, "|") + ")$")
        for arg in [string.strip(s) for s in txt.split(',')]:
            match = args_re.match(arg)
            if not match:
                env.log.debug('TicketBox: unknown arg: %s' % arg)
                continue
            elif match.group('title1'):
                title = match.group('title1')[1:-1]
            elif match.group('title2'):
                title = match.group('title2')[1:-1]
            elif match.group('width'):
                styles['width'] = match.group('width')
            elif match.group('tktnum'):
                items.append(int(match.group('tktnum')))
            elif match.group('summary'):
                show_summary = True
            elif match.group('table_report'):
                table_report_option = True
            elif match.group('ticket_report'):
                ticket_report_option = True
            elif match.group('do_not_group_none'):
                do_not_group_none = False
            elif match.group('inline'):
                inline = True
        for arg in [string.strip(s) for s in txt.split(',')]:
            match = args_re.match(arg)
            if match.group('rptnum') or match.group('rptnum2'):
                num = match.group('rptnum') or match.group('rptnum2')
                dv = {}
                # username, do not override if specified
                if not dv.has_key('USER'):
                    dv['USER'] = hdf.getValue('trac.authname', 'anonymous')
                if match.group('dv'):
                    for expr in string.split(match.group('dv')[1:], '&'):
                        k, v = string.split(expr, '=')
                        dv[k] = v
                #env.log.debug('dynamic variables = %s' % dv)
                db = env.get_db_cnx()
                curs = db.cursor()
                try:
                    curs.execute('SELECT query FROM report WHERE id=%s' % num)
                    (query, ) = curs.fetchone()
                    # replace dynamic variables with sql_sub_vars()
                    # NOTE: sql_sub_vars() takes different arguments in
                    #       several trac versions.
                    #       For 0.10 or before, arguments are (req, query, args)
                    #       For 0.10.x, arguments are (req, query, args, db)
                    #       For 0.11 or later, arguments are (query, args, db)
                    if ver <= [0, 10]:
                        args = (req, query, dv)  # for 0.10 or before
                    elif ver < [0, 11]:
                        args = (req, query, dv, db)  # for 0.10.x
                    else:
                        args = (query, dv, db)  # for 0.11 or later
                    query, dv = ReportModule(env).sql_sub_vars(*args)
                    #env.log.debug('query = %s' % query)
                    curs.execute(query, dv)
                    rows = curs.fetchall()
                    if rows:
                        descriptions = [desc[0] for desc in curs.description]

                        env.log.debug('TEST %s' % descriptions)

                        for descriptions_item in descriptions:
                            theader = theader + '<td> %s </td>' % descriptions_item

                        if do_not_group_none == False:
                            idx = descriptions.index('milestone')
                        else:
                            idx = descriptions.index('ticket')

                        for row in rows:
                            items.append(row[idx])

                            if table_report_option:
                                table_field = ''
                                for descriptions_item in descriptions:
                                    if descriptions_item == 'ticket':
                                        table_field = table_field + '<td> %s </td>' % wiki_to_oneliner(
                                            "#%s" % row[descriptions.index(
                                                descriptions_item)], env,
                                            env.get_db_cnx())
                                    else:
                                        table_field = table_field + '<td> %s </td>' % row[
                                            descriptions.index(
                                                descriptions_item)]
                                long_items[row[idx]] = table_field
                            elif ticket_report_option:
                                table_field = ''
                                for descriptions_item in descriptions:
                                    if descriptions_item == 'ticket':
                                        table_field = table_field + '<li>' + descriptions_item + ': %s' % wiki_to_oneliner(
                                            "#%s" % row[descriptions.index(
                                                descriptions_item)], env,
                                            env.get_db_cnx()) + '</li>'
                                    elif descriptions_item != 'description' and descriptions_item != 'summary':
                                        table_field = table_field + '<li>' + descriptions_item + ': %s, ' % row[
                                            descriptions.index(
                                                descriptions_item)] + '</li>'
                                    long_items[row[idx]] = '<b>%s</b><br/>' % row[
                                        descriptions.index(
                                            'summary'
                                        )] + '<ul>' + table_field + ' </ul>' + wiki_to_html(
                                            row[descriptions.index(
                                                "description")] or '', env,
                                            req, env.get_db_cnx())
                            else:
                                summ = descriptions.index('summary')
                                long_items[row[idx]] = row[summ]
                finally:
                    if not hasattr(env, 'get_cnx_pool'):
                        # without db connection pool, we should close db.
                        curs.close()
                        db.close()

        y = []
        for i in items:
            if not y.count(i):
                y.append(i)

        items = y
        items.sort()
        html = ''
        tfooter = ''
        if show_summary:
            html = string.join([
                wiki_to_oneliner("%s (#%d)" % (v, k), env, env.get_db_cnx())
                for k, v in long_items.iteritems()
            ], "<br>")
        elif table_report_option:
            for k, v in long_items.iteritems():
                if "#%s" % k == "#None" and do_not_group_none and do_not_group_none:
                    tfooter = "<tfoot>%s</tfoot>" % v
                else:
                    html = html + "<tr>%s</tr>" % v
        elif ticket_report_option:
            for k, v in long_items.iteritems():
                if "#%s" % k != "#None":
                    html = html + "%s" % v
        else:
            html = wiki_to_oneliner(
                string.join(["#%s" % c for c in items], ", "), env,
                env.get_db_cnx())

        if html != '':
            try:
                title = title % len(items)  # process %d in title
            except:
                pass
            if inline:
                style = string.join([
                    "%s:%s" % (k, v)
                    for k, v in inline_styles.items() if v <> ""
                ], "; ")
            else:
                style = string.join(
                    ["%s:%s" % (k, v) for k, v in styles.items() if v <> ""],
                    "; ")

            if table_report_option:
                return '<table border=1><caption>' + title + '</caption><thead>' + theader + '</thead><tbody>' + html + '</tbody>' + tfooter + '</table>'
            if ticket_report_option:
                return html
            else:
                return '<fieldset class="ticketbox" style="%s"><legend>%s</legend>%s</fieldset>' % \
                   (style, title, html)
        else:
            return ''
示例#26
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.report_module = ReportModule(self.env)
示例#27
0
    def post_process_request(self, req, template, data, content_type):
        if req.path_info.startswith('/report'):
            data['main_reports'] = [int(id) for id in self.main_reports]
            data['available_reports'] = self.available_reports(req)
        if data and data.get('row_groups'):
            id = req.args.get('id')
            action = req.args.get('action', 'view')
            header_groups = data.get('header_groups')
            row_groups = data.get('row_groups')

            if id and action == 'view':
                req.session['last_used_report'] = id
                if header_groups and len(header_groups) > 0:
                    all_col_names = [
                        col['col'] for header_group in header_groups
                        for col in header_group
                    ]
                    data['column_classes'] = dict(
                        [ (key, value.get('classname')) \
                            for key, value in self.fields_config().items() \
                                if key in all_col_names])
                    if self._are_all_mandatory_fields_found(all_col_names):
                        id_col = all_col_names[0]

                        args = ReportModule(self.env).get_var_args(req)
                        db = self.env.get_db_cnx()
                        cursor = db.cursor()
                        cursor.execute("SELECT query FROM report WHERE id=%s",
                                       (id, ))
                        sql, = cursor.fetchone()
                        sql, args = ReportModule(self.env).sql_sub_vars(
                            sql, args, db)
                        cursor.execute("SELECT DISTINCT __group__, __group_preset__, count("+id_col+") as q, count(*) as fq "+\
                            "FROM (%s) as group_config GROUP BY  __group__, __group_preset__" % sql, args)

                        exec_groups = [(group, preset, quantity, full_quantity)
                                       for group, preset, quantity,
                                       full_quantity in cursor]
                        data['exec_groups'] = req.args[
                            'exec_groups'] = exec_groups
                        paginator = data['paginator']
                        range_start, range_end = paginator.span

                        num_rows = 0
                        num_none_filtered = 0
                        for x, y, quantity, full_quantity in exec_groups:
                            num_rows = num_rows + quantity
                            num_none_filtered = num_none_filtered + full_quantity
                            delta = full_quantity - quantity
                            if range_start and delta and range_start > num_none_filtered:
                                range_start = range_start - delta
                                range_end = range_end - delta

                        paginator.num_items = num_rows

                        num_filtered_on_page = 0
                        for i, (value_for_group,
                                row_group) in enumerate(row_groups):
                            filtered_row_group = [
                                row for row in row_group
                                if (('id' not in row) or row['id'])
                            ]
                            row_groups[i] = (value_for_group,
                                             filtered_row_group)
                            range_end = range_end - (len(row_group) -
                                                     len(filtered_row_group))
                        if range_end > paginator.num_items:
                            range_end = paginator.num_items
                        paginator.span = range_start, range_end
        return (template, data, content_type)