729fb2d42a
- 新增 vitest 测试框架配置 - 添加 54 个测试文件,共 951 个测试用例 - 覆盖核心模块: - Agent: executor, registry, config-loader, permission-merger - Context: manager, compaction, prune, token-counter - Permission: manager, bash/file/git/web checkers, wildcard - Session: manager, storage - Tools: filesystem (12个), git (10个), web, shell, todo, task - LSP: client, server, language - Utils: config, diff - UI: terminal
186 lines
5.8 KiB
TypeScript
186 lines
5.8 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import { WebPermissionChecker } from '../../../src/permission/checkers/web.js';
|
|
|
|
describe('WebPermissionChecker - Web 权限检查器', () => {
|
|
let checker: WebPermissionChecker;
|
|
|
|
beforeEach(() => {
|
|
checker = new WebPermissionChecker();
|
|
});
|
|
|
|
describe('构造和基本属性', () => {
|
|
it('有正确的名称', () => {
|
|
expect(checker.name).toBe('web');
|
|
});
|
|
|
|
it('默认配置为 ask', () => {
|
|
const config = checker.getConfig();
|
|
expect(config.default).toBe('ask');
|
|
});
|
|
|
|
it('默认允许高级搜索', () => {
|
|
const config = checker.getConfig();
|
|
expect(config.allowAdvancedSearch).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('checkWebPermission - 检查 Web 权限', () => {
|
|
it('默认策略为 allow 时允许', async () => {
|
|
checker.setConfig({ default: 'allow' });
|
|
|
|
const result = await checker.checkWebPermission({ query: 'test search' });
|
|
|
|
expect(result.allowed).toBe(true);
|
|
expect(result.action).toBe('allow');
|
|
});
|
|
|
|
it('默认策略为 deny 时拒绝', async () => {
|
|
checker.setConfig({ default: 'deny' });
|
|
|
|
const result = await checker.checkWebPermission({ query: 'test search' });
|
|
|
|
expect(result.allowed).toBe(false);
|
|
expect(result.action).toBe('deny');
|
|
});
|
|
|
|
it('默认策略为 ask 时需要确认', async () => {
|
|
checker.setConfig({ default: 'ask' });
|
|
|
|
const result = await checker.checkWebPermission({ query: 'test search' });
|
|
|
|
expect(result.allowed).toBe(false);
|
|
expect(result.action).toBe('ask');
|
|
expect(result.needsConfirmation).toBe(true);
|
|
});
|
|
|
|
it('不允许高级搜索时拒绝', async () => {
|
|
checker.setConfig({ allowAdvancedSearch: false });
|
|
|
|
const result = await checker.checkWebPermission({
|
|
query: 'test search',
|
|
searchDepth: 'advanced',
|
|
});
|
|
|
|
expect(result.allowed).toBe(false);
|
|
expect(result.reason).toContain('不允许深度搜索');
|
|
});
|
|
|
|
it('主题不在允许列表时拒绝', async () => {
|
|
checker.setConfig({ allowedTopics: ['general', 'news'] });
|
|
|
|
const result = await checker.checkWebPermission({
|
|
query: 'test search',
|
|
topic: 'finance',
|
|
});
|
|
|
|
expect(result.allowed).toBe(false);
|
|
expect(result.reason).toContain('不允许搜索主题');
|
|
});
|
|
|
|
it('主题在允许列表时通过', async () => {
|
|
checker.setConfig({ default: 'allow', allowedTopics: ['general', 'news'] });
|
|
|
|
const result = await checker.checkWebPermission({
|
|
query: 'test search',
|
|
topic: 'news',
|
|
});
|
|
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
|
|
it('空主题列表允许所有主题', async () => {
|
|
checker.setConfig({ default: 'allow', allowedTopics: [] });
|
|
|
|
const result = await checker.checkWebPermission({
|
|
query: 'test search',
|
|
topic: 'any-topic',
|
|
});
|
|
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('会话权限管理', () => {
|
|
it('会话允许后不再询问', async () => {
|
|
const mockCallback = vi.fn().mockResolvedValue({ allow: true, remember: true });
|
|
checker.setAskCallback(mockCallback);
|
|
|
|
// 第一次调用,触发回调
|
|
const result1 = await checker.checkWebPermission({ query: 'test1' });
|
|
expect(result1.allowed).toBe(true);
|
|
expect(mockCallback).toHaveBeenCalledTimes(1);
|
|
|
|
// 第二次调用,使用会话权限
|
|
const result2 = await checker.checkWebPermission({ query: 'test2' });
|
|
expect(result2.allowed).toBe(true);
|
|
expect(mockCallback).toHaveBeenCalledTimes(1); // 不再调用
|
|
});
|
|
|
|
it('会话拒绝后不再询问', async () => {
|
|
const mockCallback = vi.fn().mockResolvedValue({ allow: false, remember: true });
|
|
checker.setAskCallback(mockCallback);
|
|
|
|
// 第一次调用
|
|
const result1 = await checker.checkWebPermission({ query: 'test1' });
|
|
expect(result1.allowed).toBe(false);
|
|
|
|
// 第二次调用
|
|
const result2 = await checker.checkWebPermission({ query: 'test2' });
|
|
expect(result2.allowed).toBe(false);
|
|
expect(mockCallback).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('不记住权限时每次询问', async () => {
|
|
const mockCallback = vi.fn().mockResolvedValue({ allow: true, remember: false });
|
|
checker.setAskCallback(mockCallback);
|
|
|
|
await checker.checkWebPermission({ query: 'test1' });
|
|
await checker.checkWebPermission({ query: 'test2' });
|
|
|
|
expect(mockCallback).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('清除会话权限后重新询问', async () => {
|
|
const mockCallback = vi.fn().mockResolvedValue({ allow: true, remember: true });
|
|
checker.setAskCallback(mockCallback);
|
|
|
|
await checker.checkWebPermission({ query: 'test1' });
|
|
checker.clearSessionPermissions();
|
|
await checker.checkWebPermission({ query: 'test2' });
|
|
|
|
expect(mockCallback).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|
|
|
|
describe('check - 通用接口', () => {
|
|
it('从 command 中提取查询', async () => {
|
|
checker.setConfig({ default: 'allow' });
|
|
|
|
const result = await checker.check({
|
|
command: 'web_search: test query',
|
|
workdir: '/test',
|
|
});
|
|
|
|
expect(result.allowed).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('配置管理', () => {
|
|
it('getConfig 返回配置副本', () => {
|
|
const config1 = checker.getConfig();
|
|
config1.default = 'deny';
|
|
|
|
const config2 = checker.getConfig();
|
|
expect(config2.default).toBe('ask'); // 原配置不变
|
|
});
|
|
|
|
it('setConfig 部分更新配置', () => {
|
|
checker.setConfig({ allowAdvancedSearch: false });
|
|
|
|
const config = checker.getConfig();
|
|
expect(config.allowAdvancedSearch).toBe(false);
|
|
expect(config.default).toBe('ask'); // 其他配置不变
|
|
});
|
|
});
|
|
});
|