Merge pull request 'chore: improve test quality' (#5904) from gusted/forgejo-improve-test into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5904
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
This commit is contained in:
Earl Warren 2024-11-10 20:35:50 +00:00
commit 8f6dfe29da
18 changed files with 620 additions and 784 deletions

View file

@ -14,6 +14,7 @@ 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/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/services/actions" "code.gitea.io/gitea/services/actions"
"code.gitea.io/gitea/services/automerge" "code.gitea.io/gitea/services/automerge"
@ -23,7 +24,7 @@ import (
func TestActionsAutomerge(t *testing.T) { func TestActionsAutomerge(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
assert.True(t, setting.Actions.Enabled, "Actions should be enabled") defer test.MockVariableValue(&setting.Actions.Enabled, true)()
ctx := db.DefaultContext ctx := db.DefaultContext

View file

@ -5,7 +5,6 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"strings" "strings"
"testing" "testing"
@ -19,57 +18,55 @@ import (
) )
func TestAPIAdminOrgCreate(t *testing.T) { func TestAPIAdminOrgCreate(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1") session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
org := api.CreateOrgOption{ org := api.CreateOrgOption{
UserName: "user2_org", UserName: "user2_org",
FullName: "User2's organization", FullName: "User2's organization",
Description: "This organization created by admin for user2", Description: "This organization created by admin for user2",
Website: "https://try.gitea.io", Website: "https://try.gitea.io",
Location: "Shanghai", Location: "Shanghai",
Visibility: "private", Visibility: "private",
} }
req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org). req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org).
AddTokenAuth(token) AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusCreated) resp := MakeRequest(t, req, http.StatusCreated)
var apiOrg api.Organization var apiOrg api.Organization
DecodeJSON(t, resp, &apiOrg) DecodeJSON(t, resp, &apiOrg)
assert.Equal(t, org.UserName, apiOrg.Name) assert.Equal(t, org.UserName, apiOrg.Name)
assert.Equal(t, org.FullName, apiOrg.FullName) assert.Equal(t, org.FullName, apiOrg.FullName)
assert.Equal(t, org.Description, apiOrg.Description) assert.Equal(t, org.Description, apiOrg.Description)
assert.Equal(t, org.Website, apiOrg.Website) assert.Equal(t, org.Website, apiOrg.Website)
assert.Equal(t, org.Location, apiOrg.Location) assert.Equal(t, org.Location, apiOrg.Location)
assert.Equal(t, org.Visibility, apiOrg.Visibility) assert.Equal(t, org.Visibility, apiOrg.Visibility)
unittest.AssertExistsAndLoadBean(t, &user_model.User{ unittest.AssertExistsAndLoadBean(t, &user_model.User{
Name: org.UserName, Name: org.UserName,
LowerName: strings.ToLower(org.UserName), LowerName: strings.ToLower(org.UserName),
FullName: org.FullName, FullName: org.FullName,
})
}) })
} }
func TestAPIAdminOrgCreateBadVisibility(t *testing.T) { func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1") session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin)
org := api.CreateOrgOption{ org := api.CreateOrgOption{
UserName: "user2_org", UserName: "user2_org",
FullName: "User2's organization", FullName: "User2's organization",
Description: "This organization created by admin for user2", Description: "This organization created by admin for user2",
Website: "https://try.gitea.io", Website: "https://try.gitea.io",
Location: "Shanghai", Location: "Shanghai",
Visibility: "notvalid", Visibility: "notvalid",
} }
req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org). req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org).
AddTokenAuth(token) AddTokenAuth(token)
MakeRequest(t, req, http.StatusUnprocessableEntity) MakeRequest(t, req, http.StatusUnprocessableEntity)
})
} }
func TestAPIAdminOrgCreateNotAdmin(t *testing.T) { func TestAPIAdminOrgCreateNotAdmin(t *testing.T) {

View file

@ -9,14 +9,13 @@ import (
"testing" "testing"
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"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"
) )
func testAPIGetBranch(t *testing.T, branchName string, exists bool) { func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
@ -234,35 +233,17 @@ func TestAPIBranchProtection(t *testing.T) {
} }
func TestAPICreateBranchWithSyncBranches(t *testing.T) { func TestAPICreateBranchWithSyncBranches(t *testing.T) {
defer tests.PrepareTestEnv(t)()
branches, err := db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{
RepoID: 1,
})
require.NoError(t, err)
assert.Len(t, branches, 4)
// make a broke repository with no branch on database
_, err = db.DeleteByBean(db.DefaultContext, git_model.Branch{RepoID: 1})
require.NoError(t, err)
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
unittest.AssertCount(t, &git_model.Branch{RepoID: 1}, 4)
// make a broke repository with no branch on database
unittest.AssertSuccessfulDelete(t, &git_model.Branch{RepoID: 1})
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
giteaURL.Path = ctx.GitPath() giteaURL.Path = ctx.GitPath()
testAPICreateBranch(t, ctx.Session, "user2", "repo1", "", "new_branch", http.StatusCreated) testAPICreateBranch(t, ctx.Session, "user2", "repo1", "", "new_branch", http.StatusCreated)
})
branches, err = db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{ unittest.AssertExistsIf(t, true, &git_model.Branch{RepoID: 1, Name: "new_branch"})
RepoID: 1,
}) })
require.NoError(t, err)
assert.Len(t, branches, 5)
branches, err = db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{
RepoID: 1,
Keyword: "new_branch",
})
require.NoError(t, err)
assert.Len(t, branches, 1)
} }

View file

@ -7,7 +7,6 @@ package integration
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"testing" "testing"
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
@ -86,25 +85,24 @@ func TestCreateForkNoLogin(t *testing.T) {
} }
func TestAPIDisabledForkRepo(t *testing.T) { func TestAPIDisabledForkRepo(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer test.MockVariableValue(&setting.Repository.DisableForks, true)()
defer test.MockVariableValue(&setting.Repository.DisableForks, true)() defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() defer tests.PrepareTestEnv(t)()
t.Run("fork listing", func(t *testing.T) { t.Run("fork listing", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks") req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks")
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
}) })
t.Run("forking", func(t *testing.T) { t.Run("forking", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user5") session := loginUser(t, "user5")
token := getTokenForLoggedInUser(t, session) token := getTokenForLoggedInUser(t, session)
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{}).AddTokenAuth(token) req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{}).AddTokenAuth(token)
session.MakeRequest(t, req, http.StatusNotFound) session.MakeRequest(t, req, http.StatusNotFound)
})
}) })
} }

View file

