forgejo/tests/integration/pull_diff_test.go
Antonin Delpeuch 4694cbf95b fix: don't mark files in AGit PRs as editable (#8642)
Fixes #8639.

For your convenience this PR is made via AGit for you to see the issue directly in Codeberg ^^

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.

I am not sure how to best write a unit test for this. It looks like there isn't any AGit PR in the default test database. The integration test in `test/integration/pull_review_test.go` creates one by manually running Git commands. I could just copy all that code to do the same in another test, but I feel bad about duplicating this. Can they be sensibly migrated to some helpers module that can be reused across tests? Or can we add an AGit PR to the test database? Or can we modify the `Flow` attribute of a PR in a test just for the sake of simulating that it's an AGit one?

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8642
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Co-committed-by: Antonin Delpeuch <antonin@delpeuch.eu>
2025-07-27 10:05:55 +02:00

136 lines
4.5 KiB
Go

// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"fmt"
"net/http"
"net/url"
"os"
"path"
"strings"
"testing"
"time"
issues_model "forgejo.org/models/issues"
unit_model "forgejo.org/models/unit"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/git"
files_service "forgejo.org/services/repository/files"
"forgejo.org/tests"
"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPullDiff_CompletePRDiff(t *testing.T) {
doTestPRDiff(t, "/user2/commitsonpr/pulls/1/files", []string{"test1.txt", "test10.txt", "test2.txt", "test3.txt", "test4.txt", "test5.txt", "test6.txt", "test7.txt", "test8.txt", "test9.txt"}, true)
}
func TestPullDiff_SingleCommitPRDiff(t *testing.T) {
doTestPRDiff(t, "/user2/commitsonpr/pulls/1/commits/c5626fc9eff57eb1bb7b796b01d4d0f2f3f792a2", []string{"test3.txt"}, true)
}
func TestPullDiff_CommitRangePRDiff(t *testing.T) {
doTestPRDiff(t, "/user2/commitsonpr/pulls/1/files/4ca8bcaf27e28504df7bf996819665986b01c847..23576dd018294e476c06e569b6b0f170d0558705", []string{"test2.txt", "test3.txt", "test4.txt"}, true)
}
func TestPullDiff_StartingFromBaseToCommitPRDiff(t *testing.T) {
doTestPRDiff(t, "/user2/commitsonpr/pulls/1/files/c5626fc9eff57eb1bb7b796b01d4d0f2f3f792a2", []string{"test1.txt", "test2.txt", "test3.txt"}, true)
}
func doTestPRDiff(t *testing.T, prDiffURL string, expectedFilenames []string, editable bool) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
req := NewRequest(t, "GET", "/user2/commitsonpr/pulls")
session.MakeRequest(t, req, http.StatusOK)
// Get the given PR diff url
req = NewRequest(t, "GET", prDiffURL)
resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
// Assert all files are visible.
fileContents := doc.doc.Find(".file-content")
numberOfFiles := fileContents.Length()
assert.Equal(t, len(expectedFilenames), numberOfFiles)
fileContents.Each(func(i int, s *goquery.Selection) {
filename, _ := s.Attr("data-old-filename")
assert.Equal(t, expectedFilenames[i], filename)
doc.AssertElement(t, "h4.diff-file-header a.button[href=\"/user2/commitsonpr/_edit/branch1/"+filename+"\"]", editable)
})
}
func TestPullDiff_AGitNotEditable(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)
// Create temporary repository.
repo, _, f := tests.CreateDeclarativeRepo(t, user2, "myrepo",
[]unit_model.Type{unit_model.TypePullRequests}, nil,
[]*files_service.ChangeRepoFile{
{
Operation: "create",
TreePath: "FUNFACT",
ContentReader: strings.NewReader("Smithy was the runner up to be Forgejo's name"),
},
},
)
defer f()
clone := func(t *testing.T, clone string) string {
t.Helper()
dstPath := t.TempDir()
cloneURL, _ := url.Parse(clone)
cloneURL.User = url.UserPassword("user2", userPassword)
require.NoError(t, git.CloneWithArgs(t.Context(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{}))
return dstPath
}
firstCommit := func(t *testing.T, dstPath string) {
t.Helper()
require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## test content"), 0o600))
require.NoError(t, git.AddChanges(dstPath, true))
require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
Committer: &git.Signature{
Email: "user2@example.com",
Name: "user2",
When: time.Now(),
},
Author: &git.Signature{
Email: "user2@example.com",
Name: "user2",
When: time.Now(),
},
Message: "Add README.",
}))
}
dstPath := clone(t, fmt.Sprintf("%suser2/%s.git", u.String(), repo.Name))
// Create first commit.
firstCommit(t, dstPath)
// Create agit PR.
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Index: 1, BaseRepoID: repo.ID})
assert.Equal(t, issues_model.PullRequestFlowAGit, pr.Flow)
resp := session.MakeRequest(t, NewRequest(t, "GET", fmt.Sprintf("/%s/pulls/%d/files", repo.FullName(), pr.Index)), http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
// There is no edit button on any changed file
doc.AssertElement(t, "h4.diff-file-header a.button[href^=\"/"+repo.FullName()+"/_edit\"]", false)
})
}