@su-record/vibe 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +13 -6
  2. package/bin/vibe +20 -2
  3. package/package.json +5 -6
  4. package/scripts/install-mcp.js +31 -5
  5. package/mcp/dist/__tests__/complexity.test.js +0 -126
  6. package/mcp/dist/__tests__/memory.test.js +0 -120
  7. package/mcp/dist/__tests__/python-dart-complexity.test.js +0 -146
  8. package/mcp/dist/index.js +0 -230
  9. package/mcp/dist/lib/ContextCompressor.js +0 -305
  10. package/mcp/dist/lib/MemoryManager.js +0 -334
  11. package/mcp/dist/lib/ProjectCache.js +0 -126
  12. package/mcp/dist/lib/PythonParser.js +0 -241
  13. package/mcp/dist/tools/browser/browserPool.js +0 -76
  14. package/mcp/dist/tools/browser/browserUtils.js +0 -135
  15. package/mcp/dist/tools/browser/inspectNetworkRequests.js +0 -140
  16. package/mcp/dist/tools/browser/monitorConsoleLogs.js +0 -97
  17. package/mcp/dist/tools/convention/analyzeComplexity.js +0 -248
  18. package/mcp/dist/tools/convention/applyQualityRules.js +0 -102
  19. package/mcp/dist/tools/convention/checkCouplingCohesion.js +0 -233
  20. package/mcp/dist/tools/convention/complexityMetrics.js +0 -133
  21. package/mcp/dist/tools/convention/dartComplexity.js +0 -117
  22. package/mcp/dist/tools/convention/getCodingGuide.js +0 -64
  23. package/mcp/dist/tools/convention/languageDetector.js +0 -50
  24. package/mcp/dist/tools/convention/pythonComplexity.js +0 -109
  25. package/mcp/dist/tools/convention/suggestImprovements.js +0 -257
  26. package/mcp/dist/tools/convention/validateCodeQuality.js +0 -177
  27. package/mcp/dist/tools/memory/autoSaveContext.js +0 -79
  28. package/mcp/dist/tools/memory/database.js +0 -123
  29. package/mcp/dist/tools/memory/deleteMemory.js +0 -39
  30. package/mcp/dist/tools/memory/listMemories.js +0 -38
  31. package/mcp/dist/tools/memory/memoryConfig.js +0 -27
  32. package/mcp/dist/tools/memory/memorySQLite.js +0 -138
  33. package/mcp/dist/tools/memory/memoryUtils.js +0 -34
  34. package/mcp/dist/tools/memory/migrate.js +0 -113
  35. package/mcp/dist/tools/memory/prioritizeMemory.js +0 -109
  36. package/mcp/dist/tools/memory/recallMemory.js +0 -40
  37. package/mcp/dist/tools/memory/restoreSessionContext.js +0 -69
  38. package/mcp/dist/tools/memory/saveMemory.js +0 -34
  39. package/mcp/dist/tools/memory/searchMemories.js +0 -37
  40. package/mcp/dist/tools/memory/startSession.js +0 -100
  41. package/mcp/dist/tools/memory/updateMemory.js +0 -46
  42. package/mcp/dist/tools/planning/analyzeRequirements.js +0 -166
  43. package/mcp/dist/tools/planning/createUserStories.js +0 -119
  44. package/mcp/dist/tools/planning/featureRoadmap.js +0 -202
  45. package/mcp/dist/tools/planning/generatePrd.js +0 -156
  46. package/mcp/dist/tools/prompt/analyzePrompt.js +0 -145
  47. package/mcp/dist/tools/prompt/enhancePrompt.js +0 -105
  48. package/mcp/dist/tools/semantic/findReferences.js +0 -195
  49. package/mcp/dist/tools/semantic/findSymbol.js +0 -200
  50. package/mcp/dist/tools/thinking/analyzeProblem.js +0 -50
  51. package/mcp/dist/tools/thinking/breakDownProblem.js +0 -140
  52. package/mcp/dist/tools/thinking/createThinkingChain.js +0 -39
  53. package/mcp/dist/tools/thinking/formatAsPlan.js +0 -73
  54. package/mcp/dist/tools/thinking/stepByStepAnalysis.js +0 -58
  55. package/mcp/dist/tools/thinking/thinkAloudProcess.js +0 -75
  56. package/mcp/dist/tools/time/getCurrentTime.js +0 -61
  57. package/mcp/dist/tools/ui/previewUiAscii.js +0 -232
  58. package/mcp/dist/types/tool.js +0 -2
  59. package/mcp/package.json +0 -53
