Files
orca/src/main/runtime/rpc/methods/github.test.ts
T
2026-05-14 23:13:37 -07:00

520 lines
18 KiB
TypeScript

/* eslint-disable max-lines -- Why: runtime GitHub RPC methods share one dispatcher suite so repo-scoped and Project-scoped contract coverage cannot drift. */
import { describe, expect, it, vi } from 'vitest'
import { RpcDispatcher } from '../dispatcher'
import type { RpcRequest } from '../core'
import type { OrcaRuntimeService } from '../../orca-runtime'
import { GITHUB_METHODS } from './github'
function makeRequest(method: string, params?: unknown): RpcRequest {
return { id: 'req-1', authToken: 'tok', method, params }
}
describe('github RPC methods', () => {
it('resolves the repo slug on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getRepoSlug: vi.fn().mockResolvedValue({ owner: 'acme', repo: 'orca' })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(makeRequest('github.repoSlug', { repo: 'repo-1' }))
expect(runtime.getRepoSlug).toHaveBeenCalledWith('repo-1')
expect(response).toMatchObject({
ok: true,
result: { owner: 'acme', repo: 'orca' }
})
})
it('fetches GitHub rate limits on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getGitHubRateLimit: vi.fn().mockResolvedValue({ ok: true, snapshot: { core: {} } })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(makeRequest('github.rateLimit', { force: true }))
expect(runtime.getGitHubRateLimit).toHaveBeenCalledWith({ force: true })
expect(response).toMatchObject({ ok: true, result: { ok: true } })
})
it('lists work items on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
listRepoWorkItems: vi.fn().mockResolvedValue({ items: [] })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.listWorkItems', { repo: 'repo-1', limit: 10, query: 'is:pr' })
)
expect(runtime.listRepoWorkItems).toHaveBeenCalledWith('repo-1', 10, 'is:pr', undefined)
expect(response).toMatchObject({ ok: true, result: { items: [] } })
})
it('looks up a single work item on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getRepoWorkItem: vi.fn().mockResolvedValue({ number: 12, type: 'pr' })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.workItem', { repo: 'repo-1', number: 12, type: 'pr' })
)
expect(runtime.getRepoWorkItem).toHaveBeenCalledWith('repo-1', 12, 'pr')
expect(response).toMatchObject({ ok: true, result: { number: 12, type: 'pr' } })
})
it('looks up a single work item by explicit owner/repo on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getRepoWorkItemByOwnerRepo: vi.fn().mockResolvedValue({ number: 12, type: 'pr' })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.workItemByOwnerRepo', {
repo: 'repo-1',
owner: 'acme',
ownerRepo: 'orca',
number: 12,
type: 'pr'
})
)
expect(runtime.getRepoWorkItemByOwnerRepo).toHaveBeenCalledWith(
'repo-1',
{ owner: 'acme', repo: 'orca' },
12,
'pr'
)
expect(response).toMatchObject({ ok: true, result: { number: 12, type: 'pr' } })
})
it('fetches work item details on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getRepoWorkItemDetails: vi.fn().mockResolvedValue({ body: 'Details' })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.workItemDetails', { repo: 'repo-1', number: 12, type: 'issue' })
)
expect(runtime.getRepoWorkItemDetails).toHaveBeenCalledWith('repo-1', 12, 'issue')
expect(response).toMatchObject({ ok: true, result: { body: 'Details' } })
})
it('counts work items on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
countRepoWorkItems: vi.fn().mockResolvedValue(3)
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.countWorkItems', { repo: 'repo-1', query: 'is:open' })
)
expect(runtime.countRepoWorkItems).toHaveBeenCalledWith('repo-1', 'is:open')
expect(response).toMatchObject({ ok: true, result: 3 })
})
it('lists repo issue metadata on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
listRepoLabels: vi.fn().mockResolvedValue(['bug']),
listRepoAssignableUsers: vi.fn().mockResolvedValue([{ login: 'octo' }])
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const labels = await dispatcher.dispatch(makeRequest('github.listLabels', { repo: 'repo-1' }))
const users = await dispatcher.dispatch(
makeRequest('github.listAssignableUsers', { repo: 'repo-1' })
)
expect(runtime.listRepoLabels).toHaveBeenCalledWith('repo-1')
expect(runtime.listRepoAssignableUsers).toHaveBeenCalledWith('repo-1')
expect(labels).toMatchObject({ ok: true, result: ['bug'] })
expect(users).toMatchObject({ ok: true, result: [{ login: 'octo' }] })
})
it('fetches PR checks on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getRepoPRChecks: vi.fn().mockResolvedValue([])
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.prChecks', {
repo: 'repo-1',
prNumber: 7,
headSha: 'abc123',
noCache: true
})
)
expect(runtime.getRepoPRChecks).toHaveBeenCalledWith('repo-1', 7, 'abc123', {
noCache: true
})
expect(response).toMatchObject({ ok: true, result: [] })
})
it('fetches PR file contents on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getRepoPRFileContents: vi.fn().mockResolvedValue({
original: '',
modified: 'new',
originalIsBinary: false,
modifiedIsBinary: false
})
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.prFileContents', {
repo: 'repo-1',
prNumber: 7,
path: 'src/app.ts',
status: 'modified',
headSha: 'head',
baseSha: 'base'
})
)
expect(runtime.getRepoPRFileContents).toHaveBeenCalledWith('repo-1', {
prNumber: 7,
path: 'src/app.ts',
oldPath: undefined,
status: 'modified',
headSha: 'head',
baseSha: 'base'
})
expect(response).toMatchObject({ ok: true, result: { modified: 'new' } })
})
it('resolves review threads on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
resolveRepoReviewThread: vi.fn().mockResolvedValue(true)
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.resolveReviewThread', {
repo: 'repo-1',
threadId: 'PRRT_1',
resolve: true
})
)
expect(runtime.resolveRepoReviewThread).toHaveBeenCalledWith('repo-1', 'PRRT_1', true)
expect(response).toMatchObject({ ok: true, result: true })
})
it('updates PR titles on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
updateRepoPRTitle: vi.fn().mockResolvedValue(true)
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.updatePRTitle', {
repo: 'repo-1',
prNumber: 7,
title: 'New title'
})
)
expect(runtime.updateRepoPRTitle).toHaveBeenCalledWith('repo-1', 7, 'New title')
expect(response).toMatchObject({ ok: true, result: true })
})
it('merges PRs on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
mergeRepoPR: vi.fn().mockResolvedValue({ ok: true })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.mergePR', {
repo: 'repo-1',
prNumber: 7,
method: 'squash'
})
)
expect(runtime.mergeRepoPR).toHaveBeenCalledWith('repo-1', 7, 'squash')
expect(response).toMatchObject({ ok: true, result: { ok: true } })
})
it('creates issues on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
createRepoIssue: vi.fn().mockResolvedValue({ ok: true, number: 3, url: 'https://gh/3' })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.createIssue', {
repo: 'repo-1',
title: 'Bug',
body: 'Body'
})
)
expect(runtime.createRepoIssue).toHaveBeenCalledWith('repo-1', 'Bug', 'Body')
expect(response).toMatchObject({ ok: true, result: { ok: true, number: 3 } })
})
it('updates issues on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
updateRepoIssue: vi.fn().mockResolvedValue({ ok: true })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.updateIssue', {
repo: 'repo-1',
number: 3,
updates: { state: 'closed', addLabels: ['bug'] }
})
)
expect(runtime.updateRepoIssue).toHaveBeenCalledWith('repo-1', 3, {
state: 'closed',
addLabels: ['bug']
})
expect(response).toMatchObject({ ok: true, result: { ok: true } })
})
it('adds issue comments on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
addRepoIssueComment: vi.fn().mockResolvedValue({ ok: true, comment: { id: 1 } })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.addIssueComment', {
repo: 'repo-1',
number: 3,
body: 'Looks good',
type: 'pr'
})
)
expect(runtime.addRepoIssueComment).toHaveBeenCalledWith('repo-1', 3, 'Looks good')
expect(response).toMatchObject({ ok: true, result: { ok: true, comment: { id: 1 } } })
})
it('adds PR review comments on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
addRepoPRReviewComment: vi.fn().mockResolvedValue({ ok: true, comment: { id: 2 } })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.addPRReviewComment', {
repo: 'repo-1',
prNumber: 7,
commitId: 'head',
path: 'src/app.ts',
line: 12,
startLine: 10,
body: 'Please tweak'
})
)
expect(runtime.addRepoPRReviewComment).toHaveBeenCalledWith('repo-1', {
prNumber: 7,
commitId: 'head',
path: 'src/app.ts',
line: 12,
startLine: 10,
body: 'Please tweak'
})
expect(response).toMatchObject({ ok: true, result: { ok: true, comment: { id: 2 } } })
})
it('adds PR review comment replies on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
addRepoPRReviewCommentReply: vi.fn().mockResolvedValue({ ok: true, comment: { id: 4 } })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.addPRReviewCommentReply', {
repo: 'repo-1',
prNumber: 7,
commentId: 2,
body: 'Done',
threadId: 'PRRT_1',
path: 'src/app.ts',
line: 12
})
)
expect(runtime.addRepoPRReviewCommentReply).toHaveBeenCalledWith('repo-1', {
prNumber: 7,
commentId: 2,
body: 'Done',
threadId: 'PRRT_1',
path: 'src/app.ts',
line: 12
})
expect(response).toMatchObject({ ok: true, result: { ok: true, comment: { id: 4 } } })
})
it('fetches GitHub project views on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
listGitHubProjectViews: vi.fn().mockResolvedValue({ ok: true, views: [] })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.project.listViews', {
owner: 'acme',
ownerType: 'organization',
projectNumber: 1
})
)
expect(runtime.listGitHubProjectViews).toHaveBeenCalledWith({
owner: 'acme',
ownerType: 'organization',
projectNumber: 1
})
expect(response).toMatchObject({ ok: true, result: { ok: true, views: [] } })
})
it('lists slug-addressed issue metadata on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
listGitHubLabelsBySlug: vi.fn().mockResolvedValue({ ok: true, labels: ['bug'] }),
listGitHubAssignableUsersBySlug: vi
.fn()
.mockResolvedValue({ ok: true, users: [{ login: 'octo' }] }),
listGitHubIssueTypesBySlug: vi.fn().mockResolvedValue({ ok: true, types: [{ id: 'it-1' }] })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const labels = await dispatcher.dispatch(
makeRequest('github.project.listLabelsBySlug', { owner: 'acme', repo: 'orca' })
)
const users = await dispatcher.dispatch(
makeRequest('github.project.listAssignableUsersBySlug', {
owner: 'acme',
repo: 'orca',
seedLogins: ['octo']
})
)
const issueTypes = await dispatcher.dispatch(
makeRequest('github.project.listIssueTypesBySlug', { owner: 'acme', repo: 'orca' })
)
expect(runtime.listGitHubLabelsBySlug).toHaveBeenCalledWith({ owner: 'acme', repo: 'orca' })
expect(runtime.listGitHubAssignableUsersBySlug).toHaveBeenCalledWith({
owner: 'acme',
repo: 'orca',
seedLogins: ['octo']
})
expect(runtime.listGitHubIssueTypesBySlug).toHaveBeenCalledWith({ owner: 'acme', repo: 'orca' })
expect(labels).toMatchObject({ ok: true, result: { ok: true, labels: ['bug'] } })
expect(users).toMatchObject({ ok: true, result: { ok: true, users: [{ login: 'octo' }] } })
expect(issueTypes).toMatchObject({ ok: true, result: { ok: true, types: [{ id: 'it-1' }] } })
})
it('fetches GitHub project tables on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
getGitHubProjectViewTable: vi.fn().mockResolvedValue({ ok: true, data: { rows: [] } })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.project.viewTable', {
owner: 'acme',
ownerType: 'organization',
projectNumber: 1,
viewId: 'view-1',
queryOverride: 'is:open'
})
)
expect(runtime.getGitHubProjectViewTable).toHaveBeenCalledWith({
owner: 'acme',
ownerType: 'organization',
projectNumber: 1,
viewId: 'view-1',
viewNumber: undefined,
viewName: undefined,
queryOverride: 'is:open'
})
expect(response).toMatchObject({ ok: true, result: { ok: true, data: { rows: [] } } })
})
it('updates GitHub project item fields on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
updateGitHubProjectItemField: vi.fn().mockResolvedValue({ ok: true })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.project.updateItemField', {
projectId: 'project-1',
itemId: 'item-1',
fieldId: 'field-1',
value: { kind: 'text', text: 'Now' }
})
)
expect(runtime.updateGitHubProjectItemField).toHaveBeenCalledWith({
projectId: 'project-1',
itemId: 'item-1',
fieldId: 'field-1',
value: { kind: 'text', text: 'Now' }
})
expect(response).toMatchObject({ ok: true, result: { ok: true } })
})
it('updates GitHub project issue types on the runtime server', async () => {
const runtime = {
getRuntimeId: () => 'test-runtime',
updateGitHubIssueTypeBySlug: vi.fn().mockResolvedValue({ ok: true })
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: GITHUB_METHODS })
const response = await dispatcher.dispatch(
makeRequest('github.project.updateIssueTypeBySlug', {
owner: 'acme',
repo: 'orca',
number: 9,
issueTypeId: null
})
)
expect(runtime.updateGitHubIssueTypeBySlug).toHaveBeenCalledWith({
owner: 'acme',
repo: 'orca',
number: 9,
issueTypeId: null
})
expect(response).toMatchObject({ ok: true, result: { ok: true } })
})
})