@keplog/cli 0.2.0

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +495 -0
  3. package/bin/keplog +2 -0
  4. package/dist/commands/delete.d.ts +3 -0
  5. package/dist/commands/delete.d.ts.map +1 -0
  6. package/dist/commands/delete.js +158 -0
  7. package/dist/commands/delete.js.map +1 -0
  8. package/dist/commands/init.d.ts +3 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +131 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/issues.d.ts +3 -0
  13. package/dist/commands/issues.d.ts.map +1 -0
  14. package/dist/commands/issues.js +543 -0
  15. package/dist/commands/issues.js.map +1 -0
  16. package/dist/commands/list.d.ts +3 -0
  17. package/dist/commands/list.d.ts.map +1 -0
  18. package/dist/commands/list.js +104 -0
  19. package/dist/commands/list.js.map +1 -0
  20. package/dist/commands/releases.d.ts +3 -0
  21. package/dist/commands/releases.d.ts.map +1 -0
  22. package/dist/commands/releases.js +100 -0
  23. package/dist/commands/releases.js.map +1 -0
  24. package/dist/commands/upload.d.ts +3 -0
  25. package/dist/commands/upload.d.ts.map +1 -0
  26. package/dist/commands/upload.js +76 -0
  27. package/dist/commands/upload.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +28 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/lib/config.d.ts +57 -0
  33. package/dist/lib/config.d.ts.map +1 -0
  34. package/dist/lib/config.js +155 -0
  35. package/dist/lib/config.js.map +1 -0
  36. package/dist/lib/uploader.d.ts +11 -0
  37. package/dist/lib/uploader.d.ts.map +1 -0
  38. package/dist/lib/uploader.js +171 -0
  39. package/dist/lib/uploader.js.map +1 -0
  40. package/jest.config.js +16 -0
  41. package/package.json +58 -0
  42. package/src/commands/delete.ts +186 -0
  43. package/src/commands/init.ts +137 -0
  44. package/src/commands/issues.ts +695 -0
  45. package/src/commands/list.ts +124 -0
  46. package/src/commands/releases.ts +122 -0
  47. package/src/commands/upload.ts +76 -0
  48. package/src/index.ts +31 -0
  49. package/src/lib/config.ts +138 -0
  50. package/src/lib/uploader.ts +168 -0
  51. package/tests/README.md +380 -0
  52. package/tests/config.test.ts +397 -0
  53. package/tests/uploader.test.ts +524 -0
  54. package/tsconfig.json +20 -0
