def test_validate_ticket_custom_field_max_size(self): """The [ticket-custom] max_size attribute is enforced.""" module = BatchModifyModule(self.env) req1 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_text1': '12345', 'action': 'leave', 'selected_tickets': '1,2', }) req2 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_text1': '123456', 'action': 'leave', 'selected_tickets': '1,2', }) self.assertTrue(module.match_request(req1)) with self.assertRaises(RequestDone): module.process_request(req1) self.assertEqual([], req1.chrome['warnings']) self.assertEqual('12345', model.Ticket(self.env, 1)['text1']) self.assertEqual('12345', model.Ticket(self.env, 2)['text1']) self.assertTrue(module.match_request(req2)) with self.assertRaises(RequestDone): module.process_request(req2) self.assertEqual(1, len(req2.chrome['warnings'])) self.assertEqual("The ticket field <strong>Text1</strong> is " "invalid: Must be less than or equal to 5 " "characters", unicode(req2.chrome['warnings'][0])) self.assertEqual('12345', model.Ticket(self.env, 1)['text1']) self.assertEqual('12345', model.Ticket(self.env, 2)['text1'])
def test_validate_ticket_comment_size(self): """The [ticket] max_comment_size value is enforced.""" module = BatchModifyModule(self.env) self.env.config.set('ticket', 'max_comment_size', 5) req1 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_comment': '12345', 'action': 'leave', 'selected_tickets': '1,2', }) req2 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_comment': '123456', 'action': 'leave', 'selected_tickets': '1,2', }) self.assertTrue(module.match_request(req1)) with self.assertRaises(RequestDone): module.process_request(req1) self.assertEqual([], req1.chrome['warnings']) self.assertCommentAdded(1, '12345') self.assertCommentAdded(2, '12345') self.assertTrue(module.match_request(req2)) with self.assertRaises(RequestDone): module.process_request(req2) self.assertEqual(1, len(req2.chrome['warnings'])) self.assertEqual("The ticket comment is invalid: Must be less than or " "equal to 5 characters", unicode(req2.chrome['warnings'][0])) self.assertEqual(1, len(model.Ticket(self.env, 1).get_changelog())) self.assertEqual(1, len(model.Ticket(self.env, 2).get_changelog()))
def test_timeline_events(self): """Regression test for #11288""" req1 = MockRequest(self.env) tktmod = web_ui.TicketModule(self.env) now = datetime_now(utc) start = now - timedelta(hours=1) stop = now + timedelta(hours=1) events = tktmod.get_timeline_events(req1, start, stop, ['ticket_details']) self.assertTrue(all(ev[0] != 'batchmodify' for ev in events)) prio_ids = {} for i in xrange(20): priority = ('', 'minor', 'major', 'critical')[i % 4] t = insert_ticket(self.env, summary='Ticket %d' % i, priority=priority) prio_ids.setdefault(t['priority'], []).append(t.id) tktids = prio_ids['critical'] + prio_ids['major'] + \ prio_ids['minor'] + prio_ids[''] req2 = MockRequest(self.env, method='POST', authname='has_ta_&_bm', path_info='/batchmodify', args={ 'batchmod_value_summary': 'batch updated ticket', 'batchmod_value_owner': 'ticket11288', 'batchmod_value_reporter': 'ticket11288', 'action': 'leave', 'selected_tickets': ','.join(str(t) for t in tktids), }) batch = BatchModifyModule(self.env) self.assertTrue(batch.match_request(req2)) with self.assertRaises(RequestDone): batch.process_request(req2) # shuffle ticket_change records with self.env.db_transaction as db: rows = db('SELECT * FROM ticket_change') db.execute('DELETE FROM ticket_change') rows = rows[0::4] + rows[1::4] + rows[2::4] + rows[3::4] db.executemany('INSERT INTO ticket_change VALUES (%s)' % ','.join(('%s',) * len(rows[0])), rows) events = tktmod.get_timeline_events(req1, start, stop, ['ticket_details']) events = [ev for ev in events if ev[0] == 'batchmodify'] self.assertEqual(1, len(events)) batch_ev = events[0] self.assertEqual('has_ta_&_bm', batch_ev[2]) self.assertEqual(tktids, batch_ev[3][0]) self.assertEqual('updated', batch_ev[3][1]) context = web_context(req2) self.assertEqual(req2.href.query(id=','.join(str(t) for t in tktids)), tktmod.render_timeline_event(context, 'url', batch_ev))
def test_action_with_state_change(self): """Actions can have change status.""" req = MockRequest(self.env, method='POST', authname='has_bm', path_info='/batchmodify', args={ 'action': 'acknowledge', 'batchmod_value_comment': '', 'selected_tickets': '1,2', }) batch = BatchModifyModule(self.env) self.assertTrue(batch.match_request(req)) with self.assertRaises(RequestDone): batch.process_request(req) self.assertFieldValue(1, 'status', 'acknowledged') self.assertFieldValue(2, 'status', 'acknowledged')
def test_save_comment(self): """Comments are saved to all selected tickets.""" req = MockRequest(self.env, method='POST', authname='has_bm', path_info='/batchmodify', args={ 'batchmod_value_comment': 'the comment', 'action': 'leave', 'selected_tickets': '1,2', }) batch = BatchModifyModule(self.env) self.assertTrue(batch.match_request(req)) with self.assertRaises(RequestDone): batch.process_request(req) self.assertCommentAdded(1, 'the comment') self.assertCommentAdded(2, 'the comment')
def test_modify_reporter_without_ticket_admin(self): """User without TICKET_ADMIN cannot batch modify the reporter.""" req = MockRequest(self.env, method='POST', authname='has_bm', path_info='/batchmodify', args={ 'batchmod_value_reporter': 'user2', 'batchmod_value_comment': '', 'action': 'leave', 'selected_tickets': '1,2', }) module = BatchModifyModule(self.env) self.assertTrue(module.match_request(req)) with self.assertRaises(RequestDone): module.process_request(req) self.assertFieldValue(1, 'reporter', 'user1') self.assertFieldValue(2, 'reporter', 'user1')
def test_list_fields_set(self): req = MockRequest(self.env, method='POST', authname='has_bm', path_info='/batchmodify', args={ 'batchmod_mode_keywords': '=', 'batchmod_primary_keywords': 'orange', 'batchmod_secondary_keywords': '*****', 'action': 'leave', 'selected_tickets': '1,2', }) batch = BatchModifyModule(self.env) self.assertTrue(batch.match_request(req)) with self.assertRaises(RequestDone): batch.process_request(req) self.assertFieldValue(1, 'keywords', 'orange') self.assertFieldValue(2, 'keywords', 'orange')
def test_list_fields_addrem(self): req = MockRequest(self.env, method='POST', authname='has_bm', path_info='/batchmodify', args={ 'batchmod_mode_keywords': '+-', 'batchmod_primary_keywords': 'one three four', 'batchmod_secondary_keywords': 'baz missing', 'action': 'leave', 'selected_tickets': '1,2', }) batch = BatchModifyModule(self.env) self.assertTrue(batch.match_request(req)) with self.assertRaises(RequestDone): batch.process_request(req) self.assertFieldValue(1, 'keywords', 'foo, one, three, four') self.assertFieldValue(2, 'keywords', 'two, one, three, four')
def test_require_post_method(self): """Request must use POST method.""" module = BatchModifyModule(self.env) req = MockRequest(self.env, method='GET', path_info='/batchmodify') req.session['query_href'] = req.href.query() self.assertTrue(module.match_request(req)) with self.assertRaises(HTTPBadRequest): module.process_request(req) req = MockRequest(self.env, method='POST', path_info='/batchmodify', args={'selected_tickets': ''}) req.session['query_href'] = req.href.query() self.assertTrue(module.match_request(req)) with self.assertRaises(RequestDone): module.process_request(req)
def test_validate_select_fields(self): """The select field values are validated.""" req = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_component': 'component3', 'action': 'leave', 'selected_tickets': '1,2', }) module = BatchModifyModule(self.env) self.assertTrue(module.match_request(req)) with self.assertRaises(RequestDone): module.process_request(req) self.assertEqual(1, len(req.chrome['warnings'])) self.assertEqual('The ticket field <strong>component</strong> is ' 'invalid: "component3" is not a valid value', unicode(req.chrome['warnings'][0]))
def test_validate_time_fields(self): """The time fields are validated.""" module = BatchModifyModule(self.env) req1 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_time1': '2016-01-02T12:34:56Z', 'action': 'leave', 'selected_tickets': '1,2', }) req2 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_time1': 'invalid', 'action': 'leave', 'selected_tickets': '1,2', }) dt = datetime(2016, 1, 2, 12, 34, 56, tzinfo=utc) self.assertTrue(module.match_request(req1)) with self.assertRaises(RequestDone): module.process_request(req1) self.assertEqual(dt, model.Ticket(self.env, 1)['time1']) self.assertEqual(dt, model.Ticket(self.env, 2)['time1']) self.assertEqual([], req1.chrome['warnings']) self.assertTrue(module.match_request(req2)) with self.assertRaises(RequestDone): module.process_request(req2) self.assertEqual(1, len(req2.chrome['warnings'])) self.assertRegexpMatches( unicode(req2.chrome['warnings'][0]), 'The ticket field <strong>Time1</strong> is invalid: "invalid" ' 'is an invalid date, or the date format is not known. ' 'Try "[^"]+" or "[^"]+" instead.') self.assertEqual(dt, model.Ticket(self.env, 1)['time1']) self.assertEqual(dt, model.Ticket(self.env, 2)['time1'])
def test_action_with_side_effects(self): """Actions can have operations with side effects.""" req = MockRequest(self.env, method='POST', authname='has_bm', path_info='/batchmodify', args={ 'action': 'reassign', 'action_reassign_reassign_owner': 'user3', 'batchmod_value_comment': '', 'selected_tickets': '1,2', }) batch = BatchModifyModule(self.env) self.assertTrue(batch.match_request(req)) with self.assertRaises(RequestDone): batch.process_request(req) self.assertFieldValue(1, 'owner', 'user3') self.assertFieldValue(2, 'owner', 'user3') self.assertFieldValue(1, 'status', 'assigned') self.assertFieldValue(2, 'status', 'assigned')
def test_modify_summary_and_description(self): """The ticket summary and description cannot be modified.""" req = MockRequest(self.env, authname='has_ta_&_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_summary': 'the new summary', 'batchmod_value_description': 'the new description', 'batchmod_value_comment': '', 'action': 'leave', 'selected_tickets': '1,2', }) module = BatchModifyModule(self.env) self.assertTrue(module.match_request(req)) with self.assertRaises(RequestDone): module.process_request(req) self.assertFieldValue(1, 'description', 'the desc') self.assertFieldValue(1, 'summary', 'Ticket 1') self.assertFieldValue(2, 'description', 'the desc') self.assertFieldValue(2, 'summary', 'Ticket 2')
def test_ticket_manipulators(self): """The ticket manipulators are called to valid the ticket.""" module = BatchModifyModule(self.env) self._insert_component('component3') self._insert_component('component4') self.env.enable_component(self.ticket_manipulators[0]) self.env.enable_component(self.ticket_manipulators[1]) req1 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_component': 'component3', 'action': 'leave', 'selected_tickets': '1,2', }) self.assertTrue(module.match_request(req1)) with self.assertRaises(RequestDone): module.process_request(req1) self.assertEqual(1, len(req1.chrome['warnings'])) self.assertEqual("The ticket field <strong>component</strong> is " "invalid: Invalid Component", unicode(req1.chrome['warnings'][0])) self.assertFieldValue(1, 'component', 'component1') self.assertFieldValue(2, 'component', 'component2') req2 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_component': 'component4', 'action': 'leave', 'selected_tickets': '1,2', }) self.assertTrue(module.match_request(req2)) with self.assertRaises(RequestDone): module.process_request(req2) self.assertEqual([], req2.chrome['warnings']) self.assertFieldValue(1, 'component', 'component4') self.assertFieldValue(2, 'component', 'component4') req3 = MockRequest(self.env, authname='has_bm', method='POST', path_info='/batchmodify', args={ 'batchmod_value_comment': 'this comment has the badword!', 'batchmod_value_component': 'component3', 'action': 'leave', 'selected_tickets': '1,2', }) self.assertTrue(module.match_request(req3)) with self.assertRaises(RequestDone): module.process_request(req3) self.assertEqual("The ticket comment is invalid: Word is not allowed " "in comment", unicode(req3.chrome['warnings'][0])) self.assertFieldValue(1, 'component', 'component4') self.assertFieldValue(2, 'component', 'component4')