diff --git a/modules/indexer/issues/dboptions.go b/modules/indexer/issues/dboptions.go index 4a98b4588a..15363847ce 100644 --- a/modules/indexer/issues/dboptions.go +++ b/modules/indexer/issues/dboptions.go @@ -38,6 +38,12 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp searchOpt.MilestoneIDs = opts.MilestoneIDs } + if opts.ProjectID > 0 { + searchOpt.ProjectID = optional.Some(opts.ProjectID) + } else if opts.ProjectID == -1 { // FIXME: this is inconsistent from other places + searchOpt.ProjectID = optional.Some[int64](0) // Those issues with no project(projectid==0) + } + // See the comment of issues_model.SearchOptions for the reason why we need to convert convertID := func(id int64) optional.Option[int64] { if id > 0 { @@ -49,7 +55,6 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp return nil } - searchOpt.ProjectID = convertID(opts.ProjectID) searchOpt.ProjectBoardID = convertID(opts.ProjectBoardID) searchOpt.PosterID = convertID(opts.PosterID) searchOpt.AssigneeID = convertID(opts.AssigneeID) diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index 94ba670b71..3f61dafbf0 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" + project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" @@ -121,6 +122,57 @@ func TestViewIssuesKeyword(t *testing.T) { }) } +func TestViewIssuesSearchOptions(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + // there are two issues in repo1, both bound to a project. Add one + // that is not bound to any project. + _, issueNoProject := testIssueWithBean(t, "user2", 1, "Title", "Description") + + t.Run("All issues", func(t *testing.T) { + req := NewRequestf(t, "GET", "%s/issues?state=all", repo.Link()) + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + issuesSelection := getIssuesSelection(t, htmlDoc) + assert.EqualValues(t, 3, issuesSelection.Length()) + }) + + t.Run("Issues with no project", func(t *testing.T) { + req := NewRequestf(t, "GET", "%s/issues?state=all&project=-1", repo.Link()) + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + issuesSelection := getIssuesSelection(t, htmlDoc) + assert.EqualValues(t, 1, issuesSelection.Length()) + issuesSelection.Each(func(_ int, selection *goquery.Selection) { + issue := getIssue(t, repo.ID, selection) + assert.Equal(t, issueNoProject.ID, issue.ID) + }) + }) + + t.Run("Issues with a specific project", func(t *testing.T) { + project := unittest.AssertExistsAndLoadBean(t, &project_model.Project{ID: 1}) + + req := NewRequestf(t, "GET", "%s/issues?state=all&project=%d", repo.Link(), project.ID) + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + issuesSelection := getIssuesSelection(t, htmlDoc) + assert.EqualValues(t, 2, issuesSelection.Length()) + found := map[int64]bool{ + 1: false, + 5: false, + } + issuesSelection.Each(func(_ int, selection *goquery.Selection) { + issue := getIssue(t, repo.ID, selection) + found[issue.ID] = true + }) + assert.EqualValues(t, 2, len(found)) + assert.True(t, found[1]) + assert.True(t, found[5]) + }) +} + func TestNoLoginViewIssue(t *testing.T) { defer tests.PrepareTestEnv(t)()