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 }