Skip to content

Commit 10644d6

Browse files
ethantkoeniglunny
authored andcommitted
Bug fixes and unit tests for models/issue_label (#802)
1 parent 0a02fb3 commit 10644d6

File tree

8 files changed

+301
-14
lines changed

8 files changed

+301
-14
lines changed

models/fixtures/comment.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-
2+
id: 1
3+
type: 7 # label
4+
poster_id: 2
5+
issue_id: 1
6+
label_id: 1
7+
content: "1"

models/fixtures/issue.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,13 @@
4444
content: content4
4545
is_closed: true
4646
is_pull: false
47+
48+
-
49+
id: 5
50+
repo_id: 1
51+
index: 4
52+
poster_id: 2
53+
name: issue5
54+
content: content5
55+
is_closed: true
56+
is_pull: false

models/fixtures/issue_label.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-
2+
id: 1
3+
issue_id: 1
4+
label_id: 1
5+
6+
-
7+
id: 2
8+
issue_id: 5
9+
label_id: 2
10+
11+
-
12+
id: 3
13+
issue_id: 2
14+
label_id: 1

models/fixtures/label.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-
2+
id: 1
3+
repo_id: 1
4+
name: label1
5+
color: '#abcdef'
6+
num_issues: 2
7+
num_closed_issues: 0
8+
9+
-
10+
id: 2
11+
repo_id: 1
12+
name: label2
13+
color: '#000000'
14+
num_issues: 1
15+
num_closed_issues: 1

models/issue.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ func (issue *Issue) getLabels(e Engine) (err error) {
345345
}
346346

347347
func (issue *Issue) removeLabel(e *xorm.Session, doer *User, label *Label) error {
348-
return deleteIssueLabel(e, doer, issue, label)
348+
return deleteIssueLabel(e, issue, label, doer)
349349
}
350350

351351
// RemoveLabel removes a label from issue by given ID.
@@ -360,7 +360,7 @@ func (issue *Issue) RemoveLabel(doer *User, label *Label) error {
360360
return ErrLabelNotExist{}
361361
}
362362

363-
if err := DeleteIssueLabel(issue, doer, label); err != nil {
363+
if err := DeleteIssueLabel(issue, label, doer); err != nil {
364364
return err
365365
}
366366

models/issue_label.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func getLabelInRepoByName(e Engine, repoID int64, labelName string) (*Label, err
114114
Name: labelName,
115115
RepoID: repoID,
116116
}
117-
has, err := x.Get(l)
117+
has, err := e.Get(l)
118118
if err != nil {
119119
return nil, err
120120
} else if !has {
@@ -135,7 +135,7 @@ func getLabelInRepoByID(e Engine, repoID, labelID int64) (*Label, error) {
135135
ID: labelID,
136136
RepoID: repoID,
137137
}
138-
has, err := x.Get(l)
138+
has, err := e.Get(l)
139139
if err != nil {
140140
return nil, err
141141
} else if !has {
@@ -355,17 +355,14 @@ func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) {
355355
Find(&issueLabels)
356356
}
357357

358-
// GetIssueLabels returns all issue-label relations of given issue by ID.
359-
func GetIssueLabels(issueID int64) ([]*IssueLabel, error) {
360-
return getIssueLabels(x, issueID)
361-
}
362-
363-
func deleteIssueLabel(e *xorm.Session, doer *User, issue *Issue, label *Label) (err error) {
364-
if _, err = e.Delete(&IssueLabel{
358+
func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label, doer *User) (err error) {
359+
if count, err := e.Delete(&IssueLabel{
365360
IssueID: issue.ID,
366361
LabelID: label.ID,
367362
}); err != nil {
368363
return err
364+
} else if count == 0 {
365+
return nil
369366
}
370367

371368
if err = issue.loadRepo(e); err != nil {
@@ -384,14 +381,14 @@ func deleteIssueLabel(e *xorm.Session, doer *User, issue *Issue, label *Label) (
384381
}
385382

386383
// DeleteIssueLabel deletes issue-label relation.
387-
func DeleteIssueLabel(issue *Issue, doer *User, label *Label) (err error) {
384+
func DeleteIssueLabel(issue *Issue, label *Label, doer *User) (err error) {
388385
sess := x.NewSession()
389386
defer sessionRelease(sess)
390387
if err = sess.Begin(); err != nil {
391388
return err
392389
}
393390

394-
if err = deleteIssueLabel(sess, doer, issue, label); err != nil {
391+
if err = deleteIssueLabel(sess, issue, label, doer); err != nil {
395392
return err
396393
}
397394

models/issue_label_test.go

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
// Copyright 2017 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package models
6+
7+
import (
8+
"html/template"
9+
"testing"
10+
11+
api "code.gitea.io/sdk/gitea"
12+
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
// TODO TestGetLabelTemplateFile
17+
18+
func TestLabel_APIFormat(t *testing.T) {
19+
assert.NoError(t, PrepareTestDatabase())
20+
label := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
21+
assert.Equal(t, api.Label{
22+
ID: label.ID,
23+
Name: label.Name,
24+
Color: "abcdef",
25+
}, *label.APIFormat())
26+
}
27+
28+
func TestLabel_CalOpenIssues(t *testing.T) {
29+
assert.NoError(t, PrepareTestDatabase())
30+
label := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
31+
label.CalOpenIssues()
32+
assert.EqualValues(t, 2, label.NumOpenIssues)
33+
}
34+
35+
func TestLabel_ForegroundColor(t *testing.T) {
36+
assert.NoError(t, PrepareTestDatabase())
37+
label := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
38+
assert.Equal(t, template.CSS("#000"), label.ForegroundColor())
39+
40+
label = AssertExistsAndLoadBean(t, &Label{ID: 2}).(*Label)
41+
assert.Equal(t, template.CSS("#fff"), label.ForegroundColor())
42+
}
43+
44+
func TestNewLabels(t *testing.T) {
45+
assert.NoError(t, PrepareTestDatabase())
46+
labels := []*Label{
47+
{RepoID: 2, Name: "labelName2", Color: "#123456"},
48+
{RepoID: 3, Name: "labelName3", Color: "#234567"},
49+
}
50+
for _, label := range labels {
51+
AssertNotExistsBean(t, label)
52+
}
53+
assert.NoError(t, NewLabels(labels...))
54+
for _, label := range labels {
55+
AssertExistsAndLoadBean(t, label)
56+
}
57+
}
58+
59+
func TestGetLabelByID(t *testing.T) {
60+
assert.NoError(t, PrepareTestDatabase())
61+
label, err := GetLabelByID(1)
62+
assert.NoError(t, err)
63+
assert.EqualValues(t, 1, label.ID)
64+
65+
_, err = GetLabelByID(NonexistentID)
66+
assert.True(t, IsErrLabelNotExist(err))
67+
}
68+
69+
func TestGetLabelInRepoByName(t *testing.T) {
70+
assert.NoError(t, PrepareTestDatabase())
71+
label, err := GetLabelInRepoByName(1, "label1")
72+
assert.NoError(t, err)
73+
assert.EqualValues(t, 1, label.ID)
74+
assert.Equal(t, "label1", label.Name)
75+
76+
_, err = GetLabelInRepoByName(1, "")
77+
assert.True(t, IsErrLabelNotExist(err))
78+
79+
_, err = GetLabelInRepoByName(NonexistentID, "nonexistent")
80+
assert.True(t, IsErrLabelNotExist(err))
81+
}
82+
83+
func TestGetLabelInRepoByID(t *testing.T) {
84+
assert.NoError(t, PrepareTestDatabase())
85+
label, err := GetLabelInRepoByID(1, 1)
86+
assert.NoError(t, err)
87+
assert.EqualValues(t, 1, label.ID)
88+
89+
_, err = GetLabelInRepoByID(1, -1)
90+
assert.True(t, IsErrLabelNotExist(err))
91+
92+
_, err = GetLabelInRepoByID(NonexistentID, NonexistentID)
93+
assert.True(t, IsErrLabelNotExist(err))
94+
}
95+
96+
func TestGetLabelsInRepoByIDs(t *testing.T) {
97+
assert.NoError(t, PrepareTestDatabase())
98+
labels, err := GetLabelsInRepoByIDs(1, []int64{1, 2, NonexistentID})
99+
assert.NoError(t, err)
100+
assert.Len(t, labels, 2)
101+
assert.EqualValues(t, 1, labels[0].ID)
102+
assert.EqualValues(t, 2, labels[1].ID)
103+
}
104+
105+
func TestGetLabelsByRepoID(t *testing.T) {
106+
assert.NoError(t, PrepareTestDatabase())
107+
testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) {
108+
labels, err := GetLabelsByRepoID(repoID, sortType)
109+
assert.NoError(t, err)
110+
assert.Len(t, labels, len(expectedIssueIDs))
111+
for i, label := range labels {
112+
assert.EqualValues(t, expectedIssueIDs[i], label.ID)
113+
}
114+
}
115+
testSuccess(1, "leastissues", []int64{2, 1})
116+
testSuccess(1, "mostissues", []int64{1, 2})
117+
testSuccess(1, "reversealphabetically", []int64{2, 1})
118+
testSuccess(1, "default", []int64{1, 2})
119+
}
120+
121+
func TestGetLabelsByIssueID(t *testing.T) {
122+
assert.NoError(t, PrepareTestDatabase())
123+
labels, err := GetLabelsByIssueID(1)
124+
assert.NoError(t, err)
125+
assert.Len(t, labels, 1)
126+
assert.EqualValues(t, 1, labels[0].ID)
127+
128+
labels, err = GetLabelsByIssueID(NonexistentID)
129+
assert.NoError(t, err)
130+
assert.Len(t, labels, 0)
131+
}
132+
133+
func TestUpdateLabel(t *testing.T) {
134+
assert.NoError(t, PrepareTestDatabase())
135+
label := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
136+
label.Color = "#ffff00"
137+
label.Name = "newLabelName"
138+
assert.NoError(t, UpdateLabel(label))
139+
newLabel := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
140+
assert.Equal(t, *label, *newLabel)
141+
}
142+
143+
func TestDeleteLabel(t *testing.T) {
144+
assert.NoError(t, PrepareTestDatabase())
145+
label := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
146+
assert.NoError(t, DeleteLabel(label.RepoID, label.ID))
147+
AssertNotExistsBean(t, &Label{ID: label.ID, RepoID: label.RepoID})
148+
149+
assert.NoError(t, DeleteLabel(label.RepoID, label.ID))
150+
AssertNotExistsBean(t, &Label{ID: label.ID, RepoID: label.RepoID})
151+
152+
assert.NoError(t, DeleteLabel(NonexistentID, NonexistentID))
153+
}
154+
155+
func TestHasIssueLabel(t *testing.T) {
156+
assert.NoError(t, PrepareTestDatabase())
157+
assert.True(t, HasIssueLabel(1, 1))
158+
assert.False(t, HasIssueLabel(1, 2))
159+
assert.False(t, HasIssueLabel(NonexistentID, NonexistentID))
160+
}
161+
162+
func TestNewIssueLabel(t *testing.T) {
163+
assert.NoError(t, PrepareTestDatabase())
164+
label := AssertExistsAndLoadBean(t, &Label{ID: 2}).(*Label)
165+
issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
166+
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
167+
168+
// add new IssueLabel
169+
prevNumIssues := label.NumIssues
170+
assert.NoError(t, NewIssueLabel(issue, label, doer))
171+
AssertExistsAndLoadBean(t, &IssueLabel{IssueID: issue.ID, LabelID: label.ID})
172+
AssertExistsAndLoadBean(t, &Comment{
173+
Type: CommentTypeLabel,
174+
PosterID: doer.ID,
175+
IssueID: issue.ID,
176+
LabelID: label.ID,
177+
Content: "1",
178+
})
179+
assert.EqualValues(t, prevNumIssues+1, label.NumIssues)
180+
181+
// re-add existing IssueLabel
182+
assert.NoError(t, NewIssueLabel(issue, label, doer))
183+
}
184+
185+
func TestNewIssueLabels(t *testing.T) {
186+
assert.NoError(t, PrepareTestDatabase())
187+
label1 := AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
188+
label2 := AssertExistsAndLoadBean(t, &Label{ID: 2}).(*Label)
189+
issue := AssertExistsAndLoadBean(t, &Issue{ID: 5}).(*Issue)
190+
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
191+
192+
assert.NoError(t, NewIssueLabels(issue, []*Label{label1, label2}, doer))
193+
AssertExistsAndLoadBean(t, &IssueLabel{IssueID: issue.ID, LabelID: label1.ID})
194+
AssertExistsAndLoadBean(t, &Comment{
195+
Type: CommentTypeLabel,
196+
PosterID: doer.ID,
197+
IssueID: issue.ID,
198+
LabelID: label1.ID,
199+
Content: "1",
200+
})
201+
AssertExistsAndLoadBean(t, &IssueLabel{IssueID: issue.ID, LabelID: label1.ID})
202+
label1 = AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
203+
assert.EqualValues(t, 3, label1.NumIssues)
204+
assert.EqualValues(t, 1, label1.NumClosedIssues)
205+
label2 = AssertExistsAndLoadBean(t, &Label{ID: 2}).(*Label)
206+
assert.EqualValues(t, 1, label2.NumIssues)
207+
assert.EqualValues(t, 1, label2.NumClosedIssues)
208+
209+
// corner case: test empty slice
210+
assert.NoError(t, NewIssueLabels(issue, []*Label{}, doer))
211+
}
212+
213+
func TestDeleteIssueLabel(t *testing.T) {
214+
assert.NoError(t, PrepareTestDatabase())
215+
testSuccess := func(labelID, issueID, doerID int64) {
216+
label := AssertExistsAndLoadBean(t, &Label{ID: labelID}).(*Label)
217+
issue := AssertExistsAndLoadBean(t, &Issue{ID: issueID}).(*Issue)
218+
doer := AssertExistsAndLoadBean(t, &User{ID: doerID}).(*User)
219+
220+
expectedNumIssues := label.NumIssues
221+
expectedNumClosedIssues := label.NumClosedIssues
222+
if BeanExists(t, &IssueLabel{IssueID: issueID, LabelID: labelID}) {
223+
expectedNumIssues--
224+
if issue.IsClosed {
225+
expectedNumClosedIssues--
226+
}
227+
}
228+
229+
assert.NoError(t, DeleteIssueLabel(issue, label, doer))
230+
AssertNotExistsBean(t, &IssueLabel{IssueID: issueID, LabelID: labelID})
231+
AssertExistsAndLoadBean(t, &Comment{
232+
Type: CommentTypeLabel,
233+
PosterID: doerID,
234+
IssueID: issueID,
235+
LabelID: labelID,
236+
}, `content=""`)
237+
label = AssertExistsAndLoadBean(t, &Label{ID: labelID}).(*Label)
238+
assert.EqualValues(t, expectedNumIssues, label.NumIssues)
239+
assert.EqualValues(t, expectedNumClosedIssues, label.NumClosedIssues)
240+
}
241+
testSuccess(1, 1, 2)
242+
testSuccess(2, 5, 2)
243+
testSuccess(1, 1, 2) // delete non-existent IssueLabel
244+
}

routers/api/v1/repo/issue_label.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func DeleteIssueLabel(ctx *context.APIContext) {
9898
return
9999
}
100100

101-
if err := models.DeleteIssueLabel(issue, ctx.User, label); err != nil {
101+
if err := models.DeleteIssueLabel(issue, label, ctx.User); err != nil {
102102
ctx.Error(500, "DeleteIssueLabel", err)
103103
return
104104
}

0 commit comments

Comments
 (0)