Files
orca/src/shared/work-item-reference.test.ts
T
Jinjing c99095b1e8 Naming usage ui copy (#8357)
* fix: work-item naming, usage % rounding, and terminal/delete copy

Address prod-release-scan P2s:

- #8238: recognize Bitbucket Server (/projects|users/.../repos/.../pull-requests/N)
  and Azure DevOps (/_git/REPO/pullrequest/N) PR URL shapes in
  work-item-reference, alongside Bitbucket Cloud; graceful fallback preserved.

- #7574: getDisplayedUsagePercentage now rounds the used value before taking the
  `remaining` complement, so the compact status bar (raw usedPercent) and tooltip
  (pre-rounded clampUsedPercent) can no longer disagree by 1% at a .5 fraction.
  clampUsedPercent moves to the shared module as the single rounding source.

- #7459: mixed remote+local batch delete confirm no longer claims the whole
  batch is a permanent "remote host" delete — it now states remote items are
  permanent while local items move to the Trash/Recycle Bin.

- #8322: right-click-to-paste settings copy is platform-aware — "Control-click"
  on macOS, "Ctrl+right-click" on Windows/Linux — matching the ctrlKey gate.

Localization catalog synced (also picks up pre-existing UsagePercentageDisplayChangeNotice drift).

* Fix NaN% usage bar and label for non-finite provider values

Non-finite usedPercent inputs (NaN/Infinity) propagated through Math.round/min/max into the CSS bar width (`NaN%`) and displayed copy. clampUsedPercent now short-circuits to 0 in that case, with a test covering the divergence from getDisplayedUsagePercentage for the 'remaining' case.
2026-07-11 22:37:26 -07:00

128 lines
4.8 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { extractWorkIdentifier, stripWorkIdentifierEcho } from './work-item-reference'
describe('extractWorkIdentifier', () => {
it('reads a GitHub pull request URL', () => {
expect(extractWorkIdentifier('Review https://github.com/EveryInc/plugin/pull/1033')).toEqual({
label: 'PR 1033',
tokens: ['pr', '1033']
})
})
it('reads a Bitbucket Cloud pull-requests URL', () => {
expect(
extractWorkIdentifier('Look at https://bitbucket.org/team/repo/pull-requests/77')?.label
).toBe('PR 77')
})
it('reads a Bitbucket Server pull-requests URL', () => {
expect(
extractWorkIdentifier(
'Review https://bitbucket.example.com/projects/ENG/repos/orca/pull-requests/1288'
)
).toEqual({ label: 'PR 1288', tokens: ['pr', '1288'] })
// Personal (fork) repos live under /users instead of /projects.
expect(
extractWorkIdentifier(
'see https://bitbucket.example.com/users/jane/repos/orca/pull-requests/9/overview'
)?.label
).toBe('PR 9')
})
it('reads Azure DevOps pull request URLs (dev.azure.com and visualstudio.com)', () => {
expect(
extractWorkIdentifier('Look at https://dev.azure.com/contoso/Orca/_git/orca/pullrequest/4521')
).toEqual({ label: 'PR 4521', tokens: ['pr', '4521'] })
expect(
extractWorkIdentifier(
'https://contoso.visualstudio.com/Orca/_git/orca/pullrequest/4521?_a=files'
)?.label
).toBe('PR 4521')
})
it('reads a GitLab merge request URL as MR, and a work_items URL as an issue', () => {
expect(extractWorkIdentifier('Check https://gitlab.com/group/app/-/merge_requests/42')).toEqual(
{ label: 'MR 42', tokens: ['mr', '42'] }
)
expect(extractWorkIdentifier('https://gitlab.example.com/g/p/-/work_items/9')?.label).toBe(
'Issue 9'
)
})
it('reads an issue URL', () => {
expect(extractWorkIdentifier('Fix https://github.com/o/r/issues/88')?.label).toBe('Issue 88')
})
it('ignores URLs whose path only resembles a work item (no owner/repo, wrong host shape)', () => {
// A CDN asset path contains `/pull/2023` but is not a pull request.
expect(
extractWorkIdentifier('Load https://cdn.vendor.com/assets/pull/2023/data.json')
).toBeNull()
// No trailing number after the item segment.
expect(extractWorkIdentifier('see https://github.com/o/r/pull/notanumber')).toBeNull()
})
it('tolerates trailing punctuation around a URL', () => {
expect(extractWorkIdentifier('(see https://github.com/o/r/pull/5).')?.label).toBe('PR 5')
})
it('reads a URL wrapped in markdown emphasis (trailing underscore/asterisk)', () => {
expect(extractWorkIdentifier('Review _https://github.com/o/r/pull/5_ now')?.label).toBe('PR 5')
expect(extractWorkIdentifier('Review **https://github.com/o/r/pull/1094**')?.label).toBe(
'PR 1094'
)
})
it('reads textual references', () => {
expect(extractWorkIdentifier('please review PR #1094')?.label).toBe('PR 1094')
expect(extractWorkIdentifier('triage pull request 500')?.label).toBe('PR 500')
expect(extractWorkIdentifier('reproduce issue 12')?.label).toBe('Issue 12')
expect(extractWorkIdentifier('handle merge request !9')?.label).toBe('MR 9')
})
it('reads a namespaced ticket id bare', () => {
expect(extractWorkIdentifier('implement ENG-456 login flow')).toEqual({
label: 'ENG-456',
tokens: ['eng', '456']
})
})
it('does not treat standards, ciphers, or encodings as tickets', () => {
expect(extractWorkIdentifier('implement SHA-256 hashing')).toBeNull()
expect(extractWorkIdentifier('parse UTF-8 input')).toBeNull()
expect(extractWorkIdentifier('handle ISO-8601 dates')).toBeNull()
})
it('skips a denylisted prefix but still finds a real key after it', () => {
expect(extractWorkIdentifier('encrypt with AES-256 for ticket ENG-99')?.label).toBe('ENG-99')
})
it('prefers a provider URL over an incidental ticket-shaped token', () => {
expect(
extractWorkIdentifier('per RFC-2616 notes, review https://github.com/o/r/pull/7')?.label
).toBe('PR 7')
})
it('falls back to a bare number, then to null', () => {
expect(extractWorkIdentifier('look at #321 when free')?.label).toBe('#321')
expect(extractWorkIdentifier('add a dark mode toggle to settings')).toBeNull()
})
})
describe('stripWorkIdentifierEcho', () => {
it('removes the identifier tokens from a description', () => {
expect(
stripWorkIdentifierEcho('Review this community PR', {
label: 'PR 1094',
tokens: ['pr', '1094']
})
).toBe('Review this community')
})
it('removes a ticket key echoed in the description', () => {
expect(
stripWorkIdentifierEcho('Fix ENG 456 crash', { label: 'ENG-456', tokens: ['eng', '456'] })
).toBe('Fix crash')
})
})