|
| 1 | +// Copyright 2025 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/url" |
| 10 | + "strings" |
| 11 | + "testing" |
| 12 | + "time" |
| 13 | + |
| 14 | + auth_model "code.gitea.io/gitea/models/auth" |
| 15 | + repo_model "code.gitea.io/gitea/models/repo" |
| 16 | + "code.gitea.io/gitea/models/unittest" |
| 17 | + user_model "code.gitea.io/gitea/models/user" |
| 18 | + api "code.gitea.io/gitea/modules/structs" |
| 19 | + "code.gitea.io/gitea/modules/util" |
| 20 | + |
| 21 | + "github.com/stretchr/testify/require" |
| 22 | +) |
| 23 | + |
| 24 | +func TestRepoSyncFork(t *testing.T) { |
| 25 | + onGiteaRun(t, func(*testing.T, *url.URL) { |
| 26 | + forkUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) |
| 27 | + |
| 28 | + baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) |
| 29 | + baseUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: baseRepo.OwnerID}) |
| 30 | + repoString := baseUser.Name + "/" + baseRepo.Name |
| 31 | + |
| 32 | + session := loginUser(t, forkUser.Name) |
| 33 | + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) |
| 34 | + |
| 35 | + checkSyncForkMessage := func(hasMessage bool, message string) { |
| 36 | + require.Eventually(t, func() bool { |
| 37 | + resp := session.MakeRequest(t, NewRequestf(t, "GET", "/%s/test-repo-fork", forkUser.Name), http.StatusOK) |
| 38 | + htmlDoc := NewHTMLParser(t, resp.Body) |
| 39 | + respMsg, _ := htmlDoc.Find(".ui.message").Html() |
| 40 | + return strings.Contains(respMsg, message) != hasMessage |
| 41 | + }, 5*time.Second, 100*time.Millisecond) |
| 42 | + } |
| 43 | + |
| 44 | + // create a fork |
| 45 | + req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/forks", repoString), &api.CreateForkOption{ |
| 46 | + Name: util.ToPointer("test-repo-fork"), |
| 47 | + }).AddTokenAuth(token) |
| 48 | + MakeRequest(t, req, http.StatusAccepted) |
| 49 | + forkRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: forkUser.ID, Name: "test-repo-fork"}) |
| 50 | + |
| 51 | + // Case 0: Update fork, should have no sync fork message |
| 52 | + require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "file0.txt", "master", "dummy")) |
| 53 | + // the repo shows a prompt to "sync fork" and with precise commit count |
| 54 | + checkSyncForkMessage(false, fmt.Sprintf(`<a href="/%v/src/branch/master">%v:master</a>`, repoString, repoString)) |
| 55 | + |
| 56 | + // Case 2: Base is ahead of fork |
| 57 | + require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "file1.txt", "master", "dummy")) |
| 58 | + // the repo shows a prompt to "sync fork" and with precise commit count |
| 59 | + checkSyncForkMessage(true, fmt.Sprintf(`This branch is 1 commit behind <a href="/%v/src/branch/master">%v:master</a>`, repoString, repoString)) |
| 60 | + |
| 61 | + // Case 3: Base has some commits that fork does not have, but fork updated |
| 62 | + require.NoError(t, createOrReplaceFileInBranch(forkUser, forkRepo, "file2.txt", "master", "dummy")) |
| 63 | + // the repo shows a prompt to "sync fork" and with just "new changes" text |
| 64 | + checkSyncForkMessage(true, fmt.Sprintf(`The base branch <a href="/%v/src/branch/master">%v:master</a> has new changes`, repoString, repoString)) |
| 65 | + |
| 66 | + // Case 4: Base updates again |
| 67 | + require.NoError(t, createOrReplaceFileInBranch(forkUser, forkRepo, "file3.txt", "master", "dummy")) |
| 68 | + // the repo shows a prompt to "sync fork" and with just "new changes" text |
| 69 | + checkSyncForkMessage(true, fmt.Sprintf(`The base branch <a href="/%v/src/branch/master">%v:master</a> has new changes`, repoString, repoString)) |
| 70 | + }) |
| 71 | +} |
0 commit comments