Skip to content

Commit

Permalink
Migrate from httpmock to gock (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
samcoe committed May 9, 2022
1 parent c41a127 commit 234a47d
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 371 deletions.
60 changes: 35 additions & 25 deletions gh_test.go
Expand Up @@ -3,12 +3,13 @@ package gh
import (
"fmt"
"os"
"strings"
"testing"

"github.com/cli/go-gh/internal/config"
"github.com/cli/go-gh/internal/httpmock"
"github.com/cli/go-gh/pkg/api"
"github.com/stretchr/testify/assert"
"gopkg.in/h2non/gock.v1"
)

func TestHelperProcess(t *testing.T) {
Expand Down Expand Up @@ -47,6 +48,7 @@ func TestRunError(t *testing.T) {
}

func TestRESTClient(t *testing.T) {
t.Cleanup(gock.Off)
tempDir := t.TempDir()
orig_GH_CONFIG_DIR := os.Getenv("GH_CONFIG_DIR")
orig_GH_TOKEN := os.Getenv("GH_TOKEN")
Expand All @@ -57,24 +59,24 @@ func TestRESTClient(t *testing.T) {
os.Setenv("GH_CONFIG_DIR", tempDir)
os.Setenv("GH_TOKEN", "GH_TOKEN")

http := httpmock.NewRegistry(t)
http.Register(
httpmock.REST("GET", "some/test/path"),
httpmock.StatusStringResponse(200, `{"message": "success"}`),
)
gock.New("https://api.github.com").
Get("/some/test/path").
MatchHeader("Authorization", "token GH_TOKEN").
Reply(200).
JSON(`{"message": "success"}`)

client, err := RESTClient(&api.ClientOptions{Transport: http})
client, err := RESTClient(nil)
assert.NoError(t, err)

res := struct{ Message string }{}
err = client.Do("GET", "some/test/path", nil, &res)
assert.NoError(t, err)
assert.True(t, gock.IsDone(), printPendingMocks(gock.Pending()))
assert.Equal(t, "success", res.Message)
assert.Equal(t, "api.github.com", http.Requests[0].URL.Hostname())
assert.Equal(t, "token GH_TOKEN", http.Requests[0].Header.Get("Authorization"))
}

func TestGQLClient(t *testing.T) {
t.Cleanup(gock.Off)
tempDir := t.TempDir()
orig_GH_CONFIG_DIR := os.Getenv("GH_CONFIG_DIR")
orig_GH_TOKEN := os.Getenv("GH_TOKEN")
Expand All @@ -85,25 +87,26 @@ func TestGQLClient(t *testing.T) {
os.Setenv("GH_CONFIG_DIR", tempDir)
os.Setenv("GH_TOKEN", "GH_TOKEN")

http := httpmock.NewRegistry(t)
http.Register(
httpmock.GQL("QUERY"),
httpmock.StringResponse(`{"data":{"viewer":{"login":"hubot"}}}`),
)
gock.New("https://api.github.com").
Post("/graphql").
MatchHeader("Authorization", "token GH_TOKEN").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(200).
JSON(`{"data":{"viewer":{"login":"hubot"}}}`)

client, err := GQLClient(&api.ClientOptions{Transport: http})
client, err := GQLClient(nil)
assert.NoError(t, err)

vars := map[string]interface{}{"var": "test"}
res := struct{ Viewer struct{ Login string } }{}
err = client.Do("QUERY", vars, &res)
assert.NoError(t, err)
assert.True(t, gock.IsDone(), printPendingMocks(gock.Pending()))
assert.Equal(t, "hubot", res.Viewer.Login)
assert.Equal(t, "api.github.com", http.Requests[0].URL.Hostname())
assert.Equal(t, "token GH_TOKEN", http.Requests[0].Header.Get("Authorization"))
}

func TestHTTPClient(t *testing.T) {
t.Cleanup(gock.Off)
tempDir := t.TempDir()
orig_GH_CONFIG_DIR := os.Getenv("GH_CONFIG_DIR")
orig_GH_TOKEN := os.Getenv("GH_TOKEN")
Expand All @@ -114,20 +117,19 @@ func TestHTTPClient(t *testing.T) {
os.Setenv("GH_CONFIG_DIR", tempDir)
os.Setenv("GH_TOKEN", "GH_TOKEN")

http := httpmock.NewRegistry(t)
http.Register(
httpmock.REST("GET", "some/test/path"),
httpmock.StatusStringResponse(200, `{"message": "success"}`),
)
gock.New("https://api.github.com").
Get("/some/test/path").
MatchHeader("Authorization", "token GH_TOKEN").
Reply(200).
JSON(`{"message": "success"}`)

client, err := HTTPClient(&api.ClientOptions{Transport: http})
client, err := HTTPClient(nil)
assert.NoError(t, err)

res, err := client.Get("https://api.github.com/some/test/path")
assert.NoError(t, err)
assert.True(t, gock.IsDone(), printPendingMocks(gock.Pending()))
assert.Equal(t, 200, res.StatusCode)
assert.Equal(t, "api.github.com", http.Requests[0].URL.Hostname())
assert.Equal(t, "token GH_TOKEN", http.Requests[0].Header.Get("Authorization"))
}

func TestResolveOptions(t *testing.T) {
Expand Down Expand Up @@ -177,3 +179,11 @@ hosts:
cfg, _ := config.FromString(data)
return cfg
}

func printPendingMocks(mocks []gock.Mock) string {
paths := []string{}
for _, mock := range mocks {
paths = append(paths, mock.Request().URLStruct.String())
}
return fmt.Sprintf("%d unmatched mocks: %s", len(paths), strings.Join(paths, ", "))
}
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -10,5 +10,6 @@ require (
github.com/kr/pretty v0.1.0 // indirect
github.com/stretchr/testify v1.7.0
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/h2non/gock.v1 v1.1.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
5 changes: 5 additions & 0 deletions go.sum
Expand Up @@ -6,13 +6,16 @@ github.com/cli/shurcooL-graphql v0.0.1 h1:/9J3t9O6p1B8zdBBtQighq5g7DQRItBwuwGh3S
github.com/cli/shurcooL-graphql v0.0.1/go.mod h1:U7gCSuMZP/Qy7kbqkk5PrqXEeDgtfG5K+W+u8weorps=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs=
github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand All @@ -28,6 +31,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
89 changes: 59 additions & 30 deletions internal/api/gql_client_test.go
Expand Up @@ -3,83 +3,112 @@ package api
import (
"testing"

"github.com/cli/go-gh/internal/httpmock"
"github.com/cli/go-gh/pkg/api"
"github.com/stretchr/testify/assert"
"gopkg.in/h2non/gock.v1"
)

func TestGQLClientDo(t *testing.T) {
tests := []struct {
name string
host string
matcher httpmock.Matcher
responder httpmock.Responder
httpMocks func()
wantErr bool
wantErrMsg string
wantHost string
wantLogin string
}{
{
name: "success request",
responder: httpmock.StringResponse(`{"data":{"viewer":{"login":"hubot"}}}`),
name: "success request",
httpMocks: func() {
gock.New("https://api.github.com").
Post("/graphql").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(200).
JSON(`{"data":{"viewer":{"login":"hubot"}}}`)
},
wantLogin: "hubot",
},
{
name: "fail request",
responder: httpmock.StringResponse(`{"errors":[{"message":"OH NO"},{"message":"this is fine"}]}`),
name: "fail request",
httpMocks: func() {
gock.New("https://api.github.com").
Post("/graphql").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(200).
JSON(`{"errors":[{"message":"OH NO"},{"message":"this is fine"}]}`)
},
wantErr: true,
wantErrMsg: "GQL error: OH NO\nthis is fine",
},
{
name: "http fail request empty response",
responder: httpmock.StatusStringResponse(404, `{}`),
name: "http fail request empty response",
httpMocks: func() {
gock.New("https://api.github.com").
Post("/graphql").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(404).
JSON(`{}`)
},
wantErr: true,
wantErrMsg: "HTTP 404 (https://api.github.com/graphql)",
},
{
name: "http fail request message response",
responder: httpmock.StatusStringResponse(422, `{"message": "OH NO"}`),
name: "http fail request message response",
httpMocks: func() {
gock.New("https://api.github.com").
Post("/graphql").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(422).
JSON(`{"message": "OH NO"}`)
},
wantErr: true,
wantErrMsg: "HTTP 422: OH NO (https://api.github.com/graphql)",
},
{
name: "http fail request errors response",
responder: httpmock.StatusStringResponse(502, `{"errors":[{"message":"Something went wrong"}]}`),
name: "http fail request errors response",
httpMocks: func() {
gock.New("https://api.github.com").
Post("/graphql").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(502).
JSON(`{"errors":[{"message":"Something went wrong"}]}`)
},
wantErr: true,
wantErrMsg: "HTTP 502: Something went wrong (https://api.github.com/graphql)",
},
{
name: "support enterprise hosts",
responder: httpmock.StatusStringResponse(204, "{}"),
host: "enterprise.com",
wantHost: "enterprise.com",
name: "support enterprise hosts",
host: "enterprise.com",
httpMocks: func() {
gock.New("https://enterprise.com").
Post("/api/graphql").
BodyString(`{"query":"QUERY","variables":{"var":"test"}}`).
Reply(200).
JSON(`{"data":{"viewer":{"login":"hubot"}}}`)
},
wantLogin: "hubot",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Cleanup(gock.Off)
if tt.host == "" {
tt.host = "github.com"
}
if tt.wantHost == "" {
tt.wantHost = "api.github.com"
if tt.httpMocks != nil {
tt.httpMocks()
}
http := httpmock.NewRegistry(t)
client := NewGQLClient(tt.host, &api.ClientOptions{Transport: http})
http.Register(
httpmock.GQL("QUERY"),
tt.responder,
)
client := NewGQLClient(tt.host, nil)
vars := map[string]interface{}{"var": "test"}
res := struct{ Viewer struct{ Login string } }{}
err := client.Do("QUERY", vars, &res)
if tt.wantErr {
assert.EqualError(t, err, tt.wantErrMsg)
return
} else {
assert.NoError(t, err)
}
assert.NoError(t, err)
assert.True(t, gock.IsDone(), printPendingMocks(gock.Pending()))
assert.Equal(t, tt.wantLogin, res.Viewer.Login)
assert.Equal(t, tt.wantHost, http.Requests[0].URL.Hostname())
})
}
}

0 comments on commit 234a47d

Please sign in to comment.