From 6332ce47cb79b34839442d93ad935b65d62a6a42 Mon Sep 17 00:00:00 2001 From: novokrest Date: Mon, 11 Jun 2018 06:58:54 +0300 Subject: [PATCH] jira: Add tests for error cases and `help` command. --- .../bots/jira/fixtures/test_create_error.json | 20 +++ .../bots/jira/fixtures/test_edit_error.json | 20 +++ .../bots/jira/fixtures/test_get_error.json | 16 +++ zulip_bots/zulip_bots/bots/jira/test_jira.py | 133 ++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 zulip_bots/zulip_bots/bots/jira/fixtures/test_create_error.json create mode 100644 zulip_bots/zulip_bots/bots/jira/fixtures/test_edit_error.json create mode 100644 zulip_bots/zulip_bots/bots/jira/fixtures/test_get_error.json diff --git a/zulip_bots/zulip_bots/bots/jira/fixtures/test_create_error.json b/zulip_bots/zulip_bots/bots/jira/fixtures/test_create_error.json new file mode 100644 index 0000000..5d2af2f --- /dev/null +++ b/zulip_bots/zulip_bots/bots/jira/fixtures/test_create_error.json @@ -0,0 +1,20 @@ +{ + "request": { + "api_url": "https://example.atlassian.net/rest/api/2/issue", + "method": "POST", + "headers": { + "Authorization": "Basic ZXhhbXBsZUBleGFtcGxlLmNvbTpxd2VydHkhMTIz", + "Content-type": "application/json" + }, + "data": "{\"fields\": {\"summary\": \"Testing\",\"project\": { \"key\": \"TEST\" },\"issuetype\": { \"name\": \"Task\" },\"description\": \"This is a test description\",\"assignee\": { \"name\": \"testuser\" },\"priority\": { \"name\": \"Medium\" },\"labels\": [\"issues\",\"testing\"],\"duedate\": \"2018-06-11\"}}" + }, + "response": { + "errors": { + "error1": "error1" + } + }, + "response-headers": { + "status": 200, + "content-type": "application/json; charset=utf-8" + } +} diff --git a/zulip_bots/zulip_bots/bots/jira/fixtures/test_edit_error.json b/zulip_bots/zulip_bots/bots/jira/fixtures/test_edit_error.json new file mode 100644 index 0000000..5e4b8cf --- /dev/null +++ b/zulip_bots/zulip_bots/bots/jira/fixtures/test_edit_error.json @@ -0,0 +1,20 @@ +{ + "request": { + "api_url": "https://example.atlassian.net/rest/api/2/issue/TEST-13", + "method": "PUT", + "headers": { + "Authorization": "Basic ZXhhbXBsZUBleGFtcGxlLmNvbTpxd2VydHkhMTIz", + "Content-type": "application/json" + }, + "data": "{\"fields\": {\"summary\": \"Change the summary\",\"project\": { \"key\": \"TEST\" },\"issuetype\": { \"name\": \"Bug\" },\"description\": \"This is a test description\",\"assignee\": { \"name\": \"testuser\" },\"priority\": { \"name\": \"Low\" },\"labels\": [\"issues\",\"testing\"],\"duedate\": \"2018-06-11\"}}" + }, + "response": { + "errors": { + "error1": "error1" + } + }, + "response-headers": { + "status": 200, + "content-type": "application/json; charset=utf-8" + } +} diff --git a/zulip_bots/zulip_bots/bots/jira/fixtures/test_get_error.json b/zulip_bots/zulip_bots/bots/jira/fixtures/test_get_error.json new file mode 100644 index 0000000..ca9c6ec --- /dev/null +++ b/zulip_bots/zulip_bots/bots/jira/fixtures/test_get_error.json @@ -0,0 +1,16 @@ +{ + "request": { + "api_url": "https://example.atlassian.net/rest/api/2/issue/TEST-13", + "method": "GET", + "headers": { + "Authorization": "Basic ZXhhbXBsZUBleGFtcGxlLmNvbTpxd2VydHkhMTIz" + } + }, + "response": { + "errorMessages": ["error1"] + }, + "response-headers": { + "status": 200, + "content-type": "application/json; charset=utf-8" + } +} diff --git a/zulip_bots/zulip_bots/bots/jira/test_jira.py b/zulip_bots/zulip_bots/bots/jira/test_jira.py index 0d6f90f..2b1bebc 100644 --- a/zulip_bots/zulip_bots/bots/jira/test_jira.py +++ b/zulip_bots/zulip_bots/bots/jira/test_jira.py @@ -46,6 +46,112 @@ class TestJiraBot(BotTestCase, DefaultTests): MOCK_NOTHING_RESPONSE = 'Sorry, I don\'t understand that! Send me `help` for instructions.' + MOCK_HELP_RESPONSE = ''' +**get** + +`get` takes in an issue key and sends back information about that issue. For example, + +you: + + > @**Jira Bot** get "BOTS-13" + +Jira Bot: + + > **Issue *BOTS-13*: Create Jira Bot** + > + > - Type: *Task* + > - Description: + > > Jira Bot would connect to Jira. + > - Creator: *admin* + > - Project: *Bots* + > - Priority: *Medium* + > - Status: *To Do* + +--- + +**create** + +`create` creates an issue using its + + - summary, + - project, + - type, + - description *(optional)*, + - assignee *(optional)*, + - priority *(optional)*, + - labels *(optional)*, and + - due date *(optional)* + +For example, to create an issue with every option, + +you: + + > @**Jira Bot** create issue "Make an issue" in project "BOTS"' with type \ +"Task" with description "This is a description" assigned to "skunkmb" with \ +priority "Medium" labeled "issues, testing" due "2017-01-23" + +Jira Bot: + + > Issue *BOTS-16* is up! https://example.atlassian.net/browse/BOTS-16 + +--- + +**edit** + +`edit` is like create, but changes an existing issue using its + + - summary, + - project *(optional)*, + - type *(optional)*, + - description *(optional)*, + - assignee *(optional)*, + - priority *(optional)*, + - labels *(optional)*, and + - due date *(optional)*. + +For example, to change every part of an issue, + +you: + + > @**Jira Bot** edit issue "BOTS-16" to use summary "Change the summary" \ +to use project "NEWBOTS" to use type "Bug" to use description "This is \ +a new description" by assigning to "admin" to use priority "Low" by \ +labeling "new, labels" by making due "2018-12-5" + +Jira Bot: + + > Issue *BOTS-16* was edited! https://example.atlassian.net/browse/BOTS-16 +''' + + def _test_invalid_config(self, invalid_config, error_message) -> None: + with self.mock_config_info(invalid_config), \ + self.assertRaisesRegexp(KeyError, error_message): + bot, bot_handler = self._get_handlers() + + def test_config_without_username(self) -> None: + config_without_username = { + 'password': 'qwerty!123', + 'domain': 'example.atlassian.net', + } + self._test_invalid_config(config_without_username, + 'No `username` was specified') + + def test_config_without_password(self) -> None: + config_without_password = { + 'username': 'example@example.com', + 'domain': 'example.atlassian.net', + } + self._test_invalid_config(config_without_password, + 'No `password` was specified') + + def test_config_without_domain(self) -> None: + config_without_domain = { + 'username': 'example@example.com', + 'password': 'qwerty!123', + } + self._test_invalid_config(config_without_domain, + 'No `domain` was specified') + def test_get(self) -> None: with patch('requests.get') as response, \ self.mock_config_info(self.MOCK_CONFIG_INFO): @@ -54,6 +160,12 @@ class TestJiraBot(BotTestCase, DefaultTests): self.verify_reply('get "TEST-13"', self.MOCK_GET_RESPONSE) + def test_get_error(self) -> None: + with self.mock_config_info(self.MOCK_CONFIG_INFO), \ + self.mock_http_conversation('test_get_error'): + self.verify_reply('get "TEST-13"', + 'Oh no! Jira raised an error:\n > error1') + def test_create(self) -> None: with patch('requests.post') as response, \ self.mock_config_info(self.MOCK_CONFIG_INFO): @@ -65,6 +177,14 @@ class TestJiraBot(BotTestCase, DefaultTests): self.MOCK_CREATE_RESPONSE ) + def test_create_error(self) -> None: + with self.mock_config_info(self.MOCK_CONFIG_INFO), \ + self.mock_http_conversation('test_create_error'): + self.verify_reply('create issue "Testing" in project "TEST" with type "Task" ' + 'with description "This is a test description" assigned to "testuser" ' + 'with priority "Medium" labeled "issues, testing" due "2018-06-11"', + 'Oh no! Jira raised an error:\n > error1') + def test_edit(self) -> None: with patch('requests.put') as response, \ self.mock_config_info(self.MOCK_CONFIG_INFO): @@ -76,6 +196,19 @@ class TestJiraBot(BotTestCase, DefaultTests): self.MOCK_EDIT_RESPONSE ) + def test_edit_error(self) -> None: + with self.mock_config_info(self.MOCK_CONFIG_INFO), \ + self.mock_http_conversation('test_edit_error'): + self.verify_reply('edit issue "TEST-13" to use summary "Change the summary" ' + 'to use project "TEST" to use type "Bug" to use description "This is a test description" ' + 'by assigning to "testuser" to use priority "Low" by labeling "issues, testing" ' + 'by making due "2018-06-11"', + 'Oh no! Jira raised an error:\n > error1') + + def test_help(self) -> None: + with self.mock_config_info(self.MOCK_CONFIG_INFO): + self.verify_reply('help', self.MOCK_HELP_RESPONSE) + # This overrides the default one in `BotTestCase`. def test_bot_responds_to_empty_message(self) -> None: with self.mock_config_info(self.MOCK_CONFIG_INFO):