Testing Framework and Planning Skill Enhancement
Date: 2025-10-21
Status: Planning
Overview
This plan addresses two interconnected needs for the ~/.config/sh repository:
Adapt the Planning Skill - The .claude/skills/planning/SKILL.md was ported from a TypeScript project and needs updates to work with this bash scripting repository.
Establish a Testing Framework - Current tests in tests/ rely heavily on manual visual inspection rather than boolean assertions. We need a robust, automated testing framework suitable for bash scripts.
Current State Analysis
Planning Skill Issues
The current planning skill has these considerations for our bash repo:
- References
pnpm test and pnpm test:types (appropriate since we'll publish to npm)
- Discusses "type tests" which are primarily relevant to TypeScript
- References Vitest testing patterns (actually appropriate for our approach)
- Uses
tests/unit/WIP/ directory structure
- File naming conventions like
*.test.ts
- TypeScript-specific test examples
Current Testing Approach
We have three test files with varying quality:
- tests/color.sh - Purely demonstrative, requires manual visual inspection
- tests/lists.sh - Has boolean assertions with pass/fail tracking (good pattern)
- tests/file-deps.sh - Most sophisticated, uses boolean checks and structured output
Problems:
- No unified test runner
- No standardized assertion library
- No aggregate pass/fail reporting
- No CI/CD integration capability
- Tests require manual execution and review
Proposed Testing Framework
Design Principles
- Leverage TypeScript Expertise - Ken is a TypeScript expert, use Vitest
- Boolean Assertions - All automated tests must have pass/fail checks
- Hybrid Approach - TypeScript tests for automation, bash demos for visual testing
- Structured Output - Support both human-readable and machine-parseable formats
- Exit Codes - Proper exit codes for CI/CD integration
- npm Publishing Ready - Aligned with eventual npm package distribution
Framework Choice: Vitest
Rationale:
- NPM Publishing - Repo will likely be published to npm, so pnpm is already required
- Expert Alignment - Ken is TypeScript expert, leverage existing expertise
- Superior Tooling - Watch mode, UI, coverage reports, parallel execution
- Bash Testing - Easy to test bash scripts via
execSync() from TypeScript
- Best of Both Worlds - Keep visual bash demos, add robust automated tests
Hybrid Architecture
tests/
├── demos/ # Bash visual demos (manual testing)
│ ├── color-demo.sh # Interactive color showcase
│ └── showcase.sh # Feature demonstrations
├── helpers/ # TypeScript test utilities
│ └── bash.ts # Helpers for testing bash from TS
├── lists.test.ts # Automated Vitest tests
├── color.test.ts
├── file-deps.test.ts
└── WIP/ # In-progress tests (TDD workflow)
Plan Phases
Phase 0: Planning Skill Adaptation
Goals:
- Update planning skill for bash/TypeScript hybrid context
- Keep Vitest references (they're appropriate!)
- Add bash-specific testing patterns
- Preserve TDD methodology and phase-based approach
Tasks:
Update .claude/skills/planning/SKILL.md:
- Keep TypeScript/Vitest examples (they're correct for our approach)
- Add bash-specific testing patterns using bash helper
- Update to reflect hybrid approach (TypeScript tests + bash source)
- Clarify when to use demos vs automated tests
- Keep start-position.ts reference (it works well)
Update test file naming conventions:
- Automated tests:
*.test.ts
- Demo scripts:
*-demo.sh or showcase-*.sh
Update directory structure recommendations:
tests/ for automated tests
tests/demos/ for visual demonstrations
tests/WIP/ for in-progress work
tests/helpers/ for TypeScript utilities
Deliverables:
- Updated
.claude/skills/planning/SKILL.md
- Keep start-position.ts as-is (it's already TypeScript)
No TDD Required - This is documentation work
Duration: 1-2 hours
Phase 1: Vitest Setup & Bash Test Helpers
Goals:
- Set up Vitest testing infrastructure
- Create bash helper utilities for testing bash from TypeScript
- Establish test patterns and conventions
Tasks:
Package Setup:
- Create
package.json with vitest dependency
- Create
vitest.config.ts configuration
- Create
tsconfig.json for test files
- Add test scripts to package.json
Bash Test Helper (tests/helpers/bash.ts):
import { execSync } from 'child_process'
export interface BashOptions {
env?: Record<string, string>
cwd?: string
}
/**
* Execute bash script and return stdout
*/
export function bash(script: string, options?: BashOptions): string {
return execSync(script, {
shell: '/bin/bash',
encoding: 'utf-8',
cwd: options?.cwd || process.cwd(),
env: {
...process.env,
ROOT: process.cwd(),
...options?.env
}
}).trim()
}
/**
* Source a bash file and execute script
*/
export function sourcedBash(file: string, script: string, options?: BashOptions): string {
return bash(`source ${file} && ${script}`, options)
}
/**
* Execute bash and return exit code
*/
export function bashExitCode(script: string, options?: BashOptions): number {
try {
bash(script, options)
return 0
} catch (error: any) {
return error.status || 1
}
}
Example Test Pattern Documentation:
Create example in tests/helpers/example.test.ts:
import { describe, it, expect } from 'vitest'
import { sourcedBash, bashExitCode } from './bash'
describe('example: testing bash functions', () => {
it('should test bash function output', () => {
const result = sourcedBash('./utils/lists.sh', `
items=("apple" "banana" "cherry")
retain_prefixes_ref items "a" "b"
`)
expect(result).toContain('apple')
expect(result).toContain('banana')
expect(result).not.toContain('cherry')
})
it('should test bash function exit codes', () => {
const exitCode = bashExitCode(`
source ./utils/lists.sh
items=("apple" "banana")
list_contains_ref items "banana"
`)
expect(exitCode).toBe(0)
})
})
TDD Approach:
- Create
tests/WIP/bash-helper.test.ts to test the bash helper itself
- Write tests for basic bash execution
- Implement bash helper to pass tests
- Write tests for sourced bash execution
- Implement sourcedBash to pass tests
- Move from WIP to
tests/helpers/bash.test.ts
Deliverables:
package.json with vitest and scripts
vitest.config.ts
tsconfig.json
tests/helpers/bash.ts
tests/helpers/bash.test.ts (tests for the helper)
tests/helpers/example.test.ts (documentation example)
Duration: 2-3 hours
Phase 2: Migrate Existing Tests to Vitest
Goals:
- Convert existing test files to Vitest
- Separate visual demos from automated tests
- Establish patterns for the rest of the codebase
Tasks:
Migrate tests/lists.sh → tests/lists.test.ts:
- Convert all 8 tests to Vitest format
- Use
sourcedBash() helper
- Keep all existing test logic and assertions
- Remove manual pass/fail tracking (Vitest handles this)
Migrate tests/file-deps.sh → tests/file-deps.test.ts:
- Keep JSON validation approach
- Use Vitest's
expect().toMatchObject() for JSON
- Test both console and JSON output formats
- Add tests for edge cases (empty dependencies, etc.)
Convert tests/color.sh:
- Move to
tests/demos/color-demo.sh (keep as visual demo)
- Create
tests/color.test.ts for automated tests:
- Test
colorize() function output structure
- Test
rgb_text() with known RGB values
- Test color shortcut functions return non-empty strings
- Test color variables are set correctly by
setup_colors()
TDD Approach:
For each test file:
- Create new test in
tests/WIP/MODULE.test.ts
- Write tests using Vitest and bash helper
- Verify tests pass against existing functionality
- If tests fail, determine if bug in source or test
- Remove old bash test file (or move to demos/)
- Move new test from WIP to
tests/
Deliverables:
tests/lists.test.ts
tests/file-deps.test.ts
tests/color.test.ts
tests/demos/color-demo.sh (visual demo)
Duration: 2-3 hours
Phase 3: Core Utilities Test Coverage
Goals:
- Add comprehensive test coverage for critical utility functions
- Focus on most-used functions first
- Aim for 80%+ coverage of exported functions
- Fix any bugs discovered during testing
Priority Functions to Test:
From utils/ directory:
- utils/text.sh - String manipulation functions (trim, uppercase, lowercase, etc.)
- utils/typeof.sh - Type checking utilities (is_function, is_number, etc.)
- utils/filesystem.sh - File operations (file_exists, dir_exists, etc.)
- utils/empty.sh - Empty/null checking (is_empty, not_empty, etc.)
- utils/detection.sh - System detection (get_os, get_shell, etc.)
- utils/errors.sh - Error handling (panic, error, warn, etc.)
TDD Approach:
For each utility module:
- Create
tests/WIP/MODULE.test.ts
- List all exported functions in the module
- Write tests for each function:
- Happy path (normal usage)
- Edge cases (empty strings, null, undefined, boundaries)
- Error cases (invalid input)
- Run tests - many will fail initially (discovering bugs or behavior issues)
- Fix bugs in source code OR clarify test expectations
- Ensure all tests pass
- Migrate test from WIP to
tests/MODULE.test.ts
Example Test Structure:
import { describe, it, expect } from 'vitest'
import { sourcedBash, bashExitCode } from './helpers/bash'
describe('text utilities', () => {
describe('trim()', () => {
it('should remove leading and trailing whitespace', () => {
const result = sourcedBash('./utils/text.sh', `
trim " hello world "
`)
expect(result).toBe('hello world')
})
it('should handle empty string', () => {
const result = sourcedBash('./utils/text.sh', `trim ""`)
expect(result).toBe('')
})
it('should handle string with only whitespace', () => {
const result = sourcedBash('./utils/text.sh', `trim " "`)
expect(result).toBe('')
})
})
describe('uppercase()', () => {
it('should convert string to uppercase', () => {
const result = sourcedBash('./utils/text.sh', `uppercase "hello"`)
expect(result).toBe('HELLO')
})
it('should handle mixed case', () => {
const result = sourcedBash('./utils/text.sh', `uppercase "HeLLo"`)
expect(result).toBe('HELLO')
})
})
})
Deliverables:
tests/text.test.ts
tests/typeof.test.ts
tests/filesystem.test.ts
tests/empty.test.ts
tests/detection.test.ts
tests/errors.test.ts
- Bug fixes discovered during testing
- Documentation updates if function behavior is clarified
Duration: 4-6 hours
Phase 4: Documentation and CI Integration
Goals:
- Document testing conventions and best practices
- Add CI/CD integration with GitHub Actions
- Create testing guidelines for contributors
- Set up useful npm scripts
Tasks:
Create tests/README.md:
- How to run tests (
pnpm test)
- How to write tests using bash helper
- Vitest commands reference:
pnpm test - run all tests once
pnpm test:watch - run in watch mode
pnpm test:ui - open Vitest UI
pnpm test:coverage - generate coverage report
- Test writing patterns and examples
- When to use demos vs automated tests
- Best practices for testing bash from TypeScript
Update CLAUDE.md:
- Add comprehensive testing section
- Link to tests/README.md
- Document TDD expectations
- Include example of testing bash functions
- Explain hybrid approach (demos + automated tests)
Package.json scripts:
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage"
},
"devDependencies": {
"vitest": "^latest",
"@vitest/ui": "^latest",
"@vitest/coverage-v8": "^latest",
"typescript": "^latest"
}
}
Create .github/workflows/test.yml:
name: Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'pnpm'
- run: pnpm install
- run: pnpm test
Add pre-commit hook example (.git/hooks/pre-commit.example):
#!/bin/bash
# Run tests before committing
pnpm test || exit 1
Deliverables:
tests/README.md
- Updated
CLAUDE.md
- Updated
package.json with scripts
.github/workflows/test.yml
.git/hooks/pre-commit.example
Duration: 1-2 hours
Testing Standards
Test File Conventions
- Automated tests:
*.test.ts in tests/ directory
- Demo scripts:
*-demo.sh or showcase-*.sh in tests/demos/
- Helper utilities:
*.ts in tests/helpers/
- Work in progress: Use
tests/WIP/ during development
Test Organization
tests/
├── demos/ # Visual demonstration scripts
│ ├── color-demo.sh # Interactive color showcase
│ └── showcase.sh # General feature demonstrations
├── helpers/ # TypeScript test utilities
│ ├── bash.ts # Bash execution helpers
│ ├── bash.test.ts # Tests for bash helper
│ └── example.test.ts # Example/documentation
├── WIP/ # Work in progress (during TDD)
├── *.test.ts # Automated test files
└── README.md # Testing documentation
Writing Tests
Principles:
- One behavior per test - Each
it() block tests a single thing
- Descriptive names - Test names should explain what's being verified
- Arrange-Act-Assert - Clear setup, execution, and verification
- Independence - Tests should not depend on each other
- Cleanup - Clean up any temporary files/state (use
beforeEach/afterEach)
Example Pattern:
import { describe, it, expect } from 'vitest'
import { sourcedBash } from './helpers/bash'
describe('function_name', () => {
it('should handle empty input gracefully', () => {
// Arrange
const input = ""
// Act
const result = sourcedBash('./utils/module.sh', `
function_name "${input}"
`)
// Assert
expect(result).toBe('default_value')
})
it('should process normal input correctly', () => {
const result = sourcedBash('./utils/module.sh', `
function_name "test input"
`)
expect(result).toContain('test input')
})
})
Running Tests
# Install dependencies (first time)
pnpm install
# Run all tests
pnpm test
# Run tests in watch mode (auto-rerun on file changes)
pnpm test:watch
# Run tests with UI
pnpm test:ui
# Run tests with coverage report
pnpm test:coverage
# Run specific test file
pnpm test lists
# Run tests matching pattern
pnpm test --grep "retain_prefixes"
When to Use Demos vs Automated Tests
Use Demo Scripts (tests/demos/) when:
- Visual inspection is required (e.g., color output)
- Interactive demonstration of features
- Showcasing functionality to users
- Manual testing during development
Use Automated Tests (tests/*.test.ts) when:
- Boolean pass/fail verification is possible
- Testing function behavior and logic
- CI/CD integration needed
- Regression testing required
Open Questions
Should we keep start-position.ts or rewrite in bash?
- Decision: Keep TypeScript - it works well and we're using TypeScript for tests anyway
Should tests be in tests/ or co-located with source?
- Decision: Keep centralized in
tests/ - cleaner separation for bash source files
Do we need a WIP directory?
- Decision: Yes, essential for TDD workflow without breaking main test suite
Coverage threshold?
- Recommendation: Start with 80% for core utils, can adjust based on what makes sense
Success Criteria
Phase 0 (Planning Skill)
Phase 1 (Vitest Setup)
Phase 2 (Existing Tests)
Phase 3 (Coverage)
Phase 4 (Documentation)
Timeline Estimate
- Phase 0: 1-2 hours (documentation)
- Phase 1: 2-3 hours (Vitest setup and bash helper)
- Phase 2: 2-3 hours (migrate existing tests)
- Phase 3: 4-6 hours (new test coverage)
- Phase 4: 1-2 hours (documentation and CI)
Total: 10-16 hours of focused work
Next Steps
After approval of this plan:
- Begin Phase 0 - Update planning skill documentation
- Execute Phase 1 - Set up Vitest and create bash helper (with TDD)
- Checkpoint after Phase 1 to review test patterns
- Execute Phase 2 - Migrate existing tests
- Execute Phase 3 - Add coverage for core utilities
- Execute Phase 4 - Documentation and CI integration
Benefits of This Approach
- Leverages Expertise - Uses TypeScript, which Ken knows well
- NPM Ready - Aligns with npm publishing plans
- Superior DX - Watch mode, UI, coverage built-in
- Best of Both - Visual demos + robust automation
- CI/CD Ready - Proper exit codes, JSON output, GitHub Actions
- Maintainable - Industry-standard tooling, familiar to contributors
1---2name: plans-yankeeinlondon-adaptive-shell3description: This plan addresses two interconnected needs for the ~/.config/sh repository:4---5
6# Testing Framework and Planning Skill Enhancement
7
8**Date:** 2025-10-21
9
10**Status:** Planning
11
12## Overview
13
14This plan addresses two interconnected needs for the `~/.config/sh` repository:
15
161. **Adapt the Planning Skill** - The `.claude/skills/planning/SKILL.md` was ported from a TypeScript project and needs updates to work with this bash scripting repository.
17
182. **Establish a Testing Framework** - Current tests in `tests/` rely heavily on manual visual inspection rather than boolean assertions. We need a robust, automated testing framework suitable for bash scripts.
19
20## Current State Analysis
21
22### Planning Skill Issues
23
24The current planning skill has these considerations for our bash repo:
25
26- References `pnpm test` and `pnpm test:types` (appropriate since we'll publish to npm)
27- Discusses "type tests" which are primarily relevant to TypeScript
28- References Vitest testing patterns (actually appropriate for our approach)
29- Uses `tests/unit/WIP/` directory structure
30- File naming conventions like `*.test.ts`
31- TypeScript-specific test examples
32
33### Current Testing Approach
34
35We have three test files with varying quality:
36
371. **tests/color.sh** - Purely demonstrative, requires manual visual inspection
382. **tests/lists.sh** - Has boolean assertions with pass/fail tracking (good pattern)
393. **tests/file-deps.sh** - Most sophisticated, uses boolean checks and structured output
40
41**Problems:**
42
43- No unified test runner
44- No standardized assertion library
45- No aggregate pass/fail reporting
46- No CI/CD integration capability
47- Tests require manual execution and review
48
49## Proposed Testing Framework
50
51### Design Principles
52
531. **Leverage TypeScript Expertise** - Ken is a TypeScript expert, use Vitest
542. **Boolean Assertions** - All automated tests must have pass/fail checks
553. **Hybrid Approach** - TypeScript tests for automation, bash demos for visual testing
564. **Structured Output** - Support both human-readable and machine-parseable formats
575. **Exit Codes** - Proper exit codes for CI/CD integration
586. **npm Publishing Ready** - Aligned with eventual npm package distribution
59
60### Framework Choice: Vitest
61
62**Rationale:**
63
64- **NPM Publishing** - Repo will likely be published to npm, so pnpm is already required
65- **Expert Alignment** - Ken is TypeScript expert, leverage existing expertise
66- **Superior Tooling** - Watch mode, UI, coverage reports, parallel execution
67- **Bash Testing** - Easy to test bash scripts via `execSync()` from TypeScript
68- **Best of Both Worlds** - Keep visual bash demos, add robust automated tests
69
70### Hybrid Architecture
71
72```txt
73tests/
74├── demos/ # Bash visual demos (manual testing)
75│ ├── color-demo.sh # Interactive color showcase
76│ └── showcase.sh # Feature demonstrations
77├── helpers/ # TypeScript test utilities
78│ └── bash.ts # Helpers for testing bash from TS
79├── lists.test.ts # Automated Vitest tests
80├── color.test.ts
81├── file-deps.test.ts
82└── WIP/ # In-progress tests (TDD workflow)
83```
84
85## Plan Phases
86
87### Phase 0: Planning Skill Adaptation
88
89**Goals:**
90
91- Update planning skill for bash/TypeScript hybrid context
92- Keep Vitest references (they're appropriate!)
93- Add bash-specific testing patterns
94- Preserve TDD methodology and phase-based approach
95
96**Tasks:**
97
981. Update `.claude/skills/planning/SKILL.md`:
99 - Keep TypeScript/Vitest examples (they're correct for our approach)
100 - Add bash-specific testing patterns using bash helper
101 - Update to reflect hybrid approach (TypeScript tests + bash source)
102 - Clarify when to use demos vs automated tests
103 - Keep start-position.ts reference (it works well)
104
1052. Update test file naming conventions:
106 - Automated tests: `*.test.ts`
107 - Demo scripts: `*-demo.sh` or `showcase-*.sh`
108
1093. Update directory structure recommendations:
110 - `tests/` for automated tests
111 - `tests/demos/` for visual demonstrations
112 - `tests/WIP/` for in-progress work
113 - `tests/helpers/` for TypeScript utilities
114
115**Deliverables:**
116
117- Updated `.claude/skills/planning/SKILL.md`
118- Keep start-position.ts as-is (it's already TypeScript)
119
120**No TDD Required** - This is documentation work
121
122**Duration:** 1-2 hours
123
124### Phase 1: Vitest Setup & Bash Test Helpers
125
126**Goals:**
127
128- Set up Vitest testing infrastructure
129- Create bash helper utilities for testing bash from TypeScript
130- Establish test patterns and conventions
131
132**Tasks:**
133
1341. **Package Setup:**
135 - Create `package.json` with vitest dependency
136 - Create `vitest.config.ts` configuration
137 - Create `tsconfig.json` for test files
138 - Add test scripts to package.json
139
1402. **Bash Test Helper (`tests/helpers/bash.ts`):**
141
142 ```typescript
143 import { execSync } from 'child_process'
144
145 export interface BashOptions {
146 env?: Record<string, string>
147 cwd?: string
148 }
149
150 /**
151 * Execute bash script and return stdout
152 */
153 export function bash(script: string, options?: BashOptions): string {
154 return execSync(script, {
155 shell: '/bin/bash',
156 encoding: 'utf-8',
157 cwd: options?.cwd || process.cwd(),
158 env: {
159 ...process.env,
160 ROOT: process.cwd(),
161 ...options?.env
162 }
163 }).trim()
164 }
165
166 /**
167 * Source a bash file and execute script
168 */
169 export function sourcedBash(file: string, script: string, options?: BashOptions): string {
170 return bash(`source ${file} && ${script}`, options)
171 }
172
173 /**
174 * Execute bash and return exit code
175 */
176 export function bashExitCode(script: string, options?: BashOptions): number {
177 try {
178 bash(script, options)
179 return 0
180 } catch (error: any) {
181 return error.status || 1
182 }
183 }
184 ```
185
1863. **Example Test Pattern Documentation:**
187
188 Create example in `tests/helpers/example.test.ts`:
189
190 ```typescript
191 import { describe, it, expect } from 'vitest'
192 import { sourcedBash, bashExitCode } from './bash'
193
194 describe('example: testing bash functions', () => {
195 it('should test bash function output', () => {
196 const result = sourcedBash('./utils/lists.sh', `
197 items=("apple" "banana" "cherry")
198 retain_prefixes_ref items "a" "b"
199 `)
200
201 expect(result).toContain('apple')
202 expect(result).toContain('banana')
203 expect(result).not.toContain('cherry')
204 })
205
206 it('should test bash function exit codes', () => {
207 const exitCode = bashExitCode(`
208 source ./utils/lists.sh
209 items=("apple" "banana")
210 list_contains_ref items "banana"
211 `)
212
213 expect(exitCode).toBe(0)
214 })
215 })
216 ```
217
218**TDD Approach:**
219
2201. Create `tests/WIP/bash-helper.test.ts` to test the bash helper itself
2212. Write tests for basic bash execution
2223. Implement bash helper to pass tests
2234. Write tests for sourced bash execution
2245. Implement sourcedBash to pass tests
2256. Move from WIP to `tests/helpers/bash.test.ts`
226
227**Deliverables:**
228
229- `package.json` with vitest and scripts
230- `vitest.config.ts`
231- `tsconfig.json`
232- `tests/helpers/bash.ts`
233- `tests/helpers/bash.test.ts` (tests for the helper)
234- `tests/helpers/example.test.ts` (documentation example)
235
236**Duration:** 2-3 hours
237
238### Phase 2: Migrate Existing Tests to Vitest
239
240**Goals:**
241
242- Convert existing test files to Vitest
243- Separate visual demos from automated tests
244- Establish patterns for the rest of the codebase
245
246**Tasks:**
247
2481. **Migrate tests/lists.sh → tests/lists.test.ts:**
249 - Convert all 8 tests to Vitest format
250 - Use `sourcedBash()` helper
251 - Keep all existing test logic and assertions
252 - Remove manual pass/fail tracking (Vitest handles this)
253
2542. **Migrate tests/file-deps.sh → tests/file-deps.test.ts:**
255 - Keep JSON validation approach
256 - Use Vitest's `expect().toMatchObject()` for JSON
257 - Test both console and JSON output formats
258 - Add tests for edge cases (empty dependencies, etc.)
259
2603. **Convert tests/color.sh:**
261 - Move to `tests/demos/color-demo.sh` (keep as visual demo)
262 - Create `tests/color.test.ts` for automated tests:
263 - Test `colorize()` function output structure
264 - Test `rgb_text()` with known RGB values
265 - Test color shortcut functions return non-empty strings
266 - Test color variables are set correctly by `setup_colors()`
267
268**TDD Approach:**
269
270For each test file:
271
2721. Create new test in `tests/WIP/MODULE.test.ts`
2732. Write tests using Vitest and bash helper
2743. Verify tests pass against existing functionality
2754. If tests fail, determine if bug in source or test
2765. Remove old bash test file (or move to demos/)
2776. Move new test from WIP to `tests/`
278
279**Deliverables:**
280
281- `tests/lists.test.ts`
282- `tests/file-deps.test.ts`
283- `tests/color.test.ts`
284- `tests/demos/color-demo.sh` (visual demo)
285
286**Duration:** 2-3 hours
287
288### Phase 3: Core Utilities Test Coverage
289
290**Goals:**
291
292- Add comprehensive test coverage for critical utility functions
293- Focus on most-used functions first
294- Aim for 80%+ coverage of exported functions
295- Fix any bugs discovered during testing
296
297**Priority Functions to Test:**
298
299From `utils/` directory:
300
3011. **utils/text.sh** - String manipulation functions (trim, uppercase, lowercase, etc.)
3022. **utils/typeof.sh** - Type checking utilities (is_function, is_number, etc.)
3033. **utils/filesystem.sh** - File operations (file_exists, dir_exists, etc.)
3044. **utils/empty.sh** - Empty/null checking (is_empty, not_empty, etc.)
3055. **utils/detection.sh** - System detection (get_os, get_shell, etc.)
3066. **utils/errors.sh** - Error handling (panic, error, warn, etc.)
307
308**TDD Approach:**
309
310For each utility module:
311
3121. Create `tests/WIP/MODULE.test.ts`
3132. List all exported functions in the module
3143. Write tests for each function:
315 - Happy path (normal usage)
316 - Edge cases (empty strings, null, undefined, boundaries)
317 - Error cases (invalid input)
3184. Run tests - many will fail initially (discovering bugs or behavior issues)
3195. Fix bugs in source code OR clarify test expectations
3206. Ensure all tests pass
3217. Migrate test from WIP to `tests/MODULE.test.ts`
322
323**Example Test Structure:**
324
325```typescript
326import { describe, it, expect } from 'vitest'
327import { sourcedBash, bashExitCode } from './helpers/bash'
328
329describe('text utilities', () => {
330 describe('trim()', () => {
331 it('should remove leading and trailing whitespace', () => {
332 const result = sourcedBash('./utils/text.sh', `
333 trim " hello world "
334 `)
335 expect(result).toBe('hello world')
336 })
337
338 it('should handle empty string', () => {
339 const result = sourcedBash('./utils/text.sh', `trim ""`)
340 expect(result).toBe('')
341 })
342
343 it('should handle string with only whitespace', () => {
344 const result = sourcedBash('./utils/text.sh', `trim " "`)
345 expect(result).toBe('')
346 })
347 })
348
349 describe('uppercase()', () => {
350 it('should convert string to uppercase', () => {
351 const result = sourcedBash('./utils/text.sh', `uppercase "hello"`)
352 expect(result).toBe('HELLO')
353 })
354
355 it('should handle mixed case', () => {
356 const result = sourcedBash('./utils/text.sh', `uppercase "HeLLo"`)
357 expect(result).toBe('HELLO')
358 })
359 })
360})
361```
362
363**Deliverables:**
364
365- `tests/text.test.ts`
366- `tests/typeof.test.ts`
367- `tests/filesystem.test.ts`
368- `tests/empty.test.ts`
369- `tests/detection.test.ts`
370- `tests/errors.test.ts`
371- Bug fixes discovered during testing
372- Documentation updates if function behavior is clarified
373
374**Duration:** 4-6 hours
375
376### Phase 4: Documentation and CI Integration
377
378**Goals:**
379
380- Document testing conventions and best practices
381- Add CI/CD integration with GitHub Actions
382- Create testing guidelines for contributors
383- Set up useful npm scripts
384
385**Tasks:**
386
3871. **Create `tests/README.md`:**
388 - How to run tests (`pnpm test`)
389 - How to write tests using bash helper
390 - Vitest commands reference:
391 - `pnpm test` - run all tests once
392 - `pnpm test:watch` - run in watch mode
393 - `pnpm test:ui` - open Vitest UI
394 - `pnpm test:coverage` - generate coverage report
395 - Test writing patterns and examples
396 - When to use demos vs automated tests
397 - Best practices for testing bash from TypeScript
398
3992. **Update `CLAUDE.md`:**
400 - Add comprehensive testing section
401 - Link to tests/README.md
402 - Document TDD expectations
403 - Include example of testing bash functions
404 - Explain hybrid approach (demos + automated tests)
405
4063. **Package.json scripts:**
407
408 ```json
409 {
410 "scripts": {
411 "test": "vitest run",
412 "test:watch": "vitest",
413 "test:ui": "vitest --ui",
414 "test:coverage": "vitest run --coverage"
415 },
416 "devDependencies": {
417 "vitest": "^latest",
418 "@vitest/ui": "^latest",
419 "@vitest/coverage-v8": "^latest",
420 "typescript": "^latest"
421 }
422 }
423 ```
424
4254. **Create `.github/workflows/test.yml`:**
426
427 ```yaml
428 name: Tests
429
430 on:
431 push:
432 branches: [ main ]
433 pull_request:
434 branches: [ main ]
435
436 jobs:
437 test:
438 runs-on: ubuntu-latest
439
440 steps:
441 - uses: actions/checkout@v3
442
443 - uses: pnpm/action-setup@v2
444 with:
445 version: 8
446
447 - uses: actions/setup-node@v3
448 with:
449 node-version: '20'
450 cache: 'pnpm'
451
452 - run: pnpm install
453
454 - run: pnpm test
455 ```
456
4575. **Add pre-commit hook example (`.git/hooks/pre-commit.example`):**
458
459 ```bash
460 #!/bin/bash
461 # Run tests before committing
462 pnpm test || exit 1
463 ```
464
465**Deliverables:**
466
467- `tests/README.md`
468- Updated `CLAUDE.md`
469- Updated `package.json` with scripts
470- `.github/workflows/test.yml`
471- `.git/hooks/pre-commit.example`
472
473**Duration:** 1-2 hours
474
475## Testing Standards
476
477### Test File Conventions
478
479- **Automated tests:** `*.test.ts` in `tests/` directory
480- **Demo scripts:** `*-demo.sh` or `showcase-*.sh` in `tests/demos/`
481- **Helper utilities:** `*.ts` in `tests/helpers/`
482- **Work in progress:** Use `tests/WIP/` during development
483
484### Test Organization
485
486```txt
487tests/
488├── demos/ # Visual demonstration scripts
489│ ├── color-demo.sh # Interactive color showcase
490│ └── showcase.sh # General feature demonstrations
491├── helpers/ # TypeScript test utilities
492│ ├── bash.ts # Bash execution helpers
493│ ├── bash.test.ts # Tests for bash helper
494│ └── example.test.ts # Example/documentation
495├── WIP/ # Work in progress (during TDD)
496├── *.test.ts # Automated test files
497└── README.md # Testing documentation
498```
499
500### Writing Tests
501
502**Principles:**
503
5041. **One behavior per test** - Each `it()` block tests a single thing
5052. **Descriptive names** - Test names should explain what's being verified
5063. **Arrange-Act-Assert** - Clear setup, execution, and verification
5074. **Independence** - Tests should not depend on each other
5085. **Cleanup** - Clean up any temporary files/state (use `beforeEach`/`afterEach`)
509
510**Example Pattern:**
511
512```typescript
513import { describe, it, expect } from 'vitest'
514import { sourcedBash } from './helpers/bash'
515
516describe('function_name', () => {
517 it('should handle empty input gracefully', () => {
518 // Arrange
519 const input = ""
520
521 // Act
522 const result = sourcedBash('./utils/module.sh', `
523 function_name "${input}"
524 `)
525
526 // Assert
527 expect(result).toBe('default_value')
528 })
529
530 it('should process normal input correctly', () => {
531 const result = sourcedBash('./utils/module.sh', `
532 function_name "test input"
533 `)
534
535 expect(result).toContain('test input')
536 })
537})
538```
539
540### Running Tests
541
542```bash
543# Install dependencies (first time)
544pnpm install
545
546# Run all tests
547pnpm test
548
549# Run tests in watch mode (auto-rerun on file changes)
550pnpm test:watch
551
552# Run tests with UI
553pnpm test:ui
554
555# Run tests with coverage report
556pnpm test:coverage
557
558# Run specific test file
559pnpm test lists
560
561# Run tests matching pattern
562pnpm test --grep "retain_prefixes"
563```
564
565### When to Use Demos vs Automated Tests
566
567**Use Demo Scripts (`tests/demos/`) when:**
568
569- Visual inspection is required (e.g., color output)
570- Interactive demonstration of features
571- Showcasing functionality to users
572- Manual testing during development
573
574**Use Automated Tests (`tests/*.test.ts`) when:**
575
576- Boolean pass/fail verification is possible
577- Testing function behavior and logic
578- CI/CD integration needed
579- Regression testing required
580
581## Open Questions
582
5831. **Should we keep start-position.ts or rewrite in bash?**
584 - **Decision:** Keep TypeScript - it works well and we're using TypeScript for tests anyway
585
5862. **Should tests be in `tests/` or co-located with source?**
587 - **Decision:** Keep centralized in `tests/` - cleaner separation for bash source files
588
5893. **Do we need a WIP directory?**
590 - **Decision:** Yes, essential for TDD workflow without breaking main test suite
591
5924. **Coverage threshold?**
593 - **Recommendation:** Start with 80% for core utils, can adjust based on what makes sense
594
595## Success Criteria
596
597### Phase 0 (Planning Skill)
598
599- [ ] Planning skill updated for bash/TypeScript hybrid approach
600- [ ] TypeScript/Vitest references kept and clarified
601- [ ] Bash-specific testing patterns added
602- [ ] Demo vs automated test guidance provided
603
604### Phase 1 (Vitest Setup)
605
606- [ ] package.json created with vitest dependencies
607- [ ] vitest.config.ts and tsconfig.json configured
608- [ ] Bash helper implemented and tested
609- [ ] Example tests created as documentation
610- [ ] All tests pass
611
612### Phase 2 (Existing Tests)
613
614- [ ] lists.test.ts migrated with all tests passing
615- [ ] file-deps.test.ts migrated with all tests passing
616- [ ] color.test.ts created for automated tests
617- [ ] color-demo.sh moved to demos/ directory
618- [ ] All tests passing, zero regressions
619
620### Phase 3 (Coverage)
621
622- [ ] Tests exist for 6 core utility modules
623- [ ] Each exported function has at least one test
624- [ ] 80%+ coverage of critical functions
625- [ ] Any discovered bugs fixed
626- [ ] All tests passing
627
628### Phase 4 (Documentation)
629
630- [ ] tests/README.md comprehensive and clear
631- [ ] CLAUDE.md includes testing guidance
632- [ ] GitHub Actions workflow functional
633- [ ] Pre-commit hook example provided
634- [ ] All npm scripts working correctly
635
636## Timeline Estimate
637
638- **Phase 0:** 1-2 hours (documentation)
639- **Phase 1:** 2-3 hours (Vitest setup and bash helper)
640- **Phase 2:** 2-3 hours (migrate existing tests)
641- **Phase 3:** 4-6 hours (new test coverage)
642- **Phase 4:** 1-2 hours (documentation and CI)
643
644**Total:** 10-16 hours of focused work
645
646## Next Steps
647
648After approval of this plan:
649
6501. Begin Phase 0 - Update planning skill documentation
6512. Execute Phase 1 - Set up Vitest and create bash helper (with TDD)
6523. Checkpoint after Phase 1 to review test patterns
6534. Execute Phase 2 - Migrate existing tests
6545. Execute Phase 3 - Add coverage for core utilities
6556. Execute Phase 4 - Documentation and CI integration
656
657## Benefits of This Approach
658
6591. **Leverages Expertise** - Uses TypeScript, which Ken knows well
6602. **NPM Ready** - Aligns with npm publishing plans
6613. **Superior DX** - Watch mode, UI, coverage built-in
6624. **Best of Both** - Visual demos + robust automation
6635. **CI/CD Ready** - Proper exit codes, JSON output, GitHub Actions
6646. **Maintainable** - Industry-standard tooling, familiar to contributors