* Use the host name from the logged in server for codespace commands * Fix existing tests * Add tests for server url configuration * Rename defaultApiUrl to defaultAPIURL and comment cleanup * Switch to t.Setenv in codespaces api tests * Switch to t.Setenv in other tests * Support custom server in web flows for list and create * Rename GetServerURL() to ServerURL()
735 lines
15 KiB
Go
735 lines
15 KiB
Go
package list
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
"github.com/cli/cli/v2/internal/tableprinter"
|
|
"github.com/cli/cli/v2/pkg/cmd/project/shared/queries"
|
|
"github.com/cli/cli/v2/pkg/cmdutil"
|
|
"github.com/cli/cli/v2/pkg/iostreams"
|
|
"github.com/google/shlex"
|
|
"github.com/stretchr/testify/assert"
|
|
"gopkg.in/h2non/gock.v1"
|
|
)
|
|
|
|
func TestNewCmdlist(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cli string
|
|
wants listOpts
|
|
wantsErr bool
|
|
wantsErrMsg string
|
|
}{
|
|
{
|
|
name: "owner",
|
|
cli: "--owner monalisa",
|
|
wants: listOpts{
|
|
owner: "monalisa",
|
|
limit: 30,
|
|
},
|
|
},
|
|
{
|
|
name: "closed",
|
|
cli: "--closed",
|
|
wants: listOpts{
|
|
closed: true,
|
|
limit: 30,
|
|
},
|
|
},
|
|
{
|
|
name: "web",
|
|
cli: "--web",
|
|
wants: listOpts{
|
|
web: true,
|
|
limit: 30,
|
|
},
|
|
},
|
|
{
|
|
name: "json",
|
|
cli: "--format json",
|
|
wants: listOpts{
|
|
format: "json",
|
|
limit: 30,
|
|
},
|
|
},
|
|
}
|
|
|
|
t.Setenv("GH_TOKEN", "auth-token")
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ios, _, _, _ := iostreams.Test()
|
|
f := &cmdutil.Factory{
|
|
IOStreams: ios,
|
|
}
|
|
|
|
argv, err := shlex.Split(tt.cli)
|
|
assert.NoError(t, err)
|
|
|
|
var gotOpts listOpts
|
|
cmd := NewCmdList(f, func(config listConfig) error {
|
|
gotOpts = config.opts
|
|
return nil
|
|
})
|
|
|
|
cmd.SetArgs(argv)
|
|
_, err = cmd.ExecuteC()
|
|
if tt.wantsErr {
|
|
assert.Error(t, err)
|
|
assert.Equal(t, tt.wantsErrMsg, err.Error())
|
|
return
|
|
}
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, tt.wants.owner, gotOpts.owner)
|
|
assert.Equal(t, tt.wants.closed, gotOpts.closed)
|
|
assert.Equal(t, tt.wants.web, gotOpts.web)
|
|
assert.Equal(t, tt.wants.limit, gotOpts.limit)
|
|
assert.Equal(t, tt.wants.format, gotOpts.format)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRunList(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
// get user ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query UserOrgOwner.*",
|
|
"variables": map[string]interface{}{
|
|
"login": "monalisa",
|
|
},
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"user": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
"errors": []interface{}{
|
|
map[string]interface{}{
|
|
"type": "NOT_FOUND",
|
|
"path": []string{"organization"},
|
|
},
|
|
},
|
|
})
|
|
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"user": map[string]interface{}{
|
|
"login": "monalisa",
|
|
"projectsV2": map[string]interface{}{
|
|
"nodes": []interface{}{
|
|
map[string]interface{}{
|
|
"title": "Project 1",
|
|
"shortDescription": "Short description 1",
|
|
"url": "url1",
|
|
"closed": false,
|
|
"ID": "id-1",
|
|
"number": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"title": "Project 2",
|
|
"shortDescription": "",
|
|
"url": "url2",
|
|
"closed": true,
|
|
"ID": "id-2",
|
|
"number": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
|
|
ios, _, stdout, _ := iostreams.Test()
|
|
config := listConfig{
|
|
tp: tableprinter.New(ios),
|
|
opts: listOpts{
|
|
owner: "monalisa",
|
|
},
|
|
client: client,
|
|
io: ios,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(
|
|
t,
|
|
"1\tProject 1\topen\tid-1\n",
|
|
stdout.String())
|
|
}
|
|
|
|
func TestRunList_Me(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get viewer ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query ViewerOwner.*",
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
})
|
|
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"login": "monalisa",
|
|
"projectsV2": map[string]interface{}{
|
|
"nodes": []interface{}{
|
|
map[string]interface{}{
|
|
"title": "Project 1",
|
|
"shortDescription": "Short description 1",
|
|
"url": "url1",
|
|
"closed": false,
|
|
"ID": "id-1",
|
|
"number": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"title": "Project 2",
|
|
"shortDescription": "",
|
|
"url": "url2",
|
|
"closed": true,
|
|
"ID": "id-2",
|
|
"number": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
|
|
ios, _, stdout, _ := iostreams.Test()
|
|
config := listConfig{
|
|
tp: tableprinter.New(ios),
|
|
opts: listOpts{
|
|
owner: "@me",
|
|
},
|
|
client: client,
|
|
io: ios,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(
|
|
t,
|
|
"1\tProject 1\topen\tid-1\n",
|
|
stdout.String())
|
|
}
|
|
|
|
func TestRunListViewer(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get viewer ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query ViewerOwner.*",
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
})
|
|
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"login": "monalisa",
|
|
"projectsV2": map[string]interface{}{
|
|
"nodes": []interface{}{
|
|
map[string]interface{}{
|
|
"title": "Project 1",
|
|
"shortDescription": "Short description 1",
|
|
"url": "url1",
|
|
"closed": false,
|
|
"ID": "id-1",
|
|
"number": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"title": "Project 2",
|
|
"shortDescription": "",
|
|
"url": "url2",
|
|
"closed": true,
|
|
"ID": "id-2",
|
|
"number": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
|
|
ios, _, stdout, _ := iostreams.Test()
|
|
config := listConfig{
|
|
tp: tableprinter.New(ios),
|
|
opts: listOpts{},
|
|
client: client,
|
|
io: ios,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(
|
|
t,
|
|
"1\tProject 1\topen\tid-1\n",
|
|
stdout.String())
|
|
}
|
|
|
|
func TestRunListOrg(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get org ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query UserOrgOwner.*",
|
|
"variables": map[string]interface{}{
|
|
"login": "github",
|
|
},
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"organization": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
"errors": []interface{}{
|
|
map[string]interface{}{
|
|
"type": "NOT_FOUND",
|
|
"path": []string{"user"},
|
|
},
|
|
},
|
|
})
|
|
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"organization": map[string]interface{}{
|
|
"login": "monalisa",
|
|
"projectsV2": map[string]interface{}{
|
|
"nodes": []interface{}{
|
|
map[string]interface{}{
|
|
"title": "Project 1",
|
|
"shortDescription": "Short description 1",
|
|
"url": "url1",
|
|
"closed": false,
|
|
"ID": "id-1",
|
|
"number": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"title": "Project 2",
|
|
"shortDescription": "",
|
|
"url": "url2",
|
|
"closed": true,
|
|
"ID": "id-2",
|
|
"number": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
|
|
ios, _, stdout, _ := iostreams.Test()
|
|
config := listConfig{
|
|
tp: tableprinter.New(ios),
|
|
opts: listOpts{
|
|
owner: "github",
|
|
},
|
|
client: client,
|
|
io: ios,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(
|
|
t,
|
|
"1\tProject 1\topen\tid-1\n",
|
|
stdout.String())
|
|
}
|
|
|
|
func TestRunListEmpty(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get viewer ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query Viewer.*",
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"id": "an ID",
|
|
"login": "theviewer",
|
|
},
|
|
},
|
|
})
|
|
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"login": "monalisa",
|
|
"projectsV2": map[string]interface{}{
|
|
"nodes": []interface{}{},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
client := queries.NewTestClient()
|
|
|
|
ios, _, _, _ := iostreams.Test()
|
|
config := listConfig{
|
|
tp: tableprinter.New(ios),
|
|
opts: listOpts{},
|
|
client: client,
|
|
io: ios,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.EqualError(
|
|
t,
|
|
err,
|
|
"No projects found for @me")
|
|
}
|
|
|
|
func TestRunListWithClosed(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
// get user ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query UserOrgOwner.*",
|
|
"variables": map[string]interface{}{
|
|
"login": "monalisa",
|
|
},
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"user": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
"errors": []interface{}{
|
|
map[string]interface{}{
|
|
"type": "NOT_FOUND",
|
|
"path": []string{"organization"},
|
|
},
|
|
},
|
|
})
|
|
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"user": map[string]interface{}{
|
|
"login": "monalisa",
|
|
"projectsV2": map[string]interface{}{
|
|
"nodes": []interface{}{
|
|
map[string]interface{}{
|
|
"title": "Project 1",
|
|
"shortDescription": "Short description 1",
|
|
"url": "url1",
|
|
"closed": false,
|
|
"ID": "id-1",
|
|
"number": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"title": "Project 2",
|
|
"shortDescription": "",
|
|
"url": "url2",
|
|
"closed": true,
|
|
"ID": "id-2",
|
|
"number": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
|
|
ios, _, stdout, _ := iostreams.Test()
|
|
config := listConfig{
|
|
tp: tableprinter.New(ios),
|
|
opts: listOpts{
|
|
owner: "monalisa",
|
|
closed: true,
|
|
},
|
|
client: client,
|
|
io: ios,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(
|
|
t,
|
|
"1\tProject 1\topen\tid-1\n2\tProject 2\tclosed\tid-2\n",
|
|
stdout.String())
|
|
}
|
|
|
|
func TestRunListWeb_User(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
// get user ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query UserOrgOwner.*",
|
|
"variables": map[string]interface{}{
|
|
"login": "monalisa",
|
|
},
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"user": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
"errors": []interface{}{
|
|
map[string]interface{}{
|
|
"type": "NOT_FOUND",
|
|
"path": []string{"organization"},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
buf := bytes.Buffer{}
|
|
config := listConfig{
|
|
opts: listOpts{
|
|
owner: "monalisa",
|
|
web: true,
|
|
},
|
|
URLOpener: func(url string) error {
|
|
buf.WriteString(url)
|
|
return nil
|
|
},
|
|
client: client,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "https://github.com/users/monalisa/projects", buf.String())
|
|
}
|
|
|
|
func TestRunListWeb_Org(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
// get org ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query UserOrgOwner.*",
|
|
"variables": map[string]interface{}{
|
|
"login": "github",
|
|
},
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"organization": map[string]interface{}{
|
|
"id": "an ID",
|
|
},
|
|
},
|
|
"errors": []interface{}{
|
|
map[string]interface{}{
|
|
"type": "NOT_FOUND",
|
|
"path": []string{"user"},
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
buf := bytes.Buffer{}
|
|
config := listConfig{
|
|
opts: listOpts{
|
|
owner: "github",
|
|
web: true,
|
|
},
|
|
URLOpener: func(url string) error {
|
|
buf.WriteString(url)
|
|
return nil
|
|
},
|
|
client: client,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "https://github.com/orgs/github/projects", buf.String())
|
|
}
|
|
|
|
func TestRunListWeb_Me(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get viewer ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query Viewer.*",
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"id": "an ID",
|
|
"login": "theviewer",
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
buf := bytes.Buffer{}
|
|
config := listConfig{
|
|
opts: listOpts{
|
|
owner: "@me",
|
|
web: true,
|
|
},
|
|
URLOpener: func(url string) error {
|
|
buf.WriteString(url)
|
|
return nil
|
|
},
|
|
client: client,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "https://github.com/users/theviewer/projects", buf.String())
|
|
}
|
|
|
|
func TestRunListWeb_Empty(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get viewer ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query Viewer.*",
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"id": "an ID",
|
|
"login": "theviewer",
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
buf := bytes.Buffer{}
|
|
config := listConfig{
|
|
opts: listOpts{
|
|
web: true,
|
|
},
|
|
URLOpener: func(url string) error {
|
|
buf.WriteString(url)
|
|
return nil
|
|
},
|
|
client: client,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "https://github.com/users/theviewer/projects", buf.String())
|
|
}
|
|
|
|
func TestRunListWeb_Closed(t *testing.T) {
|
|
defer gock.Off()
|
|
gock.Observe(gock.DumpRequest)
|
|
|
|
// get viewer ID
|
|
gock.New("https://api.github.com").
|
|
Post("/graphql").
|
|
MatchType("json").
|
|
JSON(map[string]interface{}{
|
|
"query": "query Viewer.*",
|
|
}).
|
|
Reply(200).
|
|
JSON(map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"viewer": map[string]interface{}{
|
|
"id": "an ID",
|
|
"login": "theviewer",
|
|
},
|
|
},
|
|
})
|
|
|
|
client := queries.NewTestClient()
|
|
buf := bytes.Buffer{}
|
|
config := listConfig{
|
|
opts: listOpts{
|
|
web: true,
|
|
closed: true,
|
|
},
|
|
URLOpener: func(url string) error {
|
|
buf.WriteString(url)
|
|
return nil
|
|
},
|
|
client: client,
|
|
}
|
|
|
|
err := runList(config)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "https://github.com/users/theviewer/projects?query=is%3Aclosed", buf.String())
|
|
}
|