From e3ab2f18f5a14aeeb080acef72dfcc6d0283fd79 Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 20 Oct 2025 11:12:16 -0400 Subject: [PATCH] docs: add implementation plans for coverage work --- ...025-01-20-tools-coverage-implementation.md | 263 ++++++++++++++++++ .../2025-01-20-utils-coverage-completion.md | 207 ++++++++++++++ 2 files changed, 470 insertions(+) create mode 100644 docs/plans/2025-01-20-tools-coverage-implementation.md create mode 100644 docs/plans/2025-01-20-utils-coverage-completion.md diff --git a/docs/plans/2025-01-20-tools-coverage-implementation.md b/docs/plans/2025-01-20-tools-coverage-implementation.md new file mode 100644 index 0000000..8e3a33a --- /dev/null +++ b/docs/plans/2025-01-20-tools-coverage-implementation.md @@ -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** diff --git a/docs/plans/2025-01-20-utils-coverage-completion.md b/docs/plans/2025-01-20-utils-coverage-completion.md new file mode 100644 index 0000000..9b76e3d --- /dev/null +++ b/docs/plans/2025-01-20-utils-coverage-completion.md @@ -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**