Skip to content

Commit 41ea359

Browse files
committed
implements board.GetIssuesForBacklog
1 parent 6752705 commit 41ea359

File tree

5 files changed

+245
-0
lines changed

5 files changed

+245
-0
lines changed

cloud/board.go

+37
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,19 @@ type BoardConfigurationColumnStatus struct {
139139
Self string `json:"self"`
140140
}
141141

142+
// GetBoardIssuesOptions specifies the optional parameters to the BoardService.GetIssuesForBacklog
143+
type GetBoardIssuesOptions struct {
144+
// Jql filters results to sprints in the specified jql query
145+
Jql string `json:"jql"`
146+
147+
SearchOptions
148+
}
149+
150+
// IssuesInBoardResult represents a wrapper struct for search result
151+
type IssuesInBoardResult struct {
152+
Issues []Issue `json:"issues"`
153+
}
154+
142155
// GetAllBoards will returns all boards. This only includes boards that the user has permission to view.
143156
//
144157
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
@@ -261,6 +274,30 @@ func (s *BoardService) GetAllSprints(ctx context.Context, boardID int64, options
261274
return result, resp, err
262275
}
263276

277+
// GetIssuesForBacklog returns all issues from a backlog, for a given board ID.
278+
// This only includes issues that the user has permission to view.
279+
//
280+
// Jira API docs: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-backlog-get
281+
func (s *BoardService) GetIssuesForBacklog(ctx context.Context, boardID int64, options *GetBoardIssuesOptions) ([]Issue, *Response, error) {
282+
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/backlog", boardID)
283+
url, err := addOptions(apiEndpoint, options)
284+
if err != nil {
285+
return nil, nil, err
286+
}
287+
req, err := s.client.NewRequest(ctx, http.MethodGet, url, nil)
288+
if err != nil {
289+
return nil, nil, err
290+
}
291+
292+
result := new(IssuesInBoardResult)
293+
resp, err := s.client.Do(req, result)
294+
if err != nil {
295+
err = NewJiraError(resp, err)
296+
}
297+
298+
return result.Issues, resp, err
299+
}
300+
264301
// GetBoardConfiguration will return a board configuration for a given board Id
265302
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
266303
//

cloud/board_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,31 @@ func TestBoardService_GetBoardConfigoration(t *testing.T) {
233233
t.Errorf("Expected a max of 0 issues in progress. Got %d", inProgressColumn.Max)
234234
}
235235
}
236+
237+
func TestBoardService_GetIssuesForBacklog(t *testing.T) {
238+
setup()
239+
defer teardown()
240+
testapiEndpoint := "/rest/agile/1.0/board/123/backlog"
241+
242+
raw, err := os.ReadFile("../testing/mock-data/backlog_in_board.json")
243+
if err != nil {
244+
t.Error(err.Error())
245+
}
246+
testMux.HandleFunc(testapiEndpoint, func(w http.ResponseWriter, r *http.Request) {
247+
testMethod(t, r, http.MethodGet)
248+
testRequestURL(t, r, testapiEndpoint)
249+
fmt.Fprint(w, string(raw))
250+
})
251+
252+
issues, _, err := testClient.Board.GetIssuesForBacklog(context.Background(), 123, nil)
253+
if err != nil {
254+
t.Errorf("Error given: %v", err)
255+
}
256+
if issues == nil {
257+
t.Error("Expected issues in sprint list. Issues list is nil")
258+
}
259+
if len(issues) != 1 {
260+
t.Errorf("Expect there to be 1 issue in the sprint, found %v", len(issues))
261+
}
262+
263+
}

onpremise/board.go

+37
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,19 @@ type BoardConfigurationColumnStatus struct {
125125
Self string `json:"self"`
126126
}
127127

