| # 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. |
| |
| import tempfile |
| import json |
| import operator |
| import os |
| from io import BytesIO |
| |
| from tg import tmpl_context as c |
| from cgi import FieldStorage |
| |
| from alluratest.controller import setup_basic_test |
| from ming.orm import ThreadLocalORMSession |
| |
| from allura import model as M |
| from allura.tests import decorators as td |
| from forgetracker import model as TM |
| from forgetracker.site_stats import tickets_stats_24hr |
| from forgetracker.tests.functional.test_root import TrackerTestController |
| |
| |
| class TestApp: |
| |
| def setup_method(self, method): |
| setup_basic_test() |
| |
| @td.with_tracker |
| def test_inbound_email(self): |
| ticket = TM.Ticket.new() |
| ticket.summary = 'test ticket' |
| ticket.description = 'test description' |
| |
| # send a message with no ticket matching it |
| message_id = '123@localhost' |
| message = 'test message' |
| msg = dict(payload=message, message_id=message_id, headers={'Subject': 'test'}) |
| c.app.handle_message('1', msg) |
| # message gets added as a post on the ticket |
| post = M.Post.query.get(_id=message_id) |
| assert post["text"] == message |
| |
| @td.with_tracker |
| def test_inbound_email_no_match(self): |
| # send a message with no ticket matching it |
| message_id = '123@localhost' |
| message = 'test message' |
| msg = dict(payload=message, message_id=message_id, headers={'Subject': 'test'}) |
| # no ticket matching it |
| c.app.handle_message('6789', msg) |
| # no new message |
| post = M.Post.query.get(_id=message_id) |
| assert post == None |
| |
| @td.with_tracker |
| def test_uninstall(self): |
| t = TM.Ticket.new() |
| t.summary = 'new ticket' |
| ThreadLocalORMSession.flush_all() |
| assert TM.Ticket.query.get(summary='new ticket') |
| # c.app.uninstall(c.project) errors out, but works ok in test_uninstall for repo tools. So instead: |
| c.project.uninstall_app('bugs') |
| assert not TM.Ticket.query.get(summary='new ticket') |
| |
| @td.with_tracker |
| def test_tickets_stats_24hr(self): |
| # invoked normally via entry point |
| TM.Ticket.new() |
| TM.Ticket.new() |
| assert 2 == tickets_stats_24hr() |
| |
| @td.with_tracker |
| def test_sitemap_xml(self): |
| assert [] == c.app.sitemap_xml() |
| TM.Ticket.new() |
| assert 1 == len(c.app.sitemap_xml()) |
| |
| @td.with_tracker |
| def test_sitemap_xml_ignored(self): |
| TM.Ticket.new(form_fields=dict(deleted=True)) |
| assert [] == c.app.sitemap_xml() |
| # still add to sitemap even if only tickets are closed |
| TM.Ticket.new(form_fields=dict( |
| status=c.app.globals.closed_status_names[0])) |
| assert 1 == len(c.app.sitemap_xml()) |
| |
| |
| class TestBulkExport(TrackerTestController): |
| |
| @td.with_tracker |
| def setup_with_tools(self): |
| super().setup_with_tools() |
| self.project = M.Project.query.get(shortname='test') |
| self.tracker = self.project.app_instance('bugs') |
| self.new_ticket(summary='foo', _milestone='1.0') |
| self.new_ticket(summary='bar', _milestone='2.0') |
| self.ticket = TM.Ticket.query.find(dict(summary='foo')).first() |
| self.post = self.ticket.discussion_thread.add_post(text='silly comment') |
| ThreadLocalORMSession.flush_all() |
| test_file1 = FieldStorage() |
| test_file1.name = 'file_info' |
| test_file1.filename = 'test_file' |
| test_file1.file = BytesIO(b'test file1\n') |
| self.post.add_attachment(test_file1) |
| ThreadLocalORMSession.flush_all() |
| |
| def test_bulk_export(self): |
| # Clear out some context vars, to properly simulate how this is run from the export task |
| # Besides, core functionality shouldn't need the c context vars |
| c.app = c.project = None |
| |
| f = tempfile.TemporaryFile('w+') |
| self.tracker.bulk_export(f) |
| f.seek(0) |
| tracker = json.loads(f.read()) |
| |
| tickets = sorted(tracker['tickets'], |
| key=operator.itemgetter('summary')) |
| assert len(tickets) == 2 |
| ticket_foo = tickets[1] |
| assert ticket_foo['summary'] == 'foo' |
| assert ticket_foo['custom_fields']['_milestone'] == '1.0' |
| posts_foo = ticket_foo['discussion_thread']['posts'] |
| assert len(posts_foo) == 1 |
| assert posts_foo[0]['text'] == 'silly comment' |
| |
| tracker_config = tracker['tracker_config'] |
| assert 'options' in list(tracker_config.keys()) |
| assert tracker_config['options']['mount_point'] == 'bugs' |
| |
| milestones = sorted(tracker['milestones'], |
| key=operator.itemgetter('name')) |
| assert milestones[0]['name'] == '1.0' |
| assert milestones[1]['name'] == '2.0' |
| |
| saved_bins_summaries = [bin['summary'] |
| for bin in tracker['saved_bins']] |
| assert 'Closed Tickets' in saved_bins_summaries |
| |
| def test_export_with_attachments(self): |
| |
| f = tempfile.TemporaryFile('w+') |
| temp_dir = tempfile.mkdtemp() |
| self.tracker.bulk_export(f, temp_dir, True) |
| f.seek(0) |
| tracker = json.loads(f.read()) |
| tickets = sorted(tracker['tickets'], |
| key=operator.itemgetter('summary')) |
| file_path = os.path.join( |
| 'bugs', |
| str(self.ticket._id), |
| str(self.post.thread_id), |
| self.post.slug, |
| 'test_file' |
| ) |
| assert tickets[1]['discussion_thread']['posts'][0]['attachments'][0]['path'] == file_path |
| os.path.exists(file_path) |