mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
262 lines
8.4 KiB
TypeScript
262 lines
8.4 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
getWorkspaceReferenceIdentity,
|
|
matchesWorkspaceReferenceQuery,
|
|
parseWorkspaceReferenceQuery,
|
|
parseWorkspaceReferenceUrl
|
|
} from './workspace-reference-identity'
|
|
import type { WorkspaceAttachment } from './worktree/types'
|
|
|
|
const identity = (url: string): string =>
|
|
getWorkspaceReferenceIdentity(parseWorkspaceReferenceUrl(url))
|
|
|
|
describe('reference URLs', () => {
|
|
it.each([
|
|
[
|
|
'https://github.com/ACME/api/pull/5123/files?x=1#note',
|
|
'github',
|
|
'pr',
|
|
5123,
|
|
'https://github.com/ACME/api/pull/5123'
|
|
],
|
|
[
|
|
'https://github.com/acme/api/issues/42',
|
|
'github',
|
|
'issue',
|
|
42,
|
|
'https://github.com/acme/api/issues/42'
|
|
],
|
|
[
|
|
'https://git.example:8443/group/subgroup/api/-/merge_requests/42/diffs',
|
|
'gitlab',
|
|
'mr',
|
|
42,
|
|
'https://git.example:8443/group/subgroup/api/-/merge_requests/42'
|
|
],
|
|
[
|
|
'https://gitlab.com/acme/api/-/issues/42',
|
|
'gitlab',
|
|
'issue',
|
|
42,
|
|
'https://gitlab.com/acme/api/-/issues/42'
|
|
],
|
|
[
|
|
'https://codeberg.org/acme/api/pulls/42',
|
|
'gitea',
|
|
'pr',
|
|
42,
|
|
'https://codeberg.org/acme/api/pulls/42'
|
|
],
|
|
[
|
|
'https://codeberg.org/acme/api/issues/42',
|
|
'gitea',
|
|
'issue',
|
|
42,
|
|
'https://codeberg.org/acme/api/issues/42'
|
|
],
|
|
[
|
|
'https://bitbucket.org/acme/api/pull-requests/42',
|
|
'bitbucket',
|
|
'pr',
|
|
42,
|
|
'https://bitbucket.org/acme/api/pull-requests/42'
|
|
],
|
|
[
|
|
'https://git.example/projects/ACME/repos/api/pull-requests/42/overview',
|
|
'bitbucket',
|
|
'pr',
|
|
42,
|
|
'https://git.example/projects/ACME/repos/api/pull-requests/42'
|
|
],
|
|
[
|
|
'https://dev.azure.com/acme/project/_git/api/pullrequest/42',
|
|
'azure-devops',
|
|
'pr',
|
|
42,
|
|
'https://dev.azure.com/acme/project/_git/api/pullrequest/42'
|
|
],
|
|
[
|
|
'https://linear.app/acme/issue/sta-1234/fix-it',
|
|
'linear',
|
|
'issue',
|
|
0,
|
|
'https://linear.app/acme/issue/STA-1234'
|
|
],
|
|
[
|
|
'https://jira.example:8443/jira/browse/sta-1234?selectedItem=x',
|
|
'jira',
|
|
'issue',
|
|
0,
|
|
'https://jira.example:8443/jira/browse/STA-1234'
|
|
]
|
|
])('parses %s without provider calls', (input, provider, type, number, url) => {
|
|
expect(parseWorkspaceReferenceUrl(input)).toMatchObject({ provider, type, number, url })
|
|
expect(parseWorkspaceReferenceUrl(input).origins).toBeUndefined()
|
|
})
|
|
|
|
it.each([
|
|
'5123',
|
|
'github:pr:5123',
|
|
'acme/api#5123',
|
|
'file://github.com/acme/api/pull/42',
|
|
'https://user:password@github.com/acme/api/pull/42',
|
|
'https://github.com/acme/api/pull/0',
|
|
'https://github.com/acme/api/pull/9007199254740992',
|
|
'https://github.com/acme/api/pulls/42',
|
|
'https://codeberg.org/acme/api/pull/42',
|
|
'https://github.com/acme/api/-/merge_requests/42',
|
|
'https://github.com/browse/STA-1234',
|
|
'https://unknown.example/acme/api/issues/42',
|
|
'https://linear.app/acme/issue/invalid'
|
|
])('rejects ambiguous or invalid input %s', (input) => {
|
|
expect(() => parseWorkspaceReferenceUrl(input)).toThrow()
|
|
})
|
|
})
|
|
|
|
describe('reference identity', () => {
|
|
it('ignores fragments, views, leading zeros and GitHub casing', () => {
|
|
expect(identity('https://github.com/ACME/Api/pull/0042/files#diff')).toBe(
|
|
identity('https://github.com/acme/api/pull/42')
|
|
)
|
|
})
|
|
|
|
it.each([
|
|
'https://github.com/ACME/Api/pull/42',
|
|
'https://git.example/Root/Group/Api/-/merge_requests/42',
|
|
'https://codeberg.org/Acme/Api/pulls/42'
|
|
])('stores %s with its original path casing', (url) => {
|
|
expect(parseWorkspaceReferenceUrl(url).url).toBe(url)
|
|
expect(identity(url)).toBe(identity(url.toLowerCase()))
|
|
})
|
|
|
|
it('does not read git-host /browse/ paths as Jira issues', () => {
|
|
expect(
|
|
parseWorkspaceReferenceUrl('https://git.example/acme/api/issues/42', 'github').provider
|
|
).toBe('github')
|
|
expect(() =>
|
|
parseWorkspaceReferenceUrl('https://git.example/acme/api/browse/STA-1', 'github')
|
|
).toThrow()
|
|
expect(() => parseWorkspaceReferenceUrl('https://github.com/acme/browse/STA-1')).toThrow()
|
|
expect(() =>
|
|
parseWorkspaceReferenceUrl('https://git.example/projects/P/repos/api/browse/STA-1')
|
|
).toThrow()
|
|
})
|
|
|
|
it.each([
|
|
['https://github.com/acme/api/pull/42', 'https://github.com/acme/other/pull/42'],
|
|
['https://github.com/acme/api/pull/42', 'https://github.com/acme/api/issues/42'],
|
|
['https://git.example:8443/acme/api/pull/42', 'https://git.example:9443/acme/api/pull/42'],
|
|
['https://linear.app/acme/issue/STA-1234', 'https://linear.app/other/issue/STA-1234'],
|
|
['https://jira.example/jira/browse/STA-1234', 'https://jira.example/other/browse/STA-1234'],
|
|
[
|
|
'https://jira.example:8443/jira/browse/STA-1234',
|
|
'https://jira.example:9443/jira/browse/STA-1234'
|
|
],
|
|
['https://git.example/a/api/-/issues/42', 'https://other.example/a/api/-/issues/42']
|
|
])('keeps distinct sources separate: %s vs %s', (a, b) => {
|
|
expect(identity(a)).not.toBe(identity(b))
|
|
})
|
|
|
|
it('matches URL-less entries only when stored provider metadata proves the source', () => {
|
|
const item: WorkspaceAttachment = {
|
|
provider: 'github',
|
|
type: 'pr',
|
|
number: 42,
|
|
taskSourceContext: {
|
|
kind: 'task-source',
|
|
provider: 'github',
|
|
projectId: 'local-project',
|
|
hostId: 'local',
|
|
providerIdentity: { provider: 'github', owner: 'acme', repo: 'api' }
|
|
}
|
|
}
|
|
expect(getWorkspaceReferenceIdentity(item)).toBe(
|
|
identity('https://github.com/acme/api/pull/42')
|
|
)
|
|
expect(getWorkspaceReferenceIdentity({ ...item, taskSourceContext: undefined })).not.toBe(
|
|
getWorkspaceReferenceIdentity(item)
|
|
)
|
|
})
|
|
|
|
it('retains source boundaries in legacy opaque keys', () => {
|
|
const item: WorkspaceAttachment = {
|
|
provider: 'github',
|
|
type: 'pr',
|
|
number: 42,
|
|
repoId: 'repo-a'
|
|
}
|
|
expect(getWorkspaceReferenceIdentity(item)).not.toBe(
|
|
getWorkspaceReferenceIdentity({ ...item, repoId: 'repo-b' })
|
|
)
|
|
})
|
|
|
|
it('does not trust URLs that contradict stored provider or reference ID', () => {
|
|
const parsed = parseWorkspaceReferenceUrl('https://github.com/acme/api/pull/42')
|
|
expect(getWorkspaceReferenceIdentity({ ...parsed, number: 43 })).not.toBe(
|
|
getWorkspaceReferenceIdentity(parsed)
|
|
)
|
|
expect(getWorkspaceReferenceIdentity({ ...parsed, provider: 'gitea' })).not.toBe(
|
|
getWorkspaceReferenceIdentity(parsed)
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('reference queries', () => {
|
|
it('finds a native issue key across every source', () => {
|
|
const query = parseWorkspaceReferenceQuery('sta-1234')
|
|
for (const url of [
|
|
'https://linear.app/acme/issue/STA-1234',
|
|
'https://linear.app/other/issue/STA-1234',
|
|
'https://jira.example/browse/STA-1234'
|
|
]) {
|
|
expect(matchesWorkspaceReferenceQuery(parseWorkspaceReferenceUrl(url), query)).toBe(true)
|
|
}
|
|
expect(
|
|
matchesWorkspaceReferenceQuery(
|
|
parseWorkspaceReferenceUrl('https://linear.app/acme/issue/STA-2'),
|
|
query
|
|
)
|
|
).toBe(false)
|
|
})
|
|
|
|
it('uses exact source identity for a URL query', () => {
|
|
const query = parseWorkspaceReferenceQuery('https://linear.app/acme/issue/STA-1234')
|
|
expect(
|
|
matchesWorkspaceReferenceQuery(
|
|
parseWorkspaceReferenceUrl('https://linear.app/acme/issue/STA-1234/title'),
|
|
query
|
|
)
|
|
).toBe(true)
|
|
expect(
|
|
matchesWorkspaceReferenceQuery(
|
|
parseWorkspaceReferenceUrl('https://linear.app/other/issue/STA-1234'),
|
|
query
|
|
)
|
|
).toBe(false)
|
|
})
|
|
|
|
it('finds a self-hosted issue URL whose provider the URL alone cannot prove', () => {
|
|
const url = 'https://git.example/Acme/Api/issues/42'
|
|
expect(() => parseWorkspaceReferenceUrl(url)).toThrow()
|
|
const query = parseWorkspaceReferenceQuery(url)
|
|
for (const provider of ['github', 'gitea'] as const) {
|
|
expect(matchesWorkspaceReferenceQuery(parseWorkspaceReferenceUrl(url, provider), query)).toBe(
|
|
true
|
|
)
|
|
}
|
|
expect(
|
|
matchesWorkspaceReferenceQuery(
|
|
parseWorkspaceReferenceUrl('https://git.example/acme/api/issues/43', 'gitea'),
|
|
query
|
|
)
|
|
).toBe(false)
|
|
expect(() =>
|
|
parseWorkspaceReferenceQuery('https://git.example/acme/api/pull-requests/42')
|
|
).toThrow()
|
|
})
|
|
|
|
it.each(['1234', '#1234', 'github:pr:1234'])('rejects %s', (query) => {
|
|
expect(() => parseWorkspaceReferenceQuery(query)).toThrow()
|
|
})
|
|
})
|