testing
Testing Approach
Section titled “Testing Approach”Testing strategy for the project.
Test Levels
Section titled “Test Levels”Unit Tests
Section titled “Unit Tests”Scope: Individual functions and classes
Location: */tests/unit/
Tools: Jest/Vitest
Focus:
- CRDT state manager
- Permission checking
- Audit logger
Integration Tests
Section titled “Integration Tests”Scope: Component interactions
Location: */tests/integration/
Tools: Jest + Docker
Focus:
- Sync daemon ↔ Yjs server
- Plugin ↔ state files
- Orchestrator ↔ IdP
End-to-End Tests
Section titled “End-to-End Tests”Scope: Full user flows
Location: tests/e2e/
Tools: Playwright (for web UI)
Focus:
- Two users editing simultaneously
- Vault access control
- Session persistence
Test Scenarios
Section titled “Test Scenarios”CRDT Sync
Section titled “CRDT Sync”| Scenario | Expected |
|---|---|
| User A edits, User B opens | B sees A’s changes |
| Both edit same paragraph | Merged content |
| Both edit different sections | Both changes preserved |
| Large file sync | Completes in < 5s |
| Binary attachment | Synced via MinIO |
Access Control
Section titled “Access Control”| Scenario | Expected |
|---|---|
| User with access | Vault mounts |
| User without access | Vault not visible |
| User group changes | Access reflects on next session |
| Invalid token | Access denied |
Presence
Section titled “Presence”| Scenario | Expected |
|---|---|
| User opens file | Others see presence |
| User closes file | Presence clears |
| User moves cursor | Position updates |
Testing Obsidian Plugin
Section titled “Testing Obsidian Plugin”Challenge
Section titled “Challenge”Obsidian can’t be automated headlessly. Plugin testing requires:
- Build plugin
- Install in test vault
- Open Obsidian
- Test manually
Approach
Section titled “Approach”- Unit test core logic - State manager, identity, sync logic
- Mock Obsidian API - For integration tests
- Manual testing - For UI and file hooks
- Debug log file - For persistent debugging
Test Vault
Section titled “Test Vault”Location: obsidian-plugin/test-vault/
Pre-configured with:
- Sample markdown files
- Plugin enabled
- Debug logging on
CI/CD Integration
Section titled “CI/CD Integration”GitHub Actions
Section titled “GitHub Actions”on: [push, pull_request]jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run sync-daemon tests run: cd sync-daemon && npm test - name: Run orchestrator tests run: cd orchestrator && npm testPre-commit Hooks
Section titled “Pre-commit Hooks”- Lint (ESLint)
- Type check (tsc)
- Unit tests
Test Data
Section titled “Test Data”Sample Vaults
Section titled “Sample Vaults”| Vault | Purpose |
|---|---|
| demo | Basic testing |
| large-vault | Performance testing (1000+ files) |
| conflict-test | Conflict resolution scenarios |
User Accounts
Section titled “User Accounts”| User | Groups | Purpose |
|---|---|---|
| alice | engineering | Standard user |
| bob | engineering, devops | Multi-group |
| carol | finance | Different department |
| admin | all | Admin testing |
Performance Testing
Section titled “Performance Testing”Metrics
Section titled “Metrics”- Sync latency (target: < 5s)
- VNC latency (target: < 200ms)
- File open time (target: < 1s)
- Memory usage (target: < 500MB/user)
- k6 for load testing
- Grafana for monitoring
Multi-Instance Sync Testing
Section titled “Multi-Instance Sync Testing”For testing CRDT sync with concurrent edits, we run multiple Obsidian instances sharing the same filesystem.
Compose file: docker-compose.test.yml
# Start multi-instance test environmentdocker-compose -f docker-compose.test.yml up -d
# Alice: https://localhost:3101# Bob: https://localhost:3201Three approaches (layered by complexity):
| Approach | What It Tests | Infrastructure |
|---|---|---|
| A: Docker-Only | Our CRDT sync, presence, merge | Two containers + Yjs server |
| B: Docker + Tailscale | Above + Obsidian Sync device identity | Add Tailscale sidecars + unique machine IDs |
| C: Separate Hosts | True multi-device over WireGuard mesh | Multiple machines on tailnet |
What makes instances “different”:
- Plugin client ID: auto-generated UUID v4 per install (
identity.ts) - Sync daemon USER_ID: set via environment variable per container
- WebSocket connections: separate per daemon process
- For Obsidian Sync: unique
/var/lib/dbus/machine-id+ Tailscale identity
Shared vault: vaults/shared-test/ — bind-mounted into both containers.
Per-instance config: Separate Docker volumes for /config (isolates .obsidian/).
See 2026-03-28-multi-instance-sync-testing for full analysis and Tailscale integration details.
Known Limitations
Section titled “Known Limitations”- No headless Obsidian - Can’t automate plugin UI tests
- VNC testing - Requires visual verification
- CRDT determinism - Hard to test edge cases