Add tests for pull request's content_version in API (#37044)
Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
This commit is contained in:
@@ -80,7 +80,8 @@ type Issue struct {
|
|||||||
PullRequest *PullRequestMeta `json:"pull_request"`
|
PullRequest *PullRequestMeta `json:"pull_request"`
|
||||||
Repo *RepositoryMeta `json:"repository"`
|
Repo *RepositoryMeta `json:"repository"`
|
||||||
|
|
||||||
PinOrder int `json:"pin_order"`
|
PinOrder int `json:"pin_order"`
|
||||||
|
// The version of the issue content for optimistic locking
|
||||||
ContentVersion int `json:"content_version"`
|
ContentVersion int `json:"content_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +116,8 @@ type EditIssueOption struct {
|
|||||||
// swagger:strfmt date-time
|
// swagger:strfmt date-time
|
||||||
Deadline *time.Time `json:"due_date"`
|
Deadline *time.Time `json:"due_date"`
|
||||||
RemoveDeadline *bool `json:"unset_due_date"`
|
RemoveDeadline *bool `json:"unset_due_date"`
|
||||||
ContentVersion *int `json:"content_version"`
|
// The current version of the issue content to detect conflicts during editing
|
||||||
|
ContentVersion *int `json:"content_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EditDeadlineOption options for creating a deadline
|
// EditDeadlineOption options for creating a deadline
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ type PullRequest struct {
|
|||||||
Closed *time.Time `json:"closed_at"`
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
|
||||||
// The pin order for the pull request
|
// The pin order for the pull request
|
||||||
PinOrder int `json:"pin_order"`
|
PinOrder int `json:"pin_order"`
|
||||||
|
// The version of the pull request content for optimistic locking
|
||||||
ContentVersion int `json:"content_version"`
|
ContentVersion int `json:"content_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +170,8 @@ type EditPullRequestOption struct {
|
|||||||
RemoveDeadline *bool `json:"unset_due_date"`
|
RemoveDeadline *bool `json:"unset_due_date"`
|
||||||
// Whether to allow maintainer edits
|
// Whether to allow maintainer edits
|
||||||
AllowMaintainerEdit *bool `json:"allow_maintainer_edit"`
|
AllowMaintainerEdit *bool `json:"allow_maintainer_edit"`
|
||||||
ContentVersion *int `json:"content_version"`
|
// The current version of the pull request content to detect conflicts during editing
|
||||||
|
ContentVersion *int `json:"content_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangedFile store information about files affected by the pull request
|
// ChangedFile store information about files affected by the pull request
|
||||||
|
|||||||
Generated
+4
@@ -24768,6 +24768,7 @@
|
|||||||
"x-go-name": "Body"
|
"x-go-name": "Body"
|
||||||
},
|
},
|
||||||
"content_version": {
|
"content_version": {
|
||||||
|
"description": "The current version of the issue content to detect conflicts during editing",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "ContentVersion"
|
"x-go-name": "ContentVersion"
|
||||||
@@ -24945,6 +24946,7 @@
|
|||||||
"x-go-name": "Body"
|
"x-go-name": "Body"
|
||||||
},
|
},
|
||||||
"content_version": {
|
"content_version": {
|
||||||
|
"description": "The current version of the pull request content to detect conflicts during editing",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "ContentVersion"
|
"x-go-name": "ContentVersion"
|
||||||
@@ -26235,6 +26237,7 @@
|
|||||||
"x-go-name": "Comments"
|
"x-go-name": "Comments"
|
||||||
},
|
},
|
||||||
"content_version": {
|
"content_version": {
|
||||||
|
"description": "The version of the issue content for optimistic locking",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "ContentVersion"
|
"x-go-name": "ContentVersion"
|
||||||
@@ -27742,6 +27745,7 @@
|
|||||||
"x-go-name": "Comments"
|
"x-go-name": "Comments"
|
||||||
},
|
},
|
||||||
"content_version": {
|
"content_version": {
|
||||||
|
"description": "The version of the pull request content for optimistic locking",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"x-go-name": "ContentVersion"
|
"x-go-name": "ContentVersion"
|
||||||
|
|||||||
@@ -472,8 +472,7 @@ func testAPIIssueContentVersion(t *testing.T) {
|
|||||||
|
|
||||||
req := NewRequest(t, "GET", urlStr).AddTokenAuth(token)
|
req := NewRequest(t, "GET", urlStr).AddTokenAuth(token)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
var before api.Issue
|
before := DecodeJSON(t, resp, &api.Issue{})
|
||||||
DecodeJSON(t, resp, &before)
|
|
||||||
req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditIssueOption{
|
req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditIssueOption{
|
||||||
Body: new("updated body with correct version"),
|
Body: new("updated body with correct version"),
|
||||||
ContentVersion: new(before.ContentVersion),
|
ContentVersion: new(before.ContentVersion),
|
||||||
|
|||||||
@@ -457,9 +457,8 @@ func TestAPIEditPull(t *testing.T) {
|
|||||||
Base: "master",
|
Base: "master",
|
||||||
Title: title,
|
Title: title,
|
||||||
}).AddTokenAuth(token)
|
}).AddTokenAuth(token)
|
||||||
apiPull := new(api.PullRequest)
|
|
||||||
resp := MakeRequest(t, req, http.StatusCreated)
|
resp := MakeRequest(t, req, http.StatusCreated)
|
||||||
DecodeJSON(t, resp, apiPull)
|
apiPull := DecodeJSON(t, resp, &api.PullRequest{})
|
||||||
assert.Equal(t, "master", apiPull.Base.Name)
|
assert.Equal(t, "master", apiPull.Base.Name)
|
||||||
|
|
||||||
newTitle := "edit a this pr"
|
newTitle := "edit a this pr"
|
||||||
@@ -470,8 +469,9 @@ func TestAPIEditPull(t *testing.T) {
|
|||||||
Body: &newBody,
|
Body: &newBody,
|
||||||
}).AddTokenAuth(token)
|
}).AddTokenAuth(token)
|
||||||
resp = MakeRequest(t, req, http.StatusCreated)
|
resp = MakeRequest(t, req, http.StatusCreated)
|
||||||
DecodeJSON(t, resp, apiPull)
|
apiPull = DecodeJSON(t, resp, &api.PullRequest{})
|
||||||
assert.Equal(t, "feature/1", apiPull.Base.Name)
|
assert.Equal(t, "feature/1", apiPull.Base.Name)
|
||||||
|
|
||||||
// check comment history
|
// check comment history
|
||||||
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID})
|
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID})
|
||||||
err := pull.LoadIssue(t.Context())
|
err := pull.LoadIssue(t.Context())
|
||||||
@@ -483,6 +483,62 @@ func TestAPIEditPull(t *testing.T) {
|
|||||||
Base: "not-exist",
|
Base: "not-exist",
|
||||||
}).AddTokenAuth(token)
|
}).AddTokenAuth(token)
|
||||||
MakeRequest(t, req, http.StatusNotFound)
|
MakeRequest(t, req, http.StatusNotFound)
|
||||||
|
|
||||||
|
t.Run("PullContentVersion", func(t *testing.T) {
|
||||||
|
testAPIPullContentVersion(t, pull.ID)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPIPullContentVersion(t *testing.T, pullID int64) {
|
||||||
|
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pullID})
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pull.BaseRepoID})
|
||||||
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
|
|
||||||
|
session := loginUser(t, owner.Name)
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner.Name, repo.Name, pull.Index)
|
||||||
|
|
||||||
|
t.Run("ResponseIncludesContentVersion", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", urlStr).AddTokenAuth(token)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
apiPull := DecodeJSON(t, resp, &api.PullRequest{})
|
||||||
|
assert.GreaterOrEqual(t, apiPull.ContentVersion, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("EditWithCorrectVersion", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", urlStr).AddTokenAuth(token)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
before := DecodeJSON(t, resp, &api.PullRequest{})
|
||||||
|
req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditPullRequestOption{
|
||||||
|
Body: new("updated body with correct version"),
|
||||||
|
ContentVersion: new(before.ContentVersion),
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
resp = MakeRequest(t, req, http.StatusCreated)
|
||||||
|
after := DecodeJSON(t, resp, &api.PullRequest{})
|
||||||
|
assert.Equal(t, "updated body with correct version", after.Body)
|
||||||
|
assert.Greater(t, after.ContentVersion, before.ContentVersion)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("EditWithWrongVersion", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditPullRequestOption{
|
||||||
|
Body: new("should fail"),
|
||||||
|
ContentVersion: new(99999),
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
MakeRequest(t, req, http.StatusConflict)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("EditWithoutVersion", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditPullRequestOption{
|
||||||
|
Body: new("edit without version succeeds"),
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func doAPIGetPullFiles(ctx APITestContext, pr *api.PullRequest, callback func(*testing.T, []*api.ChangedFile)) func(*testing.T) {
|
func doAPIGetPullFiles(ctx APITestContext, pr *api.PullRequest, callback func(*testing.T, []*api.ChangedFile)) func(*testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user