docs: add implementation plans for coverage work
This commit is contained in:
263
docs/plans/2025-01-20-tools-coverage-implementation.md
Normal file
263
docs/plans/2025-01-20-tools-coverage-implementation.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# Implementation Plan: 100% Tool Coverage
|
||||
|
||||
**Date:** 2025-01-20
|
||||
**Goal:** Achieve 100% test coverage on note-tools.ts and vault-tools.ts
|
||||
**Approach:** Add targeted test cases to existing test files
|
||||
|
||||
## Overview
|
||||
|
||||
This plan addresses the remaining coverage gaps in the tool modules to achieve 100% statement coverage as part of pre-release validation.
|
||||
|
||||
## Current Coverage Status
|
||||
|
||||
- **note-tools.ts:** 96.01% → Target: 100% (9 uncovered lines)
|
||||
- **vault-tools.ts:** 94.22% → Target: 100% (14 uncovered lines)
|
||||
|
||||
## Gap Analysis
|
||||
|
||||
### Note-Tools Uncovered Lines (9 lines)
|
||||
|
||||
1. **Lines 238-239:** Conflict resolution loop (when creating files with duplicate names)
|
||||
2. **Lines 377, 408, 590, 710, 836:** Folder-not-file errors (5 occurrences across different methods)
|
||||
3. **Line 647:** Include compressed data flag in Excalidraw read
|
||||
4. **Line 771:** Add frontmatter to file that has no existing frontmatter
|
||||
|
||||
### Vault-Tools Uncovered Lines (14 lines)
|
||||
|
||||
1. **Line 76:** Invalid path validation error
|
||||
2. **Line 200:** Folder assignment (possibly unreachable)
|
||||
3. **Line 267:** Skip root folder in iteration
|
||||
4. **Line 272:** Glob filtering skip
|
||||
5. **Line 325:** Alias as string (non-array) normalization
|
||||
6. **Line 374:** Folder mtime extraction error catch
|
||||
7. **Lines 452-456, 524-528:** Defensive "path doesn't exist" returns
|
||||
8. **Lines 596-597:** Glob filtering in search
|
||||
9. **Lines 608, 620:** MaxResults early termination
|
||||
10. **Line 650:** Snippet end-of-line adjustment
|
||||
11. **Line 777:** Search error catch block
|
||||
|
||||
## Implementation Tasks
|
||||
|
||||
### Task 1: Add Note-Tools Conflict Resolution Tests
|
||||
|
||||
**Objective:** Cover lines 238-239 (conflict resolution loop)
|
||||
|
||||
**Steps:**
|
||||
1. Add test: "creates file with incremented counter when conflicts exist"
|
||||
2. Mock PathUtils.fileExists to return true for "file.md" and "file 2.md"
|
||||
3. Verify creates "file 3.md"
|
||||
4. Run coverage to confirm lines 238-239 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/note-tools.test.ts`
|
||||
|
||||
**Expected outcome:** Lines 238-239 covered
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Add Note-Tools Folder-Not-File Error Tests
|
||||
|
||||
**Objective:** Cover lines 377, 408, 590, 710, 836 (folder instead of file errors)
|
||||
|
||||
**Steps:**
|
||||
1. Add test for read_note: "returns error when path is a folder"
|
||||
- Mock PathUtils.folderExists to return true
|
||||
- Verify error message uses ErrorMessages.notAFile()
|
||||
|
||||
2. Add test for rename_file: "returns error when path is a folder"
|
||||
3. Add test for update_note: "returns error when path is a folder"
|
||||
4. Add test for delete_note: "returns error when path is a folder"
|
||||
5. Add test for update_sections: "returns error when path is a folder"
|
||||
6. Run coverage to confirm all 5 lines covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/note-tools.test.ts`
|
||||
|
||||
**Expected outcome:** Lines 377, 408, 590, 710, 836 covered
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Add Note-Tools Excalidraw and Frontmatter Tests
|
||||
|
||||
**Objective:** Cover lines 647, 771
|
||||
|
||||
**Steps:**
|
||||
1. Add test for read_excalidraw: "includes compressed data when flag is true"
|
||||
- Call with includeCompressed=true
|
||||
- Verify result.compressedData is included
|
||||
|
||||
2. Add test for update_frontmatter: "adds frontmatter to file without existing frontmatter"
|
||||
- Mock file content without frontmatter
|
||||
- Update frontmatter
|
||||
- Verify frontmatter added at beginning with newline separator
|
||||
|
||||
3. Run coverage to confirm lines 647, 771 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/note-tools.test.ts`
|
||||
|
||||
**Expected outcome:** Lines 647, 771 covered, note-tools.ts at 100%
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Add Vault-Tools Invalid Path and Glob Tests
|
||||
|
||||
**Objective:** Cover lines 76, 272, 596-597
|
||||
|
||||
**Steps:**
|
||||
1. Add test for list(): "returns error for invalid vault path"
|
||||
- Mock PathUtils.isValidVaultPath to return false
|
||||
- Verify error message
|
||||
|
||||
2. Add test for list(): "filters items using glob excludes"
|
||||
- Mock GlobUtils.shouldInclude to return false for some items
|
||||
- Verify filtered items not in results
|
||||
|
||||
3. Add test for search(): "applies glob filtering to search results"
|
||||
- Provide includes/excludes patterns
|
||||
- Verify filtered files not searched
|
||||
|
||||
4. Run coverage to confirm lines 76, 272, 596-597 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/vault-tools.test.ts`
|
||||
|
||||
**Expected outcome:** Lines 76, 272, 596-597 covered
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Add Vault-Tools Edge Case Tests
|
||||
|
||||
**Objective:** Cover lines 267, 325, 374, 608, 620, 650
|
||||
|
||||
**Steps:**
|
||||
1. Add test for list(): "skips root folder in iteration"
|
||||
- Mock folder structure with root folder (path='', isRoot()=true)
|
||||
- Verify root not in results
|
||||
|
||||
2. Add test for list(): "normalizes aliases from string to array"
|
||||
- Mock cache.frontmatter.aliases as string instead of array
|
||||
- Verify result has aliases as array
|
||||
|
||||
3. Add test for getFolderMetadata(): "handles folder without mtime stat"
|
||||
- Mock folder without stat or with invalid stat
|
||||
- Verify doesn't crash, uses default mtime
|
||||
|
||||
4. Add test for search(): "stops searching when maxResults=1 reached"
|
||||
- Multiple files with matches
|
||||
- Verify only 1 result returned
|
||||
|
||||
5. Add test for search(): "adjusts snippet for long lines at end"
|
||||
- Mock line longer than snippetLength ending with match
|
||||
- Verify snippet adjustment logic (line 650)
|
||||
|
||||
6. Run coverage to confirm lines 267, 325, 374, 608, 620, 650 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/vault-tools.test.ts`
|
||||
|
||||
**Expected outcome:** Lines 267, 325, 374, 608, 620, 650 covered
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Add Vault-Tools Defensive Code Coverage
|
||||
|
||||
**Objective:** Cover lines 200, 452-456, 524-528, 777
|
||||
|
||||
**Steps:**
|
||||
1. Analyze if lines 200, 452-456, 524-528 are truly unreachable
|
||||
- If unreachable: Document why (defensive code)
|
||||
- If reachable: Add tests to trigger them
|
||||
|
||||
2. Add test for search(): "handles file read errors gracefully"
|
||||
- Mock vault.read to throw error
|
||||
- Verify error caught, logged to console, search continues
|
||||
- Covers line 777
|
||||
|
||||
3. For defensive returns (452-456, 524-528):
|
||||
- Attempt to trigger "path doesn't exist" cases
|
||||
- If impossible: Document as unreachable defensive code
|
||||
|
||||
4. Run coverage to verify maximum possible coverage
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/vault-tools.test.ts`
|
||||
- Possibly: add comments in source code marking defensive code
|
||||
|
||||
**Expected outcome:** Lines covered or documented as unreachable
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Verify 100% Coverage
|
||||
|
||||
**Objective:** Confirm 100% coverage achieved
|
||||
|
||||
**Steps:**
|
||||
1. Run `npm run test:coverage`
|
||||
2. Check coverage report:
|
||||
- note-tools.ts: 100% or documented gaps
|
||||
- vault-tools.ts: 100% or documented gaps
|
||||
3. If any gaps remain:
|
||||
- Identify what's uncovered
|
||||
- Add tests or document as unreachable
|
||||
4. Final coverage verification
|
||||
|
||||
**Expected outcome:** Both tools at 100% coverage
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Run Full Test Suite and Build
|
||||
|
||||
**Objective:** Verify no regressions
|
||||
|
||||
**Steps:**
|
||||
1. Run `npm test` - all tests must pass
|
||||
2. Run `npm run build` - must succeed
|
||||
3. Verify total test count increased
|
||||
4. Document final metrics
|
||||
|
||||
**Expected outcome:** All tests passing, build successful
|
||||
|
||||
---
|
||||
|
||||
### Task 9: Create Summary and Merge
|
||||
|
||||
**Objective:** Document and integrate work
|
||||
|
||||
**Steps:**
|
||||
1. Update IMPLEMENTATION_SUMMARY.md with:
|
||||
- Coverage improvements (before/after)
|
||||
- Test counts
|
||||
- Any unreachable code documented
|
||||
2. Use finishing-a-development-branch skill
|
||||
3. Merge to master
|
||||
|
||||
**Expected outcome:** Work merged, documentation updated
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [x] note-tools.ts at 100% statement coverage
|
||||
- [x] vault-tools.ts at 100% statement coverage
|
||||
- [x] All tests passing
|
||||
- [x] Build succeeds
|
||||
- [x] Any unreachable code documented
|
||||
- [x] Work merged to master
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
**If some lines are truly unreachable:**
|
||||
- Document with inline comments explaining why
|
||||
- Accept 99.x% if justified
|
||||
- Focus on getting all reachable code to 100%
|
||||
|
||||
**If tests become too complex:**
|
||||
- Consider minor refactoring for testability
|
||||
- Use subagent review to validate approach
|
||||
- Ensure tests remain maintainable
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- Note-tools tests: ~1 hour (7 new test cases)
|
||||
- Vault-tools tests: ~1.5 hours (10-12 new test cases)
|
||||
- Verification and cleanup: ~0.5 hours
|
||||
- **Total: ~3 hours**
|
||||
207
docs/plans/2025-01-20-utils-coverage-completion.md
Normal file
207
docs/plans/2025-01-20-utils-coverage-completion.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Implementation Plan: 100% Utils Coverage
|
||||
|
||||
**Date:** 2025-01-20
|
||||
**Goal:** Achieve 100% test coverage on all utils modules
|
||||
**Approach:** Remove dead code + Add targeted test cases
|
||||
|
||||
## Overview
|
||||
|
||||
This plan addresses the remaining coverage gaps in the utils modules to achieve 100% statement coverage as part of pre-release validation. Unlike the tools coverage work, this combines dead code removal with targeted testing.
|
||||
|
||||
## Current Coverage Status
|
||||
|
||||
- **error-messages.ts:** 82.6% → Target: 100% (lines 182-198 uncovered)
|
||||
- **version-utils.ts:** 88.88% → Target: 100% (line 52 uncovered)
|
||||
- **path-utils.ts:** 98.18% → Target: 100% (line 70 uncovered)
|
||||
- **frontmatter-utils.ts:** 96.55% → Target: 100% (lines 253-255, 310 uncovered)
|
||||
|
||||
## Gap Analysis
|
||||
|
||||
### Dead Code (To Remove)
|
||||
|
||||
1. **error-messages.ts (lines 182-198)**:
|
||||
- `permissionDenied()` - Never called anywhere in codebase
|
||||
- `formatError()` - Never called anywhere in codebase
|
||||
|
||||
2. **version-utils.ts (line 52)**:
|
||||
- `createVersionedResponse()` - Never called (only documented in CHANGELOG)
|
||||
|
||||
### Untested Code (To Test)
|
||||
|
||||
1. **path-utils.ts (line 70)**:
|
||||
- Windows absolute path validation: `/^[A-Za-z]:/` regex check
|
||||
|
||||
2. **frontmatter-utils.ts (lines 253-255)**:
|
||||
- Excalidraw parsing fallback: code fence without language specifier
|
||||
|
||||
3. **frontmatter-utils.ts (line 310)**:
|
||||
- Excalidraw decompression error handler
|
||||
|
||||
## Implementation Tasks
|
||||
|
||||
### Task 1: Remove Dead Code from error-messages.ts
|
||||
|
||||
**Objective:** Delete unused methods to improve coverage
|
||||
|
||||
**Steps:**
|
||||
1. Delete `permissionDenied()` method (lines 178-189)
|
||||
2. Delete `formatError()` method (lines 191-204)
|
||||
3. Run tests to verify no broken imports
|
||||
4. Run coverage to confirm improved percentage
|
||||
|
||||
**Files to modify:**
|
||||
- `src/utils/error-messages.ts`
|
||||
|
||||
**Expected outcome:** error-messages.ts at 100% coverage
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Remove Dead Code from version-utils.ts
|
||||
|
||||
**Objective:** Delete unused method to improve coverage
|
||||
|
||||
**Steps:**
|
||||
1. Delete `createVersionedResponse()` method (lines 48-57)
|
||||
2. Run tests to verify no broken imports
|
||||
3. Run coverage to confirm improved percentage
|
||||
|
||||
**Files to modify:**
|
||||
- `src/utils/version-utils.ts`
|
||||
|
||||
**Expected outcome:** version-utils.ts at 100% coverage
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Clean Up CHANGELOG.md
|
||||
|
||||
**Objective:** Remove references to deleted code
|
||||
|
||||
**Steps:**
|
||||
1. Remove `createVersionedResponse()` reference from line 282
|
||||
2. Keep surrounding context intact
|
||||
3. Verify file still well-formed
|
||||
|
||||
**Files to modify:**
|
||||
- `CHANGELOG.md`
|
||||
|
||||
**Expected outcome:** CHANGELOG accurate to current codebase
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Add path-utils Windows Absolute Path Tests
|
||||
|
||||
**Objective:** Cover line 70 (Windows path validation)
|
||||
|
||||
**Steps:**
|
||||
1. Add test: "rejects Windows absolute paths (C: drive)"
|
||||
- Test `isValidVaultPath('C:\\Users\\file.md')` returns false
|
||||
2. Add test: "rejects Windows absolute paths (D: drive)"
|
||||
- Test `isValidVaultPath('D:\\Documents\\note.md')` returns false
|
||||
3. Run coverage to confirm line 70 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/path-utils.test.ts`
|
||||
|
||||
**Expected outcome:** path-utils.ts at 100% coverage
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Add frontmatter-utils Code Fence Fallback Test
|
||||
|
||||
**Objective:** Cover lines 253-255 (code fence without language specifier)
|
||||
|
||||
**Steps:**
|
||||
1. Create Excalidraw note with ` ``` ` fence (no language)
|
||||
2. Add test: "parses Excalidraw with code fence lacking language specifier"
|
||||
3. Call `parseExcalidrawMetadata()` on content
|
||||
4. Verify JSON parsed correctly
|
||||
5. Run coverage to confirm lines 253-255 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/frontmatter-utils.test.ts`
|
||||
|
||||
**Expected outcome:** Lines 253-255 covered
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Add frontmatter-utils Decompression Failure Test
|
||||
|
||||
**Objective:** Cover line 310 (decompression error handler)
|
||||
|
||||
**Steps:**
|
||||
1. Create Excalidraw note with invalid compressed data
|
||||
2. Add test: "handles decompression failure gracefully"
|
||||
3. Mock or create scenario where decompression throws error
|
||||
4. Verify graceful fallback with `hasCompressedData: true`
|
||||
5. Run coverage to confirm line 310 covered
|
||||
|
||||
**Files to modify:**
|
||||
- `tests/frontmatter-utils.test.ts`
|
||||
|
||||
**Expected outcome:** frontmatter-utils.ts at 100% coverage
|
||||
|
||||
---
|
||||
|
||||
### Task 7: Verify 100% Coverage
|
||||
|
||||
**Objective:** Confirm 100% coverage achieved on all utils
|
||||
|
||||
**Steps:**
|
||||
1. Run `npm run test:coverage`
|
||||
2. Check coverage report:
|
||||
- error-messages.ts: 100%
|
||||
- version-utils.ts: 100%
|
||||
- path-utils.ts: 100%
|
||||
- frontmatter-utils.ts: 100%
|
||||
3. If any gaps remain:
|
||||
- Identify what's uncovered
|
||||
- Add tests or document as unreachable
|
||||
4. Final coverage verification
|
||||
|
||||
**Expected outcome:** All 4 utils at 100% coverage
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Create Summary and Merge
|
||||
|
||||
**Objective:** Document and integrate work
|
||||
|
||||
**Steps:**
|
||||
1. Create `UTILS_COVERAGE_SUMMARY.md` with:
|
||||
- Coverage improvements (before/after)
|
||||
- Test counts
|
||||
- Dead code removed
|
||||
2. Use finishing-a-development-branch skill
|
||||
3. Merge to master
|
||||
|
||||
**Expected outcome:** Work merged, documentation updated
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] error-messages.ts at 100% statement coverage
|
||||
- [ ] version-utils.ts at 100% statement coverage
|
||||
- [ ] path-utils.ts at 100% statement coverage
|
||||
- [ ] frontmatter-utils.ts at 100% statement coverage
|
||||
- [ ] All tests passing (505+)
|
||||
- [ ] Build succeeds
|
||||
- [ ] Dead code removed cleanly
|
||||
- [ ] Work merged to master
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
**If dead code is actually used:**
|
||||
- Full test suite will catch broken imports immediately
|
||||
- TypeScript compilation will fail if methods are referenced
|
||||
- Git revert available if needed
|
||||
|
||||
**If edge case tests are too complex:**
|
||||
- Document specific difficulty encountered
|
||||
- Consider if code is truly reachable
|
||||
- Mark with istanbul ignore if unreachable
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- Dead code removal: ~15 minutes (3 simple deletions)
|
||||
- Test additions: ~20 minutes (3 test cases)
|
||||
- Verification and cleanup: ~10 minutes
|
||||
- **Total: ~45 minutes**
|
||||
Reference in New Issue
Block a user