package jira import ( "encoding/json" "fmt" "io/ioutil" "net/http" "reflect" "strings" "testing" "github.com/trivago/tgo/tcontainer" ) func TestIssueService_Get_Success(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10002", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/issue/10002") fmt.Fprint(w, `{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://www.example.com/jira/rest/api/2/issue/10002","key":"EX-1","fields":{"watcher":{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]},"attachment":[{"self":"http://www.example.com/jira/rest/api/2.0/attachments/10000","filename":"picture.jpg","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred","24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred","32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.461+0000","size":23123,"mimeType":"image/jpeg","content":"http://www.example.com/jira/attachments/10000","thumbnail":"http://www.example.com/jira/secure/thumbnail/10000"}],"sub-tasks":[{"id":"10000","type":{"id":"10000","name":"","inward":"Parent","outward":"Sub-task"},"outwardIssue":{"id":"10003","key":"EX-2","self":"http://www.example.com/jira/rest/api/2/issue/EX-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"description":"example bug report","project":{"self":"http://www.example.com/jira/rest/api/2/project/EX","id":"10000","key":"EX","name":"Example","avatarUrls":{"48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000","24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000","16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000","32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"},"projectCategory":{"self":"http://www.example.com/jira/rest/api/2/projectCategory/10000","id":"10000","name":"FIRST","description":"First Project Category"}},"comment":{"comments":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}]},"issuelinks":[{"id":"10001","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"outwardIssue":{"id":"10004L","key":"PRJ-2","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}},{"id":"10002","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"inwardIssue":{"id":"10004","key":"PRJ-3","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"worklog":{"worklogs":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"comment":"I did some work here.","updated":"2016-03-16T04:22:37.471+0000","visibility":{"type":"group","value":"jira-developers"},"started":"2016-03-16T04:22:37.471+0000","timeSpent":"3h 20m","timeSpentSeconds":12000,"id":"100028","issueId":"10002"}]},"updated":"2016-04-06T02:36:53.594-0700","timetracking":{"originalEstimate":"10m","remainingEstimate":"3m","timeSpent":"6m","originalEstimateSeconds":600,"remainingEstimateSeconds":200,"timeSpentSeconds":400}},"names":{"watcher":"watcher","attachment":"attachment","sub-tasks":"sub-tasks","description":"description","project":"project","comment":"comment","issuelinks":"issuelinks","worklog":"worklog","updated":"updated","timetracking":"timetracking"},"schema":{}}`) }) issue, _, err := testClient.Issue.Get("10002", nil) if issue == nil { t.Error("Expected issue. Issue is nil") } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_Get_WithQuerySuccess(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10002", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/issue/10002?expand=foo") fmt.Fprint(w, `{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://www.example.com/jira/rest/api/2/issue/10002","key":"EX-1","fields":{"watcher":{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]},"attachment":[{"self":"http://www.example.com/jira/rest/api/2.0/attachments/10000","filename":"picture.jpg","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred","24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred","32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.461+0000","size":23123,"mimeType":"image/jpeg","content":"http://www.example.com/jira/attachments/10000","thumbnail":"http://www.example.com/jira/secure/thumbnail/10000"}],"sub-tasks":[{"id":"10000","type":{"id":"10000","name":"","inward":"Parent","outward":"Sub-task"},"outwardIssue":{"id":"10003","key":"EX-2","self":"http://www.example.com/jira/rest/api/2/issue/EX-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"description":"example bug report","project":{"self":"http://www.example.com/jira/rest/api/2/project/EX","id":"10000","key":"EX","name":"Example","avatarUrls":{"48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000","24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000","16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000","32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"},"projectCategory":{"self":"http://www.example.com/jira/rest/api/2/projectCategory/10000","id":"10000","name":"FIRST","description":"First Project Category"}},"comment":{"comments":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}]},"issuelinks":[{"id":"10001","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"outwardIssue":{"id":"10004L","key":"PRJ-2","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}},{"id":"10002","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"inwardIssue":{"id":"10004","key":"PRJ-3","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"worklog":{"worklogs":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"comment":"I did some work here.","updated":"2016-03-16T04:22:37.471+0000","visibility":{"type":"group","value":"jira-developers"},"started":"2016-03-16T04:22:37.471+0000","timeSpent":"3h 20m","timeSpentSeconds":12000,"id":"100028","issueId":"10002"}]},"updated":"2016-04-06T02:36:53.594-0700","timetracking":{"originalEstimate":"10m","remainingEstimate":"3m","timeSpent":"6m","originalEstimateSeconds":600,"remainingEstimateSeconds":200,"timeSpentSeconds":400}},"names":{"watcher":"watcher","attachment":"attachment","sub-tasks":"sub-tasks","description":"description","project":"project","comment":"comment","issuelinks":"issuelinks","worklog":"worklog","updated":"updated","timetracking":"timetracking"},"schema":{}}`) }) opt := &GetQueryOptions{ Expand: "foo", } issue, _, err := testClient.Issue.Get("10002", opt) if issue == nil { t.Error("Expected issue. Issue is nil") } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_Create(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issue/") w.WriteHeader(http.StatusCreated) fmt.Fprint(w, `{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://www.example.com/jira/rest/api/2/issue/10002","key":"EX-1","fields":{"watcher":{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]},"attachment":[{"self":"http://www.example.com/jira/rest/api/2.0/attachments/10000","filename":"picture.jpg","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred","24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred","32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.461+0000","size":23123,"mimeType":"image/jpeg","content":"http://www.example.com/jira/attachments/10000","thumbnail":"http://www.example.com/jira/secure/thumbnail/10000"}],"sub-tasks":[{"id":"10000","type":{"id":"10000","name":"","inward":"Parent","outward":"Sub-task"},"outwardIssue":{"id":"10003","key":"EX-2","self":"http://www.example.com/jira/rest/api/2/issue/EX-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"description":"example bug report","project":{"self":"http://www.example.com/jira/rest/api/2/project/EX","id":"10000","key":"EX","name":"Example","avatarUrls":{"48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000","24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000","16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000","32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"},"projectCategory":{"self":"http://www.example.com/jira/rest/api/2/projectCategory/10000","id":"10000","name":"FIRST","description":"First Project Category"}},"comment":{"comments":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}]},"issuelinks":[{"id":"10001","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"outwardIssue":{"id":"10004L","key":"PRJ-2","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}},{"id":"10002","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"inwardIssue":{"id":"10004","key":"PRJ-3","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"worklog":{"worklogs":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"comment":"I did some work here.","updated":"2016-03-16T04:22:37.471+0000","visibility":{"type":"group","value":"jira-developers"},"started":"2016-03-16T04:22:37.471+0000","timeSpent":"3h 20m","timeSpentSeconds":12000,"id":"100028","issueId":"10002"}]},"updated":"2016-04-06T02:36:53.594-0700","timetracking":{"originalEstimate":"10m","remainingEstimate":"3m","timeSpent":"6m","originalEstimateSeconds":600,"remainingEstimateSeconds":200,"timeSpentSeconds":400}},"names":{"watcher":"watcher","attachment":"attachment","sub-tasks":"sub-tasks","description":"description","project":"project","comment":"comment","issuelinks":"issuelinks","worklog":"worklog","updated":"updated","timetracking":"timetracking"},"schema":{}}`) }) i := &Issue{ Fields: &IssueFields{ Description: "example bug report", }, } issue, _, err := testClient.Issue.Create(i) if issue == nil { t.Error("Expected issue. Issue is nil") } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_AddComment(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10000/comment", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issue/10000/comment") w.WriteHeader(http.StatusCreated) fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}`) }) c := &Comment{ Body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.", Visibility: CommentVisibility{ Type: "role", Value: "Administrators", }, } comment, _, err := testClient.Issue.AddComment("10000", c) if comment == nil { t.Error("Expected Comment. Comment is nil") } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_AddLink(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issueLink", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issueLink") w.WriteHeader(http.StatusOK) }) il := &IssueLink{ Type: IssueLinkType{ Name: "Duplicate", }, InwardIssue: &Issue{ Key: "HSP-1", }, OutwardIssue: &Issue{ Key: "MKY-1", }, Comment: &Comment{ Body: "Linked related issue!", Visibility: CommentVisibility{ Type: "group", Value: "jira-software-users", }, }, } resp, err := testClient.Issue.AddLink(il) if resp == nil { t.Error("Expected response. Response is nil") } if resp.StatusCode != 200 { t.Errorf("Expected Status code 200. Given %d", resp.StatusCode) } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_Get_Fields(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10002", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/issue/10002") fmt.Fprint(w, `{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://www.example.com/jira/rest/api/2/issue/10002","key":"EX-1","fields":{"labels":["test"],"watcher":{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]},"epic": {"id": 19415,"key": "EPIC-77","self": "https://example.atlassian.net/rest/agile/1.0/epic/19415","name": "Epic Name","summary": "Do it","color": {"key": "color_11"},"done": false},"attachment":[{"self":"http://www.example.com/jira/rest/api/2.0/attachments/10000","filename":"picture.jpg","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred","24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred","32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.461+0000","size":23123,"mimeType":"image/jpeg","content":"http://www.example.com/jira/attachments/10000","thumbnail":"http://www.example.com/jira/secure/thumbnail/10000"}],"sub-tasks":[{"id":"10000","type":{"id":"10000","name":"","inward":"Parent","outward":"Sub-task"},"outwardIssue":{"id":"10003","key":"EX-2","self":"http://www.example.com/jira/rest/api/2/issue/EX-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"description":"example bug report","project":{"self":"http://www.example.com/jira/rest/api/2/project/EX","id":"10000","key":"EX","name":"Example","avatarUrls":{"48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000","24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000","16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000","32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"},"projectCategory":{"self":"http://www.example.com/jira/rest/api/2/projectCategory/10000","id":"10000","name":"FIRST","description":"First Project Category"}},"comment":{"comments":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}]},"issuelinks":[{"id":"10001","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"outwardIssue":{"id":"10004L","key":"PRJ-2","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}},{"id":"10002","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"inwardIssue":{"id":"10004","key":"PRJ-3","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"worklog":{"worklogs":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"comment":"I did some work here.","updated":"2016-03-16T04:22:37.471+0000","visibility":{"type":"group","value":"jira-developers"},"started":"2016-03-16T04:22:37.471+0000","timeSpent":"3h 20m","timeSpentSeconds":12000,"id":"100028","issueId":"10002"}]},"updated":"2016-04-06T02:36:53.594-0700","timetracking":{"originalEstimate":"10m","remainingEstimate":"3m","timeSpent":"6m","originalEstimateSeconds":600,"remainingEstimateSeconds":200,"timeSpentSeconds":400}},"names":{"watcher":"watcher","attachment":"attachment","sub-tasks":"sub-tasks","description":"description","project":"project","comment":"comment","issuelinks":"issuelinks","worklog":"worklog","updated":"updated","timetracking":"timetracking"},"schema":{}}`) }) issue, _, err := testClient.Issue.Get("10002", nil) if issue == nil { t.Error("Expected issue. Issue is nil") } if !reflect.DeepEqual(issue.Fields.Labels, []string{"test"}) { t.Error("Expected labels for the returned issue") } if len(issue.Fields.Comments.Comments) != 1 { t.Errorf("Expected one comment, %v found", len(issue.Fields.Comments.Comments)) } if issue.Fields.Epic == nil { t.Error("Epic expected but not found") } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_DownloadAttachment(t *testing.T) { var testAttachment = "Here is an attachment" setup() defer teardown() testMux.HandleFunc("/secure/attachment/", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/secure/attachment/10000/") w.WriteHeader(http.StatusOK) w.Write([]byte(testAttachment)) }) resp, err := testClient.Issue.DownloadAttachment("10000") if resp == nil { t.Error("Expected response. Response is nil") } defer resp.Body.Close() attachment, err := ioutil.ReadAll(resp.Body) if err != nil { t.Error("Expected attachment text", err) } if string(attachment) != testAttachment { t.Errorf("Expecting an attachment: %s", string(attachment)) } if resp.StatusCode != 200 { t.Errorf("Expected Status code 200. Given %d", resp.StatusCode) } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_DownloadAttachment_BadStatus(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/secure/attachment/", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/secure/attachment/10000/") w.WriteHeader(http.StatusForbidden) }) resp, err := testClient.Issue.DownloadAttachment("10000") if resp == nil { t.Error("Expected response. Response is nil") } defer resp.Body.Close() if resp.StatusCode != http.StatusForbidden { t.Errorf("Expected Status code %d. Given %d", http.StatusForbidden, resp.StatusCode) } if err == nil { t.Errorf("Error expected") } } func TestIssueService_PostAttachment(t *testing.T) { var testAttachment = "Here is an attachment" setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issue/10000/attachments") status := http.StatusOK file, _, err := r.FormFile("file") if err != nil { status = http.StatusNotAcceptable } if file == nil { status = http.StatusNoContent } else { // Read the file into memory data, err := ioutil.ReadAll(file) if err != nil { status = http.StatusInternalServerError } if string(data) != testAttachment { status = http.StatusNotAcceptable } w.WriteHeader(status) fmt.Fprint(w, `[{"self":"http://jira/jira/rest/api/2/attachment/228924","id":"228924","filename":"example.jpg","author":{"self":"http://jira/jira/rest/api/2/user?username=test","name":"test","emailAddress":"test@test.com","avatarUrls":{"16x16":"http://jira/jira/secure/useravatar?size=small&avatarId=10082","48x48":"http://jira/jira/secure/useravatar?avatarId=10082"},"displayName":"Tester","active":true},"created":"2016-05-24T00:25:17.000-0700","size":32280,"mimeType":"image/jpeg","content":"http://jira/jira/secure/attachment/228924/example.jpg","thumbnail":"http://jira/jira/secure/thumbnail/228924/_thumb_228924.png"}]`) file.Close() } }) reader := strings.NewReader(testAttachment) issue, resp, err := testClient.Issue.PostAttachment("10000", reader, "attachment") if issue == nil { t.Error("Expected response. Response is nil") } if resp.StatusCode != 200 { t.Errorf("Expected Status code 200. Given %d", resp.StatusCode) } if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_PostAttachment_NoResponse(t *testing.T) { var testAttachment = "Here is an attachment" setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issue/10000/attachments") w.WriteHeader(http.StatusOK) }) reader := strings.NewReader(testAttachment) _, _, err := testClient.Issue.PostAttachment("10000", reader, "attachment") if err == nil { t.Errorf("Error expected: %s", err) } } func TestIssueService_PostAttachment_NoFilename(t *testing.T) { var testAttachment = "Here is an attachment" setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issue/10000/attachments") w.WriteHeader(http.StatusOK) fmt.Fprint(w, `[{"self":"http://jira/jira/rest/api/2/attachment/228924","id":"228924","filename":"example.jpg","author":{"self":"http://jira/jira/rest/api/2/user?username=test","name":"test","emailAddress":"test@test.com","avatarUrls":{"16x16":"http://jira/jira/secure/useravatar?size=small&avatarId=10082","48x48":"http://jira/jira/secure/useravatar?avatarId=10082"},"displayName":"Tester","active":true},"created":"2016-05-24T00:25:17.000-0700","size":32280,"mimeType":"image/jpeg","content":"http://jira/jira/secure/attachment/228924/example.jpg","thumbnail":"http://jira/jira/secure/thumbnail/228924/_thumb_228924.png"}]`) }) reader := strings.NewReader(testAttachment) _, _, err := testClient.Issue.PostAttachment("10000", reader, "") if err != nil { t.Errorf("Error expected: %s", err) } } func TestIssueService_PostAttachment_NoAttachment(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, "/rest/api/2/issue/10000/attachments") w.WriteHeader(http.StatusOK) fmt.Fprint(w, `[{"self":"http://jira/jira/rest/api/2/attachment/228924","id":"228924","filename":"example.jpg","author":{"self":"http://jira/jira/rest/api/2/user?username=test","name":"test","emailAddress":"test@test.com","avatarUrls":{"16x16":"http://jira/jira/secure/useravatar?size=small&avatarId=10082","48x48":"http://jira/jira/secure/useravatar?avatarId=10082"},"displayName":"Tester","active":true},"created":"2016-05-24T00:25:17.000-0700","size":32280,"mimeType":"image/jpeg","content":"http://jira/jira/secure/attachment/228924/example.jpg","thumbnail":"http://jira/jira/secure/thumbnail/228924/_thumb_228924.png"}]`) }) _, _, err := testClient.Issue.PostAttachment("10000", nil, "attachment") if err != nil { t.Errorf("Error given: %s", err) } } func TestIssueService_Search(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/search", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/search?jql=something&startAt=1&maxResults=40&expand=foo") w.WriteHeader(http.StatusOK) fmt.Fprint(w, `{"expand": "schema,names","startAt": 1,"maxResults": 40,"total": 6,"issues": [{"expand": "html","id": "10230","self": "http://kelpie9:8081/rest/api/2/issue/BULK-62","key": "BULK-62","fields": {"summary": "testing","timetracking": null,"issuetype": {"self": "http://kelpie9:8081/rest/api/2/issuetype/5","id": "5","description": "The sub-task of the issue","iconUrl": "http://kelpie9:8081/images/icons/issue_subtask.gif","name": "Sub-task","subtask": true},"customfield_10071": null}},{"expand": "html","id": "10004","self": "http://kelpie9:8081/rest/api/2/issue/BULK-47","key": "BULK-47","fields": {"summary": "Cheese v1 2.0 issue","timetracking": null,"issuetype": {"self": "http://kelpie9:8081/rest/api/2/issuetype/3","id": "3","description": "A task that needs to be done.","iconUrl": "http://kelpie9:8081/images/icons/task.gif","name": "Task","subtask": false}}}]}`) }) opt := &SearchOptions{StartAt: 1, MaxResults: 40, Expand: "foo"} _, resp, err := testClient.Issue.Search("something", opt) if resp == nil { t.Errorf("Response given: %+v", resp) } if err != nil { t.Errorf("Error given: %s", err) } if resp.StartAt != 1 { t.Errorf("StartAt should populate with 1, %v given", resp.StartAt) } if resp.MaxResults != 40 { t.Errorf("StartAt should populate with 40, %v given", resp.MaxResults) } if resp.Total != 6 { t.Errorf("StartAt should populate with 6, %v given", resp.Total) } } func TestIssueService_Search_WithoutPaging(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/search", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/search?jql=something") w.WriteHeader(http.StatusOK) fmt.Fprint(w, `{"expand": "schema,names","startAt": 0,"maxResults": 50,"total": 6,"issues": [{"expand": "html","id": "10230","self": "http://kelpie9:8081/rest/api/2/issue/BULK-62","key": "BULK-62","fields": {"summary": "testing","timetracking": null,"issuetype": {"self": "http://kelpie9:8081/rest/api/2/issuetype/5","id": "5","description": "The sub-task of the issue","iconUrl": "http://kelpie9:8081/images/icons/issue_subtask.gif","name": "Sub-task","subtask": true},"customfield_10071": null}},{"expand": "html","id": "10004","self": "http://kelpie9:8081/rest/api/2/issue/BULK-47","key": "BULK-47","fields": {"summary": "Cheese v1 2.0 issue","timetracking": null,"issuetype": {"self": "http://kelpie9:8081/rest/api/2/issuetype/3","id": "3","description": "A task that needs to be done.","iconUrl": "http://kelpie9:8081/images/icons/task.gif","name": "Task","subtask": false}}}]}`) }) _, resp, err := testClient.Issue.Search("something", nil) if resp == nil { t.Errorf("Response given: %+v", resp) } if err != nil { t.Errorf("Error given: %s", err) } if resp.StartAt != 0 { t.Errorf("StartAt should populate with 0, %v given", resp.StartAt) } if resp.MaxResults != 50 { t.Errorf("StartAt should populate with 50, %v given", resp.MaxResults) } if resp.Total != 6 { t.Errorf("StartAt should populate with 6, %v given", resp.Total) } } func TestIssueService_GetCustomFields(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10002", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/issue/10002") fmt.Fprint(w, `{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://www.example.com/jira/rest/api/2/issue/10002","key":"EX-1","fields":{"customfield_123":"test","watcher":{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]},"attachment":[{"self":"http://www.example.com/jira/rest/api/2.0/attachments/10000","filename":"picture.jpg","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred","24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred","32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.461+0000","size":23123,"mimeType":"image/jpeg","content":"http://www.example.com/jira/attachments/10000","thumbnail":"http://www.example.com/jira/secure/thumbnail/10000"}],"sub-tasks":[{"id":"10000","type":{"id":"10000","name":"","inward":"Parent","outward":"Sub-task"},"outwardIssue":{"id":"10003","key":"EX-2","self":"http://www.example.com/jira/rest/api/2/issue/EX-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"description":"example bug report","project":{"self":"http://www.example.com/jira/rest/api/2/project/EX","id":"10000","key":"EX","name":"Example","avatarUrls":{"48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000","24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000","16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000","32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"},"projectCategory":{"self":"http://www.example.com/jira/rest/api/2/projectCategory/10000","id":"10000","name":"FIRST","description":"First Project Category"}},"comment":{"comments":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}]},"issuelinks":[{"id":"10001","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"outwardIssue":{"id":"10004L","key":"PRJ-2","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}},{"id":"10002","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"inwardIssue":{"id":"10004","key":"PRJ-3","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"worklog":{"worklogs":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"comment":"I did some work here.","updated":"2016-03-16T04:22:37.471+0000","visibility":{"type":"group","value":"jira-developers"},"started":"2016-03-16T04:22:37.471+0000","timeSpent":"3h 20m","timeSpentSeconds":12000,"id":"100028","issueId":"10002"}]},"updated":"2016-04-06T02:36:53.594-0700","timetracking":{"originalEstimate":"10m","remainingEstimate":"3m","timeSpent":"6m","originalEstimateSeconds":600,"remainingEstimateSeconds":200,"timeSpentSeconds":400}},"names":{"watcher":"watcher","attachment":"attachment","sub-tasks":"sub-tasks","description":"description","project":"project","comment":"comment","issuelinks":"issuelinks","worklog":"worklog","updated":"updated","timetracking":"timetracking"},"schema":{}}`) }) issue, _, err := testClient.Issue.GetCustomFields("10002") if err != nil { t.Errorf("Error given: %s", err) } if issue == nil { t.Error("Expected Customfields") } cf := issue["customfield_123"] if cf != "test" { t.Error("Expected \"test\" for custom field") } } func TestIssueService_GetComplexCustomFields(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10002", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, "/rest/api/2/issue/10002") fmt.Fprint(w, `{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,versionedRepresentations","id":"10002","self":"http://www.example.com/jira/rest/api/2/issue/10002","key":"EX-1","fields":{"customfield_123":{"self":"http://www.example.com/jira/rest/api/2/customFieldOption/123","value":"test","id":"123"},"watcher":{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]},"attachment":[{"self":"http://www.example.com/jira/rest/api/2.0/attachments/10000","filename":"picture.jpg","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred","24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred","32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.461+0000","size":23123,"mimeType":"image/jpeg","content":"http://www.example.com/jira/attachments/10000","thumbnail":"http://www.example.com/jira/secure/thumbnail/10000"}],"sub-tasks":[{"id":"10000","type":{"id":"10000","name":"","inward":"Parent","outward":"Sub-task"},"outwardIssue":{"id":"10003","key":"EX-2","self":"http://www.example.com/jira/rest/api/2/issue/EX-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"description":"example bug report","project":{"self":"http://www.example.com/jira/rest/api/2/project/EX","id":"10000","key":"EX","name":"Example","avatarUrls":{"48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000","24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000","16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000","32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000"},"projectCategory":{"self":"http://www.example.com/jira/rest/api/2/projectCategory/10000","id":"10000","name":"FIRST","description":"First Project Category"}},"comment":{"comments":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/comment/10000","id":"10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"body":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.","updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"created":"2016-03-16T04:22:37.356+0000","updated":"2016-03-16T04:22:37.356+0000","visibility":{"type":"role","value":"Administrators"}}]},"issuelinks":[{"id":"10001","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"outwardIssue":{"id":"10004L","key":"PRJ-2","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}},{"id":"10002","type":{"id":"10000","name":"Dependent","inward":"depends on","outward":"is depended by"},"inwardIssue":{"id":"10004","key":"PRJ-3","self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3","fields":{"status":{"iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png","name":"Open"}}}}],"worklog":{"worklogs":[{"self":"http://www.example.com/jira/rest/api/2/issue/10010/worklog/10000","author":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"updateAuthor":{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false},"comment":"I did some work here.","updated":"2016-03-16T04:22:37.471+0000","visibility":{"type":"group","value":"jira-developers"},"started":"2016-03-16T04:22:37.471+0000","timeSpent":"3h 20m","timeSpentSeconds":12000,"id":"100028","issueId":"10002"}]},"updated":"2016-04-06T02:36:53.594-0700","timetracking":{"originalEstimate":"10m","remainingEstimate":"3m","timeSpent":"6m","originalEstimateSeconds":600,"remainingEstimateSeconds":200,"timeSpentSeconds":400}},"names":{"watcher":"watcher","attachment":"attachment","sub-tasks":"sub-tasks","description":"description","project":"project","comment":"comment","issuelinks":"issuelinks","worklog":"worklog","updated":"updated","timetracking":"timetracking"},"schema":{}}`) }) issue, _, err := testClient.Issue.GetCustomFields("10002") if err != nil { t.Errorf("Error given: %s", err) } if issue == nil { t.Error("Expected Customfields") } cf := issue["customfield_123"] if cf != "test" { t.Error("Expected \"test\" for custom field") } } func TestIssueService_GetTransitions(t *testing.T) { setup() defer teardown() testAPIEndpoint := "/rest/api/2/issue/123/transitions" raw, err := ioutil.ReadFile("./mocks/transitions.json") if err != nil { t.Error(err.Error()) } testMux.HandleFunc(testAPIEndpoint, func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testRequestURL(t, r, testAPIEndpoint) fmt.Fprint(w, string(raw)) }) transitions, _, err := testClient.Issue.GetTransitions("123") if err != nil { t.Errorf("Got error: %v", err) } if transitions == nil { t.Error("Expected transition list. Got nil.") } if len(transitions) != 2 { t.Errorf("Expected 2 transitions. Got %d", len(transitions)) } if transitions[0].Fields["summary"].Required != false { t.Errorf("First transition summary field should not be required") } } func TestIssueService_DoTransition(t *testing.T) { setup() defer teardown() testAPIEndpoint := "/rest/api/2/issue/123/transitions" transitionID := "22" testMux.HandleFunc(testAPIEndpoint, func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") testRequestURL(t, r, testAPIEndpoint) decoder := json.NewDecoder(r.Body) var payload CreateTransitionPayload err := decoder.Decode(&payload) if err != nil { t.Errorf("Got error: %v", err) } if payload.Transition.ID != transitionID { t.Errorf("Expected %s to be in payload, got %s instead", transitionID, payload.Transition.ID) } }) _, err := testClient.Issue.DoTransition("123", transitionID) if err != nil { t.Errorf("Got error: %v", err) } } func TestIssueFields_TestMarshalJSON_PopulateUnknownsSuccess(t *testing.T) { data := `{ "customfield_123":"test", "description":"example bug report", "project":{ "self":"http://www.example.com/jira/rest/api/2/project/EX", "id":"10000", "key":"EX", "name":"Example", "avatarUrls":{ "48x48":"http://www.example.com/jira/secure/projectavatar?size=large&pid=10000", "24x24":"http://www.example.com/jira/secure/projectavatar?size=small&pid=10000", "16x16":"http://www.example.com/jira/secure/projectavatar?size=xsmall&pid=10000", "32x32":"http://www.example.com/jira/secure/projectavatar?size=medium&pid=10000" }, "projectCategory":{ "self":"http://www.example.com/jira/rest/api/2/projectCategory/10000", "id":"10000", "name":"FIRST", "description":"First Project Category" } }, "issuelinks":[ { "id":"10001", "type":{ "id":"10000", "name":"Dependent", "inward":"depends on", "outward":"is depended by" }, "outwardIssue":{ "id":"10004L", "key":"PRJ-2", "self":"http://www.example.com/jira/rest/api/2/issue/PRJ-2", "fields":{ "status":{ "iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png", "name":"Open" } } } }, { "id":"10002", "type":{ "id":"10000", "name":"Dependent", "inward":"depends on", "outward":"is depended by" }, "inwardIssue":{ "id":"10004", "key":"PRJ-3", "self":"http://www.example.com/jira/rest/api/2/issue/PRJ-3", "fields":{ "status":{ "iconUrl":"http://www.example.com/jira//images/icons/statuses/open.png", "name":"Open" } } } } ] }` i := new(IssueFields) err := json.Unmarshal([]byte(data), i) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } if len(i.Unknowns) != 1 { t.Errorf("Expected 1 unknown field to be present, recieved %d", len(i.Unknowns)) } if i.Description != "example bug report" { t.Errorf("Expected description to be \"%s\", recieved \"%s\"", "example bug report", i.Description) } } func TestIssueFields_MarshalJSON_OmitsEmptyFields(t *testing.T) { i := &IssueFields{ Description: "blahblah", Type: IssueType{ Name: "Story", }, Labels: []string{"aws-docker"}, } rawdata, err := json.Marshal(i) if err != nil { t.Errorf("Expected nil err, recieved %s", err) } // convert json to map and see if unset keys are there issuef := tcontainer.NewMarshalMap() err = json.Unmarshal(rawdata, &issuef) if err != nil { t.Errorf("Expected nil err, received %s", err) } _, err = issuef.Int("issuetype/avatarId") if err == nil { t.Error("Expected non nil error, recieved nil") } // verify that the field that should be there, is. name, err := issuef.String("issuetype/name") if err != nil { t.Errorf("Expected nil err, received %s", err) } if name != "Story" { t.Errorf("Expected Story, received %s", name) } } func TestIssueFields_MarshalJSON_Success(t *testing.T) { i := &IssueFields{ Description: "example bug report", Unknowns: tcontainer.MarshalMap{ "customfield_123": "test", }, Project: Project{ Self: "http://www.example.com/jira/rest/api/2/project/EX", ID: "10000", Key: "EX", }, } bytes, err := json.Marshal(i) if err != nil { t.Errorf("Expected nil err, recieved %s", err) } recieved := new(IssueFields) // the order of json might be different. so unmarshal it again and comapre objects err = json.Unmarshal(bytes, recieved) if err != nil { t.Errorf("Expected nil err, recieved %s", err) } if !reflect.DeepEqual(i, recieved) { t.Errorf("Recieved object different from expected. Expected %+v, recieved %+v", i, recieved) } } func TestInitIssueWithMetaAndFields_Success(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["summary"] = map[string]interface{}{ "name": "Summary", "schema": map[string]interface{}{ "type": "string", }, } metaIssueType := MetaIssueType{ Fields: fields, } expectedSummary := "Issue Summary" fieldConfig := map[string]string{ "Summary": "Issue Summary", } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } gotSummary, found := issue.Fields.Unknowns["summary"] if !found { t.Errorf("Expected summary to be set in issue. Not set.") } if gotSummary != expectedSummary { t.Errorf("Expected %s recieved %s", expectedSummary, gotSummary) } } func TestInitIssueWithMetaAndFields_ArrayValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["component"] = map[string]interface{}{ "name": "Component/s", "schema": map[string]interface{}{ "type": "array", "items": "component", }, } metaIssueType := MetaIssueType{ Fields: fields, } expectedComponent := "Jira automation" fieldConfig := map[string]string{ "Component/s": expectedComponent, } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } c, isArray := issue.Fields.Unknowns["component"].([]Component) if isArray == false { t.Error("Expected array, non array object recieved") } if len(c) != 1 { t.Errorf("Expected recieved array to be of length 1. Got %d", len(c)) } gotComponent := c[0].Name if err != nil { t.Errorf("Expected err to be nil, recieved %s", err) } if gotComponent != expectedComponent { t.Errorf("Expected %s recieved %s", expectedComponent, gotComponent) } } func TestInitIssueWithMetaAndFields_DateValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["created"] = map[string]interface{}{ "name": "Created", "schema": map[string]interface{}{ "type": "date", }, } metaIssueType := MetaIssueType{ Fields: fields, } expectedCreated := "19 oct 2012" fieldConfig := map[string]string{ "Created": expectedCreated, } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } gotCreated, err := issue.Fields.Unknowns.String("created") if err != nil { t.Errorf("Expected err to be nil, recieved %s", err) } if gotCreated != expectedCreated { t.Errorf("Expected %s recieved %s", expectedCreated, gotCreated) } } func TestInitIssueWithMetaAndFields_UserValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["assignee"] = map[string]interface{}{ "name": "Assignee", "schema": map[string]interface{}{ "type": "user", }, } metaIssueType := MetaIssueType{ Fields: fields, } expectedAssignee := "jdoe" fieldConfig := map[string]string{ "Assignee": expectedAssignee, } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } a, _ := issue.Fields.Unknowns.Value("assignee") gotAssignee := a.(User).Name if gotAssignee != expectedAssignee { t.Errorf("Expected %s recieved %s", expectedAssignee, gotAssignee) } } func TestInitIssueWithMetaAndFields_ProjectValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["project"] = map[string]interface{}{ "name": "Project", "schema": map[string]interface{}{ "type": "project", }, } metaIssueType := MetaIssueType{ Fields: fields, } setProject := "somewhere" fieldConfig := map[string]string{ "Project": setProject, } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } a, _ := issue.Fields.Unknowns.Value("project") gotProject := a.(Project).Name if gotProject != metaProject.Name { t.Errorf("Expected %s recieved %s", metaProject.Name, gotProject) } } func TestInitIssueWithMetaAndFields_PriorityValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["priority"] = map[string]interface{}{ "name": "Priority", "schema": map[string]interface{}{ "type": "priority", }, } metaIssueType := MetaIssueType{ Fields: fields, } expectedPriority := "Normal" fieldConfig := map[string]string{ "Priority": expectedPriority, } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } a, _ := issue.Fields.Unknowns.Value("priority") gotPriority := a.(Priority).Name if gotPriority != expectedPriority { t.Errorf("Expected %s recieved %s", expectedPriority, gotPriority) } } func TestInitIssueWithMetaAndFields_IssuetypeValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["issuetype"] = map[string]interface{}{ "name": "Issue type", "schema": map[string]interface{}{ "type": "issuetype", }, } metaIssueType := MetaIssueType{ Fields: fields, } expectedIssuetype := "Bug" fieldConfig := map[string]string{ "Issue type": expectedIssuetype, } issue, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err != nil { t.Errorf("Expected nil error, recieved %s", err) } a, _ := issue.Fields.Unknowns.Value("issuetype") gotIssuetype := a.(IssueType).Name if gotIssuetype != expectedIssuetype { t.Errorf("Expected %s recieved %s", expectedIssuetype, gotIssuetype) } } func TestInitIssueWithmetaAndFields_FailureWithUnknownValueType(t *testing.T) { metaProject := MetaProject{ Name: "Engineering - Dept", Id: "ENG", } fields := tcontainer.NewMarshalMap() fields["issuetype"] = map[string]interface{}{ "name": "Issue type", "schema": map[string]interface{}{ "type": "randomType", }, } metaIssueType := MetaIssueType{ Fields: fields, } fieldConfig := map[string]string{ "Issue tyoe": "sometype", } _, err := InitIssueWithMetaAndFields(&metaProject, &metaIssueType, fieldConfig) if err == nil { t.Error("Expected non nil error, recieved nil") } } func TestIssueService_Delete(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/api/2/issue/10002", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") testRequestURL(t, r, "/rest/api/2/issue/10002") w.WriteHeader(http.StatusNoContent) fmt.Fprint(w, `{}`) }) resp, err := testClient.Issue.Delete("10002") if resp.StatusCode != 204 { t.Error("Expected issue not deleted.") } if err != nil { t.Errorf("Error given: %s", err) } }