github.com/jepp2078/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 }