Web UI: - Peer input Enter key now resolves ETH/@alias (like /peer command) - ETH address stored and shown everywhere instead of raw fingerprint - Call UI shows ETH address: "Calling 0x0021...", "In call with 0x9D70..." - Server URL color: #444 → #666 (readable on dark background) - Peer input placeholder: "ETH address, fingerprint, or @alias" - peerEthAddr persisted in localStorage across sessions Server: - WS binary header: strip zero-padding from 64-char to 32-char fingerprint - Call routing now works (was failing due to padded fingerprint lookup) - startCall() resolves ETH/alias before sending CallSignal::Offer - Audio bridge sends auth token to wzp-web as first WS message - Deterministic room name: sorted fingerprint pair (both peers same room) Docs updated: - SERVER.md: WZP integration section (components, running, TLS, auth flow) - USAGE.md: voice call usage for web and TUI - LLM_HELP.md: call architecture, key files, environment vars - LLM_BOT_DEV.md: note that bots cannot participate in calls - TESTING_E2E.md: updated WZP prerequisites with correct flags Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
411 lines
12 KiB
Markdown
411 lines
12 KiB
Markdown
# featherChat End-to-End Testing Guide
|
|
|
|
**Version:** 0.0.43
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
### Local Testing
|
|
|
|
```bash
|
|
# Build everything
|
|
cargo build --release --bin warzone-server --bin warzone-client
|
|
wasm-pack build crates/warzone-wasm --target web --out-dir ../../wasm-pkg
|
|
|
|
# Binaries
|
|
./target/release/warzone-server
|
|
./target/release/warzone-client
|
|
```
|
|
|
|
### Two-Server Testing (Federation)
|
|
|
|
```bash
|
|
# Server Alpha
|
|
./warzone-server --bind 0.0.0.0:7700 --federation alpha.json --enable-bots --bots-config bots.json
|
|
|
|
# Server Bravo
|
|
./warzone-server --bind 0.0.0.0:7700 --federation bravo.json --enable-bots --bots-config bots.json
|
|
```
|
|
|
|
### Voice Call Testing (requires WZP relay)
|
|
|
|
```bash
|
|
# Terminal A: WZP relay (QUIC audio SFU)
|
|
./wzp-relay --listen 0.0.0.0:4433 --auth-url http://127.0.0.1:7700/v1/auth/validate
|
|
|
|
# Terminal B: WZP web bridge (browser WebSocket <-> QUIC)
|
|
./wzp-web --port 8080 --relay 127.0.0.1:4433 --auth-url http://127.0.0.1:7700/v1/auth/validate
|
|
|
|
# Terminal C: featherChat server with relay address
|
|
export WZP_RELAY_ADDR=127.0.0.1:8080
|
|
./warzone-server
|
|
```
|
|
|
|
---
|
|
|
|
## Test 1: Basic Messaging (TUI ↔ TUI)
|
|
|
|
### Setup
|
|
```bash
|
|
# Terminal 1: Server
|
|
./target/release/warzone-server
|
|
|
|
# Terminal 2: User A
|
|
./target/release/warzone-client init
|
|
./target/release/warzone-client register --server http://localhost:7700
|
|
./target/release/warzone-client tui --server http://localhost:7700
|
|
|
|
# Terminal 3: User B
|
|
WARZONE_HOME=~/.warzone-b ./target/release/warzone-client init
|
|
WARZONE_HOME=~/.warzone-b ./target/release/warzone-client register --server http://localhost:7700
|
|
WARZONE_HOME=~/.warzone-b ./target/release/warzone-client tui --server http://localhost:7700
|
|
```
|
|
|
|
### Steps
|
|
1. **User A**: Note the ETH address shown at startup (e.g., `0x85e3D8...`)
|
|
2. **User B**: `/peer 0x85e3D8e4a6EEfc048fc80497773D440Bf3487D2b`
|
|
3. **User B**: Type `Hello!` and press Enter
|
|
4. **User A**: Should see the message with ✓ (sent) → ✓✓ (delivered)
|
|
5. **User A**: `/r Hi back!` (reply)
|
|
6. **User B**: Should see the reply
|
|
|
|
### Verify
|
|
- [x] Messages delivered in real-time (< 1 second)
|
|
- [x] ✓ appears on send, ✓✓ on delivery
|
|
- [x] Timestamps show [HH:MM]
|
|
- [x] ETH address shown in header
|
|
- [x] `/info` shows both ETH and fingerprint
|
|
|
|
---
|
|
|
|
## Test 2: Basic Messaging (Web ↔ Web)
|
|
|
|
### Setup
|
|
1. Open browser tab 1: `http://localhost:7700`
|
|
2. Click "Generate Identity" → note the ETH address
|
|
3. Open browser tab 2 (incognito): `http://localhost:7700`
|
|
4. Click "Generate Identity"
|
|
|
|
### Steps
|
|
1. **Tab 2**: Paste Tab 1's ETH address in the peer input box
|
|
2. **Tab 2**: Type "Hello from web!" → Send
|
|
3. **Tab 1**: Should see the message
|
|
4. **Tab 1**: `/peer <tab2_eth_address>` → Type "Hi!" → Send
|
|
5. **Tab 2**: Should see the reply
|
|
|
|
### Verify
|
|
- [x] Messages show with 🔒 prefix (E2E encrypted)
|
|
- [x] ETH address shown in header (click to copy)
|
|
- [x] Markdown renders (**bold**, `code`, etc.)
|
|
- [x] Scrollbar visible and working
|
|
|
|
---
|
|
|
|
## Test 3: TUI ↔ Web Cross-Client
|
|
|
|
### Steps
|
|
1. Start TUI (User A) and Web (User B) as above
|
|
2. **Web**: `/peer <TUI_eth_address>` → Send message
|
|
3. **TUI**: Should see the message with terminal bell
|
|
4. **TUI**: `/r Hello from terminal!`
|
|
5. **Web**: Should see the reply
|
|
|
|
### Verify
|
|
- [x] Cross-client encryption works (TUI encrypts, Web decrypts and vice versa)
|
|
- [x] Receipts flow correctly between clients
|
|
|
|
---
|
|
|
|
## Test 4: Group Messaging
|
|
|
|
### Steps
|
|
1. **User A**: `/gcreate testgroup`
|
|
2. **User A**: `/g testgroup`
|
|
3. **User B**: `/g testgroup` (auto-joins)
|
|
4. **User A**: Type "Hello group!" → Send
|
|
5. **User B**: Should see `UserA [#testgroup]: Hello group!`
|
|
6. **User B**: Type "Reply!" → Send
|
|
7. **User A**: Should see the reply
|
|
|
|
### Verify
|
|
- [x] Group creation works
|
|
- [x] Auto-join on `/g`
|
|
- [x] Messages fan-out to all members
|
|
- [x] `/gmembers` shows online status (● / ○)
|
|
|
|
---
|
|
|
|
## Test 5: Federation (Two Servers)
|
|
|
|
### Setup
|
|
```bash
|
|
# Server Alpha (Terminal 1)
|
|
./warzone-server --bind 0.0.0.0:7700 --federation alpha.json
|
|
|
|
# Server Bravo (Terminal 2)
|
|
./warzone-server --bind 0.0.0.0:7701 --data-dir ./data-bravo --federation bravo.json
|
|
```
|
|
|
|
`alpha.json`:
|
|
```json
|
|
{"server_id":"alpha","shared_secret":"test123","peer":{"id":"bravo","url":"http://127.0.0.1:7701"}}
|
|
```
|
|
|
|
`bravo.json`:
|
|
```json
|
|
{"server_id":"bravo","shared_secret":"test123","peer":{"id":"alpha","url":"http://127.0.0.1:7700"}}
|
|
```
|
|
|
|
### Steps
|
|
1. **User A** connects to Alpha (port 7700)
|
|
2. **User B** connects to Bravo (port 7701)
|
|
3. Wait 5 seconds for federation presence sync
|
|
4. **User A**: `/peer <UserB_eth_address>` → Send message
|
|
5. **User B**: Should receive the message
|
|
|
|
### Verify
|
|
- [x] Server logs show "Federation: connected to peer"
|
|
- [x] `GET /v1/federation/status` returns `"peer_connected": true`
|
|
- [x] Messages route across servers transparently
|
|
- [x] Key bundles proxy via federation (no "Peer not registered")
|
|
- [x] Aliases resolve across servers
|
|
|
|
---
|
|
|
|
## Test 6: File Transfer
|
|
|
|
### Steps
|
|
1. Set up two peers (TUI or Web)
|
|
2. **Sender**: `/file /path/to/small-file.txt` (must be < 10MB)
|
|
3. **Receiver**: Should see "Incoming file..." → chunk progress → "File saved: ..."
|
|
4. Verify the file at `~/.warzone/downloads/small-file.txt`
|
|
|
|
### Verify
|
|
- [x] SHA-256 integrity check passes
|
|
- [x] File appears in downloads directory
|
|
- [x] Progress shown per chunk
|
|
|
|
---
|
|
|
|
## Test 7: Call Signaling
|
|
|
|
### Steps (Web ↔ Web)
|
|
1. **User A**: Set peer to User B
|
|
2. **User A**: Click 📞 Call button (or `/call`)
|
|
3. **User B**: Should see "📞 Incoming call" with Accept/Reject buttons
|
|
4. **User B**: Click ✓ Accept
|
|
5. Both: Should see "Call connected!" / "🔊 In call"
|
|
6. **Either**: Click "End Call" (or `/hangup`)
|
|
7. Both: Should see "Call ended"
|
|
|
|
### Steps (TUI ↔ TUI)
|
|
1. **User A**: `/call <peer_address>`
|
|
2. **User A**: Header shows yellow "📞 Calling..."
|
|
3. **User B**: "📞 Incoming call from ... — /accept or /reject"
|
|
4. **User B**: `/accept`
|
|
5. **User A**: Header shows green "🔊 0:00" timer
|
|
6. **User A** or **B**: `/hangup`
|
|
|
|
### Verify
|
|
- [x] Call bar appears in web when peer is set
|
|
- [x] Incoming call notification (pulsing animation in web, bell in TUI)
|
|
- [x] Call state updates in header (TUI) / call bar (web)
|
|
- [x] Hangup/reject cleans up state on both sides
|
|
|
|
---
|
|
|
|
## Test 8: Voice Call Audio (requires WZP relay)
|
|
|
|
### Prerequisites
|
|
```bash
|
|
# Terminal 1: WZP relay (QUIC audio SFU)
|
|
./wzp-relay --listen 0.0.0.0:4433 --auth-url http://127.0.0.1:7700/v1/auth/validate
|
|
|
|
# Terminal 2: WZP web bridge (browser WebSocket <-> QUIC)
|
|
./wzp-web --port 8080 --relay 127.0.0.1:4433 --auth-url http://127.0.0.1:7700/v1/auth/validate
|
|
|
|
# Terminal 3: featherChat server
|
|
WZP_RELAY_ADDR=127.0.0.1:8080 ./warzone-server
|
|
```
|
|
|
|
### Steps
|
|
1. Open two browser tabs to `http://localhost:7700`
|
|
2. **Tab 1**: Set peer to Tab 2
|
|
3. **Tab 1**: Click 📞 Call
|
|
4. **Tab 2**: Click ✓ Accept
|
|
5. Both: Allow microphone access when prompted
|
|
6. **Speak into mic** — other tab should hear audio
|
|
7. End call
|
|
|
|
### Verify
|
|
- [x] "Audio: connecting to ..." message appears
|
|
- [x] "Audio: connected — mic active" confirms WS to relay
|
|
- [x] Audio flows bidirectionally
|
|
- [x] Audio stops on hangup
|
|
- [x] No audio leak after call ends
|
|
|
|
---
|
|
|
|
## Test 9: Bot API
|
|
|
|
### Setup
|
|
```bash
|
|
# Server with bots enabled
|
|
./warzone-server --enable-bots --bots-config bots.json
|
|
```
|
|
|
|
### Create a bot via BotFather
|
|
1. Open web client
|
|
2. `/peer @botfather`
|
|
3. Type `/newbot TestEchoBot`
|
|
4. Note the token from BotFather's reply
|
|
|
|
### Run echo bot
|
|
```python
|
|
import requests, time
|
|
TOKEN = "YOUR_TOKEN_HERE"
|
|
API = f"http://localhost:7700/v1/bot/{TOKEN}"
|
|
offset = 0
|
|
while True:
|
|
r = requests.post(f"{API}/getUpdates", json={"offset": offset, "timeout": 30}).json()
|
|
for u in r.get("result", []):
|
|
offset = u["update_id"] + 1
|
|
msg = u.get("message", {})
|
|
text, cid = msg.get("text"), msg.get("chat", {}).get("id")
|
|
if text and cid:
|
|
requests.post(f"{API}/sendMessage", json={"chat_id": cid, "text": f"Echo: {text}"})
|
|
time.sleep(0.1)
|
|
```
|
|
|
|
### Test messaging the bot
|
|
1. `/peer @testechobot`
|
|
2. Type "Hello bot!"
|
|
3. Bot should reply "Echo: Hello bot!"
|
|
|
|
### Verify
|
|
- [x] BotFather creates bot and returns token
|
|
- [x] Bot receives plaintext messages (not encrypted)
|
|
- [x] Bot replies appear in chat
|
|
- [x] Markdown in bot replies renders correctly
|
|
- [x] Inline keyboards render as clickable buttons (if bot sends reply_markup)
|
|
|
|
---
|
|
|
|
## Test 10: System Bots (from config)
|
|
|
|
### Verify
|
|
1. Start server with `--bots-config bots.json`
|
|
2. Check `data/bot-tokens.txt` exists with all tokens
|
|
3. Open web client — welcome screen shows "Available bots: @helpbot, @codebot, ..."
|
|
4. `/peer @helpbot` → Send "hello" → Bot should respond (if bot process is running)
|
|
|
|
---
|
|
|
|
## Test 11: Device Management
|
|
|
|
### Steps
|
|
1. Connect with TUI
|
|
2. Open web client (same identity or different)
|
|
3. **TUI**: `/devices` — should list both sessions
|
|
4. **TUI**: `/kick <web_device_id>`
|
|
5. **Web**: Connection should drop
|
|
|
|
### Verify
|
|
- [x] `/devices` shows device IDs and connection times
|
|
- [x] `/kick` disconnects the target device
|
|
- [x] Max 5 devices per identity enforced
|
|
|
|
---
|
|
|
|
## Test 12: Friend List
|
|
|
|
### Steps
|
|
1. **User A**: `/friend <UserB_address>`
|
|
2. **User A**: `/friend` (no args) — should list User B with online/offline status
|
|
3. **User A**: `/unfriend <UserB_address>`
|
|
4. **User A**: `/friend` — should show empty
|
|
|
|
### Verify
|
|
- [x] Friend list persists across restarts (encrypted on server)
|
|
- [x] Online/offline status shown
|
|
- [x] Add/remove works
|
|
|
|
---
|
|
|
|
## Test 13: Session Recovery
|
|
|
|
### Steps
|
|
1. Establish a session between two peers (exchange messages)
|
|
2. Delete one peer's session DB: `rm -rf ~/.warzone/db/`
|
|
3. Restart that peer's TUI
|
|
4. Other peer sends a message
|
|
5. Should see "[session reset]" and then re-establish
|
|
|
|
### Verify
|
|
- [x] "[session reset]" message appears
|
|
- [x] Subsequent messages work after re-X3DH
|
|
|
|
---
|
|
|
|
## Test 14: Auto-Backup
|
|
|
|
### Steps
|
|
1. Start TUI client
|
|
2. Wait 5 minutes (or use `/backup` for immediate)
|
|
3. Check `~/.warzone/backups/` for `.wzbk` files
|
|
4. Only 3 most recent should exist
|
|
|
|
### Verify
|
|
- [x] `/backup` creates file immediately
|
|
- [x] Auto-backup runs every 5 minutes
|
|
- [x] Old backups rotated (max 3)
|
|
|
|
---
|
|
|
|
## Test 15: Protocol Versioning
|
|
|
|
### Steps
|
|
1. Send a message normally — raw bincode (legacy format)
|
|
2. Check server logs — should accept it
|
|
3. Upgrade client to send envelope format in the future
|
|
4. Old server should still accept legacy
|
|
5. New server accepts both
|
|
|
|
### Verify
|
|
- [x] Legacy (raw bincode) still works
|
|
- [x] Envelope `[WZ][v1][len][payload]` accepted
|
|
- [x] Future version envelope rejected with clear error
|
|
|
|
---
|
|
|
|
## Quick Smoke Test (5 minutes)
|
|
|
|
If you only have 5 minutes, test these:
|
|
|
|
1. `./warzone-server --enable-bots --bots-config bots.json`
|
|
2. Open `http://localhost:7700` in two browser tabs
|
|
3. Tab 1: Generate identity
|
|
4. Tab 2: Generate identity, `/peer <tab1_eth_address>`
|
|
5. Tab 2: Send "**Hello!**" → Tab 1 should see bold text
|
|
6. Tab 1: `/peer @botfather` → `/newbot QuickBot` → Note token
|
|
7. Start echo bot with the token (Python script above)
|
|
8. Tab 1: `/peer @quickbot` → "test" → Should get "Echo: test"
|
|
9. Tab 1: `/peer <tab2_address>` → Click 📞 Call → Tab 2: Accept
|
|
10. Both: Should see "Call connected!" (audio needs WZP relay running)
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
| Issue | Cause | Fix |
|
|
|-------|-------|-----|
|
|
| "Peer not registered" | Peer hasn't registered keys | Peer needs to open client first |
|
|
| "[message could not be decrypted]" | Stale session or cached bundle | Clear localStorage (web) or delete session DB |
|
|
| "alias not found" | Bot/alias doesn't exist on this server | Check `--enable-bots`, wipe data + restart |
|
|
| No audio | WZP relay not running | Start `wzp-relay` + `wzp-web` + set `WZP_RELAY_ADDR` |
|
|
| Federation not working | Peer server down or wrong config | Check `GET /v1/federation/status` on both |
|
|
| "connection limit reached" | 5 devices max | `/devices` → `/kick` old ones |
|
|
| Version mismatch (web) | Old service worker cached | Hard refresh (Cmd+Shift+R) |
|
|
| Bot not responding | Bot process not running | Check bot process is polling getUpdates |
|