mirror of
https://github.com/stablyai/orca.git
synced 2026-09-24 16:02:41 +00:00
fix: open github prs in checks tab (#2197)
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
import React from 'react'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { HostedReviewInfo } from '../../../../shared/hosted-review'
|
||||
import { HostedReviewHeaderLink } from './SourceControl'
|
||||
|
||||
function makeReview(overrides: Partial<HostedReviewInfo> = {}): HostedReviewInfo {
|
||||
return {
|
||||
provider: 'github',
|
||||
number: 2192,
|
||||
title: 'Open PR in checks',
|
||||
state: 'open',
|
||||
url: 'https://github.com/stablyai/orca/pull/2192',
|
||||
status: 'pending',
|
||||
updatedAt: '2026-05-17T00:00:00Z',
|
||||
mergeable: 'UNKNOWN',
|
||||
...overrides
|
||||
}
|
||||
}
|
||||
|
||||
type MinimalClickEvent = Pick<React.MouseEvent, 'stopPropagation'>
|
||||
|
||||
describe('HostedReviewHeaderLink', () => {
|
||||
it('opens GitHub PRs in the Checks tab instead of rendering an external link', () => {
|
||||
const onOpenGitHubPRInChecks = vi.fn()
|
||||
const element = HostedReviewHeaderLink({
|
||||
review: makeReview(),
|
||||
onOpenGitHubPRInChecks
|
||||
})
|
||||
const markup = renderToStaticMarkup(element)
|
||||
|
||||
expect(markup).toContain('<button')
|
||||
expect(markup).toContain('PR #2192')
|
||||
expect(markup).not.toContain('href=')
|
||||
expect(markup).not.toContain('target="_blank"')
|
||||
|
||||
const stopPropagation = vi.fn()
|
||||
;(element.props.onClick as (event: MinimalClickEvent) => void)({ stopPropagation })
|
||||
expect(stopPropagation).toHaveBeenCalledTimes(1)
|
||||
expect(onOpenGitHubPRInChecks).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('keeps non-GitHub reviews as external hosted-review links', () => {
|
||||
const markup = renderToStaticMarkup(
|
||||
<HostedReviewHeaderLink
|
||||
review={makeReview({
|
||||
provider: 'gitlab',
|
||||
number: 31,
|
||||
url: 'https://gitlab.com/acme/widgets/-/merge_requests/31'
|
||||
})}
|
||||
onOpenGitHubPRInChecks={vi.fn()}
|
||||
/>
|
||||
)
|
||||
|
||||
expect(markup).toContain('<a')
|
||||
expect(markup).toContain('href="https://gitlab.com/acme/widgets/-/merge_requests/31"')
|
||||
expect(markup).toContain('target="_blank"')
|
||||
expect(markup).toContain('MR #31')
|
||||
})
|
||||
})
|
||||
@@ -304,6 +304,51 @@ function HostedReviewIcon({
|
||||
return <Icon className={cn(className, hostedReviewStateClass(review))} />
|
||||
}
|
||||
|
||||
function hostedReviewLabel(review: HostedReviewInfo): string {
|
||||
return `${review.provider === 'gitlab' ? 'MR' : 'PR'} #${review.number}`
|
||||
}
|
||||
|
||||
export function HostedReviewHeaderLink({
|
||||
review,
|
||||
onOpenGitHubPRInChecks
|
||||
}: {
|
||||
review: HostedReviewInfo
|
||||
onOpenGitHubPRInChecks: () => void
|
||||
}): React.JSX.Element {
|
||||
const label = hostedReviewLabel(review)
|
||||
const className =
|
||||
'shrink-0 border-0 bg-transparent p-0 text-left font-medium leading-none text-foreground opacity-80 hover:text-foreground hover:underline'
|
||||
|
||||
if (review.provider === 'github') {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={className}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
// Why: GitHub PR details already live in Orca's Checks tab; keep
|
||||
// the sidebar workflow in-app instead of opening the browser.
|
||||
onOpenGitHubPRInChecks()
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
href={review.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={className}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
function SourceControlInner(): React.JSX.Element {
|
||||
const sourceControlRef = useRef<HTMLDivElement>(null)
|
||||
// Why: React setState is async, so a rapid double-click on the Commit
|
||||
@@ -1285,6 +1330,11 @@ function SourceControlInner(): React.JSX.Element {
|
||||
]
|
||||
)
|
||||
|
||||
const openHostedGitHubPRInChecks = useCallback(() => {
|
||||
setRightSidebarOpen(true)
|
||||
setRightSidebarTab('checks')
|
||||
}, [setRightSidebarOpen, setRightSidebarTab])
|
||||
|
||||
const hasUnstagedChanges = grouped.unstaged.length > 0 || grouped.untracked.length > 0
|
||||
const hasPartiallyStagedChanges = useMemo(() => {
|
||||
if (grouped.staged.length === 0 || grouped.unstaged.length === 0) {
|
||||
@@ -2434,15 +2484,10 @@ function SourceControlInner(): React.JSX.Element {
|
||||
{hostedReview && (
|
||||
<div className="ml-auto mb-1.5 flex items-center gap-1.5 min-w-0 text-[11.5px] leading-none">
|
||||
<HostedReviewIcon review={hostedReview} className="size-3 shrink-0" />
|
||||
<a
|
||||
href={hostedReview.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-foreground opacity-80 font-medium shrink-0 hover:text-foreground hover:underline"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{hostedReview.provider === 'gitlab' ? 'MR' : 'PR'} #{hostedReview.number}
|
||||
</a>
|
||||
<HostedReviewHeaderLink
|
||||
review={hostedReview}
|
||||
onOpenGitHubPRInChecks={openHostedGitHubPRInChecks}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user