@ -5,35 +5,31 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"testing" "testing"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestNodeinfo(t *testing.T) { func TestNodeinfo(t *testing.T) {
setting.Federation.Enabled = true defer test.MockVariableValue(&setting.Federation.Enabled, true)()
testWebRoutes = routers.NormalRoutes() defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
defer func() { defer tests.PrepareTestEnv(t)()
setting.Federation.Enabled = false
testWebRoutes = routers.NormalRoutes()
}()
onGiteaRun(t, func(*testing.T, *url.URL) { req := NewRequest(t, "GET", "/api/v1/nodeinfo")
req := NewRequest(t, "GET", "/api/v1/nodeinfo") resp := MakeRequest(t, req, http.StatusOK)
resp := MakeRequest(t, req, http.StatusOK) VerifyJSONSchema(t, resp, "nodeinfo_2.1.json")
VerifyJSONSchema(t, resp, "nodeinfo_2.1.json")
var nodeinfo api.NodeInfo var nodeinfo api.NodeInfo
DecodeJSON(t, resp, &nodeinfo) DecodeJSON(t, resp, &nodeinfo)
assert.True(t, nodeinfo.OpenRegistrations) assert.True(t, nodeinfo.OpenRegistrations)
assert.Equal(t, "forgejo", nodeinfo.Software.Name) assert.Equal(t, "forgejo", nodeinfo.Software.Name)
assert.Equal(t, 29, nodeinfo.Usage.Users.Total) assert.Equal(t, 29, nodeinfo.Usage.Users.Total)
assert.Equal(t, 22, nodeinfo.Usage.LocalPosts) assert.Equal(t, 22, nodeinfo.Usage.LocalPosts)
assert.Equal(t, 4, nodeinfo.Usage.LocalComments) assert.Equal(t, 4, nodeinfo.Usage.LocalComments)
})
} }

View file

@ -6,7 +6,6 @@ package integration
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strings" "strings"
"testing" "testing"
@ -19,150 +18,144 @@ import (
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestAPIOrgCreate(t *testing.T) { func TestAPIOrgCreate(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
org := api.CreateOrgOption{ org := api.CreateOrgOption{
UserName: "user1_org", UserName: "user1_org",
FullName: "User1's organization", FullName: "User1's organization",
Description: "This organization created by user1", Description: "This organization created by user1",
Website: "https://try.gitea.io", Website: "https://try.gitea.io",
Location: "Shanghai", Location: "Shanghai",
Visibility: "limited", Visibility: "limited",
} }
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org). req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org).
AddTokenAuth(token) AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusCreated) resp := MakeRequest(t, req, http.StatusCreated)
var apiOrg api.Organization var apiOrg api.Organization
DecodeJSON(t, resp, &apiOrg) DecodeJSON(t, resp, &apiOrg)
assert.Equal(t, org.UserName, apiOrg.Name) assert.Equal(t, org.UserName, apiOrg.Name)
assert.Equal(t, org.FullName, apiOrg.FullName) assert.Equal(t, org.FullName, apiOrg.FullName)
assert.Equal(t, org.Description, apiOrg.Description) assert.Equal(t, org.Description, apiOrg.Description)
assert.Equal(t, org.Website, apiOrg.Website) assert.Equal(t, org.Website, apiOrg.Website)
assert.Equal(t, org.Location, apiOrg.Location) assert.Equal(t, org.Location, apiOrg.Location)
assert.Equal(t, org.Visibility, apiOrg.Visibility) assert.Equal(t, org.Visibility, apiOrg.Visibility)
unittest.AssertExistsAndLoadBean(t, &user_model.User{ unittest.AssertExistsAndLoadBean(t, &user_model.User{
Name: org.UserName, Name: org.UserName,
LowerName: strings.ToLower(org.UserName), LowerName: strings.ToLower(org.UserName),
FullName: org.FullName, FullName: org.FullName,
})
// Check owner team permission
ownerTeam, _ := org_model.GetOwnerTeam(db.DefaultContext, apiOrg.ID)
for _, ut := range unit_model.AllRepoUnitTypes {
up := perm.AccessModeOwner
if ut == unit_model.TypeExternalTracker || ut == unit_model.TypeExternalWiki {
up = perm.AccessModeRead
}
unittest.AssertExistsAndLoadBean(t, &org_model.TeamUnit{
OrgID: apiOrg.ID,
TeamID: ownerTeam.ID,
Type: ut,
AccessMode: up,
})
}
req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiOrg)
assert.EqualValues(t, org.UserName, apiOrg.Name)
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
var repos []*api.Repository
DecodeJSON(t, resp, &repos)
for _, repo := range repos {
assert.False(t, repo.Private)
}
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
// user1 on this org is public
var users []*api.User
DecodeJSON(t, resp, &users)
assert.Len(t, users, 1)
assert.EqualValues(t, "user1", users[0].UserName)
}) })
// Check owner team permission
ownerTeam, _ := org_model.GetOwnerTeam(db.DefaultContext, apiOrg.ID)
for _, ut := range unit_model.AllRepoUnitTypes {
up := perm.AccessModeOwner
if ut == unit_model.TypeExternalTracker || ut == unit_model.TypeExternalWiki {
up = perm.AccessModeRead
}
unittest.AssertExistsAndLoadBean(t, &org_model.TeamUnit{
OrgID: apiOrg.ID,
TeamID: ownerTeam.ID,
Type: ut,
AccessMode: up,
})
}
req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiOrg)
assert.EqualValues(t, org.UserName, apiOrg.Name)
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
var repos []*api.Repository
DecodeJSON(t, resp, &repos)
for _, repo := range repos {
assert.False(t, repo.Private)
}
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
// user1 on this org is public
var users []*api.User
DecodeJSON(t, resp, &users)
assert.Len(t, users, 1)
assert.EqualValues(t, "user1", users[0].UserName)
} }
func TestAPIOrgEdit(t *testing.T) { func TestAPIOrgEdit(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1") session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
org := api.EditOrgOption{ org := api.EditOrgOption{
FullName: "Org3 organization new full name", FullName: "Org3 organization new full name",
Description: "A new description", Description: "A new description",
Website: "https://try.gitea.io/new", Website: "https://try.gitea.io/new",
Location: "Beijing", Location: "Beijing",
Visibility: "private", Visibility: "private",
} }
req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org). req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).
AddTokenAuth(token) AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)
var apiOrg api.Organization var apiOrg api.Organization
DecodeJSON(t, resp, &apiOrg) DecodeJSON(t, resp, &apiOrg)
assert.Equal(t, "org3", apiOrg.Name) assert.Equal(t, "org3", apiOrg.Name)
assert.Equal(t, org.FullName, apiOrg.FullName) assert.Equal(t, org.FullName, apiOrg.FullName)
assert.Equal(t, org.Description, apiOrg.Description) assert.Equal(t, org.Description, apiOrg.Description)
assert.Equal(t, org.Website, apiOrg.Website) assert.Equal(t, org.Website, apiOrg.Website)
assert.Equal(t, org.Location, apiOrg.Location) assert.Equal(t, org.Location, apiOrg.Location)
assert.Equal(t, org.Visibility, apiOrg.Visibility) assert.Equal(t, org.Visibility, apiOrg.Visibility)
})
} }
func TestAPIOrgEditBadVisibility(t *testing.T) { func TestAPIOrgEditBadVisibility(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1") session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
org := api.EditOrgOption{ org := api.EditOrgOption{
FullName: "Org3 organization new full name", FullName: "Org3 organization new full name",
Description: "A new description", Description: "A new description",
Website: "https://try.gitea.io/new", Website: "https://try.gitea.io/new",
Location: "Beijing", Location: "Beijing",
Visibility: "badvisibility", Visibility: "badvisibility",
} }
req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org). req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).
AddTokenAuth(token) AddTokenAuth(token)
MakeRequest(t, req, http.StatusUnprocessableEntity) MakeRequest(t, req, http.StatusUnprocessableEntity)
})
} }
func TestAPIOrgDeny(t *testing.T) { func TestAPIOrgDeny(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
setting.Service.RequireSignInView = true defer test.MockVariableValue(&setting.Service.RequireSignInView, true)()
defer func() {
setting.Service.RequireSignInView = false
}()
orgName := "user1_org" orgName := "user1_org"
req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName) req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", orgName) req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", orgName)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName) req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
})
} }
func TestAPIGetAll(t *testing.T) { func TestAPIGetAll(t *testing.T) {
@ -192,37 +185,36 @@ func TestAPIGetAll(t *testing.T) {
} }
func TestAPIOrgSearchEmptyTeam(t *testing.T) { func TestAPIOrgSearchEmptyTeam(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) { defer tests.PrepareTestEnv(t)()
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
orgName := "org_with_empty_team" orgName := "org_with_empty_team"
// create org // create org
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{ req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{
UserName: orgName, UserName: orgName,
}).AddTokenAuth(token) }).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated) MakeRequest(t, req, http.StatusCreated)
// create team with no member // create team with no member
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams", orgName), &api.CreateTeamOption{ req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams", orgName), &api.CreateTeamOption{
Name: "Empty", Name: "Empty",
IncludesAllRepositories: true, IncludesAllRepositories: true,
Permission: "read", Permission: "read",
Units: []string{"repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", "repo.pulls"}, Units: []string{"repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", "repo.pulls"},
}).AddTokenAuth(token) }).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated) MakeRequest(t, req, http.StatusCreated)
// case-insensitive search for teams that have no members // case-insensitive search for teams that have no members
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/teams/search?q=%s", orgName, "empty")). req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/teams/search?q=%s", orgName, "empty")).
AddTokenAuth(token) AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)
data := struct { data := struct {
Ok bool Ok bool
Data []*api.Team Data []*api.Team
}{} }{}
DecodeJSON(t, resp, &data) DecodeJSON(t, resp, &data)
assert.True(t, data.Ok) assert.True(t, data.Ok)
if assert.Len(t, data.Data, 1) { if assert.Len(t, data.Data, 1) {
assert.EqualValues(t, "Empty", data.Data[0].Name) assert.EqualValues(t, "Empty", data.Data[0].Name)
} }
})
} }