package/README.md CHANGED
@@ -29,17 +29,16 @@ Transform natural language requirements into production-ready code through struc
29
29
  npm install -g @su-record/vibe
30
30
  ```
31
31
 
32
- This automatically:
33
- - Installs the Vibe CLI
34
- - Registers the MCP server with 38 development tools
35
- - Enables slash commands for Claude Code
32
+ This installs:
33
+ - Vibe CLI commands
34
+ - @su-record/hi-ai MCP server (38 development tools)
36
35
 
37
36
  ---
38
37
 
39
38
  ## Quick Start
40
39
 
41
40
  ```bash
42
- # Initialize project
41
+ # Initialize project (registers MCP server for this project)
43
42
  vibe init
44
43
 
45
44
  # Create specification through guided Q&A
@@ -145,12 +144,20 @@ Vibe includes 38 MCP tools across multiple categories:
145
144
  - `recall_memory` - Retrieve stored information
146
145
  - `auto_save_context` - Automatic context checkpointing
147
146
 
147
+ **MCP Server Registration:**
148
+
149
+ The MCP server is automatically registered when you run `vibe init` in your project. This registers the server **locally for your project only**, not globally.
150
+
148
151
  **Verify MCP server:**
149
152
  ```bash
153
+ # Run this in your project directory
150
154
  claude mcp list
151
- # vibe: node /path/to/vibe/mcp/dist/index.js - ✓ Connected
155
+ # Expected output:
156
+ # vibe: node /path/to/@su-record/vibe/node_modules/@su-record/hi-ai/dist/index.js - ✓ Connected
152
157
  ```
153
158
 
159
+ **Important:** Each project that uses Vibe must run `vibe init` to register the MCP server for that specific project.
160
+
154
161
  ---
155
162
 
156
163
  ## Configuration
package/bin/vibe CHANGED
@@ -92,6 +92,20 @@ function init() {
92
92
  return;
93
93
  }
94
94
 
95
+ // MCP 서버 등록 먼저 체크 및 실행
96
+ console.log('🔧 MCP 서버 확인 중...\n');
97
+ try {
98
+ const { execSync } = require('child_process');
99
+
100
+ // MCP 서버 등록 스크립트 실행
101
+ const installScriptPath = path.join(__dirname, '../scripts/install-mcp.js');
102
+ execSync(`node "${installScriptPath}"`, { stdio: 'inherit' });
103
+
104
+ } catch (error) {
105
+ console.log('\n⚠️ MCP 서버 등록 중 오류가 발생했습니다.');
106
+ console.log(' 계속 진행합니다...\n');
107
+ }
108
+
95
109
  // 폴더 생성
96
110
  fs.mkdirSync(vibeDir);
97
111
  fs.mkdirSync(path.join(vibeDir, 'specs'));
@@ -115,7 +129,7 @@ function init() {
115
129
  },
116
130
  mcp: {
117
131
  enabled: true,
118
- servers: ['hi-ai', 'context-7']
132
+ servers: ['vibe']
119
133
  },
