diff --git a/README.md b/README.md index 18f984b..ee2e18b 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,31 @@ Example: >>> from jira import JIRA >>> my_jira_client = JIRA("https://my-jira-server.com", basicauth("MYUSERNAME","MYPASSWORD") >>> tb = JiraAgileToolBox(my_jira_client) ->>> tb.get_storypoints_from_epic("PROJ-001") +>>> tb.get_storypoints_from_epic("JAT-001") {'total': 100, "Reported": 50, "Closed": 50} +``` + +- ### Ranking a list of epics on top of another one + +Example: +```python +>>> from jira_agile_toolbox import JiraAgileToolBox +>>> from jira import JIRA +>>> my_jira_client = JIRA("https://my-jira-server.com", basicauth("MYUSERNAME","MYPASSWORD") +>>> tb = JiraAgileToolBox(my_jira_client) +>>> tb.rank_issues_by_list([my_jira_client.issue("JAT-001"), my_jira_client.issue("JAT-003")] my_jira_client.issue("JAT-005")) +``` + +will rank issues like: + +| original | result | +| -------- | ------ | +| JAT-010 | JAT-010 +| JAT-005 | JAT-001 +| JAT-003 | JAT-003 +| JAT-002 | JAT-005 +| JAT-001 | JAT-002 + diff --git a/jira_agile_toolbox/__init__.py b/jira_agile_toolbox/__init__.py index eaf0d55..33f8363 100644 --- a/jira_agile_toolbox/__init__.py +++ b/jira_agile_toolbox/__init__.py @@ -53,6 +53,25 @@ def get_storypoints_from_epic(self, epic): return sum_of_story_points_per_state def get_custom_field_from_name(self, name): + """ + helper method to find custom fields + + :param name: name of the field you want the "customxxxxx" value from + :return: + """ for field in self._jira_client.fields(): if field["name"] == name: return field["id"] + + def rank_issues_by_list(self, ranked_list, on_top_of_issue): + """ + sorts the provided list by rank on top of the latter issue + + :param ranked_list: list of issues to be sorted by rank index 0 has highest rank + :param on_top_of_issue: issue on top of which these issues need to land + """ + reversed_list = ranked_list[::-1] + reversed_list.insert(0, on_top_of_issue) + for i, value in enumerate(reversed_list): + if i < len(reversed_list) - 1: + self._jira_client.rank(reversed_list[i + 1].key, value.key) diff --git a/tests/test_ranking.py b/tests/test_ranking.py new file mode 100644 index 0000000..ad936d3 --- /dev/null +++ b/tests/test_ranking.py @@ -0,0 +1,42 @@ +from unittest import TestCase +from unittest.mock import Mock, MagicMock, call + +import jira + +from jira_agile_toolbox import JiraAgileToolBox + + +class MockedJiraIssue(jira.Issue): + def __init__(self, key, status="Reported"): + self.fields = MagicMock() + self.key = key + + +class TestRanking(TestCase): + def test_ranking_by_list_calls_the_jira_client_in_the_proper_order(self): + # Given + jira_client = Mock() + ranked_list = [MockedJiraIssue("PY-001"), MockedJiraIssue("PY-002"), MockedJiraIssue("PY-003")] + on_top_of = MockedJiraIssue("PY-100") + + jat = JiraAgileToolBox(jira_client) + + # When + jat.rank_issues_by_list(ranked_list, on_top_of) + + # Then + jira_client.rank.assert_has_calls([call("PY-003", "PY-100"), call("PY-002", "PY-003"), call("PY-001", "PY-002")]) + + def test_ranking_by_list_calls_the_jira_client_in_the_proper_order_with_other_order(self): + # Given + jira_client = Mock() + ranked_list = [MockedJiraIssue("PsY-011"), MockedJiraIssue("PsY-002"), MockedJiraIssue("PsY-103")] + on_top_of = MockedJiraIssue("PsY-100") + + jat = JiraAgileToolBox(jira_client) + + # When + jat.rank_issues_by_list(ranked_list, on_top_of) + + # Then + jira_client.rank.assert_has_calls([call("PsY-103", "PsY-100"), call("PsY-002", "PsY-103"), call("PsY-011", "PsY-002")])