Merge pull request #14 from github/test

Add test for `gh pr list`
This commit is contained in:
Corey Johnson 2019-10-16 11:28:08 -07:00 committed by GitHub
commit 0e18bb6492
15 changed files with 237 additions and 4 deletions

View file

@ -21,7 +21,7 @@ type graphQLResponse struct {
}
/*
graphQL usage
GraphQL: Declared as an external variable so it can be mocked in tests
type repoResponse struct {
Repository struct {
@ -45,7 +45,7 @@ if err != nil {
fmt.Printf("%+v\n", resp)
*/
func graphQL(query string, variables map[string]string, data interface{}) error {
var GraphQL = func(query string, variables map[string]string, data interface{}) error {
url := "https://api.github.com/graphql"
reqBody, err := json.Marshal(map[string]interface{}{"query": query, "variables": variables})
if err != nil {

View file

@ -98,7 +98,7 @@ func PullRequests() (PullRequestsPayload, error) {
}
var resp response
err := graphQL(query, variables, &resp)
err := GraphQL(query, variables, &resp)
if err != nil {
return PullRequestsPayload{}, err
}
@ -133,7 +133,6 @@ func project() github.Project {
if error != nil {
panic(error)
}
for _, remote := range remotes {
if project, error := remote.Project(); error == nil {
return *project

34
command/pr_test.go Normal file
View file

@ -0,0 +1,34 @@
package command
import (
"regexp"
"testing"
"github.com/github/gh-cli/test"
)
func TestPRList(t *testing.T) {
teardown := test.MockGraphQLResponse("test/fixtures/pr.json")
defer teardown()
gitRepo := test.UseTempGitRepo()
defer gitRepo.TearDown()
output, err := test.RunCommand(RootCmd, "pr list")
if err != nil {
t.Errorf("error running command `pr list`: %v", err)
}
expectedPrs := []*regexp.Regexp{
regexp.MustCompile(`#8.*\[strawberries\]`),
regexp.MustCompile(`#9.*\[apples\]`),
regexp.MustCompile(`#10.*\[blueberries\]`),
regexp.MustCompile(`#11.*\[figs\]`),
}
for _, r := range expectedPrs {
if !r.MatchString(output) {
t.Errorf("output did not match regexp /%s/", r)
}
}
}

50
test/fixtures/pr.json vendored Normal file
View file

@ -0,0 +1,50 @@
{
"repository": {
"pullRequests": {
"edges": [
{
"node": {
"number": 10,
"title": "Blueberries are a good fruit",
"url": "https://github.com/github/gh-cli/pull/10",
"headRefName": "[blueberries]"
}
}
]
}
},
"viewerCreated": {
"edges": [
{
"node": {
"number": 8,
"title": "Strawberries are not actually berries",
"url": "https://github.com/github/gh-cli/pull/8",
"headRefName": "[strawberries]"
}
}
],
"pageInfo": { "hasNextPage": false }
},
"reviewRequested": {
"edges": [
{
"node": {
"number": 9,
"title": "Apples are tasty",
"url": "https://github.com/github/gh-cli/pull/9",
"headRefName": "[apples]"
}
},
{
"node": {
"number": 11,
"title": "Figs are my favorite",
"url": "https://github.com/github/gh-cli/pull/1",
"headRefName": "[figs]"
}
}
],
"pageInfo": { "hasNextPage": false }
}
}

1
test/fixtures/test.git/HEAD vendored Normal file
View file

@ -0,0 +1 @@
ref: refs/heads/master

6
test/fixtures/test.git/config vendored Normal file
View file

@ -0,0 +1,6 @@
[core]
repositoryformatversion = 0
filemode = true
bare = true
ignorecase = true
precomposeunicode = false

6
test/fixtures/test.git/info/exclude vendored Normal file
View file

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View file

@ -0,0 +1,3 @@
x<01><>M
Â0F]çseb~œ€ˆnÝx™¦cMi¨)^ß 7pó>xðñbÉ9UÐä7ub{ŽÖbgÙ´íă#h8<68>÷<01>âµ>Ë×4o™áöÅ
Çñ'ÊyÈœ¦],ùÚ„½Fkœ†-¢j¶U«üûW—¾‡*¯z¤IÔ)”;â

View file

@ -0,0 +1,3 @@
x<01><>K
1D]η}¥3ι$qεBΟ<>dq&#^ίρs7UPΕ«XΖqhΠ/ZM Άw*<2A>cbc±G”3ΩΛ½ΦYηΠI<CEA0>βζk<CEB6> g
6-U<>s4iΦ6³1χFΆμ#Y,ό£<CF8C>K…ύ0<CF8D><30>iγG°Ύ|ƒ²=<3D>~Έ®b7 •λ$b KdD1§3eK<65>φΕn¨χο™Z<>σΥ<CF83>{Nm

View file

@ -0,0 +1 @@
9b5a719a3d76ac9dc2fa635d9b1f34fd73994c06

130
test/helpers.go Normal file
View file

@ -0,0 +1,130 @@
package test
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/github/gh-cli/api"
"github.com/github/gh-cli/github"
"github.com/spf13/cobra"
)
type TempGitRepo struct {
Remote string
TearDown func()
}
func UseTempGitRepo() *TempGitRepo {
github.CreateTestConfigs("mario", "i-love-peach")
pwd, _ := os.Getwd()
oldEnv := make(map[string]string)
overrideEnv := func(name, value string) {
oldEnv[name] = os.Getenv(name)
os.Setenv(name, value)
}
remotePath := filepath.Join(pwd, "..", "test", "fixtures", "test.git")
home, err := ioutil.TempDir("", "test-repo")
if err != nil {
panic(err)
}
overrideEnv("HOME", home)
overrideEnv("XDG_CONFIG_HOME", "")
overrideEnv("XDG_CONFIG_DIRS", "")
targetPath := filepath.Join(home, "test.git")
cmd := exec.Command("git", "clone", remotePath, targetPath)
if output, err := cmd.Output(); err != nil {
panic(fmt.Errorf("error running %s\n%s\n%s", cmd, err, output))
}
if err = os.Chdir(targetPath); err != nil {
panic(err)
}
// Our libs expect the origin to be a github url
cmd = exec.Command("git", "remote", "set-url", "origin", "https://github.com/github/FAKE-GITHUB-REPO-NAME")
if output, err := cmd.Output(); err != nil {
panic(fmt.Errorf("error running %s\n%s\n%s", cmd, err, output))
}
tearDown := func() {
if err := os.Chdir(pwd); err != nil {
panic(err)
}
for name, value := range oldEnv {
os.Setenv(name, value)
}
if err = os.RemoveAll(home); err != nil {
panic(err)
}
}
return &TempGitRepo{Remote: remotePath, TearDown: tearDown}
}
func MockGraphQLResponse(fixturePath string) (teardown func()) {
pwd, _ := os.Getwd()
fixturePath = filepath.Join(pwd, "..", fixturePath)
originalGraphQL := api.GraphQL
api.GraphQL = func(query string, variables map[string]string, v interface{}) error {
contents, err := ioutil.ReadFile(fixturePath)
if err != nil {
return err
}
json.Unmarshal(contents, &v)
if err != nil {
return err
}
return nil
}
return func() {
api.GraphQL = originalGraphQL
}
}
func RunCommand(root *cobra.Command, s string) (string, error) {
var err error
output := captureOutput(func() {
root.SetArgs(strings.Split(s, " "))
_, err = root.ExecuteC()
})
if err != nil {
return "", err
}
return output, nil
}
func captureOutput(f func()) string {
originalStdout := os.Stdout
defer func() {
os.Stdout = originalStdout
}()
r, w, err := os.Pipe()
if err != nil {
panic("failed to pipe stdout")
}
os.Stdout = w
f()
w.Close()
out, err := ioutil.ReadAll(r)
if err != nil {
panic("failed to read captured input from stdout")
}
return string(out)
}