katashiro 0.1.1
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.
- package/package.json +184 -0
- package/src/commands/command-manager.ts +452 -0
- package/src/commands/index.ts +5 -0
- package/src/extension.ts +48 -0
- package/src/index.ts +36 -0
- package/src/katashiro-extension.ts +125 -0
- package/src/ui/index.ts +9 -0
- package/src/ui/output-channel-manager.ts +105 -0
- package/src/ui/status-bar-manager.ts +157 -0
- package/src/views/history-view-provider.ts +221 -0
- package/src/views/index.ts +15 -0
- package/src/views/knowledge-view-provider.ts +204 -0
- package/src/views/research-view-provider.ts +141 -0
- package/tests/mocks/vscode.ts +121 -0
- package/tests/unit/history-view-provider.test.ts +150 -0
- package/tests/unit/knowledge-view-provider.test.ts +120 -0
- package/tests/unit/output-channel-manager.test.ts +75 -0
- package/tests/unit/research-view-provider.test.ts +111 -0
- package/tests/unit/status-bar-manager.test.ts +101 -0
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KnowledgeViewProvider テスト
|
|
3
|
+
*
|
|
4
|
+
* @task TSK-072
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
8
|
+
|
|
9
|
+
// Mock vscode module
|
|
10
|
+
vi.mock('vscode', () => import('../mocks/vscode.js'));
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
KnowledgeViewProvider,
|
|
14
|
+
KnowledgeItem,
|
|
15
|
+
} from '../../src/views/knowledge-view-provider.js';
|
|
16
|
+
|
|
17
|
+
describe('KnowledgeViewProvider', () => {
|
|
18
|
+
let provider: KnowledgeViewProvider;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
provider = new KnowledgeViewProvider();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('initialization', () => {
|
|
25
|
+
it('should create provider', () => {
|
|
26
|
+
expect(provider).toBeDefined();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should have empty stats initially', () => {
|
|
30
|
+
const stats = provider.getStats();
|
|
31
|
+
expect(stats.nodes).toBe(0);
|
|
32
|
+
expect(stats.edges).toBe(0);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('getChildren', () => {
|
|
37
|
+
it('should return root categories', async () => {
|
|
38
|
+
const children = await provider.getChildren();
|
|
39
|
+
expect(children.length).toBe(3);
|
|
40
|
+
|
|
41
|
+
const labels = children.map((c) => c.label);
|
|
42
|
+
expect(labels).toContain('Nodes');
|
|
43
|
+
expect(labels).toContain('Edges');
|
|
44
|
+
expect(labels).toContain('Actions');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should return empty nodes message initially', async () => {
|
|
48
|
+
const root = await provider.getChildren();
|
|
49
|
+
const nodes = root.find((r) => r.label === 'Nodes');
|
|
50
|
+
const children = await provider.getChildren(nodes);
|
|
51
|
+
|
|
52
|
+
expect(children.length).toBe(1);
|
|
53
|
+
expect(children[0].label).toBe('No nodes yet');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('addNode', () => {
|
|
58
|
+
it('should add node', async () => {
|
|
59
|
+
provider.addNode('node-1', 'Test Node', 'entity');
|
|
60
|
+
|
|
61
|
+
const stats = provider.getStats();
|
|
62
|
+
expect(stats.nodes).toBe(1);
|
|
63
|
+
|
|
64
|
+
const root = await provider.getChildren();
|
|
65
|
+
const nodes = root.find((r) => r.label === 'Nodes');
|
|
66
|
+
const children = await provider.getChildren(nodes);
|
|
67
|
+
|
|
68
|
+
expect(children.length).toBe(1);
|
|
69
|
+
expect(children[0].label).toBe('Test Node');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('addEdge', () => {
|
|
74
|
+
it('should add edge', async () => {
|
|
75
|
+
provider.addEdge('node-1', 'node-2', 'relates_to');
|
|
76
|
+
|
|
77
|
+
const stats = provider.getStats();
|
|
78
|
+
expect(stats.edges).toBe(1);
|
|
79
|
+
|
|
80
|
+
const root = await provider.getChildren();
|
|
81
|
+
const edges = root.find((r) => r.label === 'Edges');
|
|
82
|
+
const children = await provider.getChildren(edges);
|
|
83
|
+
|
|
84
|
+
expect(children.length).toBe(1);
|
|
85
|
+
expect(children[0].label).toBe('node-1 → node-2');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('clear', () => {
|
|
90
|
+
it('should clear all data', async () => {
|
|
91
|
+
provider.addNode('node-1', 'Node 1', 'entity');
|
|
92
|
+
provider.addEdge('node-1', 'node-2', 'relates_to');
|
|
93
|
+
|
|
94
|
+
provider.clear();
|
|
95
|
+
|
|
96
|
+
const stats = provider.getStats();
|
|
97
|
+
expect(stats.nodes).toBe(0);
|
|
98
|
+
expect(stats.edges).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('KnowledgeItem', () => {
|
|
104
|
+
it('should create item with type', () => {
|
|
105
|
+
const item = new KnowledgeItem('Test', 0, 'node');
|
|
106
|
+
expect(item.label).toBe('Test');
|
|
107
|
+
expect(item.itemType).toBe('node');
|
|
108
|
+
expect(item.contextValue).toBe('node');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should set icon based on type', () => {
|
|
112
|
+
const nodeItem = new KnowledgeItem('Node', 0, 'node');
|
|
113
|
+
const edgeItem = new KnowledgeItem('Edge', 0, 'edge');
|
|
114
|
+
const categoryItem = new KnowledgeItem('Category', 0, 'category');
|
|
115
|
+
|
|
116
|
+
expect(nodeItem.iconPath).toBeDefined();
|
|
117
|
+
expect(edgeItem.iconPath).toBeDefined();
|
|
118
|
+
expect(categoryItem.iconPath).toBeDefined();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OutputChannelManager テスト
|
|
3
|
+
*
|
|
4
|
+
* @task TSK-073
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
8
|
+
|
|
9
|
+
// Mock vscode module
|
|
10
|
+
vi.mock('vscode', () => import('../mocks/vscode.js'));
|
|
11
|
+
|
|
12
|
+
import { OutputChannelManager } from '../../src/ui/output-channel-manager.js';
|
|
13
|
+
|
|
14
|
+
describe('OutputChannelManager', () => {
|
|
15
|
+
let manager: OutputChannelManager;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
manager = new OutputChannelManager('Test');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('initialization', () => {
|
|
22
|
+
it('should create manager', () => {
|
|
23
|
+
expect(manager).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('log', () => {
|
|
28
|
+
it('should log info message', () => {
|
|
29
|
+
expect(() => manager.log('Test message')).not.toThrow();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should log with different levels', () => {
|
|
33
|
+
expect(() => manager.log('Info', 'info')).not.toThrow();
|
|
34
|
+
expect(() => manager.log('Warn', 'warn')).not.toThrow();
|
|
35
|
+
expect(() => manager.log('Error', 'error')).not.toThrow();
|
|
36
|
+
expect(() => manager.log('Debug', 'debug')).not.toThrow();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('convenience methods', () => {
|
|
41
|
+
it('should have info method', () => {
|
|
42
|
+
expect(() => manager.info('Info message')).not.toThrow();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should have warn method', () => {
|
|
46
|
+
expect(() => manager.warn('Warning message')).not.toThrow();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should have error method', () => {
|
|
50
|
+
expect(() => manager.error('Error message')).not.toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should have debug method', () => {
|
|
54
|
+
expect(() => manager.debug('Debug message')).not.toThrow();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('show', () => {
|
|
59
|
+
it('should show channel', () => {
|
|
60
|
+
expect(() => manager.show()).not.toThrow();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('clear', () => {
|
|
65
|
+
it('should clear channel', () => {
|
|
66
|
+
expect(() => manager.clear()).not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('dispose', () => {
|
|
71
|
+
it('should dispose channel', () => {
|
|
72
|
+
expect(() => manager.dispose()).not.toThrow();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResearchViewProvider テスト
|
|
3
|
+
*
|
|
4
|
+
* @task TSK-072
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
8
|
+
|
|
9
|
+
// Mock vscode module
|
|
10
|
+
vi.mock('vscode', () => import('../mocks/vscode.js'));
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
ResearchViewProvider,
|
|
14
|
+
ResearchItem,
|
|
15
|
+
} from '../../src/views/research-view-provider.js';
|
|
16
|
+
|
|
17
|
+
describe('ResearchViewProvider', () => {
|
|
18
|
+
let provider: ResearchViewProvider;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
provider = new ResearchViewProvider();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('initialization', () => {
|
|
25
|
+
it('should create provider', () => {
|
|
26
|
+
expect(provider).toBeDefined();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should have onDidChangeTreeData event', () => {
|
|
30
|
+
expect(provider.onDidChangeTreeData).toBeDefined();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('getChildren', () => {
|
|
35
|
+
it('should return root items', async () => {
|
|
36
|
+
const children = await provider.getChildren();
|
|
37
|
+
expect(children.length).toBe(3);
|
|
38
|
+
|
|
39
|
+
const labels = children.map((c) => c.label);
|
|
40
|
+
expect(labels).toContain('New Search');
|
|
41
|
+
expect(labels).toContain('Research Topic');
|
|
42
|
+
expect(labels).toContain('Recent Searches');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return empty recent searches initially', async () => {
|
|
46
|
+
const root = await provider.getChildren();
|
|
47
|
+
const recentSearches = root.find((r) => r.label === 'Recent Searches');
|
|
48
|
+
|
|
49
|
+
expect(recentSearches).toBeDefined();
|
|
50
|
+
|
|
51
|
+
const children = await provider.getChildren(recentSearches);
|
|
52
|
+
expect(children.length).toBe(1);
|
|
53
|
+
expect(children[0].label).toBe('No recent searches');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('addSearch', () => {
|
|
58
|
+
it('should add search to recent searches', async () => {
|
|
59
|
+
provider.addSearch('test query');
|
|
60
|
+
|
|
61
|
+
const root = await provider.getChildren();
|
|
62
|
+
const recentSearches = root.find((r) => r.label === 'Recent Searches');
|
|
63
|
+
const children = await provider.getChildren(recentSearches);
|
|
64
|
+
|
|
65
|
+
expect(children.length).toBe(1);
|
|
66
|
+
expect(children[0].label).toBe('test query');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should limit to 10 recent searches', async () => {
|
|
70
|
+
for (let i = 0; i < 15; i++) {
|
|
71
|
+
provider.addSearch(`query ${i}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const root = await provider.getChildren();
|
|
75
|
+
const recentSearches = root.find((r) => r.label === 'Recent Searches');
|
|
76
|
+
const children = await provider.getChildren(recentSearches);
|
|
77
|
+
|
|
78
|
+
expect(children.length).toBe(10);
|
|
79
|
+
expect(children[0].label).toBe('query 14'); // Most recent
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('getTreeItem', () => {
|
|
84
|
+
it('should return the item itself', async () => {
|
|
85
|
+
const item = new ResearchItem(
|
|
86
|
+
'Test',
|
|
87
|
+
0 // TreeItemCollapsibleState.None
|
|
88
|
+
);
|
|
89
|
+
const result = provider.getTreeItem(item);
|
|
90
|
+
expect(result).toBe(item);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('ResearchItem', () => {
|
|
96
|
+
it('should create item with label', () => {
|
|
97
|
+
const item = new ResearchItem('Test Label', 0);
|
|
98
|
+
expect(item.label).toBe('Test Label');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should create item with description', () => {
|
|
102
|
+
const item = new ResearchItem('Test', 0, 'Description');
|
|
103
|
+
expect(item.description).toBe('Description');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should create item with command', () => {
|
|
107
|
+
const command = { command: 'test.command', title: 'Test' };
|
|
108
|
+
const item = new ResearchItem('Test', 0, '', command);
|
|
109
|
+
expect(item.command).toBe(command);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusBarManager テスト
|
|
3
|
+
*
|
|
4
|
+
* @task TSK-073
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
8
|
+
|
|
9
|
+
// Mock vscode module
|
|
10
|
+
vi.mock('vscode', () => import('../mocks/vscode.js'));
|
|
11
|
+
|
|
12
|
+
import { StatusBarManager } from '../../src/ui/status-bar-manager.js';
|
|
13
|
+
|
|
14
|
+
describe('StatusBarManager', () => {
|
|
15
|
+
let manager: StatusBarManager;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
manager = new StatusBarManager();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('initialization', () => {
|
|
22
|
+
it('should create manager', () => {
|
|
23
|
+
expect(manager).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should start in idle state', () => {
|
|
27
|
+
expect(manager.getState()).toBe('idle');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('show/hide', () => {
|
|
32
|
+
it('should show status bar', () => {
|
|
33
|
+
expect(() => manager.show()).not.toThrow();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should hide status bar', () => {
|
|
37
|
+
expect(() => manager.hide()).not.toThrow();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('setIdle', () => {
|
|
42
|
+
it('should set idle state', () => {
|
|
43
|
+
manager.setWorking();
|
|
44
|
+
manager.setIdle();
|
|
45
|
+
expect(manager.getState()).toBe('idle');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should set idle with custom message', () => {
|
|
49
|
+
manager.setIdle('Custom message');
|
|
50
|
+
expect(manager.getState()).toBe('idle');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('setWorking', () => {
|
|
55
|
+
it('should set working state', () => {
|
|
56
|
+
manager.setWorking();
|
|
57
|
+
expect(manager.getState()).toBe('working');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should set working with message', () => {
|
|
61
|
+
manager.setWorking('Processing...');
|
|
62
|
+
expect(manager.getState()).toBe('working');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('setSuccess', () => {
|
|
67
|
+
it('should set success state', () => {
|
|
68
|
+
manager.setSuccess('Complete', 0);
|
|
69
|
+
expect(manager.getState()).toBe('success');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should auto-reset to idle', async () => {
|
|
73
|
+
manager.setSuccess('Done', 100);
|
|
74
|
+
expect(manager.getState()).toBe('success');
|
|
75
|
+
|
|
76
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
77
|
+
expect(manager.getState()).toBe('idle');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('setError', () => {
|
|
82
|
+
it('should set error state', () => {
|
|
83
|
+
manager.setError('Failed', 0);
|
|
84
|
+
expect(manager.getState()).toBe('error');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should auto-reset to idle', async () => {
|
|
88
|
+
manager.setError('Error', 100);
|
|
89
|
+
expect(manager.getState()).toBe('error');
|
|
90
|
+
|
|
91
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
92
|
+
expect(manager.getState()).toBe('idle');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('dispose', () => {
|
|
97
|
+
it('should dispose manager', () => {
|
|
98
|
+
expect(() => manager.dispose()).not.toThrow();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"module": "CommonJS",
|
|
7
|
+
"moduleResolution": "Node"
|
|
8
|
+
},
|
|
9
|
+
"include": ["src/**/*.ts"],
|
|
10
|
+
"exclude": ["node_modules", "dist", "tests"],
|
|
11
|
+
"references": [
|
|
12
|
+
{ "path": "../core" },
|
|
13
|
+
{ "path": "../collector" },
|
|
14
|
+
{ "path": "../analyzer" },
|
|
15
|
+
{ "path": "../generator" },
|
|
16
|
+
{ "path": "../knowledge" },
|
|
17
|
+
{ "path": "../feedback" },
|
|
18
|
+
{ "path": "../mcp-server" }
|
|
19
|
+
]
|
|
20
|
+
}
|