code.gitea.io/gitea@v1.22.3/tests/integration/pull_create_test.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "fmt" 8 "net/http" 9 "net/http/httptest" 10 "net/url" 11 "path" 12 "strings" 13 "testing" 14 15 "code.gitea.io/gitea/modules/test" 16 "code.gitea.io/gitea/tests" 17 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func testPullCreate(t *testing.T, session *TestSession, user, repo string, toSelf bool, targetBranch, sourceBranch, title string) *httptest.ResponseRecorder { 22 req := NewRequest(t, "GET", path.Join(user, repo)) 23 resp := session.MakeRequest(t, req, http.StatusOK) 24 25 // Click the PR button to create a pull 26 htmlDoc := NewHTMLParser(t, resp.Body) 27 link, exists := htmlDoc.doc.Find("#new-pull-request").Attr("href") 28 assert.True(t, exists, "The template has changed") 29 30 targetUser := strings.Split(link, "/")[1] 31 if toSelf && targetUser != user { 32 link = strings.Replace(link, targetUser, user, 1) 33 } 34 35 if targetBranch != "master" { 36 link = strings.Replace(link, "master...", targetBranch+"...", 1) 37 } 38 if sourceBranch != "master" { 39 if targetUser == user { 40 link = strings.Replace(link, "...master", "..."+sourceBranch, 1) 41 } else { 42 link = strings.Replace(link, ":master", ":"+sourceBranch, 1) 43 } 44 } 45 46 req = NewRequest(t, "GET", link) 47 resp = session.MakeRequest(t, req, http.StatusOK) 48 49 // Submit the form for creating the pull 50 htmlDoc = NewHTMLParser(t, resp.Body) 51 link, exists = htmlDoc.doc.Find("form.ui.form").Attr("action") 52 assert.True(t, exists, "The template has changed") 53 req = NewRequestWithValues(t, "POST", link, map[string]string{ 54 "_csrf": htmlDoc.GetCSRF(), 55 "title": title, 56 }) 57 resp = session.MakeRequest(t, req, http.StatusOK) 58 return resp 59 } 60 61 func testPullCreateDirectly(t *testing.T, session *TestSession, baseRepoOwner, baseRepoName, baseBranch, headRepoOwner, headRepoName, headBranch, title string) *httptest.ResponseRecorder { 62 headCompare := headBranch 63 if headRepoOwner != "" { 64 if headRepoName != "" { 65 headCompare = fmt.Sprintf("%s/%s:%s", headRepoOwner, headRepoName, headBranch) 66 } else { 67 headCompare = fmt.Sprintf("%s:%s", headRepoOwner, headBranch) 68 } 69 } 70 req := NewRequest(t, "GET", fmt.Sprintf("/%s/%s/compare/%s...%s", baseRepoOwner, baseRepoName, baseBranch, headCompare)) 71 resp := session.MakeRequest(t, req, http.StatusOK) 72 73 // Submit the form for creating the pull 74 htmlDoc := NewHTMLParser(t, resp.Body) 75 link, exists := htmlDoc.doc.Find("form.ui.form").Attr("action") 76 assert.True(t, exists, "The template has changed") 77 req = NewRequestWithValues(t, "POST", link, map[string]string{ 78 "_csrf": htmlDoc.GetCSRF(), 79 "title": title, 80 }) 81 resp = session.MakeRequest(t, req, http.StatusOK) 82 return resp 83 } 84 85 func TestPullCreate(t *testing.T) { 86 onGiteaRun(t, func(t *testing.T, u *url.URL) { 87 session := loginUser(t, "user1") 88 testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "") 89 testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") 90 resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title") 91 92 // check the redirected URL 93 url := test.RedirectURL(resp) 94 assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url) 95 96 // check .diff can be accessed and matches performed change 97 req := NewRequest(t, "GET", url+".diff") 98 resp = session.MakeRequest(t, req, http.StatusOK) 99 assert.Regexp(t, `\+Hello, World \(Edited\)`, resp.Body) 100 assert.Regexp(t, "^diff", resp.Body) 101 assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one 102 103 // check .patch can be accessed and matches performed change 104 req = NewRequest(t, "GET", url+".patch") 105 resp = session.MakeRequest(t, req, http.StatusOK) 106 assert.Regexp(t, `\+Hello, World \(Edited\)`, resp.Body) 107 assert.Regexp(t, "diff", resp.Body) 108 assert.Regexp(t, `Subject: \[PATCH\] Update README.md`, resp.Body) 109 assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one 110 }) 111 } 112 113 func TestPullCreate_TitleEscape(t *testing.T) { 114 onGiteaRun(t, func(t *testing.T, u *url.URL) { 115 session := loginUser(t, "user1") 116 testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "") 117 testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") 118 resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "<i>XSS PR</i>") 119 120 // check the redirected URL 121 url := test.RedirectURL(resp) 122 assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url) 123 124 // Edit title 125 req := NewRequest(t, "GET", url) 126 resp = session.MakeRequest(t, req, http.StatusOK) 127 htmlDoc := NewHTMLParser(t, resp.Body) 128 editTestTitleURL, exists := htmlDoc.doc.Find(".issue-title-buttons button[data-update-url]").First().Attr("data-update-url") 129 assert.True(t, exists, "The template has changed") 130 131 req = NewRequestWithValues(t, "POST", editTestTitleURL, map[string]string{ 132 "_csrf": htmlDoc.GetCSRF(), 133 "title": "<u>XSS PR</u>", 134 }) 135 session.MakeRequest(t, req, http.StatusOK) 136 137 req = NewRequest(t, "GET", url) 138 resp = session.MakeRequest(t, req, http.StatusOK) 139 htmlDoc = NewHTMLParser(t, resp.Body) 140 titleHTML, err := htmlDoc.doc.Find(".comment-list .timeline-item.event .text b").First().Html() 141 assert.NoError(t, err) 142 assert.Equal(t, "<strike><i>XSS PR</i></strike>", titleHTML) 143 titleHTML, err = htmlDoc.doc.Find(".comment-list .timeline-item.event .text b").Next().Html() 144 assert.NoError(t, err) 145 assert.Equal(t, "<u>XSS PR</u>", titleHTML) 146 }) 147 } 148 149 func testUIDeleteBranch(t *testing.T, session *TestSession, ownerName, repoName, branchName string) { 150 relURL := "/" + path.Join(ownerName, repoName, "branches") 151 req := NewRequest(t, "GET", relURL) 152 resp := session.MakeRequest(t, req, http.StatusOK) 153 htmlDoc := NewHTMLParser(t, resp.Body) 154 155 req = NewRequestWithValues(t, "POST", relURL+"/delete", map[string]string{ 156 "_csrf": htmlDoc.GetCSRF(), 157 "name": branchName, 158 }) 159 session.MakeRequest(t, req, http.StatusOK) 160 } 161 162 func testDeleteRepository(t *testing.T, session *TestSession, ownerName, repoName string) { 163 relURL := "/" + path.Join(ownerName, repoName, "settings") 164 req := NewRequest(t, "GET", relURL) 165 resp := session.MakeRequest(t, req, http.StatusOK) 166 htmlDoc := NewHTMLParser(t, resp.Body) 167 168 req = NewRequestWithValues(t, "POST", relURL+"?action=delete", map[string]string{ 169 "_csrf": htmlDoc.GetCSRF(), 170 "repo_name": repoName, 171 }) 172 session.MakeRequest(t, req, http.StatusSeeOther) 173 } 174 175 func TestPullBranchDelete(t *testing.T) { 176 onGiteaRun(t, func(t *testing.T, u *url.URL) { 177 defer tests.PrepareTestEnv(t)() 178 179 session := loginUser(t, "user1") 180 testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "") 181 testCreateBranch(t, session, "user1", "repo1", "branch/master", "master1", http.StatusSeeOther) 182 testEditFile(t, session, "user1", "repo1", "master1", "README.md", "Hello, World (Edited)\n") 183 resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master1", "This is a pull title") 184 185 // check the redirected URL 186 url := test.RedirectURL(resp) 187 assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url) 188 req := NewRequest(t, "GET", url) 189 session.MakeRequest(t, req, http.StatusOK) 190 191 // delete head branch and confirm pull page is ok 192 testUIDeleteBranch(t, session, "user1", "repo1", "master1") 193 req = NewRequest(t, "GET", url) 194 session.MakeRequest(t, req, http.StatusOK) 195 196 // delete head repository and confirm pull page is ok 197 testDeleteRepository(t, session, "user1", "repo1") 198 req = NewRequest(t, "GET", url) 199 session.MakeRequest(t, req, http.StatusOK) 200 }) 201 }