Skip to content

Commit

Permalink
ADD get_ticket_content() method to bugzilla.py
Browse files Browse the repository at this point in the history
- Add ticket_content argument and get_ticket_content() method for Bugzilla and modify unit tests.
  • Loading branch information
mjagelka authored and dmranck committed Aug 14, 2018
1 parent abb2efc commit d27e586
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 75 deletions.
22 changes: 20 additions & 2 deletions read-the-docs/source/Bugzilla.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ http://bugzilla.readthedocs.io/en/latest/api/index.html
Methods
^^^^^^^

- `get_ticket_content() <#get_ticket_content>`__
- `create() <#create>`__
- `edit() <#edit>`__
- `add_comment() <#comment>`__
Expand All @@ -24,6 +25,20 @@ Methods
- `add_cc() <#add_cc>`__
- `add_attachment() <#add_attachment>`__

get_ticket_content()
--------------------

``get_ticket_content(self, ticket_id=None)``

Queries the Bugzilla API to get ticket_content using ticket_id. The
ticket_content is expressed in a form of dictionary as a result of Bugzilla API's
get issue: http://bugzilla.readthedocs.io/en/latest/api/core/v1/bug.html#get-bug

.. code:: python
t = ticket.create(ticket_id=<ticket_id>)
returned_ticket_content = t.ticket_content
create()
--------

Expand Down Expand Up @@ -225,6 +240,7 @@ Create and update Bugzilla ticket
assignee='username@mail.com',
qa_contact='username@mail.com',
groups='beta')
t = ticket.get_ticket_id()
t = ticket.add_comment('Test Comment')
t = ticket.edit(priority='medium',
qa_contact='username@mail.com')
Expand Down Expand Up @@ -258,11 +274,13 @@ Update existing Bugzilla tickets
data=<contents/file-location>,
summary=<summary describing attachment>)
# Check the ticket content.
t = ticket.get_ticket_id()
returned_ticket_content = t.ticket_content
# Work with a different ticket.
t = ticket.set_ticket_id(<new_ticket_id>)
t = ticket.change_status(status='CLOSED', resolution='NOTABUG')
# Close Requests session.
ticket.close_requests_session()
2 changes: 1 addition & 1 deletion read-the-docs/source/Usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ URL of the ticket. An example is below.

.. note::

For ServiceNow and JIRA the user-accessible methods return a ``ticket_content``
For ServiceNow, JIRA, and Bugzilla, the user-accessible methods return a ``ticket_content``
field, which contains a json representation of the current ticket's content.
This will be expanded to the other ticketutil tools in the future. Access this
data with ``t.ticket_content``.
118 changes: 77 additions & 41 deletions tests/test_bugzilla.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@
TEXT = "There is no bug."
SUMMARY = 'The ticket summary'
DESCRIPTION = 'The ticket description'
COMPONENT = 'The ticket component'
VERSION = 'The ticket version'
TICKET_URL = "{0}/show_bug.cgi?id={1}".format(URL, TICKET_ID)
ERROR_MESSAGE = "No ticket ID associated with ticket object. Set ticket ID with set_ticket_id(<ticket_id>)"

RETURN_RESULT = namedtuple('Result', ['status', 'error_message', 'url', 'ticket_content'])
SUCCESS_RESULT = RETURN_RESULT('Success', None, None, None)
FAILURE_RESULT = RETURN_RESULT('Failure', None, None, None)
MOCK200 = {}
MOCK401 = {'error': True, 'message': 'There is some error.'}
MOCK402 = {'bugs': {0: {'changes': {}}}}


class FakeSession(object):
Expand Down Expand Up @@ -68,11 +73,11 @@ def raise_for_status(self):

def json(self):
if self.status_code == 200:
return {}
return MOCK200
elif self.status_code == 401:
return {'error': True, 'message': 'There is some error.'}
return MOCK401
elif self.status_code == 402:
return {'bugs': {0: {'changes': {}}}}
return MOCK402


class FakeResponseProject(FakeResponse):
Expand All @@ -81,7 +86,7 @@ def json(self):
if self.status_code == 204:
return {"products": []}
elif self.status_code == 200:
return {}
return MOCK200


