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	"fmt"
11	"net/http"
12	"reflect"
13	"strings"
14	"testing"
15	"time"
16)
17
18func TestRepositoriesService_ListCommits(t *testing.T) {
19	client, mux, _, teardown := setup()
20	defer teardown()
21
22	// given
23	mux.HandleFunc("/repos/o/r/commits", func(w http.ResponseWriter, r *http.Request) {
24		testMethod(t, r, "GET")
25		testFormValues(t, r,
26			values{
27				"sha":    "s",
28				"path":   "p",
29				"author": "a",
30				"since":  "2013-08-01T00:00:00Z",
31				"until":  "2013-09-03T00:00:00Z",
32			})
33		fmt.Fprintf(w, `[{"sha": "s"}]`)
34	})
35
36	opt := &CommitsListOptions{
37		SHA:    "s",
38		Path:   "p",
39		Author: "a",
40		Since:  time.Date(2013, time.August, 1, 0, 0, 0, 0, time.UTC),
41		Until:  time.Date(2013, time.September, 3, 0, 0, 0, 0, time.UTC),
42	}
43	commits, _, err := client.Repositories.ListCommits(context.Background(), "o", "r", opt)
44	if err != nil {
45		t.Errorf("Repositories.ListCommits returned error: %v", err)
46	}
47
48	want := []*RepositoryCommit{{SHA: String("s")}}
49	if !reflect.DeepEqual(commits, want) {
50		t.Errorf("Repositories.ListCommits returned %+v, want %+v", commits, want)
51	}
52}
53
54func TestRepositoriesService_GetCommit(t *testing.T) {
55	client, mux, _, teardown := setup()
56	defer teardown()
57
58	mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
59		testMethod(t, r, "GET")
60		fmt.Fprintf(w, `{
61		  "sha": "s",
62		  "commit": { "message": "m" },
63		  "author": { "login": "l" },
64		  "committer": { "login": "l" },
65		  "parents": [ { "sha": "s" } ],
66		  "stats": { "additions": 104, "deletions": 4, "total": 108 },
67		  "files": [
68		    {
69		      "filename": "f",
70		      "additions": 10,
71		      "deletions": 2,
72		      "changes": 12,
73		      "status": "s",
74		      "patch": "p",
75		      "blob_url": "b",
76		      "raw_url": "r",
77		      "contents_url": "c"
78		    }
79		  ]
80		}`)
81	})
82
83	commit, _, err := client.Repositories.GetCommit(context.Background(), "o", "r", "s")
84	if err != nil {
85		t.Errorf("Repositories.GetCommit returned error: %v", err)
86	}
87
88	want := &RepositoryCommit{
89		SHA: String("s"),
90		Commit: &Commit{
91			Message: String("m"),
92		},
93		Author: &User{
94			Login: String("l"),
95		},
96		Committer: &User{
97			Login: String("l"),
98		},
99		Parents: []Commit{
100			{
101				SHA: String("s"),
102			},
103		},
104		Stats: &CommitStats{
105			Additions: Int(104),
106			Deletions: Int(4),
107			Total:     Int(108),
108		},
109		Files: []CommitFile{
110			{
111				Filename:    String("f"),
112				Additions:   Int(10),
113				Deletions:   Int(2),
114				Changes:     Int(12),
115				Status:      String("s"),
116				Patch:       String("p"),
117				BlobURL:     String("b"),
118				RawURL:      String("r"),
119				ContentsURL: String("c"),
120			},
121		},
122	}
123	if !reflect.DeepEqual(commit, want) {
124		t.Errorf("Repositories.GetCommit returned \n%+v, want \n%+v", commit, want)
125	}
126}
127
128func TestRepositoriesService_GetCommitRaw_diff(t *testing.T) {
129	client, mux, _, teardown := setup()
130	defer teardown()
131
132	const rawStr = "@@diff content"
133
134	mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
135		testMethod(t, r, "GET")
136		testHeader(t, r, "Accept", mediaTypeV3Diff)
137		fmt.Fprint(w, rawStr)
138	})
139
140	got, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{Type: Diff})
141	if err != nil {
142		t.Fatalf("Repositories.GetCommitRaw returned error: %v", err)
143	}
144	want := rawStr
145	if got != want {
146		t.Errorf("Repositories.GetCommitRaw returned %s want %s", got, want)
147	}
148}
149
150func TestRepositoriesService_GetCommitRaw_patch(t *testing.T) {
151	client, mux, _, teardown := setup()
152	defer teardown()
153
154	const rawStr = "@@patch content"
155
156	mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
157		testMethod(t, r, "GET")
158		testHeader(t, r, "Accept", mediaTypeV3Patch)
159		fmt.Fprint(w, rawStr)
160	})
161
162	got, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{Type: Patch})
163	if err != nil {
164		t.Fatalf("Repositories.GetCommitRaw returned error: %v", err)
165	}
166	want := rawStr
167	if got != want {
168		t.Errorf("Repositories.GetCommitRaw returned %s want %s", got, want)
169	}
170}
171
172func TestRepositoriesService_GetCommitRaw_invalid(t *testing.T) {
173	client, _, _, teardown := setup()
174	defer teardown()
175
176	_, _, err := client.Repositories.GetCommitRaw(context.Background(), "o", "r", "s", RawOptions{100})
177	if err == nil {
178		t.Fatal("Repositories.GetCommitRaw should return error")
179	}
180	if !strings.Contains(err.Error(), "unsupported raw type") {
181		t.Error("Repositories.GetCommitRaw should return unsupported raw type error")
182	}
183}
184
185func TestRepositoriesService_GetCommitSHA1(t *testing.T) {
186	client, mux, _, teardown := setup()
187	defer teardown()
188	const sha1 = "01234abcde"
189
190	mux.HandleFunc("/repos/o/r/commits/master", func(w http.ResponseWriter, r *http.Request) {
191		testMethod(t, r, "GET")
192		testHeader(t, r, "Accept", mediaTypeV3SHA)
193
194		fmt.Fprintf(w, sha1)
195	})
196
197	got, _, err := client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "master", "")
198	if err != nil {
199		t.Errorf("Repositories.GetCommitSHA1 returned error: %v", err)
200	}
201
202	want := sha1
203	if got != want {
204		t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want)
205	}
206
207	mux.HandleFunc("/repos/o/r/commits/tag", func(w http.ResponseWriter, r *http.Request) {
208		testMethod(t, r, "GET")
209		testHeader(t, r, "Accept", mediaTypeV3SHA)
210		testHeader(t, r, "If-None-Match", `"`+sha1+`"`)
211
212		w.WriteHeader(http.StatusNotModified)
213	})
214
215	got, _, err = client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "tag", sha1)
216	if err == nil {
217		t.Errorf("Expected HTTP 304 response")
218	}
219
220	want = ""
221	if got != want {
222		t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want)
223	}
224}
225
226func TestRepositoriesService_NonAlphabetCharacter_GetCommitSHA1(t *testing.T) {
227	client, mux, _, teardown := setup()
228	defer teardown()
229	const sha1 = "01234abcde"
230
231	mux.HandleFunc("/repos/o/r/commits/master%20hash", func(w http.ResponseWriter, r *http.Request) {
232		testMethod(t, r, "GET")
233		testHeader(t, r, "Accept", mediaTypeV3SHA)
234
235		fmt.Fprintf(w, sha1)
236	})
237
238	got, _, err := client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "master%20hash", "")
239	if err != nil {
240		t.Errorf("Repositories.GetCommitSHA1 returned error: %v", err)
241	}
242
243	if want := sha1; got != want {
244		t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want)
245	}
246
247	mux.HandleFunc("/repos/o/r/commits/tag", func(w http.ResponseWriter, r *http.Request) {
248		testMethod(t, r, "GET")
249		testHeader(t, r, "Accept", mediaTypeV3SHA)
250		testHeader(t, r, "If-None-Match", `"`+sha1+`"`)
251
252		w.WriteHeader(http.StatusNotModified)
253	})
254
255	got, _, err = client.Repositories.GetCommitSHA1(context.Background(), "o", "r", "tag", sha1)
256	if err == nil {
257		t.Errorf("Expected HTTP 304 response")
258	}
259
260	if want := ""; got != want {
261		t.Errorf("Repositories.GetCommitSHA1 = %v, want %v", got, want)
262	}
263}
264
265func TestRepositoriesService_CompareCommits(t *testing.T) {
266	client, mux, _, teardown := setup()
267	defer teardown()
268
269	mux.HandleFunc("/repos/o/r/compare/b...h", func(w http.ResponseWriter, r *http.Request) {
270		testMethod(t, r, "GET")
271		fmt.Fprintf(w, `{
272		  "base_commit": {
273		    "sha": "s",
274		    "commit": {
275		      "author": { "name": "n" },
276		      "committer": { "name": "n" },
277		      "message": "m",
278		      "tree": { "sha": "t" }
279		    },
280		    "author": { "login": "l" },
281		    "committer": { "login": "l" },
282		    "parents": [ { "sha": "s" } ]
283		  },
284		  "status": "s",
285		  "ahead_by": 1,
286		  "behind_by": 2,
287		  "total_commits": 1,
288		  "commits": [
289		    {
290		      "sha": "s",
291		      "commit": { "author": { "name": "n" } },
292		      "author": { "login": "l" },
293		      "committer": { "login": "l" },
294		      "parents": [ { "sha": "s" } ]
295		    }
296		  ],
297		  "files": [ { "filename": "f" } ],
298		  "html_url":      "https://github.com/o/r/compare/b...h",
299		  "permalink_url": "https://github.com/o/r/compare/o:bbcd538c8e72b8c175046e27cc8f907076331401...o:0328041d1152db8ae77652d1618a02e57f745f17",
300		  "diff_url":      "https://github.com/o/r/compare/b...h.diff",
301		  "patch_url":     "https://github.com/o/r/compare/b...h.patch",
302		  "url":           "https://api.github.com/repos/o/r/compare/b...h"
303		}`)
304	})
305
306	got, _, err := client.Repositories.CompareCommits(context.Background(), "o", "r", "b", "h")
307	if err != nil {
308		t.Errorf("Repositories.CompareCommits returned error: %v", err)
309	}
310
311	want := &CommitsComparison{
312		BaseCommit: &RepositoryCommit{
313			SHA: String("s"),
314			Commit: &Commit{
315				Author:    &CommitAuthor{Name: String("n")},
316				Committer: &CommitAuthor{Name: String("n")},
317				Message:   String("m"),
318				Tree:      &Tree{SHA: String("t")},
319			},
320			Author:    &User{Login: String("l")},
321			Committer: &User{Login: String("l")},
322			Parents: []Commit{
323				{
324					SHA: String("s"),
325				},
326			},
327		},
328		Status:       String("s"),
329		AheadBy:      Int(1),
330		BehindBy:     Int(2),
331		TotalCommits: Int(1),
332		Commits: []RepositoryCommit{
333			{
334				SHA: String("s"),
335				Commit: &Commit{
336					Author: &CommitAuthor{Name: String("n")},
337				},
338				Author:    &User{Login: String("l")},
339				Committer: &User{Login: String("l")},
340				Parents: []Commit{
341					{
342						SHA: String("s"),
343					},
344				},
345			},
346		},
347		Files: []CommitFile{
348			{
349				Filename: String("f"),
350			},
351		},
352		HTMLURL:      String("https://github.com/o/r/compare/b...h"),
353		PermalinkURL: String("https://github.com/o/r/compare/o:bbcd538c8e72b8c175046e27cc8f907076331401...o:0328041d1152db8ae77652d1618a02e57f745f17"),
354		DiffURL:      String("https://github.com/o/r/compare/b...h.diff"),
355		PatchURL:     String("https://github.com/o/r/compare/b...h.patch"),
356		URL:          String("https://api.github.com/repos/o/r/compare/b...h"),
357	}
358
359	if !reflect.DeepEqual(got, want) {
360		t.Errorf("Repositories.CompareCommits returned \n%+v, want \n%+v", got, want)
361	}
362}
363
364func TestRepositoriesService_ListBranchesHeadCommit(t *testing.T) {
365	client, mux, _, teardown := setup()
366	defer teardown()
367
368	mux.HandleFunc("/repos/o/r/commits/s/branches-where-head", func(w http.ResponseWriter, r *http.Request) {
369		testMethod(t, r, "GET")
370		fmt.Fprintf(w, `[{"name": "b"}]`)
371	})
372
373	branches, _, err := client.Repositories.ListBranchesHeadCommit(context.Background(), "o", "r", "s")
374	if err != nil {
375		t.Errorf("Repositories.ListBranchesHeadCommit returned error: %v", err)
376	}
377
378	want := []*BranchCommit{{Name: String("b")}}
379	if !reflect.DeepEqual(branches, want) {
380		t.Errorf("Repositories.ListBranchesHeadCommit returned %+v, want %+v", branches, want)
381	}
382}
383