refactor tests

This commit is contained in:
wxiaoguang 2025-06-22 12:15:42 +08:00
parent 8313490acb
commit c7395dc05a
1 changed files with 286 additions and 362 deletions

View File

@ -7,6 +7,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"maps"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -19,292 +20,216 @@ import (
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestCreateFile(t *testing.T) { func TestEditor(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
session := loginUser(t, "user2") sessionUser2 := loginUser(t, "user2")
testCreateFile(t, session, "user2", "repo1", "master", "test.txt", "Content") t.Run("CreateFile", func(t *testing.T) {
testCreateFile(t, sessionUser2, "user2", "repo1", "master", "test.txt", "Content")
})
t.Run("EditFile", func(t *testing.T) {
testEditFile(t, sessionUser2, "user2", "repo1", "master", "README.md", "Hello, World (direct)\n")
})
t.Run("EditFileToNewBranch", func(t *testing.T) {
testEditFileToNewBranch(t, sessionUser2, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (commit-to-new-branch)\n")
})
t.Run("ForkToEditFile", func(t *testing.T) {
testForkToEditFile(t, loginUser(t, "user4"), "user4", "user2", "repo1", "master", "README.md")
})
t.Run("WebGitCommitEmail", testWebGitCommitEmail)
t.Run("CreateFileOnProtectedBranch", testCreateFileOnProtectedBranch)
}) })
} }
func testCreateFile(t *testing.T, session *TestSession, user, repo, branch, filePath, content string) { func testCreateFile(t *testing.T, session *TestSession, user, repo, branch, filePath, content string) {
// Request editor page testEditorActionEdit(t, session, user, repo, "_new", branch, "", map[string]string{
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)
// Save new file to master branch
req = NewRequestWithValues(t, "POST", newURL, map[string]string{
"_csrf": doc.GetCSRF(),
"last_commit": lastCommit,
"tree_path": filePath, "tree_path": filePath,
"content": content, "content": content,
"commit_choice": "direct", "commit_choice": "direct",
}) })
resp = session.MakeRequest(t, req, http.StatusOK)
assert.NotEmpty(t, test.RedirectURL(resp))
} }
func TestCreateFileOnProtectedBranch(t *testing.T) { func testCreateFileOnProtectedBranch(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { session := loginUser(t, "user2")
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)
csrf := GetUserCSRFToken(t, session) // Try to commit a file to the "master" branch and it should fail
// Change master branch to protected resp := testEditorActionPostRequest(t, session, "/user2/repo1/_new/master/", map[string]string{"tree_path": "test-protected-branch.txt", "commit_choice": "direct"})
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{ assert.Equal(t, http.StatusBadRequest, resp.Code)
"_csrf": csrf, assert.Equal(t, `Cannot commit to protected branch "master".`, test.ParseJSONError(resp.Body.Bytes()).ErrorMessage)
"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 func testEditorActionPostRequest(t *testing.T, session *TestSession, requestPath string, params map[string]string) *httptest.ResponseRecorder {
req = NewRequest(t, "GET", "/user2/repo1/_new/master/") req := NewRequest(t, "GET", requestPath)
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
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 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))
req := NewRequest(t, "GET", path.Join(user, repo, "raw/branch", newBranchName, params["tree_path"]))
resp = session.MakeRequest(t, req, http.StatusOK)
assert.Equal(t, params["content"], resp.Body.String())
return resp
}
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, 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) {
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) resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body) respMap := map[string]string{}
lastCommit := doc.GetInputValueByName("last_commit") DecodeJSON(t, resp, &respMap)
assert.NotEmpty(t, lastCommit) return respMap["uuid"]
}
// Save new file to master branch t.Run("EmailInactive", func(t *testing.T) {
req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{ defer tests.PrintCurrentTest(t)()
"_csrf": doc.GetCSRF(), email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{ID: 35, UID: user.ID})
"last_commit": lastCommit, require.False(t, email.IsActivated)
"tree_path": "test.txt", makeReq(t, "/user2/repo1/_edit/master/README.md", map[string]string{
"content": "Content", "tree_path": "README.md",
"commit_choice": "direct", "content": "test content",
}) "commit_email": email.Email,
}, "", "")
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 testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePath, newContent string) *httptest.ResponseRecorder { t.Run("EmailInvalid", func(t *testing.T) {
// Get to the 'edit this file' page defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", path.Join(user, repo, "_edit", branch, filePath)) email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{ID: 1, IsActivated: true})
resp := session.MakeRequest(t, req, http.StatusOK) require.NotEqual(t, email.UID, user.ID)
makeReq(t, "/user2/repo1/_edit/master/README.md", map[string]string{
htmlDoc := NewHTMLParser(t, resp.Body) "tree_path": "README.md",
lastCommit := htmlDoc.GetInputValueByName("last_commit") "content": "test content",
assert.NotEmpty(t, lastCommit) "commit_email": email.Email,
}, "", "")
// 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
}
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)
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)
assert.NotEmpty(t, test.RedirectURL(resp))
// Verify the change
req = NewRequest(t, "GET", path.Join(user, repo, "raw/branch", targetBranch, filePath))
resp = session.MakeRequest(t, req, http.StatusOK)
assert.Equal(t, newContent, resp.Body.String())
return resp
}
func TestEditFile(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 TestEditFileToNewBranch(t *testing.T) { testWebGit := func(t *testing.T, linkForKeepPrivate string, paramsForKeepPrivate map[string]string, linkForChosenEmail string, paramsForChosenEmail map[string]string) (resp1, resp2 *httptest.ResponseRecorder) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { t.Run("DefaultEmailKeepPrivate", func(t *testing.T) {
session := loginUser(t, "user2")
testEditFileToNewBranch(t, session, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
})
}
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
}
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)
respMap := map[string]string{}
DecodeJSON(t, resp, &respMap)
return respMap["uuid"]
}
t.Run("EmailInactive", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{ID: 35, UID: user.ID}) paramsForKeepPrivate["commit_email"] = ""
require.False(t, email.IsActivated) resp1 = makeReq(t, linkForKeepPrivate, paramsForKeepPrivate, "User Two", "user2@noreply.example.org")
makeReq(t, "/user2/repo1/_edit/master/README.md", map[string]string{
"tree_path": "README.md",
"content": "test content",
"commit_email": email.Email,
}, "", "")
}) })
t.Run("ChooseEmail", func(t *testing.T) {
t.Run("EmailInvalid", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{ID: 1, IsActivated: true}) paramsForChosenEmail["commit_email"] = "user2@example.com"
require.NotEqual(t, email.UID, user.ID) resp2 = makeReq(t, linkForChosenEmail, paramsForChosenEmail, "User Two", "user2@example.com")
makeReq(t, "/user2/repo1/_edit/master/README.md", map[string]string{
"tree_path": "README.md",
"content": "test content",
"commit_email": email.Email,
}, "", "")
}) })
return resp1, resp2
}
testWebGit := func(t *testing.T, linkForKeepPrivate string, paramsForKeepPrivate map[string]string, linkForChosenEmail string, paramsForChosenEmail map[string]string) (resp1, resp2 *httptest.ResponseRecorder) { t.Run("Edit", func(t *testing.T) {
t.Run("DefaultEmailKeepPrivate", func(t *testing.T) { testWebGit(t,
defer tests.PrintCurrentTest(t)() "/user2/repo1/_edit/master/README.md", map[string]string{"tree_path": "README.md", "content": "for keep private"},
paramsForKeepPrivate["commit_email"] = "" "/user2/repo1/_edit/master/README.md", map[string]string{"tree_path": "README.md", "content": "for chosen 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) { t.Run("UploadDelete", func(t *testing.T) {
testWebGit(t, file1UUID := uploadFile(t, "file1", "File 1")
"/user2/repo1/_edit/master/README.md", map[string]string{"tree_path": "README.md", "content": "for keep private"}, file2UUID := uploadFile(t, "file2", "File 2")
"/user2/repo1/_edit/master/README.md", map[string]string{"tree_path": "README.md", "content": "for chosen email"}, 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) { t.Run("ApplyPatchCherryPick", func(t *testing.T) {
file1UUID := uploadFile(t, "file1", "File 1") testWebGit(t,
file2UUID := uploadFile(t, "file2", "File 2") "/user2/repo1/_diffpatch/master", map[string]string{
testWebGit(t, "tree_path": "__dummy__",
"/user2/repo1/_upload/master", map[string]string{"files": file1UUID}, "content": `diff --git a/patch-file-1.txt b/patch-file-1.txt
"/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
new file mode 100644 new file mode 100644
index 0000000000..aaaaaaaaaa index 0000000000..aaaaaaaaaa
--- /dev/null --- /dev/null
@ -312,10 +237,10 @@ index 0000000000..aaaaaaaaaa
@@ -0,0 +1 @@ @@ -0,0 +1 @@
+File 1 +File 1
`, `,
}, },
"/user2/repo1/_diffpatch/master", map[string]string{ "/user2/repo1/_diffpatch/master", map[string]string{
"tree_path": "__dummy__", "tree_path": "__dummy__",
"content": `diff --git a/patch-file-2.txt b/patch-file-2.txt "content": `diff --git a/patch-file-2.txt b/patch-file-2.txt
new file mode 100644 new file mode 100644
index 0000000000..bbbbbbbbbb index 0000000000..bbbbbbbbbb
--- /dev/null --- /dev/null
@ -323,124 +248,123 @@ index 0000000000..bbbbbbbbbb
@@ -0,0 +1 @@ @@ -0,0 +1 @@
+File 2 +File 2
`, `,
}, },
) )
commit1, err := gitRepo.GetCommitByPath("patch-file-1.txt") commit1, err := gitRepo.GetCommitByPath("patch-file-1.txt")
require.NoError(t, err) require.NoError(t, err)
commit2, err := gitRepo.GetCommitByPath("patch-file-2.txt") commit2, err := gitRepo.GetCommitByPath("patch-file-2.txt")
require.NoError(t, err) require.NoError(t, err)
resp1, _ := testWebGit(t, resp1, _ := testWebGit(t,
"/user2/repo1/_cherrypick/"+commit1.ID.String()+"/master", map[string]string{"revert": "true"}, "/user2/repo1/_cherrypick/"+commit1.ID.String()+"/master", map[string]string{"revert": "true"},
"/user2/repo1/_cherrypick/"+commit2.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 // 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)) assert.Equal(t, "/user2/repo1/src/branch/master", test.RedirectURL(resp1))
})
}) })
} }
func forkToEdit(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())
}
func testForkToEditFile(t *testing.T, session *TestSession, user, owner, repo, branch, filePath string) { func testForkToEditFile(t *testing.T, session *TestSession, user, owner, repo, branch, filePath string) {
// Fork repository because we can't edit it forkToEdit := func(t *testing.T, session *TestSession, owner, repo, operation, branch, filePath string) {
forkToEdit(t, session, owner, repo, "_edit", branch, filePath) // 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)
// Archive the repository // attempt to edit a file, see the guideline page
req := NewRequestWithValues(t, "POST", path.Join(user, repo, "settings"), req = NewRequest(t, "GET", path.Join(owner, repo, operation, branch, filePath))
map[string]string{ resp = session.MakeRequest(t, req, http.StatusOK)
"_csrf": GetUserCSRFToken(t, session), assert.Contains(t, resp.Body.String(), "Fork Repository to Propose Changes")
"repo_name": repo,
"action": "archive",
},
)
session.MakeRequest(t, req, http.StatusSeeOther)
// Check editing archived repository is disabled // fork the repository
req = NewRequest(t, "GET", path.Join(owner, repo, "_edit", branch, filePath)).SetHeader("Accept", "text/html") req = NewRequestWithValues(t, "POST", path.Join(owner, repo, "_fork", branch), map[string]string{"_csrf": GetUserCSRFToken(t, session)})
resp := session.MakeRequest(t, req, http.StatusNotFound) resp = session.MakeRequest(t, req, http.StatusOK)
assert.Contains(t, resp.Body.String(), "You have forked this repository but your fork is not editable.") assert.JSONEq(t, `{"redirect":""}`, resp.Body.String())
// 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
forkToEdit(t, session, owner, repo, "_edit", branch, filePath)
// Check the existence of the forked repo with unique name
req = NewRequestf(t, "GET", "/%s/%s-1", user, repo)
session.MakeRequest(t, req, http.StatusOK)
// 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))
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
form := htmlDoc.doc.Find(".form-fetch-action")
formAction := form.AttrOr("action", "")
assert.Equal(t, fmt.Sprintf("/%s/%s-1/_upload/%s/%s?from_base_branch=%s", user, repo, branch, filePath, branch), formAction)
uploadLink := form.Find(".dropzone").AttrOr("data-link-url", "")
assert.Equal(t, fmt.Sprintf("/%s/%s-1/upload-file", user, repo), uploadLink)
newBranchName := form.Find("input[name=new_branch_name]").AttrOr("value", "")
assert.Equal(t, user+"-patch-1", newBranchName)
commitChoice := form.Find("input[name=commit_choice][checked]").AttrOr("value", "")
assert.Equal(t, "commit-to-new-branch", commitChoice)
lastCommit := form.Find("input[name=last_commit]").AttrOr("value", "")
assert.NotEmpty(t, lastCommit)
editRequestForm := map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"last_commit": lastCommit,
"tree_path": filePath,
"content": "new content in fork",
"commit_choice": commitChoice,
"new_branch_name": "master",
} }
// change a file in the forked repo with existing branch name (should fail)
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) t.Run("ForkButArchived", func(t *testing.T) {
editRequestForm["new_branch_name"] = newBranchName // Fork repository because we can't edit it
req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s-1/_edit/%s/%s?from_base_branch=%s", user, repo, branch, filePath, branch), editRequestForm) forkToEdit(t, session, owner, repo, "_edit", branch, filePath)
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 // Archive the repository
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s-1/src/branch/%s/%s", user, repo, newBranchName, filePath)) req := NewRequestWithValues(t, "POST", path.Join(user, repo, "settings"),
resp = session.MakeRequest(t, req, http.StatusOK) map[string]string{
assert.Contains(t, resp.Body.String(), "new content in fork") "_csrf": GetUserCSRFToken(t, session),
} "repo_name": repo,
"action": "archive",
},
)
session.MakeRequest(t, req, http.StatusSeeOther)
func TestForkToEditFile(t *testing.T) { // Check editing archived repository is disabled
onGiteaRun(t, func(t *testing.T, u *url.URL) { req = NewRequest(t, "GET", path.Join(owner, repo, "_edit", branch, filePath)).SetHeader("Accept", "text/html")
session := loginUser(t, "user4") resp := session.MakeRequest(t, req, http.StatusNotFound)
testForkToEditFile(t, session, "user4", "user2", "repo1", "master", "README.md") 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))
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", 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")
}) })
} }