128+
// GetBoardIssuesOptions specifies the optional parameters to the BoardService.GetIssuesForBacklog
129+
type GetBoardIssuesOptions struct {
130+
// Jql filters results to sprints in the specified jql query
131+
Jql string `json:"jql"`
132+
133+
SearchOptions
134+
}
135+
136+
// IssuesInBoardResult represents a wrapper struct for search result
137+
type IssuesInBoardResult struct {
138+
Issues []Issue `json:"issues"`
139+
}
140+
128141
// GetAllBoards will returns all boards. This only includes boards that the user has permission to view.
129142
//
130143
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
@@ -252,6 +265,30 @@ func (s *BoardService) GetAllSprints(ctx context.Context, boardID int, options *
252265
return result, resp, err
253266
}
254267

268+
// GetIssuesForBacklog returns all issues from a backlog, for a given board ID.
269+
// This only includes issues that the user has permission to view.
270+
//
271+
// Jira API docs: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-backlog-get
272+
func (s *BoardService) GetIssuesForBacklog(ctx context.Context, boardID int64, options *GetBoardIssuesOptions) ([]Issue, *Response, error) {
273+
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/backlog", boardID)
274+
url, err := addOptions(apiEndpoint, options)
275+
if err != nil {
276+
return nil, nil, err
277+
}
278+
req, err := s.client.NewRequest(ctx, http.MethodGet, url, nil)
279+
if err != nil {
280+
return nil, nil, err
281+
}
282+
283+
result := new(IssuesInBoardResult)
284+
resp, err := s.client.Do(req, result)
285+
if err != nil {
286+
err = NewJiraError(resp, err)
287+
}
288+
289+
return result.Issues, resp, err
290+
}
291+
255292
// GetBoardConfiguration will return a board configuration for a given board Id
256293
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
257294
//

