Skip to content

Commit 76b7de4

Browse files
authored
Merge pull request #362 from rajbos/unit-testing
Improve unit test setup and coverage
2 parents 7da8823 + cea0068 commit 76b7de4

File tree

59 files changed

+6679
-1319
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+6679
-1319
lines changed

.devcontainer/devcontainer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@
2727
"initializeCommand": "powershell -ExecutionPolicy Bypass -File .devcontainer/init-mounts.ps1",
2828
"mounts": [
2929
"source=${localEnv:APPDATA}/Code/User,target=/home/node/.config/Code/User,type=bind,readonly=true",
30-
"source=${localEnv:APPDATA}/Code - Insiders/User,target=/home/node/.config/Code - Insiders/User,type=bind,readonly=true"
30+
"source=${localEnv:APPDATA}/Code - Insiders/User,target=/home/node/.config/Code - Insiders/User,type=bind,readonly=true",
31+
"source=github-copilot-token-usage-nodemodules,target=/workspaces/github-copilot-token-usage/node_modules,type=volume"
3132
],
33+
"containerEnv": {
34+
"NODE_OPTIONS": "--max-old-space-size=4096"
35+
},
3236
"postCreateCommand": "npm ci",
3337
"remoteUser": "node"
3438
}

.github/agents/refactor.agent.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
description: "Improve code quality, apply security best practices, and enhance design whilst maintaining green tests."
3+
name: "Code Refactor - Improve Quality & Security"
4+
tools: ["execute/runTests", "execute/getTerminalOutput", "execute/runInTerminal", "read/terminalLastCommand", "read/terminalSelection", "search/codebase", "read/problems", "execute/testFailure"]
5+
---
6+
7+
# Code Refactor - Improve Quality & Security
8+
9+
Clean up code, apply security best practices, and enhance design whilst keeping all tests green.
10+
11+
## Core Principles
12+
13+
### Code Quality Improvements
14+
15+
- **Remove duplication** - Extract common code into reusable functions or classes
16+
- **Improve readability** - Use intention-revealing names and clear structure
17+
- **Apply SOLID principles** - Single responsibility, dependency inversion, etc.
18+
- **Simplify complexity** - Break down large functions, reduce cyclomatic complexity
19+
20+
### Security Hardening
21+
22+
- **Input validation** - Sanitise and validate all external inputs
23+
- **Authentication/Authorisation** - Implement proper access controls
24+
- **Data protection** - Encrypt sensitive data, use secure connection strings
25+
- **Error handling** - Avoid information disclosure through exception details
26+
- **Dependency scanning** - Check for vulnerable npm packages
27+
- **Secrets management** - Use environment variables or secure storage, never hard-code credentials
28+
- **OWASP compliance** - Address common security vulnerabilities
29+
30+
### Design Excellence
31+
32+
- **Design patterns** - Apply appropriate patterns (Factory, Strategy, Observer, etc.)
33+
- **Dependency injection** - Use DI for loose coupling
34+
- **Configuration management** - Externalise settings using VS Code configuration API
35+
- **Logging and monitoring** - Add structured logging for troubleshooting
36+
- **Performance optimisation** - Use async/await, efficient data structures, memoization
37+
38+
### TypeScript Best Practices
39+
40+
- **Strict type checking** - Enable strict mode in tsconfig.json
41+
- **Type safety** - Use proper types instead of `any`, leverage union types and discriminated unions
42+
- **Modern TypeScript features** - Use optional chaining, nullish coalescing, template literal types
43+
- **Immutability** - Prefer `const` and `readonly`, use immutable data patterns
44+
- **Error handling** - Use proper error types, avoid swallowing errors
45+
- **VS Code Extension API** - Follow VS Code extension best practices and API guidelines
46+
47+
## Security Checklist
48+
49+
- [ ] Input validation on all public functions
50+
- [ ] XSS protection for webview content
51+
- [ ] Command injection prevention (sanitise shell commands)
52+
- [ ] Authorisation checks on sensitive operations
53+
- [ ] Secure configuration (no secrets in code)
54+
- [ ] Error handling without information disclosure
55+
- [ ] Dependency vulnerability scanning (npm audit)
56+
- [ ] OWASP Top 10 considerations addressed
57+
58+
## Execution Guidelines
59+
60+
1. **Ensure green tests** - All tests must pass before refactoring
61+
2. **Small incremental changes** - Refactor in tiny steps, running tests frequently
62+
3. **Apply one improvement at a time** - Focus on single refactoring technique
63+
4. **Run security analysis** - Use static analysis tools (ESLint, SonarQube)
64+
5. **Document security decisions** - Add comments for security-critical code
65+
66+
## Refactor Phase Checklist
67+
68+
- [ ] Code duplication eliminated
69+
- [ ] Names clearly express intent
70+
- [ ] Functions have single responsibility
71+
- [ ] Security vulnerabilities addressed
72+
- [ ] Performance considerations applied
73+
- [ ] All tests remain green
74+
- [ ] Code coverage maintained or improved
75+
- [ ] TypeScript strict mode enabled and compliant

