mirror of
https://github.com/interviewstreet/go-jira.git
synced 2025-02-09 13:36:58 +02:00
Moved transition service into issue service, because it relates to the issue api calls
This commit is contained in:
parent
753367d382
commit
4b9e96b367
66
issue.go
66
issue.go
@ -181,6 +181,31 @@ type Progress struct {
|
|||||||
// Time represents the Time definition of JIRA as a time.Time of go
|
// Time represents the Time definition of JIRA as a time.Time of go
|
||||||
type Time time.Time
|
type Time time.Time
|
||||||
|
|
||||||
|
// Wrapper struct for search result
|
||||||
|
type transitionResult struct {
|
||||||
|
Transitions []Transition `json:transitions`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transition represents an issue transition in JIRA
|
||||||
|
type Transition struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Fields map[string]TransitionField `json:"fields"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransitionField struct {
|
||||||
|
Required bool `json:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePayload is used for creating new issue transitions
|
||||||
|
type CreateTransitionPayload struct {
|
||||||
|
Transition TransitionPayload `json:"transition"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransitionPayload struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON will transform the JIRA time into a time.Time
|
// UnmarshalJSON will transform the JIRA time into a time.Time
|
||||||
// during the transformation of the JIRA JSON response
|
// during the transformation of the JIRA JSON response
|
||||||
func (t *Time) UnmarshalJSON(b []byte) error {
|
func (t *Time) UnmarshalJSON(b []byte) error {
|
||||||
@ -492,3 +517,44 @@ func (s *IssueService) GetCustomFields(issueID string) (CustomFields, *Response,
|
|||||||
}
|
}
|
||||||
return cf, resp, nil
|
return cf, resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTransitions gets a list of the transitions possible for this issue by the current user,
|
||||||
|
// along with fields that are required and their types.
|
||||||
|
//
|
||||||
|
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getTransitions
|
||||||
|
func (s *IssueService) GetTransitions(id string) ([]Transition, *Response, error) {
|
||||||
|
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions?expand=transitions.fields", id)
|
||||||
|
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := new(transitionResult)
|
||||||
|
resp, err := s.client.Do(req, result)
|
||||||
|
return result.Transitions, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoTransition performs a transition on an issue.
|
||||||
|
// When performing the transition you can update or set other issue fields.
|
||||||
|
//
|
||||||
|
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition
|
||||||
|
func (s *IssueService) DoTransition(ticketID, transitionID string) (*Response, error) {
|
||||||
|
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions", ticketID)
|
||||||
|
|
||||||
|
payload := CreateTransitionPayload{
|
||||||
|
Transition: TransitionPayload{
|
||||||
|
ID: transitionID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
req, err := s.client.NewRequest("POST", apiEndpoint, payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := s.client.Do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
@ -7,6 +7,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIssueGet_Success(t *testing.T) {
|
func TestIssueGet_Success(t *testing.T) {
|
||||||
@ -398,3 +399,69 @@ func Test_CustomFields(t *testing.T) {
|
|||||||
t.Error("Expected \"test\" for custom field")
|
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.Error("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.Error("Got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
2
jira.go
2
jira.go
@ -28,7 +28,6 @@ type Client struct {
|
|||||||
Issue *IssueService
|
Issue *IssueService
|
||||||
Project *ProjectService
|
Project *ProjectService
|
||||||
Board *BoardService
|
Board *BoardService
|
||||||
Transition *TransitionService
|
|
||||||
Sprint *SprintService
|
Sprint *SprintService
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ func NewClient(httpClient *http.Client, baseURL string) (*Client, error) {
|
|||||||
c.Issue = &IssueService{client: c}
|
c.Issue = &IssueService{client: c}
|
||||||
c.Project = &ProjectService{client: c}
|
c.Project = &ProjectService{client: c}
|
||||||
c.Board = &BoardService{client: c}
|
c.Board = &BoardService{client: c}
|
||||||
c.Transition = &TransitionService{client: c}
|
|
||||||
c.Sprint = &SprintService{client: c}
|
c.Sprint = &SprintService{client: c}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
package jira
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TransitionService handles transitions for JIRA issue.
|
|
||||||
type TransitionService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapper struct for search result
|
|
||||||
type transitionResult struct {
|
|
||||||
Transitions []Transition `json:transitions`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transition represents an issue transition in JIRA
|
|
||||||
type Transition struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Fields map[string]TransitionField `json:"fields"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TransitionField struct {
|
|
||||||
Required bool `json:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreatePayload is used for creating new issue transitions
|
|
||||||
type CreateTransitionPayload struct {
|
|
||||||
Transition TransitionPayload `json:"transition"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TransitionPayload struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetList gets transitions available for given issue
|
|
||||||
//
|
|
||||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getTransitions
|
|
||||||
func (s *TransitionService) GetList(id string) ([]Transition, *Response, error) {
|
|
||||||
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions?expand=transitions.fields", id)
|
|
||||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := new(transitionResult)
|
|
||||||
resp, err := s.client.Do(req, result)
|
|
||||||
return result.Transitions, resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic transition creation. This simply creates transition with given ID for issue
|
|
||||||
// with given ID. It doesn't yet support anything else.
|
|
||||||
//
|
|
||||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition
|
|
||||||
func (s *TransitionService) Create(ticketID, transitionID string) (*Response, error) {
|
|
||||||
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions", ticketID)
|
|
||||||
|
|
||||||
payload := CreateTransitionPayload{
|
|
||||||
Transition: TransitionPayload{
|
|
||||||
ID: transitionID,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
req, err := s.client.NewRequest("POST", apiEndpoint, payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.Do(req, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package jira
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTransitionGetList(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.Transition.GetList("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 TestTransitionCreate(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.Error("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.Transition.Create("123", transitionID)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Error("Got error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user