Skip to content

Commit 548ea08

Browse files
damlayildizclaudeGioee
authored
feat: updates to support new cloudsync version (#3)
* fix: parse JSON response from cloudsync_network_sync * chore: add test-suite plan * chore: add @testing-library/react-native for hook tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add shared mocks for native modules Mock files for op-sqlite, NetInfo, expo-notifications, expo-secure-store, expo-task-manager, expo-constants, and expo-application. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add pure function and createDatabase tests (46 tests) - testUtils.tsx with createTestWrapper for hook tests - calculateAdaptiveSyncInterval (10 tests) - isSqliteCloudNotification (12 tests) - logger (8 tests) - pushNotificationSyncCallbacks (5 tests) - constants (2 tests) - createDatabase (9 tests) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add core logic tests (67 tests) - initializeSyncExtension (11 tests) - executeSync (14 tests) - backgroundSyncConfig (10 tests) - backgroundSyncRegistry (7 tests) - executeBackgroundSync (13 tests) - registerPushToken (12 tests) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add pushNotificationSyncTask, optionalDependencies, and context hook tests (28 tests) - pushNotificationSyncTask (8 tests) - optionalDependencies (10 tests) - useSqliteDb (2 tests) - useSyncStatus (2 tests) - useSqliteSync (2 tests) - useInternalLogger (2 tests) - useTriggerSqliteSync (2 tests) - Fix react-test-renderer version to match react 19.1.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add hook tests for useSqliteExecute, useSqliteTransaction, useOnTableUpdate, useInitialSync Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add complex hook tests for sync manager, lifecycle, polling, push notifications, and reactive queries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add useDatabaseInitialization and SQLiteSyncProvider integration tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add coverage for permission fallback, auth, and config in SQLiteSyncProvider Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update gitignore * fix: skip push token registration when siteId is unavailable When cloudsync_init fails or returns no siteId, skip registerPushToken entirely instead of registering with undefined siteId. The registration will retry on next app open since hasRequestedPermissionsRef resets on mount. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add Tier 1 coverage gap tests (262 total, 82.96% branches) Add 10 targeted tests covering uncovered branches: - useDatabaseInitialization: empty name, empty tables, close errors - useSqliteExecute/Transaction: non-Error thrown value wrapping - useSqliteSyncQuery: debounce timer clearing on query change - usePushNotificationSync: registerPushToken failure handling - isSqliteCloudNotification: Android dataString wrong URI - useSyncManager: push-mode error skips interval recalculation * test: add Tier 2 coverage gap tests (272 total, 85.47% branches) Add 10 targeted tests covering additional uncovered branches: - logger: default parameter (debug=false) branch - useNetworkListener: null isInternetReachable/isConnected coercion - useAdaptivePollingSync: interval-to-null stops scheduling - useOnTableUpdate: empty rows returns null row - useSyncManager: Android with null isInternetReachable - initializeSyncExtension: empty rows, site_id logging branches - useSqliteSyncQuery: stale subscription signature skip * test: suppress console.warn leak in backgroundSyncRegistry test * chore: update .claude/plans/test-suite-design.md * fix: correct push token registration auth header and base URL - Change auth header from Bearer connectionString?apikey=key to Bearer apiKey - Update base URL to cloudsync-staging-testing.fly.dev - Remove unused connectionString param from registerPushToken * fix: resolve TypeScript errors across test files Add jest and node types to tsconfig.json, fix missing required fields (syncMode, siteId, createTableSql) in test mocks, correct adaptive config field names, and prefix unused variables with underscore. * fix: imports * fix: update network_init params * fix: initializeSyncExtension * fix: push fallback behavior * fix: register push token endpoint call * fix: isSqliteCloudNotification * fix: update cloudsync commands / endpoints usage * fix: .env.example * fix: .env files * fix: env variables * fix: custom network init * chore: bump version to 0.9.201 * chore: update documentation * chore: update documentation * chore: update documentation * chore: update documentation * chore: update documentation * tests: improve coverage * fix: use sqlite-sync main repo instead of dev one * chore: update cloudsync url to be the production one --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Gioele Cantoni <gioele.cantoni@gmail.com> Co-authored-by: Gioele Cantoni <48024736+Gioee@users.noreply.github.com>
1 parent 1fcffd5 commit 548ea08

File tree

78 files changed

+7395
-648
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+7395
-648
lines changed

.claude/plans/test-suite.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Test Suite
2+
3+
**Status:** Implemented
4+
**Last updated:** 2026-03-20
5+
**Total:** 33 test files, 305 tests
6+
7+
## How to Run
8+
9+
```bash
10+
# Run all tests
11+
yarn test
12+
13+
# Run with coverage report
14+
yarn test:coverage
15+
16+
# Open HTML coverage report
17+
open coverage/lcov-report/index.html
18+
```
19+
20+
## Stack
21+
22+
- **Runner:** Jest (react-native preset)
23+
- **Hooks:** `renderHook` from `@testing-library/react-native`
24+
- **Mocks:** Co-located `__mocks__/` directories for native modules
25+
- **Coverage thresholds:** statements 95, branches 85, functions 95, lines 95
26+
27+
## Architecture
28+
29+
Tests are co-located next to source files in `__tests__/` directories, organized in 5 layers:
30+
31+
1. **Pure functions** — no mocks needed
32+
2. **Core logic** — mocked native modules (op-sqlite, NetInfo, Expo)
33+
3. **Context consumer hooks** — wrapped in test providers
34+
4. **Complex hooks** — renderHook with mocked dependencies
35+
5. **Integration** — SQLiteSyncProvider rendering
36+
37+
## Shared Mocks
38+
39+
Located in `src/__mocks__/`:
40+
41+
| Mock | What it provides |
42+
|------|-----------------|
43+
| `@op-engineering/op-sqlite` | `createMockDB()`, `open()`, `getDylibPath()` |
44+
| `@react-native-community/netinfo` | `addEventListener`, `fetch`, `__emit()` |
45+
| `react-native` | `AppState`, `Platform` |
46+
| `expo-notifications` | Token, permissions, listeners |
47+
| `expo-secure-store` | `getItemAsync`, `setItemAsync`, `deleteItemAsync` |
48+
| `expo-task-manager` | `defineTask`, `isTaskRegisteredAsync` |
49+
| `expo-constants` | `expoConfig.extra` |
50+
| `expo-application` | `getIosIdForVendorAsync`, `getAndroidId` |
51+
52+
Test utilities in `src/testUtils.tsx` provide `createTestWrapper` for provider-wrapped hook tests.
53+
54+
## Test Files (33 files, 305 tests)
55+
56+
### Layer 1: Pure Functions (39 tests)
57+
58+
| Test file | Source | Tests | What's tested |
59+
|-----------|--------|------:|---------------|
60+
| `core/polling/__tests__/calculateAdaptiveSyncInterval.test.ts` | calculateAdaptiveSyncInterval | 10 | Base interval, idle backoff at threshold, exponential error backoff, caps at maxInterval, error priority over idle |
61+
| `core/pushNotifications/__tests__/isSqliteCloudNotification.test.ts` | isSqliteCloudNotification | 13 | Foreground valid/invalid URI, iOS background body, Android JSON string body, Android dataString fallback, invalid JSON, wrong URI, empty data |
62+
| `core/common/__tests__/logger.test.ts` | logger | 9 | debug=true logs info/warn, debug=false suppresses, error always logs, [SQLiteSync] prefix, ISO timestamp, default debug=false |
63+
| `core/pushNotifications/__tests__/pushNotificationSyncCallbacks.test.ts` | pushNotificationSyncCallbacks | 5 | Register/get background callback, null default, set/get/clear foreground callback |
64+
| `core/__tests__/constants.test.ts` | constants | 2 | FOREGROUND_DEBOUNCE_MS value, BACKGROUND_SYNC_TASK_NAME non-empty |
65+
66+
### Layer 2: Core Logic (97 tests)
67+
68+
| Test file | Source | Tests | What's tested |
69+
|-----------|--------|------:|---------------|
70+
| `core/database/__tests__/createDatabase.test.ts` | createDatabase | 9 | Opens DB, WAL journal mode, write mode pragmas, read mode pragmas, returns DB, propagates open/pragma errors |
71+
| `core/sync/__tests__/initializeSyncExtension.test.ts` | initializeSyncExtension | 14 | Missing connectionString/auth validation, iOS/Android extension paths, version check, cloudsync_init per table, network_init, API key/accessToken auth, siteId logging |
72+
| `core/sync/__tests__/executeSync.test.ts` | executeSync | 14 | JS retry loop (returns 0/count, stops on changes, max attempts, transaction wrapping, malformed JSON), native retry passthrough |
73+
| `core/background/__tests__/backgroundSyncConfig.test.ts` | backgroundSyncConfig | 10 | Persist/get/clear config, null without SecureStore, parse errors, warn/error handling |
74+
| `core/background/__tests__/backgroundSyncRegistry.test.ts` | backgroundSyncRegistry | 7 | Register (persist + task), unregister (task + clear), warns when unavailable, error handling |
75+
| `core/background/__tests__/executeBackgroundSync.test.ts` | executeBackgroundSync | 13 | Opens DB, inits sync, executes with native retry, updateHook callback, changes collection, DB close in finally, error rethrow, close error handling |
76+
| `core/pushNotifications/__tests__/registerPushToken.test.ts` | registerPushToken | 12 | Skip duplicate, correct URL, accessToken/apiKey auth headers, body fields, iOS/Android device ID, non-ok response, persist after success, SecureStore read/write errors, missing expo-application |
77+
| `core/pushNotifications/__tests__/pushNotificationSyncTask.test.ts` | pushNotificationSyncTask | 8 | Task definition with/without ExpoTaskManager, handler routes to background sync, skips non-SQLite notification, foreground callback when app active, error handling, skip without config |
78+
| `core/common/__tests__/optionalDependencies.test.ts` | optionalDependencies | 10 | Each Expo module available/null, ExpoConstants .default fallback, isBackgroundSyncAvailable (all present vs any missing) |
79+
80+
### Layer 3: Context Consumer Hooks (10 tests)
81+
82+
| Test file | Source | Tests | What's tested |
83+
|-----------|--------|------:|---------------|
84+
| `hooks/context/__tests__/useSqliteDb.test.ts` | useSqliteDb | 2 | Returns writeDb/readDb/initError from context, null defaults |
85+
| `hooks/context/__tests__/useSyncStatus.test.ts` | useSyncStatus | 2 | Returns all status fields, default values |
86+
| `hooks/context/__tests__/useSqliteSync.test.ts` | useSqliteSync | 2 | Returns merged contexts, triggerSync callable |
87+
| `core/common/__tests__/useInternalLogger.test.ts` | useInternalLogger | 2 | Returns logger from context, has info/warn/error methods |
88+
| `hooks/sync/__tests__/useTriggerSqliteSync.test.ts` | useTriggerSqliteSync | 2 | Returns triggerSync, calls through to context |
89+
90+
### Layer 4: Complex Hooks (112 tests)
91+
92+
_Includes useDatabaseInitialization which spans init + lifecycle._
93+
94+
| Test file | Source | Tests | What's tested |
95+
|-----------|--------|------:|---------------|
96+
| `hooks/sqlite/__tests__/useSqliteExecute.test.ts` | useSqliteExecute | 10 | Undefined when no db, execute on writeDb/readDb, error state, clears error, auto-sync after write, skip on readOnly/autoSync=false, non-Error wrapping |
97+
| `hooks/sqlite/__tests__/useSqliteTransaction.test.ts` | useSqliteTransaction | 8 | Undefined when no writeDb, calls transaction, error state, clears error, auto-sync after commit, skip autoSync=false, non-Error wrapping |
98+
| `hooks/sqlite/__tests__/useOnTableUpdate.test.ts` | useOnTableUpdate | 8 | Register/remove updateHook, table filtering, null row for DELETE, empty rows, fetch error, no-op when null |
99+
| `hooks/sync/__tests__/useSqliteSyncQuery.test.ts` | useSqliteSyncQuery | 10 | Loading state, initial read, error, reactive subscription after debounce, callback updates, unmount cleanup, debounce clearing, stale subscription skip, unsubscribe |
100+
| `core/sync/__tests__/useSyncManager.test.ts` | useSyncManager | 16 | Null db/not ready guards, sync lifecycle, empty sync counters, error state, interval recalculation (polling vs push), concurrent sync prevention, Android network check, error backoff |
101+
| `core/sync/__tests__/useInitialSync.test.ts` | useInitialSync | 4 | Delayed trigger after 1500ms, not ready guard, once-only, cleanup on unmount |
102+
| `core/lifecycle/__tests__/useAppLifecycle.test.ts` | useAppLifecycle | 10 | Register/remove AppState listener, foreground sync trigger, interval reset (polling only), debounce, background state tracking |
103+
| `core/lifecycle/__tests__/useNetworkListener.test.ts` | useNetworkListener | 10 | Register/unsubscribe NetInfo, sync on reconnect, no sync online→online, background guard, isNetworkAvailable state, null isInternetReachable/isConnected handling |
104+
| `core/polling/__tests__/useAdaptivePollingSync.test.ts` | useAdaptivePollingSync | 9 | Start/stop polling, no start in push/not ready, pause on background, resume, dynamic interval, cleanup |
105+
| `core/pushNotifications/__tests__/usePushNotificationSync.test.ts` | usePushNotificationSync | 15 | Permission request, skip in polling, token registration, siteId retrieval, denied callback, foreground listener, sync trigger, ignore non-SQLite notification, background registration, fallback, unregister on mode switch, cleanup, handle failures |
106+
| `core/database/__tests__/useDatabaseInitialization.test.ts` | useDatabaseInitialization | 12 | Creates write/read DBs, initializes sync extension, onDatabaseReady callback, re-init on config change, error handling, empty name/tables validation, close errors on unmount |
107+
108+
### Layer 5: Integration And Public Surface (19 tests)
109+
110+
| Test file | Source | Tests | What's tested |
111+
|-----------|--------|------:|---------------|
112+
| `core/__tests__/SQLiteSyncProvider.test.tsx` | SQLiteSyncProvider | 14 | Renders children, provides writeDb/readDb, initError/syncError, onDatabaseReady, default status, syncMode, triggerSync, adaptive config, re-init triggers, mode fallback, cleanup |
113+
| `core/__tests__/SQLiteSyncProvider.integration.test.tsx` | SQLiteSyncProvider | 7 | Polling defaults without adaptivePolling, push foreground default, push fallback to polling, reinit on accessToken/apiKey/databaseId/table config changes |
114+
| `core/__tests__/publicExports.test.ts` | public API surface | 2 | Root exports smoke test, `./backgroundSync` subpath export smoke test |

0 commit comments

Comments
 (0)