Merge branch 'cli:trunk' into trunk
This commit is contained in:
commit
ab037b0e74
7 changed files with 180 additions and 17 deletions
|
|
@ -151,17 +151,27 @@ type PullRequestFile struct {
|
|||
type ReviewRequests struct {
|
||||
Nodes []struct {
|
||||
RequestedReviewer struct {
|
||||
TypeName string `json:"__typename"`
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
TypeName string `json:"__typename"`
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Organization struct {
|
||||
Login string `json:"login"`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const teamTypeName = "Team"
|
||||
|
||||
func (r ReviewRequests) Logins() []string {
|
||||
logins := make([]string, len(r.Nodes))
|
||||
for i, a := range r.Nodes {
|
||||
logins[i] = a.RequestedReviewer.Login
|
||||
if a.RequestedReviewer.TypeName == teamTypeName {
|
||||
logins[i] = fmt.Sprintf("%s/%s", a.RequestedReviewer.Organization.Login, a.RequestedReviewer.Slug)
|
||||
} else {
|
||||
logins[i] = a.RequestedReviewer.Login
|
||||
}
|
||||
}
|
||||
return logins
|
||||
}
|
||||
|
|
@ -393,8 +403,8 @@ func PullRequestStatus(client *Client, repo ghrepo.Interface, options StatusOpti
|
|||
queryPrefix := `
|
||||
query PullRequestStatus($owner: String!, $repo: String!, $headRefName: String!, $viewerQuery: String!, $reviewerQuery: String!, $per_page: Int = 10) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
defaultBranchRef {
|
||||
name
|
||||
defaultBranchRef {
|
||||
name
|
||||
}
|
||||
pullRequests(headRefName: $headRefName, first: $per_page, orderBy: { field: CREATED_AT, direction: DESC }) {
|
||||
totalCount
|
||||
|
|
@ -410,8 +420,8 @@ func PullRequestStatus(client *Client, repo ghrepo.Interface, options StatusOpti
|
|||
queryPrefix = `
|
||||
query PullRequestStatus($owner: String!, $repo: String!, $number: Int!, $viewerQuery: String!, $reviewerQuery: String!, $per_page: Int = 10) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
defaultBranchRef {
|
||||
name
|
||||
defaultBranchRef {
|
||||
name
|
||||
}
|
||||
pullRequest(number: $number) {
|
||||
...prWithReviews
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
"github.com/cli/cli/internal/ghrepo"
|
||||
"github.com/cli/cli/pkg/httpmock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBranchDeleteRemote(t *testing.T) {
|
||||
|
|
@ -148,13 +149,94 @@ func Test_determinePullRequestFeatures(t *testing.T) {
|
|||
}
|
||||
|
||||
gotPrFeatures, err := determinePullRequestFeatures(httpClient, tt.hostname)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("determinePullRequestFeatures() error = %v, wantErr %v", err, tt.wantErr)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if !reflect.DeepEqual(gotPrFeatures, tt.wantPrFeatures) {
|
||||
t.Errorf("determinePullRequestFeatures() = %v, want %v", gotPrFeatures, tt.wantPrFeatures)
|
||||
}
|
||||
assert.Equal(t, tt.wantPrFeatures, gotPrFeatures)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Logins(t *testing.T) {
|
||||
rr := ReviewRequests{}
|
||||
var tests = []struct {
|
||||
name string
|
||||
requestedReviews string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "no requested reviewers",
|
||||
requestedReviews: `{"nodes": []}`,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "user",
|
||||
requestedReviews: `{"nodes": [
|
||||
{
|
||||
"requestedreviewer": {
|
||||
"__typename": "User", "login": "testuser"
|
||||
}
|
||||
}
|
||||
]}`,
|
||||
want: []string{"testuser"},
|
||||
},
|
||||
{
|
||||
name: "team",
|
||||
requestedReviews: `{"nodes": [
|
||||
{
|
||||
"requestedreviewer": {
|
||||
"__typename": "Team",
|
||||
"name": "Test Team",
|
||||
"slug": "test-team",
|
||||
"organization": {"login": "myorg"}
|
||||
}
|
||||
}
|
||||
]}`,
|
||||
want: []string{"myorg/test-team"},
|
||||
},
|
||||
{
|
||||
name: "multiple users and teams",
|
||||
requestedReviews: `{"nodes": [
|
||||
{
|
||||
"requestedreviewer": {
|
||||
"__typename": "User", "login": "user1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"requestedreviewer": {
|
||||
"__typename": "User", "login": "user2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"requestedreviewer": {
|
||||
"__typename": "Team",
|
||||
"name": "Test Team",
|
||||
"slug": "test-team",
|
||||
"organization": {"login": "myorg"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"requestedreviewer": {
|
||||
"__typename": "Team",
|
||||
"name": "Dev Team",
|
||||
"slug": "dev-team",
|
||||
"organization": {"login": "myorg"}
|
||||
}
|
||||
}
|
||||
]}`,
|
||||
want: []string{"user1", "user2", "myorg/test-team", "myorg/dev-team"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := json.Unmarshal([]byte(tt.requestedReviews), &rr)
|
||||
assert.NoError(t, err, "Failed to unmarshal json string as ReviewRequests")
|
||||
logins := rr.Logins()
|
||||
assert.Equal(t, tt.want, logins)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,11 @@ var prReviewRequests = shortenQuery(`
|
|||
requestedReviewer {
|
||||
__typename,
|
||||
...on User{login},
|
||||
...on Team{name}
|
||||
...on Team{
|
||||
organization{login}
|
||||
name,
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,9 +112,14 @@ func listRun(opts *ListOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
issueState := strings.ToLower(opts.State)
|
||||
if issueState == "open" && shared.QueryHasStateClause(opts.Search) {
|
||||
issueState = ""
|
||||
}
|
||||
|
||||
filterOptions := prShared.FilterOptions{
|
||||
Entity: "issue",
|
||||
State: strings.ToLower(opts.State),
|
||||
State: issueState,
|
||||
Assignee: opts.Assignee,
|
||||
Labels: opts.Labels,
|
||||
Author: opts.Author,
|
||||
|
|
|
|||
|
|
@ -116,9 +116,14 @@ func listRun(opts *ListOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
prState := strings.ToLower(opts.State)
|
||||
if prState == "open" && shared.QueryHasStateClause(opts.Search) {
|
||||
prState = ""
|
||||
}
|
||||
|
||||
filters := shared.FilterOptions{
|
||||
Entity: "pr",
|
||||
State: strings.ToLower(opts.State),
|
||||
State: prState,
|
||||
Author: opts.Author,
|
||||
Assignee: opts.Assignee,
|
||||
Labels: opts.Labels,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package shared
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/google/shlex"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
|
|
@ -243,6 +244,21 @@ func SearchQueryBuild(options FilterOptions) string {
|
|||
return q.String()
|
||||
}
|
||||
|
||||
func QueryHasStateClause(searchQuery string) bool {
|
||||
argv, err := shlex.Split(searchQuery)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, arg := range argv {
|
||||
if arg == "is:closed" || arg == "is:merged" || arg == "state:closed" || arg == "state:merged" || strings.HasPrefix(arg, "merged:") || strings.HasPrefix(arg, "closed:") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// MeReplacer resolves usages of `@me` to the handle of the currently logged in user.
|
||||
type MeReplacer struct {
|
||||
apiClient *api.Client
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package shared
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
|
@ -151,3 +152,43 @@ func TestMeReplacer_Replace(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_QueryHasStateClause(t *testing.T) {
|
||||
tests := []struct {
|
||||
searchQuery string
|
||||
hasState bool
|
||||
}{
|
||||
{
|
||||
searchQuery: "is:closed is:merged",
|
||||
hasState: true,
|
||||
},
|
||||
{
|
||||
searchQuery: "author:mislav",
|
||||
hasState: false,
|
||||
},
|
||||
{
|
||||
searchQuery: "assignee:g14a mentions:vilmibm",
|
||||
hasState: false,
|
||||
},
|
||||
{
|
||||
searchQuery: "merged:>2021-05-20",
|
||||
hasState: true,
|
||||
},
|
||||
{
|
||||
searchQuery: "state:merged state:open",
|
||||
hasState: true,
|
||||
},
|
||||
{
|
||||
searchQuery: "assignee:g14a is:closed",
|
||||
hasState: true,
|
||||
},
|
||||
{
|
||||
searchQuery: "state:closed label:bug",
|
||||
hasState: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
gotState := QueryHasStateClause(tt.searchQuery)
|
||||
assert.Equal(t, tt.hasState, gotState)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue