2019-02-03 23:56:53 +00:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2019-02-03 23:56:53 +00:00
2022-09-02 15:18:23 -04:00
package integration
2019-02-03 23:56:53 +00:00
import (
2020-10-25 20:56:51 +00:00
"context"
2019-02-03 23:56:53 +00:00
"fmt"
"net/http"
2022-01-29 15:35:36 +00:00
"net/http/httptest"
2021-03-04 11:41:23 +08:00
"net/url"
2021-09-22 13:38:34 +08:00
"os"
2019-02-03 23:56:53 +00:00
"testing"
2020-10-25 20:56:51 +00:00
"time"
2019-02-03 23:56:53 +00:00
2023-01-17 16:46:03 -05:00
"code.gitea.io/gitea/models/auth"
2021-11-28 19:58:28 +08:00
"code.gitea.io/gitea/models/perm"
2021-12-10 09:27:50 +08:00
repo_model "code.gitea.io/gitea/models/repo"
2021-07-25 00:03:58 +08:00
"code.gitea.io/gitea/modules/json"
2020-10-25 20:56:51 +00:00
"code.gitea.io/gitea/modules/queue"
2019-05-11 18:21:34 +08:00
api "code.gitea.io/gitea/modules/structs"
2021-04-06 20:44:05 +01:00
"code.gitea.io/gitea/services/forms"
2019-08-23 09:40:30 -07:00
2019-02-03 23:56:53 +00:00
"github.com/stretchr/testify/assert"
)
type APITestContext struct {
Reponame string
Session * TestSession
Token string
Username string
ExpectedCode int
}
2023-01-17 16:46:03 -05:00
func NewAPITestContext ( t * testing . T , username , reponame string , scope ... auth . AccessTokenScope ) APITestContext {
2019-02-03 23:56:53 +00:00
session := loginUser ( t , username )
2023-01-17 16:46:03 -05:00
token := getTokenForLoggedInUser ( t , session , scope ... )
2019-02-03 23:56:53 +00:00
return APITestContext {
Session : session ,
Token : token ,
Username : username ,
Reponame : reponame ,
}
}
func ( ctx APITestContext ) GitPath ( ) string {
return fmt . Sprintf ( "%s/%s.git" , ctx . Username , ctx . Reponame )
}
func doAPICreateRepository ( ctx APITestContext , empty bool , callback ... func ( * testing . T , api . Repository ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
createRepoOption := & api . CreateRepoOption {
AutoInit : ! empty ,
Description : "Temporary repo" ,
Name : ctx . Reponame ,
Private : true ,
2020-09-25 13:18:37 +08:00
Template : true ,
2019-02-03 23:56:53 +00:00
Gitignores : "" ,
License : "WTFPL" ,
Readme : "Default" ,
}
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , "/api/v1/user/repos" , createRepoOption ) .
AddTokenAuth ( ctx . Token )
2019-02-03 23:56:53 +00:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusCreated )
var repository api . Repository
2019-06-22 18:35:34 +01:00
DecodeJSON ( t , resp , & repository )
if len ( callback ) > 0 {
callback [ 0 ] ( t , repository )
}
}
}
2021-03-04 11:41:23 +08:00
func doAPIEditRepository ( ctx APITestContext , editRepoOption * api . EditRepoOption , callback ... func ( * testing . T , api . Repository ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "PATCH" , fmt . Sprintf ( "/api/v1/repos/%s/%s" , url . PathEscape ( ctx . Username ) , url . PathEscape ( ctx . Reponame ) ) , editRepoOption ) .
AddTokenAuth ( ctx . Token )
2021-03-04 11:41:23 +08:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusOK )
var repository api . Repository
DecodeJSON ( t , resp , & repository )
if len ( callback ) > 0 {
callback [ 0 ] ( t , repository )
}
}
}
2021-11-28 19:58:28 +08:00
func doAPIAddCollaborator ( ctx APITestContext , username string , mode perm . AccessMode ) func ( * testing . T ) {
2019-06-22 18:35:34 +01:00
return func ( t * testing . T ) {
permission := "read"
2021-11-28 19:58:28 +08:00
if mode == perm . AccessModeAdmin {
2019-06-22 18:35:34 +01:00
permission = "admin"
2021-11-28 19:58:28 +08:00
} else if mode > perm . AccessModeRead {
2019-06-22 18:35:34 +01:00
permission = "write"
}
addCollaboratorOption := & api . AddCollaboratorOption {
Permission : & permission ,
}
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "PUT" , fmt . Sprintf ( "/api/v1/repos/%s/%s/collaborators/%s" , ctx . Username , ctx . Reponame , username ) , addCollaboratorOption ) .
AddTokenAuth ( ctx . Token )
2019-06-22 18:35:34 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
ctx . Session . MakeRequest ( t , req , http . StatusNoContent )
}
}
func doAPIForkRepository ( ctx APITestContext , username string , callback ... func ( * testing . T , api . Repository ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
createForkOption := & api . CreateForkOption { }
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , fmt . Sprintf ( "/api/v1/repos/%s/%s/forks" , username , ctx . Reponame ) , createForkOption ) .
AddTokenAuth ( ctx . Token )
2019-06-22 18:35:34 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusAccepted )
var repository api . Repository
2019-02-03 23:56:53 +00:00
DecodeJSON ( t , resp , & repository )
if len ( callback ) > 0 {
callback [ 0 ] ( t , repository )
}
}
}
func doAPIGetRepository ( ctx APITestContext , callback ... func ( * testing . T , api . Repository ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , "GET" , fmt . Sprintf ( "/api/v1/repos/%s/%s" , ctx . Username , ctx . Reponame ) ) .
AddTokenAuth ( ctx . Token )
2019-02-03 23:56:53 +00:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusOK )
var repository api . Repository
DecodeJSON ( t , resp , & repository )
if len ( callback ) > 0 {
callback [ 0 ] ( t , repository )
}
}
}
func doAPIDeleteRepository ( ctx APITestContext ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , "DELETE" , fmt . Sprintf ( "/api/v1/repos/%s/%s" , ctx . Username , ctx . Reponame ) ) .
AddTokenAuth ( ctx . Token )
2019-02-03 23:56:53 +00:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
ctx . Session . MakeRequest ( t , req , http . StatusNoContent )
}
}
func doAPICreateUserKey ( ctx APITestContext , keyname , keyFile string , callback ... func ( * testing . T , api . PublicKey ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
2021-09-22 13:38:34 +08:00
dataPubKey , err := os . ReadFile ( keyFile + ".pub" )
2019-02-03 23:56:53 +00:00
assert . NoError ( t , err )
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , "/api/v1/user/keys" , & api . CreateKeyOption {
2019-02-03 23:56:53 +00:00
Title : keyname ,
Key : string ( dataPubKey ) ,
2023-12-22 00:59:59 +01:00
} ) . AddTokenAuth ( ctx . Token )
2019-02-03 23:56:53 +00:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusCreated )
var publicKey api . PublicKey
DecodeJSON ( t , resp , & publicKey )
if len ( callback ) > 0 {
callback [ 0 ] ( t , publicKey )
}
}
}
func doAPIDeleteUserKey ( ctx APITestContext , keyID int64 ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , "DELETE" , fmt . Sprintf ( "/api/v1/user/keys/%d" , keyID ) ) .
AddTokenAuth ( ctx . Token )
2019-02-03 23:56:53 +00:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
ctx . Session . MakeRequest ( t , req , http . StatusNoContent )
}
}
func doAPICreateDeployKey ( ctx APITestContext , keyname , keyFile string , readOnly bool ) func ( * testing . T ) {
return func ( t * testing . T ) {
2021-09-22 13:38:34 +08:00
dataPubKey , err := os . ReadFile ( keyFile + ".pub" )
2019-02-03 23:56:53 +00:00
assert . NoError ( t , err )
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , fmt . Sprintf ( "/api/v1/repos/%s/%s/keys" , ctx . Username , ctx . Reponame ) , api . CreateKeyOption {
2019-02-03 23:56:53 +00:00
Title : keyname ,
Key : string ( dataPubKey ) ,
ReadOnly : readOnly ,
2023-12-22 00:59:59 +01:00
} ) . AddTokenAuth ( ctx . Token )
2019-02-03 23:56:53 +00:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
ctx . Session . MakeRequest ( t , req , http . StatusCreated )
}
}
2019-05-31 11:12:15 +01:00
func doAPICreatePullRequest ( ctx APITestContext , owner , repo , baseBranch , headBranch string ) func ( * testing . T ) ( api . PullRequest , error ) {
return func ( t * testing . T ) ( api . PullRequest , error ) {
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , http . MethodPost , fmt . Sprintf ( "/api/v1/repos/%s/%s/pulls" , owner , repo ) , & api . CreatePullRequestOption {
2019-05-31 11:12:15 +01:00
Head : headBranch ,
Base : baseBranch ,
Title : fmt . Sprintf ( "create a pr from %s to %s" , headBranch , baseBranch ) ,
2023-12-22 00:59:59 +01:00
} ) . AddTokenAuth ( ctx . Token )
2019-05-31 11:12:15 +01:00
2022-03-23 05:54:07 +01:00
expected := http . StatusCreated
2019-05-31 11:12:15 +01:00
if ctx . ExpectedCode != 0 {
expected = ctx . ExpectedCode
}
resp := ctx . Session . MakeRequest ( t , req , expected )
2021-03-01 21:08:10 +00:00
2019-05-31 11:12:15 +01:00
decoder := json . NewDecoder ( resp . Body )
pr := api . PullRequest { }
err := decoder . Decode ( & pr )
return pr , err
}
}
2021-04-10 09:27:29 +01:00
func doAPIGetPullRequest ( ctx APITestContext , owner , repo string , index int64 ) func ( * testing . T ) ( api . PullRequest , error ) {
return func ( t * testing . T ) ( api . PullRequest , error ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , http . MethodGet , fmt . Sprintf ( "/api/v1/repos/%s/%s/pulls/%d" , owner , repo , index ) ) .
AddTokenAuth ( ctx . Token )
2021-04-10 09:27:29 +01:00
2022-03-23 05:54:07 +01:00
expected := http . StatusOK
2021-04-10 09:27:29 +01:00
if ctx . ExpectedCode != 0 {
expected = ctx . ExpectedCode
}
resp := ctx . Session . MakeRequest ( t , req , expected )
decoder := json . NewDecoder ( resp . Body )
pr := api . PullRequest { }
err := decoder . Decode ( & pr )
return pr , err
}
}
2019-05-31 11:12:15 +01:00
func doAPIMergePullRequest ( ctx APITestContext , owner , repo string , index int64 ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
urlStr := fmt . Sprintf ( "/api/v1/repos/%s/%s/pulls/%d/merge" , owner , repo , index )
2019-05-31 11:12:15 +01:00
2023-12-22 00:59:59 +01:00
var req * RequestWrapper
2022-01-29 15:35:36 +00:00
var resp * httptest . ResponseRecorder
2020-10-25 20:56:51 +00:00
2022-01-29 15:35:36 +00:00
for i := 0 ; i < 6 ; i ++ {
2021-04-06 20:44:05 +01:00
req = NewRequestWithJSON ( t , http . MethodPost , urlStr , & forms . MergePullRequestForm {
2020-11-08 19:23:00 +00:00
MergeMessageField : "doAPIMergePullRequest Merge" ,
2021-12-10 09:27:50 +08:00
Do : string ( repo_model . MergeStyleMerge ) ,
2023-12-22 00:59:59 +01:00
} ) . AddTokenAuth ( ctx . Token )
2022-01-29 15:35:36 +00:00
2020-10-25 20:56:51 +00:00
resp = ctx . Session . MakeRequest ( t , req , NoExpectedStatus )
2022-01-29 15:35:36 +00:00
if resp . Code != http . StatusMethodNotAllowed {
break
}
err := api . APIError { }
DecodeJSON ( t , resp , & err )
assert . EqualValues ( t , "Please try again later" , err . Message )
queue . GetManager ( ) . FlushAll ( context . Background ( ) , 5 * time . Second )
<- time . After ( 1 * time . Second )
2020-10-25 20:56:51 +00:00
}
expected := ctx . ExpectedCode
if expected == 0 {
2022-03-23 05:54:07 +01:00
expected = http . StatusOK
2020-10-25 20:56:51 +00:00
}
if ! assert . EqualValues ( t , expected , resp . Code ,
"Request: %s %s" , req . Method , req . URL . String ( ) ) {
logUnexpectedResponse ( t , resp )
2019-05-31 11:12:15 +01:00
}
}
}
2019-10-16 14:42:42 +01:00
2021-03-04 11:41:23 +08:00
func doAPIManuallyMergePullRequest ( ctx APITestContext , owner , repo , commitID string , index int64 ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
urlStr := fmt . Sprintf ( "/api/v1/repos/%s/%s/pulls/%d/merge" , owner , repo , index )
2021-04-06 20:44:05 +01:00
req := NewRequestWithJSON ( t , http . MethodPost , urlStr , & forms . MergePullRequestForm {
2021-12-10 09:27:50 +08:00
Do : string ( repo_model . MergeStyleManuallyMerged ) ,
2021-03-04 11:41:23 +08:00
MergeCommitID : commitID ,
2023-12-22 00:59:59 +01:00
} ) . AddTokenAuth ( ctx . Token )
2021-03-04 11:41:23 +08:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
2022-03-23 05:54:07 +01:00
ctx . Session . MakeRequest ( t , req , http . StatusOK )
2021-03-04 11:41:23 +08:00
}
}
2022-05-07 19:05:52 +02:00
func doAPIAutoMergePullRequest ( ctx APITestContext , owner , repo string , index int64 ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
urlStr := fmt . Sprintf ( "/api/v1/repos/%s/%s/pulls/%d/merge" , owner , repo , index )
2022-05-07 19:05:52 +02:00
req := NewRequestWithJSON ( t , http . MethodPost , urlStr , & forms . MergePullRequestForm {
MergeMessageField : "doAPIMergePullRequest Merge" ,
Do : string ( repo_model . MergeStyleMerge ) ,
MergeWhenChecksSucceed : true ,
2023-12-22 00:59:59 +01:00
} ) . AddTokenAuth ( ctx . Token )
2022-05-07 19:05:52 +02:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
2023-12-22 00:59:59 +01:00
ctx . Session . MakeRequest ( t , req , http . StatusOK )
2022-05-07 19:05:52 +02:00
}
}
func doAPICancelAutoMergePullRequest ( ctx APITestContext , owner , repo string , index int64 ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , http . MethodDelete , fmt . Sprintf ( "/api/v1/repos/%s/%s/pulls/%d/merge" , owner , repo , index ) ) .
AddTokenAuth ( ctx . Token )
2022-05-07 19:05:52 +02:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
2023-12-22 00:59:59 +01:00
ctx . Session . MakeRequest ( t , req , http . StatusNoContent )
2022-05-07 19:05:52 +02:00
}
}
2019-10-16 14:42:42 +01:00
func doAPIGetBranch ( ctx APITestContext , branch string , callback ... func ( * testing . T , api . Branch ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequestf ( t , "GET" , "/api/v1/repos/%s/%s/branches/%s" , ctx . Username , ctx . Reponame , branch ) .
AddTokenAuth ( ctx . Token )
2019-10-16 14:42:42 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusOK )
var branch api . Branch
DecodeJSON ( t , resp , & branch )
if len ( callback ) > 0 {
callback [ 0 ] ( t , branch )
}
}
}
func doAPICreateFile ( ctx APITestContext , treepath string , options * api . CreateFileOptions , callback ... func ( * testing . T , api . FileResponse ) ) func ( * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , fmt . Sprintf ( "/api/v1/repos/%s/%s/contents/%s" , ctx . Username , ctx . Reponame , treepath ) , & options ) .
AddTokenAuth ( ctx . Token )
2019-10-16 14:42:42 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusCreated )
var contents api . FileResponse
DecodeJSON ( t , resp , & contents )
if len ( callback ) > 0 {
callback [ 0 ] ( t , contents )
}
}
}
2020-05-11 23:04:08 +01:00
func doAPICreateOrganization ( ctx APITestContext , options * api . CreateOrgOption , callback ... func ( * testing . T , api . Organization ) ) func ( t * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , "/api/v1/orgs" , & options ) .
AddTokenAuth ( ctx . Token )
2020-05-11 23:04:08 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusCreated )
var contents api . Organization
DecodeJSON ( t , resp , & contents )
if len ( callback ) > 0 {
callback [ 0 ] ( t , contents )
}
}
}
func doAPICreateOrganizationRepository ( ctx APITestContext , orgName string , options * api . CreateRepoOption , callback ... func ( * testing . T , api . Repository ) ) func ( t * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , fmt . Sprintf ( "/api/v1/orgs/%s/repos" , orgName ) , & options ) .
AddTokenAuth ( ctx . Token )
2020-05-11 23:04:08 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusCreated )
var contents api . Repository
DecodeJSON ( t , resp , & contents )
if len ( callback ) > 0 {
callback [ 0 ] ( t , contents )
}
}
}
func doAPICreateOrganizationTeam ( ctx APITestContext , orgName string , options * api . CreateTeamOption , callback ... func ( * testing . T , api . Team ) ) func ( t * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequestWithJSON ( t , "POST" , fmt . Sprintf ( "/api/v1/orgs/%s/teams" , orgName ) , & options ) .
AddTokenAuth ( ctx . Token )
2020-05-11 23:04:08 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
resp := ctx . Session . MakeRequest ( t , req , http . StatusCreated )
var contents api . Team
DecodeJSON ( t , resp , & contents )
if len ( callback ) > 0 {
callback [ 0 ] ( t , contents )
}
}
}
func doAPIAddUserToOrganizationTeam ( ctx APITestContext , teamID int64 , username string ) func ( t * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , "PUT" , fmt . Sprintf ( "/api/v1/teams/%d/members/%s" , teamID , username ) ) .
AddTokenAuth ( ctx . Token )
2020-05-11 23:04:08 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
ctx . Session . MakeRequest ( t , req , http . StatusNoContent )
}
}
func doAPIAddRepoToOrganizationTeam ( ctx APITestContext , teamID int64 , orgName , repoName string ) func ( t * testing . T ) {
return func ( t * testing . T ) {
2023-12-22 00:59:59 +01:00
req := NewRequest ( t , "PUT" , fmt . Sprintf ( "/api/v1/teams/%d/repos/%s/%s" , teamID , orgName , repoName ) ) .
AddTokenAuth ( ctx . Token )
2020-05-11 23:04:08 +01:00
if ctx . ExpectedCode != 0 {
ctx . Session . MakeRequest ( t , req , ctx . ExpectedCode )
return
}
ctx . Session . MakeRequest ( t , req , http . StatusNoContent )
}
}