diff --git a/jira/mocks/get-project-versions.json b/jira/mocks/get-project-versions.json new file mode 100644 index 00000000..53d83448 --- /dev/null +++ b/jira/mocks/get-project-versions.json @@ -0,0 +1,30 @@ +[ + { + "self": "https://your-domain.atlassian.net/rest/api/3/version/10000", + "id": "10000", + "description": "An excellent version", + "name": "New Version 1", + "archived": false, + "released": true, + "releaseDate": "2010-07-06", + "overdue": true, + "userReleaseDate": "6/Jul/2010", + "projectId": 10000 + }, + { + "self": "https://your-domain.atlassian.net/rest/api/3/version/10010", + "id": "10010", + "description": "Minor Bugfix version", + "name": "Next Version", + "archived": false, + "released": false, + "overdue": false, + "projectId": 10000, + "issuesStatusForFixVersion": { + "unmapped": 0, + "toDo": 10, + "inProgress": 20, + "done": 100 + } + } +] \ No newline at end of file diff --git a/jira/v2/projectVersion.go b/jira/v2/projectVersion.go index 89a22777..8990ff4c 100644 --- a/jira/v2/projectVersion.go +++ b/jira/v2/projectVersion.go @@ -12,10 +12,37 @@ import ( type ProjectVersionService struct{ client *Client } -// Gets returns a paginated list of all versions in a project. +// Gets returns all versions in a project. +// The response is not paginated. +// Use Get project versions paginated if you want to get the versions in a project with pagination. +// Atlassian Docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-project-versions/#api-rest-api-2-project-projectidorkey-versions-get +func (p *ProjectVersionService) Gets(ctx context.Context, projectKeyOrID string) (result []*models.VersionScheme, response *ResponseScheme, err error) { + + if len(projectKeyOrID) == 0 { + return nil, nil, models.ErrNoProjectIDError + } + + endpoint := fmt.Sprintf("rest/api/2/project/%v/versions", projectKeyOrID) + + request, err := p.client.newRequest(ctx, http.MethodGet, endpoint, nil) + if err != nil { + return + } + + request.Header.Set("Accept", "application/json") + + response, err = p.client.call(request, &result) + if err != nil { + return + } + + return +} + +// Search returns a paginated list of all versions in a project. // Docs: https://docs.go-atlassian.io/jira-software-cloud/projects/versions#get-project-versions-paginated // Atlassian Docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-project-versions/#api-rest-api-2-project-projectidorkey-version-get -func (p *ProjectVersionService) Gets(ctx context.Context, projectKeyOrID string, options *models.VersionGetsOptions, startAt, +func (p *ProjectVersionService) Search(ctx context.Context, projectKeyOrID string, options *models.VersionGetsOptions, startAt, maxResults int) (result *models.VersionPageScheme, response *ResponseScheme, err error) { if len(projectKeyOrID) == 0 { diff --git a/jira/v2/projectVersion_test.go b/jira/v2/projectVersion_test.go index 31d94c3a..30543634 100644 --- a/jira/v2/projectVersion_test.go +++ b/jira/v2/projectVersion_test.go @@ -372,6 +372,160 @@ func TestProjectVersionService_Get(t *testing.T) { func TestProjectVersionService_Gets(t *testing.T) { + testCases := []struct { + name string + projectKeyOrID string + mockFile string + wantHTTPMethod string + endpoint string + context context.Context + wantHTTPCodeReturn int + wantErr bool + }{ + { + name: "GetProjectVersionsWhenTheParamsAreCorrect", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/2/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: false, + }, + + { + name: "GetProjectVersionsWhenTheProjectKeyIsNotProvided", + projectKeyOrID: "", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/2/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheExpandsIsNil", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/2/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: false, + }, + + { + name: "GetProjectVersionsWhenTheRequestMethodIsIncorrect", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodPost, + endpoint: "/rest/api/2/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheStatusCodeIsIncorrect", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/2/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusBadRequest, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheContextIsNil", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/2/project/10001/versions", + context: nil, + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheResponseBodyHasADifferentFormat", + projectKeyOrID: "10001", + mockFile: "./mocks/empty_json.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/2/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + } + + for _, testCase := range testCases { + + t.Run(testCase.name, func(t *testing.T) { + + //Init a new HTTP mock server + mockOptions := mockServerOptions{ + Endpoint: testCase.endpoint, + MockFilePath: testCase.mockFile, + MethodAccepted: testCase.wantHTTPMethod, + ResponseCodeWanted: testCase.wantHTTPCodeReturn, + } + + mockServer, err := startMockServer(&mockOptions) + if err != nil { + t.Fatal(err) + } + + defer mockServer.Close() + + //Init the library instance + mockClient, err := startMockClient(mockServer.URL) + if err != nil { + t.Fatal(err) + } + + i := &ProjectVersionService{client: mockClient} + + gotResult, gotResponse, err := i.Gets(testCase.context, testCase.projectKeyOrID) + + if testCase.wantErr { + + if err != nil { + t.Logf("error returned: %v", err.Error()) + } + + assert.Error(t, err) + } else { + + assert.NoError(t, err) + assert.NotEqual(t, gotResponse, nil) + assert.NotEqual(t, gotResult, nil) + + apiEndpoint, err := url.Parse(gotResponse.Endpoint) + if err != nil { + t.Fatal(err) + } + + var endpointToAssert string + + if apiEndpoint.Query().Encode() != "" { + endpointToAssert = fmt.Sprintf("%v?%v", apiEndpoint.Path, apiEndpoint.Query().Encode()) + } else { + endpointToAssert = apiEndpoint.Path + } + + t.Logf("HTTP Endpoint Wanted: %v, HTTP Endpoint Returned: %v", testCase.endpoint, endpointToAssert) + assert.Equal(t, testCase.endpoint, endpointToAssert) + } + }) + + } + +} + +func TestProjectVersionService_Search(t *testing.T) { + testCases := []struct { name string projectKeyOrID string @@ -385,7 +539,7 @@ func TestProjectVersionService_Gets(t *testing.T) { wantErr bool }{ { - name: "GetProjectVersionsWhenTheParamsAreCorrect", + name: "SearchProjectVersionsWhenTheParamsAreCorrect", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -404,7 +558,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheOptionsAreNotProvided", + name: "SearchProjectVersionsWhenTheOptionsAreNotProvided", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "", @@ -423,7 +577,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheOptionsIsNil", + name: "SearchProjectVersionsWhenTheOptionsIsNil", projectKeyOrID: "DUMMY", options: nil, startAt: 0, @@ -437,7 +591,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheRequestMethodIsIncorrect", + name: "SearchProjectVersionsWhenTheRequestMethodIsIncorrect", projectKeyOrID: "", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -456,7 +610,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheStatusCodeIsIncorrect", + name: "SearchProjectVersionsWhenTheStatusCodeIsIncorrect", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -475,7 +629,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheContextIsNil", + name: "SearchProjectVersionsWhenTheContextIsNil", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -494,7 +648,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheResponseBodyHasADifferentFormat", + name: "SearchProjectVersionsWhenTheResponseBodyHasADifferentFormat", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -540,7 +694,7 @@ func TestProjectVersionService_Gets(t *testing.T) { i := &ProjectVersionService{client: mockClient} - gotResult, gotResponse, err := i.Gets(testCase.context, testCase.projectKeyOrID, testCase.options, + gotResult, gotResponse, err := i.Search(testCase.context, testCase.projectKeyOrID, testCase.options, testCase.startAt, testCase.maxResults) if testCase.wantErr { diff --git a/jira/v3/projectVersion.go b/jira/v3/projectVersion.go index 6f0c35b1..346647d4 100644 --- a/jira/v3/projectVersion.go +++ b/jira/v3/projectVersion.go @@ -12,10 +12,37 @@ import ( type ProjectVersionService struct{ client *Client } -// Gets returns a paginated list of all versions in a project. +// Gets returns all versions in a project. +// The response is not paginated. +// Use Get project versions paginated if you want to get the versions in a project with pagination. +// Atlassian Docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-project-versions/#api-rest-api-3-project-projectidorkey-versions-get +func (p *ProjectVersionService) Gets(ctx context.Context, projectKeyOrID string) (result []*models.VersionScheme, response *ResponseScheme, err error) { + + if len(projectKeyOrID) == 0 { + return nil, nil, models.ErrNoProjectIDError + } + + endpoint := fmt.Sprintf("rest/api/3/project/%v/versions", projectKeyOrID) + + request, err := p.client.newRequest(ctx, http.MethodGet, endpoint, nil) + if err != nil { + return + } + + request.Header.Set("Accept", "application/json") + + response, err = p.client.call(request, &result) + if err != nil { + return + } + + return +} + +// Search returns a paginated list of all versions in a project. // Docs: https://docs.go-atlassian.io/jira-software-cloud/projects/versions#get-project-versions-paginated // Atlassian Docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-project-versions/#api-rest-api-3-project-projectidorkey-version-get -func (p *ProjectVersionService) Gets(ctx context.Context, projectKeyOrID string, options *models.VersionGetsOptions, startAt, +func (p *ProjectVersionService) Search(ctx context.Context, projectKeyOrID string, options *models.VersionGetsOptions, startAt, maxResults int) (result *models.VersionPageScheme, response *ResponseScheme, err error) { if len(projectKeyOrID) == 0 { diff --git a/jira/v3/projectVersion_test.go b/jira/v3/projectVersion_test.go index f4e5d767..0d49403f 100644 --- a/jira/v3/projectVersion_test.go +++ b/jira/v3/projectVersion_test.go @@ -390,6 +390,160 @@ func TestProjectVersionService_Get(t *testing.T) { func TestProjectVersionService_Gets(t *testing.T) { + testCases := []struct { + name string + projectKeyOrID string + mockFile string + wantHTTPMethod string + endpoint string + context context.Context + wantHTTPCodeReturn int + wantErr bool + }{ + { + name: "GetProjectVersionsWhenTheParamsAreCorrect", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/3/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: false, + }, + + { + name: "GetProjectVersionsWhenTheProjectKeyIsNotProvided", + projectKeyOrID: "", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/3/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheExpandsIsNil", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/3/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: false, + }, + + { + name: "GetProjectVersionsWhenTheRequestMethodIsIncorrect", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodPost, + endpoint: "/rest/api/3/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheStatusCodeIsIncorrect", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/3/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusBadRequest, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheContextIsNil", + projectKeyOrID: "10001", + mockFile: "../mocks/get-project-versions.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/3/project/10001/versions", + context: nil, + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + + { + name: "GetProjectVersionsWhenTheResponseBodyHasADifferentFormat", + projectKeyOrID: "10001", + mockFile: "./mocks/empty_json.json", + wantHTTPMethod: http.MethodGet, + endpoint: "/rest/api/3/project/10001/versions", + context: context.Background(), + wantHTTPCodeReturn: http.StatusOK, + wantErr: true, + }, + } + + for _, testCase := range testCases { + + t.Run(testCase.name, func(t *testing.T) { + + //Init a new HTTP mock server + mockOptions := mockServerOptions{ + Endpoint: testCase.endpoint, + MockFilePath: testCase.mockFile, + MethodAccepted: testCase.wantHTTPMethod, + ResponseCodeWanted: testCase.wantHTTPCodeReturn, + } + + mockServer, err := startMockServer(&mockOptions) + if err != nil { + t.Fatal(err) + } + + defer mockServer.Close() + + //Init the library instance + mockClient, err := startMockClient(mockServer.URL) + if err != nil { + t.Fatal(err) + } + + i := &ProjectVersionService{client: mockClient} + + gotResult, gotResponse, err := i.Gets(testCase.context, testCase.projectKeyOrID) + + if testCase.wantErr { + + if err != nil { + t.Logf("error returned: %v", err.Error()) + } + + assert.Error(t, err) + } else { + + assert.NoError(t, err) + assert.NotEqual(t, gotResponse, nil) + assert.NotEqual(t, gotResult, nil) + + apiEndpoint, err := url.Parse(gotResponse.Endpoint) + if err != nil { + t.Fatal(err) + } + + var endpointToAssert string + + if apiEndpoint.Query().Encode() != "" { + endpointToAssert = fmt.Sprintf("%v?%v", apiEndpoint.Path, apiEndpoint.Query().Encode()) + } else { + endpointToAssert = apiEndpoint.Path + } + + t.Logf("HTTP Endpoint Wanted: %v, HTTP Endpoint Returned: %v", testCase.endpoint, endpointToAssert) + assert.Equal(t, testCase.endpoint, endpointToAssert) + } + }) + + } + +} + +func TestProjectVersionService_Search(t *testing.T) { + testCases := []struct { name string projectKeyOrID string @@ -403,7 +557,7 @@ func TestProjectVersionService_Gets(t *testing.T) { wantErr bool }{ { - name: "GetProjectVersionsWhenTheParamsAreCorrect", + name: "SearchProjectVersionsWhenTheParamsAreCorrect", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -422,7 +576,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheOptionsAreNotProvided", + name: "SearchProjectVersionsWhenTheOptionsAreNotProvided", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "", @@ -441,7 +595,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheOptionsIsNil", + name: "SearchProjectVersionsWhenTheOptionsIsNil", projectKeyOrID: "DUMMY", options: nil, startAt: 0, @@ -455,7 +609,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheRequestMethodIsIncorrect", + name: "SearchProjectVersionsWhenTheRequestMethodIsIncorrect", projectKeyOrID: "", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -474,7 +628,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheStatusCodeIsIncorrect", + name: "SearchProjectVersionsWhenTheStatusCodeIsIncorrect", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -493,7 +647,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheContextIsNil", + name: "SearchProjectVersionsWhenTheContextIsNil", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -512,7 +666,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheResponseBodyHasADifferentFormat", + name: "SearchProjectVersionsWhenTheResponseBodyHasADifferentFormat", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -531,7 +685,7 @@ func TestProjectVersionService_Gets(t *testing.T) { }, { - name: "GetProjectVersionsWhenTheEndpointIsIncorrect", + name: "SearchProjectVersionsWhenTheEndpointIsIncorrect", projectKeyOrID: "DUMMY", options: &models.VersionGetsOptions{ OrderBy: "description", @@ -577,7 +731,7 @@ func TestProjectVersionService_Gets(t *testing.T) { i := &ProjectVersionService{client: mockClient} - gotResult, gotResponse, err := i.Gets(testCase.context, testCase.projectKeyOrID, testCase.options, + gotResult, gotResponse, err := i.Search(testCase.context, testCase.projectKeyOrID, testCase.options, testCase.startAt, testCase.maxResults) if testCase.wantErr {