diff --git a/.github/workflows/mobile-ci.yml b/.github/workflows/mobile-ci.yml new file mode 100644 index 00000000..667f660e --- /dev/null +++ b/.github/workflows/mobile-ci.yml @@ -0,0 +1,61 @@ +name: Mobile CI + +on: + push: + branches: [ main, develop ] + paths: + - 'apps/mobile/**' + - '.github/workflows/mobile-ci.yml' + pull_request: + branches: [ main, develop ] + paths: + - 'apps/mobile/**' + - '.github/workflows/mobile-ci.yml' + +jobs: + build: + name: Lint, Type-Check & Test + runs-on: ubuntu-latest + defaults: + run: + working-directory: apps/mobile + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 8 + run_install: false + + - name: Get pnpm store path + id: pnpm-cache + shell: bash + run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Lint + run: pnpm lint + + - name: Type check + run: pnpm type-check + + - name: Test + run: pnpm test diff --git a/apps/mobile/DEV_BUILD.md b/apps/mobile/DEV_BUILD.md new file mode 100644 index 00000000..40e15683 --- /dev/null +++ b/apps/mobile/DEV_BUILD.md @@ -0,0 +1,231 @@ +# πŸ“± Vaultix Mobile β€” Dev Builds + +This guide covers how to generate development builds for the Vaultix mobile app and distribute them for internal testing. + +--- + +## Prerequisites + +- Node.js 18+ +- pnpm (`npm install -g pnpm`) +- [Expo CLI](https://docs.expo.dev/get-started/installation/) (`pnpm add -g expo-cli`) +- [EAS CLI](https://docs.expo.dev/eas/) (`pnpm add -g eas-cli`) +- Physical device or simulator/emulator +- Apple Developer account (iOS) or Expo account (Android) + +--- + +## Option 1: EAS Build (Recommended) + +EAS (Expo Application Services) builds the app in the cloud and is the easiest way to produce shareable dev builds. + +### 1. Install EAS CLI + +```bash +pnpm add -g eas-cli +``` + +### 2. Log in to Expo + +```bash +eas login +``` + +### 3. Configure EAS + +Create an `eas.json` file at the **root of the mobile app** (`apps/mobile/eas.json`): + +```json +{ + "cli": { + "version": ">= 3.0.0" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "channel": "development" + }, + "preview": { + "distribution": "internal", + "channel": "preview" + }, + "production": {} + }, + "submit": { + "production": {} + } +} +``` + +### 4. Build for Development + +```bash +# From apps/mobile +eas build --profile development --platform all +``` + +**Platform-specific builds:** + +```bash +# iOS only +eas build --profile development --platform ios + +# Android only +eas build --profile development --platform android +``` + +### 5. What Happens + +- EAS uploads your project to Expo's servers +- Builds the native app (iOS IPA / Android APK/AAB) +- Downloads the build artifact or sends it to your registered device(s) + +### 6. Install the Build + +- **iOS**: Install via the link EAS provides (TestFlight-like) or download the `.ipa` and install via Xcode +- **Android**: Download the `.apk` or `.aab` and install directly on device + +### 7. Start the Dev Server + +After installing the dev build on your device/emulator: + +```bash +cd apps/mobile +npx expo start --dev-client +``` + +This starts the Metro bundler. Open the app on your device (scan QR code or press `a` for Android / `i` for iOS). + +--- + +## Option 2: Local Dev Build (Expo Dev Client) + +Use this when you want to build locally without cloud infrastructure. + +### iOS (requires macOS + Xcode) + +```bash +# Generate the native iOS project +npx expo prebuild --platform ios + +# Open in Xcode and build +cd apps/mobile/ios +pod install +open Vaultix.xcworkspace +# Select a simulator or connected device, then Build & Run (Cmd+R) +``` + +### Android (requires Android Studio) + +```bash +# Generate the native Android project +npx expo prebuild --platform android + +# Open in Android Studio +cd apps/mobile/android +open -a "Android Studio" . + +# Build APK +cd apps/mobile/android +./gradlew assembleDebug +``` + +--- + +## Option 3: Expo Go (Quick Testing) + +For quickest feedback without a dev build, use [Expo Go](https://expo.dev/go). Note that custom native modules won't work in Expo Go if you ever add native dependencies beyond what Expo provides out of the box. + +```bash +cd apps/mobile +npx expo start +``` + +Then scan the QR code with **Expo Go** on your device. + +--- + +## Internal Distribution + +### iOS β€” TestFlight via EAS Submit + +```bash +# First, ensure you have an App Store Connect API key or Apple ID credentials +eas submit --platform ios --profile production +``` + +### Android β€” Internal Testing Track + +```bash +eas submit --platform android --profile production +``` + +Or share the `.apk` directly via a link (if using EAS Build with internal distribution). + +--- + +## Running Checks Before Build + +Always run these checks before building to catch issues early: + +```bash +# From apps/mobile + +# 1. Lint +pnpm lint + +# 2. Type check +pnpm type-check + +# 3. Run tests +pnpm test + +# 4. All three combined +pnpm validate +``` + +--- + +## Troubleshooting + +### Build fails at "pod install" + +```bash +cd apps/mobile/ios +pod deintegrate +pod install --repo-update +``` + +### Metro bundler can't resolve modules + +```bash +cd apps/mobile +pnpm start --clear +# or +npx expo start -c +``` + +### EAS Build fails + +- Check logs in the EAS dashboard +- Ensure `eas.json` has the correct profile +- Verify your Expo account has sufficient build credits +- Try building for a single platform first + +### Dev build crashes on launch + +- Ensure the Metro dev server is running (`npx expo start --dev-client`) +- Check for native module mismatches in `package.json` +- Clear the dev client cache: + ```bash + npx expo start -c + ``` + +--- + +## References + +- [Expo Dev Client Docs](https://docs.expo.dev/development/creating-a-development-build/) +- [EAS Build Docs](https://docs.expo.dev/build/introduction/) +- [EAS Submit Docs](https://docs.expo.dev/submit/introduction/) diff --git a/apps/mobile/QA_CHECKLIST.md b/apps/mobile/QA_CHECKLIST.md new file mode 100644 index 00000000..a06e298d --- /dev/null +++ b/apps/mobile/QA_CHECKLIST.md @@ -0,0 +1,149 @@ +# πŸ“± Vaultix Mobile β€” QA Checklist + +> Use this checklist to manually validate the core mobile flows before submitting a release or dev build. + +--- + +## 1. Welcome / Connect Wallet Screen + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 1.1 | Launch the app on a simulator/device | Welcome screen appears with branding (**Vaultix** + tagline) | ☐ | +| 1.2 | Verify feature cards are displayed | Three cards: Secure Escrow, Milestone Tracking, Dispute Resolution | ☐ | +| 1.3 | Tap **Connect Wallet** | Button shows loading spinner ("Connecting…") for ~1.5s | ☐ | +| 1.4 | Wait for connection to finish | App navigates to **Dashboard** tab automatically | ☐ | +| 1.5 | Tap **Explore without wallet β†’** | App navigates to **Dashboard** tab (skip wallet) | ☐ | +| 1.6 | Rotate the device or resize | Layout adapts correctly (ScrollView still scrollable) | ☐ | + +--- + +## 2. Dashboard β€” Escrow List + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 2.1 | Dashboard loads on wallet connect or skip | Screen shows empty state ("No escrows found") when API returns empty | ☐ | +| 2.2 | Pull down to refresh | Refresh indicator appears; list reloads | ☐ | +| 2.3 | Skeleton loaders appear while loading | Grey placeholder cards shown before real data | ☐ | +| 2.4 | **Status filter tabs** are visible | Tabs: All, Created, Funded, Active, Completed, Disputed, Expired | ☐ | +| 2.5 | Tap a status filter (e.g., "Active") | List filters to show only escrows with that status | ☐ | +| 2.6 | Active filter tab has highlighted style | Selected tab has purple (#6c63ff) background | ☐ | +| 2.7 | Escrow cards show: title, status badge, amount, deadline | All fields visible and formatted | ☐ | +| 2.8 | Status badge color matches status | Created=purple, Funded=blue, Completed=green, Disputed=red, Expired=orange | ☐ | +| 2.9 | Scroll to bottom of list (β‰₯20 items) | Pagination triggers; "loading more" spinner appears | ☐ | +| 2.10 | Tap **οΌ‹** button (top-right) | Navigates to **Create Escrow** screen | ☐ | +| 2.11 | Tap an escrow card | Navigates to **Escrow Detail** screen with correct ID | ☐ | + +--- + +## 3. Escrow Detail Screen + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 3.1 | Navigate to escrow detail (from dashboard) | Skeleton loaders shown while fetching | ☐ | +| 3.2 | Data loads successfully | Title, description, status badge, amount, deadline are displayed | ☐ | +| 3.3 | **Milestones** section visible | Each milestone shows title, amount, and status (Released / Pending) | ☐ | +| 3.4 | **Parties** section visible | Each party shows role, wallet address (truncated), and status | ☐ | +| 3.5 | **Activity Timeline** section visible | Events listed in order with date/time | ☐ | +| 3.6 | **Actions** section shows correct buttons per status + role | See table below | ☐ | + +### Action visibility by status / role + +| Escrow Status | Depositor | Recipient | Arbitrator | +|---------------|-----------|-----------|------------| +| created | Fund Escrow | β€” | β€” | +| funded / confirmed | Release (per milestone) + Raise Dispute | β€” | β€” | +| disputed | β€” | β€” | Resolve Dispute | +| completed / cancelled / expired | No actions | No actions | No actions | + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 3.7 | Tap **Release** on a milestone | Navigates to **Release Milestone** screen | ☐ | +| 3.8 | Swipe back from detail screen | Returns to Dashboard with previous state preserved | ☐ | +| 3.9 | Error state (e.g., network offline) | Error message + "Retry" button shown | ☐ | + +--- + +## 4. Create Escrow β€” Multi-Step Form + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 4.1 | Navigate to Create Escrow (+ button) | Step indicator shows "Step 1 of 4" | ☐ | +| 4.2 | **Step 1 β€” Parties & Amount**: Leave all fields empty, tap **Next β†’** | Validation errors shown for Title, Recipient, Amount | ☐ | +| 4.3 | Fill valid data, tap **Next β†’** | Advances to Step 2 (Milestones) | ☐ | +| 4.4 | **Step 2 β€” Milestones**: One milestone pre-filled | Can edit title, amount | ☐ | +| 4.5 | Enter milestone amounts that sum to more/less than total | Error shown: "Milestone amounts must equal total" | ☐ | +| 4.6 | Tap **+ Add Milestone** (up to 10) | New milestone block added | ☐ | +| 4.7 | Tap **Remove** on a milestone (if > 1) | Milestone block removed | ☐ | +| 4.8 | Fill milestone amounts that sum to total, tap **Next β†’** | Advances to Step 3 (Deadline) | ☐ | +| 4.9 | **Step 3 β€” Deadline**: Leave empty, tap **Next β†’** | Validation error: "Deadline is required" | ☐ | +| 4.10 | Enter a past date, tap **Next β†’** | Error: "Deadline must be in the future" | ☐ | +| 4.11 | Enter a future date, tap **Next β†’** | Advances to Step 4 (Review) | ☐ | +| 4.12 | **Step 4 β€” Review**: Verify all fields show correctly | Title, Recipient, Amount, Deadline, Milestone count displayed | ☐ | +| 4.13 | Tap **Create Escrow** | Loading indicator; success alert on completion | ☐ | +| 4.14 | Tap "View" in success alert | Navigates to Escrow Detail screen for the new escrow | ☐ | +| 4.15 | Tap ← Back at any step | Returns to previous step with all data preserved | ☐ | + +--- + +## 5. Release Milestone Screen + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 5.1 | Navigate to Release Milestone (from detail screen) | Screen shows escrow ID, milestone ID, and "Confirm Release" button | ☐ | +| 5.2 | Tap **Confirm Release** | Status changes to "Submitting" with spinner | ☐ | +| 5.3 | Tx submitted successfully | Status changes to "Submitted", polling starts | ☐ | +| 5.4 | Tx confirmed by network | Status changes to "Confirmed" with success banner | ☐ | +| 5.5 | Tx fails | Status shows "Failed" with error message + "Retry" + "Go Back" buttons | ☐ | +| 5.6 | Tap **Retry** after failure | State resets to "Ready" (idle) | ☐ | +| 5.7 | Tap **Back to Escrow** after confirmation | Navigates to Escrow Detail screen | ☐ | +| 5.8 | Transaction hash displayed during submitted/confirmed states | Hash shown in monospace font, tappable | ☐ | + +--- + +## 6. Notifications Screen + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 6.1 | Navigate to Notifications (tab) | Screen shows empty state or notification list | ☐ | +| 6.2 | Skeleton loaders shown while loading | Grey skeleton items before data loads | ☐ | +| 6.3 | Unread notifications have a purple dot + left border | Visual distinction from read items | ☐ | +| 6.4 | Unread count shown in header | "(N) unread" badge visible | ☐ | +| 6.5 | Tap an unread notification | Dot disappears; navigates to related Escrow Detail (if escrowId exists) | ☐ | +| 6.6 | Tap **Mark all read** | All notifications marked as read; count goes to 0 | ☐ | +| 6.7 | Pull down to refresh | List reloads with latest data | ☐ | +| 6.8 | Error state (network offline) | Error message + "Retry" button shown | ☐ | +| 6.9 | Notification event types display readable labels | CREATED β†’ "Escrow Created", FUNDED β†’ "Escrow Funded", etc. | ☐ | + +--- + +## 7. Cross-Cutting Concerns + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 7.1 | **Dark theme** consistency across all screens | Background: #12121f, cards: #1e1e30, text: white/grey | ☐ | +| 7.2 | **Accessibility**: Screen reader labels | Buttons have `accessibilityLabel` props | ☐ | +| 7.3 | **Keyboard handling**: Create Escrow form on iOS | KeyboardAvoidingView pushes content up | ☐ | +| 7.4 | **API timeout** (15s) | Requests fail gracefully with error state | ☐ | +| 7.5 | **Memory**: Navigate between all screens repeatedly | No crashes, no memory warnings | ☐ | + +--- + +## 8. Build & CI Checks + +| # | Check | Expected Result | Pass/Fail | +|---|-------|----------------|-----------| +| 8.1 | `pnpm lint` passes | No ESLint errors | ☐ | +| 8.2 | `pnpm type-check` passes | No TypeScript errors | ☐ | +| 8.3 | `pnpm test` passes | All Jest tests green | ☐ | +| 8.4 | `pnpm validate` passes | lint β†’ type-check β†’ test all pass in sequence | ☐ | +| 8.5 | EAS dev build compiles | `eas build --profile development --platform all` succeeds | ☐ | +| 8.6 | Dev build installs on device/emulator | App launches without crash | ☐ | + +--- + +## Tips for Testers + +- **Reset state**: Clear app data or reinstall to test fresh-start scenarios. +- **Network simulation**: Toggle airplane mode to verify error states. +- **Backend**: Ensure the backend is running (`cd apps/backend && pnpm start:dev`) and seeded with test data. +- **Reporting bugs**: Include screen name, step number, expected vs actual result, and a screenshot/video if possible. diff --git a/apps/mobile/eas.json b/apps/mobile/eas.json new file mode 100644 index 00000000..0edb4d8f --- /dev/null +++ b/apps/mobile/eas.json @@ -0,0 +1,20 @@ +{ + "cli": { + "version": ">= 3.0.0" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "channel": "development" + }, + "preview": { + "distribution": "internal", + "channel": "preview" + }, + "production": {} + }, + "submit": { + "production": {} + } +} diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 39b667ff..1ff52963 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -8,7 +8,8 @@ "ios": "expo start --ios", "lint": "eslint . --ext .ts,.tsx", "type-check": "tsc --noEmit", - "test": "jest" + "test": "jest", + "validate": "pnpm lint && pnpm type-check && pnpm test" }, "dependencies": { "expo": "~52.0.0",