code.gitea.io/gitea@v1.22.3/tests/integration/api_comment_test.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "fmt" 8 "net/http" 9 "net/url" 10 "testing" 11 12 auth_model "code.gitea.io/gitea/models/auth" 13 "code.gitea.io/gitea/models/db" 14 issues_model "code.gitea.io/gitea/models/issues" 15 repo_model "code.gitea.io/gitea/models/repo" 16 "code.gitea.io/gitea/models/unittest" 17 user_model "code.gitea.io/gitea/models/user" 18 api "code.gitea.io/gitea/modules/structs" 19 "code.gitea.io/gitea/services/convert" 20 "code.gitea.io/gitea/tests" 21 22 "github.com/stretchr/testify/assert" 23 ) 24 25 func TestAPIListRepoComments(t *testing.T) { 26 defer tests.PrepareTestEnv(t)() 27 28 comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{}, 29 unittest.Cond("type = ?", issues_model.CommentTypeComment)) 30 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) 31 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 32 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 33 34 link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments", repoOwner.Name, repo.Name)) 35 req := NewRequest(t, "GET", link.String()) 36 resp := MakeRequest(t, req, http.StatusOK) 37 38 var apiComments []*api.Comment 39 DecodeJSON(t, resp, &apiComments) 40 assert.Len(t, apiComments, 2) 41 for _, apiComment := range apiComments { 42 c := &issues_model.Comment{ID: apiComment.ID} 43 unittest.AssertExistsAndLoadBean(t, c, 44 unittest.Cond("type = ?", issues_model.CommentTypeComment)) 45 unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: c.IssueID, RepoID: repo.ID}) 46 } 47 48 // test before and since filters 49 query := url.Values{} 50 before := "2000-01-01T00:00:11+00:00" // unix: 946684811 51 since := "2000-01-01T00:00:12+00:00" // unix: 946684812 52 query.Add("before", before) 53 link.RawQuery = query.Encode() 54 req = NewRequest(t, "GET", link.String()) 55 resp = MakeRequest(t, req, http.StatusOK) 56 DecodeJSON(t, resp, &apiComments) 57 assert.Len(t, apiComments, 1) 58 assert.EqualValues(t, 2, apiComments[0].ID) 59 60 query.Del("before") 61 query.Add("since", since) 62 link.RawQuery = query.Encode() 63 req = NewRequest(t, "GET", link.String()) 64 resp = MakeRequest(t, req, http.StatusOK) 65 DecodeJSON(t, resp, &apiComments) 66 assert.Len(t, apiComments, 1) 67 assert.EqualValues(t, 3, apiComments[0].ID) 68 } 69 70 func TestAPIListIssueComments(t *testing.T) { 71 defer tests.PrepareTestEnv(t)() 72 73 comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{}, 74 unittest.Cond("type = ?", issues_model.CommentTypeComment)) 75 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) 76 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 77 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 78 79 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeReadIssue) 80 req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/comments", repoOwner.Name, repo.Name, issue.Index). 81 AddTokenAuth(token) 82 resp := MakeRequest(t, req, http.StatusOK) 83 84 var comments []*api.Comment 85 DecodeJSON(t, resp, &comments) 86 expectedCount := unittest.GetCount(t, &issues_model.Comment{IssueID: issue.ID}, 87 unittest.Cond("type = ?", issues_model.CommentTypeComment)) 88 assert.Len(t, comments, expectedCount) 89 } 90 91 func TestAPICreateComment(t *testing.T) { 92 defer tests.PrepareTestEnv(t)() 93 const commentBody = "Comment body" 94 95 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{}) 96 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 97 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 98 99 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue) 100 urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments", 101 repoOwner.Name, repo.Name, issue.Index) 102 req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ 103 "body": commentBody, 104 }).AddTokenAuth(token) 105 resp := MakeRequest(t, req, http.StatusCreated) 106 107 var updatedComment api.Comment 108 DecodeJSON(t, resp, &updatedComment) 109 assert.EqualValues(t, commentBody, updatedComment.Body) 110 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: updatedComment.ID, IssueID: issue.ID, Content: commentBody}) 111 112 t.Run("BlockedByRepoOwner", func(t *testing.T) { 113 defer tests.PrintCurrentTest(t)() 114 115 user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34}) 116 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) 117 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 118 119 req := NewRequestWithValues(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments", repo.OwnerName, repo.Name, issue.Index), map[string]string{ 120 "body": commentBody, 121 }).AddTokenAuth(getUserToken(t, user34.Name, auth_model.AccessTokenScopeWriteRepository)) 122 MakeRequest(t, req, http.StatusForbidden) 123 }) 124 125 t.Run("BlockedByIssuePoster", func(t *testing.T) { 126 defer tests.PrintCurrentTest(t)() 127 128 user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34}) 129 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 13}) 130 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 131 132 req := NewRequestWithValues(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments", repo.OwnerName, repo.Name, issue.Index), map[string]string{ 133 "body": commentBody, 134 }).AddTokenAuth(getUserToken(t, user34.Name, auth_model.AccessTokenScopeWriteRepository)) 135 MakeRequest(t, req, http.StatusForbidden) 136 }) 137 } 138 139 func TestAPIGetComment(t *testing.T) { 140 defer tests.PrepareTestEnv(t)() 141 142 comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2}) 143 assert.NoError(t, comment.LoadIssue(db.DefaultContext)) 144 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID}) 145 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 146 147 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeReadIssue) 148 req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID) 149 MakeRequest(t, req, http.StatusOK) 150 req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID). 151 AddTokenAuth(token) 152 resp := MakeRequest(t, req, http.StatusOK) 153 154 var apiComment api.Comment 155 DecodeJSON(t, resp, &apiComment) 156 157 assert.NoError(t, comment.LoadPoster(db.DefaultContext)) 158 expect := convert.ToAPIComment(db.DefaultContext, repo, comment) 159 160 assert.Equal(t, expect.ID, apiComment.ID) 161 assert.Equal(t, expect.Poster.FullName, apiComment.Poster.FullName) 162 assert.Equal(t, expect.Body, apiComment.Body) 163 assert.Equal(t, expect.Created.Unix(), apiComment.Created.Unix()) 164 } 165 166 func TestAPIGetSystemUserComment(t *testing.T) { 167 defer tests.PrepareTestEnv(t)() 168 169 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{}) 170 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 171 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 172 173 for _, systemUser := range []*user_model.User{ 174 user_model.NewGhostUser(), 175 user_model.NewActionsUser(), 176 } { 177 body := fmt.Sprintf("Hello %s", systemUser.Name) 178 comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{ 179 Type: issues_model.CommentTypeComment, 180 Doer: systemUser, 181 Repo: repo, 182 Issue: issue, 183 Content: body, 184 }) 185 assert.NoError(t, err) 186 187 req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID) 188 resp := MakeRequest(t, req, http.StatusOK) 189 190 var apiComment api.Comment 191 DecodeJSON(t, resp, &apiComment) 192 193 if assert.NotNil(t, apiComment.Poster) { 194 if assert.Equal(t, systemUser.ID, apiComment.Poster.ID) { 195 assert.NoError(t, comment.LoadPoster(db.DefaultContext)) 196 assert.Equal(t, systemUser.Name, apiComment.Poster.UserName) 197 } 198 } 199 assert.Equal(t, body, apiComment.Body) 200 } 201 } 202 203 func TestAPIEditComment(t *testing.T) { 204 defer tests.PrepareTestEnv(t)() 205 const newCommentBody = "This is the new comment body" 206 207 comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 8}, 208 unittest.Cond("type = ?", issues_model.CommentTypeComment)) 209 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) 210 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 211 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 212 213 t.Run("UnrelatedCommentID", func(t *testing.T) { 214 // Using the ID of a comment that does not belong to the repository must fail 215 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) 216 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 217 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue) 218 urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d", 219 repoOwner.Name, repo.Name, comment.ID) 220 req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{ 221 "body": newCommentBody, 222 }).AddTokenAuth(token) 223 MakeRequest(t, req, http.StatusNotFound) 224 }) 225 226 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue) 227 urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d", 228 repoOwner.Name, repo.Name, comment.ID) 229 req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{ 230 "body": newCommentBody, 231 }).AddTokenAuth(token) 232 resp := MakeRequest(t, req, http.StatusOK) 233 234 var updatedComment api.Comment 235 DecodeJSON(t, resp, &updatedComment) 236 assert.EqualValues(t, comment.ID, updatedComment.ID) 237 assert.EqualValues(t, newCommentBody, updatedComment.Body) 238 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: comment.ID, IssueID: issue.ID, Content: newCommentBody}) 239 } 240 241 func TestAPIDeleteComment(t *testing.T) { 242 defer tests.PrepareTestEnv(t)() 243 244 comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 8}, 245 unittest.Cond("type = ?", issues_model.CommentTypeComment)) 246 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) 247 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 248 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 249 250 t.Run("UnrelatedCommentID", func(t *testing.T) { 251 // Using the ID of a comment that does not belong to the repository must fail 252 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) 253 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 254 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue) 255 req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID). 256 AddTokenAuth(token) 257 MakeRequest(t, req, http.StatusNotFound) 258 }) 259 260 token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue) 261 req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d", repoOwner.Name, repo.Name, comment.ID). 262 AddTokenAuth(token) 263 MakeRequest(t, req, http.StatusNoContent) 264 265 unittest.AssertNotExistsBean(t, &issues_model.Comment{ID: comment.ID}) 266 } 267 268 func TestAPIListIssueTimeline(t *testing.T) { 269 defer tests.PrepareTestEnv(t)() 270 271 // load comment 272 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) 273 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) 274 repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 275 276 // make request 277 req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/timeline", repoOwner.Name, repo.Name, issue.Index) 278 resp := MakeRequest(t, req, http.StatusOK) 279 280 // check if lens of list returned by API and 281 // lists extracted directly from DB are the same 282 var comments []*api.TimelineComment 283 DecodeJSON(t, resp, &comments) 284 expectedCount := unittest.GetCount(t, &issues_model.Comment{IssueID: issue.ID}) 285 assert.Len(t, comments, expectedCount) 286 }