Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implements board.GetIssuesForBacklog #670

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions cloud/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ type BoardConfigurationColumnStatus struct {
Self string `json:"self"`
}

// GetBoardIssuesOptions specifies the optional parameters to the BoardService.GetIssuesForBacklog
type GetBoardIssuesOptions struct {
// Jql filters results to sprints in the specified jql query
Jql string `json:"jql"`

SearchOptions
}

// IssuesInBoardResult represents a wrapper struct for search result
type IssuesInBoardResult struct {
Issues []Issue `json:"issues"`
}

// GetAllBoards will returns all boards. This only includes boards that the user has permission to view.
//
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
Expand Down Expand Up @@ -261,6 +274,30 @@ func (s *BoardService) GetAllSprints(ctx context.Context, boardID int64, options
return result, resp, err
}

// GetIssuesForBacklog returns all issues from a backlog, for a given board ID.
// This only includes issues that the user has permission to view.
//
// Jira API docs: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-backlog-get
func (s *BoardService) GetIssuesForBacklog(ctx context.Context, boardID int64, options *GetBoardIssuesOptions) ([]Issue, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/backlog", boardID)
url, err := addOptions(apiEndpoint, options)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, nil, err
}

result := new(IssuesInBoardResult)
resp, err := s.client.Do(req, result)
if err != nil {
err = NewJiraError(resp, err)
}

return result.Issues, resp, err
}

// GetBoardConfiguration will return a board configuration for a given board Id
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
//
Expand Down
28 changes: 28 additions & 0 deletions cloud/board_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,31 @@ func TestBoardService_GetBoardConfigoration(t *testing.T) {
t.Errorf("Expected a max of 0 issues in progress. Got %d", inProgressColumn.Max)
}
}

func TestBoardService_GetIssuesForBacklog(t *testing.T) {
setup()
defer teardown()
testapiEndpoint := "/rest/agile/1.0/board/123/backlog"

raw, err := os.ReadFile("../testing/mock-data/backlog_in_board.json")
if err != nil {
t.Error(err.Error())
}
testMux.HandleFunc(testapiEndpoint, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
testRequestURL(t, r, testapiEndpoint)
fmt.Fprint(w, string(raw))
})

issues, _, err := testClient.Board.GetIssuesForBacklog(context.Background(), 123, nil)
if err != nil {
t.Errorf("Error given: %v", err)
}
if issues == nil {
t.Error("Expected issues in sprint list. Issues list is nil")
}
if len(issues) != 1 {
t.Errorf("Expect there to be 1 issue in the sprint, found %v", len(issues))
}

}
37 changes: 37 additions & 0 deletions onpremise/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ type BoardConfigurationColumnStatus struct {
Self string `json:"self"`
}

// GetBoardIssuesOptions specifies the optional parameters to the BoardService.GetIssuesForBacklog
type GetBoardIssuesOptions struct {
// Jql filters results to sprints in the specified jql query
Jql string `json:"jql"`

SearchOptions
}

// IssuesInBoardResult represents a wrapper struct for search result
type IssuesInBoardResult struct {
Issues []Issue `json:"issues"`
}

// GetAllBoards will returns all boards. This only includes boards that the user has permission to view.
//
// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
Expand Down Expand Up @@ -252,6 +265,30 @@ func (s *BoardService) GetAllSprints(ctx context.Context, boardID int, options *
return result, resp, err
}

// GetIssuesForBacklog returns all issues from a backlog, for a given board ID.
// This only includes issues that the user has permission to view.
//
// Jira API docs: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-backlog-get
func (s *BoardService) GetIssuesForBacklog(ctx context.Context, boardID int64, options *GetBoardIssuesOptions) ([]Issue, *Response, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/backlog", boardID)
url, err := addOptions(apiEndpoint, options)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, nil, err
}

result := new(IssuesInBoardResult)
resp, err := s.client.Do(req, result)
if err != nil {
err = NewJiraError(resp, err)
}

return result.Issues, resp, err
}

// GetBoardConfiguration will return a board configuration for a given board Id
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
//
Expand Down
28 changes: 28 additions & 0 deletions onpremise/board_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,31 @@ func TestBoardService_GetBoardConfigoration(t *testing.T) {
t.Errorf("Expected a max of 0 issues in progress. Got %d", inProgressColumn.Max)
}
}

func TestBoardService_GetIssuesForBacklog(t *testing.T) {
setup()
defer teardown()
testapiEndpoint := "/rest/agile/1.0/board/123/backlog"

raw, err := os.ReadFile("../testing/mock-data/backlog_in_board.json")
if err != nil {
t.Error(err.Error())
}
testMux.HandleFunc(testapiEndpoint, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
testRequestURL(t, r, testapiEndpoint)
fmt.Fprint(w, string(raw))
})

