5e32375f0e
架构变更: - 采用 pnpm workspaces 实现 Monorepo 结构 - 将现有代码迁移到 packages/core - 新增 packages/server HTTP 服务层 Server 功能: - REST API: 会话管理、工具管理、配置管理 - WebSocket: 实时双向通信支持 - SSE: 服务端事件推送 - Hono + Bun 作为运行时 API 端点: - GET/POST /api/sessions - 会话 CRUD - GET/POST /api/sessions/:id/messages - 消息管理 - GET /api/sessions/:id/events - SSE 事件流 - WS /api/ws/:sessionId - WebSocket 连接 - GET/POST /api/tools - 工具管理 - GET/PUT /api/config - 配置管理
164 lines
4.9 KiB
TypeScript
164 lines
4.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { parseCommandSimple } from '../../../src/permission/bash-parser.js';
|
|
|
|
// 注意:parseBashCommand 需要初始化 tree-sitter wasm,在单元测试中使用 parseCommandSimple
|
|
|
|
describe('parseCommandSimple - 简单命令解析', () => {
|
|
describe('基本命令解析', () => {
|
|
it('解析单个命令', () => {
|
|
const result = parseCommandSimple('ls');
|
|
|
|
expect(result.name).toBe('ls');
|
|
expect(result.subcommand).toBeUndefined();
|
|
expect(result.args).toEqual([]);
|
|
expect(result.text).toBe('ls');
|
|
});
|
|
|
|
it('解析带子命令的命令', () => {
|
|
const result = parseCommandSimple('git status');
|
|
|
|
expect(result.name).toBe('git');
|
|
expect(result.subcommand).toBe('status');
|
|
expect(result.args).toEqual([]);
|
|
});
|
|
|
|
it('解析带参数的命令', () => {
|
|
const result = parseCommandSimple('git commit -m "message"');
|
|
|
|
expect(result.name).toBe('git');
|
|
expect(result.subcommand).toBe('commit');
|
|
expect(result.args).toContain('-m');
|
|
});
|
|
|
|
it('解析带 flag 前缀的子命令', () => {
|
|
const result = parseCommandSimple('rm -rf node_modules');
|
|
|
|
expect(result.name).toBe('rm');
|
|
// -rf 以 - 开头,所以 node_modules 是第一个非 flag 参数
|
|
expect(result.subcommand).toBe('node_modules');
|
|
expect(result.args).toContain('-rf');
|
|
});
|
|
});
|
|
|
|
describe('flag 和参数分离', () => {
|
|
it('短 flag 放入 args', () => {
|
|
const result = parseCommandSimple('ls -la');
|
|
|
|
expect(result.name).toBe('ls');
|
|
expect(result.subcommand).toBeUndefined();
|
|
expect(result.args).toContain('-la');
|
|
});
|
|
|
|
it('长 flag 放入 args', () => {
|
|
const result = parseCommandSimple('npm install --save-dev');
|
|
|
|
expect(result.name).toBe('npm');
|
|
expect(result.subcommand).toBe('install');
|
|
expect(result.args).toContain('--save-dev');
|
|
});
|
|
|
|
it('混合 flag 和参数', () => {
|
|
const result = parseCommandSimple('git checkout -b feature-branch');
|
|
|
|
expect(result.name).toBe('git');
|
|
expect(result.subcommand).toBe('checkout');
|
|
expect(result.args).toContain('-b');
|
|
expect(result.args).toContain('feature-branch');
|
|
});
|
|
});
|
|
|
|
describe('空白处理', () => {
|
|
it('处理前后空格', () => {
|
|
const result = parseCommandSimple(' git status ');
|
|
|
|
expect(result.name).toBe('git');
|
|
expect(result.subcommand).toBe('status');
|
|
});
|
|
|
|
it('处理多个空格分隔', () => {
|
|
const result = parseCommandSimple('git status -v');
|
|
|
|
expect(result.name).toBe('git');
|
|
expect(result.subcommand).toBe('status');
|
|
expect(result.args).toContain('-v');
|
|
});
|
|
|
|
it('空字符串返回空命令', () => {
|
|
const result = parseCommandSimple('');
|
|
|
|
expect(result.name).toBe('');
|
|
expect(result.subcommand).toBeUndefined();
|
|
expect(result.args).toEqual([]);
|
|
});
|
|
|
|
it('只有空格返回空命令', () => {
|
|
const result = parseCommandSimple(' ');
|
|
|
|
expect(result.name).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('复杂命令', () => {
|
|
it('解析 git push 命令', () => {
|
|
const result = parseCommandSimple('git push origin main --force');
|
|
|
|
expect(result.name).toBe('git');
|
|
expect(result.subcommand).toBe('push');
|
|
expect(result.args).toContain('origin');
|
|
expect(result.args).toContain('main');
|
|
expect(result.args).toContain('--force');
|
|
});
|
|
|
|
it('解析 npm 命令', () => {
|
|
const result = parseCommandSimple('npm run build -- --watch');
|
|
|
|
expect(result.name).toBe('npm');
|
|
expect(result.subcommand).toBe('run');
|
|
expect(result.args).toContain('build');
|
|
});
|
|
|
|
it('解析 docker 命令', () => {
|
|
const result = parseCommandSimple('docker run -d -p 8080:80 nginx');
|
|
|
|
expect(result.name).toBe('docker');
|
|
expect(result.subcommand).toBe('run');
|
|
expect(result.args).toContain('-d');
|
|
expect(result.args).toContain('-p');
|
|
});
|
|
|
|
it('解析管道前的命令', () => {
|
|
// 简单解析不处理管道,只作为普通参数
|
|
const result = parseCommandSimple('cat file.txt');
|
|
|
|
expect(result.name).toBe('cat');
|
|
expect(result.subcommand).toBe('file.txt');
|
|
});
|
|
});
|
|
|
|
describe('保留原始文本', () => {
|
|
it('text 字段保留原始命令', () => {
|
|
const original = 'git commit -m "fix bug"';
|
|
const result = parseCommandSimple(original);
|
|
|
|
expect(result.text).toBe(original);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('ParsedCommand 结构', () => {
|
|
it('包含所有必要字段', () => {
|
|
const result = parseCommandSimple('git push');
|
|
|
|
expect(result).toHaveProperty('name');
|
|
expect(result).toHaveProperty('subcommand');
|
|
expect(result).toHaveProperty('args');
|
|
expect(result).toHaveProperty('text');
|
|
});
|
|
|
|
it('args 始终是数组', () => {
|
|
const result = parseCommandSimple('ls');
|
|
|
|
expect(Array.isArray(result.args)).toBe(true);
|
|
});
|
|
});
|