diff --git a/gitea/client.go b/gitea/client.go index 2877f86..3c72db5 100644 --- a/gitea/client.go +++ b/gitea/client.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2020 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -21,7 +22,7 @@ func Version() string { return "0.12.3" } -// Client represents a Gogs API client. +// Client represents a Gitea API client. type Client struct { url string accessToken string diff --git a/gitea/issue.go b/gitea/issue.go index f1711f6..a6e42e1 100644 --- a/gitea/issue.go +++ b/gitea/issue.go @@ -9,6 +9,7 @@ import ( "bytes" "encoding/json" "fmt" + "net/url" "time" ) @@ -44,26 +45,80 @@ type Issue struct { // ListIssueOption list issue options type ListIssueOption struct { - Page int - State string + Page int + // open, closed, all + State string + Labels []string + KeyWord string +} + +func (opt *ListIssueOption) QueryEncode() string { + query := make(url.Values) + if opt.Page > 0 { + query.Add("page", fmt.Sprintf("%d", opt.Page)) + } + if len(opt.State) > 0 { + query.Add("state", opt.State) + } + + if opt.Page > 0 { + query.Add("page", fmt.Sprintf("%d", opt.Page)) + } + if len(opt.State) > 0 { + query.Add("state", opt.State) + } + if len(opt.Labels) > 0 { + var lq string + for _, l := range opt.Labels { + if len(lq) > 0 { + lq += "," + } + lq += l + } + query.Add("labels", lq) + } + if len(opt.KeyWord) > 0 { + query.Add("q", opt.KeyWord) + } + + return query.Encode() } // ListIssues returns all issues assigned the authenticated user func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, error) { + link, _ := url.Parse("/repos/issues/search") issues := make([]*Issue, 0, 10) - return issues, c.getParsedResponse("GET", fmt.Sprintf("/issues?page=%d", opt.Page), nil, nil, &issues) + link.RawQuery = opt.QueryEncode() + return issues, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) } // ListUserIssues returns all issues assigned to the authenticated user func (c *Client) ListUserIssues(opt ListIssueOption) ([]*Issue, error) { + // WARNING: "/user/issues" API is not implemented jet! + allIssues, err := c.ListIssues(opt) + if err != nil { + return nil, err + } + user, err := c.GetMyUserInfo() + if err != nil { + return nil, err + } + // Workaround: client sort out non user related issues issues := make([]*Issue, 0, 10) - return issues, c.getParsedResponse("GET", fmt.Sprintf("/user/issues?page=%d", opt.Page), nil, nil, &issues) + for _, i := range allIssues { + if i.ID == user.ID { + issues = append(issues, i) + } + } + return issues, nil } // ListRepoIssues returns all issues for a given repository func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) { + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo)) issues := make([]*Issue, 0, 10) - return issues, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues?page=%d", owner, repo, opt.Page), nil, nil, &issues) + link.RawQuery = opt.QueryEncode() + return issues, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) } // GetIssue returns a single issue for a given repository diff --git a/gitea/issue_test.go b/gitea/issue_test.go new file mode 100644 index 0000000..72607f7 --- /dev/null +++ b/gitea/issue_test.go @@ -0,0 +1,102 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "log" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +// TestIssue is main func witch call all Tests for Issue API +// (to make sure they are on correct order) +func TestIssue(t *testing.T) { + c := newTestClient() + + createIssue(t, c) + listIssues(t, c) +} + +func createIssue(t *testing.T, c *Client) { + log.Println("== TestCreateIssues ==") + + user, err := c.GetMyUserInfo() + assert.NoError(t, err) + repo, _ := createTestRepo(t, "IssueTestsRepo", c) + + createOne := func(title, body string, assignees []string, deadline *time.Time, milestone int64, labels []int64, closed, shouldFail bool) { + issue, e := c.CreateIssue(user.UserName, repo.Name, CreateIssueOption{ + Title: title, + Body: body, + Assignees: assignees, + Deadline: deadline, + Milestone: milestone, + Labels: labels, + Closed: closed, + }) + if shouldFail { + assert.Error(t, e) + return + } + assert.NoError(t, e) + assert.NotEmpty(t, issue) + assert.EqualValues(t, title, issue.Title) + assert.EqualValues(t, body, issue.Body) + assert.EqualValues(t, len(assignees), len(issue.Assignees)) + for i, a := range issue.Assignees { + assert.EqualValues(t, assignees[i], a.UserName) + } + if milestone > 0 { + assert.EqualValues(t, milestone, issue.Milestone.ID) + } + assert.EqualValues(t, len(labels), len(issue.Labels)) + if closed { + assert.False(t, issue.Closed.IsZero()) + } else { + assert.Empty(t, issue.Closed) + } + } + + nowTime := time.Now() + mile, _ := c.CreateMilestone(user.UserName, repo.Name, CreateMilestoneOption{Title: "mile1"}) + label1, _ := c.CreateLabel(user.UserName, repo.Name, CreateLabelOption{Name: "Label1", Description: "a", Color: "#ee0701"}) + label2, _ := c.CreateLabel(user.UserName, repo.Name, CreateLabelOption{Name: "Label2", Description: "b", Color: "#128a0c"}) + + createOne("First Issue", "", nil, nil, 0, nil, false, false) + createOne("Issue 2", "closed isn't it?", nil, nil, 0, nil, true, false) + createOne("Issue 3", "", nil, nil, 0, nil, true, false) + createOne("Feature: spam protect 4", "explain explain explain", []string{user.UserName}, &nowTime, 0, nil, true, false) + createOne("W 123", "", nil, &nowTime, mile.ID, nil, false, false) + createOne("First Issue", "", nil, nil, 0, nil, false, false) + createOne("Do it soon!", "is important!", []string{user.UserName}, &nowTime, mile.ID, []int64{label1.ID, label2.ID}, false, false) + createOne("Job Done", "you never know", nil, nil, mile.ID, []int64{label2.ID}, true, false) + createOne("", "you never know", nil, nil, mile.ID, nil, true, true) +} + +func listIssues(t *testing.T, c *Client) { + log.Println("== TestListIssues ==") + + issues, err := c.ListRepoIssues("test01", "IssueTestsRepo", ListIssueOption{ + Labels: []string{"Label2"}, + KeyWord: "", + State: "all", + }) + assert.NoError(t, err) + assert.Len(t, issues, 2) + + issues, err = c.ListIssues(ListIssueOption{ + Labels: []string{"Label2"}, + KeyWord: "Done", + State: "", + }) + assert.NoError(t, err) + assert.Len(t, issues, 1) + + issues, err = c.ListRepoIssues("test01", "IssueTestsRepo", ListIssueOption{}) + assert.NoError(t, err) + assert.Len(t, issues, 4) +} diff --git a/gitea/main_test.go b/gitea/main_test.go index e04fced..79eb98c 100644 --- a/gitea/main_test.go +++ b/gitea/main_test.go @@ -43,7 +43,6 @@ func newTestClient() *Client { token := getGiteaToken() if token == "" { client := NewClientWithHTTP(getGiteaURL(), &http.Client{}) - log.Printf("testing with %v, %v, %v\n", getGiteaURL(), getGiteaUsername(), getGiteaPassword()) client.SetBasicAuth(getGiteaUsername(), getGiteaPassword()) return client } @@ -151,6 +150,7 @@ func TestMain(m *testing.M) { p.Kill() }() } + log.Printf("testing with %v, %v, %v\n", getGiteaURL(), getGiteaUsername(), getGiteaPassword()) exitCode := m.Run() os.Exit(exitCode) } diff --git a/gitea/pull_test.go b/gitea/pull_test.go index f1f3dcd..7c391eb 100644 --- a/gitea/pull_test.go +++ b/gitea/pull_test.go @@ -5,30 +5,22 @@ package gitea import ( + "log" "testing" "github.com/stretchr/testify/assert" ) func TestPull(t *testing.T) { + log.Println("== TestPull ==") c := newTestClient() user, err := c.GetMyUserInfo() assert.NoError(t, err) var repoName = "repo_pull_test" - repo, err := c.GetRepo(user.UserName, repoName) + _, err = createTestRepo(t, repoName, c) if err != nil { - repo, err = c.CreateRepo(CreateRepoOption{ - Name: repoName, - Description: "PullTests", - AutoInit: true, - Gitignores: "C,C++", - License: "MIT", - Readme: "Default", - Private: false, - }) - assert.NoError(t, err) - assert.NotNil(t, repo) + return } // ListRepoPullRequests list PRs of one repository diff --git a/gitea/repo_test.go b/gitea/repo_test.go index bbd8d9e..f46e735 100644 --- a/gitea/repo_test.go +++ b/gitea/repo_test.go @@ -5,12 +5,14 @@ package gitea import ( + "log" "testing" "github.com/stretchr/testify/assert" ) func TestCreateRepo(t *testing.T) { + log.Println("== TestCreateRepo ==") c := newTestClient() user, err := c.GetMyUserInfo() assert.NoError(t, err) @@ -28,3 +30,34 @@ func TestCreateRepo(t *testing.T) { err = c.DeleteRepo(user.UserName, repoName) assert.NoError(t, err) } + +func TestDeleteRepo(t *testing.T) { + log.Println("== TestDeleteRepo ==") + c := newTestClient() + repo, _ := createTestRepo(t, "TestDeleteRepo", c) + assert.NoError(t, c.DeleteRepo(repo.Owner.UserName, repo.Name)) +} + +// standard func to create a init repo for test routines +func createTestRepo(t *testing.T, name string, c *Client) (*Repository, error) { + user, uErr := c.GetMyUserInfo() + assert.NoError(t, uErr) + _, err := c.GetRepo(user.UserName, name) + if err == nil { + _ = c.DeleteRepo(user.UserName, name) + } + repo, err := c.CreateRepo(CreateRepoOption{ + Name: name, + Description: "A test Repo: " + name, + AutoInit: true, + Gitignores: "C,C++", + License: "MIT", + Readme: "Default", + IssueLabels: "Default", + Private: false, + }) + assert.NoError(t, err) + assert.NotNil(t, repo) + + return repo, err +}