View file

@ -2,60 +2,59 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"path" "path"
"strings" "strings"
"testing" "testing"
"code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestRepoLastUpdatedTime(t *testing.T) { func TestRepoLastUpdatedTime(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrepareTestEnv(t)()
user := "user2" user := "user2"
session := loginUser(t, user) session := loginUser(t, user)
req := NewRequest(t, "GET", "/explore/repos?q=repo1") req := NewRequest(t, "GET", "/explore/repos?q=repo1")
resp := session.MakeRequest(t, req, http.StatusOK) resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body) doc := NewHTMLParser(t, resp.Body)
node := doc.doc.Find(".flex-item-body").First() node := doc.doc.Find(".flex-item-body").First()
{ {
buf := "" buf := ""
findTextNonNested(t, node, &buf) findTextNonNested(t, node, &buf)
assert.Equal(t, "Updated", strings.TrimSpace(buf)) assert.Equal(t, "Updated", strings.TrimSpace(buf))
} }
// Relative time should be present as a descendent // Relative time should be present as a descendent
{ {
relativeTime := node.Find("relative-time").Text() relativeTime := node.Find("relative-time").Text()
assert.True(t, strings.HasPrefix(relativeTime, "19")) // ~1970, might underflow with timezone assert.True(t, strings.HasPrefix(relativeTime, "19")) // ~1970, might underflow with timezone
} }
})
} }
func TestBranchLastUpdatedTime(t *testing.T) { func TestBranchLastUpdatedTime(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrepareTestEnv(t)()
user := "user2" user := "user2"
repo := "repo1" repo := "repo1"
session := loginUser(t, user) session := loginUser(t, user)
req := NewRequest(t, "GET", path.Join(user, repo, "branches")) req := NewRequest(t, "GET", path.Join(user, repo, "branches"))
resp := session.MakeRequest(t, req, http.StatusOK) resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body) doc := NewHTMLParser(t, resp.Body)
node := doc.doc.Find("p:has(span.commit-message)") node := doc.doc.Find("p:has(span.commit-message)")
{ {
buf := "" buf := ""
findTextNonNested(t, node, &buf) findTextNonNested(t, node, &buf)
assert.True(t, strings.Contains(buf, "Updated")) assert.True(t, strings.Contains(buf, "Updated"))
} }
{ {
relativeTime := node.Find("relative-time").Text() relativeTime := node.Find("relative-time").Text()
assert.True(t, strings.HasPrefix(relativeTime, "2017")) assert.True(t, strings.HasPrefix(relativeTime, "2017"))
} }
})
} }
// Find all text that are direct descendents // Find all text that are direct descendents

View file

@ -5,30 +5,29 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"testing" "testing"
pull_service "code.gitea.io/gitea/services/pull" pull_service "code.gitea.io/gitea/services/pull"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestListPullCommits(t *testing.T) { func TestListPullCommits(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user5") session := loginUser(t, "user5")
req := NewRequest(t, "GET", "/user2/repo1/pulls/3/commits/list") req := NewRequest(t, "GET", "/user2/repo1/pulls/3/commits/list")
resp := session.MakeRequest(t, req, http.StatusOK) resp := session.MakeRequest(t, req, http.StatusOK)
var pullCommitList struct { var pullCommitList struct {
Commits []pull_service.CommitInfo `json:"commits"` Commits []pull_service.CommitInfo `json:"commits"`
LastReviewCommitSha string `json:"last_review_commit_sha"` LastReviewCommitSha string `json:"last_review_commit_sha"`
} }
DecodeJSON(t, resp, &pullCommitList) DecodeJSON(t, resp, &pullCommitList)
if assert.Len(t, pullCommitList.Commits, 2) { if assert.Len(t, pullCommitList.Commits, 2) {
assert.Equal(t, "5f22f7d0d95d614d25a5b68592adb345a4b5c7fd", pullCommitList.Commits[0].ID) assert.Equal(t, "5f22f7d0d95d614d25a5b68592adb345a4b5c7fd", pullCommitList.Commits[0].ID)
assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.Commits[1].ID) assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.Commits[1].ID)
} }
assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.LastReviewCommitSha) assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.LastReviewCommitSha)
})
} }

View file

