Skip to content

Commit 3f670d5

Browse files
committed
Merge PR sooperset#685: fix: make jira_get_sprint_issues respect fields parameter
2 parents 7213d6d + 8ba90b7 commit 3f670d5

File tree

2 files changed

+96
-31
lines changed

2 files changed

+96
-31
lines changed

src/mcp_atlassian/jira/search.py

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -255,36 +255,17 @@ def get_sprint_issues(
255255
JiraSearchResult object containing sprint issues and metadata
256256
257257
Raises:
258-
Exception: If there is an error getting board issues
258+
Exception: If there is an error getting sprint issues
259259
"""
260260
try:
261-
# Determine fields_param
262-
fields_param = fields
263-
if fields_param is None:
264-
fields_param = ",".join(DEFAULT_READ_JIRA_FIELDS)
265-
266-
response = self.jira.get_sprint_issues(
267-
sprint_id=sprint_id,
261+
# Use JQL search to get sprint issues with proper fields filtering
262+
jql = f"sprint = {sprint_id}"
263+
return self.search_issues(
264+
jql=jql,
265+
fields=fields,
268266
start=start,
269267
limit=limit,
270268
)
271-
if not isinstance(response, dict):
272-
msg = f"Unexpected return value type from `jira.get_sprint_issues`: {type(response)}"
273-
logger.error(msg)
274-
raise TypeError(msg)
275-
276-
# Convert the response to a search result model
277-
search_result = JiraSearchResult.from_api_response(
278-
response, base_url=self.config.url, requested_fields=fields_param
279-
)
280-
return search_result
281-
except requests.HTTPError as e:
282-
logger.error(
283-
f"Error searching issues for sprint '{sprint_id}': {str(e.response.content)}"
284-
)
285-
raise Exception(
286-
f"Error searching issues for sprint: {str(e.response.content)}"
287-
) from e
288269
except Exception as e:
289-
logger.error(f"Error searching issues for sprint: {sprint_id}': {str(e)}")
270+
logger.error(f"Error searching issues for sprint '{sprint_id}': {str(e)}")
290271
raise Exception(f"Error searching issues for sprint: {str(e)}") from e

tests/unit/jira/test_search.py

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -527,11 +527,24 @@ def test_get_sprint_issues(self, search_mixin: SearchMixin):
527527
"startAt": 0,
528528
"maxResults": 50,
529529
}
530-
search_mixin.jira.get_sprint_issues.return_value = mock_issues
530+
531+
# Mock search_issues since get_sprint_issues now uses it internally
532+
search_result = JiraSearchResult.from_api_response(
533+
mock_issues, base_url=search_mixin.config.url
534+
)
535+
search_mixin.search_issues = MagicMock(return_value=search_result)
531536

532537
# Call the method
533538
result = search_mixin.get_sprint_issues("10001")
534539

540+
# Verify that search_issues was called with correct JQL
541+
search_mixin.search_issues.assert_called_once_with(
542+
jql="sprint = 10001",
543+
fields=None,
544+
start=0,
545+
limit=50,
546+
)
547+
535548
# Verify results
536549
assert isinstance(result, JiraSearchResult)
537550
assert len(result.issues) == 1
@@ -553,20 +566,91 @@ def test_get_sprint_issues(self, search_mixin: SearchMixin):
553566
assert issue.priority.name == "High"
554567

555568
def test_get_sprint_issues_exception(self, search_mixin: SearchMixin):
556-
search_mixin.jira.get_sprint_issues.side_effect = Exception("API Error")
569+
search_mixin.search_issues = MagicMock(side_effect=Exception("API Error"))
557570

558571
with pytest.raises(Exception) as e:
559572
search_mixin.get_sprint_issues("10001")
560573
assert "API Error" in str(e.value)
561574

562575
def test_get_sprint_issues_http_error(self, search_mixin: SearchMixin):
563-
search_mixin.jira.get_sprint_issues.side_effect = requests.HTTPError(
564-
response=MagicMock(content="API Error content")
576+
search_mixin.search_issues = MagicMock(
577+
side_effect=requests.HTTPError(
578+
response=MagicMock(content="API Error content")
579+
)
565580
)
566581

567582
with pytest.raises(Exception) as e:
568583
search_mixin.get_sprint_issues("10001")
569-
assert "API Error content" in str(e.value)
584+
assert "Error searching issues for sprint" in str(e.value)
585+
586+
def test_get_sprint_issues_with_fields_parameter(self, search_mixin: SearchMixin):
587+
"""Test get_sprint_issues method properly passes fields parameter to search_issues."""
588+
mock_issues = {
589+
"issues": [
590+
{
591+
"id": "10001",
592+
"key": "TEST-123",
593+
"fields": {
594+
"summary": "Test issue with custom field",
595+
"assignee": {
596+
"displayName": "Test User",
597+
"emailAddress": "[email protected]",
598+
"active": True,
599+
},
600+
"customfield_10049": "Custom value",
601+
"issuetype": {"name": "Bug"},
602+
"status": {"name": "Open"},
603+
"description": "Issue description",
604+
"created": "2024-01-01T10:00:00.000+0000",
605+
"updated": "2024-01-01T11:00:00.000+0000",
606+
"priority": {"name": "High"},
607+
},
608+
}
609+
],
610+
"total": 1,
611+
"startAt": 0,
612+
"maxResults": 50,
613+
}
614+
615+
# Mock search_issues to return a result with requested_fields set
616+
search_result = JiraSearchResult.from_api_response(
617+
mock_issues,
618+
base_url=search_mixin.config.url,
619+
requested_fields="summary,assignee,customfield_10049",
620+
)
621+
search_mixin.search_issues = MagicMock(return_value=search_result)
622+
623+
# Call the method with specific fields
624+
result = search_mixin.get_sprint_issues(
625+
"10001", fields="summary,assignee,customfield_10049"
626+
)
627+
628+
# Verify that search_issues was called with correct parameters
629+
search_mixin.search_issues.assert_called_once_with(
630+
jql="sprint = 10001",
631+
fields="summary,assignee,customfield_10049",
632+
start=0,
633+
limit=50,
634+
)
635+
636+
# Verify results
637+
assert isinstance(result, JiraSearchResult)
638+
assert len(result.issues) == 1
639+
issue = result.issues[0]
640+
641+
# Convert to simplified dict to check field filtering
642+
simplified = issue.to_simplified_dict()
643+
644+
# These fields should be included (plus id and key which are always included)
645+
assert "id" in simplified
646+
assert "key" in simplified
647+
assert "summary" in simplified
648+
assert "assignee" in simplified
649+
assert "customfield_10049" in simplified
650+
651+
assert simplified["customfield_10049"] == {"value": "Custom value"}
652+
assert "assignee" in simplified
653+
assert simplified["assignee"]["display_name"] == "Test User"
570654

571655
@pytest.mark.parametrize("is_cloud", [True, False])
572656
def test_search_issues_with_projects_filter_jql_construction(

0 commit comments

Comments
 (0)