Add E2E testing infrastructure with WebdriverIO + Appium
Set up E2E test framework for Android using WebdriverIO, Appium, and UiAutomator2. Add testID props to key components (AuthButton, BaseButton, ChatBubble, CustomTextInput, ProposedEventCard) and apply testIDs to login screen, chat screen, tab bar, and settings. Include initial tests for app launch detection and login flow validation. Update CLAUDE.md with E2E docs.
This commit is contained in:
62
CLAUDE.md
62
CLAUDE.md
@@ -25,6 +25,7 @@ npm run ios -w @calchat/client # Start on iOS
|
||||
npm run web -w @calchat/client # Start web version
|
||||
npm run lint -w @calchat/client # Run ESLint
|
||||
npm run build:apk -w @calchat/client # Build APK locally with EAS
|
||||
npm run test:e2e -w @calchat/client # Run E2E tests (requires Appium server running)
|
||||
```
|
||||
|
||||
### Shared (packages/shared)
|
||||
@@ -61,6 +62,8 @@ npm run test -w @calchat/server # Run Jest unit tests
|
||||
| | tsdav | CalDAV client library |
|
||||
| | ical.js | iCalendar parsing/generation |
|
||||
| Testing | Jest / ts-jest | Server unit tests |
|
||||
| | WebdriverIO + Appium | E2E tests (Android) |
|
||||
| | UiAutomator2 | Android UI automation driver |
|
||||
| Deployment | Docker | Server containerization (multi-stage build) |
|
||||
| | Drone CI | CI/CD pipelines (build, test, format check, deploy, APK build + Gitea release) |
|
||||
| Planned | iCalendar | Event export/import |
|
||||
@@ -132,6 +135,19 @@ src/
|
||||
│ └── ThemeStore.ts # theme, setTheme() - reactive theme switching with Zustand
|
||||
└── hooks/
|
||||
└── useDropdownPosition.ts # Hook for positioning dropdowns relative to trigger element
|
||||
e2e/ # E2E tests (WebdriverIO + Appium)
|
||||
├── jest.config.ts # Jest config (ts-jest, 120s timeout)
|
||||
├── tsconfig.json # TypeScript config (ES2020, CommonJS)
|
||||
├── .env # Test credentials, device name, Appium host/port
|
||||
├── config/
|
||||
│ └── capabilities.ts # Appium capabilities (Dev Client vs APK mode)
|
||||
├── helpers/
|
||||
│ ├── driver.ts # WebdriverIO driver singleton (init, get, quit)
|
||||
│ ├── selectors.ts # testID constants for all screens
|
||||
│ └── utils.ts # Helpers (waitForTestId, performLogin, ensureLoggedIn, ensureOnLoginScreen)
|
||||
└── tests/
|
||||
├── 01-app-launch.test.ts # App startup & screen detection
|
||||
└── 02-login.test.ts # Login flow (empty fields, invalid creds, success)
|
||||
```
|
||||
|
||||
**Routing:** Tab-based navigation with Chat, Calendar, and Settings as main screens. Auth screens (login, register) outside tabs. Dynamic routes for event detail and note editing.
|
||||
@@ -672,6 +688,13 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- **Chat mode**: Edit AI-proposed events before confirming - updates ChatStore locally and persists to server via ChatService.updateProposalEvent()
|
||||
- Route params: `mode` ('calendar' | 'chat'), `id?`, `date?`, `eventData?` (JSON), `proposalContext?` (JSON with messageId, proposalId, conversationId)
|
||||
- Supports recurring events with RRULE configuration (daily/weekly/monthly/yearly)
|
||||
- **E2E testing infrastructure:**
|
||||
- WebdriverIO + Appium with UiAutomator2 driver for Android
|
||||
- testID props added to key components (`AuthButton`, `BaseButton`, `ChatBubble`, `CustomTextInput`, `ProposedEventCard`)
|
||||
- testIDs applied to login screen, chat screen, tab bar, settings logout button, and event proposal buttons
|
||||
- `app.json`: `usesCleartextTraffic: true` for Android (allows HTTP connections needed by Appium)
|
||||
- Two execution modes: Dev Client (local) and APK (CI)
|
||||
- Tests: app launch detection, login flow validation (empty fields, invalid creds, success)
|
||||
|
||||
## Building
|
||||
|
||||
@@ -714,12 +737,49 @@ The project uses Drone CI (`.drone.yml`) with five pipelines:
|
||||
|
||||
## Testing
|
||||
|
||||
Server uses Jest with ts-jest for unit testing. Config in `apps/server/jest.config.js` ignores `/node_modules/` and `/dist/`.
|
||||
### Server Unit Tests
|
||||
|
||||
Jest with ts-jest for unit testing. Config in `apps/server/jest.config.js` ignores `/node_modules/` and `/dist/`.
|
||||
|
||||
**Existing tests:**
|
||||
- `src/utils/password.test.ts` - Tests for bcrypt hash() and compare()
|
||||
- `src/utils/recurrenceExpander.test.ts` - Tests for expandRecurringEvents() (non-recurring, weekly/daily/UNTIL recurrence, EXDATE filtering, RRULE: prefix stripping, invalid RRULE fallback, multi-day events, sorting)
|
||||
|
||||
### E2E Tests (Client)
|
||||
|
||||
WebdriverIO + Appium for Android E2E testing. Tests run sequentially (`--runInBand`) sharing a singleton Appium driver.
|
||||
|
||||
**Two execution modes:**
|
||||
- **Dev Client mode** (local): Connects to running Expo app (`host.exp.exponent`), `noReset: true`
|
||||
- **APK mode** (CI): Installs APK via `APK_PATH` env var, `noReset: false`
|
||||
|
||||
**Running locally:**
|
||||
```bash
|
||||
# Terminal 1: Start Appium server
|
||||
appium
|
||||
# Terminal 2: Start Expo dev server on Android emulator
|
||||
npm run android -w @calchat/client
|
||||
# Terminal 3: Run E2E tests
|
||||
npm run test:e2e -w @calchat/client
|
||||
```
|
||||
|
||||
**Environment variables** (`apps/client/e2e/.env`):
|
||||
```
|
||||
TEST_USER=test # Login credentials for tests
|
||||
TEST_PASSWORD=test
|
||||
DEVICE_NAME=emulator-5554 # Android device/emulator
|
||||
APPIUM_HOST=localhost
|
||||
APPIUM_PORT=4723
|
||||
```
|
||||
|
||||
**Element selection:** Uses Android UiAutomator2 with `resource-id` selectors (React Native maps `testID` → `resource-id` on Android).
|
||||
|
||||
**testID conventions:** Components with testID support: `AuthButton`, `BaseButton`, `ChatBubble`, `CustomTextInput`, `ProposedEventCard`. Key testIDs: `login-title`, `login-identifier-input`, `login-password-input`, `login-button`, `login-error-text`, `tab-chat`, `tab-calendar`, `tab-settings`, `chat-message-input`, `chat-send-button`, `chat-bubble-left`, `chat-bubble-right`, `settings-logout-button`, `event-accept-button`, `event-reject-button`.
|
||||
|
||||
**Existing E2E tests:**
|
||||
- `01-app-launch.test.ts` - App startup, detects login or auto-logged-in state
|
||||
- `02-login.test.ts` - Empty field validation, invalid credentials error, successful login
|
||||
|
||||
## Documentation
|
||||
|
||||
Detailed architecture diagrams are in `docs/`:
|
||||
|
||||
Reference in New Issue
Block a user