@ -18,7 +18,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"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/gitrepo" "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
issue_service "code.gitea.io/gitea/services/issue" issue_service "code.gitea.io/gitea/services/issue"
@ -283,32 +282,18 @@ func TestPullView_CodeOwner(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
// Create the repo. repo, _, f := tests.CreateDeclarativeRepo(t, user2, "test_codeowner", nil, nil, []*files_service.ChangeRepoFile{
repo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{ {
Name: "test_codeowner", Operation: "create",
Readme: "Default", TreePath: "CODEOWNERS",
AutoInit: true, ContentReader: strings.NewReader("README.md @user5\n"),
ObjectFormatName: git.Sha1ObjectFormat.Name(),
DefaultBranch: "master",
})
require.NoError(t, err)
// add CODEOWNERS to default branch
_, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
OldBranch: repo.DefaultBranch,
Files: []*files_service.ChangeRepoFile{
{
Operation: "create",
TreePath: "CODEOWNERS",
ContentReader: strings.NewReader("README.md @user5\n"),
},
}, },
}) })
require.NoError(t, err) defer f()
t.Run("First Pull Request", func(t *testing.T) { t.Run("First Pull Request", func(t *testing.T) {
// create a new branch to prepare for pull request // create a new branch to prepare for pull request
_, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ _, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
NewBranch: "codeowner-basebranch", NewBranch: "codeowner-basebranch",
Files: []*files_service.ChangeRepoFile{ Files: []*files_service.ChangeRepoFile{
{ {
@ -328,7 +313,7 @@ func TestPullView_CodeOwner(t *testing.T) {
unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5}) unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5})
require.NoError(t, pr.LoadIssue(db.DefaultContext)) require.NoError(t, pr.LoadIssue(db.DefaultContext))
err := issue_service.ChangeTitle(db.DefaultContext, pr.Issue, user2, "[WIP] Test Pull Request") err = issue_service.ChangeTitle(db.DefaultContext, pr.Issue, user2, "[WIP] Test Pull Request")
require.NoError(t, err) require.NoError(t, err)
prUpdated1 := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID}) prUpdated1 := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
require.NoError(t, prUpdated1.LoadIssue(db.DefaultContext)) require.NoError(t, prUpdated1.LoadIssue(db.DefaultContext))
@ -342,7 +327,7 @@ func TestPullView_CodeOwner(t *testing.T) {
}) })
// change the default branch CODEOWNERS file to change README.md's codeowner // change the default branch CODEOWNERS file to change README.md's codeowner
_, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ _, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{ Files: []*files_service.ChangeRepoFile{
{ {
Operation: "update", Operation: "update",

View file

@ -22,8 +22,6 @@ func TestRenameBranch(t *testing.T) {
} }
func testRenameBranch(t *testing.T, u *url.URL) { func testRenameBranch(t *testing.T, u *url.URL) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "master"}) unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "master"})

View file

@ -5,33 +5,33 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"strings" "strings"
"testing" "testing"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
// TestRepoCollaborators is a test for contents of Collaborators tab in the repo settings // TestRepoCollaborators is a test for contents of Collaborators tab in the repo settings
// It only covers a few elements and can be extended as needed // It only covers a few elements and can be extended as needed
func TestRepoCollaborators(t *testing.T) { func TestRepoCollaborators(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2") session := loginUser(t, "user2")
// Visit Collaborators tab of repo settings // Visit Collaborators tab of repo settings
response := session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/settings/collaboration"), http.StatusOK) response := session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/settings/collaboration"), http.StatusOK)
page := NewHTMLParser(t, response.Body).Find(".repo-setting-content") page := NewHTMLParser(t, response.Body).Find(".repo-setting-content")
// Veirfy header // Veirfy header
assert.EqualValues(t, "Collaborators", strings.TrimSpace(page.Find("h4").Text())) assert.EqualValues(t, "Collaborators", strings.TrimSpace(page.Find("h4").Text()))
// Veirfy button text // Veirfy button text
page = page.Find("#repo-collab-form") page = page.Find("#repo-collab-form")
assert.EqualValues(t, "Add collaborator", strings.TrimSpace(page.Find("button.primary").Text())) assert.EqualValues(t, "Add collaborator", strings.TrimSpace(page.Find("button.primary").Text()))
// Veirfy placeholder // Veirfy placeholder
placeholder, exists := page.Find("#search-user-box input").Attr("placeholder") placeholder, exists := page.Find("#search-user-box input").Attr("placeholder")
assert.True(t, exists) assert.True(t, exists)
assert.EqualValues(t, "Search users...", placeholder) assert.EqualValues(t, "Search users...", placeholder)
})
} }

View file

@ -5,26 +5,26 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"testing" "testing"
"code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestRepoMigrationUI(t *testing.T) { func TestRepoMigrationUI(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { defer tests.PrepareTestEnv(t)()
sessionUser1 := loginUser(t, "user1") sessionUser1 := loginUser(t, "user1")
// Nothing is tested in plain Git migration form right now // Nothing is tested in plain Git migration form right now
testRepoMigrationFormGitHub(t, sessionUser1) testRepoMigrationFormGitHub(t, sessionUser1)
testRepoMigrationFormGitea(t, sessionUser1) testRepoMigrationFormGitea(t, sessionUser1)
testRepoMigrationFormGitLab(t, sessionUser1) testRepoMigrationFormGitLab(t, sessionUser1)
testRepoMigrationFormGogs(t, sessionUser1) testRepoMigrationFormGogs(t, sessionUser1)
testRepoMigrationFormOneDev(t, sessionUser1) testRepoMigrationFormOneDev(t, sessionUser1)
testRepoMigrationFormGitBucket(t, sessionUser1) testRepoMigrationFormGitBucket(t, sessionUser1)
testRepoMigrationFormCodebase(t, sessionUser1) testRepoMigrationFormCodebase(t, sessionUser1)
testRepoMigrationFormForgejo(t, sessionUser1) testRepoMigrationFormForgejo(t, sessionUser1)
})
} }
func testRepoMigrationFormGitHub(t *testing.T, session *TestSession) { func testRepoMigrationFormGitHub(t *testing.T, session *TestSession) {

View file

@ -11,8 +11,6 @@ import (
"testing" "testing"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"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"
@ -31,20 +29,6 @@ func TestTagViewWithoutRelease(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
defer func() {
releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{
IncludeTags: true,
TagNames: []string{"no-release"},
RepoID: repo.ID,
})
require.NoError(t, err)
for _, release := range releases {
_, err = db.DeleteByID[repo_model.Release](db.DefaultContext, release.ID)
require.NoError(t, err)
}
}()
err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "no-release", "release-less tag") err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "no-release", "release-less tag")
require.NoError(t, err) require.NoError(t, err)
@ -70,27 +54,27 @@ func TestTagViewWithoutRelease(t *testing.T) {
} }
func TestCreateNewTagProtected(t *testing.T) { func TestCreateNewTagProtected(t *testing.T) {
defer tests.PrepareTestEnv(t)() onGiteaRun(t, func(t *testing.T, u *url.URL) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) t.Run("Code", func(t *testing.T) {
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) defer tests.PrintCurrentTest(t)()
t.Run("Code", func(t *testing.T) { err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "t-first", "first tag")
defer tests.PrintCurrentTest(t)() require.NoError(t, err)
err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "t-first", "first tag") err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag")
require.NoError(t, err) require.Error(t, err)
assert.True(t, models.IsErrProtectedTagName(err))
err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag") err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1.1", "third tag")
require.Error(t, err) require.NoError(t, err)
assert.True(t, models.IsErrProtectedTagName(err)) })
err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1.1", "third tag") t.Run("Git", func(t *testing.T) {
require.NoError(t, err) defer tests.PrintCurrentTest(t)()
})
t.Run("Git", func(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
httpContext := NewAPITestContext(t, owner.Name, repo.Name) httpContext := NewAPITestContext(t, owner.Name, repo.Name)
dstPath := t.TempDir() dstPath := t.TempDir()
@ -107,10 +91,10 @@ func TestCreateNewTagProtected(t *testing.T) {
require.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), "Tag v-2 is protected") assert.Contains(t, err.Error(), "Tag v-2 is protected")
}) })
})
t.Run("GitTagForce", func(t *testing.T) { t.Run("GitTagForce", func(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrintCurrentTest(t)()
httpContext := NewAPITestContext(t, owner.Name, repo.Name) httpContext := NewAPITestContext(t, owner.Name, repo.Name)
dstPath := t.TempDir() dstPath := t.TempDir()
@ -120,13 +104,7 @@ func TestCreateNewTagProtected(t *testing.T) {
doGitClone(dstPath, u)(t) doGitClone(dstPath, u)(t)
_, _, err := git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update", "--force").RunStdString(&git.RunOpts{Dir: dstPath}) _, _, err := git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(&git.RunOpts{Dir: dstPath})
require.NoError(t, err)
_, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath})
require.NoError(t, err)
_, _, err = git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(&git.RunOpts{Dir: dstPath})
require.NoError(t, err) require.NoError(t, err)
_, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath}) _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath})
@ -142,27 +120,6 @@ func TestCreateNewTagProtected(t *testing.T) {
assert.Contains(t, tagsTab.Text(), "force update v2") assert.Contains(t, tagsTab.Text(), "force update v2")
}) })
}) })
// Cleanup
releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{
IncludeTags: true,
TagNames: []string{"v-1", "v-1.1"},
RepoID: repo.ID,
})
require.NoError(t, err)
for _, release := range releases {
_, err = db.DeleteByID[repo_model.Release](db.DefaultContext, release.ID)
require.NoError(t, err)
}
protectedTags, err := git_model.GetProtectedTags(db.DefaultContext, repo.ID)
require.NoError(t, err)
for _, protectedTag := range protectedTags {
err = git_model.DeleteProtectedTag(db.DefaultContext, protectedTag)
require.NoError(t, err)
}
} }
func TestSyncRepoTags(t *testing.T) { func TestSyncRepoTags(t *testing.T) {
@ -200,18 +157,5 @@ func TestSyncRepoTags(t *testing.T) {
require.NoError(t, repo_module.SyncRepoTags(git.DefaultContext, repo.ID)) require.NoError(t, repo_module.SyncRepoTags(git.DefaultContext, repo.ID))
testTag(t) testTag(t)
}) })
// Cleanup
releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{
IncludeTags: true,
TagNames: []string{"v2"},
RepoID: repo.ID,
})
require.NoError(t, err)
for _, release := range releases {
_, err = db.DeleteByID[repo_model.Release](db.DefaultContext, release.ID)
require.NoError(t, err)
}
}) })
} }

