def post(self, request, *args, **kwargs): project = get_r_object_or_404(self.request.user, Project, name_short=self.kwargs.get('project')) try: parser.compile(self.request.POST.get('expression'), project, self.request.user) # add to sprint if currentsprint is set and issue was newly created if self.request.POST.get( 'currentsprint') != "" and parser.issue_created: sprint = Sprint.objects.get( project__name_short=self.kwargs.get('project'), seqnum=self.request.POST.get('currentsprint')) parser.issue_to_change.sprint = sprint parser.issue_to_change.save() except Exception as e: messages.add_message( request, messages.ERROR, _("An error occurred when processing your request") + ": " + str(e)) # store expression in session data to give edit ability to user self.request.session['oleaexpression'] = self.request.POST.get( 'expression') # set focus to olea bar self.request.session['oleafocus'] = 'autofocus' return redirect(self.request.POST.get('next'))
def test_modify_issue_backlog_bar(self): parser.compile('>1 @user2', self.issue.project, self.user) self.assertCalled( "chat.postMessage", channel="channel", attachments=[{ 'fallback': "username changed issue proj-1 sometitle.", 'pretext': 'Issue changed:', 'title': "proj-1 sometitle", 'title_link': "http://localhost:8000" + self.issue.get_absolute_url(), 'author_name': "username", 'author_link': "http://localhost:8000" + self.user.get_absolute_url(), 'author_icon': "http://localhost:8000" + self.user.avatar.url, 'fields': [ { "title": "Assignee", "value": "{} → {}, {}".format(self.user, self.user, self.user2), "short": True }, ], 'color': 'good', }])
def test_create_issue_without_params_backlog_bar(self): parser.compile('sometitle', self.issue.project, self.user) self.assertCalled( "chat.postMessage", channel="channel", attachments=[{ 'fallback': "username created issue proj-4 sometitle.", 'pretext': 'New Issue:', 'text': "", 'title': "proj-4 sometitle", 'title_link': "http://localhost:8000" + self.issue.get_absolute_url().replace("1", "4"), 'author_name': "username", 'author_link': "http://localhost:8000" + self.user.get_absolute_url(), 'author_icon': "http://localhost:8000" + self.user.avatar.url, 'color': 'good', }])
def test_parser(self): # contains test strings and the expected length of the attrs_to_set list # the third field indicates whether an issue shoud have been created tag = Tag(project=self.project, tag_text="testtag") tag.save() tag2 = Tag(project=self.project, tag_text="zweitertag") tag2.save() tests = [ ['Fancy task :Task &Todo', 2, True], [ 'Another fancy task :Bug !2 #testtag @a ;with description', 5, True ], ['>PRJ-1 !2 :Bug', 2, False], ['>2 $8', 1, False], ] for t in tests: parser.compile(t[0], self.project, self.user) self.assertEqual(len(parser.attrs_to_set), t[1]) self.assertEqual(parser.issue_created, t[2]) # all the above expressions should set issue_changed to True self.assertEqual(parser.issue_changed, True) # now we should have two new issues, check also their numbers self.assertEqual(Project.objects.first().issue.count(), 2) self.assertEqual(Issue.objects.filter(title="Fancy task").count(), 1) self.assertEqual( Issue.objects.filter(project=self.project, number=1).count(), 1) self.assertEqual( Issue.objects.filter(project=self.project, number=1).first().creator, self.user) self.assertEqual( Issue.objects.filter(project=self.project, number=1).first().kanbancol.name, 'Todo') self.assertEqual( Issue.objects.filter(project=self.project, number=2).count(), 1) self.assertEqual( Issue.objects.filter(project=self.project, number=2).first().storypoints, 8) self.assertEqual( Issue.objects.filter(project=self.project, number=2).first().description, 'with description') self.assertEqual( Issue.objects.filter(project=self.project, number=2).first().creator, self.user) # validate that fancy task is of type bug self.assertEqual( Issue.objects.filter(title="Fancy task", type="Bug").count(), 1) # validate that Another fancy task is of type bug with given attributes self.assertEqual( Issue.objects.filter(title="Another fancy task", type="Bug", priority=2, assignee=self.user, tags=tag).count(), 1) # set description of Another fancy task parser.compile('>PRJ-2 ;new description', self.project, self.user) self.assertEqual( Issue.objects.filter(project=self.project, number=2).first().description, 'new description') # set kanbancol of Fancy task parser.compile('>PRJ-1 &Progr', self.project, self.user) self.assertEqual( Issue.objects.filter(project=self.project, number=1).first().kanbancol.name, 'In Progress') # test icontains when setting kanbancol self.assertRaises(Exception, parser.compile, '>PRJ-1 &done', self.project, self.user) self.assertEqual( Issue.objects.filter(project=self.project, number=1).first().kanbancol.name, 'In Progress') parser.compile('>PRJ-1 &Done', self.project, self.user) self.assertEqual( Issue.objects.filter(project=self.project, number=1).first().kanbancol.name, 'Done') # add second tag and new assignee to PRJ2 and validate currentID = self.project.nextTicketId parser.compile('>PRJ-2 #zweitertag @d', self.project, self.user) issue = Issue.objects.get(title="Another fancy task") self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual(parser.issue_to_change, issue) self.assertEqual(issue.tags.count(), 2) self.assertEqual(issue.assignee.count(), 2) self.assertIn(self.user, issue.assignee.all()) self.assertIn(self.user2, issue.assignee.all()) self.assertEqual(issue.number, 2) self.project.refresh_from_db() self.assertEqual(currentID, self.project.nextTicketId) # test permission checks and validations user = get_user_model().objects.create_user('g', 'h', 'i') issue.tags.clear() issue.refresh_from_db self.assertEqual(issue.tags.count(), 0) # not existing issues may not be edited and nextTicketId must not change currentID = self.project.nextTicketId self.assertRaises(Exception, parser.compile, '>PRJ-3 #zweitertag @d', self.project, self.user) self.project.refresh_from_db() self.assertEqual(currentID, self.project.nextTicketId) # user must not edit projects to which he has no devel access self.assertRaises(Exception, parser.compile, '>PRJ-2 #zweitertag @d', self.project, user) # only users with access to project may be set as assignee self.assertRaises(Exception, parser.compile, '>PRJ-2 #zweitertag @g', self.project, self.user) # tags must not have changed issue.refresh_from_db self.assertEqual(issue.tags.count(), 0) # create another tag containing a space tag = Tag(project=self.project, tag_text="tag with spaces") tag.save() parser.compile('>PRJ-2 #tag with spaces @d', self.project, self.user) self.assertEqual(parser.issue_changed, True) issue.refresh_from_db() self.assertEqual(issue.tags.filter(pk=tag.pk).count(), 1) # dependent issue must exist and be in the same project parser.compile('Test-Issue proj2 :Bug', self.project2, self.user) self.assertEqual(parser.issue_created, True) self.assertEqual(parser.issue_changed, True) issue = Issue.objects.get(title="Test-Issue proj2") self.assertEqual(parser.issue_to_change, issue) self.assertEqual( Issue.objects.filter(project=self.project2).count(), 1) self.assertRaises(Exception, parser.compile, '>TPJ-1 ~PRJ-1', self.project, self.user) # log time to issue parser.compile('>PRJ-1 +2h5m', self.project, self.user) self.assertEqual(parser.issue_created, False) # logging time is no change action self.assertEqual(parser.issue_changed, False) t = Timelog.objects.get(issue__title='Fancy task') self.assertEqual(t.time.total_seconds(), 7500) # log many times to issue parser.compile('>PRJ-1 +2h5m +1m', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, False) self.assertEqual( Timelog.objects.filter(issue__title='Fancy task').count(), 3) totaltime = 0 for log in Timelog.objects.filter(issue__title='Fancy task'): totaltime += log.time.total_seconds() self.assertEqual(totaltime, 15060) # log time to new issue issuetitle = 'Timelog-test-issue' parser.compile(issuetitle + ' +2h5m', self.project, self.user) self.assertEqual(parser.issue_created, True) self.assertEqual(parser.issue_changed, False) self.assertEqual(Issue.objects.filter(title=issuetitle).count(), 1) t = Timelog.objects.get(issue__title=issuetitle) self.assertEqual(t.time.total_seconds(), 7500) # test empty timelog field (must not create new timelog object, should still be 3) parser.compile('>PRJ-1 +', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, False) self.assertEqual( Timelog.objects.filter(issue__title='Fancy task').count(), 3) # some syntactic stuff that should fail tests = [ 'Test-String ', '> @a', '>PRJ-2', ] for t in tests: self.assertRaises(Exception, parser.compile, t, self.project, self.user) # tests for contains checks of tag Issue.objects.get(title='Fancy task').tags.clear() self.assertRaises(Exception, parser.compile, '>PRJ-1 #tag', self.project, self.user) self.assertEqual(Issue.objects.get(title='Fancy task').tags.count(), 0) parser.compile('>PRJ-1 #ttag', self.project, self.user) self.assertEqual(Issue.objects.get(title='Fancy task').tags.count(), 1) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) tag3 = Tag(project=self.project, tag_text="ttag") tag3.save() parser.compile('>PRJ-1 #ttag', self.project, self.user) self.assertEqual(parser.issue_changed, True) self.assertEqual(Issue.objects.filter(tags=tag3).count(), 1) self.assertEqual(Issue.objects.get(title='Fancy task').tags.count(), 2) # check that searching for tag is case insensitive Issue.objects.get(title='Fancy task').tags.clear() parser.compile('>PRJ-1 #teStTaG', self.project, self.user) self.assertEqual(Issue.objects.get(title='Fancy task').tags.count(), 1) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) # same for user Issue.objects.get(title='Fancy task').assignee.clear() user3 = get_user_model().objects.create_user('jj', 'x', 'x') self.project.developer.add(user3) user4 = get_user_model().objects.create_user('jjj', 'y', 'y') self.project.developer.add(user4) user5 = get_user_model().objects.create_user('kj', 'z', 'z') self.project.developer.add(user5) self.assertRaises(Exception, parser.compile, '>PRJ-1 @j', self.project, self.user) self.assertEqual( Issue.objects.get(title='Fancy task').assignee.count(), 0) parser.compile('>PRJ-1 @jj', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.filter(title='Fancy task', assignee=user3).count(), 1) parser.compile('>PRJ-1 @jjj', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.filter(title='Fancy task', assignee=user4).count(), 1) # user search case insensitive Issue.objects.get(title='Fancy task').assignee.clear() parser.compile('>PRJ-1 @jJJ', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.filter(title='Fancy task', assignee=user4).count(), 1) # check that setting more than one assignee is possible parser.compile('>PRJ-1 @a @jj @kj', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.get(title='Fancy task').assignee.count(), 4) parser.compile('>PRJ-1 @jj', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.get(title='Fancy task').assignee.count(), 4) # test add depends functionality parser.compile('New issue depending on PRJ-1 ~PRJ-1', self.project, self.user) self.assertEqual(parser.issue_created, True) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.filter(project=self.project, title='New issue depending on PRJ-1').count(), 1) self.assertEqual( Issue.objects.get( project=self.project, title='New issue depending on PRJ-1').dependsOn.count(), 1) parser.compile('>PRJ-1 ~PRJ-2', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.get(title='Fancy task').dependsOn.count(), 1) # tag not existant Issue.objects.get(title='Fancy task').tags.clear() self.assertRaises(Exception, parser.compile, '>PRJ-1 #imnothere', self.project, self.user) self.assertEqual(Issue.objects.get(title='Fancy task').tags.count(), 0) # user not existant Issue.objects.get(title='Fancy task').assignee.clear() self.assertRaises(Exception, parser.compile, '>PRJ-1 @imnothere', self.project, self.user) self.assertEqual( Issue.objects.get(title='Fancy task').assignee.count(), 0) # test omitting project shortname in depends and modify tag Issue.objects.get(title='Fancy task').dependsOn.clear() parser.compile('>1 ~2', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual( Issue.objects.get(title='Fancy task').dependsOn.count(), 1) self.assertEqual( Issue.objects.get(title='Fancy task').dependsOn.first().title, 'Another fancy task') # check permissions test for issue to modify user5 = get_user_model().objects.create_user('tt', 'hh', 'ii') self.assertNotEqual(Issue.objects.get(title='Fancy task').priority, 4) self.assertRaises(Exception, parser.compile, '>1 !4', self.project, user5) self.assertNotEqual(Issue.objects.get(title='Fancy task').priority, 4) # check that managers and (managers & developers) are valid as assignee u_manager = get_user_model().objects.create_user('manager', 'ma', 'ma') u_maneloper = get_user_model().objects.create_user( 'maneloper', 'mar', 'mar') self.project.manager.add(u_manager) self.project.manager.add(u_maneloper) self.project.developer.add(u_maneloper) Issue.objects.get(title='Fancy task').assignee.clear() parser.compile('>PRJ-1 @manager @maneloper', self.project, self.user) self.assertEqual(parser.issue_created, False) self.assertEqual(parser.issue_changed, True) self.assertEqual( Issue.objects.filter( Q(title='Fancy task') & (Q(assignee=u_manager) | Q(assignee=u_maneloper))).count(), 2) # check that first and last name is also valid when searching for users parser.compile('>PRJ-1 @alice @bob', self.project, self.user) issue = self.project.issue.get(number=1) self.assertIn(self.user, issue.assignee.all()) self.assertIn(self.user2, issue.assignee.all()) self.assertIn(u_manager, issue.assignee.all()) self.assertIn(u_maneloper, issue.assignee.all()) self.assertEqual(issue.assignee.count(), 4) parser.compile('>PRJ-1 @alice @Blub', self.project, self.user) issue.refresh_from_db() self.assertIn(self.user, issue.assignee.all()) self.assertIn(self.user2, issue.assignee.all()) self.assertIn(u_manager, issue.assignee.all()) self.assertIn(u_maneloper, issue.assignee.all()) self.assertEqual(issue.assignee.count(), 4) # check that user is not assigned more than once Issue.objects.get(title='Fancy task').assignee.clear() parser.compile('>PRJ-1 @alice @Bla', self.project, self.user) issue.refresh_from_db() self.assertIn(self.user, issue.assignee.all()) self.assertEqual(issue.assignee.count(), 1) # check that no issue is created with error in change expression self.project.refresh_from_db() currentID = self.project.nextTicketId currentTicketCount = self.project.issue.count() self.assertRaises(Exception, parser.compile, 'New Issue #nonexistanttag', self.project, self.user) self.project.refresh_from_db() self.assertEqual(currentID, self.project.nextTicketId) self.assertEqual(currentTicketCount, self.project.issue.count()) # check that issue creation without change expression is possible self.project.refresh_from_db() currentID = self.project.nextTicketId currentTicketCount = self.project.issue.count() title = 'Fancy new issue without chgxpr' parser.compile(title, self.project, self.user) self.assertEqual(parser.issue_created, True) self.assertEqual(parser.issue_changed, False) self.project.refresh_from_db() self.assertEqual(self.project.issue.filter(title=title).count(), 1) self.assertEqual(currentID + 1, self.project.nextTicketId) self.assertEqual(currentTicketCount + 1, self.project.issue.count()) # check that changing an issue without change expression throws an exception self.assertRaises(Exception, parser.compile, '>1', self.project, self.user)
def test_log_time(self): parser.compile('>1 +1m', self.issue.project, self.user) self.assertNotCalled()