120
134
  quality: {
121
135
  strict: true,
@@ -135,11 +149,15 @@ function init() {
135
149
  ├── plans/ # 기술 계획들
136
150
  └── tasks/ # 작업 목록들
137
151
 
152
+ MCP 서버:
153
+ ✓ vibe MCP 서버 등록 완료 (38개 도구)
154
+ 확인: claude mcp list
155
+
138
156
  언어 변경:
139
157
  .vibe/config.json에서 "language"를 "en" 또는 "ko"로 변경
140
158
 
141
159
  다음 단계:
142
- vibe story create "기능명" - 새 기능 스토리 작성
160
+ vibe spec "기능명" - 새 기능 SPEC 작성
143
161
  `);
144
162
  }
145
163
 
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Vibe - SPEC-driven AI coding framework with MCP integration",
5
5
  "main": "cli/index.js",
6
6
  "bin": {
7
7
  "vibe": "./bin/vibe"
8
8
  },
9
9
  "scripts": {
10
- "build": "cd mcp && npm install && npm run build",
11
- "postinstall": "node scripts/install-mcp.js",
10
+ "build": "echo \"No build needed - using @su-record/hi-ai\"",
12
11
  "test": "echo \"Error: no test specified\" && exit 1"
13
12
  },
14
13
  "keywords": [
@@ -32,7 +31,9 @@
32
31
  "engines": {
33
32
  "node": ">=18.0.0"
34
33
  },
35
- "dependencies": {},
34
+ "dependencies": {
35
+ "@su-record/hi-ai": "latest"
36
+ },
36
37
  "devDependencies": {},
37
38
  "files": [
38
39
  "bin/",
@@ -41,8 +42,6 @@
41
42
  "skills/",
42
43
  "templates/",
43
44
  "scripts/",
44
- "mcp/dist/",
45
- "mcp/package.json",
46
45
  "README.md",
47
46
  "LICENSE"
48
47
  ]
@@ -6,14 +6,23 @@ const fs = require('fs');
6
6
 
7
7
  console.log('🔧 vibe MCP 서버 설치 중...\n');
8
8
 
9
- // MCP 서버 경로 (npm 글로벌 설치 위치)
10
- const mcpIndexPath = path.join(__dirname, '../mcp/dist/index.js');
9
+ // vibe 패키지의 실제 설치 경로 찾기
10
+ // npm link인 경우: 로컬 개발 경로
11
+ // npm install -g인 경우: 글로벌 설치 경로
12
+ // path.dirname()을 사용해 크로스 플랫폼 호환 (Windows/Unix)
13
+ const vibePackagePath = path.dirname(__dirname);
11
14
 
12
- // 상대 경로로 확인 (로컬 개발 시)
15
+ // MCP 서버 경로 (hi-ai 패키지)
16
+ // path.join()이 자동으로 OS별 경로 구분자 처리
17
+ const mcpIndexPath = path.join(vibePackagePath, 'node_modules', '@su-record', 'hi-ai', 'dist', 'index.js');
18
+
19
+ // hi-ai 설치 확인
13
20
  if (!fs.existsSync(mcpIndexPath)) {
14
- console.log('⚠️ MCP 서버를 찾을 수 없습니다.');
21
+ console.log('⚠️ hi-ai MCP 서버를 찾을 수 없습니다.');
15
22
  console.log(' 경로:', mcpIndexPath);
16
- console.log(' npm install을 다시 실행해주세요.\n');
23
+ console.log(' npm install을 실행해주세요.\n');
24
+ console.log(' npm install');
25
+ console.log('');
17
26
  process.exit(1);
18
27
  }
19
28
 
@@ -38,11 +47,28 @@ try {
38
47
  console.log('');
39
48
 
40
49
  } catch (error) {
50
+ // stderr 출력 확인
51
+ const stderrOutput = error.stderr ? error.stderr.toString() : '';
52
+ const stdoutOutput = error.stdout ? error.stdout.toString() : '';
53
+ const fullOutput = error.message + stderrOutput + stdoutOutput;
54
+
55
+ // "already exists" 에러는 성공으로 간주
56
+ if (fullOutput.includes('already exists')) {
57
+ console.log('ℹ️ vibe MCP 서버가 이미 등록되어 있습니다.');
58
+ console.log('');
59
+ console.log('다음 명령어로 확인:');
60
+ console.log(' claude mcp list');
61
+ console.log('');
62
+ process.exit(0);
63
+ }
64
+
41
65
  console.error('❌ MCP 서버 등록 실패');
42
66
  console.error('');
43
67
  console.error('수동 등록 방법:');
44
68
  console.error(` claude mcp add vibe node "${mcpIndexPath}"`);
45
69
  console.error('');
46
70
  console.error('에러:', error.message);
71
+ if (stderrOutput) console.error('stderr:', stderrOutput);
72
+ if (stdoutOutput) console.error('stdout:', stdoutOutput);
47
73
  process.exit(1);
48
74
  }
@@ -1,126 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
- import { analyzeComplexity, analyzeComplexityDefinition } from '../tools/convention/analyzeComplexity.js';
3
- describe('Code Complexity Analysis', () => {
4
- describe('analyzeComplexity', () => {
5
- test('should analyze simple function with low complexity', async () => {
6
- const simpleCode = `
7
- function add(a, b) {
8
- return a + b;
9
- }
10
- `;
11
- const result = await analyzeComplexity({ code: simpleCode, metrics: 'all' });
12
- const parsed = JSON.parse(result.content[0].text.replace('Complexity Analysis:\n', ''));
13
- expect(parsed.status).toBe('success');
14
- expect(parsed.results.cyclomaticComplexity).toBeDefined();
15
- expect(parsed.results.cognitiveComplexity).toBeDefined();
16
- expect(parsed.results.halsteadMetrics).toBeDefined();
17
- expect(parsed.results.cyclomaticComplexity.status).toBe('pass');
18
- });
19
- test('should detect high cyclomatic complexity', async () => {
20
- const complexCode = `
21
- function complexFunction(x) {
22
- if (x > 0) {
23
- if (x < 10) {
24
- for (let i = 0; i < x; i++) {
25
- if (i % 2 === 0) {
26
- while (i < 5) {
27
- if (i === 3) {
28
- return i;
29
- }
30
- i++;
31
- }
32
- }
33
- }
34
- }
35
- }
36
- return x;
37
- }
38
- `;
39
- const result = await analyzeComplexity({ code: complexCode, metrics: 'all' });
40
- const parsed = JSON.parse(result.content[0].text.replace('Complexity Analysis:\n', ''));
41
- expect(parsed.results.cyclomaticComplexity.value).toBeGreaterThan(5);
42
- expect(parsed.issues.length).toBeGreaterThan(0);
43
- });
44
- test('should calculate AST-based complexity', async () => {
45
- const code = `
46
- function test() {
47
- if (true) return 1;
48
- for (let i = 0; i < 10; i++) {
49
- console.log(i);
50
- }
51
- }
52
- `;
53
- const result = await analyzeComplexity({ code, metrics: 'cyclomatic' });
54
- const parsed = JSON.parse(result.content[0].text.replace('Complexity Analysis:\n', ''));
55
- expect(parsed.results.astCyclomaticComplexity).toBeDefined();
56
- expect(parsed.results.astCyclomaticComplexity.value).toBeGreaterThan(1);
57
- });
58
- test('should calculate cognitive complexity with nesting', async () => {
59
- const code = `
60
- function nested() {
61
- if (a) {
62
- if (b) {
63
- if (c) {
64
- return true;
65
- }
66
- }
67
- }
68
- }
69
- `;
70
- const result = await analyzeComplexity({ code, metrics: 'cognitive' });
71
- const parsed = JSON.parse(result.content[0].text.replace('Complexity Analysis:\n', ''));
72
- expect(parsed.results.cognitiveComplexity.value).toBeGreaterThan(0);
73
- });
74
- test('should calculate Halstead metrics', async () => {
75
- const code = `
76
- function calculate(x, y) {
77
- const sum = x + y;
78
- const product = x * y;
79
- return sum + product;
80
- }
81
- `;
82
- const result = await analyzeComplexity({ code, metrics: 'halstead' });
83
- const parsed = JSON.parse(result.content[0].text.replace('Complexity Analysis:\n', ''));
84
- expect(parsed.results.halsteadMetrics).toBeDefined();
85
- expect(parsed.results.halsteadMetrics.vocabulary).toBeGreaterThan(0);
86
- expect(parsed.results.halsteadMetrics.difficulty).toBeGreaterThan(0);
87
- });
88
- test('should provide recommendations for complex code', async () => {
89
- const veryComplexCode = `
90
- function veryComplex(a, b, c, d, e) {
91
- if (a) {
92
- if (b) {
93
- for (let i = 0; i < 10; i++) {
94
- if (c) {
95
- while (d) {
96
- if (e) {
97
- return true;
98
- }
99
- }
100
- }
101
- }
102
- }
103
- }
104
- return false;
105
- }
106
- `;
107
- const result = await analyzeComplexity({ code: veryComplexCode, metrics: 'all' });
108
- const parsed = JSON.parse(result.content[0].text.replace('Complexity Analysis:\n', ''));
109
- expect(parsed.recommendations).toBeDefined();
110
- expect(parsed.recommendations.length).toBeGreaterThan(0);
111
- expect(parsed.overallScore).toBeLessThan(100);
112
- });
113
- });
114
- describe('Tool Definition', () => {
115
- test('should have correct definition', () => {
116
- expect(analyzeComplexityDefinition.name).toBe('analyze_complexity');
117
- expect(analyzeComplexityDefinition.description).toContain('IMPORTANT');
118
- expect(analyzeComplexityDefinition.inputSchema.required).toContain('code');
119
- });
120
- test('should include keyword triggers', () => {
121
- const desc = analyzeComplexityDefinition.description;
122
- expect(desc).toContain('복잡도');
123
- expect(desc).toContain('complexity');
124
- });
125
- });
126
- });
@@ -1,120 +0,0 @@
1
- import { describe, test, expect, beforeEach, afterEach } from 'vitest';
2
- import { saveMemory, saveMemoryDefinition } from '../tools/memory/saveMemory.js';
3
- import { recallMemory } from '../tools/memory/recallMemory.js';
4
- import { listMemories } from '../tools/memory/listMemories.js';
5
- import { deleteMemory } from '../tools/memory/deleteMemory.js';
6
- import { memoryDB } from '../tools/memory/database.js';
7
- import { clearAllMemories } from '../tools/memory/memorySQLite.js';
8
- import { promises as fs } from 'fs';
9
- import path from 'path';
10
- const TEST_MEMORY_DIR = path.join(process.cwd(), 'memories');
11
- describe('Memory Management Tools', () => {
12
- beforeEach(async () => {
13
- // Ensure fresh database for each test
14
- try {
15
- // Close existing connection if any
16
- memoryDB.close();
17
- }
18
- catch (error) {
19
- // Ignore
20
- }
21
- // Clean up test files
22
- try {
23
- await fs.rm(TEST_MEMORY_DIR, { recursive: true, force: true });
24
- }
25
- catch (error) {
26
- // Ignore
27
- }
28
- // Clear all memories (this will recreate DB if needed)
29
- try {
30
- clearAllMemories();
31
- }
32
- catch (error) {
33
- // Database might not exist yet, will be created on first use
34
- }
35
- });
36
- afterEach(async () => {
37
- // Close database connection
38
- try {
39
- memoryDB.close();
40
- }
41
- catch (error) {
42
- // Ignore
43
- }
44
- });
45
- describe('saveMemory', () => {
46
- test('should save memory successfully', async () => {
47
- const result = await saveMemory({
48
- key: 'test-key',
49
- value: 'test-value',
50
- category: 'project'
51
- });
52
- expect(result.content[0].text).toContain('success');
53
- expect(result.content[0].text).toContain('test-key');
54
- });
55
- test('should create memory database if not exists', async () => {
56
- await saveMemory({ key: 'test-key', value: 'test-value' });
57
- // Check if database file exists
58
- const dbPath = path.join(TEST_MEMORY_DIR, 'memories.db');
59
- const dbExists = await fs.access(dbPath).then(() => true).catch(() => false);
60
- expect(dbExists).toBe(true);
61
- });
62
- });
63
- describe('recallMemory', () => {
64
- test('should recall saved memory', async () => {
65
- await saveMemory({ key: 'recall-test', value: 'recall-value' });
66
- const result = await recallMemory({ key: 'recall-test' });
67
- const parsedResult = JSON.parse(result.content[0].text.replace('Memory recalled:\n', ''));
68
- expect(parsedResult.value).toBe('recall-value');
69
- expect(parsedResult.key).toBe('recall-test');
70
- });
71
- test('should return not found for non-existent key', async () => {
72
- const result = await recallMemory({ key: 'non-existent' });
73
- expect(result.content[0].text).toContain('not found');
74
- });
75
- });
76
- describe('listMemories', () => {
77
- test('should list all memories', async () => {
78
- await saveMemory({ key: 'key1', value: 'value1', category: 'project' });
79
- await saveMemory({ key: 'key2', value: 'value2', category: 'code' });
80
- const result = await listMemories({ summary: false });
81
- const parsed = JSON.parse(result.content[0].text.replace('Memory list:\n', ''));
82
- expect(parsed.memories.length).toBe(2);
83
- expect(parsed.total).toBe(2);
84
- });
85
- test('should filter memories by category', async () => {
86
- await saveMemory({ key: 'project1', value: 'val1', category: 'project' });
87
- await saveMemory({ key: 'code1', value: 'val2', category: 'code' });
88
- const result = await listMemories({ category: 'project', summary: false });
89
- const parsed = JSON.parse(result.content[0].text.replace('Memory list:\n', ''));
90
- expect(parsed.total).toBe(1);
91
- expect(parsed.memories[0].key).toBe('project1');
92
- });
93
- test('should return empty array when no memories exist', async () => {
94
- const result = await listMemories({ summary: false });
95
- const parsed = JSON.parse(result.content[0].text.replace('Memory list:\n', ''));
96
- expect(parsed.memories).toEqual([]);
97
- expect(parsed.total).toBe(0);
98
- });
99
- });
100
- describe('deleteMemory', () => {
101
- test('should delete existing memory', async () => {
102
- await saveMemory({ key: 'delete-me', value: 'temporary' });
103
- const deleteResult = await deleteMemory({ key: 'delete-me' });
104
- expect(deleteResult.content[0].text).toContain('success');
105
- const recallResult = await recallMemory({ key: 'delete-me' });
106
- expect(recallResult.content[0].text).toContain('not found');
107
- });
108
- });
109
- describe('Tool Definition', () => {
110
- test('should have correct structure', () => {
111
- expect(saveMemoryDefinition.name).toBe('save_memory');
112
- expect(saveMemoryDefinition.description).toContain('IMPORTANT');
113
- expect(saveMemoryDefinition.inputSchema.required).toContain('key');
114
- });
115
- test('should include keyword triggers', () => {
116
- expect(saveMemoryDefinition.description).toContain('기억해');
117
- expect(saveMemoryDefinition.description).toContain('remember');
118
- });
119
- });
120
- });
@@ -1,146 +0,0 @@
1
- /**
2
- * Tests for Python and Dart/Flutter code complexity analysis
3
- */
4
- import { describe, it, expect } from 'vitest';
5
- import { detectLanguage } from '../tools/convention/languageDetector.js';
6
- import { calculatePythonComplexity, calculatePythonCognitiveComplexity } from '../tools/convention/pythonComplexity.js';
7
- import { calculateDartComplexity, calculateDartCognitiveComplexity } from '../tools/convention/dartComplexity.js';
8
- import { analyzeComplexity } from '../tools/convention/analyzeComplexity.js';
9
- describe('Language Detection', () => {
10
- it('should detect Python code', () => {
11
- const pythonCode = `
12
- def calculate_sum(numbers):
13
- total = 0
14
- for num in numbers:
15
- total += num
16
- return total
17
- `;
18
- expect(detectLanguage(pythonCode)).toBe('python');
19
- });
20
- it('should detect Dart/Flutter code', () => {
21
- const dartCode = `
22
- class MyWidget extends StatelessWidget {
23
- @override
24
- Widget build(BuildContext context) {
25
- return Container(
26
- child: Text('Hello'),
27
- );
28
- }
29
- }
30
- `;
31
- expect(detectLanguage(dartCode)).toBe('dart');
32
- });
33
- it('should detect TypeScript code', () => {
34
- const tsCode = `
35
- interface User {
36
- name: string;
37
- age: number;
38
- }
39
-
40
- function greet(user: User): void {
41
- console.log(\`Hello, \${user.name}\`);
42
- }
43
- `;
44
- expect(detectLanguage(tsCode)).toBe('typescript');
45
- });
46
- });
47
- describe('Python Complexity Analysis', () => {
48
- it('should calculate Python cyclomatic complexity', () => {
49
- const pythonCode = `
50
- def complex_function(x, y, z):
51
- if x > 0:
52
- if y > 0:
53
- return x + y
54
- elif y < 0:
55
- return x - y
56
- elif z > 0:
57
- for i in range(10):
58
- if i % 2 == 0:
59
- print(i)
60
- return 0
61
- `;
62
- const result = calculatePythonComplexity(pythonCode);
63
- expect(result.value).toBeGreaterThan(5);
64
- expect(result.status).toBeDefined();
65
- });
66
- it('should calculate Python cognitive complexity', () => {
67
- const pythonCode = `
68
- def nested_function(items):
69
- for item in items:
70
- if item > 0:
71
- if item % 2 == 0:
72
- print("Even positive")
73
- return items
74
- `;
75
- const result = calculatePythonCognitiveComplexity(pythonCode);
76
- expect(result.value).toBeGreaterThan(0);
77
- });
78
- });
79
- describe('Dart Complexity Analysis', () => {
80
- it('should calculate Dart cyclomatic complexity', () => {
81
- const dartCode = `
82
- Widget buildWidget(bool condition) {
83
- if (condition) {
84
- return Text('Yes');
85
- } else {
86
- return Text('No');
87
- }
88
- }
89
- `;
90
- const result = calculateDartComplexity(dartCode);
91
- expect(result.value).toBeGreaterThan(1);
92
- });
93
- it('should calculate Dart cognitive complexity', () => {
94
- const dartCode = `
95
- class MyWidget extends StatelessWidget {
96
- @override
97
- Widget build(BuildContext context) {
98
- return condition1
99
- ? Text('A')
100
- : condition2
101
- ? Text('B')
102
- : Text('C');
103
- }
104
- }
105
- `;
106
- const result = calculateDartCognitiveComplexity(dartCode);
107
- expect(result.value).toBeGreaterThanOrEqual(0); // Ternary operators may not be counted
108
- });
109
- });
110
- describe('Integrated Complexity Analysis', () => {
111
- it('should analyze Python code with auto-detection', async () => {
112
- const pythonCode = `
113
- def fibonacci(n):
114
- if n <= 1:
115
- return n
116
- return fibonacci(n-1) + fibonacci(n-2)
117
- `;
118
- const result = await analyzeComplexity({ code: pythonCode });
119
- expect(result.content[0].text).toContain('Python');
120
- expect(result.content[0].text).toContain('cyclomaticComplexity');
121
- });
122
- it('should analyze Dart code with auto-detection', async () => {
123
- const dartCode = `
124
- class Counter extends StatefulWidget {
125
- @override
126
- _CounterState createState() => _CounterState();
127
- }
128
- `;
129
- const result = await analyzeComplexity({ code: dartCode });
130
- expect(result.content[0].text).toContain('Dart');
131
- });
132
- it('should analyze TypeScript code', async () => {
133
- const tsCode = `
134
- function complexFunc(a: number, b: number): number {
135
- if (a > b) {
136
- return a;
137
- } else if (a < b) {
138
- return b;
139
- }
140
- return 0;
141
- }
142
- `;
143
- const result = await analyzeComplexity({ code: tsCode });
144
- expect(result.content[0].text).toContain('TypeScript');
145
- });
146
- });