View file

@ -62,8 +62,9 @@ func createRepoAndGetContext(t *testing.T, files []string, deleteMdReadme bool)
} }
func TestRepoView_FindReadme(t *testing.T) { func TestRepoView_FindReadme(t *testing.T) {
t.Run("PrioOneLocalizedMdReadme", func(t *testing.T) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { t.Run("PrioOneLocalizedMdReadme", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
ctx, f := createRepoAndGetContext(t, []string{"README.en.md", "README.en.org", "README.org", "README.txt", "README.tex"}, false) ctx, f := createRepoAndGetContext(t, []string{"README.en.md", "README.en.org", "README.org", "README.txt", "README.tex"}, false)
defer f() defer f()
@ -73,9 +74,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README.en.md", file.Name()) assert.Equal(t, "README.en.md", file.Name())
}) })
}) t.Run("PrioTwoMdReadme", func(t *testing.T) {
t.Run("PrioTwoMdReadme", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{"README.en.org", "README.org", "README.txt", "README.tex"}, false) ctx, f := createRepoAndGetContext(t, []string{"README.en.org", "README.org", "README.txt", "README.tex"}, false)
defer f() defer f()
@ -85,9 +85,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README.md", file.Name()) assert.Equal(t, "README.md", file.Name())
}) })
}) t.Run("PrioThreeLocalizedOrgReadme", func(t *testing.T) {
t.Run("PrioThreeLocalizedOrgReadme", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{"README.en.org", "README.org", "README.txt", "README.tex"}, true) ctx, f := createRepoAndGetContext(t, []string{"README.en.org", "README.org", "README.txt", "README.tex"}, true)
defer f() defer f()
@ -97,9 +96,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README.en.org", file.Name()) assert.Equal(t, "README.en.org", file.Name())
}) })
}) t.Run("PrioFourOrgReadme", func(t *testing.T) {
t.Run("PrioFourOrgReadme", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{"README.org", "README.txt", "README.tex"}, true) ctx, f := createRepoAndGetContext(t, []string{"README.org", "README.txt", "README.tex"}, true)
defer f() defer f()
@ -109,9 +107,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README.org", file.Name()) assert.Equal(t, "README.org", file.Name())
}) })
}) t.Run("PrioFiveTxtReadme", func(t *testing.T) {
t.Run("PrioFiveTxtReadme", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{"README.txt", "README", "README.tex"}, true) ctx, f := createRepoAndGetContext(t, []string{"README.txt", "README", "README.tex"}, true)
defer f() defer f()
@ -121,9 +118,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README.txt", file.Name()) assert.Equal(t, "README.txt", file.Name())
}) })
}) t.Run("PrioSixWithoutExtensionReadme", func(t *testing.T) {
t.Run("PrioSixWithoutExtensionReadme", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{"README", "README.tex"}, true) ctx, f := createRepoAndGetContext(t, []string{"README", "README.tex"}, true)
defer f() defer f()
@ -133,9 +129,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README", file.Name()) assert.Equal(t, "README", file.Name())
}) })
}) t.Run("PrioSevenAnyReadme", func(t *testing.T) {
t.Run("PrioSevenAnyReadme", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{"README.tex"}, true) ctx, f := createRepoAndGetContext(t, []string{"README.tex"}, true)
defer f() defer f()
@ -145,9 +140,8 @@ func TestRepoView_FindReadme(t *testing.T) {
assert.Equal(t, "README.tex", file.Name()) assert.Equal(t, "README.tex", file.Name())
}) })
}) t.Run("DoNotPickReadmeIfNonPresent", func(t *testing.T) {
t.Run("DoNotPickReadmeIfNonPresent", func(t *testing.T) { defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
ctx, f := createRepoAndGetContext(t, []string{}, true) ctx, f := createRepoAndGetContext(t, []string{}, true)
defer f() defer f()

View file

@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
"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"
@ -63,8 +64,8 @@ func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.Chang
Files: []*files_service.ChangeRepoFile{ Files: []*files_service.ChangeRepoFile{
{ {
Operation: "delete", Operation: "delete",
TreePath: "README.md", TreePath: "README_new.md",
SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647",
}, },
}, },
LastCommitID: "", LastCommitID: "",
@ -244,184 +245,142 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA
} }
} }
func TestChangeRepoFilesForCreate(t *testing.T) { func TestChangeRepoFiles(t *testing.T) {
// setup
onGiteaRun(t, func(t *testing.T, u *url.URL) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
opts := getCreateRepoFilesOptions(repo)
// test gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
// asserts
require.NoError(t, err) require.NoError(t, err)
gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo)
defer gitRepo.Close() defer gitRepo.Close()
commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) t.Run("Create", func(t *testing.T) {
lastCommit, _ := gitRepo.GetCommitByPath("new/file.txt") defer tests.PrintCurrentTest(t)()
expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String()) opts := getCreateRepoFilesOptions(repo)
assert.NotNil(t, expectedFileResponse) filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
if expectedFileResponse != nil { require.NoError(t, err)
commitID, err := gitRepo.GetBranchCommitID(opts.NewBranch)
require.NoError(t, err)
lastCommit, err := gitRepo.GetCommitByPath("new/file.txt")
require.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String())
assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0])
assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
} })
})
}
func TestChangeRepoFilesForUpdate(t *testing.T) { t.Run("Update", func(t *testing.T) {
// setup defer tests.PrintCurrentTest(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) { opts := getUpdateRepoFilesOptions(repo)
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) require.NoError(t, err)
opts := getUpdateRepoFilesOptions(repo)
// test commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) require.NoError(t, err)
lastCommit, err := commit.GetCommitByPath(opts.Files[0].TreePath)
require.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0])
assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
})
// asserts t.Run("Update and move", func(t *testing.T) {
require.NoError(t, err) defer tests.PrintCurrentTest(t)()
gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) opts := getUpdateRepoFilesOptions(repo)
defer gitRepo.Close() opts.Files[0].SHA = "dbf8d00e022e05b7e5cf7e535de857de57925647"
opts.Files[0].FromTreePath = "README.md"
opts.Files[0].TreePath = "README_new.md" // new file name, README_new.md
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
require.NoError(t, err)
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) require.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) lastCommit, err := commit.GetCommitByPath(opts.Files[0].TreePath)
assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) require.NoError(t, err)
assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name)
})
}
func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { // assert that the old file no longer exists in the last commit of the branch
// setup fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath)
onGiteaRun(t, func(t *testing.T, u *url.URL) { switch err.(type) {
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) case git.ErrNotExist:
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // correct, continue
opts := getUpdateRepoFilesOptions(repo) default:
opts.Files[0].FromTreePath = "README.md" t.Fatalf("expected git.ErrNotExist, got:%v", err)
opts.Files[0].TreePath = "README_new.md" // new file name, README_new.md }
toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath)
require.NoError(t, err)
assert.Nil(t, fromEntry) // Should no longer exist here
assert.NotNil(t, toEntry) // Should exist here
// assert SHA has remained the same but paths use the new file name
assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA)
assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name)
assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path)
assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL)
assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
})
// test t.Run("Change without branch names", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) defer tests.PrintCurrentTest(t)()
opts := getUpdateRepoFilesOptions(repo)
opts.OldBranch = ""
opts.NewBranch = ""
opts.Files[0].TreePath = "README_new.md"
opts.Files[0].SHA = "dbf8d00e022e05b7e5cf7e535de857de57925647"
// asserts filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
require.NoError(t, err) require.NoError(t, err)
gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo)
defer gitRepo.Close()
commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch)
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath)
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String())
// assert that the old file no longer exists in the last commit of the branch assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0])
fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath) })
switch err.(type) {
case git.ErrNotExist:
// correct, continue
default:
t.Fatalf("expected git.ErrNotExist, got:%v", err)
}
toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath)
require.NoError(t, err)
assert.Nil(t, fromEntry) // Should no longer exist here
assert.NotNil(t, toEntry) // Should exist here
// assert SHA has remained the same but paths use the new file name
assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA)
assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name)
assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path)
assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL)
assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA)
assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL)
})
}
// Test opts with branch names removed, should get same results as above test t.Run("Delete files", func(t *testing.T) {
func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { defer tests.PrintCurrentTest(t)()
// setup opts := getDeleteRepoFilesOptions(repo)
onGiteaRun(t, func(t *testing.T, u *url.URL) {
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
opts := getUpdateRepoFilesOptions(repo)
opts.OldBranch = ""
opts.NewBranch = ""
// test filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) require.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification)
// asserts filesResponse, err = files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
require.NoError(t, err) assert.Nil(t, filesResponse)
gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) expectedError := "repository file does not exist [path: " + opts.Files[0].TreePath + "]"
defer gitRepo.Close() assert.EqualError(t, err, expectedError)
})
commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) t.Run("Delete without branch name", func(t *testing.T) {
lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) defer tests.PrintCurrentTest(t)()
expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) opts := getDeleteRepoFilesOptions(repo)
assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) opts.OldBranch = ""
}) opts.NewBranch = ""
} opts.Files[0].SHA = "103ff9234cefeee5ec5361d22b49fbb04d385885"
opts.Files[0].TreePath = "new/file.txt"
func TestChangeRepoFilesForDelete(t *testing.T) { filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
onGiteaRun(t, testDeleteRepoFiles) require.NoError(t, err)
} expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
assert.NotNil(t, filesResponse)
func testDeleteRepoFiles(t *testing.T, u *url.URL) { assert.Nil(t, filesResponse.Files[0])
// setup assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
unittest.PrepareTestEnv(t) assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification)
opts := getDeleteRepoFilesOptions(repo) })
t.Run("Delete README.md file", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
require.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification)
})
t.Run("Verify README.md has been deleted", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
assert.Nil(t, filesResponse)
expectedError := "repository file does not exist [path: " + opts.Files[0].TreePath + "]"
assert.EqualError(t, err, expectedError)
})
}
// Test opts with branch names removed, same results
func TestChangeRepoFilesForDeleteWithoutBranchNames(t *testing.T) {
onGiteaRun(t, testDeleteRepoFilesWithoutBranchNames)
}
func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) {
// setup
unittest.PrepareTestEnv(t)
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
opts := getDeleteRepoFilesOptions(repo)
opts.OldBranch = ""
opts.NewBranch = ""
t.Run("Delete README.md without Branch Name", func(t *testing.T) {
filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts)
require.NoError(t, err)
expectedFileResponse := getExpectedFileResponseForRepofilesDelete()
assert.NotNil(t, filesResponse)
assert.Nil(t, filesResponse.Files[0])
assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message)
assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity)
assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity)
assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification)
}) })
} }

