docs: comprehensive E2E testing guide (15 test scenarios + quick smoke test)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
409
warzone/docs/TESTING_E2E.md
Normal file
409
warzone/docs/TESTING_E2E.md
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
# 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
|
||||||
|
# Start WZP web bridge (from warzone-phone repo)
|
||||||
|
./wzp-web --bind 0.0.0.0:8080 --relay 127.0.0.1:4433
|
||||||
|
|
||||||
|
# Start WZP relay
|
||||||
|
./wzp-relay --bind 0.0.0.0:4433
|
||||||
|
|
||||||
|
# Set relay address for featherChat
|
||||||
|
export WZP_RELAY_ADDR=127.0.0.1:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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
|
||||||
|
./wzp-relay --bind 0.0.0.0:4433
|
||||||
|
|
||||||
|
# Terminal 2: WZP web bridge
|
||||||
|
./wzp-web --bind 0.0.0.0:8080 --relay 127.0.0.1:4433
|
||||||
|
|
||||||
|
# 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 |
|
||||||
Reference in New Issue
Block a user