class FakeResponseID(FakeResponse):
Expand All @@ -98,7 +103,7 @@ def test_generate_ticket_url(self, mock_session):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
self.assertEqual(TICKET_URL, ticket._generate_ticket_url())
self.assertEqual(ticket.request_result, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(ticket.request_result, SUCCESS_RESULT._replace(url=TICKET_URL, ticket_content=MOCK200))

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_generate_ticket_url_no_ticket_id(self, mock_session):
Expand Down Expand Up @@ -175,23 +180,45 @@ def test_verify_project_unexpected_response(self, mock_session):
self.assertFalse(ticket._verify_project(PROJECT))

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_verify_ticket_id(self, mock_session):
def test_get_ticket_content(self, mock_session):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
self.assertTrue(ticket._verify_ticket_id(TICKET_ID))
ticket = bugzilla.BugzillaTicket(URL, PROJECT, TICKET_ID)
t = ticket.get_ticket_content(TICKET_ID)
self.assertEqual(ticket.ticket_content, {})
self.assertEqual(t, SUCCESS_RESULT._replace(ticket_content={}))

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_verify_ticket_id_not_valid(self, mock_session):
mock_session.return_value = FakeSession(text="Bug #{0} does not exist.".format(TICKET_ID))
def test_get_ticket_content_no_id(self, mock_session):
mock_session.return_value = FakeSession()
error_message = "No ticket ID associated with ticket object. " \
"Set ticket ID with set_ticket_id(<ticket_id>)"
with patch.object(bugzilla.BugzillaTicket, '_verify_ticket_id'):
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
self.assertFalse(ticket._verify_ticket_id(TICKET_ID))
self.assertEqual(ticket.get_ticket_content(), FAILURE_RESULT._replace(error_message=error_message))

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_verify_ticket_id_unexpected_response(self, mock_session):
def test_get_ticket_content_unexpected_response(self, mock_session):
mock_session.return_value = FakeSession(status_code=400)
error_message = "Error getting ticket content"
with self.assertRaises(ticketutil.ticket.TicketException):
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, TICKET_ID)
self.assertEquals(ticket.get_ticket_content(), FAILURE_RESULT._replace(error_message=error_message))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_verify_ticket_success(self, mock_session, mock_content):
mock_session.return_value = FakeSession()
mock_content.return_value = SUCCESS_RESULT
ticket = bugzilla.BugzillaTicket(URL, PROJECT, TICKET_ID)
self.assertTrue(ticket._verify_ticket_id(TICKET_ID))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_verify_ticket_failure(self, mock_session, mock_content):
mock_session.return_value = FakeSession(status_code=400)
mock_content.return_value = FAILURE_RESULT
with self.assertRaises(ticketutil.ticket.TicketException):
ticket = bugzilla.BugzillaTicket(URL, PROJECT, TICKET_ID)
self.assertFalse(ticket._verify_ticket_id(TICKET_ID))

@patch.object(bugzilla.BugzillaTicket, '_create_ticket_request')
Expand All @@ -200,16 +227,16 @@ def test_verify_ticket_id_unexpected_response(self, mock_session):
def test_create(self, mock_session, mock_parameters, mock_request):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
t = ticket.create(SUMMARY, DESCRIPTION, assignee='me')
mock_parameters.assert_called_with(SUMMARY, DESCRIPTION, {'assignee': 'me'})
t = ticket.create(SUMMARY, DESCRIPTION, COMPONENT, VERSION, assignee='me')
mock_parameters.assert_called_with(SUMMARY, DESCRIPTION, COMPONENT, VERSION, {'assignee': 'me'})
self.assertEqual(t, mock_request.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_create_no_summary(self, mock_session):
mock_session.return_value = FakeSession()
error_message = "summary is a necessary parameter for ticket creation"
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
t = ticket.create(None, DESCRIPTION, assignee='me')
t = ticket.create(None, DESCRIPTION, COMPONENT, VERSION, assignee='me')
self.assertEqual(t, FAILURE_RESULT._replace(error_message=error_message))

@patch.object(bugzilla, '_prepare_ticket_fields')
Expand All @@ -219,23 +246,26 @@ def test_create_ticket_parameters(self, mock_session, mock_fields):
FIELDS = {'assignee': 'me'}
mock_fields.return_value = FIELDS
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
t = ticket._create_ticket_parameters(SUMMARY, DESCRIPTION, FIELDS)
t = ticket._create_ticket_parameters(SUMMARY, DESCRIPTION, COMPONENT, VERSION, FIELDS)
expected_params = {"product": PROJECT,
"summary": SUMMARY,
"description": DESCRIPTION,
"component": COMPONENT,
"version": VERSION,
'assignee': 'me'}
self.assertDictEqual(t, expected_params)

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla.BugzillaTicket, '_verify_project')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_create_ticket_request_id(self, mock_session, mock_project):
def test_create_ticket_request_id(self, mock_session, mock_project, mock_content):
mock_session.return_value = FakeSession(status_code=204)
ticket = bugzilla.BugzillaTicket(URL, PROJECT)
with patch.object(bugzilla.BugzillaTicket, '_generate_ticket_url') as mock_url:
t = ticket._create_ticket_request({})
self.assertEqual(ticket.ticket_id, TICKET_ID2)
self.assertEqual(ticket.ticket_url, mock_url.return_value)
self.assertEqual(t, SUCCESS_RESULT)
self.assertEqual(t, mock_content.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_create_ticket_request_error(self, mock_session):
Expand Down Expand Up @@ -285,23 +315,24 @@ def test_edit_bugs(self, mock_session, mock_fields):
mock_session.return_value = FakeSession(status_code=402)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.edit()
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL, ticket_content=MOCK402))

