firstsun-dev_git-files-sync/docs/test-coverage.md
ClaudiaFang fcb9447733 test: expand coverage for binary files, hidden paths, and edge cases
- Add sync-manager-binary.test.ts: push/pull ArrayBuffer via adapter.readBinary/writeBinary
- Add sync-manager-hidden.test.ts: hidden path mkdir, push, pull via string paths
- Add utils/path.test.ts: isBinaryPath and contentsEqual full coverage
- Add metadata-on-equal assertion to sync-manager tests
- Add GitHub truncated result and GitLab pagination boundary tests
- Add hidden file gitignore filter tests
- Add docs/test-coverage.md with all 189 test cases documented

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 03:35:36 +00:00

7.3 KiB

Test Coverage

All tests are in tests/ and run with npm run test (Vitest).


utils/path — tests/utils/path.test.ts

isBinaryPath()

Group Cases
Image formats png, jpg, gif, bmp, webp (legacy); heic, heif, avif, tiff, tif, jxl (modern)
Audio formats mp3, wav, ogg, flac, aac, m4a, opus, aiff
Video formats mp4, webm, mov, mkv, avi, wmv, flv, m4v
Archive formats zip, tar, gz, bz2, xz, zst, 7z, rar
Font formats ttf, otf, woff, woff2
Database formats sqlite, db
Text files md, json, ts, yml, txt → returns false
Hidden file paths .gitignore, .env → false; .claude/settings.json → false; .claude/photo.png → true
Case insensitivity .PNG, .JPG, .FLAC
BINARY_EXTENSIONS completeness Set membership checks for major categories

contentsEqual()

Group Cases
String identical, different, empty, case-sensitive
ArrayBuffer identical, different bytes, different lengths, empty buffers
Mixed types string vs ArrayBuffer → false

logic/SyncManager — tests/logic/sync-manager.test.ts

Case
Push file content correctly
Detect conflict when remote SHA differs from last synced SHA
Resolve conflict by choosing local
Resolve conflict by choosing remote
Update metadata when file is already in sync (contentsEqual)
Update metadata after successful push
Pull and modify file content, update metadata
Handle file not existing in vault
Add new file to repo when exists locally but not on remote
Renames: detect and handle file rename
Error handling: push errors, rename errors
pullFile: file not in remote, pull new file, pull errors

logic/SyncManager Batch — tests/logic/sync-manager-batch.test.ts

Case
Push multiple files (TFile and string paths)
Handle failures during batch push
Pull multiple files (TFile and string paths)
Handle missing remote files during batch pull
onProgress callback called for each file
Detect and handle rename during batch push

logic/SyncManager Path Mapping — tests/logic/sync-manager-mapping.test.ts

Case
Strip vaultFolder prefix when pushing
Re-add vaultFolder prefix when pulling
Handle root-level files with no vaultFolder

logic/SyncManager Binary Files — tests/logic/sync-manager-binary.test.ts

pushFile with binary path (string)

Case
Reads via adapter.readBinary for binary extensions
Skips push when binary content is already in sync
Updates metadata when binary is already in sync

pullFile with binary content

Case
Writes via adapter.writeBinary when remote content is ArrayBuffer
Creates parent directory before writing binary
Skips pull when binary content is already in sync
Updates metadata after pulling binary file

logic/SyncManager Hidden Files — tests/logic/sync-manager-hidden.test.ts

pullFile with hidden paths

Case
Creates single hidden parent directory (.claude/) on pull
Creates all nested hidden parent directories (.claude/memory/) on pull
Does not throw if hidden directory already exists (mkdir error is swallowed)
Updates syncMetadata after pulling hidden file

pushFile with hidden paths

Case
Pushes hidden file content via string path
Skips push when hidden file is already in sync (same content)
Does not push when hidden file is missing from vault

logic/GitignoreManager — tests/logic/gitignore-manager.test.ts

loadGitignores()

Case
Load root .gitignore from local if it exists
Load gitignores from remote as fallback
Fall back to [".gitignore"] when getRepoGitignores throws
Fall back to remote when local .gitignore read throws
Handle subdirectory .gitignores correctly
Pick up local-only subdirectory .gitignore not yet on remote

isIgnored() with rootPath

Case
Correctly resolve paths relative to git root

Complex patterns

Case
Negative patterns (!important.log)
Directory-only patterns (build/)
Deep wildcards (**/temp/*)

Hidden file and directory filtering

Case
Ignore hidden directory when listed in .gitignore (.obsidian/, .trash/)
Pass through hidden directory absent from .gitignore (.claude/)
Ignore .claude/ when explicitly added to .gitignore
Pass normal files when only hidden dirs are ignored
Find .gitignore inside a hidden directory via scanDir

services/GitServiceBase — tests/services/git-service-base.test.ts

Case
No double-slash when rootPath already ends with /
Wrap non-Error throws in a new Error
Correctly encode and decode UTF-8 content

services/GitHubService — tests/services/github-service.test.ts

Group Cases
getFile fetch and decode content, 404 handling, bypass rootPath with / prefix, no double-prefix, return sha
pushFile new file (no sha), update existing file (with sha)
listFiles list blob files, filter by rootPath, no sibling path collision, truncated result warning
deleteFile delete using file sha

services/GitLabService — tests/services/gitlab-service.test.ts

Group Cases
getFile fetch and decode content, 404 handling, return last_commit_id as sha
pushFile POST for new file, PUT for existing file
listFiles list blob files, filter by rootPath, no sibling path collision, pagination boundary (100 items), multi-page (200 items), stop on partial page
deleteFile delete with commit message

ui/ActionBar — tests/ui/ActionBar.test.ts

Group Cases
No files always renders refresh button; no push/pull/delete; no select-all
Has files renders push, pull, delete, select-all; disabled states when count is 0; enabled when count > 0
Interactions onRefresh, onPush, onPull, onDelete, onSelectAll(true/false)

ui/DiffPanel — tests/ui/DiffPanel.test.ts

Case
Returns element with ssv-diff class
Renders Remote and Local column headers
Renders unchanged lines
Renders added line
Renders removed line
Renders replacement (removed + added)
Renders unchanged lines for identical content

ui/FileListItem — tests/ui/FileListItem.test.ts

Group Cases
Status CSS distinct class for each status
Rendering file path, status badge, checkbox (selected/unselected)
Interactions onSelect(path, true/false)
Synced status no action buttons
Remote-only status no action buttons
Modified status push + pull buttons; onPush/onPull callbacks; diff toggle; diff panel visibility toggle; diff button label toggle
Local-only status push + delete buttons; no pull; onDelete callback
Missing status pull button; no push

utils/diff — tests/utils/diff.test.ts

Group Cases
Identical content single-line, multi-line, empty strings
CRLF normalisation CRLF = LF, CR-only
Additions only single added line, multiple added lines, single-line change
Removals only single removed line, multiple removed lines
Mixed changes paired removed+added, unchanged lines between changes
Line numbers correct numbering