Files
orca/src/shared/issue-link-input.test.ts
T
Jinjing 9e2c7357da fix(sidebar): respect one-issue-per-workspace rule conditionally
Only clear displaced issue links when they actually existed, preventing
unnecessary Linear keys in GitHub-only workspaces. Skip comment updates
when unchanged to avoid workspace reordering. Add accessibility to
displacement messages and improve folder workspace error handling.
2026-08-03 20:15:08 -07:00

119 lines
4.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { getIssueLinkProviderFromUrl, parseIssueLinkInput } from './issue-link-input'
describe('getIssueLinkProviderFromUrl', () => {
it('detects GitHub issue URLs', () => {
expect(getIssueLinkProviderFromUrl('https://github.com/o/r/issues/12')).toBe('github')
})
it('does not flip the provider for a GitHub pull URL', () => {
expect(getIssueLinkProviderFromUrl('https://github.com/o/r/pull/12')).toBeNull()
})
it('detects Linear issue URLs with and without a slug', () => {
expect(getIssueLinkProviderFromUrl('https://linear.app/acme/issue/STA-335')).toBe('linear')
expect(getIssueLinkProviderFromUrl('https://linear.app/acme/issue/STA-335/some-slug')).toBe(
'linear'
)
})
it('ignores non-issue paths on the Linear host', () => {
expect(getIssueLinkProviderFromUrl('https://linear.app/acme/team/ENG/all')).toBeNull()
})
it('rejects hosts that merely contain linear.app', () => {
expect(getIssueLinkProviderFromUrl('https://linear.app.evil.com/acme/issue/STA-335')).toBeNull()
})
// Linear and Jira issue-key shapes are byte-identical, so a bare key must
// never override the user's explicit provider choice.
it('is not decisive for bare issue keys', () => {
expect(getIssueLinkProviderFromUrl('STA-335')).toBeNull()
expect(getIssueLinkProviderFromUrl(' STA-335 ')).toBeNull()
})
it('is not decisive for bare numbers', () => {
expect(getIssueLinkProviderFromUrl('1234')).toBeNull()
expect(getIssueLinkProviderFromUrl('#1234')).toBeNull()
})
it('returns null for empty input', () => {
expect(getIssueLinkProviderFromUrl('')).toBeNull()
expect(getIssueLinkProviderFromUrl(' ')).toBeNull()
})
})
describe('parseIssueLinkInput', () => {
describe('github provider', () => {
it('accepts bare and hash-prefixed numbers', () => {
expect(parseIssueLinkInput('12', 'github')).toEqual({ provider: 'github', number: 12 })
expect(parseIssueLinkInput('#12', 'github')).toEqual({ provider: 'github', number: 12 })
})
it('accepts issue URLs', () => {
expect(parseIssueLinkInput('https://github.com/o/r/issues/12', 'github')).toEqual({
provider: 'github',
number: 12
})
})
it('rejects pull URLs', () => {
expect(parseIssueLinkInput('https://github.com/o/r/pull/12', 'github')).toBeNull()
})
it('rejects non-positive numbers and junk', () => {
expect(parseIssueLinkInput('0', 'github')).toBeNull()
expect(parseIssueLinkInput('-1', 'github')).toBeNull()
expect(parseIssueLinkInput('not an issue', 'github')).toBeNull()
expect(parseIssueLinkInput(' ', 'github')).toBeNull()
})
it('rejects Linear identifiers', () => {
expect(parseIssueLinkInput('STA-335', 'github')).toBeNull()
})
// Past the safe-integer range every digit string parses to the same float,
// so an unbounded parse would link an arbitrary issue number.
it('rejects numbers beyond the safe-integer range', () => {
expect(parseIssueLinkInput('9'.repeat(400), 'github')).toBeNull()
})
})
describe('linear provider', () => {
it('accepts bare identifiers and normalizes case', () => {
expect(parseIssueLinkInput('STA-335', 'linear')).toEqual({
provider: 'linear',
identifier: 'STA-335'
})
expect(parseIssueLinkInput('sta-335', 'linear')).toEqual({
provider: 'linear',
identifier: 'STA-335'
})
})
it('omits the organization key for bare identifiers', () => {
expect(parseIssueLinkInput('STA-335', 'linear')).not.toHaveProperty('organizationUrlKey')
})
it('accepts issue URLs and returns the organization key', () => {
expect(
parseIssueLinkInput('https://linear.app/acme/issue/STA-335/some-slug', 'linear')
).toEqual({
provider: 'linear',
identifier: 'STA-335',
organizationUrlKey: 'acme'
})
})
it('rejects GitHub URLs', () => {
expect(parseIssueLinkInput('https://github.com/o/r/issues/12', 'linear')).toBeNull()
})
it('rejects junk and empty input', () => {
expect(parseIssueLinkInput('not an issue', 'linear')).toBeNull()
expect(parseIssueLinkInput(' ', 'linear')).toBeNull()
})
})
})