View file

@ -10,85 +10,78 @@ import (
"io" "io"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/url"
"testing" "testing"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"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/avatar" "code.gitea.io/gitea/modules/avatar"
"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 TestUserAvatar(t *testing.T) { func TestUserAvatar(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrepareTestEnv(t)()
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org
seed := user2.Email seed := user2.Email
if len(seed) == 0 { if len(seed) == 0 {
seed = user2.Name seed = user2.Name
} }
img, err := avatar.RandomImage([]byte(seed)) img, err := avatar.RandomImage([]byte(seed))
if err != nil { if err != nil {
require.NoError(t, err) require.NoError(t, err)
return return
} }
session := loginUser(t, "user2") session := loginUser(t, "user2")
csrf := GetCSRF(t, session, "/user/settings") csrf := GetCSRF(t, session, "/user/settings")
imgData := &bytes.Buffer{} imgData := &bytes.Buffer{}
body := &bytes.Buffer{} body := &bytes.Buffer{}
// Setup multi-part // Setup multi-part
writer := multipart.NewWriter(body) writer := multipart.NewWriter(body)
writer.WriteField("source", "local") writer.WriteField("source", "local")
part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png") part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png")
if err != nil { if err != nil {
require.NoError(t, err) require.NoError(t, err)
return return
} }
if err := png.Encode(imgData, img); err != nil { if err := png.Encode(imgData, img); err != nil {
require.NoError(t, err) require.NoError(t, err)
return return
} }
if _, err := io.Copy(part, imgData); err != nil { if _, err := io.Copy(part, imgData); err != nil {
require.NoError(t, err) require.NoError(t, err)
return return
} }
if err := writer.Close(); err != nil { if err := writer.Close(); err != nil {
require.NoError(t, err) require.NoError(t, err)
return return
} }
req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body) req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body)
req.Header.Add("X-Csrf-Token", csrf) req.Header.Add("X-Csrf-Token", csrf)
req.Header.Add("Content-Type", writer.FormDataContentType()) req.Header.Add("Content-Type", writer.FormDataContentType())
session.MakeRequest(t, req, http.StatusSeeOther) session.MakeRequest(t, req, http.StatusSeeOther)
user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org
req = NewRequest(t, "GET", user2.AvatarLinkWithSize(db.DefaultContext, 0)) req = NewRequest(t, "GET", user2.AvatarLinkWithSize(db.DefaultContext, 0))
_ = session.MakeRequest(t, req, http.StatusOK) _ = session.MakeRequest(t, req, http.StatusOK)
testGetAvatarRedirect(t, user2) req = NewRequestf(t, "GET", "/%s.png", user2.Name)
resp := MakeRequest(t, req, http.StatusSeeOther)
assert.EqualValues(t, fmt.Sprintf("/avatars/%s", user2.Avatar), resp.Header().Get("location"))
// Can't test if the response matches because the image is re-generated on upload but checking that this at least doesn't give a 404 should be enough. // Can't test if the response matches because the image is re-generated on upload but checking that this at least doesn't give a 404 should be enough.
})
}
func testGetAvatarRedirect(t *testing.T, user *user_model.User) {
t.Run(fmt.Sprintf("getAvatarRedirect_%s", user.Name), func(t *testing.T) {
req := NewRequestf(t, "GET", "/%s.png", user.Name)
resp := MakeRequest(t, req, http.StatusSeeOther)
assert.EqualValues(t, fmt.Sprintf("/avatars/%s", user.Avatar), resp.Header().Get("location"))
})
} }

