| @ -0,0 +1,140 @@ | |||||
| // 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 github | |||||
| import ( | |||||
| "fmt" | |||||
| "time" | |||||
| ) | |||||
| // Milestone represents a Github repository milestone. | |||||
| type Milestone struct { | |||||
| URL *string `json:"url,omitempty"` | |||||
| Number *int `json:"number,omitempty"` | |||||
| State *string `json:"state,omitempty"` | |||||
| Title *string `json:"title,omitempty"` | |||||
| Description *string `json:"description,omitempty"` | |||||
| Creator *User `json:"creator,omitempty"` | |||||
| OpenIssues *int `json:"open_issues,omitempty"` | |||||
| ClosedIssues *int `json:"closed_issues,omitempty"` | |||||
| CreatedAt *time.Time `json:"created_at,omitempty"` | |||||
| UpdatedAt *time.Time `json:"updated_at,omitempty"` | |||||
| DueOn *time.Time `json:"due_on,omitempty"` | |||||
| } | |||||
| func (m Milestone) String() string { | |||||
| return Stringify(m) | |||||
| } | |||||
| // MilestoneListOptions specifies the optional parameters to the | |||||
| // IssuesService.ListMilestones method. | |||||
| type MilestoneListOptions struct { | |||||
| // State filters milestones based on their state. Possible values are: | |||||
| // open, closed. Default is "open". | |||||
| State string `url:"state,omitempty"` | |||||
| // Sort specifies how to sort milestones. Possible values are: due_date, completeness. | |||||
| // Default value is "due_date". | |||||
| Sort string `url:"sort,omitempty"` | |||||
| // Direction in which to sort milestones. Possible values are: asc, desc. | |||||
| // Default is "asc". | |||||
| Direction string `url:"direction,omitempty"` | |||||
| } | |||||
| // ListMilestones lists all milestones for a repository. | |||||
| // | |||||
| // GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository | |||||
| func (s *IssuesService) ListMilestones(owner string, repo string, opt *MilestoneListOptions) ([]Milestone, *Response, error) { | |||||
| u := fmt.Sprintf("/repos/%v/%v/milestones", owner, repo) | |||||
| u, err := addOptions(u, opt) | |||||
| if err != nil { | |||||
| return nil, nil, err | |||||
| } | |||||
| req, err := s.client.NewRequest("GET", u, nil) | |||||
| if err != nil { | |||||
| return nil, nil, err | |||||
| } | |||||
| milestones := new([]Milestone) | |||||
| resp, err := s.client.Do(req, milestones) | |||||
| if err != nil { | |||||
| return nil, resp, err | |||||
| } | |||||
| return *milestones, resp, err | |||||
| } | |||||
| // GetMilestone gets a single milestone. | |||||
| // | |||||
| // GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone | |||||
| func (s *IssuesService) GetMilestone(owner string, repo string, number int) (*Milestone, *Response, error) { | |||||
| u := fmt.Sprintf("/repos/%v/%v/milestones/%d", owner, repo, number) | |||||
| req, err := s.client.NewRequest("GET", u, nil) | |||||
| if err != nil { | |||||
| return nil, nil, err | |||||
| } | |||||
| milestone := new(Milestone) | |||||
| resp, err := s.client.Do(req, milestone) | |||||
| if err != nil { | |||||
| return nil, resp, err | |||||
| } | |||||
| return milestone, resp, err | |||||
| } | |||||
| // CreateMilestone creates a new milestone on the specified repository. | |||||
| // | |||||
| // GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone | |||||
| func (s *IssuesService) CreateMilestone(owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) { | |||||
| u := fmt.Sprintf("/repos/%v/%v/milestones", owner, repo) | |||||
| req, err := s.client.NewRequest("POST", u, milestone) | |||||
| if err != nil { | |||||
| return nil, nil, err | |||||
| } | |||||
| m := new(Milestone) | |||||
| resp, err := s.client.Do(req, m) | |||||
| if err != nil { | |||||
| return nil, resp, err | |||||
| } | |||||
| return m, resp, err | |||||
| } | |||||
| // EditMilestone edits a milestone. | |||||
| // | |||||
| // GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone | |||||
| func (s *IssuesService) EditMilestone(owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) { | |||||
| u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) | |||||
| req, err := s.client.NewRequest("PATCH", u, milestone) | |||||
| if err != nil { | |||||
| return nil, nil, err | |||||
| } | |||||
| m := new(Milestone) | |||||
| resp, err := s.client.Do(req, m) | |||||
| if err != nil { | |||||
| return nil, resp, err | |||||
| } | |||||
| return m, resp, err | |||||
| } | |||||
| // DeleteMilestone deletes a milestone. | |||||
| // | |||||
| // GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone | |||||
| func (s *IssuesService) DeleteMilestone(owner string, repo string, number int) (*Response, error) { | |||||
| u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) | |||||
| req, err := s.client.NewRequest("DELETE", u, nil) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| return s.client.Do(req, nil) | |||||
| } | |||||
| @ -0,0 +1,157 @@ | |||||
| // 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 github | |||||
| import ( | |||||
| "encoding/json" | |||||
| "fmt" | |||||
| "net/http" | |||||
| "reflect" | |||||
| "testing" | |||||
| ) | |||||
| func TestIssuesService_ListMilestones(t *testing.T) { | |||||
| setup() | |||||
| defer teardown() | |||||
| mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) { | |||||
| testMethod(t, r, "GET") | |||||
| testFormValues(t, r, values{ | |||||
| "state": "closed", | |||||
| "sort": "due_date", | |||||
| "direction": "asc", | |||||
| }) | |||||
| fmt.Fprint(w, `[{"number":1}]`) | |||||
| }) | |||||
| opt := &MilestoneListOptions{"closed", "due_date", "asc"} | |||||
| milestones, _, err := client.Issues.ListMilestones("o", "r", opt) | |||||
| if err != nil { | |||||
| t.Errorf("IssuesService.ListMilestones returned error: %v", err) | |||||
| } | |||||
| want := []Milestone{{Number: Int(1)}} | |||||
| if !reflect.DeepEqual(milestones, want) { | |||||
| t.Errorf("IssuesService.ListMilestones returned %+v, want %+v", milestones, want) | |||||
| } | |||||
| } | |||||
| func TestIssuesService_ListMilestones_invalidOwner(t *testing.T) { | |||||
| _, _, err := client.Issues.ListMilestones("%", "r", nil) | |||||
| testURLParseError(t, err) | |||||
| } | |||||
| func TestIssuesService_GetMilestone(t *testing.T) { | |||||
| setup() | |||||
| defer teardown() | |||||
| mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) { | |||||
| testMethod(t, r, "GET") | |||||
| fmt.Fprint(w, `{"number":1}`) | |||||
| }) | |||||
| milestone, _, err := client.Issues.GetMilestone("o", "r", 1) | |||||
| if err != nil { | |||||
| t.Errorf("IssuesService.GetMilestone returned error: %v", err) | |||||
| } | |||||
| want := &Milestone{Number: Int(1)} | |||||
| if !reflect.DeepEqual(milestone, want) { | |||||
| t.Errorf("IssuesService.GetMilestone returned %+v, want %+v", milestone, want) | |||||
| } | |||||
| } | |||||
| func TestIssuesService_GetMilestone_invalidOwner(t *testing.T) { | |||||
| _, _, err := client.Issues.GetMilestone("%", "r", 1) | |||||
| testURLParseError(t, err) | |||||
| } | |||||
| func TestIssuesService_CreateMilestone(t *testing.T) { | |||||
| setup() | |||||
| defer teardown() | |||||
| input := &Milestone{Title: String("t")} | |||||
| mux.HandleFunc("/repos/o/r/milestones", func(w http.ResponseWriter, r *http.Request) { | |||||
| v := new(Milestone) | |||||
| json.NewDecoder(r.Body).Decode(v) | |||||
| testMethod(t, r, "POST") | |||||
| if !reflect.DeepEqual(v, input) { | |||||
| t.Errorf("Request body = %+v, want %+v", v, input) | |||||
| } | |||||
| fmt.Fprint(w, `{"number":1}`) | |||||
| }) | |||||
| milestone, _, err := client.Issues.CreateMilestone("o", "r", input) | |||||
| if err != nil { | |||||
| t.Errorf("IssuesService.CreateMilestone returned error: %v", err) | |||||
| } | |||||
| want := &Milestone{Number: Int(1)} | |||||
| if !reflect.DeepEqual(milestone, want) { | |||||
| t.Errorf("IssuesService.CreateMilestone returned %+v, want %+v", milestone, want) | |||||
| } | |||||
| } | |||||
| func TestIssuesService_CreateMilestone_invalidOwner(t *testing.T) { | |||||
| _, _, err := client.Issues.CreateMilestone("%", "r", nil) | |||||
| testURLParseError(t, err) | |||||
| } | |||||
| func TestIssuesService_EditMilestone(t *testing.T) { | |||||
| setup() | |||||
| defer teardown() | |||||
| input := &Milestone{Title: String("t")} | |||||
| mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) { | |||||
| v := new(Milestone) | |||||
| json.NewDecoder(r.Body).Decode(v) | |||||
| testMethod(t, r, "PATCH") | |||||
| if !reflect.DeepEqual(v, input) { | |||||
| t.Errorf("Request body = %+v, want %+v", v, input) | |||||
| } | |||||
| fmt.Fprint(w, `{"number":1}`) | |||||
| }) | |||||
| milestone, _, err := client.Issues.EditMilestone("o", "r", 1, input) | |||||
| if err != nil { | |||||
| t.Errorf("IssuesService.EditMilestone returned error: %v", err) | |||||
| } | |||||
| want := &Milestone{Number: Int(1)} | |||||
| if !reflect.DeepEqual(milestone, want) { | |||||
| t.Errorf("IssuesService.EditMilestone returned %+v, want %+v", milestone, want) | |||||
| } | |||||
| } | |||||
| func TestIssuesService_EditMilestone_invalidOwner(t *testing.T) { | |||||
| _, _, err := client.Issues.EditMilestone("%", "r", 1, nil) | |||||
| testURLParseError(t, err) | |||||
| } | |||||
| func TestIssuesService_DeleteMilestone(t *testing.T) { | |||||
| setup() | |||||
| defer teardown() | |||||
| mux.HandleFunc("/repos/o/r/milestones/1", func(w http.ResponseWriter, r *http.Request) { | |||||
| testMethod(t, r, "DELETE") | |||||
| }) | |||||
| _, err := client.Issues.DeleteMilestone("o", "r", 1) | |||||
| if err != nil { | |||||
| t.Errorf("IssuesService.DeleteMilestone returned error: %v", err) | |||||
| } | |||||
| } | |||||
| func TestIssuesService_DeleteMilestone_invalidOwner(t *testing.T) { | |||||
| _, err := client.Issues.DeleteMilestone("%", "r", 1) | |||||
| testURLParseError(t, err) | |||||
| } | |||||