Files
daily-notification-plugin/docs/localhost-testing-guide.md
Matthew Raymer ed5dcfbbd1 docs(testing): add PlanAction JWT hydration implementation guide
Add comprehensive implementation guide for creating PlanAction claims
via hydratePlan() function pattern, following established hydrateGive()
and hydrateOffer() patterns.

Changes:
- Add hydrate-plan-implementation-guide.md with complete implementation
  details, usage examples, and testing recommendations
- Link implementation guide from getting-valid-plan-ids.md Method 6
- Link implementation guide from localhost-testing-guide.md Option B

The guide provides:
- Complete hydratePlan() function implementation
- PlanActionClaim interface structure
- Helper functions (createAndSubmitPlan, editAndSubmitPlan)
- Usage examples and edge cases
- Testing recommendations and security considerations

This complements plan creation documentation by showing how to
programmatically construct valid PlanAction JWTs for POST /api/v2/claim.
2025-10-29 12:46:41 +00:00

394 lines
12 KiB
Markdown

# Localhost Testing Guide
**Author**: Matthew Raymer
**Version**: 1.0.0
**Status**: Testing Setup
## Overview
This guide explains how to test the daily notification plugin's prefetch functionality with a localhost development API server running on your host machine.
## Android Emulator Localhost Access
On Android emulator, `localhost` (127.0.0.1) refers to the **emulator itself**, not your host machine. To access your host machine's localhost from the Android emulator, use:
**`10.0.2.2`** - Special alias that maps to host machine's localhost
### Platform-Specific Localhost Addresses
- **Android Emulator**: `http://10.0.2.2:PORT`
- **iOS Simulator**: `http://localhost:PORT` or `http://127.0.0.1:PORT`
- **Web Browser**: `http://localhost:PORT`
## Setup Steps
### 1. Start Your Local Development Server
You have two options:
#### Option A: Use the Test API Server (Recommended for Quick Testing)
The plugin includes a ready-to-use test API server with automatic project seeding:
```bash
cd /home/matthew/projects/timesafari/daily-notification-plugin
node scripts/test-api-server-with-seed.js [port]
# Default port: 3000
# Starts on http://localhost:3000
```
This server:
-**Automatically creates plans in-memory on startup** (no fetch errors)
- ✅ Implements the `/api/v2/report/plansLastUpdatedBetween` endpoint
- ✅ Returns seeded projects when queried by `planIds`
- ✅ Ready to use immediately with auto-generated valid URI format IDs
- ✅ Provides debugging endpoints to view seeded projects
**Note**: Plans are stored in-memory only. When the server restarts, plans are re-seeded automatically.
#### Option B: Use Your Existing TimeSafari API Server
If you have your own localhost API server, you must create plans first. Plans are created by importing JWT claims containing a `PlanAction`:
**Route: POST `/api/v2/claim`**
```json
{
"jwtEncoded": "<signed JWT with PlanAction claim>"
}
```
**Requirements**:
- JWT must contain `@type: "PlanAction"` in the claim payload
- JWT must be signed with a valid DID key
- Response includes `handleId` and `planId` if creation succeeds
**Methods to Create Plans**:
1. **TimeSafari App UI** (easiest) - Create projects through the app UI and note `handleId` from API responses
2. **Import PlanAction JWT** - Generate a signed JWT with `PlanAction` claim and POST to `/api/v2/claim`
3. **Direct Database** - Insert plans directly into your database (not recommended for production data integrity)
**Note**: Creating PlanAction JWTs requires DID signing and proper claim structure, which is complex. For quick testing, **Option A (test API server) is recommended**.
**Implementation Reference**: If you need to programmatically create PlanAction JWTs, see [`docs/hydrate-plan-implementation-guide.md`](./hydrate-plan-implementation-guide.md) for the complete implementation pattern, including `hydratePlan()` function and helper utilities.
Then verify your setup:
```bash
# Seed projects to your existing API server
node scripts/seed-test-projects.js seed http://localhost:3000
# Or export projects as JSON for manual import
node scripts/seed-test-projects.js export test-projects.json
```
Then ensure your server implements the endpoint as described in the "Localhost API Server Requirements" section below.
### 2. Configure Test App for Localhost
Edit `test-apps/daily-notification-test/src/config/test-user-zero.ts`:
```typescript
api: {
serverMode: "localhost", // Change from "mock" to "localhost"
servers: {
localhost: {
android: "http://10.0.2.2:3000", // Match your local server port
ios: "http://localhost:3000",
web: "http://localhost:3000"
},
// ... other server configs
},
// ...
},
testing: {
enableMockResponses: false, // Disable mocks to use real localhost API
// ...
}
```
### 3. Update Starred Plans in Test App
In the test app UI (UserZeroView), use `updateStarredPlans()` to set which project IDs to query:
```typescript
// In UserZeroView.vue or your test code
await DailyNotification.updateStarredPlans({
planIds: ["test_project_1", "test_project_2", "test_project_3"]
});
```
### 4. Schedule Notification for Testing
Schedule a notification that will trigger prefetch 5 minutes before:
```typescript
await DailyNotification.scheduleDailyNotification({
time: "11:25", // Current time + 5+ minutes for testing
title: "Test Notification",
body: "Testing prefetch with localhost",
priority: "high"
});
```
The prefetch will run 5 minutes before (11:20 in this example) and query your localhost API.
## Testing Prefetch Flow
### Expected Timeline
1. **T-0**: You schedule notification for `11:25`
2. **T+0**: Plugin schedules prefetch for `11:20` (5 minutes before)
3. **T+0**: Plugin logs:
```
DN|SCHEDULE_FETCH_START time=...
DN|WORK_ENQUEUED work_id=... fetch_at=... delay_ms=...
```
4. **T+~5 minutes**: WorkManager triggers prefetch at `11:20`
5. **T+~5 minutes**: Plugin queries `http://10.0.2.2:3000/api/v2/report/plansLastUpdatedBetween`
6. **T+~10 minutes**: Notification displays at `11:25`
### Monitoring Prefetch
Watch logs for prefetch execution:
```bash
# Filter for prefetch-related logs
adb logcat | grep -E "DN|SCHEDULE_FETCH|FETCH_PROJECT|WORK_ENQUEUED"
# Watch WorkManager queue
adb shell dumpsys jobscheduler | grep daily_notification
# Monitor network requests (if your server logs them)
# Check your localhost server logs for POST requests to /api/v2/report/plansLastUpdatedBetween
```
## Localhost API Server Requirements
Your localhost API server must implement:
### Endpoint: `POST /api/v2/report/plansLastUpdatedBetween`
**Request:**
```json
{
"planIds": ["test_project_1", "test_project_2"],
"afterId": "optional_jwt_id_for_pagination"
}
```
**Response:**
```json
{
"data": [
{
"planSummary": {
"jwtId": "jwt_id_1",
"handleId": "test_project_1",
"name": "Test Project 1",
"description": "Project description",
"issuerDid": "did:key:...",
"agentDid": "did:key:...",
"startTime": "2025-01-01T00:00:00Z",
"endTime": "2025-01-31T23:59:59Z"
},
"previousClaim": {
"jwtId": "previous_jwt_id",
"claimType": "project_update"
}
}
],
"hitLimit": false,
"pagination": {
"hasMore": false,
"nextAfterId": null
}
}
```
**Headers Required:**
- `Authorization: Bearer <JWT_TOKEN>`
- `Content-Type: application/json`
- `User-Agent: TimeSafari-DailyNotificationPlugin/1.0.0`
## Seeding Test Projects
### Using the Test API Server (Automatic)
If you're using `test-api-server-with-seed.js`, **projects are automatically created on startup** - no additional seeding needed. The server creates plans in-memory, so they're available immediately when the prefetch endpoint is called.
### Using Your Real TimeSafari API Server
If your localhost API has no projects, create them via **POST `/api/v2/claim`** with a PlanAction JWT (see "Option B" section above).
**Note**: The `seed-test-projects.js` script cannot directly create plans because it would require generating signed PlanAction JWTs with DID keys, which is complex. The seed script is designed for the test API server (Option A) or for verifying API responses after plans are created through other means.
### Generate Test Projects
```bash
# Generate test projects and display as JSON
node scripts/seed-test-projects.js generate
# Export projects to JSON file
node scripts/seed-test-projects.js export test-projects.json
# Seed projects directly to your API server
node scripts/seed-test-projects.js seed http://localhost:3000
# Use custom project IDs
node scripts/seed-test-projects.js seed http://localhost:3000 "project_1,project_2,project_3"
```
The seed script generates test projects matching the structure expected by the plugin, including:
- `handleId` (from your config)
- `jwtId` (timestamp-based for pagination)
- `planSummary` (name, description, dates, location)
- `previousClaim` (for change detection)
### Using the Test API Server (Includes Seeding)
The easiest way is to use the included test API server:
```bash
node scripts/test-api-server-with-seed.js
```
This server:
1. Seeds 5 test projects automatically on startup
2. Provides the prefetch endpoint ready to use
3. Includes debugging endpoints
## Quick Test Script (Alternative)
If you want to create your own minimal localhost API server:
```javascript
// test-api-server.js
const express = require('express');
const app = express();
app.use(express.json());
app.post('/api/v2/report/plansLastUpdatedBetween', (req, res) => {
console.log('📥 Prefetch request received:', {
planIds: req.body.planIds,
afterId: req.body.afterId,
headers: req.headers
});
// Return mock response
res.json({
data: [
{
planSummary: {
jwtId: `${Date.now()}_test_123`,
handleId: req.body.planIds[0] || "test_project",
name: "Localhost Test Project",
description: "Testing prefetch from localhost",
issuerDid: "did:test:issuer",
agentDid: "did:test:agent",
startTime: new Date().toISOString(),
endTime: new Date(Date.now() + 86400000).toISOString()
},
previousClaim: {
jwtId: "previous_test_jwt",
claimType: "project_update"
}
}
],
hitLimit: false,
pagination: {
hasMore: false,
nextAfterId: null
}
});
});
app.listen(3000, () => {
console.log('🧪 Test API server running on http://localhost:3000');
console.log('📡 Android emulator should use: http://10.0.2.2:3000');
});
```
Run with:
```bash
node test-api-server.js
```
**Note**: The included `scripts/test-api-server-with-seed.js` provides the same functionality plus automatic seeding, so you may prefer to use that instead.
## Troubleshooting
### Prefetch Not Executing
1. **Check WorkManager queue:**
```bash
adb shell dumpsys jobscheduler | grep -A 20 "daily_notification"
```
2. **Verify prefetch was scheduled:**
```bash
adb logcat | grep "DN|SCHEDULE_FETCH"
```
3. **Check if WorkManager has constraints:**
- Battery optimization might be blocking execution
- Network might not be available
- Device might be in deep sleep
### Cannot Connect to Localhost
1. **Android Emulator**: Use `10.0.2.2` not `localhost` or `127.0.0.1`
2. **Firewall**: Check if your firewall is blocking port 3000
3. **Server not running**: Verify server is listening on correct port
4. **Wrong port**: Match the port in config with your server's port
### Network Timeout
Increase timeout in config:
```typescript
testing: {
timeoutMs: 60000, // Increase from 30000 to 60000
}
```
### Authentication Errors
Your localhost server should accept the JWT token generated by the plugin. For testing, you can:
1. **Disable JWT validation** in your localhost server
2. **Use a test JWT secret** that matches plugin config
3. **Log the JWT** in your server to see what's being sent
## Switching Between Mock and Localhost
You can switch modes without rebuilding:
1. **Mock Mode** (offline testing):
```typescript
api.serverMode = "mock";
testing.enableMockResponses = true;
```
2. **Localhost Mode** (real API calls to localhost):
```typescript
api.serverMode = "localhost";
testing.enableMockResponses = false;
```
3. **Staging Mode** (real API calls to staging):
```typescript
api.serverMode = "staging";
testing.enableMockResponses = false;
```
## Next Steps
- Test prefetch execution with real localhost API
- Monitor network traffic to verify requests
- Test with different starred plan IDs
- Verify prefetch timing (5 minutes before notification)
- Test notification delivery after prefetch completes