diff --git a/integrations/api_repo_test.go b/integrations/api_repo_test.go index d5b1676d6eac3..c13b1422e5b70 100644 --- a/integrations/api_repo_test.go +++ b/integrations/api_repo_test.go @@ -6,7 +6,6 @@ package integrations import ( "net/http" - "strings" "testing" "code.gitea.io/gitea/models" @@ -33,11 +32,6 @@ func TestAPIUserReposNotLogin(t *testing.T) { } } -type searchResponseBody struct { - ok bool - data []api.Repository -} - func TestAPISearchRepoNotLogin(t *testing.T) { prepareTestEnv(t) const keyword = "test" @@ -45,10 +39,226 @@ func TestAPISearchRepoNotLogin(t *testing.T) { req := NewRequestf(t, "GET", "/api/v1/repos/search?q=%s", keyword) resp := MakeRequest(t, req, http.StatusOK) - var body searchResponseBody + var body api.SearchResults + DecodeJSON(t, resp, &body) + assert.NotEmpty(t, body.Data) + for _, repo := range body.Data { + assert.Contains(t, repo.Name, keyword) + assert.False(t, repo.Private) + } + + // Should return all (max 50) public repositories + req = NewRequest(t, "GET", "/api/v1/repos/search?limit=50") + resp = MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 12) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + // Should return (max 10) public repositories + req = NewRequest(t, "GET", "/api/v1/repos/search?limit=10") + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &body) - for _, repo := range body.data { - assert.True(t, strings.Contains(repo.Name, keyword)) + assert.Len(t, body.Data, 10) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + const keyword2 = "big_test_" + // Should return all public repositories which (partial) match keyword + req = NewRequestf(t, "GET", "/api/v1/repos/search?q=%s", keyword2) + resp = MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 4) + for _, repo := range body.Data { + assert.Contains(t, repo.Name, keyword2) + assert.False(t, repo.Private) + } + + // Should return all public repositories accessible and related to user + const userID = int64(15) + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", userID) + resp = MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 4) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + // Should return all public repositories accessible and related to user + const user2ID = int64(16) + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", user2ID) + resp = MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 1) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + // Should return all public repositories owned by organization + const orgID = int64(17) + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", orgID) + resp = MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 1) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.Equal(t, repo.Owner.ID, orgID) + assert.False(t, repo.Private) + } +} + +func TestAPISearchRepoLoggedUser(t *testing.T) { + prepareTestEnv(t) + + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 15}).(*models.User) + user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 16}).(*models.User) + session := loginUser(t, user.Name) + session2 := loginUser(t, user2.Name) + + var body api.SearchResults + + // Get public repositories accessible and not related to logged in user that match the keyword + // Should return all public repositories which (partial) match keyword + const keyword = "big_test_" + req := NewRequestf(t, "GET", "/api/v1/repos/search?q=%s", keyword) + resp := session.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 4) + for _, repo := range body.Data { + assert.Contains(t, repo.Name, keyword) + assert.False(t, repo.Private) + } + // Test when user2 is logged in + resp = session2.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 4) + for _, repo := range body.Data { + assert.Contains(t, repo.Name, keyword) + assert.False(t, repo.Private) + } + + // Get all public repositories accessible and not related to logged in user + // Should return all (max 50) public repositories + req = NewRequest(t, "GET", "/api/v1/repos/search?limit=50") + resp = session.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 12) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + // Test when user2 is logged in + resp = session2.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 12) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + // Get all public repositories accessible and not related to logged in user + // Should return all (max 10) public repositories + req = NewRequest(t, "GET", "/api/v1/repos/search?limit=10") + resp = session.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 10) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + // Test when user2 is logged in + resp = session2.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 10) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + // Get repositories of logged in user + // Should return all public and private repositories accessible and related to user + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", user.ID) + resp = session.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 8) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + } + // Test when user2 is logged in + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", user2.ID) + resp = session2.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 2) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + } + + // Get repositories of another user + // Should return all public repositories accessible and related to user + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", user2.ID) + resp = session.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 1) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + // Test when user2 is logged in + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", user.ID) + resp = session2.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 4) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.False(t, repo.Private) + } + + // Get repositories of organization owned by logged in user + // Should return all public and private repositories owned by organization + const orgID = int64(17) + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", orgID) + resp = session.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 2) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.Equal(t, repo.Owner.ID, orgID) + } + + // Get repositories of organization owned by another user + // Should return all public repositories owned by organization + req = NewRequestf(t, "GET", "/api/v1/repos/search?uid=%d", orgID) + resp = session2.MakeRequest(t, req, http.StatusOK) + + DecodeJSON(t, resp, &body) + assert.Len(t, body.Data, 1) + for _, repo := range body.Data { + assert.NotEmpty(t, repo.Name) + assert.Equal(t, repo.Owner.ID, orgID) + assert.False(t, repo.Private) } } diff --git a/models/fixtures/access.yml b/models/fixtures/access.yml index 8722b248db2fb..34d5c5c59405c 100644 --- a/models/fixtures/access.yml +++ b/models/fixtures/access.yml @@ -15,3 +15,27 @@ user_id: 4 repo_id: 3 mode: 2 # write + +- + id: 4 + user_id: 15 + repo_id: 22 + mode: 2 # write + +- + id: 5 + user_id: 15 + repo_id: 21 + mode: 2 # write + +- + id: 6 + user_id: 15 + repo_id: 23 + mode: 4 # owner + +- + id: 7 + user_id: 15 + repo_id: 24 + mode: 4 # owner \ No newline at end of file diff --git a/models/fixtures/org_user.yml b/models/fixtures/org_user.yml index a7b8d178aa13a..c7fe2cf369522 100644 --- a/models/fixtures/org_user.yml +++ b/models/fixtures/org_user.yml @@ -29,3 +29,11 @@ is_public: false is_owner: true num_teams: 1 + +- + id: 5 + uid: 15 + org_id: 17 + is_public: true + is_owner: true + num_teams: 1 diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index b8f607b2a8ec5..8c8afb27b083e 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -188,3 +188,100 @@ num_pulls: 0 num_closed_pulls: 0 num_watches: 0 + +- + id: 17 + owner_id: 15 + lower_name: big_test_public_1 + name: big_test_public_1 + is_private: false + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + num_watches: 0 + is_mirror: false + +- + id: 18 + owner_id: 15 + lower_name: big_test_public_2 + name: big_test_public_2 + is_private: false + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false + +- + id: 19 + owner_id: 15 + lower_name: big_test_private_1 + name: big_test_private_1 + is_private: true + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false + +- + id: 20 + owner_id: 15 + lower_name: big_test_private_2 + name: big_test_private_2 + is_private: true + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false + +- + id: 21 + owner_id: 16 + lower_name: big_test_public_3 + name: big_test_public_3 + is_private: false + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false + +- + id: 22 + owner_id: 16 + lower_name: big_test_private_3 + name: big_test_private_3 + is_private: true + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false + +- + id: 23 + owner_id: 17 + lower_name: big_test_public_4 + name: big_test_public_4 + is_private: false + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false + +- + id: 24 + owner_id: 17 + lower_name: big_test_private_4 + name: big_test_private_4 + is_private: true + num_issues: 0 + num_closed_issues: 0 + num_pulls: 0 + num_closed_pulls: 0 + is_mirror: false diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml index 795d5cda6c998..298de648ddf78 100644 --- a/models/fixtures/team.yml +++ b/models/fixtures/team.yml @@ -37,3 +37,12 @@ num_repos: 0 num_members: 1 unit_types: '[1,2,3,4,5,6,7]' +- + id: 5 + org_id: 17 + lower_name: owners + name: Owners + authorize: 4 # owner + num_repos: 2 + num_members: 1 + unit_types: '[1,2,3,4,5,6,7]' diff --git a/models/fixtures/team_repo.yml b/models/fixtures/team_repo.yml index 1f7385e7e9c17..5154453f7b4dd 100644 --- a/models/fixtures/team_repo.yml +++ b/models/fixtures/team_repo.yml @@ -15,3 +15,15 @@ org_id: 3 team_id: 1 repo_id: 5 + +- + id: 4 + org_id: 17 + team_id: 5 + repo_id: 23 + +- + id: 5 + org_id: 17 + team_id: 5 + repo_id: 24 \ No newline at end of file diff --git a/models/fixtures/team_user.yml b/models/fixtures/team_user.yml index 955a80e4cdf03..8d9d9203782e4 100644 --- a/models/fixtures/team_user.yml +++ b/models/fixtures/team_user.yml @@ -27,3 +27,9 @@ org_id: 7 team_id: 4 uid: 5 + +- + id: 6 + org_id: 17 + team_id: 5 + uid: 15 \ No newline at end of file diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml index abd72b1168105..e1fbc9e578bfe 100644 --- a/models/fixtures/user.yml +++ b/models/fixtures/user.yml @@ -218,3 +218,50 @@ avatar_email: user13@example.com num_repos: 3 is_active: true + +- + id: 15 + lower_name: user15 + name: user15 + full_name: User 15 + email: user15@example.com + passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password + type: 0 # individual + salt: ZogKvWdyEx + is_admin: false + avatar: avatar15 + avatar_email: user15@example.com + num_repos: 4 + is_active: true + +- + id: 16 + lower_name: user16 + name: user16 + full_name: User 16 + email: user16@example.com + passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password + type: 0 # individual + salt: ZogKvWdyEx + is_admin: false + avatar: avatar16 + avatar_email: user16@example.com + num_repos: 2 + is_active: true + +- + id: 17 + lower_name: user17 + name: user17 + full_name: User 17 + email: user17@example.com + passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password + type: 1 # organization + salt: ZogKvWdyEx + is_admin: false + avatar: avatar17 + avatar_email: user17@example.com + num_repos: 2 + is_active: true + num_members: 1 + num_teams: 1 \ No newline at end of file diff --git a/models/org_test.go b/models/org_test.go index 07da2d56af906..c7bdb8b5d3dbb 100644 --- a/models/org_test.go +++ b/models/org_test.go @@ -252,7 +252,7 @@ func TestOrganizations(t *testing.T) { []int64{3, 6}) testSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 2, PageSize: 2}, - []int64{7}) + []int64{7, 17}) testSuccess(&SearchUserOptions{Page: 3, PageSize: 2}, []int64{}) diff --git a/models/repo_list_test.go b/models/repo_list_test.go index 8ac0d804892da..bf5b708744a38 100644 --- a/models/repo_list_test.go +++ b/models/repo_list_test.go @@ -18,10 +18,8 @@ func TestSearchRepositoryByName(t *testing.T) { Keyword: "repo_12", Page: 1, PageSize: 10, - Searcher: nil, }) - assert.NotNil(t, repos) assert.NoError(t, err) if assert.Len(t, repos, 1) { assert.Equal(t, "test_repo_12", repos[0].Name) @@ -32,12 +30,11 @@ func TestSearchRepositoryByName(t *testing.T) { Keyword: "test_repo", Page: 1, PageSize: 10, - Searcher: nil, }) - assert.NotNil(t, repos) assert.NoError(t, err) assert.Equal(t, int64(2), count) + assert.Len(t, repos, 2) // test search private repository on explore page repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ @@ -45,10 +42,8 @@ func TestSearchRepositoryByName(t *testing.T) { Page: 1, PageSize: 10, Private: true, - Searcher: &User{ID: 14}, }) - assert.NotNil(t, repos) assert.NoError(t, err) if assert.Len(t, repos, 1) { assert.Equal(t, "test_repo_13", repos[0].Name) @@ -60,10 +55,133 @@ func TestSearchRepositoryByName(t *testing.T) { Page: 1, PageSize: 10, Private: true, - Searcher: &User{ID: 14}, }) - assert.NotNil(t, repos) assert.NoError(t, err) assert.Equal(t, int64(3), count) + assert.Len(t, repos, 3) + + // Get all public repositories by name + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Keyword: "big_test_", + Page: 1, + PageSize: 10, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(4), count) + assert.Len(t, repos, 4) + + // Get all public + private repositories by name + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Keyword: "big_test_", + Page: 1, + PageSize: 10, + Private: true, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(8), count) + assert.Len(t, repos, 8) + + // Get all public + private repositories by name with pagesize limit (first page) + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Keyword: "big_test_", + Page: 1, + PageSize: 5, + Private: true, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(8), count) + assert.Len(t, repos, 5) + + // Get all public + private repositories by name with pagesize limit (second page) + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Keyword: "big_test_", + Page: 2, + PageSize: 5, + Private: true, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(8), count) + assert.Len(t, repos, 3) + + // Get all public repositories of user + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Page: 1, + PageSize: 10, + OwnerID: 15, + Searcher: &User{ID: 15}, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(2), count) + assert.Len(t, repos, 2) + + // Get all public + private repositories of user + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Page: 1, + PageSize: 10, + OwnerID: 15, + Private: true, + Searcher: &User{ID: 15}, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(4), count) + assert.Len(t, repos, 4) + + // Get all public (including collaborative) repositories of user + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Page: 1, + PageSize: 10, + OwnerID: 15, + Collaborate: true, + Searcher: &User{ID: 15}, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(4), count) + assert.Len(t, repos, 4) + + // Get all public + private (including collaborative) repositories of user + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Page: 1, + PageSize: 10, + OwnerID: 15, + Private: true, + Collaborate: true, + Searcher: &User{ID: 15}, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(8), count) + assert.Len(t, repos, 8) + + // Get all public repositories of organization + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Page: 1, + PageSize: 10, + OwnerID: 17, + Searcher: &User{ID: 17}, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(1), count) + assert.Len(t, repos, 1) + + // Get all public + private repositories of organization + repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ + Page: 1, + PageSize: 10, + OwnerID: 17, + Private: true, + Searcher: &User{ID: 17}, + }) + + assert.NoError(t, err) + assert.Equal(t, int64(2), count) + assert.Len(t, repos, 2) }