code.gitea.io/gitea@v1.22.3/models/issues/label_test.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package issues_test 5 6 import ( 7 "testing" 8 9 "code.gitea.io/gitea/models/db" 10 issues_model "code.gitea.io/gitea/models/issues" 11 repo_model "code.gitea.io/gitea/models/repo" 12 "code.gitea.io/gitea/models/unittest" 13 user_model "code.gitea.io/gitea/models/user" 14 "code.gitea.io/gitea/modules/timeutil" 15 16 "github.com/stretchr/testify/assert" 17 ) 18 19 func TestLabel_CalOpenIssues(t *testing.T) { 20 assert.NoError(t, unittest.PrepareTestDatabase()) 21 label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) 22 label.CalOpenIssues() 23 assert.EqualValues(t, 2, label.NumOpenIssues) 24 } 25 26 func TestLabel_ExclusiveScope(t *testing.T) { 27 assert.NoError(t, unittest.PrepareTestDatabase()) 28 label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 7}) 29 assert.Equal(t, "scope", label.ExclusiveScope()) 30 31 label = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 9}) 32 assert.Equal(t, "scope/subscope", label.ExclusiveScope()) 33 } 34 35 func TestNewLabels(t *testing.T) { 36 assert.NoError(t, unittest.PrepareTestDatabase()) 37 labels := []*issues_model.Label{ 38 {RepoID: 2, Name: "labelName2", Color: "#123456"}, 39 {RepoID: 3, Name: "labelName3", Color: "#123"}, 40 {RepoID: 4, Name: "labelName4", Color: "ABCDEF"}, 41 {RepoID: 5, Name: "labelName5", Color: "DEF"}, 42 } 43 assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: ""})) 44 assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "#45G"})) 45 assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "#12345G"})) 46 assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "45G"})) 47 assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "12345G"})) 48 for _, label := range labels { 49 unittest.AssertNotExistsBean(t, label) 50 } 51 assert.NoError(t, issues_model.NewLabels(db.DefaultContext, labels...)) 52 for _, label := range labels { 53 unittest.AssertExistsAndLoadBean(t, label, unittest.Cond("id = ?", label.ID)) 54 } 55 unittest.CheckConsistencyFor(t, &issues_model.Label{}, &repo_model.Repository{}) 56 } 57 58 func TestGetLabelByID(t *testing.T) { 59 assert.NoError(t, unittest.PrepareTestDatabase()) 60 label, err := issues_model.GetLabelByID(db.DefaultContext, 1) 61 assert.NoError(t, err) 62 assert.EqualValues(t, 1, label.ID) 63 64 _, err = issues_model.GetLabelByID(db.DefaultContext, unittest.NonexistentID) 65 assert.True(t, issues_model.IsErrLabelNotExist(err)) 66 } 67 68 func TestGetLabelInRepoByName(t *testing.T) { 69 assert.NoError(t, unittest.PrepareTestDatabase()) 70 label, err := issues_model.GetLabelInRepoByName(db.DefaultContext, 1, "label1") 71 assert.NoError(t, err) 72 assert.EqualValues(t, 1, label.ID) 73 assert.Equal(t, "label1", label.Name) 74 75 _, err = issues_model.GetLabelInRepoByName(db.DefaultContext, 1, "") 76 assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) 77 78 _, err = issues_model.GetLabelInRepoByName(db.DefaultContext, unittest.NonexistentID, "nonexistent") 79 assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) 80 } 81 82 func TestGetLabelInRepoByNames(t *testing.T) { 83 assert.NoError(t, unittest.PrepareTestDatabase()) 84 labelIDs, err := issues_model.GetLabelIDsInRepoByNames(db.DefaultContext, 1, []string{"label1", "label2"}) 85 assert.NoError(t, err) 86 87 assert.Len(t, labelIDs, 2) 88 89 assert.Equal(t, int64(1), labelIDs[0]) 90 assert.Equal(t, int64(2), labelIDs[1]) 91 } 92 93 func TestGetLabelInRepoByNamesDiscardsNonExistentLabels(t *testing.T) { 94 assert.NoError(t, unittest.PrepareTestDatabase()) 95 // label3 doesn't exists.. See labels.yml 96 labelIDs, err := issues_model.GetLabelIDsInRepoByNames(db.DefaultContext, 1, []string{"label1", "label2", "label3"}) 97 assert.NoError(t, err) 98 99 assert.Len(t, labelIDs, 2) 100 101 assert.Equal(t, int64(1), labelIDs[0]) 102 assert.Equal(t, int64(2), labelIDs[1]) 103 assert.NoError(t, err) 104 } 105 106 func TestGetLabelInRepoByID(t *testing.T) { 107 assert.NoError(t, unittest.PrepareTestDatabase()) 108 label, err := issues_model.GetLabelInRepoByID(db.DefaultContext, 1, 1) 109 assert.NoError(t, err) 110 assert.EqualValues(t, 1, label.ID) 111 112 _, err = issues_model.GetLabelInRepoByID(db.DefaultContext, 1, -1) 113 assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) 114 115 _, err = issues_model.GetLabelInRepoByID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) 116 assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) 117 } 118 119 func TestGetLabelsInRepoByIDs(t *testing.T) { 120 assert.NoError(t, unittest.PrepareTestDatabase()) 121 labels, err := issues_model.GetLabelsInRepoByIDs(db.DefaultContext, 1, []int64{1, 2, unittest.NonexistentID}) 122 assert.NoError(t, err) 123 if assert.Len(t, labels, 2) { 124 assert.EqualValues(t, 1, labels[0].ID) 125 assert.EqualValues(t, 2, labels[1].ID) 126 } 127 } 128 129 func TestGetLabelsByRepoID(t *testing.T) { 130 assert.NoError(t, unittest.PrepareTestDatabase()) 131 testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) { 132 labels, err := issues_model.GetLabelsByRepoID(db.DefaultContext, repoID, sortType, db.ListOptions{}) 133 assert.NoError(t, err) 134 assert.Len(t, labels, len(expectedIssueIDs)) 135 for i, label := range labels { 136 assert.EqualValues(t, expectedIssueIDs[i], label.ID) 137 } 138 } 139 testSuccess(1, "leastissues", []int64{2, 1}) 140 testSuccess(1, "mostissues", []int64{1, 2}) 141 testSuccess(1, "reversealphabetically", []int64{2, 1}) 142 testSuccess(1, "default", []int64{1, 2}) 143 } 144 145 // Org versions 146 147 func TestGetLabelInOrgByName(t *testing.T) { 148 assert.NoError(t, unittest.PrepareTestDatabase()) 149 label, err := issues_model.GetLabelInOrgByName(db.DefaultContext, 3, "orglabel3") 150 assert.NoError(t, err) 151 assert.EqualValues(t, 3, label.ID) 152 assert.Equal(t, "orglabel3", label.Name) 153 154 _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, 3, "") 155 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 156 157 _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, 0, "orglabel3") 158 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 159 160 _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, -1, "orglabel3") 161 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 162 163 _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, unittest.NonexistentID, "nonexistent") 164 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 165 } 166 167 func TestGetLabelInOrgByID(t *testing.T) { 168 assert.NoError(t, unittest.PrepareTestDatabase()) 169 label, err := issues_model.GetLabelInOrgByID(db.DefaultContext, 3, 3) 170 assert.NoError(t, err) 171 assert.EqualValues(t, 3, label.ID) 172 173 _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, 3, -1) 174 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 175 176 _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, 0, 3) 177 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 178 179 _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, -1, 3) 180 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 181 182 _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) 183 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 184 } 185 186 func TestGetLabelsInOrgByIDs(t *testing.T) { 187 assert.NoError(t, unittest.PrepareTestDatabase()) 188 labels, err := issues_model.GetLabelsInOrgByIDs(db.DefaultContext, 3, []int64{3, 4, unittest.NonexistentID}) 189 assert.NoError(t, err) 190 if assert.Len(t, labels, 2) { 191 assert.EqualValues(t, 3, labels[0].ID) 192 assert.EqualValues(t, 4, labels[1].ID) 193 } 194 } 195 196 func TestGetLabelsByOrgID(t *testing.T) { 197 assert.NoError(t, unittest.PrepareTestDatabase()) 198 testSuccess := func(orgID int64, sortType string, expectedIssueIDs []int64) { 199 labels, err := issues_model.GetLabelsByOrgID(db.DefaultContext, orgID, sortType, db.ListOptions{}) 200 assert.NoError(t, err) 201 assert.Len(t, labels, len(expectedIssueIDs)) 202 for i, label := range labels { 203 assert.EqualValues(t, expectedIssueIDs[i], label.ID) 204 } 205 } 206 testSuccess(3, "leastissues", []int64{3, 4}) 207 testSuccess(3, "mostissues", []int64{4, 3}) 208 testSuccess(3, "reversealphabetically", []int64{4, 3}) 209 testSuccess(3, "default", []int64{3, 4}) 210 211 var err error 212 _, err = issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{}) 213 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 214 215 _, err = issues_model.GetLabelsByOrgID(db.DefaultContext, -1, "leastissues", db.ListOptions{}) 216 assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) 217 } 218 219 // 220 221 func TestGetLabelsByIssueID(t *testing.T) { 222 assert.NoError(t, unittest.PrepareTestDatabase()) 223 labels, err := issues_model.GetLabelsByIssueID(db.DefaultContext, 1) 224 assert.NoError(t, err) 225 if assert.Len(t, labels, 1) { 226 assert.EqualValues(t, 1, labels[0].ID) 227 } 228 229 labels, err = issues_model.GetLabelsByIssueID(db.DefaultContext, unittest.NonexistentID) 230 assert.NoError(t, err) 231 assert.Len(t, labels, 0) 232 } 233 234 func TestUpdateLabel(t *testing.T) { 235 assert.NoError(t, unittest.PrepareTestDatabase()) 236 label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) 237 // make sure update wont overwrite it 238 update := &issues_model.Label{ 239 ID: label.ID, 240 Color: "#ffff00", 241 Name: "newLabelName", 242 Description: label.Description, 243 Exclusive: false, 244 ArchivedUnix: timeutil.TimeStamp(0), 245 } 246 label.Color = update.Color 247 label.Name = update.Name 248 assert.NoError(t, issues_model.UpdateLabel(db.DefaultContext, update)) 249 newLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) 250 assert.EqualValues(t, label.ID, newLabel.ID) 251 assert.EqualValues(t, label.Color, newLabel.Color) 252 assert.EqualValues(t, label.Name, newLabel.Name) 253 assert.EqualValues(t, label.Description, newLabel.Description) 254 assert.EqualValues(t, newLabel.ArchivedUnix, 0) 255 unittest.CheckConsistencyFor(t, &issues_model.Label{}, &repo_model.Repository{}) 256 } 257 258 func TestDeleteLabel(t *testing.T) { 259 assert.NoError(t, unittest.PrepareTestDatabase()) 260 label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) 261 assert.NoError(t, issues_model.DeleteLabel(db.DefaultContext, label.RepoID, label.ID)) 262 unittest.AssertNotExistsBean(t, &issues_model.Label{ID: label.ID, RepoID: label.RepoID}) 263 264 assert.NoError(t, issues_model.DeleteLabel(db.DefaultContext, label.RepoID, label.ID)) 265 unittest.AssertNotExistsBean(t, &issues_model.Label{ID: label.ID}) 266 267 assert.NoError(t, issues_model.DeleteLabel(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) 268 unittest.CheckConsistencyFor(t, &issues_model.Label{}, &repo_model.Repository{}) 269 } 270 271 func TestHasIssueLabel(t *testing.T) { 272 assert.NoError(t, unittest.PrepareTestDatabase()) 273 assert.True(t, issues_model.HasIssueLabel(db.DefaultContext, 1, 1)) 274 assert.False(t, issues_model.HasIssueLabel(db.DefaultContext, 1, 2)) 275 assert.False(t, issues_model.HasIssueLabel(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) 276 } 277 278 func TestNewIssueLabel(t *testing.T) { 279 assert.NoError(t, unittest.PrepareTestDatabase()) 280 label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 2}) 281 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) 282 doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 283 284 // add new IssueLabel 285 prevNumIssues := label.NumIssues 286 assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer)) 287 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID}) 288 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ 289 Type: issues_model.CommentTypeLabel, 290 PosterID: doer.ID, 291 IssueID: issue.ID, 292 LabelID: label.ID, 293 Content: "1", 294 }) 295 label = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 2}) 296 assert.EqualValues(t, prevNumIssues+1, label.NumIssues) 297 298 // re-add existing IssueLabel 299 assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer)) 300 unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) 301 } 302 303 func TestNewIssueExclusiveLabel(t *testing.T) { 304 assert.NoError(t, unittest.PrepareTestDatabase()) 305 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 18}) 306 doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 307 308 otherLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 6}) 309 exclusiveLabelA := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 7}) 310 exclusiveLabelB := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8}) 311 312 // coexisting regular and exclusive label 313 assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, otherLabel, doer)) 314 assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelA, doer)) 315 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) 316 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) 317 318 // exclusive label replaces existing one 319 assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelB, doer)) 320 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) 321 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID}) 322 unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) 323 324 // exclusive label replaces existing one again 325 assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelA, doer)) 326 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) 327 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) 328 unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID}) 329 } 330 331 func TestNewIssueLabels(t *testing.T) { 332 assert.NoError(t, unittest.PrepareTestDatabase()) 333 label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) 334 label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 2}) 335 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 5}) 336 doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 337 338 assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label2}, doer)) 339 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label1.ID}) 340 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ 341 Type: issues_model.CommentTypeLabel, 342 PosterID: doer.ID, 343 IssueID: issue.ID, 344 LabelID: label1.ID, 345 Content: "1", 346 }) 347 unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label1.ID}) 348 label1 = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) 349 assert.EqualValues(t, 3, label1.NumIssues) 350 assert.EqualValues(t, 1, label1.NumClosedIssues) 351 label2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 2}) 352 assert.EqualValues(t, 1, label2.NumIssues) 353 assert.EqualValues(t, 1, label2.NumClosedIssues) 354 355 // corner case: test empty slice 356 assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{}, doer)) 357 358 unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) 359 } 360 361 func TestDeleteIssueLabel(t *testing.T) { 362 assert.NoError(t, unittest.PrepareTestDatabase()) 363 testSuccess := func(labelID, issueID, doerID int64) { 364 label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID}) 365 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issueID}) 366 doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doerID}) 367 368 expectedNumIssues := label.NumIssues 369 expectedNumClosedIssues := label.NumClosedIssues 370 if unittest.BeanExists(t, &issues_model.IssueLabel{IssueID: issueID, LabelID: labelID}) { 371 expectedNumIssues-- 372 if issue.IsClosed { 373 expectedNumClosedIssues-- 374 } 375 } 376 377 ctx, committer, err := db.TxContext(db.DefaultContext) 378 defer committer.Close() 379 assert.NoError(t, err) 380 assert.NoError(t, issues_model.DeleteIssueLabel(ctx, issue, label, doer)) 381 assert.NoError(t, committer.Commit()) 382 383 unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issueID, LabelID: labelID}) 384 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ 385 Type: issues_model.CommentTypeLabel, 386 PosterID: doerID, 387 IssueID: issueID, 388 LabelID: labelID, 389 }, `content=""`) 390 label = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID}) 391 assert.EqualValues(t, expectedNumIssues, label.NumIssues) 392 assert.EqualValues(t, expectedNumClosedIssues, label.NumClosedIssues) 393 } 394 testSuccess(1, 1, 2) 395 testSuccess(2, 5, 2) 396 testSuccess(1, 1, 2) // delete non-existent IssueLabel 397 398 unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) 399 }