# -*- coding: utf-8 -*- """ (c) 2015-2018 - Copyright Red Hat Inc Authors: Pierre-Yves Chibon """ from __future__ import unicode_literals, absolute_import from unittest.case import SkipTest import json import unittest import shutil import sys import os try: import pyclamd except ImportError: pyclamd = None import six import tempfile import re from datetime import datetime, timedelta from six.moves.urllib.parse import urlparse, parse_qs import pygit2 from bs4 import BeautifulSoup from mock import patch, MagicMock sys.path.insert(0, os.path.join(os.path.dirname( os.path.abspath(__file__)), '..')) import pagure.lib.query import tests class PagureFlaskIssuestests(tests.Modeltests): """ Tests for flask issues controller of pagure """ @patch.dict('pagure.config.config', {'ENABLE_TICKETS_NAMESPACE': ['foobar']}) @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) def test_new_issue_wrong_namespace(self): """ Test the new_issue endpoint. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) user = tests.FakeUser(username='pingou') with tests.user_set(self.app.application, user): csrf_token = self.get_csrf() data = { 'title': 'Test issue', 'issue_content': 'We really should improve on this issue', 'status': 'Open', 'csrf_token': csrf_token, } # Things work fine when the project has no namespace output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue - test - Pagure', output_text) self.assertIn( '', output_text) # Things do not work when the project has a namespace not allowed output = self.app.post( '/somenamespace/test3/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 404) output_text = output.get_data(as_text=True) self.assertIn( 'Page not found :\'( - Pagure', output_text) self.assertIn( '

No issue tracker found for this project

', output_text) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_new_issue(self, p_send_email, p_ugt): """ Test the new_issue endpoint. """ p_send_email.return_value = True p_ugt.return_value = True # No Git repo output = self.app.get('/foo/new_issue') self.assertEqual(output.status_code, 404) user = tests.FakeUser() with tests.user_set(self.app.application, user): output = self.app.get('/foo/new_issue') self.assertEqual(output.status_code, 404) tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) self.assertIn( 'New Issue', output.get_data(as_text=True)) csrf_token = self.get_csrf(output=output) data = { } # Insufficient input output = self.app.post('/test/new_issue', data=data) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertEqual(output_text.count( 'This field is required.'), 2) data['title'] = 'Test issue' output = self.app.post('/test/new_issue', data=data) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertEqual(output_text.count( 'This field is required.'), 1) data['issue_content'] = 'We really should improve on this issue' data['status'] = 'Open' output = self.app.post('/test/new_issue', data=data) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertEqual(output_text.count( 'This field is required.'), 0) # Invalid user data['csrf_token'] = csrf_token output = self.app.post('/test/new_issue', data=data) self.assertEqual(output.status_code, 404) self.assertIn( '

No such user found in the database: username

', output.get_data(as_text=True)) # User not logged in output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 302) user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue - test - Pagure', output_text) self.assertIn( '
', output_text) # Project w/o issue tracker repo = pagure.lib.query.get_authorized_project(self.session, 'test') repo.settings = {'issue_tracker': False} self.session.add(repo) self.session.commit() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 404) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_new_issue_w_file(self, p_send_email, p_ugt): """ Test the new_issue endpoint with a file. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) self.assertIn( '

New Issue

\n', output.get_data(as_text=True)) csrf_token = self.get_csrf() with open(os.path.join(tests.HERE, 'placebo.png'), 'rb') as stream: data = { 'title': 'Test issue', 'issue_content': 'We really should improve on this issue\n' '', 'status': 'Open', 'filestream': stream, 'enctype': 'multipart/form-data', 'csrf_token': csrf_token, } output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue - test - Pagure', output_text) self.assertIn( '
', output_text) # Check the image was uploaded self.assertIn( 'href="/test/issue/raw/files/' '8a06845923010b27bfd8e7e75acff7badc40d1021b4' '994e01f5e11ca40bc3abe', output_text) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_new_issue_w_file_no_issue_tracker(self, p_send_email, p_ugt): """ Test the new_issue endpoint with a file. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) # Project w/o issue tracker repo = pagure.lib.query.get_authorized_project(self.session, 'test') repo.settings = {'issue_tracker': False} self.session.add(repo) self.session.commit() user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): with open(os.path.join(tests.HERE, 'placebo.png'), 'rb') as stream: data = { 'title': 'Test issue', 'issue_content': 'We really should improve on this issue', 'status': 'Open', 'filestream': stream, 'enctype': 'multipart/form-data', 'csrf_token': self.get_csrf(), } output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 404) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_new_issue_w_file_namespace(self, p_send_email, p_ugt): """ Test the new_issue endpoint with a file. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) # Project with a namespace user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/somenamespace/test3/new_issue') self.assertEqual(output.status_code, 200) self.assertTrue( '