View file

@ -5,11 +5,11 @@ package integration
import ( import (
"net/http" "net/http"
"net/url"
"strconv" "strconv"
"testing" "testing"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -23,70 +23,69 @@ import (
// - Profile visibility // - Profile visibility
// - Public activity visibility // - Public activity visibility
func TestUserProfileActivity(t *testing.T) { func TestUserProfileActivity(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { defer tests.PrepareTestEnv(t)()
// This test needs multiple users with different access statuses to check for all possible states // This test needs multiple users with different access statuses to check for all possible states
userAdmin := loginUser(t, "user1") userAdmin := loginUser(t, "user1")
userRegular := loginUser(t, "user2") userRegular := loginUser(t, "user2")
// Activity availability should be the same for guest and another non-admin user, so this is not tested separately // Activity availability should be the same for guest and another non-admin user, so this is not tested separately
userGuest := emptyTestSession(t) userGuest := emptyTestSession(t)
// = Public profile, public activity = // = Public profile, public activity =
// Set activity visibility of user2 to public. This is the default, but won't hurt to set it before testing. // Set activity visibility of user2 to public. This is the default, but won't hurt to set it before testing.
testChangeUserActivityVisibility(t, userRegular, "off") testChangeUserActivityVisibility(t, userRegular, "off")
// Verify availability of RSS button and activity tab // Verify availability of RSS button and activity tab
testUser2ActivityButtonsAvailability(t, userAdmin, true) testUser2ActivityButtonsAvailability(t, userAdmin, true)
testUser2ActivityButtonsAvailability(t, userRegular, true) testUser2ActivityButtonsAvailability(t, userRegular, true)
testUser2ActivityButtonsAvailability(t, userGuest, true) testUser2ActivityButtonsAvailability(t, userGuest, true)
// Verify the hint for all types of users: admin, self, guest // Verify the hint for all types of users: admin, self, guest
testUser2ActivityVisibility(t, userAdmin, "This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.", true) testUser2ActivityVisibility(t, userAdmin, "This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.", true)
hintLink := testUser2ActivityVisibility(t, userRegular, "Your activity is visible to everyone, except for interactions in private spaces. Configure.", true) hintLink := testUser2ActivityVisibility(t, userRegular, "Your activity is visible to everyone, except for interactions in private spaces. Configure.", true)
testUser2ActivityVisibility(t, userGuest, "", true) testUser2ActivityVisibility(t, userGuest, "", true)
// When viewing own profile, the user is offered to configure activity visibility. Verify that the link is correct and works, also check that it links back to the activity tab. // When viewing own profile, the user is offered to configure activity visibility. Verify that the link is correct and works, also check that it links back to the activity tab.
linkCorrect := assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink) linkCorrect := assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink)
if linkCorrect { if linkCorrect {
page := NewHTMLParser(t, userRegular.MakeRequest(t, NewRequest(t, "GET", hintLink), http.StatusOK).Body) page := NewHTMLParser(t, userRegular.MakeRequest(t, NewRequest(t, "GET", hintLink), http.StatusOK).Body)
activityLink, exists := page.Find(".field:has(.checkbox#keep-activity-private) .help a").Attr("href") activityLink, exists := page.Find(".field:has(.checkbox#keep-activity-private) .help a").Attr("href")
assert.True(t, exists) assert.True(t, exists)
assert.EqualValues(t, "/user2?tab=activity", activityLink) assert.EqualValues(t, "/user2?tab=activity", activityLink)
} }
// = Private profile, but public activity = // = Private profile, but public activity =
// Set profile visibility of user2 to private // Set profile visibility of user2 to private
testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePrivate) testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePrivate)
// When profile activity is configured as public, but the profile is private, tell the user about this and link to visibility settings. // When profile activity is configured as public, but the profile is private, tell the user about this and link to visibility settings.
hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators because your profile is private. Configure.", true) hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators because your profile is private. Configure.", true)
assert.EqualValues(t, "/user/settings#visibility-setting", hintLink) assert.EqualValues(t, "/user/settings#visibility-setting", hintLink)
// When the profile is private, tell the admin about this. // When the profile is private, tell the admin about this.
testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true) testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true)
// Set profile visibility of user2 back to public // Set profile visibility of user2 back to public
testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePublic) testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePublic)
// = Private acitivty = // = Private acitivty =
// Set activity visibility of user2 to private // Set activity visibility of user2 to private
testChangeUserActivityVisibility(t, userRegular, "on") testChangeUserActivityVisibility(t, userRegular, "on")
// Verify availability of RSS button and activity tab // Verify availability of RSS button and activity tab
testUser2ActivityButtonsAvailability(t, userAdmin, true) testUser2ActivityButtonsAvailability(t, userAdmin, true)
testUser2ActivityButtonsAvailability(t, userRegular, true) testUser2ActivityButtonsAvailability(t, userRegular, true)
testUser2ActivityButtonsAvailability(t, userGuest, false) testUser2ActivityButtonsAvailability(t, userGuest, false)
// Verify the hint for all types of users: admin, self, guest // Verify the hint for all types of users: admin, self, guest
testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true) testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true)
hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators. Configure.", true) hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators. Configure.", true)
testUser2ActivityVisibility(t, userGuest, "This user has disabled the public visibility of the activity.", false) testUser2ActivityVisibility(t, userGuest, "This user has disabled the public visibility of the activity.", false)
// Verify that Configure link is correct // Verify that Configure link is correct
assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink) assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink)
})
} }
// testChangeUserActivityVisibility allows to easily change visibility of public activity for a user // testChangeUserActivityVisibility allows to easily change visibility of public activity for a user