@@ -0,0 +1,380 @@
1
+ # Keplog CLI Test Suite
2
+
3
+ Comprehensive unit tests for the official Keplog CLI.
4
+
5
+ ## Test Overview
6
+
7
+ ### Test Coverage
8
+
9
+ - **Total Tests**: 53 passing
10
+ - **Test Suites**: 2 (config.test.ts, uploader.test.ts)
11
+ - **Core Library Coverage**: 96%+
12
+ - `lib/config.ts`: 97.43% coverage
13
+ - `lib/uploader.ts`: 95.5% coverage
14
+
15
+ ### Test Files
16
+
17
+ #### `config.test.ts` (31 tests)
18
+
19
+ Tests for the `ConfigManager` class that handles CLI configuration.
20
+
21
+ **Coverage Areas:**
22
+ - ✅ Local config file operations (.keplog.json)
23
+ - ✅ Global config file operations (~/.keplogrc)
24
+ - ✅ Config file discovery (walks up directory tree)
25
+ - ✅ Priority system (local > global > environment variables)
26
+ - ✅ Environment variable fallbacks
27
+ - ✅ Default values
28
+ - ✅ Error handling (malformed JSON, missing files)
29
+ - ✅ Edge cases (empty strings, partial configs)
30
+
31
+ **Key Test Scenarios:**
32
+ ```typescript
33
+ // Config priority
34
+ ConfigManager.getConfig() // local > global > env vars
35
+
36
+ // Directory tree walking
37
+ project/
38
+ ├── deep/
39
+ │ └── nested/
40
+ │ └── current-dir/ <- Finds .keplog.json from root
41
+ └── .keplog.json
42
+
43
+ // Environment variable fallback
44
+ KEPLOG_PROJECT_ID=env-project // Used when file config is empty
45
+ KEPLOG_API_KEY=env-key
46
+ ```
47
+
48
+ #### `uploader.test.ts` (22 tests)
49
+
50
+ Tests for the `uploadSourceMaps` function that uploads source maps to Keplog API.
51
+
52
+ **Coverage Areas:**
53
+ - ✅ File discovery with glob patterns
54
+ - ✅ Nested directory traversal
55
+ - ✅ Multiple file patterns
56
+ - ✅ Duplicate file removal
57
+ - ✅ .map file filtering
58
+ - ✅ HTTP API communication
59
+ - ✅ Request headers and authentication
60
+ - ✅ Form data creation
61
+ - ✅ Error handling (401, 404, network errors, timeouts)
62
+ - ✅ Connection errors (ECONNREFUSED, ENOTFOUND)
63
+ - ✅ Verbose mode output
64
+ - ✅ Edge cases (large file sets, custom API URLs)
65
+
66
+ **Key Test Scenarios:**
67
+ ```typescript
68
+ // Glob pattern matching
69
+ uploadSourceMaps({
70
+ filePatterns: [
71
+ 'dist/**/*.map', // Nested directories
72
+ 'build/*.map', // Single directory
73
+ ],
74
+ // ... other options
75
+ });
76
+
77
+ // Error handling
78
+ - 401 Unauthorized (invalid API key)
79
+ - 404 Not Found (project doesn't exist)
80
+ - Network errors
81
+ - Timeout errors
82
+ - Connection refused
83
+ - DNS resolution failures
84
+ ```
85
+
86
+ ## Running Tests
87
+
88
+ ### Run All Tests
89
+ ```bash
90
+ npm test
91
+ ```
92
+
93
+ ### Watch Mode (Re-run on Changes)
94
+ ```bash
95
+ npm run test:watch
96
+ ```
97
+
98
+ ### Coverage Report
99
+ ```bash
100
+ npm run test:coverage
101
+ ```
102
+
103
+ ### Verbose Output
104
+ ```bash
105
+ npm run test:verbose
106
+ ```
107
+
108
+ ## Test Structure
109
+
110
+ ### ConfigManager Tests
111
+
112
+ ```
113
+ ConfigManager
114
+ ├── writeLocalConfig
115
+ │ ├── should write config to local .keplog.json file
116
+ │ ├── should format config file with proper indentation
117
+ │ └── should overwrite existing config
118
+ ├── writeGlobalConfig
119
+ │ └── should write config to global ~/.keplogrc file
120
+ ├── readConfig
121
+ │ ├── should read local config when it exists
122
+ │ ├── should read global config when local does not exist
123
+ │ ├── should prefer local config over global config
124
+ │ ├── should return empty object when no config exists
125
+ │ ├── should handle malformed JSON gracefully
126
+ │ └── should walk up directory tree to find local config
127
+ ├── getConfig
128
+ │ ├── should merge file config with environment variables
129
+ │ ├── should prioritize file config over environment variables
130
+ │ ├── should use environment variables when file config is empty
131
+ │ ├── should use default API URL when not specified
132
+ │ ├── should override default API URL with environment variable
133
+ │ └── should override environment API URL with file config
134
+ ├── hasLocalConfig / hasGlobalConfig
135
+ │ ├── should return true when config exists
136
+ │ └── should return false when config does not exist
137
+ ├── getLocalConfigPath
138
+ │ ├── should return config path when it exists
139
+ │ ├── should return null when config does not exist
140
+ │ └── should return parent directory config path
141
+ ├── deleteLocalConfig / deleteGlobalConfig
142
+ │ ├── should delete config file
143
+ │ └── should not throw when config does not exist
144
+ └── edge cases
145
+ ├── should handle partial config objects
146
+ ├── should handle config with only optional fields
147
+ └── should handle empty string values
148
+ ```
149
+
150
+ ### Uploader Tests
151
+
152
+ ```
153
+ uploadSourceMaps
154
+ ├── file discovery
155
+ │ ├── should find source map files matching pattern
156
+ │ ├── should find nested source map files with glob pattern
157
+ │ ├── should handle multiple file patterns
158
+ │ ├── should remove duplicate files from multiple patterns
159
+ │ ├── should exit with error when no files found
160
+ │ └── should filter out non-.map files
161
+ ├── API communication
162
+ │ ├── should send correct API request
163
+ │ ├── should include release in form data
164
+ │ ├── should handle successful upload
165
+ │ └── should exit with error when upload has errors
166
+ ├── error handling
167
+ │ ├── should handle 401 authentication error
168
+ │ ├── should handle 404 project not found
169
+ │ ├── should handle network errors
170
+ │ ├── should handle timeout errors
171
+ │ ├── should handle server connection errors
172
+ │ └── should handle DNS resolution errors
173
+ ├── verbose mode
174
+ │ ├── should display detailed information in verbose mode
175
+ │ └── should not display extra information when verbose is false
176
+ └── edge cases
177
+ ├── should handle empty release string
178
+ ├── should handle very large number of files
179
+ └── should handle custom API URL
180
+ ```
181
+
182
+ ## Testing Approach
183
+
184
+ ### Unit Testing Strategy
185
+
186
+ 1. **Isolation**: Each test runs in a temporary directory with clean state
187
+ 2. **Mocking**: External dependencies (axios, process.exit) are mocked
188
+ 3. **Coverage**: Aim for >95% code coverage on core modules
189
+ 4. **Edge Cases**: Test boundary conditions and error paths
190
+ 5. **Real Scenarios**: Test actual use cases developers will encounter
191
+
192
+ ### Test Setup/Teardown
193
+
194
+ ```typescript
195
+ beforeEach(() => {
196
+ // Create temporary test directory
197
+ testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'keplog-test-'));
198
+
199
+ // Save original state
200
+ originalCwd = process.cwd();
201
+ originalEnv = { ...process.env };
202
+
203
+ // Clean environment
204
+ process.chdir(testDir);
205
+ delete process.env.KEPLOG_PROJECT_ID;
206
+ delete process.env.KEPLOG_API_KEY;
207
+ });
208
+
209
+ afterEach(() => {
210
+ // Restore original state
211
+ process.chdir(originalCwd);
212
+ process.env = originalEnv;
213
+
214
+ // Clean up test files
215
+ fs.rmSync(testDir, { recursive: true, force: true });
216
+ });
217
+ ```
218
+
219
+ ### Mocking Strategy
220
+
221
+ #### Axios Mocking
222
+ ```typescript
223
+ import MockAdapter from 'axios-mock-adapter';
224
+
225
+ const mock = new MockAdapter(axios);
226
+
227
+ // Mock successful response
228
+ mock.onPost('/api/endpoint').reply(200, { data: 'response' });
229
+
230
+ // Mock error
231
+ mock.onPost('/api/endpoint').reply(404, { error: 'Not found' });
232
+
233
+ // Mock network error
234
+ mock.onPost('/api/endpoint').networkError();
235
+ ```
236
+
237
+ #### Process Exit Mocking
238
+ ```typescript
239
+ process.exit = jest.fn() as any;
240
+
241
+ // Test that exit was called
242
+ expect(process.exit).toHaveBeenCalledWith(1);
243
+ ```
244
+
245
+ #### Console Output Suppression
246
+ ```typescript
247
+ jest.spyOn(console, 'log').mockImplementation();
248
+ jest.spyOn(console, 'error').mockImplementation();
249
+ ```
250
+
251
+ ## Future Test Additions
252
+
253
+ ### Planned Enhancements
254
+
255
+ 1. **Integration Tests**
256
+ - End-to-end CLI command testing
257
+ - Test actual command execution
258
+ - Verify command-line argument parsing
259
+
260
+ 2. **Command Tests**
261
+ - `keplog init` - Interactive configuration setup
262
+ - `keplog upload` - Source map upload workflow
263
+ - `keplog list` - List releases
264
+ - `keplog delete` - Delete releases
265
+ - `keplog releases` - Manage releases
266
+
267
+ 3. **Error Recovery Tests**
268
+ - Partial upload failures
269
+ - Network interruption recovery
270
+ - Invalid configuration recovery
271
+
272
+ 4. **Performance Tests**
273
+ - Large file upload performance
274
+ - Many files (1000+) handling
275
+ - Memory usage profiling
276
+
277
+ ## Continuous Integration
278
+
279
+ ### Running Tests in CI
280
+
281
+ ```yaml
282
+ # GitHub Actions example
283
+ - name: Run tests
284
+ run: npm test
285
+
286
+ - name: Generate coverage report
287
+ run: npm run test:coverage
288
+
289
+ - name: Upload coverage to Codecov
290
+ uses: codecov/codecov-action@v3
291
+ ```
292
+
293
+ ### Test Quality Gates
294
+
295
+ - **Minimum Coverage**: 90% for core library modules
296
+ - **All Tests Must Pass**: No failing tests allowed in CI
297
+ - **No console warnings**: Tests should run cleanly
298
+
299
+ ## Troubleshooting
300
+
301
+ ### Common Issues
302
+
303
+ **Issue**: Tests fail with "Cannot find module"
304
+ ```bash
305
+ # Solution: Rebuild TypeScript
306
+ npm run build
307
+ ```
308
+
309
+ **Issue**: Permission errors on ~/.keplogrc
310
+ ```bash
311
+ # Solution: Clean up global config before tests
312
+ rm ~/.keplogrc
313
+ ```
314
+
315
+ **Issue**: Tests timeout
316
+ ```bash
317
+ # Solution: Increase Jest timeout in jest.config.js
318
+ testTimeout: 30000 // 30 seconds
319
+ ```
320
+
321
+ **Issue**: Path differences on macOS (/var vs /private/var)
322
+ ```typescript
323
+ // Solution: Use fs.realpathSync() for path comparisons
324
+ const expectedPath = fs.realpathSync(path.join(testDir, '.keplog.json'));
325
+ ```
326
+
327
+ ## Contributing Tests
328
+
329
+ ### Adding New Tests
330
+
331
+ 1. Create test file in `tests/` directory
332
+ 2. Import module under test
333
+ 3. Write describe/it blocks
334
+ 4. Ensure proper setup/teardown
335
+ 5. Run tests: `npm test`
336
+ 6. Check coverage: `npm run test:coverage`
337
+
338
+ ### Test Naming Conventions
339
+
340
+ ```typescript
341
+ describe('ClassName or functionName', () => {
342
+ describe('methodName or scenario', () => {
343
+ it('should do something specific', () => {
344
+ // Test implementation
345
+ });
346
+ });
347
+ });
348
+ ```
349
+
350
+ ### Test Best Practices
351
+
352
+ ✅ **DO**:
353
+ - Write descriptive test names
354
+ - Test one thing per test
355
+ - Use beforeEach/afterEach for setup/cleanup
356
+ - Mock external dependencies
357
+ - Test edge cases and error paths
358
+ - Keep tests fast (<100ms per test)
359
+
360
+ ❌ **DON'T**:
361
+ - Test implementation details
362
+ - Share state between tests
363
+ - Use real network requests
364
+ - Hardcode file paths
365
+ - Skip cleanup
366
+
367
+ ## Test Metrics
368
+
369
+ Current Status (as of latest run):
370
+ - ✅ 53 tests passing
371
+ - ✅ 0 tests failing
372
+ - ✅ 96% average coverage on core modules
373
+ - ⏱️ ~1s total test execution time
374
+
375
+ ---
376
+
377
+ **Test Suite Maintained By**: Keplog Team
378
+ **Last Updated**: December 2024
379
+ **Jest Version**: 30.2.0
380
+ **TypeScript Version**: 5.3.3