mirror of
https://github.com/firstsun-dev/git-files-sync.git
synced 2026-07-22 17:20:30 +00:00
- 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>
7.3 KiB
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 |