Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion src/format-check/scripts/format-check.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import * as gi from 'azure-devops-node-api/interfaces/GitInterfaces';
import { beforeEach, describe, expect, it } from '@jest/globals';
import { PullRequestService } from './services/pull-request-service';
import { PullRequestFileChange } from './types/pull-request-file-change';
import { getChangedFilesInPR, runFormatCheck } from "./format-check";
import { getChangedFilesInPR, runFormatCheck, updatePullRequestThreads } from "./format-check";
import { Settings } from './types/settings';
import { BaseGitApiService } from './services/base-git-api-service';
import { IGitApi } from 'azure-devops-node-api/GitApi';
Expand Down Expand Up @@ -353,4 +353,58 @@ describe('runFormatCheck', () => {
}
}
});

it('should find existing thread by file path and line number when content does not match exactly', async () => {
// Test the thread matching logic directly
const existingThreads = [
{
id: 1,
comments: [
{
content: '[DotNetFormatTask][Automated] IMPORTS: Fix imports ordering. on line 1, position 1',
}
],
threadContext: {
filePath: '/src/somefile.ts'
}
}
];

const reports = [
{
DocumentId: {
Id: randomUUID(),
ProjectId: {
Id: randomUUID()
}
},
FileName: "somefile.ts",
FilePath: "/src/somefile.ts",
FileChanges: [
{
CharNumber: 1,
DiagnosticId: "IMPORTS",
LineNumber: 1,
FormatDescription: "Fix imports ordering"
}
],
commitId: '',
changeType: gi.VersionControlChangeType.None
}
];

// Mock the necessary functions
const mockPullRequestService = {
getThreads: jest.fn().mockReturnValue(Promise.resolve(existingThreads)),
updateThread: jest.fn(),
createThread: jest.fn()
};

// Test the updatePullRequestThreads function directly
await updatePullRequestThreads(mockPullRequestService as any, reports as any);

// Verify that the existing thread was updated instead of creating a new one
expect(mockPullRequestService.updateThread).toHaveBeenCalled();
expect(mockPullRequestService.createThread).not.toHaveBeenCalled();
});
});
18 changes: 17 additions & 1 deletion src/format-check/scripts/format-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,23 @@ async function updatePullRequestThreads(
for (const change of report.FileChanges) {
const content = `${commentPreamble} ${change.DiagnosticId}: ${change.FormatDescription} on line ${change.LineNumber}, position ${change.CharNumber}`;
activeIssuesContent.push(content); // Keep track of active issues
const existingThread = existingThreads.find(thread => thread.comments?.some(comment => comment.content === content));

// First try to find existing thread by exact content match
let existingThread = existingThreads.find(thread => thread.comments?.some(comment => comment.content === content));

// If no match found by content, try to find by file path and line number
if (!existingThread) {
existingThread = existingThreads.find(thread => {
return thread.threadContext?.filePath === report.FilePath &&
thread.comments?.some(comment => {
// Check if the comment is about the same issue (same line and diagnostic)
const commentContent = comment.content || '';
return commentContent.includes(change.DiagnosticId) &&
commentContent.includes(`line ${change.LineNumber}`) &&
commentContent.includes(commentPreamble);
});
});
}

const comment = <gi.Comment>{
content: content,
Expand Down
Loading