Send operations to project-history when resolving/unresolving comments (#17540)

* Send operations to project-history when resolving/unresolving comments

* small fixes

* added doc_id in web unit test

* Revert "added doc_id in web unit test"

This reverts commit f0b8251abfce17965d5e1b0e45d8784fcf1d9eed.

* fix mocked dependency in test

* wip: web unit tests

* document updater, reopen test

* document-updater tests

* format fix

* fix typo

* fix callsArgWith

* fix reopenThread calls in doc updater tests

* fix typos

* log error if chat api resolve failes

* log error when reopening thread

* sendStatus calls done() in tests

* using OError instead of logging

* removed timers

* preserve legacy endpoints

* update after merge

* Remove timer check in HttpControllerTest

* prettier

* added "legacy" in log

* remove metrics.timer

* fix promisify issues

* remove unused cb

GitOrigin-RevId: 849538c86996973a065c727835e93028e5429344
This commit is contained in:
Domagoj Kriskovic
2024-04-10 08:04:08 +00:00
committed by Copybot
parent 1557338775
commit 8bde496da4
12 changed files with 485 additions and 10 deletions
@@ -19,6 +19,8 @@ module.exports = {
getProjectDocsIfMatch,
clearProjectState,
acceptChanges,
resolveThread,
reopenThread,
deleteThread,
resyncProjectHistory,
updateProjectStructure,
@@ -38,6 +40,8 @@ module.exports = {
getProjectDocsIfMatch: promisify(getProjectDocsIfMatch),
clearProjectState: promisify(clearProjectState),
acceptChanges: promisify(acceptChanges),
resolveThread: promisify(resolveThread),
reopenThread: promisify(reopenThread),
deleteThread: promisify(deleteThread),
resyncProjectHistory: promisify(resyncProjectHistory),
updateProjectStructure: promisify(updateProjectStructure),
@@ -212,6 +216,36 @@ function acceptChanges(projectId, docId, changeIds, callback) {
)
}
function resolveThread(projectId, docId, threadId, userId, callback) {
_makeRequest(
{
path: `/project/${projectId}/doc/${docId}/comment/${threadId}/resolve`,
method: 'POST',
json: {
user_id: userId,
},
},
projectId,
'resolve-thread',
callback
)
}
function reopenThread(projectId, docId, threadId, userId, callback) {
_makeRequest(
{
path: `/project/${projectId}/doc/${docId}/comment/${threadId}/reopen`,
method: 'POST',
json: {
user_id: userId,
},
},
projectId,
'reopen-thread',
callback
)
}
function deleteThread(projectId, docId, threadId, userId, callback) {
_makeRequest(
{
@@ -898,7 +898,9 @@ function useReviewPanelState(): ReviewPanel.ReviewPanelState {
},
}))
postJSON(`/project/${projectId}/thread/${entry.thread_id}/resolve`)
postJSON(
`/project/${projectId}/doc/${docId}/thread/${entry.thread_id}/resolve`
)
onCommentResolved(entry.thread_id, user)
sendMB('rp-comment-resolve', { view })
},
@@ -925,9 +927,9 @@ function useReviewPanelState(): ReviewPanel.ReviewPanelState {
)
const unresolveComment = useCallback(
(threadId: ThreadId) => {
(docId: DocId, threadId: ThreadId) => {
onCommentReopened(threadId)
const url = `/project/${projectId}/thread/${threadId}/reopen`
const url = `/project/${projectId}/doc/${docId}/thread/${threadId}/reopen`
postJSON(url).catch(debugConsole.error)
sendMB('rp-comment-reopen')
},
@@ -38,7 +38,7 @@ function ResolvedCommentEntry({
: thread.content
const handleUnresolve = () => {
unresolveComment(thread.threadId)
unresolveComment(thread.docId, thread.threadId)
}
const handleDelete = () => {
@@ -71,7 +71,7 @@ export interface ReviewPanelState {
commentId: CommentId,
content: string
) => void
unresolveComment: (threadId: ThreadId) => void
unresolveComment: (docId: DocId, threadId: ThreadId) => void
deleteThread: (docId: DocId, threadId: ThreadId) => void
refreshResolvedCommentsDropdown: () => Promise<
void | ReviewPanelDocEntries[]
@@ -849,7 +849,7 @@ export default App.controller('ReviewPanelController', [
const entry = getDocEntries(doc_id)[entry_id]
entry.focused = false
$http.post(
`/project/${$scope.project_id}/thread/${entry.thread_id}/resolve`,
`/project/${$scope.project_id}/doc/${doc_id}/thread/${entry.thread_id}/resolve`,
{ _csrf: window.csrfToken }
)
_onCommentResolved(entry.thread_id, ide.$scope.user)
@@ -860,11 +860,14 @@ export default App.controller('ReviewPanelController', [
})
}
ide.$scope.unresolveComment = function (thread_id) {
ide.$scope.unresolveComment = function (doc_id, thread_id) {
_onCommentReopened(thread_id)
$http.post(`/project/${$scope.project_id}/thread/${thread_id}/reopen`, {
_csrf: window.csrfToken,
})
$http.post(
`/project/${$scope.project_id}/doc/${doc_id}/thread/${thread_id}/reopen`,
{
_csrf: window.csrfToken,
}
)
eventTracking.sendMB('rp-comment-reopen')
}
@@ -838,6 +838,174 @@ describe('DocumentUpdaterHandler', function () {
})
})
describe('resolveThread', function () {
beforeEach(function () {
this.thread_id = 'mock-thread-id-1'
})
describe('successfully', function () {
beforeEach(function () {
this.request.callsArgWith(1, null, { statusCode: 200 }, this.body)
this.handler.resolveThread(
this.project_id,
this.doc_id,
this.thread_id,
this.user_id,
this.callback
)
})
it('should resolve the thread in the document updater', function () {
this.request
.calledWithMatch({
url: `${this.settings.apis.documentupdater.url}/project/${this.project_id}/doc/${this.doc_id}/comment/${this.thread_id}/resolve`,
method: 'POST',
})
.should.equal(true)
})
it('should call the callback', function () {
this.callback.calledWith(null).should.equal(true)
})
})
describe('when the document updater API returns an error', function () {
beforeEach(function () {
this.request.callsArgWith(
1,
new Error('something went wrong'),
null,
null
)
this.handler.resolveThread(
this.project_id,
this.doc_id,
this.thread_id,
this.user_id,
this.callback
)
})
it('should return an error to the callback', function () {
this.callback
.calledWith(sinon.match.instanceOf(Error))
.should.equal(true)
})
})
describe('when the document updater returns a failure error code', function () {
beforeEach(function () {
this.request.callsArgWith(1, null, { statusCode: 500 }, '')
this.handler.resolveThread(
this.project_id,
this.doc_id,
this.thread_id,
this.user_id,
this.callback
)
})
it('should return the callback with an error', function () {
this.callback
.calledWith(
sinon.match
.instanceOf(Error)
.and(
sinon.match.has(
'message',
'document updater returned a failure status code: 500'
)
)
)
.should.equal(true)
})
})
})
describe('reopenThread', function () {
beforeEach(function () {
this.thread_id = 'mock-thread-id-1'
})
describe('successfully', function () {
beforeEach(function () {
this.request.callsArgWith(1, null, { statusCode: 200 }, this.body)
this.handler.reopenThread(
this.project_id,
this.doc_id,
this.thread_id,
this.user_id,
this.callback
)
})
it('should reopen the thread in the document updater', function () {
this.request
.calledWithMatch({
url: `${this.settings.apis.documentupdater.url}/project/${this.project_id}/doc/${this.doc_id}/comment/${this.thread_id}/reopen`,
method: 'POST',
})
.should.equal(true)
})
it('should call the callback', function () {
this.callback.calledWith(null).should.equal(true)
})
})
describe('when the document updater API returns an error', function () {
beforeEach(function () {
this.request.callsArgWith(
1,
new Error('something went wrong'),
null,
null
)
this.handler.reopenThread(
this.project_id,
this.doc_id,
this.thread_id,
this.user_id,
this.callback
)
})
it('should return an error to the callback', function () {
this.callback
.calledWith(sinon.match.instanceOf(Error))
.should.equal(true)
})
})
describe('when the document updater returns a failure error code', function () {
beforeEach(function () {
this.request.callsArgWith(1, null, { statusCode: 500 }, '')
this.handler.reopenThread(
this.project_id,
this.doc_id,
this.thread_id,
this.user_id,
this.callback
)
})
it('should return the callback with an error', function () {
this.callback
.calledWith(
sinon.match
.instanceOf(Error)
.and(
sinon.match.has(
'message',
'document updater returned a failure status code: 500'
)
)
)
.should.equal(true)
})
})
})
describe('updateProjectStructure ', function () {
beforeEach(function () {
this.user_id = 1234