6.7 KiB
6.7 KiB
Master Test Plan — Claude Telegram Bot
Compiled from per-block test plans produced during implementation.
Block 1: Project Scaffolding
- 1.1:
git log --onelineshows initial commit - 1.2:
bun run src/index.tsstarts without errors (with valid .env) - 1.3:
.envis NOT tracked by git - 1.4:
git show --stat HEAD~8shows exactly: .gitignore, bun.lock, package.json, src/index.ts, tsconfig.json - 1.5:
node_modules/exists with dependencies installed
Block 2: State Store (src/state/store.ts)
- 2.1:
new Store()returns default state{ projects: {}, sessions: {}, activeSession: null }when no state file exists - 2.2:
store.save()creates~/.claude-telegram-bot/state.jsonwith valid JSON - 2.3: Save then load round-trips correctly — write state, create new Store, verify data matches
- 2.4:
save()auto-creates~/.claude-telegram-bot/directory if missing - 2.5: TypeScript rejects invalid
SessionInfo.statusvalues (only "idle" | "busy")
Block 3: Session Manager (src/services/session-manager.ts)
- 3.1:
activeSessionreturnsnullwhen no session started - 3.2:
createSessionsets session data, marks as active, and persists - 3.3:
stopSessionremoves session, reassigns active to remaining (or null) - 3.4:
stopSessionreturnsfalsefor unknown session name - 3.5:
stopAllclears all sessions, sets activeSession to null, returns count - 3.6:
switchSessionupdates activeSession and returns true for valid name - 3.7:
switchSessionreturns false for unknown name - 3.8:
setStatusupdates only status field, no-ops for unknown session - 3.9:
resolveProjectPathreturns bookmarked path when name matches a project - 3.10:
resolveProjectPathextracts basename from path for non-bookmarked input - 3.11:
generateNameappends-2,-3on name conflicts - 3.12:
saveProject/removeProjectCRUD works correctly - 3.13: Every mutating method calls
store.save()exactly once
Block 4: Claude Service (src/services/claude.ts)
- 4.1:
createSessionreturns non-emptysessionIdwith valid prompt and cwd - 4.2:
createSessionreturns non-emptyresultstring - 4.3:
sendMessagewith valid sessionId resumes context and returns result - 4.4: Session context is preserved — sendMessage result reflects prior conversation
- 4.5: Invalid sessionId in
sendMessagethrows or returns empty string gracefully - 4.6:
cwdis respected — Claude tools resolve paths relative to it - 4.7: Multi-message stream handled — only final result captured
Block 5: Telegram Utilities (src/utils/telegram.ts)
- 5.1: Short message (<=4096 chars) returns single-element array
- 5.2: Exactly 4096 chars returns single-element array (boundary)
- 5.3: Long message with
\n\nsplits at paragraph boundary - 5.4: Long message with only
\nsplits at line boundary - 5.5: Long message with no whitespace hard-splits at 4096
- 5.6: All chunks are <= 4096 characters
- 5.7: No data loss — concatenated chunks reconstruct original content
- 5.8:
escapeMarkdownreturns input unchanged
Block 6: Command Handlers (src/handlers/commands.ts)
- 6.1:
/startwithout argument shows usage - 6.2:
/start <path>with existing session name suggests/switch - 6.3:
/start <path>creates Claude session, registers in manager, replies with result - 6.4:
/stopwith no active session replies "Nothing to stop" - 6.5:
/stop <name>removes session, shows next active if any - 6.6:
/stop <name>for unknown session replies "not found" - 6.7:
/stopallstops all, reports count - 6.8:
/switchwithout argument shows usage - 6.9:
/switch <name>switches and confirms - 6.10:
/switch <name>for unknown session shows error + hint - 6.11:
/sessionswith no sessions replies "No active sessions" - 6.12:
/sessionslists sessions with►marker and inline keyboard - 6.13:
/statuswith no session replies "No active session" - 6.14:
/statusshows name, path, status - 6.15:
/savewith <2 args shows usage - 6.16:
/save <name> <path>saves and confirms - 6.17:
/remove <name>removes or says "not found" - 6.18:
/projectsshows list with inline "Start" buttons - 6.19:
/helpshows full command reference
Block 7: Message Handler (src/handlers/message.ts)
- 7.1: Non-text message ignored silently
- 7.2: Text with no active session shows "No active session" message
- 7.3: Text when session busy shows "Session is busy" message
- 7.4: Status set to "busy" before Claude call, "idle" after (including on error)
- 7.5: Typing indicator sent before Claude call
- 7.6: Response split into chunks and sent sequentially
- 7.7: Empty Claude response sends "(empty response)"
- 7.8: Claude error caught, error message sent, status reset to idle
Block 8: Bot Setup (src/bot.ts)
- 8.1:
createBotreturns Bot instance without errors - 8.2: Non-owner messages silently dropped by middleware
- 8.3: Owner messages reach handlers
- 8.4:
switch:callback switches session and confirms - 8.5:
start:callback for unknown project answers "not found" - 8.6:
start:callback for existing session switches instead of creating - 8.7:
start:callback for new project creates session via Claude - 8.8: Claude error in
start:callback sends error message - 8.9: All imports are static,
createBotis synchronous
Block 9: Entry Point (src/index.ts)
- 9.1: Missing TELEGRAM_BOT_TOKEN throws with clear message
- 9.2: Missing TELEGRAM_OWNER_ID throws with clear message
- 9.3: Missing ANTHROPIC_API_KEY throws with clear message
- 9.4: All vars present — bot starts, logs "Bot started successfully"
- 9.5: TELEGRAM_OWNER_ID converted to number
- 9.6: SIGINT triggers graceful shutdown with "Shutting down..." log
- 9.7:
.envfile loaded by dotenv/config
Integration / Smoke Test
- E2E-1:
/help— shows command list - E2E-2:
/start /d/claude_telegram_bot— creates session, Claude responds - E2E-3:
What files are in this directory?— Claude lists project files - E2E-4:
/status— shows session name, path, idle status - E2E-5:
/sessions— shows list with inline button - E2E-6: Click inline button — switches session
- E2E-7:
/save mybot /d/claude_telegram_bot— saves bookmark - E2E-8:
/projects— shows bookmark with "Start" button - E2E-9:
/stop— stops session - E2E-10:
/sessions— shows "No active sessions" - E2E-11: Send text without session — shows "No active session" error
- E2E-12: Message from non-owner — silently ignored