View file

@ -6,10 +6,11 @@ package integration
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strings" "strings"
"testing" "testing"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -19,92 +20,92 @@ import (
// - Followers and Following lists have correct amounts of items // - Followers and Following lists have correct amounts of items
// - %d followers and %following counters are always present and always have correct numbers and use correct plurals // - %d followers and %following counters are always present and always have correct numbers and use correct plurals
func TestUserProfileFollows(t *testing.T) { func TestUserProfileFollows(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { defer tests.PrepareTestEnv(t)()
// This test needs 3 users to check for all possible states
// The accounts of user3 and user4 are not functioning
user1 := loginUser(t, "user1")
user2 := loginUser(t, "user2")
user5 := loginUser(t, "user5")
followersLink := "#profile-avatar-card a[href='/user1?tab=followers']" // This test needs 3 users to check for all possible states
followingLink := "#profile-avatar-card a[href='/user1?tab=following']" // The accounts of user3 and user4 are not functioning
listHeader := ".user-cards h2" user1 := loginUser(t, "user1")
listItems := ".user-cards .list" user2 := loginUser(t, "user2")
user5 := loginUser(t, "user5")
// = No follows = followersLink := "#profile-avatar-card a[href='/user1?tab=followers']"
followingLink := "#profile-avatar-card a[href='/user1?tab=following']"
listHeader := ".user-cards h2"
listItems := ".user-cards .list"
var followCount int // = No follows =
// Request the profile of user1, the Followers tab var followCount int
response := user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK)
page := NewHTMLParser(t, response.Body)
// Verify that user1 has no followers // Request the profile of user1, the Followers tab
testSelectorEquals(t, page, followersLink, "0 followers") response := user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK)
testSelectorEquals(t, page, listHeader, "Followers") page := NewHTMLParser(t, response.Body)
testListCount(t, page, listItems, followCount)
// Request the profile of user1, the Following tab // Verify that user1 has no followers
response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) testSelectorEquals(t, page, followersLink, "0 followers")
page = NewHTMLParser(t, response.Body) testSelectorEquals(t, page, listHeader, "Followers")
testListCount(t, page, listItems, followCount)
// Verify that user1 does not follow anyone // Request the profile of user1, the Following tab
testSelectorEquals(t, page, followingLink, "0 following") response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK)
testSelectorEquals(t, page, listHeader, "Following") page = NewHTMLParser(t, response.Body)
testListCount(t, page, listItems, followCount)
// Make user1 and user2 follow each other // Verify that user1 does not follow anyone
testUserFollowUser(t, user1, "user2") testSelectorEquals(t, page, followingLink, "0 following")
testUserFollowUser(t, user2, "user1") testSelectorEquals(t, page, listHeader, "Following")
testListCount(t, page, listItems, followCount)
// = 1 follow each = // Make user1 and user2 follow each other
testUserFollowUser(t, user1, "user2")
testUserFollowUser(t, user2, "user1")
followCount++ // = 1 follow each =
// Request the profile of user1, the Followers tab followCount++
response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK)
page = NewHTMLParser(t, response.Body)
// Verify it is now followed by 1 user // Request the profile of user1, the Followers tab
testSelectorEquals(t, page, followersLink, "1 follower") response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK)
testSelectorEquals(t, page, listHeader, "Follower") page = NewHTMLParser(t, response.Body)
testListCount(t, page, listItems, followCount)
// Request the profile of user1, the Following tab // Verify it is now followed by 1 user
response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) testSelectorEquals(t, page, followersLink, "1 follower")
page = NewHTMLParser(t, response.Body) testSelectorEquals(t, page, listHeader, "Follower")
testListCount(t, page, listItems, followCount)
// Verify it now follows follows 1 user // Request the profile of user1, the Following tab
testSelectorEquals(t, page, followingLink, "1 following") response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK)
testSelectorEquals(t, page, listHeader, "Following") page = NewHTMLParser(t, response.Body)
testListCount(t, page, listItems, followCount)
// Make user1 and user3 follow each other // Verify it now follows follows 1 user
testUserFollowUser(t, user1, "user5") testSelectorEquals(t, page, followingLink, "1 following")
testUserFollowUser(t, user5, "user1") testSelectorEquals(t, page, listHeader, "Following")
testListCount(t, page, listItems, followCount)
// = 2 follows = // Make user1 and user3 follow each other
testUserFollowUser(t, user1, "user5")
testUserFollowUser(t, user5, "user1")
followCount++ // = 2 follows =
// Request the profile of user1, the Followers tab followCount++
response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK)
page = NewHTMLParser(t, response.Body)
// Verify it is now followed by 2 users // Request the profile of user1, the Followers tab
testSelectorEquals(t, page, followersLink, "2 followers") response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK)
testSelectorEquals(t, page, listHeader, "Followers") page = NewHTMLParser(t, response.Body)
testListCount(t, page, listItems, followCount)
// Request the profile of user1, the Following tab // Verify it is now followed by 2 users
response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) testSelectorEquals(t, page, followersLink, "2 followers")
page = NewHTMLParser(t, response.Body) testSelectorEquals(t, page, listHeader, "Followers")
testListCount(t, page, listItems, followCount)
// Verify it now follows follows 2 users // Request the profile of user1, the Following tab
testSelectorEquals(t, page, followingLink, "2 following") response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK)
testSelectorEquals(t, page, listHeader, "Following") page = NewHTMLParser(t, response.Body)
testListCount(t, page, listItems, followCount)
}) // Verify it now follows follows 2 users
testSelectorEquals(t, page, followingLink, "2 following")
testSelectorEquals(t, page, listHeader, "Following")
testListCount(t, page, listItems, followCount)
} }
// testUserFollowUser simply follows a user `following` by session of user `follower` // testUserFollowUser simply follows a user `following` by session of user `follower`