diff --git a/src/renderer/src/components/status-bar/hosted-review-label.test.ts b/src/renderer/src/components/status-bar/hosted-review-label.test.ts new file mode 100644 index 00000000000..558245b330f --- /dev/null +++ b/src/renderer/src/components/status-bar/hosted-review-label.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'vitest' +import { formatHostedReviewLabel } from './hosted-review-label' + +describe('formatHostedReviewLabel', () => { + it('labels a GitLab review as "MR !N" — not "PR #N"', () => { + expect( + formatHostedReviewLabel({ provider: 'gitlab', number: 5, state: 'open', status: 'none' }) + ).toBe('MR !5 Open') + }) + + it.each([ + ['github' as const, 'PR #7 Open'], + ['azure-devops' as const, 'PR #7 Open'], + ['gitea' as const, 'PR #7 Open'], + ['bitbucket' as const, 'PR #7 Open'] + ])('uses the "PR #" form and correct copy for %s', (provider, expected) => { + expect(formatHostedReviewLabel({ provider, number: 7, state: 'open', status: 'none' })).toBe( + expected + ) + }) + + it('keeps the GitHub label for older cached reviews without a provider', () => { + expect(formatHostedReviewLabel({ number: 42, state: 'open', status: 'none' })).toBe( + 'PR #42 Open' + ) + }) + + it('appends a non-"none" status suffix', () => { + expect( + formatHostedReviewLabel({ provider: 'gitlab', number: 5, state: 'open', status: 'draft' }) + ).toBe('MR !5 Open, draft') + }) + + it('omits the suffix when status is "none" or empty', () => { + expect( + formatHostedReviewLabel({ provider: 'github', number: 5, state: 'closed', status: '' }) + ).toBe('PR #5 Closed') + }) +}) diff --git a/src/renderer/src/components/status-bar/hosted-review-label.ts b/src/renderer/src/components/status-bar/hosted-review-label.ts new file mode 100644 index 00000000000..90ee7dd7726 --- /dev/null +++ b/src/renderer/src/components/status-bar/hosted-review-label.ts @@ -0,0 +1,23 @@ +import type { HostedReviewProvider } from '../../../../shared/hosted-review' +import { + localizedHostedReviewCopy, + resolveSupportedHostedReviewCopyProvider +} from '@/i18n/hosted-review-localized-copy' + +function formatReviewState(state: string): string { + return state.charAt(0).toUpperCase() + state.slice(1) +} + +export function formatHostedReviewLabel(review: { + provider?: HostedReviewProvider + number: number + state: string + status: string +}): string { + const { shortLabel } = localizedHostedReviewCopy( + resolveSupportedHostedReviewCopyProvider(review.provider) + ) + const symbol = review.provider === 'gitlab' ? '!' : '#' + const statusSuffix = review.status && review.status !== 'none' ? `, ${review.status}` : '' + return `${shortLabel} ${symbol}${review.number} ${formatReviewState(review.state)}${statusSuffix}` +} diff --git a/src/renderer/src/components/status-bar/workspace-space-decision-details.ts b/src/renderer/src/components/status-bar/workspace-space-decision-details.ts index b85df924934..1a4bac8b572 100644 --- a/src/renderer/src/components/status-bar/workspace-space-decision-details.ts +++ b/src/renderer/src/components/status-bar/workspace-space-decision-details.ts @@ -16,6 +16,7 @@ import { issueCacheKey as getIssueCacheKey } from '../../store/github/cache-iden import { countWorkspaceSpaceActiveAgents } from './workspace-space-presentation' import { getWorkspaceSpaceWorktreeIdentity } from './workspace-space-delete-selection' import { getWorkspaceSpaceBranchLabel } from './workspace-space-format' +import { formatHostedReviewLabel } from './hosted-review-label' export type WorkspaceDecisionDetails = { isActive: boolean @@ -78,10 +79,6 @@ export function pluralize(count: number, singular: string, plural = `${singular} return `${count} ${count === 1 ? singular : plural}` } -function formatReviewState(state: string): string { - return state.charAt(0).toUpperCase() + state.slice(1) -} - function countLiveTerminals( tabs: readonly TerminalTab[], ptyIdsByTabId: Record @@ -156,9 +153,7 @@ export function getWorkspaceDecisionDetails( const linkedPR = workspaceRecord?.linkedPR ?? null const reviewLabel = hostedReview !== undefined && hostedReview !== null - ? `PR #${hostedReview.number} ${formatReviewState(hostedReview.state)}${ - hostedReview.status && hostedReview.status !== 'none' ? `, ${hostedReview.status}` : '' - }` + ? formatHostedReviewLabel(hostedReview) : linkedPR ? `PR #${linkedPR}` : null diff --git a/src/renderer/src/components/status-bar/workspace-space-presentation.test.ts b/src/renderer/src/components/status-bar/workspace-space-presentation.test.ts index c9b212a2320..8e5b7df9d21 100644 --- a/src/renderer/src/components/status-bar/workspace-space-presentation.test.ts +++ b/src/renderer/src/components/status-bar/workspace-space-presentation.test.ts @@ -564,7 +564,7 @@ describe('workspace space presentation helpers', () => { ) expect(explicit.reviewLabel).toBe('PR #12 Open, success') - expect(gitLab.reviewLabel).toBe('PR #12 Open, success') + expect(gitLab.reviewLabel).toBe('MR !12 Open, success') }) it('counts migration-unsupported agent entries by worktree id', () => {