1// Copyright 2013 The go-github AUTHORS. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package github
7
8import (
9	"context"
10	"encoding/json"
11	"fmt"
12	"net/http"
13	"reflect"
14	"testing"
15	"time"
16)
17
18func TestGistsService_List_specifiedUser(t *testing.T) {
19	client, mux, _, teardown := setup()
20	defer teardown()
21
22	since := "2013-01-01T00:00:00Z"
23
24	mux.HandleFunc("/users/u/gists", func(w http.ResponseWriter, r *http.Request) {
25		testMethod(t, r, "GET")
26		testFormValues(t, r, values{
27			"since": since,
28		})
29		fmt.Fprint(w, `[{"id": "1"}]`)
30	})
31
32	opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)}
33	gists, _, err := client.Gists.List(context.Background(), "u", opt)
34	if err != nil {
35		t.Errorf("Gists.List returned error: %v", err)
36	}
37
38	want := []*Gist{{ID: String("1")}}
39	if !reflect.DeepEqual(gists, want) {
40		t.Errorf("Gists.List returned %+v, want %+v", gists, want)
41	}
42}
43
44func TestGistsService_List_authenticatedUser(t *testing.T) {
45	client, mux, _, teardown := setup()
46	defer teardown()
47
48	mux.HandleFunc("/gists", func(w http.ResponseWriter, r *http.Request) {
49		testMethod(t, r, "GET")
50		fmt.Fprint(w, `[{"id": "1"}]`)
51	})
52
53	gists, _, err := client.Gists.List(context.Background(), "", nil)
54	if err != nil {
55		t.Errorf("Gists.List returned error: %v", err)
56	}
57
58	want := []*Gist{{ID: String("1")}}
59	if !reflect.DeepEqual(gists, want) {
60		t.Errorf("Gists.List returned %+v, want %+v", gists, want)
61	}
62}
63
64func TestGistsService_List_invalidUser(t *testing.T) {
65	client, _, _, teardown := setup()
66	defer teardown()
67
68	_, _, err := client.Gists.List(context.Background(), "%", nil)
69	testURLParseError(t, err)
70}
71
72func TestGistsService_ListAll(t *testing.T) {
73	client, mux, _, teardown := setup()
74	defer teardown()
75
76	since := "2013-01-01T00:00:00Z"
77
78	mux.HandleFunc("/gists/public", func(w http.ResponseWriter, r *http.Request) {
79		testMethod(t, r, "GET")
80		testFormValues(t, r, values{
81			"since": since,
82		})
83		fmt.Fprint(w, `[{"id": "1"}]`)
84	})
85
86	opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)}
87	gists, _, err := client.Gists.ListAll(context.Background(), opt)
88	if err != nil {
89		t.Errorf("Gists.ListAll returned error: %v", err)
90	}
91
92	want := []*Gist{{ID: String("1")}}
93	if !reflect.DeepEqual(gists, want) {
94		t.Errorf("Gists.ListAll returned %+v, want %+v", gists, want)
95	}
96}
97
98func TestGistsService_ListStarred(t *testing.T) {
99	client, mux, _, teardown := setup()
100	defer teardown()
101
102	since := "2013-01-01T00:00:00Z"
103
104	mux.HandleFunc("/gists/starred", func(w http.ResponseWriter, r *http.Request) {
105		testMethod(t, r, "GET")
106		testFormValues(t, r, values{
107			"since": since,
108		})
109		fmt.Fprint(w, `[{"id": "1"}]`)
110	})
111
112	opt := &GistListOptions{Since: time.Date(2013, time.January, 1, 0, 0, 0, 0, time.UTC)}
113	gists, _, err := client.Gists.ListStarred(context.Background(), opt)
114	if err != nil {
115		t.Errorf("Gists.ListStarred returned error: %v", err)
116	}
117
118	want := []*Gist{{ID: String("1")}}
119	if !reflect.DeepEqual(gists, want) {
120		t.Errorf("Gists.ListStarred returned %+v, want %+v", gists, want)
121	}
122}
123
124func TestGistsService_Get(t *testing.T) {
125	client, mux, _, teardown := setup()
126	defer teardown()
127
128	mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) {
129		testMethod(t, r, "GET")
130		fmt.Fprint(w, `{"id": "1"}`)
131	})
132
133	gist, _, err := client.Gists.Get(context.Background(), "1")
134	if err != nil {
135		t.Errorf("Gists.Get returned error: %v", err)
136	}
137
138	want := &Gist{ID: String("1")}
139	if !reflect.DeepEqual(gist, want) {
140		t.Errorf("Gists.Get returned %+v, want %+v", gist, want)
141	}
142}
143
144func TestGistsService_Get_invalidID(t *testing.T) {
145	client, _, _, teardown := setup()
146	defer teardown()
147
148	_, _, err := client.Gists.Get(context.Background(), "%")
149	testURLParseError(t, err)
150}
151
152func TestGistsService_GetRevision(t *testing.T) {
153	client, mux, _, teardown := setup()
154	defer teardown()
155
156	mux.HandleFunc("/gists/1/s", func(w http.ResponseWriter, r *http.Request) {
157		testMethod(t, r, "GET")
158		fmt.Fprint(w, `{"id": "1"}`)
159	})
160
161	gist, _, err := client.Gists.GetRevision(context.Background(), "1", "s")
162	if err != nil {
163		t.Errorf("Gists.Get returned error: %v", err)
164	}
165
166	want := &Gist{ID: String("1")}
167	if !reflect.DeepEqual(gist, want) {
168		t.Errorf("Gists.Get returned %+v, want %+v", gist, want)
169	}
170}
171
172func TestGistsService_GetRevision_invalidID(t *testing.T) {
173	client, _, _, teardown := setup()
174	defer teardown()
175
176	_, _, err := client.Gists.GetRevision(context.Background(), "%", "%")
177	testURLParseError(t, err)
178}
179
180func TestGistsService_Create(t *testing.T) {
181	client, mux, _, teardown := setup()
182	defer teardown()
183
184	input := &Gist{
185		Description: String("Gist description"),
186		Public:      Bool(false),
187		Files: map[GistFilename]GistFile{
188			"test.txt": {Content: String("Gist file content")},
189		},
190	}
191
192	mux.HandleFunc("/gists", func(w http.ResponseWriter, r *http.Request) {
193		v := new(Gist)
194		json.NewDecoder(r.Body).Decode(v)
195
196		testMethod(t, r, "POST")
197		if !reflect.DeepEqual(v, input) {
198			t.Errorf("Request body = %+v, want %+v", v, input)
199		}
200
201		fmt.Fprint(w,
202			`
203			{
204				"id": "1",
205				"description": "Gist description",
206				"public": false,
207				"files": {
208					"test.txt": {
209						"filename": "test.txt"
210					}
211				}
212			}`)
213	})
214
215	gist, _, err := client.Gists.Create(context.Background(), input)
216	if err != nil {
217		t.Errorf("Gists.Create returned error: %v", err)
218	}
219
220	want := &Gist{
221		ID:          String("1"),
222		Description: String("Gist description"),
223		Public:      Bool(false),
224		Files: map[GistFilename]GistFile{
225			"test.txt": {Filename: String("test.txt")},
226		},
227	}
228	if !reflect.DeepEqual(gist, want) {
229		t.Errorf("Gists.Create returned %+v, want %+v", gist, want)
230	}
231}
232
233func TestGistsService_Edit(t *testing.T) {
234	client, mux, _, teardown := setup()
235	defer teardown()
236
237	input := &Gist{
238		Description: String("New description"),
239		Files: map[GistFilename]GistFile{
240			"new.txt": {Content: String("new file content")},
241		},
242	}
243
244	mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) {
245		v := new(Gist)
246		json.NewDecoder(r.Body).Decode(v)
247
248		testMethod(t, r, "PATCH")
249		if !reflect.DeepEqual(v, input) {
250			t.Errorf("Request body = %+v, want %+v", v, input)
251		}
252
253		fmt.Fprint(w,
254			`
255			{
256				"id": "1",
257				"description": "new description",
258				"public": false,
259				"files": {
260					"test.txt": {
261						"filename": "test.txt"
262					},
263					"new.txt": {
264						"filename": "new.txt"
265					}
266				}
267			}`)
268	})
269
270	gist, _, err := client.Gists.Edit(context.Background(), "1", input)
271	if err != nil {
272		t.Errorf("Gists.Edit returned error: %v", err)
273	}
274
275	want := &Gist{
276		ID:          String("1"),
277		Description: String("new description"),
278		Public:      Bool(false),
279		Files: map[GistFilename]GistFile{
280			"test.txt": {Filename: String("test.txt")},
281			"new.txt":  {Filename: String("new.txt")},
282		},
283	}
284	if !reflect.DeepEqual(gist, want) {
285		t.Errorf("Gists.Edit returned %+v, want %+v", gist, want)
286	}
287}
288
289func TestGistsService_Edit_invalidID(t *testing.T) {
290	client, _, _, teardown := setup()
291	defer teardown()
292
293	_, _, err := client.Gists.Edit(context.Background(), "%", nil)
294	testURLParseError(t, err)
295}
296
297func TestGistsService_ListCommits(t *testing.T) {
298	client, mux, _, teardown := setup()
299	defer teardown()
300
301	mux.HandleFunc("/gists/1/commits", func(w http.ResponseWriter, r *http.Request) {
302		testMethod(t, r, "GET")
303		testFormValues(t, r, nil)
304		fmt.Fprint(w, `
305		  [
306		    {
307		      "url": "https://api.github.com/gists/1/1",
308		      "version": "1",
309		      "user": {
310		        "id": 1
311		      },
312		      "change_status": {
313		        "deletions": 0,
314		        "additions": 180,
315		        "total": 180
316		      },
317		      "committed_at": "2010-01-01T00:00:00Z"
318		    }
319		  ]
320		`)
321	})
322
323	gistCommits, _, err := client.Gists.ListCommits(context.Background(), "1", nil)
324	if err != nil {
325		t.Errorf("Gists.ListCommits returned error: %v", err)
326	}
327
328	want := []*GistCommit{{
329		URL:         String("https://api.github.com/gists/1/1"),
330		Version:     String("1"),
331		User:        &User{ID: Int64(1)},
332		CommittedAt: &Timestamp{time.Date(2010, time.January, 1, 00, 00, 00, 0, time.UTC)},
333		ChangeStatus: &CommitStats{
334			Additions: Int(180),
335			Deletions: Int(0),
336			Total:     Int(180),
337		}}}
338
339	if !reflect.DeepEqual(gistCommits, want) {
340		t.Errorf("Gists.ListCommits returned %+v, want %+v", gistCommits, want)
341	}
342}
343
344func TestGistsService_ListCommits_withOptions(t *testing.T) {
345	client, mux, _, teardown := setup()
346	defer teardown()
347
348	mux.HandleFunc("/gists/1/commits", func(w http.ResponseWriter, r *http.Request) {
349		testMethod(t, r, "GET")
350		testFormValues(t, r, values{
351			"page": "2",
352		})
353		fmt.Fprint(w, `[]`)
354	})
355
356	_, _, err := client.Gists.ListCommits(context.Background(), "1", &ListOptions{Page: 2})
357	if err != nil {
358		t.Errorf("Gists.ListCommits returned error: %v", err)
359	}
360}
361
362func TestGistsService_Delete(t *testing.T) {
363	client, mux, _, teardown := setup()
364	defer teardown()
365
366	mux.HandleFunc("/gists/1", func(w http.ResponseWriter, r *http.Request) {
367		testMethod(t, r, "DELETE")
368	})
369
370	_, err := client.Gists.Delete(context.Background(), "1")
371	if err != nil {
372		t.Errorf("Gists.Delete returned error: %v", err)
373	}
374}
375
376func TestGistsService_Delete_invalidID(t *testing.T) {
377	client, _, _, teardown := setup()
378	defer teardown()
379
380	_, err := client.Gists.Delete(context.Background(), "%")
381	testURLParseError(t, err)
382}
383
384func TestGistsService_Star(t *testing.T) {
385	client, mux, _, teardown := setup()
386	defer teardown()
387
388	mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
389		testMethod(t, r, "PUT")
390	})
391
392	_, err := client.Gists.Star(context.Background(), "1")
393	if err != nil {
394		t.Errorf("Gists.Star returned error: %v", err)
395	}
396}
397
398func TestGistsService_Star_invalidID(t *testing.T) {
399	client, _, _, teardown := setup()
400	defer teardown()
401
402	_, err := client.Gists.Star(context.Background(), "%")
403	testURLParseError(t, err)
404}
405
406func TestGistsService_Unstar(t *testing.T) {
407	client, mux, _, teardown := setup()
408	defer teardown()
409
410	mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
411		testMethod(t, r, "DELETE")
412	})
413
414	_, err := client.Gists.Unstar(context.Background(), "1")
415	if err != nil {
416		t.Errorf("Gists.Unstar returned error: %v", err)
417	}
418}
419
420func TestGistsService_Unstar_invalidID(t *testing.T) {
421	client, _, _, teardown := setup()
422	defer teardown()
423
424	_, err := client.Gists.Unstar(context.Background(), "%")
425	testURLParseError(t, err)
426}
427
428func TestGistsService_IsStarred_hasStar(t *testing.T) {
429	client, mux, _, teardown := setup()
430	defer teardown()
431
432	mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
433		testMethod(t, r, "GET")
434		w.WriteHeader(http.StatusNoContent)
435	})
436
437	star, _, err := client.Gists.IsStarred(context.Background(), "1")
438	if err != nil {
439		t.Errorf("Gists.Starred returned error: %v", err)
440	}
441	if want := true; star != want {
442		t.Errorf("Gists.Starred returned %+v, want %+v", star, want)
443	}
444}
445
446func TestGistsService_IsStarred_noStar(t *testing.T) {
447	client, mux, _, teardown := setup()
448	defer teardown()
449
450	mux.HandleFunc("/gists/1/star", func(w http.ResponseWriter, r *http.Request) {
451		testMethod(t, r, "GET")
452		w.WriteHeader(http.StatusNotFound)
453	})
454
455	star, _, err := client.Gists.IsStarred(context.Background(), "1")
456	if err != nil {
457		t.Errorf("Gists.Starred returned error: %v", err)
458	}
459	if want := false; star != want {
460		t.Errorf("Gists.Starred returned %+v, want %+v", star, want)
461	}
462}
463
464func TestGistsService_IsStarred_invalidID(t *testing.T) {
465	client, _, _, teardown := setup()
466	defer teardown()
467
468	_, _, err := client.Gists.IsStarred(context.Background(), "%")
469	testURLParseError(t, err)
470}
471
472func TestGistsService_Fork(t *testing.T) {
473	client, mux, _, teardown := setup()
474	defer teardown()
475
476	mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) {
477		testMethod(t, r, "POST")
478		fmt.Fprint(w, `{"id": "2"}`)
479	})
480
481	gist, _, err := client.Gists.Fork(context.Background(), "1")
482	if err != nil {
483		t.Errorf("Gists.Fork returned error: %v", err)
484	}
485
486	want := &Gist{ID: String("2")}
487	if !reflect.DeepEqual(gist, want) {
488		t.Errorf("Gists.Fork returned %+v, want %+v", gist, want)
489	}
490}
491
492func TestGistsService_ListForks(t *testing.T) {
493	client, mux, _, teardown := setup()
494	defer teardown()
495
496	mux.HandleFunc("/gists/1/forks", func(w http.ResponseWriter, r *http.Request) {
497		testMethod(t, r, "GET")
498		testFormValues(t, r, nil)
499		fmt.Fprint(w, `
500		  [
501		    {"url": "https://api.github.com/gists/1",
502		     "user": {"id": 1},
503		     "id": "1",
504		     "created_at": "2010-01-01T00:00:00Z",
505		     "updated_at": "2013-01-01T00:00:00Z"
506		    }
507		  ]
508		`)
509	})
510
511	gistForks, _, err := client.Gists.ListForks(context.Background(), "1")
512	if err != nil {
513		t.Errorf("Gists.ListForks returned error: %v", err)
514	}
515
516	want := []*GistFork{{
517		URL:       String("https://api.github.com/gists/1"),
518		ID:        String("1"),
519		User:      &User{ID: Int64(1)},
520		CreatedAt: &Timestamp{time.Date(2010, time.January, 1, 00, 00, 00, 0, time.UTC)},
521		UpdatedAt: &Timestamp{time.Date(2013, time.January, 1, 00, 00, 00, 0, time.UTC)}}}
522
523	if !reflect.DeepEqual(gistForks, want) {
524		t.Errorf("Gists.ListForks returned %+v, want %+v", gistForks, want)
525	}
526}
527
528func TestGistsService_Fork_invalidID(t *testing.T) {
529	client, _, _, teardown := setup()
530	defer teardown()
531
532	_, _, err := client.Gists.Fork(context.Background(), "%")
533	testURLParseError(t, err)
534}
535