From 909bff1a52ed30e1cb34a1eb23d2ec801dbe845d Mon Sep 17 00:00:00 2001 From: Oleks Date: Fri, 15 May 2026 15:47:36 +0300 Subject: [PATCH] test(api): add MoveProjectIssue integration test for repo project scope The repo-scope POST .../projects/{id}/issues/{issue_id}/move handler had no test coverage. Adds testAPIMoveProjectIssue with happy-path move, 422 on non-existent target column, and 404 when the issue isn't in the project. --- tests/integration/api_repo_project_test.go | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/integration/api_repo_project_test.go b/tests/integration/api_repo_project_test.go index 0fc9ea25d2..596184fcb8 100644 --- a/tests/integration/api_repo_project_test.go +++ b/tests/integration/api_repo_project_test.go @@ -36,9 +36,62 @@ func TestAPIProjects(t *testing.T) { t.Run("AddIssueToProjectColumn", testAPIAddIssueToProjectColumn) t.Run("RemoveIssueFromProjectColumn", testAPIRemoveIssueFromProjectColumn) t.Run("ListProjectColumnIssues", testAPIListProjectColumnIssues) + t.Run("MoveProjectIssue", testAPIMoveProjectIssue) t.Run("Permissions", testAPIProjectPermissions) } +func testAPIMoveProjectIssue(t *testing.T) { + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + issueA := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) + + project := &project_model.Project{ + Title: "Project for MoveIssue", + RepoID: repo.ID, + Type: project_model.TypeRepository, + CreatorID: owner.ID, + TemplateType: project_model.TemplateTypeNone, + } + err := project_model.NewProject(t.Context(), project) + assert.NoError(t, err) + + colA := &project_model.Column{Title: "A", ProjectID: project.ID, CreatorID: owner.ID} + err = project_model.NewColumn(t.Context(), colA) + assert.NoError(t, err) + colB := &project_model.Column{Title: "B", ProjectID: project.ID, CreatorID: owner.ID} + err = project_model.NewColumn(t.Context(), colB) + assert.NoError(t, err) + + err = issues_model.IssueAssignOrRemoveProject(t.Context(), issueA, owner, []int64{project.ID}) + assert.NoError(t, err) + err = projects_service.MoveIssuesOnProjectColumn(t.Context(), owner, colA, map[int64]int64{0: issueA.ID}) + assert.NoError(t, err) + + token := getUserToken(t, owner.Name, auth_model.AccessTokenScopeWriteIssue) + + req := NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/projects/%d/issues/%d/move", owner.Name, repo.Name, project.ID, issueA.ID), + &api.MoveProjectIssueOption{ColumnID: colB.ID}, + ).AddTokenAuth(token) + MakeRequest(t, req, http.StatusNoContent) + + pi := unittest.AssertExistsAndLoadBean(t, &project_model.ProjectIssue{ProjectID: project.ID, IssueID: issueA.ID}) + assert.Equal(t, colB.ID, pi.ProjectColumnID) + + req = NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/projects/%d/issues/%d/move", owner.Name, repo.Name, project.ID, issueA.ID), + &api.MoveProjectIssueOption{ColumnID: 99999}, + ).AddTokenAuth(token) + MakeRequest(t, req, http.StatusUnprocessableEntity) + + issueB := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}) + req = NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/projects/%d/issues/%d/move", owner.Name, repo.Name, project.ID, issueB.ID), + &api.MoveProjectIssueOption{ColumnID: colA.ID}, + ).AddTokenAuth(token) + MakeRequest(t, req, http.StatusNotFound) +} + func testAPIListProjects(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})