Verified Commit 08dd6e29 authored by Zubeen's avatar Zubeen 🤖 Committed by GitLab
Browse files

feat(merge_requests): add missing list filters to merge request list options

Changelog: Improvements
parent ea8d5daf
Loading
Loading
Loading
Loading
+44
Changes for merge_requests.go: 44 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -479,11 +479,26 @@ type ListMergeRequestsOptions struct {
	CreatedBefore          *time.Time        `url:"created_before,omitempty" json:"created_before,omitempty"`
	UpdatedAfter           *time.Time        `url:"updated_after,omitempty" json:"updated_after,omitempty"`
	UpdatedBefore          *time.Time        `url:"updated_before,omitempty" json:"updated_before,omitempty"`
	DeployedBefore         *time.Time        `url:"deployed_before,omitempty" json:"deployed_before,omitempty"`
	DeployedAfter          *time.Time        `url:"deployed_after,omitempty" json:"deployed_after,omitempty"`
	Environment            *string           `url:"environment,omitempty" json:"environment,omitempty"`
	MergedAfter            *time.Time        `url:"merged_after,omitempty" json:"merged_after,omitempty"`
	MergedBefore           *time.Time        `url:"merged_before,omitempty" json:"merged_before,omitempty"`
	MergeUserID            *int64            `url:"merge_user_id,omitempty" json:"merge_user_id,omitempty"`
	MergeUserUsername      *string           `url:"merge_user_username,omitempty" json:"merge_user_username,omitempty"`
	Scope                  *string           `url:"scope,omitempty" json:"scope,omitempty"`
	AuthorID               *int64            `url:"author_id,omitempty" json:"author_id,omitempty"`
	AuthorUsername         *string           `url:"author_username,omitempty" json:"author_username,omitempty"`
	NotAuthorUsername      *string           `url:"not[author_username],omitempty" json:"not[author_username],omitempty"`
	NotAssigneeID          *AssigneeIDValue  `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"`
	NotAssigneeUsername    *[]string         `url:"not[assignee_username][],omitempty" json:"not[assignee_username],omitempty"`
	NotAuthorID            *int64            `url:"not[author_id],omitempty" json:"not[author_id],omitempty"`
	NotMilestone           *string           `url:"not[milestone],omitempty" json:"not[milestone],omitempty"`
	NotMyReactionEmoji     *string           `url:"not[my_reaction_emoji],omitempty" json:"not[my_reaction_emoji],omitempty"`
	NotReviewerID          *int64            `url:"not[reviewer_id],omitempty" json:"not[reviewer_id],omitempty"`
	NotReviewerUsername    *string           `url:"not[reviewer_username],omitempty" json:"not[reviewer_username],omitempty"`
	AssigneeID             *AssigneeIDValue  `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
	AssigneeUsername       *[]string         `url:"assignee_username[],omitempty" json:"assignee_username,omitempty"`
	ApproverIDs            *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
	ApprovedByUsernames    *[]string         `url:"approved_by_usernames,omitempty" json:"approved_by_usernames,omitempty"`
	ApprovedByIDs          *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
@@ -535,13 +550,25 @@ type ListProjectMergeRequestsOptions struct {
	CreatedBefore          *time.Time        `url:"created_before,omitempty" json:"created_before,omitempty"`
	UpdatedAfter           *time.Time        `url:"updated_after,omitempty" json:"updated_after,omitempty"`
	UpdatedBefore          *time.Time        `url:"updated_before,omitempty" json:"updated_before,omitempty"`
	MergedAfter            *time.Time        `url:"merged_after,omitempty" json:"merged_after,omitempty"`
	MergedBefore           *time.Time        `url:"merged_before,omitempty" json:"merged_before,omitempty"`
	MergeUserID            *int64            `url:"merge_user_id,omitempty" json:"merge_user_id,omitempty"`
	MergeUserUsername      *string           `url:"merge_user_username,omitempty" json:"merge_user_username,omitempty"`
	DeployedBefore         *time.Time        `url:"deployed_before,omitempty" json:"deployed_before,omitempty"`
	DeployedAfter          *time.Time        `url:"deployed_after,omitempty" json:"deployed_after,omitempty"`
	Scope                  *string           `url:"scope,omitempty" json:"scope,omitempty"`
	AuthorID               *int64            `url:"author_id,omitempty" json:"author_id,omitempty"`
	AuthorUsername         *string           `url:"author_username,omitempty" json:"author_username,omitempty"`
	NotAuthorUsername      *string           `url:"not[author_username],omitempty" json:"not[author_username],omitempty"`
	NotAssigneeID          *AssigneeIDValue  `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"`
	NotAssigneeUsername    *[]string         `url:"not[assignee_username][],omitempty" json:"not[assignee_username],omitempty"`
	NotAuthorID            *int64            `url:"not[author_id],omitempty" json:"not[author_id],omitempty"`
	NotMilestone           *string           `url:"not[milestone],omitempty" json:"not[milestone],omitempty"`
	NotMyReactionEmoji     *string           `url:"not[my_reaction_emoji],omitempty" json:"not[my_reaction_emoji],omitempty"`
	NotReviewerID          *int64            `url:"not[reviewer_id],omitempty" json:"not[reviewer_id],omitempty"`
	NotReviewerUsername    *string           `url:"not[reviewer_username],omitempty" json:"not[reviewer_username],omitempty"`
	AssigneeID             *AssigneeIDValue  `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
	AssigneeUsername       *[]string         `url:"assignee_username[],omitempty" json:"assignee_username,omitempty"`
	ApproverIDs            *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
	ApprovedByUsernames    *[]string         `url:"approved_by_usernames,omitempty" json:"approved_by_usernames,omitempty"`
	ApprovedByIDs          *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
@@ -551,6 +578,7 @@ type ListProjectMergeRequestsOptions struct {
	SourceBranch           *string           `url:"source_branch,omitempty" json:"source_branch,omitempty"`
	TargetBranch           *string           `url:"target_branch,omitempty" json:"target_branch,omitempty"`
	Search                 *string           `url:"search,omitempty" json:"search,omitempty"`
	In                     *string           `url:"in,omitempty" json:"in,omitempty"`
	Draft                  *bool             `url:"draft,omitempty" json:"draft,omitempty"`
	WIP                    *string           `url:"wip,omitempty" json:"wip,omitempty"`
	NonArchived            *bool             `url:"non_archived,omitempty" json:"non_archived,omitempty"`
@@ -590,11 +618,26 @@ type ListGroupMergeRequestsOptions struct {
	CreatedBefore          *time.Time        `url:"created_before,omitempty" json:"created_before,omitempty"`
	UpdatedAfter           *time.Time        `url:"updated_after,omitempty" json:"updated_after,omitempty"`
	UpdatedBefore          *time.Time        `url:"updated_before,omitempty" json:"updated_before,omitempty"`
	DeployedBefore         *time.Time        `url:"deployed_before,omitempty" json:"deployed_before,omitempty"`
	DeployedAfter          *time.Time        `url:"deployed_after,omitempty" json:"deployed_after,omitempty"`
	Environment            *string           `url:"environment,omitempty" json:"environment,omitempty"`
	MergedAfter            *time.Time        `url:"merged_after,omitempty" json:"merged_after,omitempty"`
	MergedBefore           *time.Time        `url:"merged_before,omitempty" json:"merged_before,omitempty"`
	MergeUserID            *int64            `url:"merge_user_id,omitempty" json:"merge_user_id,omitempty"`
	MergeUserUsername      *string           `url:"merge_user_username,omitempty" json:"merge_user_username,omitempty"`
	Scope                  *string           `url:"scope,omitempty" json:"scope,omitempty"`
	AuthorID               *int64            `url:"author_id,omitempty" json:"author_id,omitempty"`
	AuthorUsername         *string           `url:"author_username,omitempty" json:"author_username,omitempty"`
	NotAuthorUsername      *string           `url:"not[author_username],omitempty" json:"not[author_username],omitempty"`
	NotAssigneeID          *AssigneeIDValue  `url:"not[assignee_id],omitempty" json:"not[assignee_id],omitempty"`
	NotAssigneeUsername    *[]string         `url:"not[assignee_username][],omitempty" json:"not[assignee_username],omitempty"`
	NotAuthorID            *int64            `url:"not[author_id],omitempty" json:"not[author_id],omitempty"`
	NotMilestone           *string           `url:"not[milestone],omitempty" json:"not[milestone],omitempty"`
	NotMyReactionEmoji     *string           `url:"not[my_reaction_emoji],omitempty" json:"not[my_reaction_emoji],omitempty"`
	NotReviewerID          *int64            `url:"not[reviewer_id],omitempty" json:"not[reviewer_id],omitempty"`
	NotReviewerUsername    *string           `url:"not[reviewer_username],omitempty" json:"not[reviewer_username],omitempty"`
	AssigneeID             *AssigneeIDValue  `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
	AssigneeUsername       *[]string         `url:"assignee_username[],omitempty" json:"assignee_username,omitempty"`
	ApproverIDs            *ApproverIDsValue `url:"approver_ids,omitempty" json:"approver_ids,omitempty"`
	ApprovedByUsernames    *[]string         `url:"approved_by_usernames,omitempty" json:"approved_by_usernames,omitempty"`
	ApprovedByIDs          *ApproverIDsValue `url:"approved_by_ids,omitempty" json:"approved_by_ids,omitempty"`
@@ -602,6 +645,7 @@ type ListGroupMergeRequestsOptions struct {
	ReviewerUsername       *string           `url:"reviewer_username,omitempty" json:"reviewer_username,omitempty"`
	MyReactionEmoji        *string           `url:"my_reaction_emoji,omitempty" json:"my_reaction_emoji,omitempty"`
	SourceBranch           *string           `url:"source_branch,omitempty" json:"source_branch,omitempty"`
	SourceProjectID        *int64            `url:"source_project_id,omitempty" json:"source_project_id,omitempty"`
	TargetBranch           *string           `url:"target_branch,omitempty" json:"target_branch,omitempty"`
	Search                 *string           `url:"search,omitempty" json:"search,omitempty"`
	In                     *string           `url:"in,omitempty" json:"in,omitempty"`
+156
Changes for merge_requests_test.go: 156 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"testing"
	"time"

@@ -860,6 +861,161 @@ func TestListGroupMergeRequests_search(t *testing.T) {
	assert.Contains(t, mr.Description, "Renovate")
}

func TestListMergeRequests_filters(t *testing.T) {
	t.Parallel()

	mergedAfter := mustParseTime("2019-03-15T08:00:00Z")
	mergedBefore := mustParseTime("2019-03-16T08:00:00Z")

	tests := []struct {
		name string
		path string
		want url.Values
		call func(client *Client) ([]*BasicMergeRequest, *Response, error)
	}{
		{
			name: "global",
			path: "/api/v4/merge_requests",
			want: url.Values{
				"assignee_username[]":      {"alice", "bob"},
				"deployed_after":           {"2019-03-15T08:00:00Z"},
				"deployed_before":          {"2019-03-16T08:00:00Z"},
				"environment":              {"production"},
				"merged_after":             {"2019-03-15T08:00:00Z"},
				"merged_before":            {"2019-03-16T08:00:00Z"},
				"merge_user_id":            {"7"},
				"merge_user_username":      {"carol"},
				"not[assignee_id]":         {"None"},
				"not[assignee_username][]": {"dave"},
				"not[author_id]":           {"8"},
				"not[milestone]":           {"v1"},
				"not[my_reaction_emoji]":   {"thumbsup"},
				"not[reviewer_id]":         {"9"},
				"not[reviewer_username]":   {"erin"},
			},
			call: func(client *Client) ([]*BasicMergeRequest, *Response, error) {
				return client.MergeRequests.ListMergeRequests(&ListMergeRequestsOptions{
					AssigneeUsername:    &[]string{"alice", "bob"},
					DeployedAfter:       mergedAfter,
					DeployedBefore:      mergedBefore,
					Environment:         new("production"),
					MergedAfter:         mergedAfter,
					MergedBefore:        mergedBefore,
					MergeUserID:         new(int64(7)),
					MergeUserUsername:   new("carol"),
					NotAssigneeID:       AssigneeID(UserIDNone),
					NotAssigneeUsername: &[]string{"dave"},
					NotAuthorID:         new(int64(8)),
					NotMilestone:        new("v1"),
					NotMyReactionEmoji:  new("thumbsup"),
					NotReviewerID:       new(int64(9)),
					NotReviewerUsername: new("erin"),
				})
			},
		},
		{
			name: "project",
			path: "/api/v4/projects/1/merge_requests",
			want: url.Values{
				"assignee_username[]":      {"alice", "bob"},
				"in":                       {"title"},
				"merged_after":             {"2019-03-15T08:00:00Z"},
				"merged_before":            {"2019-03-16T08:00:00Z"},
				"merge_user_id":            {"7"},
				"merge_user_username":      {"carol"},
				"not[assignee_id]":         {"None"},
				"not[assignee_username][]": {"dave"},
				"not[author_id]":           {"8"},
				"not[milestone]":           {"v1"},
				"not[my_reaction_emoji]":   {"thumbsup"},
				"not[reviewer_id]":         {"9"},
				"not[reviewer_username]":   {"erin"},
			},
			call: func(client *Client) ([]*BasicMergeRequest, *Response, error) {
				return client.MergeRequests.ListProjectMergeRequests(1, &ListProjectMergeRequestsOptions{
					AssigneeUsername:    &[]string{"alice", "bob"},
					In:                  new("title"),
					MergedAfter:         mergedAfter,
					MergedBefore:        mergedBefore,
					MergeUserID:         new(int64(7)),
					MergeUserUsername:   new("carol"),
					NotAssigneeID:       AssigneeID(UserIDNone),
					NotAssigneeUsername: &[]string{"dave"},
					NotAuthorID:         new(int64(8)),
					NotMilestone:        new("v1"),
					NotMyReactionEmoji:  new("thumbsup"),
					NotReviewerID:       new(int64(9)),
					NotReviewerUsername: new("erin"),
				})
			},
		},
		{
			name: "group",
			path: "/api/v4/groups/1/merge_requests",
			want: url.Values{
				"assignee_username[]":      {"alice", "bob"},
				"deployed_after":           {"2019-03-15T08:00:00Z"},
				"deployed_before":          {"2019-03-16T08:00:00Z"},
				"environment":              {"production"},
				"merged_after":             {"2019-03-15T08:00:00Z"},
				"merged_before":            {"2019-03-16T08:00:00Z"},
				"merge_user_id":            {"7"},
				"merge_user_username":      {"carol"},
				"not[assignee_id]":         {"None"},
				"not[assignee_username][]": {"dave"},
				"not[author_id]":           {"8"},
				"not[milestone]":           {"v1"},
				"not[my_reaction_emoji]":   {"thumbsup"},
				"not[reviewer_id]":         {"9"},
				"not[reviewer_username]":   {"erin"},
				"source_project_id":        {"10"},
			},
			call: func(client *Client) ([]*BasicMergeRequest, *Response, error) {
				return client.MergeRequests.ListGroupMergeRequests(1, &ListGroupMergeRequestsOptions{
					AssigneeUsername:    &[]string{"alice", "bob"},
					DeployedAfter:       mergedAfter,
					DeployedBefore:      mergedBefore,
					Environment:         new("production"),
					MergedAfter:         mergedAfter,
					MergedBefore:        mergedBefore,
					MergeUserID:         new(int64(7)),
					MergeUserUsername:   new("carol"),
					NotAssigneeID:       AssigneeID(UserIDNone),
					NotAssigneeUsername: &[]string{"dave"},
					NotAuthorID:         new(int64(8)),
					NotMilestone:        new("v1"),
					NotMyReactionEmoji:  new("thumbsup"),
					NotReviewerID:       new(int64(9)),
					NotReviewerUsername: new("erin"),
					SourceProjectID:     new(int64(10)),
				})
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			mux, client := setup(t)

			// GIVEN a list endpoint that only answers when all filters are sent
			mux.HandleFunc(tt.path, func(w http.ResponseWriter, r *http.Request) {
				testMethod(t, r, http.MethodGet)
				assert.Equal(t, tt.want, r.URL.Query())
				mustWriteHTTPResponse(t, w, "testdata/list_group_merge_requests.json")
			})

			// WHEN listing with the new filters
			mrs, resp, err := tt.call(client)

			// THEN the request carries every filter
			require.NoError(t, err)
			require.NotNil(t, resp)
			assert.Len(t, mrs, 1)
		})
	}
}

func TestCreateMergeRequest_milestoneAndMergeAfter(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)