Skip to main content
Glama
integration-tools.test.ts7.22 kB
/** * 集成工具测试 */ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; describe('项目结构分析', () => { let testDir: string; beforeEach(() => { testDir = join(tmpdir(), `test-project-${Date.now()}`); mkdirSync(testDir, { recursive: true }); }); afterEach(() => { if (existsSync(testDir)) { rmSync(testDir, { recursive: true, force: true }); } }); /** * 模拟的项目分析函数(从 server.ts 提取的核心逻辑) */ function analyzeProject(projectPath: string) { const features: string[] = []; const techStack: string[] = []; // 检测 package.json const pkgPath = join(projectPath, 'package.json'); if (existsSync(pkgPath)) { try { const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); features.push('Node.js 项目'); const deps = { ...pkg.dependencies, ...pkg.devDependencies }; if (deps.react) techStack.push('React'); if (deps.vue) techStack.push('Vue'); if (deps.angular) techStack.push('Angular'); if (deps.next) techStack.push('Next.js'); if (deps.express) techStack.push('Express'); if (deps.nestjs || deps['@nestjs/core']) techStack.push('NestJS'); if (deps.typescript) techStack.push('TypeScript'); if (deps.tailwindcss) techStack.push('TailwindCSS'); } catch { // 忽略解析错误 } } // 检测配置文件 if (existsSync(join(projectPath, 'tsconfig.json'))) features.push('TypeScript 配置'); if (existsSync(join(projectPath, 'docker-compose.yml')) || existsSync(join(projectPath, 'Dockerfile'))) features.push('Docker 支持'); if (existsSync(join(projectPath, '.github'))) features.push('GitHub Actions'); if (existsSync(join(projectPath, 'pyproject.toml')) || existsSync(join(projectPath, 'requirements.txt'))) features.push('Python 项目'); if (existsSync(join(projectPath, 'Cargo.toml'))) features.push('Rust 项目'); if (existsSync(join(projectPath, 'go.mod'))) features.push('Go 项目'); return { features, techStack }; } it('应该识别 Node.js 项目', () => { writeFileSync(join(testDir, 'package.json'), JSON.stringify({ name: 'test', dependencies: {}, })); const result = analyzeProject(testDir); expect(result.features).toContain('Node.js 项目'); }); it('应该识别 React 技术栈', () => { writeFileSync(join(testDir, 'package.json'), JSON.stringify({ name: 'test', dependencies: { react: '^18.0.0' }, })); const result = analyzeProject(testDir); expect(result.techStack).toContain('React'); }); it('应该识别 TypeScript 配置', () => { writeFileSync(join(testDir, 'tsconfig.json'), '{}'); const result = analyzeProject(testDir); expect(result.features).toContain('TypeScript 配置'); }); it('应该识别 Docker 支持', () => { writeFileSync(join(testDir, 'Dockerfile'), 'FROM node:18'); const result = analyzeProject(testDir); expect(result.features).toContain('Docker 支持'); }); it('应该识别 Python 项目', () => { writeFileSync(join(testDir, 'requirements.txt'), 'flask==2.0.0'); const result = analyzeProject(testDir); expect(result.features).toContain('Python 项目'); }); it('应该识别 Rust 项目', () => { writeFileSync(join(testDir, 'Cargo.toml'), '[package]\nname = "test"'); const result = analyzeProject(testDir); expect(result.features).toContain('Rust 项目'); }); it('应该识别 Go 项目', () => { writeFileSync(join(testDir, 'go.mod'), 'module test'); const result = analyzeProject(testDir); expect(result.features).toContain('Go 项目'); }); it('应该识别多个技术栈', () => { writeFileSync(join(testDir, 'package.json'), JSON.stringify({ name: 'test', dependencies: { react: '^18.0.0', next: '^13.0.0', }, devDependencies: { typescript: '^5.0.0', tailwindcss: '^3.0.0', }, })); const result = analyzeProject(testDir); expect(result.techStack).toContain('React'); expect(result.techStack).toContain('Next.js'); expect(result.techStack).toContain('TypeScript'); expect(result.techStack).toContain('TailwindCSS'); }); it('应该识别 GitHub Actions', () => { mkdirSync(join(testDir, '.github'), { recursive: true }); const result = analyzeProject(testDir); expect(result.features).toContain('GitHub Actions'); }); it('应该在空项目时返回空数组', () => { const result = analyzeProject(testDir); expect(result.features).toEqual([]); expect(result.techStack).toEqual([]); }); }); describe('文件读取工具', () => { let testDir: string; beforeEach(() => { testDir = join(tmpdir(), `test-files-${Date.now()}`); mkdirSync(testDir, { recursive: true }); }); afterEach(() => { if (existsSync(testDir)) { rmSync(testDir, { recursive: true, force: true }); } }); /** * 文件匹配函数 */ function matchFiles(files: string[], pattern?: string): string[] { if (!pattern) return files; const regex = new RegExp(pattern.replace('*', '.*')); return files.filter(f => regex.test(f)); } it('应该匹配 *.ts 文件', () => { const files = ['index.ts', 'app.js', 'utils.ts', 'readme.md']; const result = matchFiles(files, '*.ts'); expect(result).toEqual(['index.ts', 'utils.ts']); }); it('应该匹配 *.js 文件', () => { const files = ['index.ts', 'app.js', 'utils.ts', 'main.js']; const result = matchFiles(files, '*.js'); expect(result).toEqual(['app.js', 'main.js']); }); it('应该在无模式时返回所有文件', () => { const files = ['a.ts', 'b.js', 'c.md']; const result = matchFiles(files); expect(result).toEqual(files); }); it('应该在无匹配时返回空数组', () => { const files = ['a.ts', 'b.js']; const result = matchFiles(files, '*.py'); expect(result).toEqual([]); }); }); describe('Commit Message 风格', () => { const stylePrompts: Record<string, string> = { conventional: '使用约定式提交格式:type(scope): description。', simple: '使用简洁风格:一行描述主要变更。', detailed: '使用详细风格:标题 + 空行 + 详细说明。', }; it('应该有 conventional 风格', () => { expect(stylePrompts.conventional).toBeDefined(); expect(stylePrompts.conventional).toContain('type'); }); it('应该有 simple 风格', () => { expect(stylePrompts.simple).toBeDefined(); expect(stylePrompts.simple).toContain('一行'); }); it('应该有 detailed 风格', () => { expect(stylePrompts.detailed).toBeDefined(); expect(stylePrompts.detailed).toContain('详细'); }); it('应该默认使用 conventional', () => { const style = 'unknown'; const prompt = stylePrompts[style] || stylePrompts.conventional; expect(prompt).toBe(stylePrompts.conventional); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/7836246/claude-team-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server