Test Frameworks
Tests run across three platforms with specialized frameworks:| Platform | Framework | Coverage |
|---|---|---|
| React Native | Jest + React Native Testing Library | Stores, services, components, screens, contracts |
| Android | JUnit | LocalDream, DownloadManager, BroadcastReceiver |
| iOS | XCTest | PDFExtractor, CoreMLDiffusion, DownloadManager |
| E2E | Maestro | Critical path flows (launch, chat, models, downloads) |
Running Tests
All Tests
Run the complete test suite (Jest + Android + iOS):- Jest tests with coverage
- Android JUnit tests
- iOS XCTest suite
React Native Tests (Jest)
Android Tests (JUnit)
Android tests require the Gradle wrapper in
android/. Ensure you’ve run cd android && ./gradlew clean at least once.iOS Tests (XCTest)
End-to-End Tests (Maestro)
Maestro tests verify critical user flows end-to-end.E2E tests require a running app on an emulator/simulator. They test:
- App launch and onboarding
- Chat message flow
- Model download and switching
- Image generation
- Settings changes
Test Coverage
Off Grid uses Codecov for test coverage tracking:Viewing Coverage Reports
After running Jest with--coverage, view the HTML report:
Coverage Requirements
- Jest coverage is uploaded to Codecov on every PR
- Codecov checks enforce coverage thresholds (no decrease in coverage allowed)
- Uncovered lines are flagged in PR comments
Add tests for new code before submitting PRs. The CI pipeline will reject PRs that decrease test coverage.
Continuous Integration (GitHub Actions)
All tests run automatically on every PR and push tomain via GitHub Actions.
CI Workflow Jobs
The CI workflow (.github/workflows/ci.yml) includes:
- Lint
- Type Check
- Test
- Android Build
Job: This runs:
lintRuns on: macos-latestSteps:- ESLint (JavaScript/TypeScript)
- SwiftLint (iOS Swift code)
- Android Lint (Kotlin code)
eslint .swiftlint lint --quietcd android && ./gradlew :app:lintDebug
CI Badge
main branch.
Pre-Commit Quality Gates (Husky)
Off Grid uses Husky to run quality gates automatically on everygit commit. Tests are scoped to the file types you staged.
Pre-Commit Hook Behavior
| Staged file type | Checks that run automatically |
|---|---|
.ts / .tsx / .js / .jsx | ESLint (staged only), tsc --noEmit, npm test |
.swift | SwiftLint (staged only), npm run test:ios |
.kt / .kts | compileDebugKotlin (type check), lintDebug, npm run test:android |
Requirements
- SwiftLint:
brew install swiftlint(skipped with a warning if not installed) - Android: Gradle wrapper in
android/
Pre-Commit Hook Source
The hook is defined in.husky/pre-commit:
.husky/pre-commit
Writing Tests
Jest Tests (React Native)
Example test for a Zustand store:src/stores/__tests__/chatStore.test.ts
Android Tests (JUnit)
Example test for a Kotlin module:android/app/src/test/java/ai/offgridmobile/PdfExtractorTest.kt
iOS Tests (XCTest)
Example test for a Swift module:ios/OffgridMobileTests/PDFExtractorTests.swift
Troubleshooting
Jest tests hang
Jest tests hang
Use This is already included in the
--forceExit to force Jest to exit after tests complete:npm test script.Android tests fail to find Gradle
Android tests fail to find Gradle
Ensure you’ve initialized the Android project:
iOS tests fail: Simulator not found
iOS tests fail: Simulator not found
Check available simulators:Update the
-destination flag in the test command to match an available simulator.SwiftLint not found
SwiftLint not found
Install SwiftLint via Homebrew:
Coverage decreases on PR
Coverage decreases on PR
Codecov will block the PR if coverage decreases. Add tests for new code:
- Check the Codecov report in the PR comment
- Identify uncovered lines
- Write tests to cover those lines
- Push updated code
Next Steps
Contributing Guide
Learn the full contribution workflow including PR reviews
Project Structure
Understand the codebase organization