def milestone_setup(tc): from datetime import datetime from trac.util.datefmt import utc boo = Milestone(tc.env) boo.name = 'boo' boo.completed = boo.due = None boo.insert() roo = Milestone(tc.env) roo.name = 'roo' roo.completed = datetime.now(utc) roo.due = None roo.insert()
def process_request(self, req): milestone_id = req.args.get('id') req.perm('milestone', milestone_id).require('MILESTONE_VIEW') add_link(req, 'up', req.href.roadmap(), _('Roadmap')) action = req.args.get('action', 'view') try: milestone = Milestone(self.env, milestone_id) except ResourceNotFound: if 'MILESTONE_CREATE' not in req.perm('milestone', milestone_id): raise milestone = Milestone(self.env, None) milestone.name = milestone_id action = 'edit' # rather than 'new' so that it works for POST/save if req.method == 'POST': if req.args.has_key('cancel'): if milestone.exists: req.redirect(req.href.milestone(milestone.name)) else: req.redirect(req.href.roadmap()) elif action == 'edit': return self._do_save(req, milestone) elif action == 'delete': self._do_delete(req, milestone) elif action in ('new', 'edit'): return self._render_editor(req, milestone) elif action == 'delete': return self._render_confirm(req, milestone) if not milestone.name: req.redirect(req.href.roadmap()) return self._render_view(req, milestone)
def process_request(self, req): milestone_id = req.args.get('id') req.perm('milestone', milestone_id).require('MILESTONE_VIEW') add_link(req, 'up', req.href.roadmap(), _('Roadmap')) action = req.args.get('action', 'view') try: milestone = Milestone(self.env, milestone_id) except ResourceNotFound: if 'MILESTONE_CREATE' not in req.perm('milestone', milestone_id): raise milestone = Milestone(self.env, None) milestone.name = milestone_id action = 'edit' # rather than 'new' so that it works for POST/save if req.method == 'POST': if 'cancel' in req.args: if milestone.exists: req.redirect(req.href.milestone(milestone.name)) else: req.redirect(req.href.roadmap()) elif action == 'edit': return self._do_save(req, milestone) elif action == 'delete': self._do_delete(req, milestone) elif action in ('new', 'edit'): return self._render_editor(req, milestone) elif action == 'delete': return self._render_confirm(req, milestone) if not milestone.name: req.redirect(req.href.roadmap()) return self._render_view(req, milestone)
def test_update_milestone_without_name(self): cursor = self.db.cursor() cursor.execute("INSERT INTO milestone (name) VALUES ('Test')") cursor.close() milestone = Milestone(self.env, 'Test') milestone.name = None self.assertRaises(TracError, milestone.update)
def test_update_milestone_without_name(self): cursor = self.db.cursor() cursor.execute("INSERT INTO milestone (name) VALUES ('Test')") cursor.close() milestone = Milestone(self.env, 'Test') milestone.name = None self.assertRaises(AssertionError, milestone.update)
def test_create_milestone(self): milestone = Milestone(self.env) milestone.name = 'Test' milestone.insert() cursor = self.db.cursor() cursor.execute("SELECT name,due,completed,description FROM milestone " "WHERE name='Test'") self.assertEqual(('Test', 0, 0, ''), cursor.fetchone())
def test_rename_milestone(self): milestone = Milestone(self.env) milestone.name = 'OldName' milestone.insert() attachment = Attachment(self.env, 'milestone', 'OldName') attachment.insert('foo.txt', StringIO(), 0, 1) milestone = Milestone(self.env, 'OldName') milestone.name = 'NewName' milestone.update() self.assertRaises(ResourceNotFound, Milestone, self.env, 'OldName') self.assertEqual('NewName', Milestone(self.env, 'NewName').name) attachments = Attachment.select(self.env, 'milestone', 'OldName') self.assertRaises(StopIteration, attachments.next) attachments = Attachment.select(self.env, 'milestone', 'NewName') self.assertEqual('foo.txt', attachments.next().filename) self.assertRaises(StopIteration, attachments.next)
def milestone_setup(tc): boo = Milestone(tc.env) boo.name = 'boo' boo.completed = boo.due = None boo.insert() roo = Milestone(tc.env) roo.name = 'roo' roo.completed = dt_past roo.due = None roo.insert() woo = Milestone(tc.env) woo.name = 'woo' woo.completed = None woo.due = dt_future woo.insert() zoo = Milestone(tc.env) zoo.name = 'zoo' zoo.completed = None zoo.due = dt_past zoo.insert()
def test_rename_milestone(self): milestone = Milestone(self.env) milestone.name = "OldName" milestone.insert() attachment = Attachment(self.env, "milestone", "OldName") attachment.insert("foo.txt", StringIO(), 0, 1) milestone = Milestone(self.env, "OldName") milestone.name = "NewName" milestone.update() self.assertRaises(ResourceNotFound, Milestone, self.env, "OldName") self.assertEqual("NewName", Milestone(self.env, "NewName").name) attachments = Attachment.select(self.env, "milestone", "OldName") self.assertRaises(StopIteration, attachments.next) attachments = Attachment.select(self.env, "milestone", "NewName") self.assertEqual("foo.txt", attachments.next().filename) self.assertRaises(StopIteration, attachments.next)
def ticket_changed(self, ticket, comment, author, old_values): old_summary = old_values.get('summary') if ticket['type']==milestone_ticket_type \ and old_summary \ and ticket['summary'] != old_summary: try: milestone = Milestone(self.env, old_summary) if milestone.exists: milestone.name = ticket['summary'] milestone.update() except ResourceNotFound: pass
def test_delete_milestone_with_attachment(self): milestone = Milestone(self.env) milestone.name = 'MilestoneWithAttachment' milestone.insert() attachment = Attachment(self.env, 'milestone', milestone.name) attachment.insert('foo.txt', StringIO(), 0, 1) milestone.delete() self.assertEqual(False, milestone.exists) attachments = Attachment.select(self.env, 'milestone', milestone.name) self.assertRaises(StopIteration, attachments.next)
def test_create_and_update_milestone(self): milestone = Milestone(self.env) milestone.name = "Test" milestone.insert() cursor = self.db.cursor() cursor.execute("SELECT name,due,completed,description FROM milestone " "WHERE name='Test'") self.assertEqual(("Test", 0, 0, ""), cursor.fetchone()) # Use the same model object to update the milestone milestone.description = "Some text" milestone.update() cursor.execute("SELECT name,due,completed,description FROM milestone " "WHERE name='Test'") self.assertEqual(("Test", 0, 0, "Some text"), cursor.fetchone())
def test_create_and_update_milestone(self): milestone = Milestone(self.env) milestone.name = 'Test' milestone.insert() cursor = self.db.cursor() cursor.execute("SELECT name,due,completed,description FROM milestone " "WHERE name='Test'") self.assertEqual(('Test', 0, 0, ''), cursor.fetchone()) # Use the same model object to update the milestone milestone.description = 'Some text' milestone.update() cursor.execute("SELECT name,due,completed,description FROM milestone " "WHERE name='Test'") self.assertEqual(('Test', 0, 0, 'Some text'), cursor.fetchone())
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_create_and_update_milestone(self): milestone = Milestone(self.env) milestone.name = 'Test' milestone.insert() self.assertEqual([('Test', 0, 0, '')], self.env.db_query(""" SELECT name, due, completed, description FROM milestone WHERE name='Test' """)) # Use the same model object to update the milestone milestone.description = 'Some text' milestone.update() self.assertEqual([('Test', 0, 0, 'Some text')], self.env.db_query(""" SELECT name, due, completed, description FROM milestone WHERE name='Test' """))
def test_rename_milestone_retarget_tickets(self): self.env.db_transaction("INSERT INTO milestone (name) VALUES ('Test')") tkt1 = self._insert_ticket(status='new', summary='Foo', milestone='Test') tkt2 = self._insert_ticket(status='new', summary='Bar', milestone='Test') self._update_ticket(tkt2, status='closed', resolution='fixed') milestone = Milestone(self.env, 'Test') milestone.name = 'Testing' milestone.update() tkt1 = Ticket(self.env, tkt1.id) tkt2 = Ticket(self.env, tkt2.id) self.assertEqual('Testing', tkt1['milestone']) self.assertEqual('Testing', tkt2['milestone']) self.assertEqual(tkt1['changetime'], tkt2['changetime']) self.assertNotEqual(self.updated_at, tkt1['changetime'])
def testBacklogForMultipleSprint(self): """Tests a Backlog associated to a Sprint with multiple sprints""" # Creates a Milestone m = Milestone(self.env) m.name = "Milestone 1" m.insert() # Create 2 Sprints sprint1 = self.teh.create_sprint( name="Sprint 1", start=to_datetime(t=None), duration=20, milestone=m.name) sprint2 = self.teh.create_sprint( name="Sprint 2", start=to_datetime(t=None), duration=20, milestone=m.name) # Create some tickets s1 = self.teh.create_ticket(Type.USER_STORY, props={Key.STORY_POINTS: '3', Key.SPRINT: sprint1.name}) self.assert_true(s1.link_to(self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '4', Key.SPRINT: sprint1.name}))) self.assert_true(s1.link_to(self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '8', Key.SPRINT: sprint1.name}))) self.assert_true(s1.link_to(self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '4'}))) s2 = self.teh.create_ticket(Type.USER_STORY, props={Key.STORY_POINTS: '5', Key.SPRINT: sprint2.name}) self.assert_true(s2.link_to(self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '2', Key.SPRINT: sprint2.name}))) self.assert_true(s2.link_to(self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '3'}))) # Creates the Backlog bound to the Sprint backlog = BacklogConfiguration(self.env, name="Sprint-Backlog", type=BacklogType.SPRINT) backlog.ticket_types = [Type.USER_STORY, Type.TASK] backlog.save() # The Backlog should contains only the items planned for the Sprint, and with parents # planned for the Sprint too backlog1 = self.bmm.get(name="Sprint-Backlog", scope=sprint1.name) self.assert_length(3, backlog1) backlog2 = self.bmm.get(name="Sprint-Backlog", scope=sprint2.name) self.assert_length(2, backlog2)
def task(add): """the thread task - either we are discovering or adding events""" with lock: env = ProductEnvironment(self.global_env, self.default_product) if add: name = 'milestone_from_' + threading.current_thread().name milestone = Milestone(env) milestone.name = name milestone.insert() else: # collect the names of milestones reported by Milestone and # directly from the db - as sets to ease comparison later results.append({ 'from_t': set([m.name for m in Milestone.select(env)]), 'from_db': set( [v[0] for v in self.env.db_query( "SELECT name FROM milestone")])})
def test_update_milestone_update_tickets(self): cursor = self.db.cursor() cursor.execute("INSERT INTO milestone (name) VALUES ('Test')") cursor.close() 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_get_ticket_fields_milestone_rename(self): """Cached ticket fields are updated when milestone is renamed.""" fields = self.ticket_system.get_ticket_fields() milestone_field = self._get_ticket_field('milestone') m2 = Milestone(self.env, 'milestone2') m2.name = 'milestone5' m2.update() updated_fields = self.ticket_system.get_ticket_fields() updated_milestone_field = self._get_ticket_field('milestone') self.assertNotEqual(fields, updated_fields) self.assertEqual(['milestone1', 'milestone2', 'milestone3', 'milestone4'], milestone_field['options']) self.assertEqual(['milestone1', 'milestone3', 'milestone4', 'milestone5'], updated_milestone_field['options'])
def test_update_milestone_update_tickets(self): cursor = self.db.cursor() cursor.execute("INSERT INTO milestone (name) VALUES ('Test')") cursor.close() 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_change_milestone_requires_milestone_view(self): """Changing ticket milestone requires MILESTONE_VIEW.""" perm_sys = PermissionSystem(self.env) self._insert_ticket(summary='the summary') for name in ('milestone1', 'milestone2'): m = Milestone(self.env) m.name = name m.insert() def make_req(authname): return MockRequest(self.env, authname=authname, method='GET', path_info='/ticket/1') def get_milestone_field(fields): for field in fields: if 'milestone' == field['name']: return field perm_sys.grant_permission('user', 'TICKET_VIEW') req = make_req('user') self.assertTrue(self.ticket_module.match_request(req)) data = self.ticket_module.process_request(req)[1] milestone_field = get_milestone_field(data['fields']) self.assertFalse(milestone_field['editable']) self.assertEqual([], milestone_field['optgroups'][0]['options']) self.assertEqual([], milestone_field['optgroups'][1]['options']) perm_sys.grant_permission('user_w_mv', 'TICKET_VIEW') perm_sys.grant_permission('user_w_mv', 'MILESTONE_VIEW') req = make_req('user_w_mv') self.assertTrue(self.ticket_module.match_request(req)) data = self.ticket_module.process_request(req)[1] milestone_field = get_milestone_field(data['fields']) self.assertTrue(milestone_field['editable']) self.assertEqual([], milestone_field['optgroups'][0]['options']) self.assertEqual(['milestone1', 'milestone2'], milestone_field['optgroups'][1]['options'])
def task(add): """the thread task - either we are discovering or adding events""" with lock: env = ProductEnvironment(self.global_env, self.default_product) if add: name = 'milestone_from_' + threading.current_thread().name milestone = Milestone(env) milestone.name = name milestone.insert() else: # collect the names of milestones reported by Milestone and # directly from the db - as sets to ease comparison later results.append({ 'from_t': set([m.name for m in Milestone.select(env)]), 'from_db': set([ v[0] for v in self.env.db_query( "SELECT name FROM milestone") ]) })
def process_request(self, req): milestone_id = req.args.get('id') action = req.args.get('action', 'view') if not milestone_id and action == 'view': req.redirect(req.href.roadmap()) req.perm(self.realm, milestone_id).require('MILESTONE_VIEW') add_link(req, 'up', req.href.roadmap(), _("Roadmap")) try: milestone = Milestone(self.env, milestone_id) except ResourceNotFound: if 'MILESTONE_CREATE' not in req.perm(self.realm, milestone_id): raise milestone = Milestone(self.env) milestone.name = milestone_id action = 'edit' # rather than 'new', so it works for POST/save if req.method == 'POST': if 'cancel' in req.args: if milestone.exists: req.redirect(req.href.milestone(milestone.name)) else: req.redirect(req.href.roadmap()) elif action == 'edit': return self._do_save(req, milestone) elif action == 'delete': self._do_delete(req, milestone) else: raise HTTPBadRequest(_("Invalid request arguments.")) elif action in ('new', 'edit'): return self._render_editor(req, milestone) elif action == 'delete': return self._render_confirm(req, milestone) if not milestone.name: req.redirect(req.href.roadmap()) return self._render_view(req, milestone)
def testBacklogForMultipleSprint(self): """Tests a Backlog associated to a Sprint with multiple sprints""" # Creates a Milestone m = Milestone(self.env) m.name = "Milestone 1" m.insert() # Create 2 Sprints sprint1 = self.teh.create_sprint(name="Sprint 1", start=to_datetime(t=None), duration=20, milestone=m.name) sprint2 = self.teh.create_sprint(name="Sprint 2", start=to_datetime(t=None), duration=20, milestone=m.name) # Create some tickets s1 = self.teh.create_ticket(Type.USER_STORY, props={ Key.STORY_POINTS: '3', Key.SPRINT: sprint1.name }) self.assert_true( s1.link_to( self.teh.create_ticket(Type.TASK, props={ Key.REMAINING_TIME: '4', Key.SPRINT: sprint1.name }))) self.assert_true( s1.link_to( self.teh.create_ticket(Type.TASK, props={ Key.REMAINING_TIME: '8', Key.SPRINT: sprint1.name }))) self.assert_true( s1.link_to( self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '4'}))) s2 = self.teh.create_ticket(Type.USER_STORY, props={ Key.STORY_POINTS: '5', Key.SPRINT: sprint2.name }) self.assert_true( s2.link_to( self.teh.create_ticket(Type.TASK, props={ Key.REMAINING_TIME: '2', Key.SPRINT: sprint2.name }))) self.assert_true( s2.link_to( self.teh.create_ticket(Type.TASK, props={Key.REMAINING_TIME: '3'}))) # Creates the Backlog bound to the Sprint backlog = BacklogConfiguration(self.env, name="Sprint-Backlog", type=BacklogType.SPRINT) backlog.ticket_types = [Type.USER_STORY, Type.TASK] backlog.save() # The Backlog should contains only the items planned for the Sprint, and with parents # planned for the Sprint too backlog1 = self.bmm.get(name="Sprint-Backlog", scope=sprint1.name) self.assert_length(3, backlog1) backlog2 = self.bmm.get(name="Sprint-Backlog", scope=sprint2.name) self.assert_length(2, backlog2)
def _test_change_milestone(self, editor): milestone = Milestone(self.env) milestone.name = 'milestone1' milestone.insert() perm_cache = PermissionCache(self.env, editor, milestone.resource) return perm_cache, milestone.resource
def test_update_milestone_without_name(self): self.env.db_transaction("INSERT INTO milestone (name) VALUES ('Test')") milestone = Milestone(self.env, 'Test') milestone.name = None self.assertRaises(TracError, milestone.update)