@@ -39,6 +39,7 @@ export interface Props { | |||
branchName?: string; | |||
issueKey: string; | |||
projectKey: string; | |||
pullRequestID?: string; | |||
} | |||
interface State { | |||
@@ -62,7 +63,12 @@ const showError = () => | |||
const showSuccess = () => addGlobalSuccessMessage(translate('issues.open_in_ide.success')); | |||
export function IssueOpenInIdeButton({ branchName, issueKey, projectKey }: Readonly<Props>) { | |||
export function IssueOpenInIdeButton({ | |||
branchName, | |||
issueKey, | |||
projectKey, | |||
pullRequestID, | |||
}: Readonly<Props>) { | |||
const [state, setState] = React.useState<State>({ ides: [], mounted: false }); | |||
React.useEffect(() => { | |||
@@ -83,7 +89,7 @@ export function IssueOpenInIdeButton({ branchName, issueKey, projectKey }: Reado | |||
const openIssue = (ide: Ide) => { | |||
setState({ ...state, ides: [] }); | |||
return openSonarLintIssue(ide.port, projectKey, issueKey, branchName) | |||
return openSonarLintIssue(ide.port, projectKey, issueKey, branchName, pullRequestID) | |||
.then(showSuccess) | |||
.catch(showError) | |||
.finally(cleanState); |
@@ -118,6 +118,7 @@ it('handles button click with one ide found', async () => { | |||
MOCK_PROJECT_KEY, | |||
MOCK_ISSUE_KEY, | |||
undefined, | |||
undefined, | |||
); | |||
expect(addGlobalSuccessMessage).toHaveBeenCalledWith('issues.open_in_ide.success'); | |||
@@ -163,6 +164,7 @@ it('handles button click with several ides found', async () => { | |||
MOCK_PROJECT_KEY, | |||
MOCK_ISSUE_KEY, | |||
undefined, | |||
undefined, | |||
); | |||
expect(addGlobalSuccessMessage).toHaveBeenCalledWith('issues.open_in_ide.success'); |
@@ -90,16 +90,16 @@ export function IssueSourceViewerHeader(props: Readonly<Props>) { | |||
border-bottom: none; | |||
`; | |||
const branchName = React.useMemo(() => { | |||
const [branchName, pullRequestID] = React.useMemo(() => { | |||
if (isBranch(branchLike)) { | |||
return branchLike.name; | |||
return [branchLike.name, undefined]; | |||
} | |||
if (isPullRequest(branchLike)) { | |||
return branchLike.branch; | |||
return [branchLike.branch, branchLike.key]; | |||
} | |||
return undefined; // should never end up here, but needed for consistent returns | |||
return [undefined, undefined]; // should never end up here, but needed for consistent returns | |||
}, [branchLike]); | |||
return ( | |||
@@ -163,7 +163,12 @@ export function IssueSourceViewerHeader(props: Readonly<Props>) { | |||
</div> | |||
{!isProjectRoot && isLoggedIn(currentUser) && ( | |||
<IssueOpenInIdeButton branchName={branchName} issueKey={issueKey} projectKey={project} /> | |||
<IssueOpenInIdeButton | |||
branchName={branchName} | |||
issueKey={issueKey} | |||
projectKey={project} | |||
pullRequestID={pullRequestID} | |||
/> | |||
)} | |||
{!isProjectRoot && measures.issues !== undefined && ( |
@@ -96,6 +96,7 @@ describe('openHotspot', () => { | |||
describe('openIssue', () => { | |||
it('should send the correct request to the IDE to open an issue', async () => { | |||
let branchName: string | undefined = undefined; | |||
let pullRequestID: string | undefined = undefined; | |||
const issueKey = 'my-issue-key'; | |||
const resp = new Response(); | |||
@@ -108,6 +109,8 @@ describe('openIssue', () => { | |||
expect(calledUrl.searchParams.get('issue')).toStrictEqual(issueKey); | |||
// eslint-disable-next-line jest/no-conditional-in-test | |||
expect(calledUrl.searchParams.get('branch') ?? undefined).toStrictEqual(branchName); | |||
// eslint-disable-next-line jest/no-conditional-in-test | |||
expect(calledUrl.searchParams.get('pullRequest') ?? undefined).toStrictEqual(pullRequestID); | |||
} catch (error) { | |||
return Promise.reject(error); | |||
} | |||
@@ -124,6 +127,18 @@ describe('openIssue', () => { | |||
result = await openIssue(SONARLINT_PORT_START, PROJECT_KEY, issueKey, branchName); | |||
expect(result).toBe(resp); | |||
pullRequestID = 'pr-1'; | |||
result = await openIssue( | |||
SONARLINT_PORT_START, | |||
PROJECT_KEY, | |||
issueKey, | |||
branchName, | |||
pullRequestID, | |||
); | |||
expect(result).toBe(resp); | |||
}); | |||
}); | |||
@@ -60,6 +60,7 @@ export function openIssue( | |||
projectKey: string, | |||
issueKey: string, | |||
branchName?: string, | |||
pullRequestID?: string, | |||
) { | |||
const showUrl = new URL(buildSonarLintEndpoint(calledPort, '/issues/show')); | |||
@@ -71,6 +72,10 @@ export function openIssue( | |||
showUrl.searchParams.set('branch', branchName); | |||
} | |||
if (pullRequestID !== undefined) { | |||
showUrl.searchParams.set('pullRequest', pullRequestID); | |||
} | |||
return fetch(showUrl.toString()).then((response: Response) => checkStatus(response, true)); | |||
} | |||