def test_no_disown_from_changed_component(self): """ Verify that a ticket is not disowned when the component is changed to a non-assigned component. """ component1 = Component(self.env) component1.name = 'test1' component1.owner = 'joe' component1.insert() component2 = Component(self.env) component2.name = 'test2' component2.owner = '' component2.insert() ticket = Ticket(self.env) ticket['reporter'] = 'santa' ticket['summary'] = 'Foo' ticket['component'] = 'test1' ticket['status'] = 'new' tktid = ticket.insert() ticket = Ticket(self.env, tktid) ticket['component'] = 'test2' ticket.save_changes('jane', 'Testing') self.assertEqual('joe', ticket['owner'])
def test_modify_missing_cnums_and_comment(self): """Editing a comment when all cnums are missing and one comment field is missing """ with self.env.db_transaction as db: db("UPDATE ticket_change SET oldvalue='' WHERE oldvalue='1'") db("""DELETE FROM ticket_change WHERE field='comment' AND oldvalue='1.2'""") db("UPDATE ticket_change SET oldvalue='' WHERE oldvalue='3'") # Modify after missing comment ticket = Ticket(self.env, self.id) t = self.created + timedelta(seconds=50) ticket.modify_comment(self._find_change(ticket, 3), 'joe', 'New comment 3', t) self.assertChange(ticket, 3, self.t3, 'jim', keywords=dict(author='jim', old='a, b, c', new='a, b'), comment=dict(author='jim', old='', new='New comment 3'), _comment0=dict(author='joe', old='Comment 3', new=str(to_utimestamp(t)))) # Modify missing comment t = self.created + timedelta(seconds=60) ticket.modify_comment(self._find_change(ticket, 2), 'joe', 'New comment 2', t) self.assertChange(ticket, 2, self.t2, 'john', owner=dict(author='john', old='john', new='jack'), comment=dict(author='john', old='', new='New comment 2'), _comment0=dict(author='joe', old='', new=str(to_utimestamp(t))))
def test_owner_from_changed_component(self): """ Verify that the owner of a new ticket is updated when the component is changed. """ component1 = Component(self.env) component1.name = 'test1' component1.owner = 'joe' component1.insert() component2 = Component(self.env) component2.name = 'test2' component2.owner = 'kate' component2.insert() ticket = Ticket(self.env) ticket['reporter'] = 'santa' ticket['summary'] = 'Foo' ticket['component'] = 'test1' ticket['status'] = 'new' tktid = ticket.insert() ticket = Ticket(self.env, tktid) ticket['component'] = 'test2' ticket.save_changes('jane', 'Testing') self.assertEqual('kate', ticket['owner'])
def _create_a_ticket(self): # 1. Creating ticket ticket = Ticket(self.env) ticket['reporter'] = 'santa' ticket['summary'] = 'Foo' ticket['description'] = 'Bar' ticket['foo'] = 'This is a custom field' ticket.insert() return ticket
def test_changelog_with_reverted_change(self): tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') ticket = Ticket(self.env, tkt_id) ticket['component'] = 'bar' ticket['component'] = 'foo' now = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes('jane', 'Testing', now) self.assertEqual([(now, 'jane', 'comment', '1', 'Testing', True)], list(ticket.get_changelog()))
def test_delete_last_comment_by_date(self): ticket = Ticket(self.env, self.id) self.assertEqual('a', ticket['keywords']) self.assertEqual('change4', ticket['foo']) t = datetime.now(utc) ticket.delete_change(cdate=self.t4, when=t) self.assertEqual('a, b', ticket['keywords']) self.assertEqual('change3', ticket['foo']) self.assertEqual(None, ticket.get_change(cdate=self.t4)) self.assertNotEqual(None, ticket.get_change(cdate=self.t3)) self.assertEqual(t, ticket.time_changed)
def test_threading(self): """Check modification of a "threaded" comment""" ticket = Ticket(self.env, self.id) t = self.created + timedelta(seconds=20) ticket.modify_comment(self._find_change(ticket, 2), 'joe', 'New comment 2', t) self.assertChange(ticket, 2, self.t2, 'john', owner=dict(author='john', old='john', new='jack'), comment=dict(author='john', old='1.2', new='New comment 2'), _comment0=dict(author='joe', old='Comment 2', new=str(to_utimestamp(t))))
def test_modify_missing_cnum(self): """Editing a comment with no cnum in oldvalue""" self.env.db_transaction( "UPDATE ticket_change SET oldvalue='' WHERE oldvalue='3'") ticket = Ticket(self.env, self.id) t = self.created + timedelta(seconds=30) ticket.modify_comment(self._find_change(ticket, 3), 'joe', 'New comment 3', t) self.assertChange(ticket, 3, self.t3, 'jim', keywords=dict(author='jim', old='a, b, c', new='a, b'), comment=dict(author='jim', old='', new='New comment 3'), _comment0=dict(author='joe', old='Comment 3', new=str(to_utimestamp(t))))
def test_changelog(self): tkt_id = self._insert_ticket('Test', reporter='joe', component='foo', milestone='bar') ticket = Ticket(self.env, tkt_id) ticket['component'] = 'bar' ticket['milestone'] = 'foo' now = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes('jane', 'Testing', now) changelog = sorted(ticket.get_changelog()) self.assertEqual([(now, 'jane', 'comment', '1', 'Testing', True), (now, 'jane', 'component', 'foo', 'bar', True), (now, 'jane', 'milestone', 'bar', 'foo', True)], changelog)
def test_modify_missing_comment(self): """Editing a comment where the comment field is missing""" self.env.db_transaction(""" DELETE FROM ticket_change WHERE field='comment' AND oldvalue='1.2' """) ticket = Ticket(self.env, self.id) t = self.created + timedelta(seconds=40) ticket.modify_comment(self._find_change(ticket, 2), 'joe', 'New comment 2', t) self.assertChange(ticket, 2, self.t2, 'john', owner=dict(author='john', old='john', new='jack'), comment=dict(author='john', old='', new='New comment 2'), _comment0=dict(author='joe', old='', new=str(to_utimestamp(t))))
def test_prop_whitespace_change_is_not_saved(self): ticket = Ticket(self.env) ticket.populate({'summary': 'ticket summary'}) ticket.insert() ticket['summary'] = ' ticket summary ' ticket.save_changes() self.assertEqual(0, len(ticket.get_changelog()))
def test_delete_mid_comment_by_date(self): ticket = Ticket(self.env, self.id) self.assertChange(ticket, 4, self.t4, 'joe', comment=dict(author='joe', old='4', new='Comment 4'), keywords=dict(author='joe', old='a, b', new='a'), foo=dict(author='joe', old='change3', new='change4')) t = datetime.now(utc) ticket.delete_change(cdate=self.t3, when=t) self.assertEqual(None, ticket.get_change(cdate=self.t3)) self.assertEqual('a', ticket['keywords']) self.assertChange(ticket, 4, self.t4, 'joe', comment=dict(author='joe', old='4', new='Comment 4'), keywords=dict(author='joe', old='a, b, c', new='a'), foo=dict(author='joe', old='change2', new='change4')) self.assertEqual(t, ticket.time_changed)
def test_owner_from_component(self): """ Verify that the owner of a new ticket is set to the owner of the component. """ component = Component(self.env) component.name = 'test' component.owner = 'joe' component.insert() ticket = Ticket(self.env) ticket['reporter'] = 'santa' ticket['summary'] = 'Foo' ticket['component'] = 'test' ticket.insert() self.assertEqual('joe', ticket['owner'])
def test_delete_milestone_retarget_tickets(self): self.env.db_transaction("INSERT INTO milestone (name) VALUES ('Test')") tkt1 = Ticket(self.env) tkt1.populate({'summary': 'Foo', 'milestone': 'Test'}) tkt1.insert() tkt2 = Ticket(self.env) tkt2.populate({'summary': 'Bar', 'milestone': 'Test'}) tkt2.insert() milestone = Milestone(self.env, 'Test') milestone.delete(retarget_to='Other') self.assertEqual(False, milestone.exists) self.assertEqual('Other', Ticket(self.env, tkt1.id)['milestone']) self.assertEqual('Other', Ticket(self.env, tkt2.id)['milestone'])
def test_update_milestone_update_tickets(self): self.env.db_transaction("INSERT INTO milestone (name) VALUES ('Test')") tkt1 = Ticket(self.env) tkt1.populate({'summary': 'Foo', 'milestone': 'Test'}) tkt1.insert() tkt2 = Ticket(self.env) tkt2.populate({'summary': 'Bar', 'milestone': 'Test'}) tkt2.insert() milestone = Milestone(self.env, 'Test') milestone.name = 'Testing' milestone.update() self.assertEqual('Testing', Ticket(self.env, tkt1.id)['milestone']) self.assertEqual('Testing', Ticket(self.env, tkt2.id)['milestone'])
def test_action_with_state_change(self): """Actions can have change status.""" self.env.config.set('ticket-workflow', 'embiggen', '* -> big') first_ticket_id = self._insert_ticket('Test 1', reporter='joe', status='small') second_ticket_id = self._insert_ticket('Test 2', reporter='joe') selected_tickets = [first_ticket_id, second_ticket_id] batch = BatchModifyModule(self.env) batch._save_ticket_changes(self.req, selected_tickets, {}, '', 'embiggen') ticket = Ticket(self.env, int(first_ticket_id)) changes = ticket.get_changelog() self.assertFieldChanged(first_ticket_id, 'status', 'big') self.assertFieldChanged(second_ticket_id, 'status', 'big')
def test_change_listener_changed(self): listener = TestTicketChangeListener(self.env) data = {'component': 'foo', 'milestone': 'bar'} tkt_id = self._insert_ticket('Hello World', reporter='john', **data) ticket = Ticket(self.env, tkt_id) ticket['component'] = 'new component' ticket['milestone'] = 'new milestone' comment = 'changing ticket' ticket.save_changes('author', comment) self.assertEqual('changed', listener.action) self.assertEqual(comment, listener.comment) self.assertEqual('author', listener.author) for key, value in data.iteritems(): self.assertEqual(value, listener.old_values[key])
def test_missing_comment_edit(self): """Modify a comment where one edit is missing""" ticket = Ticket(self.env, self.id) t1 = self.created + timedelta(seconds=70) ticket.modify_comment(self._find_change(ticket, 1), 'joe', 'New comment 1', t1) t2 = self.created + timedelta(seconds=80) ticket.modify_comment(self._find_change(ticket, 1), 'joe', 'Other comment 1', t2) self.assertChange(ticket, 1, self.t1, 'jack', comment=dict(author='jack', old='1', new='Other comment 1'), _comment0=dict(author='joe', old='Comment 1', new=str(to_utimestamp(t1))), _comment1=dict(author='joe', old='New comment 1', new=str(to_utimestamp(t2)))) self.env.db_transaction( "DELETE FROM ticket_change WHERE field='_comment0'") t3 = self.created + timedelta(seconds=90) ticket.modify_comment(self._find_change(ticket, 1), 'joe', 'Newest comment 1', t3) self.assertChange(ticket, 1, self.t1, 'jack', comment=dict(author='jack', old='1', new='Newest comment 1'), _comment1=dict(author='joe', old='New comment 1', new=str(to_utimestamp(t2))), _comment2=dict(author='joe', old='Other comment 1', new=str(to_utimestamp(t3))))
def test_delete_all_comments(self): ticket = Ticket(self.env, self.id) ticket.delete_change(4) ticket.delete_change(3) ticket.delete_change(2) t = datetime.now(utc) ticket.delete_change(1, when=t) self.assertEqual(t, ticket.time_changed)
def test_invalid_ticket_id(self): self.assertEqual(Ticket.id_is_valid(-1), False) self.assertEqual(Ticket.id_is_valid(0), False) self.assertEqual(Ticket.id_is_valid(1), True) self.assertEqual(Ticket.id_is_valid(1L << 31), True) self.assertEqual(Ticket.id_is_valid(1L << 32), False) self.assertRaises(ResourceNotFound, Ticket, self.env, -1) self.assertRaises(ResourceNotFound, Ticket, self.env, 1L << 32)
def test_comment_history(self): """Check the generation of the comment history""" ticket = Ticket(self.env, self.id) t = [self.t1] for i in range(1, 32): t.append(self.created + timedelta(minutes=i)) ticket.modify_comment(self._find_change(ticket, 1), 'joe (%d)' % i, 'Comment 1 (%d)' % i, t[-1]) history = ticket.get_comment_history(cnum=1) self.assertEqual((0, t[0], 'jack', 'Comment 1'), history[0]) for i in range(1, len(history)): self.assertEqual((i, t[i], 'joe (%d)' % i, 'Comment 1 (%d)' % i), history[i]) history = ticket.get_comment_history(cdate=self.t1) self.assertEqual((0, t[0], 'jack', 'Comment 1'), history[0]) for i in range(1, len(history)): self.assertEqual((i, t[i], 'joe (%d)' % i, 'Comment 1 (%d)' % i), history[i])
def test_delete_mid_comment_inconsistent(self): # Make oldvalue on keywords for change 4 inconsistent. This should # result in no change in oldvalue when deleting change 3. The # oldvalue of foo should change normally. self.env.db_transaction(""" UPDATE ticket_change SET oldvalue='1, 2' WHERE field='keywords' AND oldvalue='a, b' """) ticket = Ticket(self.env, self.id) self.assertChange(ticket, 4, self.t4, 'joe', comment=dict(author='joe', old='4', new='Comment 4'), keywords=dict(author='joe', old='1, 2', new='a'), foo=dict(author='joe', old='change3', new='change4')) ticket.delete_change(3) self.assertEqual(None, ticket.get_change(3)) self.assertEqual('a', ticket['keywords']) self.assertChange(ticket, 4, self.t4, 'joe', comment=dict(author='joe', old='4', new='Comment 4'), keywords=dict(author='joe', old='1, 2', new='a'), foo=dict(author='joe', old='change2', new='change4'))
def test_populate_ticket(self): data = {'summary': 'Hello world', 'reporter': 'john', 'foo': 'bar', 'checkbox_cbon': '', 'cbon': 'on', 'checkbox_cboff': ''} ticket = Ticket(self.env) ticket.populate(data) # Standard fields self.assertEqual('Hello world', ticket['summary']) self.assertEqual('john', ticket['reporter']) # An unknown field assert ticket['bar'] is None # Custom field self.assertEqual('bar', ticket['foo']) # Custom field of type 'checkbox' self.assertEqual('on', ticket['cbon']) self.assertEqual('0', ticket['cboff'])
def test_modify_comment(self): """Check modification of a "standalone" comment""" ticket = Ticket(self.env, self.id) self.assertChange(ticket, 1, self.t1, 'jack', comment=dict(author='jack', old='1', new='Comment 1')) self.assertChange(ticket, 2, self.t2, 'john', owner=dict(author='john', old='john', new='jack'), comment=dict(author='john', old='1.2', new='Comment 2')) self.assertChange(ticket, 3, self.t3, 'jim', keywords=dict(author='jim', old='a, b, c', new='a, b'), comment=dict(author='jim', old='3', new='Comment 3')) t = self.created + timedelta(seconds=10) ticket.modify_comment(self._find_change(ticket, 1), 'joe', 'New comment 1', t) self.assertChange(ticket, 1, self.t1, 'jack', comment=dict(author='jack', old='1', new='New comment 1'), _comment0=dict(author='joe', old='Comment 1', new=str(to_utimestamp(t)))) self.assertEqual(t, Ticket(self.env, self.id)['changetime'])
def test_action_with_side_effects(self): """Actions can have operations with side effects.""" self.env.config.set('ticket-workflow', 'buckify', '* -> *') self.env.config.set('ticket-workflow', 'buckify.operations', 'set_owner') self.req.args = {} self.req.args['action_buckify_reassign_owner'] = 'buck' first_ticket_id = self._insert_ticket('Test 1', reporter='joe', owner='foo') second_ticket_id = self._insert_ticket('Test 2', reporter='joe') selected_tickets = [first_ticket_id, second_ticket_id] batch = BatchModifyModule(self.env) batch._save_ticket_changes(self.req, selected_tickets, {}, '', 'buckify') ticket = Ticket(self.env, int(first_ticket_id)) changes = ticket.get_changelog() self.assertFieldChanged(first_ticket_id, 'owner', 'buck') self.assertFieldChanged(second_ticket_id, 'owner', 'buck')
def test_can_save_ticket_without_explicit_username(self): ticket = Ticket(self.env) ticket.insert() ticket['summary'] = 'another summary' ticket.save_changes() for change in ticket.get_changelog(): self.assertEqual(None, change[1])
def test_can_save_ticket_without_explicit_comment(self): ticket = Ticket(self.env) ticket.insert() ticket['summary'] = 'another summary' ticket.save_changes('foo') changes = ticket.get_changelog() comment_change = [c for c in changes if c[2] == 'comment'][0] self.assertEqual('1', comment_change[3]) self.assertEqual('', comment_change[4])
def test_subsecond_change(self): """Perform two ticket changes within a second.""" tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') ticket = Ticket(self.env, tkt_id) t1 = datetime(2001, 1, 1, 1, 1, 1, 123456, utc) ticket.save_changes('jane', 'Testing', t1) t2 = datetime(2001, 1, 1, 1, 1, 1, 123789, utc) ticket.save_changes('jim', 'Other', t2) log = ticket.get_changelog() self.assertEqual(2, len(log)) self.assertEqual((t1, 'jane', 'comment', '1', 'Testing', True), log[0]) self.assertEqual((t2, 'jim', 'comment', '2', 'Other', True), log[1])
def _format_link(self, formatter, ns, target, label, fullmatch=None): intertrac = formatter.shorthand_intertrac_helper(ns, target, label, fullmatch) if intertrac: return intertrac try: link, params, fragment = formatter.split_link(target) r = Ranges(link) if len(r) == 1: num = r.a ticket = formatter.resource('ticket', num) from txomon.ticket.model import Ticket if Ticket.id_is_valid(num) and \ 'TICKET_VIEW' in formatter.perm(ticket): # TODO: attempt to retrieve ticket view directly, # something like: t = Ticket.view(num) for type, summary, status, resolution in \ self.env.db_query(""" SELECT type, summary, status, resolution FROM ticket WHERE id=%s """, (str(num),)): title = self.format_summary(summary, status, resolution, type) href = formatter.href.ticket(num) + params + fragment return tag.a(label, title=title, href=href, class_='%s ticket' % status) else: ranges = str(r) if params: params = '&' + params[1:] label_wrap = label.replace(',', u',\u200b') ranges_wrap = ranges.replace(',', u', ') return tag.a(label_wrap, title=_("Tickets %(ranges)s", ranges=ranges_wrap), href=formatter.href.query(id=ranges) + params) except ValueError: pass return tag.a(label, class_='missing ticket')
def test_custom_time(self): # Add a custom field of type 'time' self.env.config.set('ticket-custom', 'due', 'time') ticket = Ticket(self.env) self.assertFalse('due' in ticket.std_fields) self.assertTrue('due' in ticket.time_fields) ticket['reporter'] = 'john' ticket['summary'] = 'Task1' tktid = ticket.insert() ticket = Ticket(self.env, tktid) # Empty string is default value, but not a time stamp self.assertEqual(None, ticket['due']) ts = datetime(2011, 11, 11, 0, 0, 0, 0, utc) ticket['due'] = ts t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes('joe', when=t1) self.assertEqual(ts, ticket['due']) ticket['due'] = '' t2 = datetime(2001, 1, 1, 1, 1, 2, 0, utc) ticket.save_changes('joe', when=t2) self.assertEqual('', ticket['due'])