github.com/deliveroo/gqlgen@v0.7.2/example/todo/todo_test.go (about)

     1  package todo
     2  
     3  import (
     4  	"net/http/httptest"
     5  	"testing"
     6  
     7  	"github.com/99designs/gqlgen/client"
     8  	"github.com/99designs/gqlgen/graphql/introspection"
     9  	"github.com/99designs/gqlgen/handler"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestTodo(t *testing.T) {
    14  	srv := httptest.NewServer(handler.GraphQL(NewExecutableSchema(New())))
    15  	c := client.New(srv.URL)
    16  
    17  	var resp struct {
    18  		CreateTodo struct{ ID int }
    19  	}
    20  	c.MustPost(`mutation { createTodo(todo:{text:"Fery important"}) { id } }`, &resp)
    21  
    22  	require.Equal(t, 5, resp.CreateTodo.ID)
    23  
    24  	t.Run("update the todo text", func(t *testing.T) {
    25  		var resp struct {
    26  			UpdateTodo struct{ Text string }
    27  		}
    28  		c.MustPost(
    29  			`mutation($id: Int!, $text: String!) { updateTodo(id: $id, changes:{text:$text}) { text } }`,
    30  			&resp,
    31  			client.Var("id", 5),
    32  			client.Var("text", "Very important"),
    33  		)
    34  
    35  		require.Equal(t, "Very important", resp.UpdateTodo.Text)
    36  	})
    37  
    38  	t.Run("get __typename", func(t *testing.T) {
    39  		var resp struct {
    40  			Todo struct {
    41  				Typename string `json:"__typename"`
    42  			}
    43  		}
    44  		c.MustPost(`{ todo(id: 5) { __typename } }`, &resp)
    45  
    46  		require.Equal(t, "Todo", resp.Todo.Typename)
    47  	})
    48  
    49  	t.Run("update the todo status", func(t *testing.T) {
    50  		var resp struct {
    51  			UpdateTodo struct{ Text string }
    52  		}
    53  		c.MustPost(`mutation { updateTodo(id: 5, changes:{done:true}) { text } }`, &resp)
    54  
    55  		require.Equal(t, "Very important", resp.UpdateTodo.Text)
    56  	})
    57  
    58  	t.Run("select with alias", func(t *testing.T) {
    59  		var resp struct {
    60  			A struct{ Text string }
    61  			B struct{ ID int }
    62  		}
    63  		c.MustPost(`{ a: todo(id:1) { text } b: todo(id:2) { id } }`, &resp)
    64  
    65  		require.Equal(t, "A todo not to forget", resp.A.Text)
    66  		require.Equal(t, 2, resp.B.ID)
    67  	})
    68  
    69  	t.Run("find a missing todo", func(t *testing.T) {
    70  		var resp struct {
    71  			Todo *struct{ Text string }
    72  		}
    73  		err := c.Post(`{ todo(id:99) { text } }`, &resp)
    74  
    75  		require.Error(t, err)
    76  		require.Nil(t, resp.Todo)
    77  	})
    78  
    79  	t.Run("get done status of unowned todo", func(t *testing.T) {
    80  		var resp struct {
    81  			Todo *struct {
    82  				Text string
    83  				Done bool
    84  			}
    85  		}
    86  		err := c.Post(`{ todo(id:3) { text, done } }`, &resp)
    87  
    88  		require.EqualError(t, err, `[{"message":"you dont own that","path":["todo","done"]}]`)
    89  		require.Nil(t, resp.Todo)
    90  	})
    91  
    92  	t.Run("test panic", func(t *testing.T) {
    93  		var resp struct {
    94  			Todo *struct{ Text string }
    95  		}
    96  		err := c.Post(`{ todo(id:666) { text } }`, &resp)
    97  
    98  		require.EqualError(t, err, `[{"message":"internal system error","path":["todo"]}]`)
    99  	})
   100  
   101  	t.Run("select all", func(t *testing.T) {
   102  		var resp struct {
   103  			Todo struct {
   104  				ID   int
   105  				Text string
   106  				Done bool
   107  			}
   108  			LastTodo struct {
   109  				ID   int
   110  				Text string
   111  				Done bool
   112  			}
   113  			Todos []struct {
   114  				ID   int
   115  				Text string
   116  			}
   117  		}
   118  		c.MustPost(`{
   119  			todo(id:1) { id done text }
   120  			lastTodo { id text done }
   121  			todos { id text }
   122  		}`, &resp)
   123  
   124  		require.Equal(t, 1, resp.Todo.ID)
   125  		require.Equal(t, 5, resp.LastTodo.ID)
   126  		require.Len(t, resp.Todos, 5)
   127  		require.Equal(t, "Very important", resp.LastTodo.Text)
   128  		require.Equal(t, 5, resp.LastTodo.ID)
   129  	})
   130  
   131  	t.Run("introspection", func(t *testing.T) {
   132  		// Make sure we can run the graphiql introspection query without errors
   133  		var resp interface{}
   134  		c.MustPost(introspection.Query, &resp)
   135  	})
   136  
   137  	t.Run("null optional field", func(t *testing.T) {
   138  		var resp struct {
   139  			CreateTodo struct{ Text string }
   140  		}
   141  		c.MustPost(`mutation { createTodo(todo:{text:"Completed todo", done: null}) { text } }`, &resp)
   142  
   143  		require.Equal(t, "Completed todo", resp.CreateTodo.Text)
   144  	})
   145  }
   146  
   147  func TestSkipAndIncludeDirectives(t *testing.T) {
   148  	srv := httptest.NewServer(handler.GraphQL(NewExecutableSchema(New())))
   149  	c := client.New(srv.URL)
   150  
   151  	t.Run("skip on field", func(t *testing.T) {
   152  		var resp map[string]interface{}
   153  		c.MustPost(`{ todo(id: 1) @skip(if:true) { __typename } }`, &resp)
   154  		_, ok := resp["todo"]
   155  		require.False(t, ok)
   156  	})
   157  
   158  	t.Run("skip on variable", func(t *testing.T) {
   159  		q := `query Test($cond: Boolean!) { todo(id: 1) @skip(if: $cond) { __typename } }`
   160  		var resp map[string]interface{}
   161  
   162  		c.MustPost(q, &resp, client.Var("cond", true))
   163  		_, ok := resp["todo"]
   164  		require.False(t, ok)
   165  
   166  		c.MustPost(q, &resp, client.Var("cond", false))
   167  		_, ok = resp["todo"]
   168  		require.True(t, ok)
   169  	})
   170  
   171  	t.Run("skip on inline fragment", func(t *testing.T) {
   172  		var resp struct {
   173  			Todo struct {
   174  				Typename string `json:"__typename"`
   175  			}
   176  		}
   177  		c.MustPost(`{ todo(id: 1) {
   178  				...@skip(if:true) {
   179  					__typename
   180  				}
   181  			}
   182  		}`, &resp)
   183  		require.Empty(t, resp.Todo.Typename)
   184  	})
   185  
   186  	t.Run("skip on fragment", func(t *testing.T) {
   187  		var resp struct {
   188  			Todo struct {
   189  				Typename string `json:"__typename"`
   190  			}
   191  		}
   192  		c.MustPost(`
   193  		{
   194  			todo(id: 1) {
   195  				...todoFragment @skip(if:true)
   196  			}
   197  		}
   198  		fragment todoFragment on Todo {
   199  			__typename
   200  		}
   201  		`, &resp)
   202  		require.Empty(t, resp.Todo.Typename)
   203  	})
   204  
   205  	t.Run("include on field", func(t *testing.T) {
   206  		q := `query Test($cond: Boolean!) { todo(id: 1) @include(if: $cond) { __typename } }`
   207  		var resp map[string]interface{}
   208  
   209  		c.MustPost(q, &resp, client.Var("cond", true))
   210  		_, ok := resp["todo"]
   211  		require.True(t, ok)
   212  
   213  		c.MustPost(q, &resp, client.Var("cond", false))
   214  		_, ok = resp["todo"]
   215  		require.False(t, ok)
   216  	})
   217  
   218  	t.Run("both skip and include defined", func(t *testing.T) {
   219  		type TestCase struct {
   220  			Skip     bool
   221  			Include  bool
   222  			Expected bool
   223  		}
   224  		table := []TestCase{
   225  			{Skip: true, Include: true, Expected: false},
   226  			{Skip: true, Include: false, Expected: false},
   227  			{Skip: false, Include: true, Expected: true},
   228  			{Skip: false, Include: false, Expected: false},
   229  		}
   230  		q := `query Test($skip: Boolean!, $include: Boolean!) { todo(id: 1) @skip(if: $skip) @include(if: $include) { __typename } }`
   231  		for _, tc := range table {
   232  			var resp map[string]interface{}
   233  			c.MustPost(q, &resp, client.Var("skip", tc.Skip), client.Var("include", tc.Include))
   234  			_, ok := resp["todo"]
   235  			require.Equal(t, tc.Expected, ok)
   236  		}
   237  	})
   238  
   239  	t.Run("skip with default query argument", func(t *testing.T) {
   240  		var resp map[string]interface{}
   241  		c.MustPost(`query Test($skip: Boolean = true) { todo(id: 1) @skip(if: $skip) { __typename } }`, &resp)
   242  		_, ok := resp["todo"]
   243  		require.False(t, ok)
   244  	})
   245  }