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

feat: add UpdateIssueWithOptions #658

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
2 changes: 1 addition & 1 deletion cloud/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Filter struct {

// GetMyFiltersQueryOptions specifies the optional parameters for the Get My Filters method
type GetMyFiltersQueryOptions struct {
IncludeFavourites bool `url:"includeFavourites,omitempty"`
IncludeFavourites *bool `url:"includeFavourites,omitempty"`
Expand string `url:"expand,omitempty"`
}

Expand Down
34 changes: 25 additions & 9 deletions cloud/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ type IssueService service

// UpdateQueryOptions specifies the optional parameters to the Edit issue
type UpdateQueryOptions struct {
NotifyUsers bool `url:"notifyUsers,omitempty"`
OverrideScreenSecurity bool `url:"overrideScreenSecurity,omitempty"`
OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"`
NotifyUsers *bool `url:"notifyUsers,omitempty"`
OverrideScreenSecurity *bool `url:"overrideScreenSecurity,omitempty"`
OverrideEditableFlag *bool `url:"overrideEditableFlag,omitempty"`
}

// Issue represents a Jira issue.
Expand Down Expand Up @@ -545,8 +545,8 @@ type GetQueryOptions struct {
// Properties is the list of properties to return for the issue. By default no properties are returned.
Properties string `url:"properties,omitempty"`
// FieldsByKeys if true then fields in issues will be referenced by keys instead of ids
FieldsByKeys bool `url:"fieldsByKeys,omitempty"`
UpdateHistory bool `url:"updateHistory,omitempty"`
FieldsByKeys *bool `url:"fieldsByKeys,omitempty"`
UpdateHistory *bool `url:"updateHistory,omitempty"`
ProjectKeys string `url:"projectKeys,omitempty"`
}

Expand All @@ -559,12 +559,12 @@ type GetWorklogsQueryOptions struct {
}

type AddWorklogQueryOptions struct {
NotifyUsers bool `url:"notifyUsers,omitempty"`
NotifyUsers *bool `url:"notifyUsers",omitempty`
AdjustEstimate string `url:"adjustEstimate,omitempty"`
NewEstimate string `url:"newEstimate,omitempty"`
ReduceBy string `url:"reduceBy,omitempty"`
Expand string `url:"expand,omitempty"`
OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"`
OverrideEditableFlag *bool `url:"overrideEditableFlag,omitempty"`
}

// CustomFields represents custom fields of Jira
Expand Down Expand Up @@ -868,8 +868,24 @@ func (s *IssueService) Update(ctx context.Context, issue *Issue, opts *UpdateQue
// TODO Double check this method if this works as expected, is using the latest API and the response is complete
// This double check effort is done for v2 - Remove this two lines if this is completed.
func (s *IssueService) UpdateIssue(ctx context.Context, jiraID string, data map[string]interface{}) (*Response, error) {
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", jiraID)
req, err := s.client.NewRequest(ctx, http.MethodPut, apiEndpoint, data)
return s.UpdateIssueWithOptions(ctx, jiraID, data, &UpdateQueryOptions{})
}

// UpdateIssueWithOptions updates an issue from a JSON patch,
// while also specifying query params. The issue is found by key.
//
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issues/#api-rest-api-2-issue-issueidorkey-put
// Caller must close resp.Body
//
// TODO Double check this method if this works as expected, is using the latest API and the response is complete
// This double check effort is done for v2 - Remove this two lines if this is completed.
func (s *IssueService) UpdateIssueWithOptions(ctx context.Context, jiraID string, data map[string]interface{}, opts *UpdateQueryOptions) (*Response, error) {
a := fmt.Sprintf("rest/api/2/issue/%v", jiraID)
url, err := addOptions(a, opts)
if err != nil {
return nil, err
}
req, err := s.client.NewRequest(ctx, http.MethodPut, url, data)
if err != nil {
return nil, err
}
Expand Down
25 changes: 25 additions & 0 deletions cloud/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,31 @@ func TestIssueService_UpdateIssue(t *testing.T) {

}

func TestIssueService_UpdateIssueWithOptions(t *testing.T) {
setup()
defer teardown()
testMux.HandleFunc("/rest/api/2/issue/PROJ-9001", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodPut)
testRequestURL(t, r, "/rest/api/2/issue/PROJ-9001")
testRequestParams(t, r, map[string]string{"notifyUsers": "true"})

w.WriteHeader(http.StatusNoContent)
})
jID := "PROJ-9001"
i := make(map[string]interface{})
fields := make(map[string]interface{})
i["fields"] = fields

resp, err := testClient.Issue.client.Issue.UpdateIssueWithOptions(context.Background(), jID, i, &UpdateQueryOptions{NotifyUsers: Bool(true)})
if resp == nil {
t.Error("Expected resp. resp is nil")
}
if err != nil {
t.Errorf("Error given: %s", err)
}

}

func TestIssueService_AddComment(t *testing.T) {
setup()
defer teardown()
Expand Down
13 changes: 13 additions & 0 deletions cloud/jira_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ func testRequestParams(t *testing.T, r *http.Request, want map[string]string) {

}

func Test_addOptions(t *testing.T) {
v, err := addOptions("rest/api/2/issue/123", &UpdateQueryOptions{NotifyUsers: Bool(false)})
if err != nil {
t.Errorf("Expected no error. Got: %+v", err)
}

expectedOutput := "rest/api/2/issue/123?notifyUsers=false"
if v != expectedOutput {
t.Errorf("Expected: %+v, got: %+v", expectedOutput, v)
}

}

func TestNewClient_WrongUrl(t *testing.T) {
c, err := NewClient("://issues.apache.org/jira/", nil)

Expand Down
2 changes: 1 addition & 1 deletion onpremise/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Filter struct {

// GetMyFiltersQueryOptions specifies the optional parameters for the Get My Filters method
type GetMyFiltersQueryOptions struct {
IncludeFavourites bool `url:"includeFavourites,omitempty"`
IncludeFavourites *bool `url:"includeFavourites,omitempty"`
Expand string `url:"expand,omitempty"`
}

Expand Down
14 changes: 7 additions & 7 deletions onpremise/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ type IssueService service

// UpdateQueryOptions specifies the optional parameters to the Edit issue
type UpdateQueryOptions struct {
NotifyUsers bool `url:"notifyUsers,omitempty"`
OverrideScreenSecurity bool `url:"overrideScreenSecurity,omitempty"`
OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"`
NotifyUsers *bool `url:"notifyUsers,omitempty"`
OverrideScreenSecurity *bool `url:"overrideScreenSecurity,omitempty"`
OverrideEditableFlag *bool `url:"overrideEditableFlag,omitempty"`
}

// Issue represents a Jira issue.
Expand Down Expand Up @@ -544,8 +544,8 @@ type GetQueryOptions struct {
// Properties is the list of properties to return for the issue. By default no properties are returned.
Properties string `url:"properties,omitempty"`
// FieldsByKeys if true then fields in issues will be referenced by keys instead of ids
FieldsByKeys bool `url:"fieldsByKeys,omitempty"`
UpdateHistory bool `url:"updateHistory,omitempty"`
FieldsByKeys *bool `url:"fieldsByKeys,omitempty"`
UpdateHistory *bool `url:"updateHistory,omitempty"`
ProjectKeys string `url:"projectKeys,omitempty"`
}

Expand All @@ -558,12 +558,12 @@ type GetWorklogsQueryOptions struct {
}

type AddWorklogQueryOptions struct {
NotifyUsers bool `url:"notifyUsers,omitempty"`
NotifyUsers *bool `url:"notifyUsers,omitempty"`
AdjustEstimate string `url:"adjustEstimate,omitempty"`
NewEstimate string `url:"newEstimate,omitempty"`
ReduceBy string `url:"reduceBy,omitempty"`
Expand string `url:"expand,omitempty"`
OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"`
OverrideEditableFlag *bool `url:"overrideEditableFlag,omitempty"`
}

// CustomFields represents custom fields of Jira
Expand Down
54 changes: 54 additions & 0 deletions onpremise/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,60 @@ func TestIssueService_Update(t *testing.T) {
}
}

func TestIssueService_Update_with_false_opts(t *testing.T) {
setup()
defer teardown()
testMux.HandleFunc("/rest/api/2/issue/PROJ-9001", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodPut)
testRequestURL(t, r, "/rest/api/2/issue/PROJ-9001")
testRequestParams(t, r, map[string]string{"notifyUsers": "false"})
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails without the omitEmpty changes


w.WriteHeader(http.StatusNoContent)
})

i := &Issue{
Key: "PROJ-9001",
Fields: &IssueFields{
Description: "example bug report",
},
}
issue, _, err := testClient.Issue.Update(context.Background(), i, &UpdateQueryOptions{NotifyUsers: Bool(false)})
if issue == nil {
t.Error("Expected issue. Issue is nil")
}
if err != nil {
t.Errorf("Error given: %s", err)
}

}

func TestIssueService_Update_with_multiple_opts(t *testing.T) {
setup()
defer teardown()
testMux.HandleFunc("/rest/api/2/issue/PROJ-9001", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodPut)
testRequestURL(t, r, "/rest/api/2/issue/PROJ-9001")
testRequestParams(t, r, map[string]string{"notifyUsers": "false", "overrideScreenSecurity": "true"})

w.WriteHeader(http.StatusNoContent)
})

i := &Issue{
Key: "PROJ-9001",
Fields: &IssueFields{
Description: "example bug report",
},
}
issue, _, err := testClient.Issue.Update(context.Background(), i, &UpdateQueryOptions{NotifyUsers: Bool(false), OverrideScreenSecurity: Bool(true)})
if issue == nil {
t.Error("Expected issue. Issue is nil")
}
if err != nil {
t.Errorf("Error given: %s", err)
}

}

func TestIssueService_UpdateIssue(t *testing.T) {
setup()
defer teardown()
Expand Down