github.com/geneva/gqlgen@v0.17.7-0.20230801155730-7b9317164836/client/client_test.go (about)

     1  package client_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"mime/multipart"
     9  	"net/http"
    10  	"net/textproto"
    11  	"reflect"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/geneva/gqlgen/client"
    16  	"github.com/mitchellh/mapstructure"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestClient(t *testing.T) {
    21  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    22  		b, err := io.ReadAll(r.Body)
    23  		if err != nil {
    24  			panic(err)
    25  		}
    26  		require.Equal(t, `{"query":"user(id:$id){name}","variables":{"id":1}}`, string(b))
    27  
    28  		err = json.NewEncoder(w).Encode(map[string]interface{}{
    29  			"data": map[string]interface{}{
    30  				"name": "bob",
    31  			},
    32  		})
    33  		if err != nil {
    34  			panic(err)
    35  		}
    36  	})
    37  
    38  	c := client.New(h)
    39  
    40  	var resp struct {
    41  		Name string
    42  	}
    43  
    44  	c.MustPost("user(id:$id){name}", &resp, client.Var("id", 1))
    45  
    46  	require.Equal(t, "bob", resp.Name)
    47  }
    48  
    49  func TestClientMultipartFormData(t *testing.T) {
    50  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    51  		bodyBytes, err := io.ReadAll(r.Body)
    52  		require.NoError(t, err)
    53  		require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="operations"`)
    54  		require.Contains(t, string(bodyBytes), `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`)
    55  		require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="map"`)
    56  		require.Contains(t, string(bodyBytes), `{"0":["variables.file"]}`)
    57  		require.Contains(t, string(bodyBytes), `Content-Disposition: form-data; name="0"; filename="example.txt"`)
    58  		require.Contains(t, string(bodyBytes), `Content-Type: text/plain`)
    59  		require.Contains(t, string(bodyBytes), `Hello World`)
    60  
    61  		w.Write([]byte(`{}`))
    62  	})
    63  
    64  	c := client.New(h)
    65  
    66  	var resp struct{}
    67  	c.MustPost("{ id }", &resp,
    68  		func(bd *client.Request) {
    69  			bodyBuf := &bytes.Buffer{}
    70  			bodyWriter := multipart.NewWriter(bodyBuf)
    71  			bodyWriter.WriteField("operations", `{"query":"mutation ($input: Input!) {}","variables":{"file":{}}`)
    72  			bodyWriter.WriteField("map", `{"0":["variables.file"]}`)
    73  
    74  			h := make(textproto.MIMEHeader)
    75  			h.Set("Content-Disposition", `form-data; name="0"; filename="example.txt"`)
    76  			h.Set("Content-Type", "text/plain")
    77  			ff, _ := bodyWriter.CreatePart(h)
    78  			ff.Write([]byte("Hello World"))
    79  			bodyWriter.Close()
    80  
    81  			bd.HTTP.Body = io.NopCloser(bodyBuf)
    82  			bd.HTTP.Header.Set("Content-Type", bodyWriter.FormDataContentType())
    83  		},
    84  	)
    85  }
    86  
    87  func TestAddHeader(t *testing.T) {
    88  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    89  		require.Equal(t, "ASDF", r.Header.Get("Test-Key"))
    90  
    91  		w.Write([]byte(`{}`))
    92  	})
    93  
    94  	c := client.New(h)
    95  
    96  	var resp struct{}
    97  	c.MustPost("{ id }", &resp,
    98  		client.AddHeader("Test-Key", "ASDF"),
    99  	)
   100  }
   101  
   102  func TestAddClientHeader(t *testing.T) {
   103  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   104  		require.Equal(t, "ASDF", r.Header.Get("Test-Key"))
   105  
   106  		w.Write([]byte(`{}`))
   107  	})
   108  
   109  	c := client.New(h, client.AddHeader("Test-Key", "ASDF"))
   110  
   111  	var resp struct{}
   112  	c.MustPost("{ id }", &resp)
   113  }
   114  
   115  func TestBasicAuth(t *testing.T) {
   116  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   117  		user, pass, ok := r.BasicAuth()
   118  		require.True(t, ok)
   119  		require.Equal(t, "user", user)
   120  		require.Equal(t, "pass", pass)
   121  
   122  		w.Write([]byte(`{}`))
   123  	})
   124  
   125  	c := client.New(h)
   126  
   127  	var resp struct{}
   128  	c.MustPost("{ id }", &resp,
   129  		client.BasicAuth("user", "pass"),
   130  	)
   131  }
   132  
   133  func TestAddCookie(t *testing.T) {
   134  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   135  		c, err := r.Cookie("foo")
   136  		require.NoError(t, err)
   137  		require.Equal(t, "value", c.Value)
   138  
   139  		w.Write([]byte(`{}`))
   140  	})
   141  
   142  	c := client.New(h)
   143  
   144  	var resp struct{}
   145  	c.MustPost("{ id }", &resp,
   146  		client.AddCookie(&http.Cookie{Name: "foo", Value: "value"}),
   147  	)
   148  }
   149  
   150  func TestAddExtensions(t *testing.T) {
   151  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   152  		b, err := io.ReadAll(r.Body)
   153  		if err != nil {
   154  			panic(err)
   155  		}
   156  		require.Equal(t, `{"query":"user(id:1){name}","extensions":{"persistedQuery":{"sha256Hash":"ceec2897e2da519612279e63f24658c3e91194cbb2974744fa9007a7e1e9f9e7","version":1}}}`, string(b))
   157  		err = json.NewEncoder(w).Encode(map[string]interface{}{
   158  			"data": map[string]interface{}{
   159  				"Name": "Bob",
   160  			},
   161  		})
   162  		if err != nil {
   163  			panic(err)
   164  		}
   165  	})
   166  
   167  	c := client.New(h)
   168  
   169  	var resp struct {
   170  		Name string
   171  	}
   172  	c.MustPost("user(id:1){name}", &resp,
   173  		client.Extensions(map[string]interface{}{"persistedQuery": map[string]interface{}{"version": 1, "sha256Hash": "ceec2897e2da519612279e63f24658c3e91194cbb2974744fa9007a7e1e9f9e7"}}),
   174  	)
   175  }
   176  
   177  func TestSetCustomDecodeConfig(t *testing.T) {
   178  	now := time.Now()
   179  
   180  	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   181  		w.WriteHeader(http.StatusOK)
   182  		w.Header().Set("Content-Type", "application/json")
   183  		w.Write([]byte(fmt.Sprintf(`{"data": {"created_at":"%s"}}`, now.Format(time.RFC3339))))
   184  	})
   185  
   186  	dc := &mapstructure.DecoderConfig{
   187  		TagName:     "json",
   188  		ErrorUnused: true,
   189  		ZeroFields:  true,
   190  		DecodeHook: func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
   191  			if t != reflect.TypeOf(time.Time{}) {
   192  				return data, nil
   193  			}
   194  
   195  			switch f.Kind() {
   196  			case reflect.String:
   197  				return time.Parse(time.RFC3339, data.(string))
   198  			default:
   199  				return data, nil
   200  			}
   201  		},
   202  	}
   203  
   204  	c := client.New(h)
   205  
   206  	var resp struct {
   207  		CreatedAt time.Time `json:"created_at"`
   208  	}
   209  
   210  	err := c.Post("user(id: 1) {created_at}", &resp)
   211  	require.Error(t, err)
   212  
   213  	c.SetCustomDecodeConfig(dc)
   214  
   215  	c.MustPost("user(id: 1) {created_at}", &resp)
   216  	require.WithinDuration(t, now, resp.CreatedAt, time.Second)
   217  }