Skip to content

Commit

Permalink
✨ Added the ability to move issues to a sprint ID
Browse files Browse the repository at this point in the history
  • Loading branch information
ctreminiom committed Nov 8, 2022
1 parent 632ebbf commit 8fd28f1
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 0 deletions.
34 changes: 34 additions & 0 deletions jira/agile/internal/sprint_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,45 @@ func (s *SprintService) Close(ctx context.Context, sprintID int) (*model.Respons
return s.internalClient.Close(ctx, sprintID)
}

// Move moves issues to a sprint, for a given sprint ID.
//
// Issues can only be moved to open or active sprints.
//
// The maximum number of issues that can be moved in one operation is 50.
//
// POST /rest/agile/1.0/sprint/{sprintId}/issue
//
// https://docs.go-atlassian.io/jira-agile/sprints#move-issues-to-sprint
func (s *SprintService) Move(ctx context.Context, sprintID int, payload *model.SprintMovePayloadScheme) (*model.ResponseScheme, error) {
return s.internalClient.Move(ctx, sprintID, payload)
}

type internalSprintImpl struct {
c service.Client
version string
}

func (i *internalSprintImpl) Move(ctx context.Context, sprintID int, payload *model.SprintMovePayloadScheme) (*model.ResponseScheme, error) {

if sprintID == 0 {
return nil, model.ErrNoSprintIDError
}

reader, err := i.c.TransformStructToReader(payload)
if err != nil {
return nil, err
}

endpoint := fmt.Sprintf("/rest/agile/%v/sprint/%v/issue", i.version, sprintID)

request, err := i.c.NewRequest(ctx, http.MethodPost, endpoint, reader)
if err != nil {
return nil, err
}

return i.c.Call(request, nil)
}

func (i *internalSprintImpl) Get(ctx context.Context, sprintID int) (*model.SprintScheme, *model.ResponseScheme, error) {

if sprintID == 0 {
Expand Down
162 changes: 162 additions & 0 deletions jira/agile/internal/sprint_impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1353,3 +1353,165 @@ func Test_SprintService_Close(t *testing.T) {
})
}
}

func Test_SprintService_Move(t *testing.T) {

payloadMocked := &model.SprintMovePayloadScheme{
Issues: []string{"DUMMY-1", "DUMMY-2"},
RankBeforeIssue: "DUMMY-4",
RankAfterIssue: "DUMMY-12",
RankCustomFieldId: 10521,
}

type fields struct {
c service.Client
}

type args struct {
ctx context.Context
sprintId int
payload *model.SprintMovePayloadScheme
}

testCases := []struct {
name string
fields fields
args args
on func(*fields)
wantErr bool
Err error
}{
{
name: "when the parameters are correct",
args: args{
ctx: context.Background(),
sprintId: 1001,
payload: payloadMocked,
},
on: func(fields *fields) {

client := mocks.NewClient(t)

client.On("TransformStructToReader",
payloadMocked).
Return(bytes.NewReader([]byte{}), nil)

client.On("NewRequest",
context.Background(),
http.MethodPost,
"/rest/agile/1.0/sprint/1001/issue",
bytes.NewReader([]byte{})).
Return(&http.Request{}, nil)

client.On("Call",
&http.Request{},
nil).
Return(&model.ResponseScheme{}, nil)

fields.c = client
},
},

{
name: "when the sprintId is not provided",
args: args{
ctx: context.Background(),
},
on: func(fields *fields) {
fields.c = mocks.NewClient(t)
},
Err: model.ErrNoSprintIDError,
wantErr: true,
},

{
name: "when the api cannot be executed",
args: args{
ctx: context.Background(),
sprintId: 1001,
payload: payloadMocked,
},
on: func(fields *fields) {

client := mocks.NewClient(t)

client.On("TransformStructToReader",
payloadMocked).
Return(bytes.NewReader([]byte{}), nil)

client.On("NewRequest",
context.Background(),
http.MethodPost,
"/rest/agile/1.0/sprint/1001/issue",
bytes.NewReader([]byte{})).
Return(&http.Request{}, nil)

client.On("Call",
&http.Request{},
nil).
Return(&model.ResponseScheme{}, errors.New("error, unable to execute the http call"))

fields.c = client
},
Err: errors.New("error, unable to execute the http call"),
wantErr: true,
},

{
name: "when the request cannot be created",
args: args{
ctx: context.Background(),
sprintId: 1001,
payload: payloadMocked,
},
on: func(fields *fields) {

client := mocks.NewClient(t)

client.On("TransformStructToReader",
payloadMocked).
Return(bytes.NewReader([]byte{}), nil)

client.On("NewRequest",
context.Background(),
http.MethodPost,
"/rest/agile/1.0/sprint/1001/issue",
bytes.NewReader([]byte{})).
Return(&http.Request{}, errors.New("unable to create the http request"))

fields.c = client
},
Err: errors.New("unable to create the http request"),
wantErr: true,
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {

if testCase.on != nil {
testCase.on(&testCase.fields)
}

sprintService, err := NewSprintService(testCase.fields.c, "1.0")
assert.NoError(t, err)

gotResponse, err := sprintService.Move(testCase.args.ctx, testCase.args.sprintId, testCase.args.payload)

if testCase.wantErr {

if err != nil {
t.Logf("error returned: %v", err.Error())
}

assert.EqualError(t, err, testCase.Err.Error())

} else {

assert.NoError(t, err)
assert.NotEqual(t, gotResponse, nil)
}

})
}
}
7 changes: 7 additions & 0 deletions pkg/infra/models/agile_sprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@ type SprintIssueScheme struct {
Self string `json:"self,omitempty"`
Key string `json:"key,omitempty"`
}

type SprintMovePayloadScheme struct {
Issues []string `json:"issues,omitempty"`
RankBeforeIssue string `json:"rankBeforeIssue,omitempty"`
RankAfterIssue string `json:"rankAfterIssue,omitempty"`
RankCustomFieldId int `json:"rankCustomFieldId,omitempty"`
}
11 changes: 11 additions & 0 deletions service/agile/sprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,15 @@ type SprintConnector interface {
//
// https://docs.go-atlassian.io/jira-agile/sprints#close-sprint
Close(ctx context.Context, sprintID int) (*models.ResponseScheme, error)

// Move moves issues to a sprint, for a given sprint ID.
//
// Issues can only be moved to open or active sprints.
//
// The maximum number of issues that can be moved in one operation is 50.
//
// POST /rest/agile/1.0/sprint/{sprintId}/issue
//
// https://docs.go-atlassian.io/jira-agile/sprints#move-issues-to-sprint
Move(ctx context.Context, sprintID int, payload *models.SprintMovePayloadScheme) (*models.ResponseScheme, error)
}

0 comments on commit 8fd28f1

Please sign in to comment.