@ -7,6 +7,7 @@ import (
"bytes"
"fmt"
"io"
"maps"
"mime/multipart"
"net/http"
"net/http/httptest"
@ -19,292 +20,278 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test CreateFile ( t * testing . T ) {
func Test Editor ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
session := loginUser ( t , "user2" )
testCreateFile ( t , session , "user2" , "repo1" , "master" , "test.txt" , "Content" )
sessionUser2 := loginUser ( t , "user2" )
t . Run ( "EditFileNotAllowed" , testEditFileNotAllowed )
t . Run ( "DiffPreview" , testEditorDiffPreview )
t . Run ( "CreateFile" , testEditorCreateFile )
t . Run ( "EditFile" , func ( t * testing . T ) {
testEditFile ( t , sessionUser2 , "user2" , "repo1" , "master" , "README.md" , "Hello, World (direct)\n" )
testEditFileToNewBranch ( t , sessionUser2 , "user2" , "repo1" , "master" , "feature/test" , "README.md" , "Hello, World (commit-to-new-branch)\n" )
} )
t . Run ( "PatchFile" , testEditorPatchFile )
t . Run ( "DeleteFile" , func ( t * testing . T ) {
viewLink := "/user2/repo1/src/branch/branch2/README.md"
sessionUser2 . MakeRequest ( t , NewRequest ( t , "GET" , viewLink ) , http . StatusOK )
testEditorActionPostRequest ( t , sessionUser2 , "/user2/repo1/_delete/branch2/README.md" , map [ string ] string { "commit_choice" : "direct" } )
sessionUser2 . MakeRequest ( t , NewRequest ( t , "GET" , viewLink ) , http . StatusNotFound )
} )
t . Run ( "ForkToEditFile" , func ( t * testing . T ) {
testForkToEditFile ( t , loginUser ( t , "user4" ) , "user4" , "user2" , "repo1" , "master" , "README.md" )
} )
t . Run ( "WebGitCommitEmail" , testEditorWebGitCommitEmail )
t . Run ( "ProtectedBranch" , testEditorProtectedBranch )
} )
}
func testCreateFile ( t * testing . T , session * TestSession , user , repo , branch , filePath , content string ) {
// Request editor page
newURL := fmt . Sprintf ( "/%s/%s/_new/%s/" , user , repo , branch )
req := NewRequest ( t , "GET" , newURL )
resp := session . MakeRequest ( t , req , http . StatusOK )
doc := NewHTMLParser ( t , resp . Body )
lastCommit := doc . GetInputValueByName ( "last_commit" )
assert . NotEmpty ( t , lastCommit )
func testEditorCreateFile ( t * testing . T ) {
session := loginUser ( t , "user2" )
testCreateFile ( t , session , "user2" , "repo1" , "master" , "test.txt" , "Content" )
testEditorActionPostRequestError ( t , session , "/user2/repo1/_new/master/" , map [ string ] string {
"tree_path" : "test.txt" ,
"commit_choice" : "direct" ,
"new_branch_name" : "master" ,
} , ` A file named "test.txt" already exists in this repository. ` )
testEditorActionPostRequestError ( t , session , "/user2/repo1/_new/master/" , map [ string ] string {
"tree_path" : "test.txt" ,
"commit_choice" : "commit-to-new-branch" ,
"new_branch_name" : "master" ,
} , ` Branch "master" already exists in this repository. ` )
}
// Save new file to master branch
req = NewRequestWithValues ( t , "POST" , newURL , map [ string ] string {
"_csrf" : doc . GetCSRF ( ) ,
"last_commit" : lastCommit ,
func testCreateFile ( t * testing . T , session * TestSession , user , repo , branch , filePath , content string ) {
testEditorActionEdit ( t , session , user , repo , "_new" , branch , "" , map [ string ] string {
"tree_path" : filePath ,
"content" : content ,
"commit_choice" : "direct" ,
} )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . NotEmpty ( t , test . RedirectURL ( resp ) )
}
func TestCreateFileOnProtectedBranch ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
session := loginUser ( t , "user2" )
csrf := GetUserCSRFToken ( t , session )
// Change master branch to protected
req := NewRequestWithValues ( t , "POST" , "/user2/repo1/settings/branches/edit" , map [ string ] string {
"_csrf" : csrf ,
"rule_name" : "master" ,
"enable_push" : "true" ,
} )
session . MakeRequest ( t , req , http . StatusSeeOther )
// Check if master branch has been locked successfully
flashMsg := session . GetCookieFlashMessage ( )
assert . Equal ( t , ` Branch protection for rule "master" has been updated. ` , flashMsg . SuccessMsg )
// Request editor page
req = NewRequest ( t , "GET" , "/user2/repo1/_new/master/" )
resp := session . MakeRequest ( t , req , http . StatusOK )
doc := NewHTMLParser ( t , resp . Body )
lastCommit := doc . GetInputValueByName ( "last_commit" )
assert . NotEmpty ( t , lastCommit )
// Save new file to master branch
req = NewRequestWithValues ( t , "POST" , "/user2/repo1/_new/master/" , map [ string ] string {
"_csrf" : doc . GetCSRF ( ) ,
"last_commit" : lastCommit ,
"tree_path" : "test.txt" ,
"content" : "Content" ,
"commit_choice" : "direct" ,
} )
resp = session . MakeRequest ( t , req , http . StatusBadRequest )
respErr := test . ParseJSONError ( resp . Body . Bytes ( ) )
assert . Equal ( t , ` Cannot commit to protected branch "master". ` , respErr . ErrorMessage )
// remove the protected branch
csrf = GetUserCSRFToken ( t , session )
// Change master branch to protected
req = NewRequestWithValues ( t , "POST" , "/user2/repo1/settings/branches/1/delete" , map [ string ] string {
"_csrf" : csrf ,
} )
resp = session . MakeRequest ( t , req , http . StatusOK )
res := make ( map [ string ] string )
assert . NoError ( t , json . NewDecoder ( resp . Body ) . Decode ( & res ) )
assert . Equal ( t , "/user2/repo1/settings/branches" , res [ "redirect" ] )
// Check if master branch has been locked successfully
flashMsg = session . GetCookieFlashMessage ( )
assert . Equal ( t , ` Removing branch protection rule "1" failed. ` , flashMsg . ErrorMsg )
func testEditorProtectedBranch ( t * testing . T ) {
session := loginUser ( t , "user2" )
// Change the "master" branch to "protected"
req := NewRequestWithValues ( t , "POST" , "/user2/repo1/settings/branches/edit" , map [ string ] string {
"_csrf" : GetUserCSRFToken ( t , session ) ,
"rule_name" : "master" ,
"enable_push" : "true" ,
} )
session . MakeRequest ( t , req , http . StatusSeeOther )
flashMsg := session . GetCookieFlashMessage ( )
assert . Equal ( t , ` Branch protection for rule "master" has been updated. ` , flashMsg . SuccessMsg )
// Try to commit a file to the "master" branch and it should fail
resp := testEditorActionPostRequest ( t , session , "/user2/repo1/_new/master/" , map [ string ] string { "tree_path" : "test-protected-branch.txt" , "commit_choice" : "direct" } )
assert . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Equal ( t , ` Cannot commit to protected branch "master". ` , test . ParseJSONError ( resp . Body . Bytes ( ) ) . ErrorMessage )
}
func testEditFile ( t * testing . T , session * TestSession , user , repo , branch , filePath , newContent string ) * httptest . ResponseRecorder {
// Get to the 'edit this file' page
req := NewRequest ( t , "GET" , path . Join ( user , repo , "_edit" , branch , filePath ) )
func testEditorActionPostRequest ( t * testing . T , session * TestSession , requestPath string , params map [ string ] string ) * httptest . ResponseRecorder {
req := NewRequest ( t , "GET" , requestPath )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
lastCommit := htmlDoc . GetInputValueByName ( "last_commit" )
assert . NotEmpty ( t , lastCommit )
// Submit the edits
req = NewRequestWithValues ( t , "POST" , path . Join ( user , repo , "_edit" , branch , filePath ) ,
map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"last_commit" : lastCommit ,
"tree_path" : filePath ,
"content" : newContent ,
"commit_choice" : "direct" ,
} ,
)
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . NotEmpty ( t , test . RedirectURL ( resp ) )
// Verify the change
req = NewRequest ( t , "GET" , path . Join ( user , repo , "raw/branch" , branch , filePath ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . Equal ( t , newContent , resp . Body . String ( ) )
return resp
form := map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"last_commit" : htmlDoc . GetInputValueByName ( "last_commit" ) ,
}
maps . Copy ( form , params )
req = NewRequestWithValues ( t , "POST" , requestPath , form )
return session . MakeRequest ( t , req , NoExpectedStatus )
}
func testEditFileToNewBranch ( t * testing . T , session * TestSession , user , repo , branch , targetBranch , filePath , newContent string ) * httptest . ResponseRecorder {
// Get to the 'edit this file' page
req := NewRequest ( t , "GET" , path . Join ( user , repo , "_edit" , branch , filePath ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
func testEditorActionPostRequestError ( t * testing . T , session * TestSession , requestPath string , params map [ string ] string , errorMessage string ) {
resp := testEditorActionPostRequest ( t , session , requestPath , params )
assert . Equal ( t , http . StatusBadRequest , resp . Code )
assert . Equal ( t , errorMessage , test . ParseJSONError ( resp . Body . Bytes ( ) ) . ErrorMessage )
}
htmlDoc := NewHTMLParser ( t , resp . Body )
lastCommit := htmlDoc . GetInputValueByName ( "last_commit" )
assert . NotEmpty ( t , lastCommit )
// Submit the edits
req = NewRequestWithValues ( t , "POST" , path . Join ( user , repo , "_edit" , branch , filePath ) ,
map [ string ] string {
"_csrf" : htmlDoc . GetCSRF ( ) ,
"last_commit" : lastCommit ,
"tree_path" : filePath ,
"content" : newContent ,
"commit_choice" : "commit-to-new-branch" ,
"new_branch_name" : targetBranch ,
} ,
)
resp = session . MakeRequest ( t , req , http . StatusOK )
func testEditorActionEdit ( t * testing . T , session * TestSession , user , repo , editorAction , branch , filePath string , params map [ string ] string ) * httptest . ResponseRecorder {
params [ "tree_path" ] = util . IfZero ( params [ "tree_path" ] , filePath )
newBranchName := util . Iif ( params [ "commit_choice" ] == "direct" , branch , params [ "new_branch_name" ] )
resp := testEditorActionPostRequest ( t , session , fmt . Sprintf ( "/%s/%s/%s/%s/%s" , user , repo , editorAction , branch , filePath ) , params )
assert . Equal ( t , http . StatusOK , resp . Code )
assert . NotEmpty ( t , test . RedirectURL ( resp ) )
// Verify the change
req = NewRequest ( t , "GET" , path . Join ( user , repo , "raw/branch" , targetBranch , filePath ) )
req := NewRequest ( t , "GET" , path . Join ( user , repo , "raw/branch" , newBranchName , params [ "tree_path" ] ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . Equal ( t , newContent , resp . Body . String ( ) )
assert . Equal ( t , params [ "content" ] , resp . Body . String ( ) )
return resp
}
func T estEditFile( t * testing . T ) {
onGiteaRun( t , func ( t * testing . T , u * url . URL ) {
session := loginUser ( t , "user2" )
testEditFile ( t , session , "user2" , "repo1" , "master" , "README.md" , "Hello, World (Edited)\n" )
func testEditFile ( t * testing . T , session * TestSession , user , repo , branch , filePath , newContent string ) {
testEditorActionEdit ( t , session , user , repo , "_edit" , branch , filePath , map [ string ] string {
"content" : newContent ,
"commit_choice" : "direct" ,
} )
}
func TestEditFileToNewBranch ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
session := loginUser ( t , "user2" )
testEditFileToNewBranch ( t , session , "user2" , "repo1" , "master" , "feature/test" , "README.md" , "Hello, World (Edited)\n" )
func testEditFileToNewBranch ( t * testing . T , session * TestSession , user , repo , branch , targetBranch , filePath , newContent string ) {
testEditorActionEdit ( t , session , user , repo , "_edit" , branch , filePath , map [ string ] string {
"content" : newContent ,
"commit_choice" : "commit-to-new-branch" ,
"new_branch_name" : targetBranch ,
} )
}
func TestWebGitCommitEmail ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , _ * url . URL ) {
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
require . True ( t , user . KeepEmailPrivate )
repo1 := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : 1 } )
gitRepo , _ := git . OpenRepository ( git . DefaultContext , repo1 . RepoPath ( ) )
defer gitRepo . Close ( )
getLastCommit := func ( t * testing . T ) * git . Commit {
c , err := gitRepo . GetBranchCommit ( "master" )
require . NoError ( t , err )
return c
}
func testEditorDiffPreview ( t * testing . T ) {
session := loginUser ( t , "user2" )
req := NewRequestWithValues ( t , "POST" , "/user2/repo1/_preview/master/README.md" , map [ string ] string {
"_csrf" : GetUserCSRFToken ( t , session ) ,
"content" : "Hello, World (Edited)\n" ,
} )
resp := session . MakeRequest ( t , req , http . StatusOK )
assert . Contains ( t , resp . Body . String ( ) , ` <span class="added-code">Hello, World (Edited)</span> ` )
}
session := loginUser ( t , user . Name )
makeReq := func ( t * testing . T , link string , params map [ string ] string , expectedUserName , expectedEmail string ) * httptest . ResponseRecorder {
lastCommit := getLastCommit ( t )
params [ "_csrf" ] = GetUserCSRFToken ( t , session )
params [ "last_commit" ] = lastCommit . ID . String ( )
params [ "commit_choice" ] = "direct"
req := NewRequestWithValues ( t , "POST" , link , params )
resp := session . MakeRequest ( t , req , NoExpectedStatus )
newCommit := getLastCommit ( t )
if expectedUserName == "" {
require . Equal ( t , lastCommit . ID . String ( ) , newCommit . ID . String ( ) )
respErr := test . ParseJSONError ( resp . Body . Bytes ( ) )
assert . Equal ( t , translation . NewLocale ( "en-US" ) . TrString ( "repo.editor.invalid_commit_email" ) , respErr . ErrorMessage )
} else {
require . NotEqual ( t , lastCommit . ID . String ( ) , newCommit . ID . String ( ) )
assert . Equal ( t , expectedUserName , newCommit . Author . Name )
assert . Equal ( t , expectedEmail , newCommit . Author . Email )
assert . Equal ( t , expectedUserName , newCommit . Committer . Name )
assert . Equal ( t , expectedEmail , newCommit . Committer . Email )
}
return resp
}
func testEditorPatchFile ( t * testing . T ) {
session := loginUser ( t , "user2" )
pathContentCommon := ` diff -- git a / patch - file - 1. txt b / patch - file - 1. txt
new file mode 100644
index 0000000000. . aaaaaaaaaa
-- - / dev / null
++ + b / patch - file - 1. txt
@ @ - 0 , 0 + 1 @ @
+ `
testEditorActionPostRequest ( t , session , "/user2/repo1/_diffpatch/master/" , map [ string ] string {
"content" : pathContentCommon + "patched content\n" ,
"commit_choice" : "commit-to-new-branch" ,
"new_branch_name" : "patched-branch" ,
} )
resp := MakeRequest ( t , NewRequest ( t , "GET" , "/user2/repo1/raw/branch/patched-branch/patch-file-1.txt" ) , http . StatusOK )
assert . Equal ( t , "patched content\n" , resp . Body . String ( ) )
// patch again, it should fail
resp = testEditorActionPostRequest ( t , session , "/user2/repo1/_diffpatch/patched-branch/" , map [ string ] string {
"content" : pathContentCommon + "another patched content\n" ,
"commit_choice" : "commit-to-new-branch" ,
"new_branch_name" : "patched-branch-1" ,
} )
assert . Equal ( t , "Unable to apply patch" , test . ParseJSONError ( resp . Body . Bytes ( ) ) . ErrorMessage )
}
uploadFile := func ( t * testing . T , name , content string ) string {
body := & bytes . Buffer { }
uploadForm := multipart . NewWriter ( body )
file , _ := uploadForm . CreateFormFile ( "file" , name )
_ , _ = io . Copy ( file , strings . NewReader ( content ) )
_ = uploadForm . WriteField ( "_csrf" , GetUserCSRFToken ( t , session ) )
_ = uploadForm . Close ( )
req := NewRequestWithBody ( t , "POST" , "/user2/repo1/upload-file" , body )
req . Header . Add ( "Content-Type" , uploadForm . FormDataContentType ( ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
respMap := map [ string ] string { }
DecodeJSON ( t , resp , & respMap )
return respMap [ "uuid" ]
func testEditorWebGitCommitEmail ( t * testing . T ) {
user := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
require . True ( t , user . KeepEmailPrivate )
repo1 := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { ID : 1 } )
gitRepo , _ := git . OpenRepository ( git . DefaultContext , repo1 . RepoPath ( ) )
defer gitRepo . Close ( )
getLastCommit := func ( t * testing . T ) * git . Commit {
c , err := gitRepo . GetBranchCommit ( "master" )
require . NoError ( t , err )
return c
}
session := loginUser ( t , user . Name )
makeReq := func ( t * testing . T , link string , params map [ string ] string , expectedUserName , expectedEmail string ) * httptest . ResponseRecorder {
lastCommit := getLastCommit ( t )
params [ "_csrf" ] = GetUserCSRFToken ( t , session )
params [ "last_commit" ] = lastCommit . ID . String ( )
params [ "commit_choice" ] = "direct"
req := NewRequestWithValues ( t , "POST" , link , params )
resp := session . MakeRequest ( t , req , NoExpectedStatus )
newCommit := getLastCommit ( t )
if expectedUserName == "" {
require . Equal ( t , lastCommit . ID . String ( ) , newCommit . ID . String ( ) )
respErr := test . ParseJSONError ( resp . Body . Bytes ( ) )
assert . Equal ( t , translation . NewLocale ( "en-US" ) . TrString ( "repo.editor.invalid_commit_email" ) , respErr . ErrorMessage )
} else {
require . NotEqual ( t , lastCommit . ID . String ( ) , newCommit . ID . String ( ) )
assert . Equal ( t , expectedUserName , newCommit . Author . Name )
assert . Equal ( t , expectedEmail , newCommit . Author . Email )
assert . Equal ( t , expectedUserName , newCommit . Committer . Name )
assert . Equal ( t , expectedEmail , newCommit . Committer . Email )
}
return resp
}
uploadFile := func ( t * testing . T , name , content string ) string {
body := & bytes . Buffer { }
uploadForm := multipart . NewWriter ( body )
file , _ := uploadForm . CreateFormFile ( "file" , name )
_ , _ = io . Copy ( file , strings . NewReader ( content ) )
_ = uploadForm . WriteField ( "_csrf" , GetUserCSRFToken ( t , session ) )
_ = uploadForm . Close ( )
req := NewRequestWithBody ( t , "POST" , "/user2/repo1/upload-file" , body )
req . Header . Add ( "Content-Type" , uploadForm . FormDataContentType ( ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
t . Run ( "EmailInactive" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
email := unittest . AssertExistsAndLoadBean ( t , & user_model . EmailAddress { ID : 35 , UID : user . ID } )
require . False ( t , email . IsActivated )
makeReq ( t , "/user2/repo1/_edit/master/README.md" , map [ string ] string {
"tree_path" : "README.md" ,
"content" : "test content" ,
"commit_email" : email . Email ,
} , "" , "" )
} )
respMap := map [ string ] string { }
DecodeJSON ( t , resp , & respMap )
return respMap [ "uuid" ]
}
t . Run ( "EmailInactive" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
email := unittest . AssertExistsAndLoadBean ( t , & user_model . EmailAddress { ID : 35 , UID : user . ID } )
require . False ( t , email . IsActivated )
makeReq ( t , "/user2/repo1/_edit/master/README.md" , map [ string ] string {
"tree_path" : "README.md" ,
"content" : "test content" ,
"commit_email" : email . Email ,
} , "" , "" )
} )
t . Run ( "EmailInvalid" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
email := unittest . AssertExistsAndLoadBean ( t , & user_model . EmailAddress { ID : 1 , IsActivated : true } )
require . NotEqual ( t , email . UID , user . ID )
makeReq ( t , "/user2/repo1/_edit/master/README.md" , map [ string ] string {
"tree_path" : "README.md" ,
"content" : "test content" ,
"commit_email" : email . Email ,
} , "" , "" )
} )
t . Run ( "EmailInvalid" , func ( t * testing . T ) {
testWebGit := func ( t * testing . T , linkForKeepPrivate string , paramsForKeepPrivate map [ string ] string , linkForChosenEmail string , paramsForChosenEmail map [ string ] string ) ( resp1 , resp2 * httptest . ResponseRecorder ) {
t . Run ( "DefaultEmailKeepPrivate" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
email := unittest . AssertExistsAndLoadBean ( t , & user_model . EmailAddress { ID : 1 , IsActivated : true } )
require . NotEqual ( t , email . UID , user . ID )
makeReq ( t , "/user2/repo1/_edit/master/README.md" , map [ string ] string {
"tree_path" : "README.md" ,
"content" : "test content" ,
"commit_email" : email . Email ,
} , "" , "" )
paramsForKeepPrivate [ "commit_email" ] = ""
resp1 = makeReq ( t , linkForKeepPrivate , paramsForKeepPrivate , "User Two" , "user2@noreply.example.org" )
} )
testWebGit := func ( t * testing . T , linkForKeepPrivate string , paramsForKeepPrivate map [ string ] string , linkForChosenEmail string , paramsForChosenEmail map [ string ] string ) ( resp1 , resp2 * httptest . ResponseRecorder ) {
t . Run ( "DefaultEmailKeepPrivate" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
paramsForKeepPrivate [ "commit_email" ] = ""
resp1 = makeReq ( t , linkForKeepPrivate , paramsForKeepPrivate , "User Two" , "user2@noreply.example.org" )
} )
t . Run ( "ChooseEmail" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
paramsForChosenEmail [ "commit_email" ] = "user2@example.com"
resp2 = makeReq ( t , linkForChosenEmail , paramsForChosenEmail , "User Two" , "user2@example.com" )
} )
return resp1 , resp2
}
t . Run ( "Edit" , func ( t * testing . T ) {
testWebGit ( t ,
"/user2/repo1/_edit/master/README.md" , map [ string ] string { "tree_path" : "README.md" , "content" : "for keep private" } ,
"/user2/repo1/_edit/master/README.md" , map [ string ] string { "tree_path" : "README.md" , "content" : "for chosen email" } ,
)
t . Run ( "ChooseEmail" , func ( t * testing . T ) {
defer tests . PrintCurrentTest ( t ) ( )
paramsForChosenEmail [ "commit_email" ] = "user2@example.com"
resp2 = makeReq ( t , linkForChosenEmail , paramsForChosenEmail , "User Two" , "user2@example.com" )
} )
return resp1 , resp2
}
t . Run ( "Edit" , func ( t * testing . T ) {
testWebGit ( t ,
"/user2/repo1/_edit/master/README.md" , map [ string ] string { "tree_path" : "README.md" , "content" : "for keep private" } ,
"/user2/repo1/_edit/master/README.md" , map [ string ] string { "tree_path" : "README.md" , "content" : "for chosen email" } ,
)
} )
t . Run ( "UploadDelete" , func ( t * testing . T ) {
file1UUID := uploadFile ( t , "file1" , "File 1" )
file2UUID := uploadFile ( t , "file2" , "File 2" )
testWebGit ( t ,
"/user2/repo1/_upload/master" , map [ string ] string { "files" : file1UUID } ,
"/user2/repo1/_upload/master" , map [ string ] string { "files" : file2UUID } ,
)
testWebGit ( t ,
"/user2/repo1/_delete/master/file1" , map [ string ] string { } ,
"/user2/repo1/_delete/master/file2" , map [ string ] string { } ,
)
} )
t . Run ( "UploadDelete" , func ( t * testing . T ) {
file1UUID := uploadFile ( t , "file1" , "File 1" )
file2UUID := uploadFile ( t , "file2" , "File 2" )
testWebGit ( t ,
"/user2/repo1/_upload/master" , map [ string ] string { "files" : file1UUID } ,
"/user2/repo1/_upload/master" , map [ string ] string { "files" : file2UUID } ,
)
testWebGit ( t ,
"/user2/repo1/_delete/master/file1" , map [ string ] string { } ,
"/user2/repo1/_delete/master/file2" , map [ string ] string { } ,
)
} )
t . Run ( "ApplyPatchCherryPick" , func ( t * testing . T ) {
testWebGit ( t ,
"/user2/repo1/_diffpatch/master" , map [ string ] string {
"tree_path" : "__dummy__" ,
"content" : ` diff -- git a / patch - file - 1. txt b / patch - file - 1. txt
t . Run ( "ApplyPatchCherryPick" , func ( t * testing . T ) {
testWebGit ( t ,
"/user2/repo1/_diffpatch/master" , map [ string ] string {
"tree_path" : "__dummy__" ,
"content" : ` diff -- git a / patch - file - 1. txt b / patch - file - 1. txt
new file mode 100644
index 0000000000. . aaaaaaaaaa
-- - / dev / null
@ -312,10 +299,10 @@ index 0000000000..aaaaaaaaaa
@ @ - 0 , 0 + 1 @ @
+ File 1
` ,
} ,
"/user2/repo1/_diffpatch/master" , map [ string ] string {
"tree_path" : "__dummy__" ,
"content" : ` diff -- git a / patch - file - 2. txt b / patch - file - 2. txt
} ,
"/user2/repo1/_diffpatch/master" , map [ string ] string {
"tree_path" : "__dummy__" ,
"content" : ` diff -- git a / patch - file - 2. txt b / patch - file - 2. txt
new file mode 100644
index 0000000000. . bbbbbbbbbb
-- - / dev / null
@ -323,20 +310,146 @@ index 0000000000..bbbbbbbbbb
@ @ - 0 , 0 + 1 @ @
+ File 2
` ,
} ,
)
commit1 , err := gitRepo . GetCommitByPath ( "patch-file-1.txt" )
require . NoError ( t , err )
commit2 , err := gitRepo . GetCommitByPath ( "patch-file-2.txt" )
require . NoError ( t , err )
resp1 , _ := testWebGit ( t ,
"/user2/repo1/_cherrypick/" + commit1 . ID . String ( ) + "/master" , map [ string ] string { "revert" : "true" } ,
"/user2/repo1/_cherrypick/" + commit2 . ID . String ( ) + "/master" , map [ string ] string { "revert" : "true" } ,
)
// By the way, test the "cherrypick" page: a successful revert redirects to the main branch
assert . Equal ( t , "/user2/repo1/src/branch/master" , test . RedirectURL ( resp1 ) )
} )
} ,
)
commit1 , err := gitRepo . GetCommitByPath ( "patch-file-1.txt" )
require . NoError ( t , err )
commit2 , err := gitRepo . GetCommitByPath ( "patch-file-2.txt" )
require . NoError ( t , err )
resp1 , _ := testWebGit ( t ,
"/user2/repo1/_cherrypick/" + commit1 . ID . String ( ) + "/master" , map [ string ] string { "revert" : "true" } ,
"/user2/repo1/_cherrypick/" + commit2 . ID . String ( ) + "/master" , map [ string ] string { "revert" : "true" } ,
)
// By the way, test the "cherrypick" page: a successful revert redirects to the main branch
assert . Equal ( t , "/user2/repo1/src/branch/master" , test . RedirectURL ( resp1 ) )
} )
}
func testForkToEditFile ( t * testing . T , session * TestSession , user , owner , repo , branch , filePath string ) {
forkToEdit := func ( t * testing . T , session * TestSession , owner , repo , operation , branch , filePath string ) {
// visit the base repo, see the "Add File" button
req := NewRequest ( t , "GET" , path . Join ( owner , repo ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
AssertHTMLElement ( t , htmlDoc , ".repo-add-file" , 1 )
// attempt to edit a file, see the guideline page
req = NewRequest ( t , "GET" , path . Join ( owner , repo , operation , branch , filePath ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . Contains ( t , resp . Body . String ( ) , "Fork Repository to Propose Changes" )
// fork the repository
req = NewRequestWithValues ( t , "POST" , path . Join ( owner , repo , "_fork" , branch ) , map [ string ] string { "_csrf" : GetUserCSRFToken ( t , session ) } )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . JSONEq ( t , ` { "redirect":""} ` , resp . Body . String ( ) )
}
t . Run ( "ForkButArchived" , func ( t * testing . T ) {
// Fork repository because we can't edit it
forkToEdit ( t , session , owner , repo , "_edit" , branch , filePath )
// Archive the repository
req := NewRequestWithValues ( t , "POST" , path . Join ( user , repo , "settings" ) ,
map [ string ] string {
"_csrf" : GetUserCSRFToken ( t , session ) ,
"repo_name" : repo ,
"action" : "archive" ,
} ,
)
session . MakeRequest ( t , req , http . StatusSeeOther )
// Check editing archived repository is disabled
req = NewRequest ( t , "GET" , path . Join ( owner , repo , "_edit" , branch , filePath ) ) . SetHeader ( "Accept" , "text/html" )
resp := session . MakeRequest ( t , req , http . StatusNotFound )
assert . Contains ( t , resp . Body . String ( ) , "You have forked this repository but your fork is not editable." )
// Unfork the repository
req = NewRequestWithValues ( t , "POST" , path . Join ( user , repo , "settings" ) ,
map [ string ] string {
"_csrf" : GetUserCSRFToken ( t , session ) ,
"repo_name" : repo ,
"action" : "convert_fork" ,
} ,
)
session . MakeRequest ( t , req , http . StatusSeeOther )
} )
// Fork repository again, and check the existence of the forked repo with unique name
forkToEdit ( t , session , owner , repo , "_edit" , branch , filePath )
session . MakeRequest ( t , NewRequestf ( t , "GET" , "/%s/%s-1" , user , repo ) , http . StatusOK )
t . Run ( "CheckBaseRepoForm" , func ( t * testing . T ) {
// the base repo's edit form should have the correct action and upload links (pointing to the forked repo)
req := NewRequest ( t , "GET" , path . Join ( owner , repo , "_upload" , branch , filePath ) + "?foo=bar" )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
uploadForm := htmlDoc . doc . Find ( ".form-fetch-action" )
formAction := uploadForm . AttrOr ( "action" , "" )
assert . Equal ( t , fmt . Sprintf ( "/%s/%s-1/_upload/%s/%s?from_base_branch=%s&foo=bar" , user , repo , branch , filePath , branch ) , formAction )
uploadLink := uploadForm . Find ( ".dropzone" ) . AttrOr ( "data-link-url" , "" )
assert . Equal ( t , fmt . Sprintf ( "/%s/%s-1/upload-file" , user , repo ) , uploadLink )
newBranchName := uploadForm . Find ( "input[name=new_branch_name]" ) . AttrOr ( "value" , "" )
assert . Equal ( t , user + "-patch-1" , newBranchName )
commitChoice := uploadForm . Find ( "input[name=commit_choice][checked]" ) . AttrOr ( "value" , "" )
assert . Equal ( t , "commit-to-new-branch" , commitChoice )
lastCommit := uploadForm . Find ( "input[name=last_commit]" ) . AttrOr ( "value" , "" )
assert . NotEmpty ( t , lastCommit )
} )
t . Run ( "ViewBaseEditFormAndCommitToFork" , func ( t * testing . T ) {
req := NewRequest ( t , "GET" , path . Join ( owner , repo , "_edit" , branch , filePath ) )
resp := session . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
editRequestForm := map [ string ] string {
"_csrf" : GetUserCSRFToken ( t , session ) ,
"last_commit" : htmlDoc . GetInputValueByName ( "last_commit" ) ,
"tree_path" : filePath ,
"content" : "new content in fork" ,
"commit_choice" : "commit-to-new-branch" ,
}
// change a file in the forked repo with existing branch name (should fail)
editRequestForm [ "new_branch_name" ] = "master"
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s-1/_edit/%s/%s?from_base_branch=%s" , user , repo , branch , filePath , branch ) , editRequestForm )
resp = session . MakeRequest ( t , req , http . StatusBadRequest )
respJSON := test . ParseJSONError ( resp . Body . Bytes ( ) )
assert . Equal ( t , ` Branch "master" already exists in your fork, please choose a new branch name. ` , respJSON . ErrorMessage )
// change a file in the forked repo (should succeed)
newBranchName := htmlDoc . GetInputValueByName ( "new_branch_name" )
editRequestForm [ "new_branch_name" ] = newBranchName
req = NewRequestWithValues ( t , "POST" , fmt . Sprintf ( "/%s/%s-1/_edit/%s/%s?from_base_branch=%s" , user , repo , branch , filePath , branch ) , editRequestForm )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . Equal ( t , fmt . Sprintf ( "/%s/%s/compare/%s...%s/%s-1:%s" , owner , repo , branch , user , repo , newBranchName ) , test . RedirectURL ( resp ) )
// check the file in the fork's branch is changed
req = NewRequest ( t , "GET" , fmt . Sprintf ( "/%s/%s-1/src/branch/%s/%s" , user , repo , newBranchName , filePath ) )
resp = session . MakeRequest ( t , req , http . StatusOK )
assert . Contains ( t , resp . Body . String ( ) , "new content in fork" )
} )
}
func testEditFileNotAllowed ( t * testing . T ) {
sessionUser1 := loginUser ( t , "user1" ) // admin, all access
sessionUser4 := loginUser ( t , "user4" )
// "_cherrypick" has a different route pattern, so skip its test
operations := [ ] string { "_new" , "_edit" , "_delete" , "_upload" , "_diffpatch" }
for _ , operation := range operations {
t . Run ( operation , func ( t * testing . T ) {
// Branch does not exist
targetLink := path . Join ( "user2" , "repo1" , operation , "missing" , "README.md" )
sessionUser1 . MakeRequest ( t , NewRequest ( t , "GET" , targetLink ) , http . StatusNotFound )
// Private repository
targetLink = path . Join ( "user2" , "repo2" , operation , "master" , "Home.md" )
sessionUser1 . MakeRequest ( t , NewRequest ( t , "GET" , targetLink ) , http . StatusOK )
sessionUser4 . MakeRequest ( t , NewRequest ( t , "GET" , targetLink ) , http . StatusNotFound )
// Empty repository
targetLink = path . Join ( "org41" , "repo61" , operation , "master" , "README.md" )
sessionUser1 . MakeRequest ( t , NewRequest ( t , "GET" , targetLink ) , http . StatusNotFound )
} )
}
}