github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/example/todo/todo_test.go (about)

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