From 8a2222a538b15c8944373c48641db1cdd3fbba45 Mon Sep 17 00:00:00 2001 From: Will Norris Date: Thu, 10 Apr 2014 12:47:42 -0700 Subject: [PATCH] add support for repository subscription methods (I kinda hate how long some of these names are... I'd much rather just call them "subscriptions", but the API docs is pretty consistent about calling them "repository subscriptions", so that's what we go with. Maybe the intend to later add other kinds of subscriptions?) --- github/activity_watching.go | 99 +++++++++++++++++++- github/activity_watching_test.go | 139 +++++++++++++++++++++++++++++ tests/integration/activity_test.go | 58 ++++++++++++ 3 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 tests/integration/activity_test.go diff --git a/github/activity_watching.go b/github/activity_watching.go index 25f2929..3af168a 100644 --- a/github/activity_watching.go +++ b/github/activity_watching.go @@ -2,13 +2,23 @@ package github import "fmt" +// RepositorySubscription identifies a repository subscription. +type RepositorySubscription struct { + Subscribed *bool `json:"subscribed,omitempty"` + Ignored *bool `json:"ignored,omitempty"` + Reason *string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` +} + // ListWatchers lists watchers of a particular repo. // // GitHub API Docs: http://developer.github.com/v3/activity/watching/#list-watchers func (s *ActivityService) ListWatchers(owner, repo string) ([]User, *Response, error) { - url := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) + u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) - req, err := s.client.NewRequest("GET", url, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } @@ -21,3 +31,88 @@ func (s *ActivityService) ListWatchers(owner, repo string) ([]User, *Response, e return *watchers, resp, err } + +// ListWatchedRepositories lists the repositories the specified user is watching. +// Passing the empty string will fetch watched repos for the authenticated +// user. +// +// GitHub API Docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched +func (s *ActivityService) ListWatchedRepositories(user string) ([]Repository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/subscriptions", user) + } else { + u = "user/subscriptions" + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + watched := new([]Repository) + resp, err := s.client.Do(req, watched) + if err != nil { + return nil, resp, err + } + + return *watched, resp, err +} + +// GetRepositorySubscription returns the subscription for the specified repository for +// the authenticated user. If the authenticated user is not watching the +// repository, a nil RepositorySubscription is returned. +// +// GitHub API Docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription +func (s *ActivityService) GetRepositorySubscription(owner, repo string) (*RepositorySubscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(RepositorySubscription) + resp, err := s.client.Do(req, sub) + if err != nil { + // if it's just a 404, don't return that as an error + _, err = parseBoolResponse(err) + return nil, resp, err + } + + return sub, resp, err +} + +// SetRepositorySubscription sets the subscription for the specified repository for +// the authenticated user. +// +// GitHub API Docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription +func (s *ActivityService) SetRepositorySubscription(owner, repo string, subscription *RepositorySubscription) (*RepositorySubscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(RepositorySubscription) + resp, err := s.client.Do(req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, err +} + +// DeleteRepositorySubscription deletes the subscription for the specified repository for +// the authenticated user. +// +// GitHub API Docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription +func (s *ActivityService) DeleteRepositorySubscription(owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/github/activity_watching_test.go b/github/activity_watching_test.go index 72f1b51..46a2d96 100644 --- a/github/activity_watching_test.go +++ b/github/activity_watching_test.go @@ -1,6 +1,7 @@ package github import ( + "encoding/json" "fmt" "net/http" "reflect" @@ -26,3 +27,141 @@ func TestActivityService_ListWatchers(t *testing.T) { t.Errorf("Activity.ListWatchers returned %+v, want %+v", watchers, want) } } + +func TestActivityService_ListWatchedRepositories_authenticatedUser(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/user/subscriptions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[{"id":1}]`) + }) + + watched, _, err := client.Activity.ListWatchedRepositories("") + if err != nil { + t.Errorf("Activity.ListWatchedRepositories returned error: %v", err) + } + + want := []Repository{{ID: Int(1)}} + if !reflect.DeepEqual(watched, want) { + t.Errorf("Activity.ListWatchedRepositories returned %+v, want %+v", watched, want) + } +} + +func TestActivityService_ListWatchedRepositories_specifiedUser(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/users/u/subscriptions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[{"id":1}]`) + }) + + watched, _, err := client.Activity.ListWatchedRepositories("u") + if err != nil { + t.Errorf("Activity.ListWatchedRepositories returned error: %v", err) + } + + want := []Repository{{ID: Int(1)}} + if !reflect.DeepEqual(watched, want) { + t.Errorf("Activity.ListWatchedRepositories returned %+v, want %+v", watched, want) + } +} + +func TestActivityService_GetRepositorySubscription_true(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"subscribed":true}`) + }) + + sub, _, err := client.Activity.GetRepositorySubscription("o", "r") + if err != nil { + t.Errorf("Activity.GetRepositorySubscription returned error: %v", err) + } + + want := &RepositorySubscription{Subscribed: Bool(true)} + if !reflect.DeepEqual(sub, want) { + t.Errorf("Activity.GetRepositorySubscription returned %+v, want %+v", sub, want) + } +} + +func TestActivityService_GetRepositorySubscription_false(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + w.WriteHeader(http.StatusNotFound) + }) + + sub, _, err := client.Activity.GetRepositorySubscription("o", "r") + if err != nil { + t.Errorf("Activity.GetRepositorySubscription returned error: %v", err) + } + + var want *RepositorySubscription + if !reflect.DeepEqual(sub, want) { + t.Errorf("Activity.GetRepositorySubscription returned %+v, want %+v", sub, want) + } +} + +func TestActivityService_GetRepositorySubscription_error(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + w.WriteHeader(http.StatusBadRequest) + }) + + _, _, err := client.Activity.GetRepositorySubscription("o", "r") + if err == nil { + t.Errorf("Expected HTTP 400 response") + } +} + +func TestActivityService_SetRepositorySubscription(t *testing.T) { + setup() + defer teardown() + + input := &RepositorySubscription{Subscribed: Bool(true)} + + mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { + v := new(RepositorySubscription) + json.NewDecoder(r.Body).Decode(v) + + testMethod(t, r, "PUT") + if !reflect.DeepEqual(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, `{"ignored":true}`) + }) + + sub, _, err := client.Activity.SetRepositorySubscription("o", "r", input) + if err != nil { + t.Errorf("Activity.SetRepositorySubscription returned error: %v", err) + } + + want := &RepositorySubscription{Ignored: Bool(true)} + if !reflect.DeepEqual(sub, want) { + t.Errorf("Activity.SetRepositorySubscription returned %+v, want %+v", sub, want) + } +} + +func TestActivityService_DeleteRepositorySubscription(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/subscription", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + _, err := client.Activity.DeleteRepositorySubscription("o", "r") + if err != nil { + t.Errorf("Activity.DeleteRepositorySubscription returned error: %v", err) + } +} diff --git a/tests/integration/activity_test.go b/tests/integration/activity_test.go new file mode 100644 index 0000000..a6e0f73 --- /dev/null +++ b/tests/integration/activity_test.go @@ -0,0 +1,58 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tests + +import ( + "testing" + + "github.com/google/go-github/github" +) + +func TestActivity_Watching(t *testing.T) { + if !checkAuth("TestActivity_Watching") { + return + } + + // first, check if already watching google/go-github + sub, _, err := client.Activity.GetRepositorySubscription("google", "go-github") + if err != nil { + t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err) + } + if sub != nil { + t.Fatalf("Already watching google/go-github. Please manually stop watching it first.") + } + + // watch google/go-github + sub = &github.RepositorySubscription{Subscribed: github.Bool(true)} + _, _, err = client.Activity.SetRepositorySubscription("google", "go-github", sub) + if err != nil { + t.Fatalf("Activity.SetRepositorySubscription returned error: %v", err) + } + + // check again and verify watching + sub, _, err = client.Activity.GetRepositorySubscription("google", "go-github") + if err != nil { + t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err) + } + if sub == nil || !*sub.Subscribed { + t.Fatalf("Not watching google/go-github after setting subscription.") + } + + // delete subscription + _, err = client.Activity.DeleteRepositorySubscription("google", "go-github") + if err != nil { + t.Fatalf("Activity.DeleteRepositorySubscription returned error: %v", err) + } + + // check again and verify not watching + sub, _, err = client.Activity.GetRepositorySubscription("google", "go-github") + if err != nil { + t.Fatalf("Activity.GetRepositorySubscription returned error: %v", err) + } + if sub != nil { + t.Fatalf("Still watching google/go-github after deleting subscription.") + } +}