.github/copilot-instructions.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,40 @@ To check if data is available:
129129
[ -f ./usage-data/usage-agg-daily.json ] && echo "Aggregated data available"
130130
```
131131

132+
## DevContainer Terminal Behavior
133+
134+
This repository uses a devcontainer (`.devcontainer/devcontainer.json`). When working inside the devcontainer, **terminal output capture is unreliable** — commands execute successfully but the `run_in_terminal` tool often returns empty or truncated output. This is a known limitation of the remote filesystem layer.
135+
136+
### What NOT to do
137+
138+
Do not enter retry loops trying to capture terminal output. These patterns waste turns and never converge:
139+
- Running commands repeatedly hoping output will appear
140+
- Redirecting output to `/tmp/` files and using `read_file` to read them (the remote FS often fails on newly-written temp files)
141+
- Spawning background terminals with `sleep && tail` to poll for results
142+
- Delegating to subagents to "run tests in a clean way"
143+
144+
### What to do instead
145+
146+
1. **Use `npm` scripts for standard operations.** The project defines scripts for common tasks:
147+
- `npm run compile` — lint + build
148+
- `npm run compile-tests` — compile test files to `out/`
149+
- `npm run test:node` — compile + run a single test file
150+
- `npm run test:coverage` — compile + run tests with coverage thresholds
151+
152+
2. **Use `get_errors` to validate compilation.** After edits, call `get_errors` on the changed files instead of running `tsc` in the terminal. This is more reliable than parsing terminal output.
153+
154+
3. **Run tests in small batches.** Instead of running all 25+ test files in one command, run one file at a time:
155+
```bash
156+
node --require ./out/test/unit/vscode-shim-register.js --test out/test/unit/sessionParser.test.js
157+
```
158+
Small commands are more likely to return output before the capture times out.
159+
160+
4. **Accept a single run.** If a test command runs without returning output, do **not** re-run it. Instead, move on and note that the tests were executed but output was not captured. The user can verify locally.
161+
162+
5. **Use `runTests` tool when available.** Prefer the dedicated test-runner tool over terminal commands for running tests, though note it may not support the Node.js built-in test runner (`node --test`).
163+
164+
6. **Write output to the workspace (not `/tmp/`).** If you must capture output to a file, write it inside the workspace (e.g., `test-results.txt` in the repo root) where `read_file` can reliably access it. Add the file to `.gitignore` if it doesn't already match. Clean it up after reading.
165+
132166
## Webview Navigation Buttons
133167

134168
To maintain a consistent, VS Code-native look across all webview panels (Details, Chart, Usage Analysis, Diagnostics), use the VS Code Webview UI Toolkit for top-level navigation buttons.

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
strategy:
17+
fail-fast: false
1718
matrix:
18-
node-version: [18.x, 20.x]
19+
node-version: [20.x, 22.x, 24.x]
1920

2021
steps:
2122
- name: Harden the runner (Audit all outbound calls)
@@ -52,6 +53,9 @@ jobs:
5253

5354
- name: Compile tests
5455
run: npm run compile-tests
56+
57+
- name: Run Node.js unit tests
58+
run: node --require ./out/test/unit/vscode-shim-register.js --test out/test/unit/*.test.js
5559

5660
- name: Run tests
5761
uses: coactions/setup-xvfb@b6b4fcfb9f5a895edadc3bc76318fae0ac17c8b3 # v1.0.1

.vscode-test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { defineConfig } from '@vscode/test-cli';
22

33
export default defineConfig({
4-
files: 'out/test/**/*.test.js',
4+
files: 'out/test/integration/**/*.test.js',
55
mocha: {
66
timeout: 60000,
77
parallel: false

.vscodeignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ out
1010
out/**
1111
test
1212
test/**
13-
test-node
14-
test-node/**
1513
node_modules
1614
node_modules/**
1715
.github

docs/specs/backend.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ All settings in VS Code user settings (global scope, Settings Sync compatible):
514514
### Test Organization
515515

516516
```
517-
src/test-node/
517+
test/unit/
518518
├── backend-identity.test.ts # Identity & validation (317 lines)
519519
├── backend-settings.test.ts # Configuration parsing
520520
├── backend-rollups.test.ts # Aggregation logic (117 lines)

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@
278278
"lint:css": "stylelint \"src/webview/**/*.css\"",
279279
"lint:json": "node scripts/validate-json.js",
280280
"test": "vscode-test",
281-
"test:node": "npm run compile-tests && node --test out/test/test-node/backend-identity.test.js",
282-
"test:coverage": "npm run compile-tests && node --require ./out/test/test-node/vscode-shim-register.js --experimental-test-coverage --test --test-coverage-lines=60 --test-coverage-functions=60 --test-coverage-branches=60 --test-coverage-include=out/test/backend/**/*.js --test-coverage-include=out/test/utils/**/*.js out/test/test-node/backend-identity.test.js out/test/test-node/utils-errors.test.js out/test/test-node/backend-settings.test.js out/test/test-node/backend-copyConfig.test.js out/test/test-node/backend-integration.test.js out/test/test-node/backend-commands.test.js out/test/test-node/backend-facade-helpers.test.js out/test/test-node/backend-facade-rollups.test.js out/test/test-node/backend-facade-query.test.js",
281+
"test:node": "npm run compile-tests && node --require ./out/test/unit/vscode-shim-register.js --test --test-force-exit out/test/unit/*.test.js",
282+
"test:coverage": "npm run compile-tests && node --require ./out/test/unit/vscode-shim-register.js --experimental-test-coverage --test --test-force-exit --test-coverage-lines=80 --test-coverage-functions=80 --test-coverage-branches=60 --test-coverage-include=out/src/backend/**/*.js --test-coverage-include=out/src/utils/**/*.js out/test/unit/*.test.js",
283283
"pre-release": "node scripts/pre-release.js",
284284
"capture-screenshots": "pwsh -File scripts/capture-screenshots.ps1",
285285
"sync-changelog": "node scripts/sync-changelog.js",

src/backend/identity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const MAX_TEAM_ALIAS_LENGTH = 32;
1212
const COMMON_NAME_PATTERNS = /\b(john|jane|smith|doe|admin|user|dev|test|demo)\b/i;
1313

1414
export function validateTeamAlias(input: string): TeamAliasValidationResult {
15-
const alias = (input ?? '').trim();
15+
const alias = (input ?? '').trim().toLowerCase();
1616
if (!alias) {
1717
return {
1818
valid: false,

0 commit comments

Comments
 (0)