gh-here 1.0.2 → 1.0.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.
- package/.claude/settings.local.json +15 -10
- package/README.md +6 -3
- package/bin/gh-here.js +8 -1255
- package/lib/file-utils.js +264 -0
- package/lib/git.js +207 -0
- package/lib/gitignore.js +91 -0
- package/lib/renderers.js +569 -0
- package/lib/server.js +391 -0
- package/package.json +1 -1
- package/public/app.js +692 -129
- package/public/styles.css +414 -44
- package/tests/draftManager.test.js +241 -0
- package/tests/httpService.test.js +268 -0
- package/tests/languageDetection.test.js +145 -0
- package/tests/pathUtils.test.js +136 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Tests for Path Utilities
|
|
2
|
+
// Run with: node tests/pathUtils.test.js
|
|
3
|
+
|
|
4
|
+
// Path utility functions extracted for testability
|
|
5
|
+
const PathUtils = {
|
|
6
|
+
// Extract current path from URL parameters
|
|
7
|
+
getCurrentPath() {
|
|
8
|
+
const currentUrl = new URL(window.location.href);
|
|
9
|
+
return currentUrl.searchParams.get('path') || '';
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
// Navigate to parent directory
|
|
13
|
+
getParentPath(currentPath) {
|
|
14
|
+
if (!currentPath || currentPath === '') {
|
|
15
|
+
return null; // Already at root
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const pathParts = currentPath.split('/').filter(p => p);
|
|
19
|
+
if (pathParts.length === 0) {
|
|
20
|
+
return null; // Already at root
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pathParts.pop();
|
|
24
|
+
return pathParts.join('/');
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// Build file path from directory and filename
|
|
28
|
+
buildFilePath(currentPath, filename) {
|
|
29
|
+
return currentPath ? `${currentPath}/${filename}` : filename;
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// Get filename from full path
|
|
33
|
+
getFileName(filePath) {
|
|
34
|
+
return filePath.split('/').pop() || 'file.txt';
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// Build URL with encoded path parameter
|
|
38
|
+
buildPathUrl(basePath, targetPath) {
|
|
39
|
+
return targetPath ? `${basePath}?path=${encodeURIComponent(targetPath)}` : basePath;
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
// Extract directory path from file path
|
|
43
|
+
getDirectoryPath(filePath) {
|
|
44
|
+
const parts = filePath.split('/').filter(p => p);
|
|
45
|
+
if (parts.length <= 1) return '';
|
|
46
|
+
return parts.slice(0, -1).join('/');
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Simple test framework
|
|
51
|
+
function test(name, fn) {
|
|
52
|
+
try {
|
|
53
|
+
fn();
|
|
54
|
+
console.log(`✅ ${name}`);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.log(`❌ ${name}: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function assertEqual(actual, expected, message = '') {
|
|
61
|
+
if (actual !== expected) {
|
|
62
|
+
throw new Error(`Expected "${expected}" but got "${actual}". ${message}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function assertNull(actual, message = '') {
|
|
67
|
+
if (actual !== null) {
|
|
68
|
+
throw new Error(`Expected null but got "${actual}". ${message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Test cases
|
|
73
|
+
console.log('🧪 Testing Path Utilities\n');
|
|
74
|
+
|
|
75
|
+
test('gets parent path correctly', () => {
|
|
76
|
+
assertEqual(PathUtils.getParentPath('src/components/App.js'), 'src/components');
|
|
77
|
+
assertEqual(PathUtils.getParentPath('src/App.js'), 'src');
|
|
78
|
+
assertEqual(PathUtils.getParentPath('App.js'), '');
|
|
79
|
+
assertNull(PathUtils.getParentPath(''));
|
|
80
|
+
assertNull(PathUtils.getParentPath(null));
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('builds file paths correctly', () => {
|
|
84
|
+
assertEqual(PathUtils.buildFilePath('src/components', 'App.js'), 'src/components/App.js');
|
|
85
|
+
assertEqual(PathUtils.buildFilePath('src', 'App.js'), 'src/App.js');
|
|
86
|
+
assertEqual(PathUtils.buildFilePath('', 'App.js'), 'App.js');
|
|
87
|
+
assertEqual(PathUtils.buildFilePath(null, 'App.js'), 'App.js');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('gets filename from path correctly', () => {
|
|
91
|
+
assertEqual(PathUtils.getFileName('src/components/App.js'), 'App.js');
|
|
92
|
+
assertEqual(PathUtils.getFileName('App.js'), 'App.js');
|
|
93
|
+
assertEqual(PathUtils.getFileName(''), 'file.txt');
|
|
94
|
+
assertEqual(PathUtils.getFileName('src/components/'), 'file.txt');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('builds URLs with path parameters', () => {
|
|
98
|
+
assertEqual(PathUtils.buildPathUrl('/', 'src/components'), '/?path=src%2Fcomponents');
|
|
99
|
+
assertEqual(PathUtils.buildPathUrl('/new', 'src'), '/new?path=src');
|
|
100
|
+
assertEqual(PathUtils.buildPathUrl('/', ''), '/');
|
|
101
|
+
assertEqual(PathUtils.buildPathUrl('/new', null), '/new');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('gets directory path from file path', () => {
|
|
105
|
+
assertEqual(PathUtils.getDirectoryPath('src/components/App.js'), 'src/components');
|
|
106
|
+
assertEqual(PathUtils.getDirectoryPath('src/App.js'), 'src');
|
|
107
|
+
assertEqual(PathUtils.getDirectoryPath('App.js'), '');
|
|
108
|
+
assertEqual(PathUtils.getDirectoryPath(''), '');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('handles git commit dialog scenarios correctly', () => {
|
|
112
|
+
// Test cases that match the commit dialog usage pattern
|
|
113
|
+
// where we extract directory from file.name
|
|
114
|
+
assertEqual(PathUtils.getDirectoryPath('src/components/Button.tsx'), 'src/components');
|
|
115
|
+
assertEqual(PathUtils.getDirectoryPath('lib/utils/helper.js'), 'lib/utils');
|
|
116
|
+
assertEqual(PathUtils.getDirectoryPath('tests/unit/test.js'), 'tests/unit');
|
|
117
|
+
assertEqual(PathUtils.getDirectoryPath('package.json'), ''); // Root level file
|
|
118
|
+
assertEqual(PathUtils.getDirectoryPath('docs/README.md'), 'docs');
|
|
119
|
+
|
|
120
|
+
// Edge cases from commit dialog
|
|
121
|
+
assertEqual(PathUtils.getDirectoryPath('very/deeply/nested/folder/structure/file.txt'), 'very/deeply/nested/folder/structure');
|
|
122
|
+
assertEqual(PathUtils.getDirectoryPath('single-level.txt'), '');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('handles edge cases in parent path', () => {
|
|
126
|
+
assertEqual(PathUtils.getParentPath('a/b/c/d/e'), 'a/b/c/d');
|
|
127
|
+
assertEqual(PathUtils.getParentPath('single'), '');
|
|
128
|
+
assertNull(PathUtils.getParentPath(''));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('handles edge cases in file path building', () => {
|
|
132
|
+
assertEqual(PathUtils.buildFilePath('a/b/c', 'file.txt'), 'a/b/c/file.txt');
|
|
133
|
+
assertEqual(PathUtils.buildFilePath('', 'README.md'), 'README.md');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
console.log('\n🎉 Path utilities tests complete!');
|