onpremise/board_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,31 @@ func TestBoardService_GetBoardConfigoration(t *testing.T) {
233233
t.Errorf("Expected a max of 0 issues in progress. Got %d", inProgressColumn.Max)
234234
}
235235
}
236+
237+
func TestBoardService_GetIssuesForBacklog(t *testing.T) {
238+
setup()
239+
defer teardown()
240+
testapiEndpoint := "/rest/agile/1.0/board/123/backlog"
241+
242+
raw, err := os.ReadFile("../testing/mock-data/backlog_in_board.json")
243+
if err != nil {
244+
t.Error(err.Error())
245+
}
246+
testMux.HandleFunc(testapiEndpoint, func(w http.ResponseWriter, r *http.Request) {
247+
testMethod(t, r, http.MethodGet)
248+
testRequestURL(t, r, testapiEndpoint)
249+
fmt.Fprint(w, string(raw))
250+
})
251+
252+
issues, _, err := testClient.Board.GetIssuesForBacklog(context.Background(), 123, nil)
253+
if err != nil {
254+
t.Errorf("Error given: %v", err)
255+
}
256+
if issues == nil {
257+
t.Error("Expected issues in sprint list. Issues list is nil")
258+
}
259+
if len(issues) != 1 {
260+
t.Errorf("Expect there to be 1 issue in the sprint, found %v", len(issues))
261+
}
262+
263+
}
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"expand": "schema,names",
3+
"startAt": 0,
4+
"maxResults": 50,
5+
"total": 10,
6+
"issues": [
7+
{
8+
"expand": "operations,versionedRepresentations,editmeta,changelog,renderedFields",
9+
"id": "12338",
10+
"self": "https://example.atlassian.net/rest/agile/1.0/issue/12338",
11+
"key": "AR-86",
12+
"fields": {
13+
"issuetype": {
14+
"self": "https://example.atlassian.net/rest/api/2/issuetype/3",
15+
"id": "3",
16+
"description": "A task that needs to be done.",
17+
"iconUrl": "https://example.atlassian.net/secure/viewavatar?size=xsmall&avatarId=10418&avatarType=issuetype",
18+
"name": "Task",
19+
"subtask": false,
20+
"avatarId": 10418
21+
},
22+
"timespent": null,
23+
"project": {
24+
"self": "https://example.atlassian.net/rest/api/2/project/10302",
25+
"id": "10302",
26+
"key": "AR",
27+
"name": "Team Argon",
28+
"avatarUrls": {
29+
"48x48": "https://example.atlassian.net/secure/projectavatar?pid=10302&avatarId=10610",
30+
"24x24": "https://example.atlassian.net/secure/projectavatar?size=small&pid=10302&avatarId=10610",
31+
"16x16": "https://example.atlassian.net/secure/projectavatar?size=xsmall&pid=10302&avatarId=10610",
32+
"32x32": "https://example.atlassian.net/secure/projectavatar?size=medium&pid=10302&avatarId=10610"
33+
}
34+
},
35+
"fixVersions": [],
36+
"customfield_11200": "0|0zzzzd:vi",
37+
"aggregatetimespent": null,
38+
"resolution": {
39+
"self": "https://example.atlassian.net/rest/api/2/resolution/6",
40+
"id": "6",
41+
"description": "",
42+
"name": "Done"
43+
},
44+
"customfield_11401": null,
45+
"customfield_11400": null,
46+
"customfield_10105": 13.0,
47+
"customfield_10700": "AR-37",
48+
"resolutiondate": "2015-12-07T14:19:13.000-0800",
49+
"workratio": -1,
50+
"lastViewed": null,
51+
"watches": {
52+
"self": "https://example.atlassian.net/rest/api/2/issue/AR-86/watchers",
53+
"watchCount": 2,
54+
"isWatching": true
55+
},
56+
"created": "2015-12-02T07:39:15.000-0800",
57+
"epic": {
58+
"id": 11900,
59+
"key": "AR-37",
60+
"self": "https://example.atlassian.net/rest/agile/1.0/epic/11900",
61+
"name": "Moderation: Design",
62+
"summary": "Moderation design",
63+
"color": {
64+
"key": "color_8"
65+
},
66+
"done": true
67+
},
68+
"priority": {
69+
"self": "https://example.atlassian.net/rest/api/2/priority/3",
70+
"iconUrl": "https://example.atlassian.net/images/icons/priorities/major.svg",
71+
"name": "Major",
72+
"id": "3"
73+
},
74+
"customfield_10102": null,
75+
"customfield_10103": null,
76+
"labels": [],
77+
"customfield_11700": null,
78+
"timeestimate": null,
79+
"aggregatetimeoriginalestimate": null,
80+
"versions": [],
81+
"issuelinks": [],
82+
"assignee": {
83+
"self": "https://example.atlassian.net/rest/api/2/user?username=mister.morris",
84+
"name": "mister.morris",
85+
"key": "mister.morris",
86+
"emailAddress": "[email protected]",
87+
"avatarUrls": {
88+
"48x48": "https://example.atlassian.net/secure/useravatar?ownerId=mister.morris&avatarId=10604",
89+
"24x24": "https://example.atlassian.net/secure/useravatar?size=small&ownerId=mister.morris&avatarId=10604",
90+
"16x16": "https://example.atlassian.net/secure/useravatar?size=xsmall&ownerId=mister.morris&avatarId=10604",
91+
"32x32": "https://example.atlassian.net/secure/useravatar?size=medium&ownerId=mister.morris&avatarId=10604"
92+
},
93+
"displayName": "mister Morris",
94+
"active": true,
95+
"timeZone": "America/New_York"
96+
},
97+
"updated": "2016-02-01T08:17:04.000-0800",
98+
"status": {
99+
"self": "https://example.atlassian.net/rest/api/2/status/10000",
100+
"description": "Ready to move to dev team for grooming",
101+
"iconUrl": "https://example.atlassian.net/images/icons/statuses/closed.png",
102+
"name": "Ready",
103+
"id": "10000",
104+
"statusCategory": {
105+
"self": "https://example.atlassian.net/rest/api/2/statuscategory/2",
106+
"id": 2,
107+
"key": "new",
108+
"colorName": "blue-gray",
109+
"name": "To Do"
110+
}
111+
}
112+
}
113+
}
114+
]
115+
}

0 commit comments

Comments
 (0)