New Issue

\n' in output.get_data(as_text=True)) csrf_token = self.get_csrf() with open(os.path.join(tests.HERE, 'placebo.png'), 'rb') as stream: data = { 'title': 'Test issue3', 'issue_content': 'We really should improve on this issue\n' '', 'status': 'Open', 'filestream': stream, 'enctype': 'multipart/form-data', 'csrf_token': csrf_token, } output = self.app.post( '/somenamespace/test3/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue3 - test3 - Pagure', output_text) self.assertIn( '
\n', output_text) # Check the image was uploaded self.assertIn( 'href="/somenamespace/test3/issue/raw/files/' '8a06845923010b27bfd8e7e75acff7badc40d1021b4' '994e01f5e11ca40bc3abe', output_text) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_new_issue_w_files(self, p_send_email, p_ugt): """ Test the new_issue endpoint with two files. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) self.assertTrue( '

New Issue

\n' in output.get_data(as_text=True)) csrf_token = self.get_csrf() with open( os.path.join(tests.HERE, 'placebo.png'), 'rb' ) as stream: with open( os.path.join(tests.HERE, 'pagure.png'), 'rb' ) as stream2: data = { 'title': 'Test issue', 'issue_content': 'We really should improve on this issue\n' '\n', 'status': 'Open', 'filestream': [stream, stream2], 'enctype': 'multipart/form-data', 'csrf_token': csrf_token, } output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue - test - Pagure', output_text) self.assertIn( '
', output_text) # Check the image was uploaded self.assertIn( 'href="/test/issue/raw/files/' '8a06845923010b27bfd8e7e75acff7badc40d1021b4' '994e01f5e11ca40bc3abe', output_text) self.assertIn( 'href="/test/issue/raw/files/' '6498a2de405546200b6144da56fc25d0a3976ae688d' 'bfccaca609c8b4480523e', output_text) # Check that the files are accessible _, full_name = output_text.split("/test/issue/raw/files/", 1) full_name1, full_name2 = full_name.split( "/test/issue/raw/files/", 1) full_name1 = full_name1.split(".png", 1)[0] full_name2 = full_name2.split(".png", 1)[0] for full_name in [full_name1, full_name2]: req = self.app.get("/test/issue/raw/files/%s.png" % full_name) self.assertEqual(req.status_code, 200) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_new_issue_w_files_namespace(self, p_send_email, p_ugt): """ Test the new_issue endpoint with two files. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) # Project with a namespace user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/somenamespace/test3/new_issue') self.assertEqual(output.status_code, 200) self.assertTrue( '

New Issue

\n' in output.get_data(as_text=True)) csrf_token = self.get_csrf() with open( os.path.join(tests.HERE, 'placebo.png'), 'rb' ) as stream: with open( os.path.join(tests.HERE, 'pagure.png'), 'rb' ) as stream2: data = { 'title': 'Test issue3', 'issue_content': 'We really should improve on this issue\n' '\n', 'status': 'Open', 'filestream': [stream, stream2], 'enctype': 'multipart/form-data', 'csrf_token': csrf_token, } output = self.app.post( '/somenamespace/test3/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue3 - test3 - Pagure', output_text) self.assertIn( '
\n', output_text) # Check the image was uploaded self.assertIn( 'href="/somenamespace/test3/issue/raw/files/' '8a06845923010b27bfd8e7e75acff7badc40d1021b4' '994e01f5e11ca40bc3abe', output_text) self.assertIn( 'href="/somenamespace/test3/issue/raw/files/' '6498a2de405546200b6144da56fc25d0a3976ae688d' 'bfccaca609c8b4480523e', output_text) def test_new_issue_metadata_user(self): """ Test the new_issue endpoint when the user has access to the project. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertIn( 'Tags', output_text) self.assertIn( 'Assignee', output_text) def test_new_issue_metadata_not_user(self): """ Test the new_issue endpoint when the user does not have access to the project. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) user = tests.FakeUser() user.username = 'foo' with tests.user_set(self.app.application, user): output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertNotIn( 'Tags', output_text) self.assertNotIn( 'Assignee', output_text) @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) def test_new_issue_with_metadata(self): """ Test the new_issue endpoint when the user has access to the project. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) # Set some milestone repo = pagure.lib.query.get_authorized_project(self.session, 'test') repo.milestones = {'v1.0': '', 'v2.0': 'Tomorrow!'} self.session.add(repo) self.session.commit() user = tests.FakeUser() user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertIn( 'Tags', output_text) self.assertIn( 'Assignee', output_text) csrf_token = self.get_csrf(output=output) data = { 'title': 'Test issue3', 'issue_content': 'We really should improve on this issue\n', 'status': 'Open', 'assignee': 'foo', 'milestone': 'v2.0', 'tag': 'tag2', 'csrf_token': csrf_token, } output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue3 - test - Pagure', output_text) self.assertIn( '
\n', output_text) # Check the metadata self.assertIn( 'title="comma separated list of tags"\n ' 'value="tag2" />', output_text) self.assertIn( 'placeholder="username"\n value="foo" />\n', output_text) self.assertIn( 'href="/test/roadmap/v2.0/"', output_text) @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) def test_new_issue_with_metadata_not_user(self): """ Test the new_issue endpoint when the user does not have access to the project but still tries to. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) tests.create_projects_git( os.path.join(self.path, 'tickets'), bare=True) # Set some milestone repo = pagure.lib.query.get_authorized_project(self.session, 'test') repo.milestones = {'v1.0': '', 'v2.0': 'Tomorrow!'} self.session.add(repo) self.session.commit() user = tests.FakeUser() user.username = 'foo' with tests.user_set(self.app.application, user): output = self.app.get('/test/new_issue') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '

New Issue

\n', output_text) self.assertNotIn( 'Tags', output_text) self.assertNotIn( 'Assignee', output_text) csrf_token = self.get_csrf(output=output) data = { 'title': 'Test issue3', 'issue_content': 'We really should improve on this issue\n', 'status': 'Open', 'assignee': 'foo', 'milestone': 'v2.0', 'tag': 'tag2', 'csrf_token': csrf_token, } output = self.app.post( '/test/new_issue', data=data, follow_redirects=True) self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #1: Test issue3 - test - Pagure', output_text) self.assertIn( '
\n', output_text) # Check the metadata self.assertNotIn( 'title="comma separated list of tags"\n ' 'value="tag2" />', output_text) self.assertNotIn( 'placeholder="username"\n value="foo" />\n', output_text) self.assertNotIn( '
\n ' '\n ' '\n v2.0\n', output_text) @patch.dict('pagure.config.config', {'ENABLE_TICKETS_NAMESPACE': ['foobar']}) @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) def test_view_issues_wrong_namespace(self): """ Test the view_issues endpoint. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) user = tests.FakeUser(username='pingou') with tests.user_set(self.app.application, user): # Things work fine when the project has no namespace output = self.app.get('/test/issues') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) # Things do not work when the project has a namespace not allowed output = self.app.get('/somenamespace/test3/issues') self.assertEqual(output.status_code, 404) output_text = output.get_data(as_text=True) self.assertIn( 'Page not found :\'( - Pagure', output_text) self.assertIn( '

No issue tracker found for this project

', output_text) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_view_issues(self, p_send_email, p_ugt): """ Test the view_issues endpoint. """ p_send_email.return_value = True p_ugt.return_value = True output = self.app.get('/foo/issues') self.assertEqual(output.status_code, 404) tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) output = self.app.get('/test/issues') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( '', output_text) self.assertIn( '
test', output_text) self.assertIn( ' 0 Open Issues\n', output_text) repo = pagure.lib.query.get_authorized_project(self.session, 'test') # Create some custom fields to play with msg = pagure.lib.query.set_custom_key_fields( session=self.session, project=repo, fields=['test1'], types=['text'], data=[None], notify=[None] ) self.session.commit() self.assertEqual(msg, 'List of custom fields updated') cfield = pagure.lib.query.get_custom_key( session=self.session, project=repo, keyname='test1') # Create issues to play with msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='tést íssüé', content='We should work on this', user='pingou', ) self.session.commit() self.assertEqual(msg.title, 'tést íssüé') msg = pagure.lib.query.set_custom_key_value( session=self.session, issue=msg, key=cfield, value='firstissue') self.session.commit() self.assertEqual(msg, 'Custom field test1 adjusted to firstissue') msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Tést íssüé with milestone', content='Testing search', user='pingou', milestone='1.1', ) self.session.commit() self.assertEqual(msg.title, 'Tést íssüé with milestone') # Add a comment to that ticket pagure.lib.query.add_issue_comment( session=self.session, issue=msg, comment='How about nóã!', user='foo', ) self.session.commit() msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test invalid issue', content='This really is not related', user='pingou', status='Closed', close_status='Invalid', ) self.session.commit() self.assertEqual(msg.title, 'Test invalid issue') msg = pagure.lib.query.set_custom_key_value( session=self.session, issue=msg, key=cfield, value='second issue') self.session.commit() self.assertEqual(msg, 'Custom field test1 adjusted to second issue') # Whole list output = self.app.get('/test/issues') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertIn( ' 2 Open Issues\n', output_text) self.assertIn( 'title="2 Open Issues | 1 Closed Issues', output_text) self.assertIn( 'bg-success" role="progressbar"\n' ' style="width:67%"\n', output_text) # Status = closed (all but open) output = self.app.get('/test/issues?status=cloSED') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertIn( ' 1 Closed Issues\n', output_text) self.assertIn( 'title="2 Open Issues | 1 Closed Issues"', output_text) self.assertIn( 'bg-danger" role="progressbar"\n' ' style="width:33%"\n', output_text) # Status = fixed output = self.app.get('/test/issues?status=fixed') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertIn( ' 0 Closed:Fixed Issues\n', output_text) # Status = Invalid output = self.app.get('/test/issues?status=Invalid') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertTrue( ' 1 Closed:Invalid Issues\n' in output_text) # All tickets output = self.app.get('/test/issues?status=all') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertTrue( ' 3 Open & Closed Issues\n' in output_text) # Unicode search pattern output = self.app.get( '/test/issues?status=all&search_pattern=گروه') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertIn('0 Open & Closed Issues', output_text) # Content search - description output = self.app.get( '/test/issues?status=all&search_pattern=content:work') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn('1 Open & Closed Issues', output_text) # Content search - comment output = self.app.get( '/test/issues?status=all&search_pattern=content:nóã') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn('1 Open & Closed Issues', output_text) # Custom key searching output = self.app.get( '/test/issues?status=all&search_pattern=test1:firstissue') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn('1 Open & Closed Issues', output_text) # Custom key searching with space output = self.app.get( '/test/issues?status=all&search_pattern=test1:"second issue"') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn('1 Open & Closed Issues', output_text) # All tickets - different pagination before = pagure.config.config['ITEM_PER_PAGE'] pagure.config.config['ITEM_PER_PAGE'] = 1 output = self.app.get('/test/issues?status=all') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn( ' 3 Open & Closed Issues\n', output_text) self.assertIn( 'page 1 of 3', output_text) # All tickets - filtered for 1 - checking the pagination output = self.app.get( '/test/issues?status=all&search_pattern=invalid') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertIn(' 1 Open & Closed Issues\n', output_text) self.assertNotIn( 'page 1', output_text) pagure.config.config['ITEM_PER_PAGE'] = before # Search for issues with no milestone MARK output = self.app.get( '/test/issues?milestone=none') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn(' 1 Open Issues\n', output_text) # Search for issues with no milestone and milestone 1.1 output = self.app.get( '/test/issues?milestone=none&milestone=1.1') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issues - test - Pagure', output_text) self.assertIn(' 2 Open Issues\n', output_text) # Add another issue to test sorting msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Big problÈm!', content='I need help ASAP', user='foo', ) self.session.commit() self.assertEqual(msg.title, 'Big problÈm!') # Sort by last_updated output = self.app.get('/test/issues?order_key=last_updated') self.assertEqual(output.status_code, 200) tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) # Make sure that issue four is first since it was modified last self.assertIn('href="/test/issue/4"', tr_elements[0]) # Make sure that issue two is second since it was modified second self.assertIn('href="/test/issue/2"', tr_elements[1]) # Make sure that issue one is last since it was modified first self.assertIn('href="/test/issue/1"', tr_elements[2]) # Modify the date of the first issue and try again issue_one = pagure.lib.query.search_issues(self.session, repo, 1) issue_one.last_updated = datetime.utcnow() + timedelta(seconds=2) self.session.add(issue_one) self.session.commit() output = self.app.get('/test/issues?order_key=last_updated') self.assertEqual(output.status_code, 200) tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) # Make sure that issue one is first since it was modified last self.assertIn('href="/test/issue/1"', tr_elements[0]) # Make sure that issue four is second since it was modified before # last self.assertIn('href="/test/issue/4"', tr_elements[1]) # Make sure that issue two is last since it was modified before issue # one and four self.assertIn('href="/test/issue/2"', tr_elements[2]) # Now query so that the results are ascending output = self.app.get('/test/issues?order_key=last_updated&order=asc') tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) self.assertIn('href="/test/issue/2"', tr_elements[0]) self.assertIn('href="/test/issue/4"', tr_elements[1]) self.assertIn('href="/test/issue/1"', tr_elements[2]) # Sort by title descending output = self.app.get('/test/issues?order_key=title') self.assertEqual(output.status_code, 200) tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) self.assertIn('href="/test/issue/2"', tr_elements[0]) self.assertIn('href="/test/issue/1"', tr_elements[1]) self.assertIn('href="/test/issue/4"', tr_elements[2]) # Sort by title ascending output = self.app.get('/test/issues?order_key=title&order=asc') self.assertEqual(output.status_code, 200) tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) self.assertIn('href="/test/issue/4"', tr_elements[0]) self.assertIn('href="/test/issue/1"', tr_elements[1]) self.assertIn('href="/test/issue/2"', tr_elements[2]) # Sort by user (reporter/author) descending output = self.app.get('/test/issues?order_key=user&order=desc') self.assertEqual(output.status_code, 200) tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) # We check that they are unassigned, otherwise our previous check is # not specific enough as it can catch an assignee of "pingou" self.assertNotIn('fa-user-plus', tr_elements[0]) self.assertIn('pingou', tr_elements[1]) self.assertNotIn('fa-user-plus', tr_elements[1]) self.assertIn('foo', tr_elements[2]) self.assertNotIn('fa-user-plus', tr_elements[2]) # Sort by user (reporter/author) ascending output = self.app.get('/test/issues?order_key=user&order=asc') self.assertEqual(output.status_code, 200) tr_elements = re.findall(r'
(.*?)
', output.get_data(as_text=True), re.M | re.S) # Check for the name after the avatar self.assertIn('foo', tr_elements[0]) # We check that they are unassigned, otherwise our previous check is # not specific enough as it can catch an assignee of "foo" self.assertNotIn('fa-user-plus', tr_elements[0]) self.assertIn('pingou', tr_elements[1]) self.assertNotIn('fa-user-plus', tr_elements[1]) self.assertIn('pingou', tr_elements[2]) self.assertNotIn('fa-user-plus', tr_elements[2]) # Set some assignees issues = self.session.query(pagure.lib.model.Issue).filter_by( status='Open').order_by(pagure.lib.model.Issue.id).all() issues[0].assignee_id = 1 issues[1].assignee_id = 2 issues[2].assignee_id = 1 self.session.commit() # This detects the assignee but keying on if a certain link is present def _check_assignee_link(html, expected_links): soup = BeautifulSoup(html, "html.parser") for index, expected_link in enumerate(expected_links): link = soup.find_all("tr")[index + 1].find( "a", title="Filter issues by assignee") self.assertIsNotNone(link, "Link %s was not found" % expected_link) self.assertURLEqual(link["href"], expected_link) # Sort by assignee descending output = self.app.get('/test/issues?order_key=assignee&order=desc') self.assertEqual(output.status_code, 200) #tr_elements = re.findall(r'
(.*?)
', # output.get_data(as_text=True), re.M | re.S) #arrowed_th = ('Assignee\n ') # First table row is the header #self.assertIn(arrowed_th, tr_elements[0]) #_check_assignee_link(output.get_data(as_text=True), [ # '/test/issues?status=Open&assignee=pingou', # '/test/issues?status=Open&assignee=pingou', # '/test/issues?status=Open&assignee=foo', #]) # Sort by assignee ascending #output = self.app.get('/test/issues?order_key=assignee&order=asc') #self.assertEqual(output.status_code, 200) #tr_elements = re.findall(r'(.*?)', output.get_data(as_text=True), re.M | re.S) #arrowed_th = ('Assignee\n ') # First table row is the header #self.assertIn(arrowed_th, tr_elements[0]) #_check_assignee_link(output.get_data(as_text=True), [ # '/test/issues?status=Open&assignee=foo', # '/test/issues?status=Open&assignee=pingou', # '/test/issues?status=Open&assignee=pingou', #]) # New issue button is shown user = tests.FakeUser() with tests.user_set(self.app.application, user): output = self.app.get('/test') self.assertEqual(output.status_code, 200) self.assertIn( 'fa-exclamation-circle fa-fw"> New issue', output.get_data(as_text=True)) output = self.app.get('/test') self.assertEqual(output.status_code, 200) self.assertNotIn( 'fa-exclamation-circle fa-fw"> New issue', output.get_data(as_text=True)) # Project w/o issue tracker repo = pagure.lib.query.get_authorized_project(self.session, 'test') repo.settings = {'issue_tracker': False} self.session.add(repo) self.session.commit() output = self.app.get('/test/issues') self.assertEqual(output.status_code, 404) # New issue button is hidden user = tests.FakeUser() with tests.user_set(self.app.application, user): output = self.app.get('/test') self.assertEqual(output.status_code, 200) self.assertNotIn( 'fa-exclamation-circle fa-fw"> New issue', output.get_data(as_text=True)) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_search_issues_unicode(self, p_send_email, p_ugt): """ Test the view_issues endpoint filtering for an unicode char. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) repo = pagure.lib.query.get_authorized_project(self.session, 'test') # Create 2 issues to play with msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test issue ☃', content='We should work on this ❤', user='pingou', ) self.session.commit() self.assertEqual(msg.title, 'Test issue ☃') msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test issue with milestone', content='Testing search', user='pingou', milestone='1.1', ) self.session.commit() self.assertEqual(msg.title, 'Test issue with milestone') # Whole list output = self.app.get('/test/issues') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertTrue( ' 2 Open Issues\n' in output_text) # Unicode search pattern output = self.app.get( '/test/issues?status=all&search_pattern=☃') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn('Issues - test - Pagure', output_text) self.assertIn(' 1 Open & Closed Issues\n', output_text) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_view_issue_inconsistent_milestone(self, p_send_email, p_ugt): """ Test the view_issue endpoint when the milestone keys are inconsistent with the milestones of the project. """ p_send_email.return_value = True p_ugt.return_value = True tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) # Add milestones to the project repo = pagure.lib.query.get_authorized_project(self.session, 'test') milestones = { 'v1.0': {'date': None, 'active': True}, 'v2.0': {'date': 'in the future', 'active': True}, } repo.milestones = milestones repo.milestones_keys = ['', 'v1.0', 'v2.0'] # Create issues to play with repo = pagure.lib.query.get_authorized_project(self.session, 'test') msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test issue', content='We should work on this', user='pingou', ) self.session.commit() self.assertEqual(msg.title, 'Test issue') output = self.app.get('/test/issue/1') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) # Not authentified = No edit self.assertNotIn( '\n', output_text) self.assertIn( '' 'Login\n to comment on this ticket.', output_text) @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') def test_view_issue(self, p_send_email, p_ugt): """ Test the view_issue endpoint. """ p_send_email.return_value = True p_ugt.return_value = True output = self.app.get('/foo/issue/1') self.assertEqual(output.status_code, 404) tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) output = self.app.get('/test/issue/1') self.assertEqual(output.status_code, 404) # Create issues to play with repo = pagure.lib.query.get_authorized_project(self.session, 'test') msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test issue', content='We should work on this', user='pingou', ) self.session.commit() self.assertEqual(msg.title, 'Test issue') output = self.app.get('/test/issue/1') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) # Not authentified = No edit self.assertNotIn( '\n', output_text) self.assertIn( '' 'Login\n to comment on this ticket.', output_text) user = tests.FakeUser() with tests.user_set(self.app.application, user): output = self.app.get('/test/issue/1') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) # Not author nor admin = No edit self.assertNotIn( '', output_text) self.assertNotIn( '\n', output_text) self.assertFalse( 'Login to comment on this ticket.' in output_text) # Not author nor admin = No take self.assertNotIn('function take_issue(){', output_text) self.assertNotIn('function drop_issue(){', output_text) self.assertNotIn( '', output_text) self.assertIn( '\n', output_text) csrf_token = self.get_csrf(output=output) # Create private issue repo = pagure.lib.query.get_authorized_project(self.session, 'test') msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test issue', content='We should work on this', user='pingou', private=True, ) self.session.commit() self.assertEqual(msg.title, 'Test issue') # Not logged in output = self.app.get('/test/issue/2') self.assertEqual(output.status_code, 404) # Wrong user user = tests.FakeUser() with tests.user_set(self.app.application, user): output = self.app.get('/test/issue/2') self.assertEqual(output.status_code, 404) # reporter user.username = 'pingou' with tests.user_set(self.app.application, user): output = self.app.get('/test/issue/2') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) self.assertIn( 'Issue #2: Test issue - test - Pagure', output_text) self.assertIn( '', output_text) self.assertIn( '', output_text) # Project w/o issue tracker repo = pagure.lib.query.get_authorized_project(self.session, 'test') repo.settings = {'issue_tracker': False} self.session.add(repo) self.session.commit() output = self.app.get('/test/issue/1') self.assertEqual(output.status_code, 404) @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) def test_view_issue_author(self): """ Test the view_issue endpoint when you're the author. """ tests.create_projects(self.session) tests.create_projects_git( os.path.join(self.path, 'repos'), bare=True) # Create issues to play with repo = pagure.lib.query.get_authorized_project(self.session, 'test') msg = pagure.lib.query.new_issue( session=self.session, repo=repo, title='Test issue', content='We should work on this', user='foo', ) self.session.commit() self.assertEqual(msg.title, 'Test issue') output = self.app.get('/test/issue/1') self.assertEqual(output.status_code, 200) output_text = output.get_data(as_text=True) # Not authentified = No edit & no Close self.assertNotIn( '\n', output_text) self.assertNotIn( '