issues, _, err := testClient.Board.GetIssuesForBacklog(context.Background(), 123, nil)
if err != nil {
t.Errorf("Error given: %v", err)
}
if issues == nil {
t.Error("Expected issues in sprint list. Issues list is nil")
}
if len(issues) != 1 {
t.Errorf("Expect there to be 1 issue in the sprint, found %v", len(issues))
}

}
115 changes: 115 additions & 0 deletions testing/mock-data/backlog_in_board.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 10,
"issues": [
{
"expand": "operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id": "12338",
"self": "https://example.atlassian.net/rest/agile/1.0/issue/12338",
"key": "AR-86",
"fields": {
"issuetype": {
"self": "https://example.atlassian.net/rest/api/2/issuetype/3",
"id": "3",
"description": "A task that needs to be done.",
"iconUrl": "https://example.atlassian.net/secure/viewavatar?size=xsmall&avatarId=10418&avatarType=issuetype",
"name": "Task",
"subtask": false,
"avatarId": 10418
},
"timespent": null,
"project": {
"self": "https://example.atlassian.net/rest/api/2/project/10302",
"id": "10302",
"key": "AR",
"name": "Team Argon",
"avatarUrls": {
"48x48": "https://example.atlassian.net/secure/projectavatar?pid=10302&avatarId=10610",
"24x24": "https://example.atlassian.net/secure/projectavatar?size=small&pid=10302&avatarId=10610",
"16x16": "https://example.atlassian.net/secure/projectavatar?size=xsmall&pid=10302&avatarId=10610",
"32x32": "https://example.atlassian.net/secure/projectavatar?size=medium&pid=10302&avatarId=10610"
}
},
"fixVersions": [],
"customfield_11200": "0|0zzzzd:vi",
"aggregatetimespent": null,
"resolution": {
"self": "https://example.atlassian.net/rest/api/2/resolution/6",
"id": "6",
"description": "",
"name": "Done"
},
"customfield_11401": null,
"customfield_11400": null,
"customfield_10105": 13.0,
"customfield_10700": "AR-37",
"resolutiondate": "2015-12-07T14:19:13.000-0800",
"workratio": -1,
"lastViewed": null,
"watches": {
"self": "https://example.atlassian.net/rest/api/2/issue/AR-86/watchers",
"watchCount": 2,
"isWatching": true
},
"created": "2015-12-02T07:39:15.000-0800",
"epic": {
"id": 11900,
"key": "AR-37",
"self": "https://example.atlassian.net/rest/agile/1.0/epic/11900",
"name": "Moderation: Design",
"summary": "Moderation design",
"color": {
"key": "color_8"
},
"done": true
},
"priority": {
"self": "https://example.atlassian.net/rest/api/2/priority/3",
"iconUrl": "https://example.atlassian.net/images/icons/priorities/major.svg",
"name": "Major",
"id": "3"
},
"customfield_10102": null,
"customfield_10103": null,
"labels": [],
"customfield_11700": null,
"timeestimate": null,
"aggregatetimeoriginalestimate": null,
"versions": [],
"issuelinks": [],
"assignee": {
"self": "https://example.atlassian.net/rest/api/2/user?username=mister.morris",
"name": "mister.morris",
"key": "mister.morris",
"emailAddress": "[email protected]",
"avatarUrls": {
"48x48": "https://example.atlassian.net/secure/useravatar?ownerId=mister.morris&avatarId=10604",
"24x24": "https://example.atlassian.net/secure/useravatar?size=small&ownerId=mister.morris&avatarId=10604",
"16x16": "https://example.atlassian.net/secure/useravatar?size=xsmall&ownerId=mister.morris&avatarId=10604",
"32x32": "https://example.atlassian.net/secure/useravatar?size=medium&ownerId=mister.morris&avatarId=10604"
},
"displayName": "mister Morris",
"active": true,
"timeZone": "America/New_York"
},
"updated": "2016-02-01T08:17:04.000-0800",
"status": {
"self": "https://example.atlassian.net/rest/api/2/status/10000",
"description": "Ready to move to dev team for grooming",
"iconUrl": "https://example.atlassian.net/images/icons/statuses/closed.png",
"name": "Ready",
"id": "10000",
"statusCategory": {
"self": "https://example.atlassian.net/rest/api/2/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "To Do"
}
}
}
}
]
}