From 8fcda0442e60209d7e6783c95d96f20ff04dbdd6 Mon Sep 17 00:00:00 2001 From: Ethan Koenig Date: Wed, 14 Jun 2017 23:09:03 -0400 Subject: [PATCH] Fix search by issue type (#1914) * Fix search by issue type --- integrations/issue_test.go | 50 ++++++++++++++++++++++++++++++++ models/issue.go | 52 +++++++++------------------------- models/unit_tests.go | 40 +++++++++++++++++++++----- routers/repo/issue.go | 12 +++++++- templates/repo/issue/list.tmpl | 26 +++++++++-------- 5 files changed, 121 insertions(+), 59 deletions(-) diff --git a/integrations/issue_test.go b/integrations/issue_test.go index 3b486dc50..f94f11a86 100644 --- a/integrations/issue_test.go +++ b/integrations/issue_test.go @@ -6,11 +6,30 @@ package integrations import ( "net/http" + "strconv" + "strings" "testing" + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/setting" + + "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" ) +func getIssuesSelection(htmlDoc *HtmlDoc) *goquery.Selection { + return htmlDoc.doc.Find(".issue.list").Find("li").Find(".title") +} + +func getIssue(t *testing.T, repoID int64, issueSelection *goquery.Selection) *models.Issue { + href, exists := issueSelection.Attr("href") + assert.True(t, exists) + indexStr := href[strings.LastIndexByte(href, '/')+1:] + index, err := strconv.Atoi(indexStr) + assert.NoError(t, err, "Invalid issue href: %s", href) + return models.AssertExistsAndLoadBean(t, &models.Issue{RepoID: repoID, Index: int64(index)}).(*models.Issue) +} + func TestNoLoginViewIssues(t *testing.T) { prepareTestEnv(t) @@ -19,6 +38,37 @@ func TestNoLoginViewIssues(t *testing.T) { assert.EqualValues(t, http.StatusOK, resp.HeaderCode) } +func TestNoLoginViewIssuesSortByType(t *testing.T) { + prepareTestEnv(t) + + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + repo.Owner = models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User) + + session := loginUser(t, user.Name, "password") + req := NewRequest(t, "GET", repo.RelLink()+"/issues?type=created_by") + resp := session.MakeRequest(t, req) + assert.EqualValues(t, http.StatusOK, resp.HeaderCode) + + htmlDoc, err := NewHtmlParser(resp.Body) + assert.NoError(t, err) + issuesSelection := getIssuesSelection(htmlDoc) + expectedNumIssues := models.GetCount(t, + &models.Issue{RepoID: repo.ID, PosterID: user.ID}, + models.Cond("is_closed=?", false), + models.Cond("is_pull=?", false), + ) + if expectedNumIssues > setting.UI.IssuePagingNum { + expectedNumIssues = setting.UI.IssuePagingNum + } + assert.EqualValues(t, expectedNumIssues, issuesSelection.Length()) + + issuesSelection.Each(func(_ int, selection *goquery.Selection) { + issue := getIssue(t, repo.ID, selection) + assert.EqualValues(t, user.ID, issue.PosterID) + }) +} + func TestNoLoginViewIssue(t *testing.T) { prepareTestEnv(t) diff --git a/models/issue.go b/models/issue.go index 8340595fc..d4d0a5a2f 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1223,7 +1223,6 @@ func parseCountResult(results []map[string][]byte) int64 { // IssueStatsOptions contains parameters accepted by GetIssueStats. type IssueStatsOptions struct { - FilterMode int RepoID int64 Labels string MilestoneID int64 @@ -1241,7 +1240,7 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) { countSession := func(opts *IssueStatsOptions) *xorm.Session { sess := x. Where("issue.repo_id = ?", opts.RepoID). - And("is_pull = ?", opts.IsPull) + And("issue.is_pull = ?", opts.IsPull) if len(opts.IssueIDs) > 0 { sess.In("issue.id", opts.IssueIDs) @@ -1252,8 +1251,8 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) { if err != nil { log.Warn("Malformed Labels argument: %s", opts.Labels) } else if len(labelIDs) > 0 { - sess.Join("INNER", "issue_label", "issue.id = issue_id"). - In("label_id", labelIDs) + sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id"). + In("issue_label.label_id", labelIDs) } } @@ -1262,11 +1261,11 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) { } if opts.AssigneeID > 0 { - sess.And("assignee_id = ?", opts.AssigneeID) + sess.And("issue.assignee_id = ?", opts.AssigneeID) } if opts.PosterID > 0 { - sess.And("poster_id = ?", opts.PosterID) + sess.And("issue.poster_id = ?", opts.PosterID) } if opts.MentionedID > 0 { @@ -1279,40 +1278,15 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) { } var err error - switch opts.FilterMode { - case FilterModeAll, FilterModeAssign: - stats.OpenCount, err = countSession(opts). - And("is_closed = ?", false). - Count(new(Issue)) - - stats.ClosedCount, err = countSession(opts). - And("is_closed = ?", true). - Count(new(Issue)) - case FilterModeCreate: - stats.OpenCount, err = countSession(opts). - And("poster_id = ?", opts.PosterID). - And("is_closed = ?", false). - Count(new(Issue)) - - stats.ClosedCount, err = countSession(opts). - And("poster_id = ?", opts.PosterID). - And("is_closed = ?", true). - Count(new(Issue)) - case FilterModeMention: - stats.OpenCount, err = countSession(opts). - Join("INNER", "issue_user", "issue.id = issue_user.issue_id"). - And("issue_user.uid = ?", opts.PosterID). - And("issue_user.is_mentioned = ?", true). - And("issue.is_closed = ?", false). - Count(new(Issue)) - - stats.ClosedCount, err = countSession(opts). - Join("INNER", "issue_user", "issue.id = issue_user.issue_id"). - And("issue_user.uid = ?", opts.PosterID). - And("issue_user.is_mentioned = ?", true). - And("issue.is_closed = ?", true). - Count(new(Issue)) + stats.OpenCount, err = countSession(opts). + And("issue.is_closed = ?", false). + Count(new(Issue)) + if err != nil { + return stats, err } + stats.ClosedCount, err = countSession(opts). + And("issue.is_closed = ?", true). + Count(new(Issue)) return stats, err } diff --git a/models/unit_tests.go b/models/unit_tests.go index a3459e49f..16eb09968 100644 --- a/models/unit_tests.go +++ b/models/unit_tests.go @@ -37,13 +37,31 @@ func PrepareTestDatabase() error { return LoadFixtures() } +type testCond struct { + query interface{} + args []interface{} +} + +// Cond create a condition with arguments for a test +func Cond(query interface{}, args ...interface{}) interface{} { + return &testCond{query: query, args: args} +} + +func whereConditions(sess *xorm.Session, conditions []interface{}) { + for _, condition := range conditions { + switch cond := condition.(type) { + case *testCond: + sess.Where(cond.query, cond.args...) + default: + sess.Where(cond) + } + } +} + func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) { sess := x.NewSession() defer sess.Close() - - for _, cond := range conditions { - sess = sess.Where(cond) - } + whereConditions(sess, conditions) return sess.Get(bean) } @@ -65,6 +83,16 @@ func AssertExistsAndLoadBean(t *testing.T, bean interface{}, conditions ...inter return bean } +// GetCount get the count of a bean +func GetCount(t *testing.T, bean interface{}, conditions ...interface{}) int { + sess := x.NewSession() + defer sess.Close() + whereConditions(sess, conditions) + count, err := sess.Count(bean) + assert.NoError(t, err) + return int(count) +} + // AssertNotExistsBean assert that a bean does not exist in the test database func AssertNotExistsBean(t *testing.T, bean interface{}, conditions ...interface{}) { exists, err := loadBeanIfExists(bean, conditions...) @@ -80,7 +108,5 @@ func AssertSuccessfulInsert(t *testing.T, beans ...interface{}) { // AssertCount assert the count of a bean func AssertCount(t *testing.T, bean interface{}, expected interface{}) { - actual, err := x.Count(bean) - assert.NoError(t, err) - assert.EqualValues(t, expected, actual) + assert.EqualValues(t, expected, GetCount(t, bean)) } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index c54cd2843..b94eddc4e 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -120,6 +120,15 @@ func Issues(ctx *context.Context) { forceEmpty bool ) + if ctx.IsSigned { + switch viewType { + case "created_by": + posterID = ctx.User.ID + case "mentioned": + mentionedID = ctx.User.ID + } + } + repo := ctx.Repo.Repository selectLabels := ctx.Query("labels") milestoneID := ctx.QueryInt64("milestone") @@ -150,11 +159,12 @@ func Issues(ctx *context.Context) { MilestoneID: milestoneID, AssigneeID: assigneeID, MentionedID: mentionedID, + PosterID: posterID, IsPull: isPullList, IssueIDs: issueIDs, }) if err != nil { - ctx.Error(500, "GetSearchIssueStats") + ctx.Handle(500, "GetIssueStats", err) return } } diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 863ae6a74..8de52fb23 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -68,19 +68,21 @@ - -