@patch.object(bugzilla, '_prepare_ticket_fields')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_edit_error(self, mock_session, mock_fields):
mock_session.return_value = FakeSession(status_code=401)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.edit()
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, MOCK401))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla, '_prepare_ticket_fields')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_edit(self, mock_session, mock_fields):
def test_edit(self, mock_session, mock_fields, mock_content):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.edit()
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, mock_content.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_comment_no_id(self, mock_session):
Expand All @@ -325,15 +356,16 @@ def test_add_comment_error(self, mock_session, mock_fields):
mock_session.return_value = FakeSession(status_code=401)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_comment('')
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, MOCK401))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla, '_prepare_ticket_fields')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_comment(self, mock_session, mock_fields):
def test_add_comment(self, mock_session, mock_fields, mock_content):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_comment('')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, mock_content.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_attachment_no_id(self, mock_session):
Expand All @@ -347,7 +379,7 @@ def test_add_attachment_ioerror(self, mock_session):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_attachment('file_name', 'data', 'summary')
self.assertEqual(t, RETURN_RESULT('Failure', 'File file_name not found', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'File file_name not found', TICKET_URL, MOCK200))

@patch('ticketutil.bugzilla.base64.standard_b64encode')
@patch('ticketutil.bugzilla.mimetypes.guess_type')
Expand All @@ -370,17 +402,18 @@ def test_add_attachment_error(self, mock_session, mock_open, mock_guess_type, mo
mock_session.return_value = FakeSession(status_code=401)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_attachment('file_name', 'data', 'summary')
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, MOCK401))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch('ticketutil.bugzilla.base64.standard_b64encode')
@patch('ticketutil.bugzilla.mimetypes.guess_type')
@patch('builtins.open')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_attachment(self, mock_session, mock_open, mock_guess_type, mock_encode):
def test_add_attachment(self, mock_session, mock_open, mock_guess_type, mock_encode, mock_content):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_attachment('file_name', 'data', 'summary')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, mock_content.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_change_status_no_id(self, mock_session):
Expand All @@ -404,15 +437,16 @@ def test_change_status_error(self, mock_session, mock_fields):
mock_session.return_value = FakeSession(status_code=401)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.change_status('')
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, MOCK401))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla, '_prepare_ticket_fields')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_change_status(self, mock_session, mock_fields):
def test_change_status(self, mock_session, mock_fields, mock_content):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.change_status('')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, mock_content.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_cc_no_id(self, mock_session):
Expand All @@ -435,21 +469,22 @@ def test_add_cc_bugs(self, mock_session):
mock_session.return_value = FakeSession(status_code=402)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_cc('')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL, ticket_content=MOCK402))

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_cc_error(self, mock_session):
mock_session.return_value = FakeSession(status_code=401)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_cc('')
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, MOCK401))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_add_cc(self, mock_session):
def test_add_cc(self, mock_session, mock_content):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.add_cc('')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, mock_content.return_value)

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_remove_cc_no_id(self, mock_session):
Expand All @@ -472,21 +507,22 @@ def test_remove_cc_bugs(self, mock_session):
mock_session.return_value = FakeSession(status_code=402)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.remove_cc('')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL, ticket_content=MOCK402))

@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_remove_cc_error(self, mock_session):
mock_session.return_value = FakeSession(status_code=401)
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.remove_cc('')
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, None))
self.assertEqual(t, RETURN_RESULT('Failure', 'There is some error.', TICKET_URL, MOCK401))

@patch.object(bugzilla.BugzillaTicket, 'get_ticket_content')
@patch.object(bugzilla.BugzillaTicket, '_create_requests_session')
def test_remove_cc(self, mock_session):
def test_remove_cc(self, mock_session, mock_content):
mock_session.return_value = FakeSession()
ticket = bugzilla.BugzillaTicket(URL, PROJECT, ticket_id=TICKET_ID)
t = ticket.remove_cc('')
self.assertEqual(t, SUCCESS_RESULT._replace(url=TICKET_URL))
self.assertEqual(t, mock_content.return_value)

def test_prepare_ticket_fields(self):
fields = {'groups': ['group1', 'group2'], 'assignee': 'me'}
Expand Down

0 comments on commit d27e586

Please sign in to comment.