cc-haha/adapters/common/__tests__/permission.test.ts
程序员阿江(Relakkes) f1c5f86b80 feat: keep IM permission approvals consistent
DingTalk can receive interactive card callbacks, but the card UI still depends on a published template, so the adapter now supports a template-backed card path with text commands as the reliable fallback. Telegram and WeChat use the same allow-once, allow-always, and deny semantics so manual authorization behaves the same across platforms.

Constraint: DingTalk button rendering requires an operator-provided interactive card template id
Rejected: Treat the existing AI streaming card template as a permission card | it cannot guarantee visible action buttons
Confidence: high
Scope-risk: moderate
Directive: Do not remove the text approval fallback unless DingTalk card template provisioning is guaranteed
Tested: bun test adapters/common/__tests__/permission.test.ts adapters/dingtalk/__tests__/permission-card.test.ts adapters/telegram/__tests__/telegram.test.ts adapters/common/__tests__/config.test.ts src/server/__tests__/adapters.test.ts
Tested: bunx tsc -p adapters/tsconfig.json --noEmit
Tested: bun run check:adapters
Tested: cd desktop && bun run build
Tested: bun run check:server
Tested: bun run check:docs
Tested: git diff --check
Not-tested: bun run quality:pr is blocked by existing CLI core approval policy; see artifacts/quality-runs/2026-05-03T13-19-56-232Z/report.md
2026-05-04 19:03:36 +08:00

30 lines
1.5 KiB
TypeScript

import { describe, expect, it } from 'bun:test'
import {
formatPermissionDecisionStatus,
formatPermissionInstructions,
parsePermissionCommand,
parsePermitCallbackData,
} from '../permission.js'
describe('permission helpers', () => {
it('parses text permission commands', () => {
expect(parsePermissionCommand('/allow req-1')).toEqual({ requestId: 'req-1', allowed: true })
expect(parsePermissionCommand('/always req-2')).toEqual({ requestId: 'req-2', allowed: true, rule: 'always' })
expect(parsePermissionCommand('/allow-always req-3')).toEqual({ requestId: 'req-3', allowed: true, rule: 'always' })
expect(parsePermissionCommand('/deny req-4')).toEqual({ requestId: 'req-4', allowed: false })
})
it('parses callback permission actions', () => {
expect(parsePermitCallbackData('permit:req-1:yes')).toEqual({ requestId: 'req-1', allowed: true })
expect(parsePermitCallbackData('permit:req-2:always')).toEqual({ requestId: 'req-2', allowed: true, rule: 'always' })
expect(parsePermitCallbackData('permit:req-3:no')).toEqual({ requestId: 'req-3', allowed: false })
expect(parsePermitCallbackData('permit:req-4:unknown')).toBeNull()
})
it('formats text fallback and status labels', () => {
expect(formatPermissionInstructions('req-1')).toContain('/always req-1')
expect(formatPermissionDecisionStatus({ allowed: true, rule: 'always' })).toContain('永久允许')
expect(formatPermissionDecisionStatus({ allowed: false })).toContain('拒绝')
})
})