aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/vektah/gqlgen/client
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-09-26 15:55:14 +0200
committerMichael Muré <batolettre@gmail.com>2018-09-26 16:26:50 +0200
commitf969370901f9f6d3c71c0391c74ac933d683e784 (patch)
tree9230635ac72092f753edc06312d9319c2759f88e /vendor/github.com/vektah/gqlgen/client
parent879e147e2be0b6216a00f8141e71647a0be5b566 (diff)
downloadgit-bug-f969370901f9f6d3c71c0391c74ac933d683e784.tar.gz
graphql: add a general test for the handler/resolvers
Diffstat (limited to 'vendor/github.com/vektah/gqlgen/client')
-rw-r--r--vendor/github.com/vektah/gqlgen/client/client.go141
-rw-r--r--vendor/github.com/vektah/gqlgen/client/readme.md5
-rw-r--r--vendor/github.com/vektah/gqlgen/client/websocket.go103
3 files changed, 249 insertions, 0 deletions
diff --git a/vendor/github.com/vektah/gqlgen/client/client.go b/vendor/github.com/vektah/gqlgen/client/client.go
new file mode 100644
index 00000000..1d482700
--- /dev/null
+++ b/vendor/github.com/vektah/gqlgen/client/client.go
@@ -0,0 +1,141 @@
+// client is used internally for testing. See readme for alternatives
+package client
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// Client for graphql requests
+type Client struct {
+ url string
+ client *http.Client
+}
+
+// New creates a graphql client
+func New(url string, client ...*http.Client) *Client {
+ p := &Client{
+ url: url,
+ }
+
+ if len(client) > 0 {
+ p.client = client[0]
+ } else {
+ p.client = http.DefaultClient
+ }
+ return p
+}
+
+type Request struct {
+ Query string `json:"query"`
+ Variables map[string]interface{} `json:"variables,omitempty"`
+ OperationName string `json:"operationName,omitempty"`
+}
+
+type Option func(r *Request)
+
+func Var(name string, value interface{}) Option {
+ return func(r *Request) {
+ if r.Variables == nil {
+ r.Variables = map[string]interface{}{}
+ }
+
+ r.Variables[name] = value
+ }
+}
+
+func Operation(name string) Option {
+ return func(r *Request) {
+ r.OperationName = name
+ }
+}
+
+func (p *Client) MustPost(query string, response interface{}, options ...Option) {
+ if err := p.Post(query, response, options...); err != nil {
+ panic(err)
+ }
+}
+
+func (p *Client) mkRequest(query string, options ...Option) Request {
+ r := Request{
+ Query: query,
+ }
+
+ for _, option := range options {
+ option(&r)
+ }
+
+ return r
+}
+
+func (p *Client) Post(query string, response interface{}, options ...Option) (resperr error) {
+ r := p.mkRequest(query, options...)
+ requestBody, err := json.Marshal(r)
+ if err != nil {
+ return fmt.Errorf("encode: %s", err.Error())
+ }
+
+ rawResponse, err := p.client.Post(p.url, "application/json", bytes.NewBuffer(requestBody))
+ if err != nil {
+ return fmt.Errorf("post: %s", err.Error())
+ }
+ defer func() {
+ _ = rawResponse.Body.Close()
+ }()
+
+ if rawResponse.StatusCode >= http.StatusBadRequest {
+ responseBody, _ := ioutil.ReadAll(rawResponse.Body)
+ return fmt.Errorf("http %d: %s", rawResponse.StatusCode, responseBody)
+ }
+
+ responseBody, err := ioutil.ReadAll(rawResponse.Body)
+ if err != nil {
+ return fmt.Errorf("read: %s", err.Error())
+ }
+
+ // decode it into map string first, let mapstructure do the final decode
+ // because it can be much stricter about unknown fields.
+ respDataRaw := struct {
+ Data interface{}
+ Errors json.RawMessage
+ }{}
+ err = json.Unmarshal(responseBody, &respDataRaw)
+ if err != nil {
+ return fmt.Errorf("decode: %s", err.Error())
+ }
+
+ // we want to unpack even if there is an error, so we can see partial responses
+ unpackErr := unpack(respDataRaw.Data, response)
+
+ if respDataRaw.Errors != nil {
+ return RawJsonError{respDataRaw.Errors}
+ }
+ return unpackErr
+}
+
+type RawJsonError struct {
+ json.RawMessage
+}
+
+func (r RawJsonError) Error() string {
+ return string(r.RawMessage)
+}
+
+func unpack(data interface{}, into interface{}) error {
+ d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
+ Result: into,
+ TagName: "json",
+ ErrorUnused: true,
+ ZeroFields: true,
+ })
+ if err != nil {
+ return fmt.Errorf("mapstructure: %s", err.Error())
+ }
+
+ return d.Decode(data)
+}
diff --git a/vendor/github.com/vektah/gqlgen/client/readme.md b/vendor/github.com/vektah/gqlgen/client/readme.md
new file mode 100644
index 00000000..755a1433
--- /dev/null
+++ b/vendor/github.com/vektah/gqlgen/client/readme.md
@@ -0,0 +1,5 @@
+This client is used internally for testing. I wanted a simple graphql client sent user specified queries.
+
+You might want to look at:
+ - https://github.com/shurcooL/graphql: Uses reflection to build queries from structs.
+ - https://github.com/machinebox/graphql: Probably would have been a perfect fit, but it uses form encoding instead of json...
diff --git a/vendor/github.com/vektah/gqlgen/client/websocket.go b/vendor/github.com/vektah/gqlgen/client/websocket.go
new file mode 100644
index 00000000..bd92e3c0
--- /dev/null
+++ b/vendor/github.com/vektah/gqlgen/client/websocket.go
@@ -0,0 +1,103 @@
+package client
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/gorilla/websocket"
+ "github.com/vektah/gqlparser/gqlerror"
+)
+
+const (
+ connectionInitMsg = "connection_init" // Client -> Server
+ startMsg = "start" // Client -> Server
+ connectionAckMsg = "connection_ack" // Server -> Client
+ dataMsg = "data" // Server -> Client
+ errorMsg = "error" // Server -> Client
+)
+
+type operationMessage struct {
+ Payload json.RawMessage `json:"payload,omitempty"`
+ ID string `json:"id,omitempty"`
+ Type string `json:"type"`
+}
+
+type Subscription struct {
+ Close func() error
+ Next func(response interface{}) error
+}
+
+func errorSubscription(err error) *Subscription {
+ return &Subscription{
+ Close: func() error { return nil },
+ Next: func(response interface{}) error {
+ return err
+ },
+ }
+}
+
+func (p *Client) Websocket(query string, options ...Option) *Subscription {
+ r := p.mkRequest(query, options...)
+ requestBody, err := json.Marshal(r)
+ if err != nil {
+ return errorSubscription(fmt.Errorf("encode: %s", err.Error()))
+ }
+
+ url := strings.Replace(p.url, "http://", "ws://", -1)
+ url = strings.Replace(url, "https://", "wss://", -1)
+
+ c, _, err := websocket.DefaultDialer.Dial(url, nil)
+ if err != nil {
+ return errorSubscription(fmt.Errorf("dial: %s", err.Error()))
+ }
+
+ if err = c.WriteJSON(operationMessage{Type: connectionInitMsg}); err != nil {
+ return errorSubscription(fmt.Errorf("init: %s", err.Error()))
+ }
+
+ var ack operationMessage
+ if err = c.ReadJSON(&ack); err != nil {
+ return errorSubscription(fmt.Errorf("ack: %s", err.Error()))
+ }
+ if ack.Type != connectionAckMsg {
+ return errorSubscription(fmt.Errorf("expected ack message, got %#v", ack))
+ }
+
+ if err = c.WriteJSON(operationMessage{Type: startMsg, ID: "1", Payload: requestBody}); err != nil {
+ return errorSubscription(fmt.Errorf("start: %s", err.Error()))
+ }
+
+ return &Subscription{
+ Close: c.Close,
+ Next: func(response interface{}) error {
+ var op operationMessage
+ c.ReadJSON(&op)
+ if op.Type != dataMsg {
+ if op.Type == errorMsg {
+ return fmt.Errorf(string(op.Payload))
+ } else {
+ return fmt.Errorf("expected data message, got %#v", op)
+ }
+ }
+
+ respDataRaw := map[string]interface{}{}
+ err = json.Unmarshal(op.Payload, &respDataRaw)
+ if err != nil {
+ return fmt.Errorf("decode: %s", err.Error())
+ }
+
+ if respDataRaw["errors"] != nil {
+ var errs []*gqlerror.Error
+ if err = unpack(respDataRaw["errors"], &errs); err != nil {
+ return err
+ }
+ if len(errs) > 0 {
+ return fmt.Errorf("errors: %s", errs)
+ }
+ }
+
+ return unpack(respDataRaw["data"], response)
+ },
+ }
+}