feat: 添加工具类增强与状态管理改进

- 新增 workflowRuns、remoteTriggerAudit、pipeStatus 等工具
- 增强 permissionSetup: auto mode 和 bypass permissions 始终可用
- 新增多组测试覆盖 (modifiers, teamDiscovery, deepLink 等)
- 修复 parseInt 缺少 radix 参数
- 移除多余 biome-ignore 注释

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
unraid
2026-04-22 22:38:10 +08:00
parent 94c4b37eed
commit fb41513b32
54 changed files with 1037 additions and 102 deletions

View File

@@ -0,0 +1,93 @@
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
const mockParseDeepLink = mock((uri: string) => {
if (uri === null || uri === undefined || uri === 'bad-uri') {
throw new Error('invalid deep link')
}
return { query: 'hello', cwd: 'E:/Source_code/Claude-code-bast-test' }
})
const mockLaunchInTerminal = mock(async () => true)
mock.module('../parseDeepLink.js', () => ({
parseDeepLink: mockParseDeepLink,
}))
mock.module('../registerProtocol.js', () => ({
MACOS_BUNDLE_ID: 'com.anthropic.claude-code-url-handler',
}))
mock.module('../terminalLauncher.js', () => ({
launchInTerminal: mockLaunchInTerminal,
}))
mock.module('../banner.js', () => ({
readLastFetchTime: async () => undefined,
buildDeepLinkBanner: () => '',
}))
mock.module('../../githubRepoPathMapping.js', () => ({
updateGithubRepoPathMapping: async () => {},
getKnownPathsForRepo: () => [],
filterExistingPaths: async () => [],
validateRepoAtPath: async () => false,
removePathFromRepo: () => {},
}))
const { handleDeepLinkUri, handleUrlSchemeLaunch } = await import(
'../protocolHandler.js'
)
const originalBundleId = process.env.__CFBundleIdentifier
const originalUrlEvent = process.env.CLAUDE_CODE_URL_EVENT
beforeEach(() => {
mockParseDeepLink.mockClear()
mockLaunchInTerminal.mockClear()
process.env.__CFBundleIdentifier = undefined
delete process.env.CLAUDE_CODE_URL_EVENT
})
afterEach(() => {
process.env.__CFBundleIdentifier = originalBundleId
if (originalUrlEvent === undefined) {
delete process.env.CLAUDE_CODE_URL_EVENT
} else {
process.env.CLAUDE_CODE_URL_EVENT = originalUrlEvent
}
})
describe('handleUrlSchemeLaunch', () => {
test('returns null without calling url-handler-napi when bundle id does not match', async () => {
process.env.__CFBundleIdentifier = 'other.bundle'
await expect(handleUrlSchemeLaunch()).resolves.toBeNull()
expect(mockParseDeepLink).not.toHaveBeenCalled()
})
test('returns null for a matching bundle id when no URL event arrives', async () => {
process.env.__CFBundleIdentifier = 'com.anthropic.claude-code-url-handler'
await expect(handleUrlSchemeLaunch()).resolves.toBeNull()
expect(mockParseDeepLink).not.toHaveBeenCalled()
})
test('handles a URL event after waiting for url-handler-napi', async () => {
process.env.__CFBundleIdentifier = 'com.anthropic.claude-code-url-handler'
process.env.CLAUDE_CODE_URL_EVENT = 'claude-cli://prompt?q=hello'
await expect(handleUrlSchemeLaunch()).resolves.toBe(0)
expect(mockParseDeepLink).toHaveBeenCalledWith(
'claude-cli://prompt?q=hello',
)
})
})
describe('handleDeepLinkUri', () => {
test('returns 1 when parsing fails', async () => {
await expect(handleDeepLinkUri('bad-uri')).resolves.toBe(1)
expect(mockLaunchInTerminal).not.toHaveBeenCalled()
})
test('returns 0 when parsing succeeds and terminal launch succeeds', async () => {
await expect(
handleDeepLinkUri('claude-cli://prompt?q=hello'),
).resolves.toBe(0)
expect(mockLaunchInTerminal).toHaveBeenCalled()
})
})

View File

@@ -94,11 +94,13 @@ export async function handleUrlSchemeLaunch(): Promise<number | null> {
try {
const { waitForUrlEvent } = await import('url-handler-napi')
const url = (waitForUrlEvent as any)(5000)
const url = await (
waitForUrlEvent as (timeoutMs?: number) => Promise<string | null>
)(5000)
if (!url) {
return null
}
return await handleDeepLinkUri(await url as string)
return await handleDeepLinkUri(url)
} catch {
// NAPI module not available, or handleDeepLinkUri rejected — not a URL launch
return null