2017-04-29 13:52:25 +08:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2024-02-17 10:20:10 +01:00
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2017-04-29 13:52:25 +08:00
2022-09-02 15:18:23 -04:00
package integration
2017-04-29 13:52:25 +08:00
import (
2023-10-16 02:56:57 +08:00
"context"
2019-09-20 02:45:38 -03:00
"fmt"
2017-04-29 13:52:25 +08:00
"net/http"
2022-04-08 02:59:56 +08:00
"net/url"
2017-06-18 21:25:58 +08:00
"path"
2024-07-25 11:35:56 +02:00
"regexp"
2017-06-14 23:09:03 -04:00
"strconv"
"strings"
2017-04-29 13:52:25 +08:00
"testing"
2020-01-07 11:23:09 +00:00
"time"
2017-04-29 13:52:25 +08:00
2024-04-30 11:55:46 +02:00
auth_model "code.gitea.io/gitea/models/auth"
2022-06-13 17:37:59 +08:00
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
2024-06-23 19:57:07 +02:00
project_model "code.gitea.io/gitea/models/project"
2021-12-10 09:27:50 +08:00
repo_model "code.gitea.io/gitea/models/repo"
2024-04-04 00:01:21 +02:00
unit_model "code.gitea.io/gitea/models/unit"
2021-11-16 16:53:21 +08:00
"code.gitea.io/gitea/models/unittest"
2021-11-24 17:49:20 +08:00
user_model "code.gitea.io/gitea/models/user"
2020-01-07 11:23:09 +00:00
"code.gitea.io/gitea/modules/indexer/issues"
2024-04-30 13:06:31 +02:00
"code.gitea.io/gitea/modules/optional"
2019-10-13 19:29:10 -03:00
"code.gitea.io/gitea/modules/references"
2017-06-14 23:09:03 -04:00
"code.gitea.io/gitea/modules/setting"
2022-04-08 02:59:56 +08:00
api "code.gitea.io/gitea/modules/structs"
2017-12-15 13:11:02 -08:00
"code.gitea.io/gitea/modules/test"
2024-04-04 00:01:21 +02:00
files_service "code.gitea.io/gitea/services/repository/files"
2022-09-02 15:18:23 -04:00
"code.gitea.io/gitea/tests"
2017-06-14 23:09:03 -04:00
"github.com/PuerkitoBio/goquery"
2017-04-29 13:52:25 +08:00
"github.com/stretchr/testify/assert"
)
2017-09-16 13:16:21 -07:00
func getIssuesSelection ( t testing . TB , htmlDoc * HTMLDoc ) * goquery . Selection {
2023-08-01 00:13:42 +02:00
issueList := htmlDoc . doc . Find ( "#issue-list" )
2017-09-16 13:16:21 -07:00
assert . EqualValues ( t , 1 , issueList . Length ( ) )
2023-08-01 00:13:42 +02:00
return issueList . Find ( ".flex-item" ) . Find ( ".issue-title" )
2017-06-14 23:09:03 -04:00
}
2022-06-13 17:37:59 +08:00
func getIssue ( t * testing . T , repoID int64 , issueSelection * goquery . Selection ) * issues_model . Issue {
2017-06-14 23:09:03 -04:00
href , exists := issueSelection . Attr ( "href" )
assert . True ( t , exists )
indexStr := href [ strings . LastIndexByte ( href , '/' ) + 1 : ]
index , err := strconv . Atoi ( indexStr )
assert . NoError ( t , err , "Invalid issue href: %s" , href )
2022-08-16 10:22:25 +08:00
return unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { RepoID : repoID , Index : int64 ( index ) } )
2017-06-14 23:09:03 -04:00
}
2022-06-13 17:37:59 +08:00
func assertMatch ( t testing . TB , issue * issues_model . Issue , keyword string ) {
2017-09-16 13:16:21 -07:00
matches := strings . Contains ( strings . ToLower ( issue . Title ) , keyword ) ||
strings . Contains ( strings . ToLower ( issue . Content ) , keyword )
for _ , comment := range issue . Comments {
matches = matches || strings . Contains (
strings . ToLower ( comment . Content ) ,
keyword ,
)
}
assert . True ( t , matches )
}
2017-05-26 23:34:11 -04:00
func TestNoLoginViewIssues ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2017-05-26 23:34:11 -04:00
2017-06-09 20:41:36 -04:00
req := NewRequest ( t , "GET" , "/user2/repo1/issues" )
2017-07-07 15:36:47 -04:00
MakeRequest ( t , req , http . StatusOK )
2017-05-26 23:34:11 -04:00
}
2024-07-25 03:33:44 +00:00
func TestViewIssues ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
req := NewRequest ( t , "GET" , "/user2/repo1/issues" )
resp := MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
search := htmlDoc . doc . Find ( ".list-header-search > .search > .input > input" )
placeholder , _ := search . Attr ( "placeholder" )
assert . Equal ( t , "Search issues..." , placeholder )
}
2017-09-16 13:16:21 -07:00
func TestViewIssuesSortByType ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2017-06-14 23:09:03 -04:00
2022-08-16 10:22:25 +08:00
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
repo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : 1 } )
2017-06-14 23:09:03 -04:00
2017-06-17 00:49:45 -04:00
session := loginUser ( t , user . Name )
2021-11-16 18:18:25 +00:00
req := NewRequest ( t , "GET" , repo . Link ( ) + "/issues?type=created_by" )
2017-07-07 15:36:47 -04:00
resp := session . MakeRequest ( t , req , http . StatusOK )
2017-06-14 23:09:03 -04:00
2017-06-17 11:29:59 -05:00
htmlDoc := NewHTMLParser ( t , resp . Body )
2017-09-16 13:16:21 -07:00
issuesSelection := getIssuesSelection ( t , htmlDoc )
2021-11-16 16:53:21 +08:00
expectedNumIssues := unittest . GetCount ( t ,
2022-06-13 17:37:59 +08:00
& issues_model . Issue { RepoID : repo . ID , PosterID : user . ID } ,
2021-11-16 16:53:21 +08:00
unittest . Cond ( "is_closed=?" , false ) ,
unittest . Cond ( "is_pull=?" , false ) ,
2017-06-14 23:09:03 -04:00
)
if expectedNumIssues > setting . UI . IssuePagingNum {
expectedNumIssues = setting . UI . IssuePagingNum
}
assert . EqualValues ( t , expectedNumIssues , issuesSelection . Length ( ) )
issuesSelection . Each ( func ( _ int , selection * goquery . Selection ) {
issue := getIssue ( t , repo . ID , selection )
assert . EqualValues ( t , user . ID , issue . PosterID )
} )
}
2017-09-16 13:16:21 -07:00
func TestViewIssuesKeyword ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2017-09-16 13:16:21 -07:00
2022-08-16 10:22:25 +08:00
repo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : 1 } )
2022-06-13 17:37:59 +08:00
issue := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue {
2020-01-07 11:23:09 +00:00
RepoID : repo . ID ,
Index : 1 ,
2022-08-16 10:22:25 +08:00
} )
2023-10-16 02:56:57 +08:00
issues . UpdateIssueIndexer ( context . Background ( ) , issue . ID )
2020-01-07 11:23:09 +00:00
time . Sleep ( time . Second * 1 )
2024-06-17 18:58:24 +00:00
2017-09-16 13:16:21 -07:00
const keyword = "first"
2021-11-16 18:18:25 +00:00
req := NewRequestf ( t , "GET" , "%s/issues?q=%s" , repo . Link ( ) , keyword )
2017-09-16 13:16:21 -07:00
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 . False ( t , issue . IsClosed )
assert . False ( t , issue . IsPull )
assertMatch ( t , issue , keyword )
} )
2024-06-17 18:58:24 +00:00
// keyword: 'firstt'
// should not match when fuzzy searching is disabled
req = NewRequestf ( t , "GET" , "%s/issues?q=%st&fuzzy=false" , repo . Link ( ) , keyword )
resp = MakeRequest ( t , req , http . StatusOK )
htmlDoc = NewHTMLParser ( t , resp . Body )
issuesSelection = getIssuesSelection ( t , htmlDoc )
assert . EqualValues ( t , 0 , issuesSelection . Length ( ) )
// should match as 'first' when fuzzy seaeching is enabled
req = NewRequestf ( t , "GET" , "%s/issues?q=%st&fuzzy=true" , repo . Link ( ) , keyword )
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 . False ( t , issue . IsClosed )
assert . False ( t , issue . IsPull )
assertMatch ( t , issue , keyword )
} )
2017-09-16 13:16:21 -07:00
}
2024-06-23 19:57:07 +02:00
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 ] )
} )
}
2017-04-29 13:52:25 +08:00
func TestNoLoginViewIssue ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2017-04-29 13:52:25 +08:00
2017-06-09 20:41:36 -04:00
req := NewRequest ( t , "GET" , "/user2/repo1/issues/1" )
2017-07-07 15:36:47 -04:00
MakeRequest ( t , req , http . StatusOK )
2017-04-29 13:52:25 +08:00
}
2017-06-18 21:25:58 +08:00
2017-11-03 11:23:17 +02:00
func testNewIssue ( t * testing . T , session * TestSession , user , repo , title , content string ) string {
2017-06-18 21:25:58 +08:00
req := NewRequest ( t , "GET" , path . Join ( user , repo , "issues" , "new" ) )
2017-07-07 15:36:47 -04:00
resp := session . MakeRequest ( t , req , http . StatusOK )
2017-06-18 21:25:58 +08:00
htmlDoc := NewHTMLParser ( t , resp . Body )
link , exists := htmlDoc . doc . Find ( "form.ui.form" ) . Attr ( "action" )
assert . True ( t , exists , "The template has changed" )
req = NewRequestWithValues ( t , "POST" , link , map [ string ] string {
2017-11-03 11:23:17 +02:00
"_csrf" : htmlDoc . GetCSRF ( ) ,
"title" : title ,
"content" : content ,
} )
2023-06-16 14:32:43 +08:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2017-11-03 11:23:17 +02:00
2017-12-15 13:11:02 -08:00
issueURL := test . RedirectURL ( resp )
2017-11-03 11:23:17 +02:00
req = NewRequest ( t , "GET" , issueURL )
resp = session . MakeRequest ( t , req , http . StatusOK )
htmlDoc = NewHTMLParser ( t , resp . Body )
2024-05-20 23:32:48 +00:00
val := htmlDoc . doc . Find ( "#issue-title-display" ) . Text ( )
2023-05-03 23:58:59 +02:00
assert . Contains ( t , val , title )
2024-07-25 11:35:56 +02:00
// test for first line only and if it contains only letters and spaces
contentFirstLine := strings . Split ( content , "\n" ) [ 0 ]
patNotLetterOrSpace , _ := regexp . Compile ( "[^\\p{L}\\s]" )
if len ( contentFirstLine ) != 0 && ! patNotLetterOrSpace . MatchString ( contentFirstLine ) {
val = htmlDoc . doc . Find ( ".comment .render-content p" ) . First ( ) . Text ( )
assert . Equal ( t , contentFirstLine , val )
}
2017-11-03 11:23:17 +02:00
return issueURL
}
2019-09-20 02:45:38 -03:00
func testIssueAddComment ( t * testing . T , session * TestSession , issueURL , content , status string ) int64 {
2017-11-03 11:23:17 +02:00
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
link , exists := htmlDoc . doc . Find ( "#comment-form" ) . Attr ( "action" )
assert . True ( t , exists , "The template has changed" )
2020-04-11 00:01:41 +02:00
commentCount := htmlDoc . doc . Find ( ".comment-list .comment .render-content" ) . Length ( )
2017-11-03 11:23:17 +02:00
req = NewRequestWithValues ( t , "POST" , link , map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"content" : content ,
"status" : status ,
2017-06-18 21:25:58 +08:00
} )
2023-06-16 14:32:43 +08:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2017-07-07 15:36:47 -04:00
2017-12-15 13:11:02 -08:00
req = NewRequest ( t , "GET" , test . RedirectURL ( resp ) )
2017-07-07 15:36:47 -04:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2017-11-03 11:23:17 +02:00
htmlDoc = NewHTMLParser ( t , resp . Body )
2020-04-11 00:01:41 +02:00
val := htmlDoc . doc . Find ( ".comment-list .comment .render-content p" ) . Eq ( commentCount ) . Text ( )
2017-11-03 11:23:17 +02:00
assert . Equal ( t , content , val )
2019-09-20 02:45:38 -03:00
2020-04-11 00:01:41 +02:00
idAttr , has := htmlDoc . doc . Find ( ".comment-list .comment" ) . Eq ( commentCount ) . Attr ( "id" )
2019-09-20 02:45:38 -03:00
idStr := idAttr [ strings . LastIndexByte ( idAttr , '-' ) + 1 : ]
assert . True ( t , has )
id , err := strconv . Atoi ( idStr )
assert . NoError ( t , err )
return int64 ( id )
2017-06-18 21:25:58 +08:00
}
func TestNewIssue ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2017-06-18 21:25:58 +08:00
session := loginUser ( t , "user2" )
2017-11-03 11:23:17 +02:00
testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
}
2024-07-25 11:35:56 +02:00
func TestIssueCheckboxes ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , ` - [ x ] small x
- [ X ] capital X
- [ ] empty
- [ x ] x without gap
- [ ] empty without gap
- [ x ]
x on new line
- [ ]
empty on new line
- [ ] tabs instead of spaces
Description ` )
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
issueContent := NewHTMLParser ( t , resp . Body ) . doc . Find ( ".comment .render-content" ) . First ( )
isCheckBox := func ( i int , s * goquery . Selection ) bool {
typeVal , typeExists := s . Attr ( "type" )
return typeExists && typeVal == "checkbox"
}
isChecked := func ( i int , s * goquery . Selection ) bool {
_ , checkedExists := s . Attr ( "checked" )
return checkedExists
}
checkBoxes := issueContent . Find ( "input" ) . FilterFunction ( isCheckBox )
assert . Equal ( t , 8 , checkBoxes . Length ( ) )
assert . Equal ( t , 4 , checkBoxes . FilterFunction ( isChecked ) . Length ( ) )
}
2024-04-30 11:55:46 +02:00
func TestIssueDependencies ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
owner := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
session := loginUser ( t , owner . Name )
token := getTokenForLoggedInUser ( t , session , auth_model . AccessTokenScopeWriteIssue )
repo , _ , f := CreateDeclarativeRepoWithOptions ( t , owner , DeclarativeRepoOptions { } )
defer f ( )
createIssue := func ( t * testing . T , title string ) api . Issue {
t . Helper ( )
urlStr := fmt . Sprintf ( "/api/v1/repos/%s/%s/issues" , owner . Name , repo . Name )
req := NewRequestWithJSON ( t , "POST" , urlStr , & api . CreateIssueOption {
Body : "" ,
Title : title ,
} ) . AddTokenAuth ( token )
resp := MakeRequest ( t , req , http . StatusCreated )
var apiIssue api . Issue
DecodeJSON ( t , resp , & apiIssue )
return apiIssue
}
addDependency := func ( t * testing . T , issue , dependency api . Issue ) {
t . Helper ( )
urlStr := fmt . Sprintf ( "/%s/%s/issues/%d/dependency/add" , owner . Name , repo . Name , issue . Index )
req := NewRequestWithValues ( t , "POST" , urlStr , map [ string ] string {
"_csrf" : GetCSRF ( t , session , fmt . Sprintf ( "/%s/%s/issues/%d" , owner . Name , repo . Name , issue . Index ) ) ,
"newDependency" : fmt . Sprintf ( "%d" , dependency . Index ) ,
} )
session . MakeRequest ( t , req , http . StatusSeeOther )
}
removeDependency := func ( t * testing . T , issue , dependency api . Issue ) {
t . Helper ( )
urlStr := fmt . Sprintf ( "/%s/%s/issues/%d/dependency/delete" , owner . Name , repo . Name , issue . Index )
req := NewRequestWithValues ( t , "POST" , urlStr , map [ string ] string {
"_csrf" : GetCSRF ( t , session , fmt . Sprintf ( "/%s/%s/issues/%d" , owner . Name , repo . Name , issue . Index ) ) ,
"removeDependencyID" : fmt . Sprintf ( "%d" , dependency . Index ) ,
"dependencyType" : "blockedBy" ,
} )
session . MakeRequest ( t , req , http . StatusSeeOther )
}
assertHasDependency := func ( t * testing . T , issueID , dependencyID int64 , hasDependency bool ) {
t . Helper ( )
urlStr := fmt . Sprintf ( "/api/v1/repos/%s/%s/issues/%d/dependencies" , owner . Name , repo . Name , issueID )
req := NewRequest ( t , "GET" , urlStr )
resp := MakeRequest ( t , req , http . StatusOK )
var issues [ ] api . Issue
DecodeJSON ( t , resp , & issues )
if hasDependency {
assert . NotEmpty ( t , issues )
assert . EqualValues ( t , issues [ 0 ] . Index , dependencyID )
} else {
assert . Empty ( t , issues )
}
}
t . Run ( "Add dependency" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
issue1 := createIssue ( t , "issue #1" )
issue2 := createIssue ( t , "issue #2" )
addDependency ( t , issue1 , issue2 )
assertHasDependency ( t , issue1 . Index , issue2 . Index , true )
} )
t . Run ( "Remove dependency" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
issue1 := createIssue ( t , "issue #1" )
issue2 := createIssue ( t , "issue #2" )
addDependency ( t , issue1 , issue2 )
removeDependency ( t , issue1 , issue2 )
assertHasDependency ( t , issue1 . Index , issue2 . Index , false )
} )
}
2024-05-27 18:34:18 +03:00
func TestEditIssue ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
req := NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "%s/content" , issueURL ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : "modified content" ,
"context" : fmt . Sprintf ( "/%s/%s" , "user2" , "repo1" ) ,
} )
session . MakeRequest ( t , req , http . StatusOK )
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "%s/content" , issueURL ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : "modified content" ,
"context" : fmt . Sprintf ( "/%s/%s" , "user2" , "repo1" ) ,
} )
session . MakeRequest ( t , req , http . StatusBadRequest )
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "%s/content" , issueURL ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : "modified content" ,
"content_version" : "1" ,
"context" : fmt . Sprintf ( "/%s/%s" , "user2" , "repo1" ) ,
} )
session . MakeRequest ( t , req , http . StatusOK )
}
2017-11-03 11:23:17 +02:00
func TestIssueCommentClose ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2017-11-03 11:23:17 +02:00
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
testIssueAddComment ( t , session , issueURL , "Test comment 1" , "" )
testIssueAddComment ( t , session , issueURL , "Test comment 2" , "" )
testIssueAddComment ( t , session , issueURL , "Test comment 3" , "close" )
// Validate that issue content has not been updated
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
2020-04-11 00:01:41 +02:00
val := htmlDoc . doc . Find ( ".comment-list .comment .render-content p" ) . First ( ) . Text ( )
2017-11-03 11:23:17 +02:00
assert . Equal ( t , "Description" , val )
2017-06-18 21:25:58 +08:00
}
2019-09-20 02:45:38 -03:00
2023-11-26 01:21:21 +08:00
func TestIssueCommentDelete ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
comment1 := "Test comment 1"
commentID := testIssueAddComment ( t , session , issueURL , comment1 , "" )
comment := unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment { ID : commentID } )
assert . Equal ( t , comment1 , comment . Content )
// Using the ID of a comment that does not belong to the repository must fail
req := NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d/delete" , "user5" , "repo4" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
} )
session . MakeRequest ( t , req , http . StatusNotFound )
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d/delete" , "user2" , "repo1" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
} )
session . MakeRequest ( t , req , http . StatusOK )
unittest . AssertNotExistsBean ( t , & issues_model . Comment { ID : commentID } )
}
2023-11-12 13:52:48 +01:00
func TestIssueCommentAttachment ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
const repoURL = "user2/repo1"
const content = "Test comment 4"
const status = ""
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
link , exists := htmlDoc . doc . Find ( "#comment-form" ) . Attr ( "action" )
assert . True ( t , exists , "The template has changed" )
uuid := createAttachment ( t , session , repoURL , "image.png" , generateImg ( ) , http . StatusOK )
commentCount := htmlDoc . doc . Find ( ".comment-list .comment .render-content" ) . Length ( )
req = NewRequestWithValues ( t , "POST" , link , map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"content" : content ,
"status" : status ,
"files" : uuid ,
} )
resp = session . MakeRequest ( t , req , http . StatusOK )
req = NewRequest ( t , "GET" , test . RedirectURL ( resp ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
htmlDoc = NewHTMLParser ( t , resp . Body )
val := htmlDoc . doc . Find ( ".comment-list .comment .render-content p" ) . Eq ( commentCount ) . Text ( )
assert . Equal ( t , content , val )
idAttr , has := htmlDoc . doc . Find ( ".comment-list .comment" ) . Eq ( commentCount ) . Attr ( "id" )
idStr := idAttr [ strings . LastIndexByte ( idAttr , '-' ) + 1 : ]
assert . True ( t , has )
id , err := strconv . Atoi ( idStr )
assert . NoError ( t , err )
assert . NotEqual ( t , 0 , id )
req = NewRequest ( t , "GET" , fmt . Sprintf ( "/%s/%s/comments/%d/attachments" , "user2" , "repo1" , id ) )
session . MakeRequest ( t , req , http . StatusOK )
// Using the ID of a comment that does not belong to the repository must fail
req = NewRequest ( t , "GET" , fmt . Sprintf ( "/%s/%s/comments/%d/attachments" , "user5" , "repo4" , id ) )
session . MakeRequest ( t , req , http . StatusNotFound )
}
2023-11-26 01:21:21 +08:00
func TestIssueCommentUpdate ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
comment1 := "Test comment 1"
commentID := testIssueAddComment ( t , session , issueURL , comment1 , "" )
comment := unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment { ID : commentID } )
assert . Equal ( t , comment1 , comment . Content )
modifiedContent := comment . Content + "MODIFIED"
// Using the ID of a comment that does not belong to the repository must fail
req := NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d" , "user5" , "repo4" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : modifiedContent ,
} )
session . MakeRequest ( t , req , http . StatusNotFound )
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d" , "user2" , "repo1" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : modifiedContent ,
} )
session . MakeRequest ( t , req , http . StatusOK )
comment = unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment { ID : commentID } )
assert . Equal ( t , modifiedContent , comment . Content )
2024-04-25 11:20:04 +02:00
// make the comment empty
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d" , "user2" , "repo1" , commentID ) , map [ string ] string {
2024-05-27 18:34:18 +03:00
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : "" ,
"content_version" : fmt . Sprintf ( "%d" , comment . ContentVersion ) ,
2024-04-25 11:20:04 +02:00
} )
session . MakeRequest ( t , req , http . StatusOK )
comment = unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment { ID : commentID } )
assert . Equal ( t , "" , comment . Content )
2023-11-26 01:21:21 +08:00
}
2024-05-27 18:34:18 +03:00
func TestIssueCommentUpdateSimultaneously ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
comment1 := "Test comment 1"
commentID := testIssueAddComment ( t , session , issueURL , comment1 , "" )
comment := unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment { ID : commentID } )
assert . Equal ( t , comment1 , comment . Content )
modifiedContent := comment . Content + "MODIFIED"
req := NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d" , "user2" , "repo1" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : modifiedContent ,
} )
session . MakeRequest ( t , req , http . StatusOK )
modifiedContent = comment . Content + "2"
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d" , "user2" , "repo1" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : modifiedContent ,
} )
session . MakeRequest ( t , req , http . StatusBadRequest )
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s/comments/%d" , "user2" , "repo1" , commentID ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"content" : modifiedContent ,
"content_version" : "1" ,
} )
session . MakeRequest ( t , req , http . StatusOK )
comment = unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment { ID : commentID } )
assert . Equal ( t , modifiedContent , comment . Content )
assert . Equal ( t , 2 , comment . ContentVersion )
}
2019-12-01 23:57:24 +01:00
func TestIssueReaction ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2019-12-01 23:57:24 +01:00
session := loginUser ( t , "user2" )
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title" , "Description" )
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
req = NewRequestWithValues ( t , "POST" , path . Join ( issueURL , "/reactions/react" ) , map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"content" : "8ball" ,
} )
session . MakeRequest ( t , req , http . StatusInternalServerError )
req = NewRequestWithValues ( t , "POST" , path . Join ( issueURL , "/reactions/react" ) , map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"content" : "eyes" ,
} )
session . MakeRequest ( t , req , http . StatusOK )
req = NewRequestWithValues ( t , "POST" , path . Join ( issueURL , "/reactions/unreact" ) , map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"content" : "eyes" ,
} )
session . MakeRequest ( t , req , http . StatusOK )
}
2019-09-20 02:45:38 -03:00
func TestIssueCrossReference ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2019-09-20 02:45:38 -03:00
// Issue that will be referenced
_ , issueBase := testIssueWithBean ( t , "user2" , 1 , "Title" , "Description" )
// Ref from issue title
issueRefURL , issueRef := testIssueWithBean ( t , "user2" , 1 , fmt . Sprintf ( "Title ref #%d" , issueBase . Index ) , "Description" )
2022-06-13 17:37:59 +08:00
unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment {
2019-09-20 02:45:38 -03:00
IssueID : issueBase . ID ,
RefRepoID : 1 ,
RefIssueID : issueRef . ID ,
RefCommentID : 0 ,
RefIsPull : false ,
2022-01-20 18:46:10 +01:00
RefAction : references . XRefActionNone ,
} )
2019-09-20 02:45:38 -03:00
// Edit title, neuter ref
testIssueChangeInfo ( t , "user2" , issueRefURL , "title" , "Title no ref" )
2022-06-13 17:37:59 +08:00
unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment {
2019-09-20 02:45:38 -03:00
IssueID : issueBase . ID ,
RefRepoID : 1 ,
RefIssueID : issueRef . ID ,
RefCommentID : 0 ,
RefIsPull : false ,
2022-01-20 18:46:10 +01:00
RefAction : references . XRefActionNeutered ,
} )
2019-09-20 02:45:38 -03:00
// Ref from issue content
issueRefURL , issueRef = testIssueWithBean ( t , "user2" , 1 , "TitleXRef" , fmt . Sprintf ( "Description ref #%d" , issueBase . Index ) )
2022-06-13 17:37:59 +08:00
unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment {
2019-09-20 02:45:38 -03:00
IssueID : issueBase . ID ,
RefRepoID : 1 ,
RefIssueID : issueRef . ID ,
RefCommentID : 0 ,
RefIsPull : false ,
2022-01-20 18:46:10 +01:00
RefAction : references . XRefActionNone ,
} )
2019-09-20 02:45:38 -03:00
// Edit content, neuter ref
testIssueChangeInfo ( t , "user2" , issueRefURL , "content" , "Description no ref" )
2022-06-13 17:37:59 +08:00
unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment {
2019-09-20 02:45:38 -03:00
IssueID : issueBase . ID ,
RefRepoID : 1 ,
RefIssueID : issueRef . ID ,
RefCommentID : 0 ,
RefIsPull : false ,
2022-01-20 18:46:10 +01:00
RefAction : references . XRefActionNeutered ,
} )
2019-09-20 02:45:38 -03:00
// Ref from a comment
session := loginUser ( t , "user2" )
commentID := testIssueAddComment ( t , session , issueRefURL , fmt . Sprintf ( "Adding ref from comment #%d" , issueBase . Index ) , "" )
2022-06-13 17:37:59 +08:00
comment := & issues_model . Comment {
2019-09-20 02:45:38 -03:00
IssueID : issueBase . ID ,
RefRepoID : 1 ,
RefIssueID : issueRef . ID ,
RefCommentID : commentID ,
RefIsPull : false ,
2022-01-20 18:46:10 +01:00
RefAction : references . XRefActionNone ,
}
2021-11-16 16:53:21 +08:00
unittest . AssertExistsAndLoadBean ( t , comment )
2019-09-20 02:45:38 -03:00
// Ref from a different repository
2021-11-18 01:33:06 +00:00
_ , issueRef = testIssueWithBean ( t , "user12" , 10 , "TitleXRef" , fmt . Sprintf ( "Description ref user2/repo1#%d" , issueBase . Index ) )
2022-06-13 17:37:59 +08:00
unittest . AssertExistsAndLoadBean ( t , & issues_model . Comment {
2019-09-20 02:45:38 -03:00
IssueID : issueBase . ID ,
RefRepoID : 10 ,
RefIssueID : issueRef . ID ,
RefCommentID : 0 ,
RefIsPull : false ,
2022-01-20 18:46:10 +01:00
RefAction : references . XRefActionNone ,
} )
2019-09-20 02:45:38 -03:00
}
2022-06-13 17:37:59 +08:00
func testIssueWithBean ( t * testing . T , user string , repoID int64 , title , content string ) ( string , * issues_model . Issue ) {
2019-09-20 02:45:38 -03:00
session := loginUser ( t , user )
issueURL := testNewIssue ( t , session , user , fmt . Sprintf ( "repo%d" , repoID ) , title , content )
indexStr := issueURL [ strings . LastIndexByte ( issueURL , '/' ) + 1 : ]
index , err := strconv . Atoi ( indexStr )
assert . NoError ( t , err , "Invalid issue href: %s" , issueURL )
2022-06-13 17:37:59 +08:00
issue := & issues_model . Issue { RepoID : repoID , Index : int64 ( index ) }
2021-11-16 16:53:21 +08:00
unittest . AssertExistsAndLoadBean ( t , issue )
2019-09-20 02:45:38 -03:00
return issueURL , issue
}
2021-12-20 05:41:31 +01:00
func testIssueChangeInfo ( t * testing . T , user , issueURL , info , value string ) {
2019-09-20 02:45:38 -03:00
session := loginUser ( t , user )
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
req = NewRequestWithValues ( t , "POST" , path . Join ( issueURL , info ) , map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
info : value ,
} )
_ = session . MakeRequest ( t , req , http . StatusOK )
}
2019-12-07 05:21:18 +01:00
func TestIssueRedirect ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2019-12-07 05:21:18 +01:00
session := loginUser ( t , "user2" )
// Test external tracker where style not set (shall default numeric)
req := NewRequest ( t , "GET" , path . Join ( "org26" , "repo_external_tracker" , "issues" , "1" ) )
2022-03-23 05:54:07 +01:00
resp := session . MakeRequest ( t , req , http . StatusSeeOther )
2019-12-07 05:21:18 +01:00
assert . Equal ( t , "https://tracker.com/org26/repo_external_tracker/issues/1" , test . RedirectURL ( resp ) )
// Test external tracker with numeric style
req = NewRequest ( t , "GET" , path . Join ( "org26" , "repo_external_tracker_numeric" , "issues" , "1" ) )
2022-03-23 05:54:07 +01:00
resp = session . MakeRequest ( t , req , http . StatusSeeOther )
2019-12-07 05:21:18 +01:00
assert . Equal ( t , "https://tracker.com/org26/repo_external_tracker_numeric/issues/1" , test . RedirectURL ( resp ) )
// Test external tracker with alphanumeric style (for a pull request)
req = NewRequest ( t , "GET" , path . Join ( "org26" , "repo_external_tracker_alpha" , "issues" , "1" ) )
2022-03-23 05:54:07 +01:00
resp = session . MakeRequest ( t , req , http . StatusSeeOther )
2019-12-07 05:21:18 +01:00
assert . Equal ( t , "/" + path . Join ( "org26" , "repo_external_tracker_alpha" , "pulls" , "1" ) , test . RedirectURL ( resp ) )
}
2022-04-08 02:59:56 +08:00
func TestSearchIssues ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2022-04-08 02:59:56 +08:00
session := loginUser ( t , "user2" )
2024-02-24 20:38:43 +08:00
expectedIssueCount := 20 // from the fixtures
2022-08-06 12:43:40 +02:00
if expectedIssueCount > setting . UI . IssuePagingNum {
expectedIssueCount = setting . UI . IssuePagingNum
}
2022-04-08 02:59:56 +08:00
link , _ := url . Parse ( "/issues/search" )
req := NewRequest ( t , "GET" , link . String ( ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
var apiIssues [ ] * api . Issue
DecodeJSON ( t , resp , & apiIssues )
2022-08-06 12:43:40 +02:00
assert . Len ( t , apiIssues , expectedIssueCount )
2022-04-08 02:59:56 +08:00
2023-09-01 20:01:36 +08:00
since := "2000-01-01T00:50:01+00:00" // 946687801
2022-04-08 02:59:56 +08:00
before := time . Unix ( 999307200 , 0 ) . Format ( time . RFC3339 )
query := url . Values { }
query . Add ( "since" , since )
query . Add ( "before" , before )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
2023-09-21 19:59:50 +08:00
assert . Len ( t , apiIssues , 11 )
2022-04-08 02:59:56 +08:00
query . Del ( "since" )
query . Del ( "before" )
query . Add ( "state" , "closed" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
query . Set ( "state" , "all" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
2024-02-24 20:38:43 +08:00
assert . EqualValues ( t , "22" , resp . Header ( ) . Get ( "X-Total-Count" ) )
2023-09-21 19:59:50 +08:00
assert . Len ( t , apiIssues , 20 )
2022-04-08 02:59:56 +08:00
2022-08-06 12:43:40 +02:00
query . Add ( "limit" , "5" )
2022-04-08 02:59:56 +08:00
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
2024-02-24 20:38:43 +08:00
assert . EqualValues ( t , "22" , resp . Header ( ) . Get ( "X-Total-Count" ) )
2022-08-06 12:43:40 +02:00
assert . Len ( t , apiIssues , 5 )
2022-04-08 02:59:56 +08:00
query = url . Values { "assigned" : { "true" } , "state" : { "all" } }
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
2022-05-16 09:49:17 +00:00
assert . Len ( t , apiIssues , 2 )
2022-04-08 02:59:56 +08:00
query = url . Values { "milestones" : { "milestone1" } , "state" : { "all" } }
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 1 )
query = url . Values { "milestones" : { "milestone1,milestone3" } , "state" : { "all" } }
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
query = url . Values { "owner" : { "user2" } } // user
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
2023-07-28 21:18:12 +02:00
assert . Len ( t , apiIssues , 8 )
2022-04-08 02:59:56 +08:00
2023-09-14 10:59:53 +08:00
query = url . Values { "owner" : { "org3" } } // organization
2022-04-08 02:59:56 +08:00
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
2022-05-16 09:49:17 +00:00
assert . Len ( t , apiIssues , 5 )
2022-04-08 02:59:56 +08:00
2023-09-14 10:59:53 +08:00
query = url . Values { "owner" : { "org3" } , "team" : { "team1" } } // organization + team
2022-04-08 02:59:56 +08:00
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
}
func TestSearchIssuesWithLabels ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2022-04-08 02:59:56 +08:00
2024-02-24 20:38:43 +08:00
expectedIssueCount := 20 // from the fixtures
2022-08-06 12:43:40 +02:00
if expectedIssueCount > setting . UI . IssuePagingNum {
expectedIssueCount = setting . UI . IssuePagingNum
}
2022-04-08 02:59:56 +08:00
2022-08-06 12:43:40 +02:00
session := loginUser ( t , "user1" )
link , _ := url . Parse ( "/issues/search" )
query := url . Values { }
2022-04-08 02:59:56 +08:00
var apiIssues [ ] * api . Issue
link . RawQuery = query . Encode ( )
2022-08-06 12:43:40 +02:00
req := NewRequest ( t , "GET" , link . String ( ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
2022-04-08 02:59:56 +08:00
DecodeJSON ( t , resp , & apiIssues )
2022-08-06 12:43:40 +02:00
assert . Len ( t , apiIssues , expectedIssueCount )
2022-04-08 02:59:56 +08:00
query . Add ( "labels" , "label1" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
2022-08-06 12:43:40 +02:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2022-04-08 02:59:56 +08:00
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
// multiple labels
query . Set ( "labels" , "label1,label2" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
2022-08-06 12:43:40 +02:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2022-04-08 02:59:56 +08:00
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
// an org label
query . Set ( "labels" , "orglabel4" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
2022-08-06 12:43:40 +02:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2022-04-08 02:59:56 +08:00
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 1 )
// org and repo label
query . Set ( "labels" , "label2,orglabel4" )
query . Add ( "state" , "all" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
2022-08-06 12:43:40 +02:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2022-04-08 02:59:56 +08:00
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
// org and repo label which share the same issue
query . Set ( "labels" , "label1,orglabel4" )
link . RawQuery = query . Encode ( )
req = NewRequest ( t , "GET" , link . String ( ) )
2022-08-06 12:43:40 +02:00
resp = session . MakeRequest ( t , req , http . StatusOK )
2022-04-08 02:59:56 +08:00
DecodeJSON ( t , resp , & apiIssues )
assert . Len ( t , apiIssues , 2 )
}
func TestGetIssueInfo ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2022-04-08 02:59:56 +08:00
2022-08-16 10:22:25 +08:00
issue := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : 10 } )
repo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : issue . RepoID } )
owner := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : repo . OwnerID } )
2022-06-13 17:37:59 +08:00
assert . NoError ( t , issue . LoadAttributes ( db . DefaultContext ) )
2022-04-08 02:59:56 +08:00
assert . Equal ( t , int64 ( 1019307200 ) , int64 ( issue . DeadlineUnix ) )
assert . Equal ( t , api . StateOpen , issue . State ( ) )
session := loginUser ( t , owner . Name )
urlStr := fmt . Sprintf ( "/%s/%s/issues/%d/info" , owner . Name , repo . Name , issue . Index )
req := NewRequest ( t , "GET" , urlStr )
resp := session . MakeRequest ( t , req , http . StatusOK )
var apiIssue api . Issue
DecodeJSON ( t , resp , & apiIssue )
assert . EqualValues ( t , issue . ID , apiIssue . ID )
}
2023-11-20 16:34:04 +01:00
func TestIssuePinMove ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issueURL , issue := testIssueWithBean ( t , "user2" , 1 , "Title" , "Content" )
assert . EqualValues ( t , 0 , issue . PinOrder )
req := NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "%s/pin" , issueURL ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
} )
session . MakeRequest ( t , req , http . StatusOK )
issue = unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : issue . ID } )
position := 1
assert . EqualValues ( t , position , issue . PinOrder )
newPosition := 2
// Using the ID of an issue that does not belong to the repository must fail
{
session5 := loginUser ( t , "user5" )
movePinURL := "/user5/repo4/issues/move_pin?_csrf=" + GetCSRF ( t , session5 , issueURL )
req = NewRequestWithJSON ( t , "POST" , movePinURL , map [ string ] any {
"id" : issue . ID ,
"position" : newPosition ,
} )
session5 . MakeRequest ( t , req , http . StatusNotFound )
issue = unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : issue . ID } )
assert . EqualValues ( t , position , issue . PinOrder )
}
movePinURL := issueURL [ : strings . LastIndexByte ( issueURL , '/' ) ] + "/move_pin?_csrf=" + GetCSRF ( t , session , issueURL )
req = NewRequestWithJSON ( t , "POST" , movePinURL , map [ string ] any {
"id" : issue . ID ,
"position" : newPosition ,
} )
session . MakeRequest ( t , req , http . StatusNoContent )
issue = unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : issue . ID } )
assert . EqualValues ( t , newPosition , issue . PinOrder )
}
2022-04-08 02:59:56 +08:00
func TestUpdateIssueDeadline ( t * testing . T ) {
2022-09-02 15:18:23 -04:00
defer tests . PrepareTestEnv ( t ) ( )
2022-04-08 02:59:56 +08:00
2022-08-16 10:22:25 +08:00
issueBefore := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : 10 } )
repoBefore := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : issueBefore . RepoID } )
owner := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : repoBefore . OwnerID } )
2022-06-13 17:37:59 +08:00
assert . NoError ( t , issueBefore . LoadAttributes ( db . DefaultContext ) )
2022-04-08 02:59:56 +08:00
assert . Equal ( t , int64 ( 1019307200 ) , int64 ( issueBefore . DeadlineUnix ) )
assert . Equal ( t , api . StateOpen , issueBefore . State ( ) )
session := loginUser ( t , owner . Name )
issueURL := fmt . Sprintf ( "%s/%s/issues/%d" , owner . Name , repoBefore . Name , issueBefore . Index )
req := NewRequest ( t , "GET" , issueURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
urlStr := issueURL + "/deadline?_csrf=" + htmlDoc . GetCSRF ( )
req = NewRequestWithJSON ( t , "POST" , urlStr , map [ string ] string {
"due_date" : "2022-04-06T00:00:00.000Z" ,
} )
resp = session . MakeRequest ( t , req , http . StatusCreated )
var apiIssue api . IssueDeadline
DecodeJSON ( t , resp , & apiIssue )
assert . EqualValues ( t , "2022-04-06" , apiIssue . Deadline . Format ( "2006-01-02" ) )
}
2024-01-07 18:50:03 +08:00
func TestIssueReferenceURL ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
session := loginUser ( t , "user2" )
issue := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : 1 } )
repo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : issue . RepoID } )
req := NewRequest ( t , "GET" , fmt . Sprintf ( "%s/issues/%d" , repo . FullName ( ) , issue . Index ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
// the "reference" uses relative URLs, then JS code will convert them to absolute URLs for current origin, in case users are using multiple domains
ref , _ := htmlDoc . Find ( ` .timeline-item.comment.first .reference-issue ` ) . Attr ( "data-reference" )
assert . EqualValues ( t , "/user2/repo1/issues/1#issue-1" , ref )
ref , _ = htmlDoc . Find ( ` .timeline-item.comment:not(.first) .reference-issue ` ) . Attr ( "data-reference" )
assert . EqualValues ( t , "/user2/repo1/issues/1#issuecomment-2" , ref )
}
2024-01-13 11:55:33 +01:00
func TestGetContentHistory ( t * testing . T ) {
defer tests . AddFixtures ( "tests/integration/fixtures/TestGetContentHistory/" ) ( )
defer tests . PrepareTestEnv ( t ) ( )
issue := unittest . AssertExistsAndLoadBean ( t , & issues_model . Issue { ID : 1 } )
repo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : issue . RepoID } )
issueURL := fmt . Sprintf ( "%s/issues/%d" , repo . FullName ( ) , issue . Index )
contentHistory := unittest . AssertExistsAndLoadBean ( t , & issues_model . ContentHistory { ID : 2 , IssueID : issue . ID } )
contentHistoryURL := fmt . Sprintf ( "%s/issues/%d/content-history/detail?comment_id=%d&history_id=%d" , repo . FullName ( ) , issue . Index , contentHistory . CommentID , contentHistory . ID )
type contentHistoryResp struct {
CanSoftDelete bool ` json:"canSoftDelete" `
HistoryID int ` json:"historyId" `
PrevHistoryID int ` json:"prevHistoryId" `
}
testCase := func ( t * testing . T , session * TestSession , canDelete bool ) {
t . Helper ( )
contentHistoryURL := contentHistoryURL + "&_csrf=" + GetCSRF ( t , session , issueURL )
req := NewRequest ( t , "GET" , contentHistoryURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
var respJSON contentHistoryResp
DecodeJSON ( t , resp , & respJSON )
assert . EqualValues ( t , canDelete , respJSON . CanSoftDelete )
assert . EqualValues ( t , contentHistory . ID , respJSON . HistoryID )
assert . EqualValues ( t , contentHistory . ID - 1 , respJSON . PrevHistoryID )
}
t . Run ( "Anonymous" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
testCase ( t , emptyTestSession ( t ) , false )
} )
t . Run ( "Another user" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
testCase ( t , loginUser ( t , "user8" ) , false )
} )
t . Run ( "Repo owner" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
testCase ( t , loginUser ( t , "user2" ) , true )
} )
t . Run ( "Poster" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
testCase ( t , loginUser ( t , "user5" ) , true )
} )
}
2024-01-28 20:17:46 +01:00
func TestCommitRefComment ( t * testing . T ) {
defer tests . AddFixtures ( "tests/integration/fixtures/TestCommitRefComment/" ) ( )
defer tests . PrepareTestEnv ( t ) ( )
t . Run ( "Pull request" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , "/user2/repo1/pulls/2" )
resp := MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
event := htmlDoc . Find ( "#issuecomment-1000 .text" ) . Text ( )
assert . Contains ( t , event , "referenced this pull request" )
} )
t . Run ( "Issue" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , "/user2/repo1/issues/1" )
resp := MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
event := htmlDoc . Find ( "#issuecomment-1001 .text" ) . Text ( )
assert . Contains ( t , event , "referenced this issue" )
} )
}
2024-02-17 10:20:10 +01:00
func TestIssueFilterNoFollow ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
req := NewRequest ( t , "GET" , "/user2/repo1/issues" )
resp := MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
// Check that every link in the filter list has rel="nofollow".
2024-03-25 07:13:11 +01:00
filterLinks := htmlDoc . Find ( ".issue-list-toolbar-right a[href*=\"?q=\"]" )
2024-02-17 10:20:10 +01:00
assert . True ( t , filterLinks . Length ( ) > 0 )
filterLinks . Each ( func ( i int , link * goquery . Selection ) {
rel , has := link . Attr ( "rel" )
assert . True ( t , has )
assert . Equal ( t , "nofollow" , rel )
} )
}
2024-04-04 00:01:21 +02:00
func TestIssueForm ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
user2 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
session := loginUser ( t , user2 . Name )
repo , _ , f := CreateDeclarativeRepo ( t , user2 , "" ,
[ ] unit_model . Type { unit_model . TypeCode , unit_model . TypeIssues } , nil ,
[ ] * files_service . ChangeRepoFile {
{
Operation : "create" ,
TreePath : ".forgejo/issue_template/test.yaml" ,
ContentReader : strings . NewReader ( ` name : Test
about : Hello World
body :
- type : checkboxes
id : test
attributes :
label : Test
options :
- label : This is a label
` ) ,
} ,
} ,
)
defer f ( )
t . Run ( "Choose list" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , repo . Link ( ) + "/issues/new/choose" )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
htmlDoc . AssertElement ( t , "a[href$='/issues/new?template=.forgejo%2fissue_template%2ftest.yaml']" , true )
} )
t . Run ( "Issue template" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , repo . Link ( ) + "/issues/new?template=.forgejo%2fissue_template%2ftest.yaml" )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
htmlDoc . AssertElement ( t , "#new-issue .field .ui.checkbox input[name='form-field-test-0']" , true )
checkboxLabel := htmlDoc . Find ( "#new-issue .field .ui.checkbox label" ) . Text ( )
assert . Contains ( t , checkboxLabel , "This is a label" )
} )
} )
}
2024-04-30 13:06:31 +02:00
func TestIssueUnsubscription ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
defer tests . PrepareTestEnv ( t ) ( )
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
repo , _ , f := CreateDeclarativeRepoWithOptions ( t , user , DeclarativeRepoOptions {
AutoInit : optional . Some ( false ) ,
} )
defer f ( )
session := loginUser ( t , user . Name )
issueURL := testNewIssue ( t , session , user . Name , repo . Name , "Issue title" , "Description" )
req := NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "%s/watch" , issueURL ) , map [ string ] string {
"_csrf" : GetCSRF ( t , session , issueURL ) ,
"watch" : "0" ,
} )
session . MakeRequest ( t , req , http . StatusOK )
} )
}
2024-07-14 05:38:45 +02:00
func TestIssueLabelList ( t * testing . T ) {
defer tests . PrepareTestEnv ( t ) ( )
2024-07-17 12:41:51 +05:00
// The label list should always be present. When no labels are selected, .no-select is visible, otherwise hidden.
2024-07-14 05:38:45 +02:00
labelListSelector := ".labels.list .labels-list"
hiddenClass := "tw-hidden"
2024-07-17 12:41:51 +05:00
t . Run ( "Test label list" , func ( t * testing . T ) {
2024-07-14 05:38:45 +02:00
defer tests . PrintCurrentTest ( t ) ( )
req := NewRequest ( t , "GET" , "/user2/repo1/issues/1" )
resp := MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
htmlDoc . AssertElement ( t , labelListSelector , true )
2024-07-17 12:41:51 +05:00
htmlDoc . AssertElement ( t , ".labels.list .no-select." + hiddenClass , true )
2024-07-14 05:38:45 +02:00
} )
}