# Backend Test Plan (Updated) ## Overview This test plan is designed for iterative execution using sub-agents, with each sub-agent handling a specific phase to avoid exceeding the 300,000 token context limit. Each phase focuses on a distinct subsystem and includes specific test cases and verification steps. **Last Updated:** 2026-06-08 **Status:** Phase 1 Complete - Database & Migration Tests Verified --- ## Test Phases ### Phase 1: Database & Migration Tests ✅ COMPLETE **Scope:** Alembic migrations, database schema, model relationships **Sub-agent Task:** Verify all migrations run correctly and database schema is consistent **Status:** ✅ Verified - All migrations functionally correct #### Actual Migration Structure: **Migration 000 (`000_base_tables.py`)** - Creates 8 base tables: - `mtgonline_users` (base table) - `mtgonline_decklist_folders` (FK to mtgonline_users.id, self-ref) - `mtgonline_decklist_files` (FK to mtgonline_decklist_folders.id, mtgonline_users.id) - `mtgonline_rooms` (base table) - `mtgonline_rooms_gametypes` (FK to mtgonline_rooms.id) - `mtgonline_bans` (FK to mtgonline_users.id) - `mtgonline_log` (FK to mtgonline_rooms.id, mtgonline_users.id) - `mtgonline_audit` (FK to mtgonline_users.id) **Migration 001 (`001_initial_user_schema.py`)** - Creates 15 user-related tables: - `user_sessions` (FK to mtgonline_users.id) - `deck_versions` (FK to mtgonline_decklist_files.id) - `game_replays` (FK to mtgonline_rooms.id) - `replay_players` (FK to game_replays.id, mtgonline_users.id, mtgonline_decklist_files.id) - `game_outcomes` (FK to mtgonline_users.id, game_replays.game_uuid) - `user_statistics` (PK: user_id, FK to mtgonline_users.id) - `user_card_collection` (FK to mtgonline_users.id) - `card_wishlist` (FK to mtgonline_users.id) - `user_groups` (FK to mtgonline_users.id) - `group_members` (FK to user_groups.id, mtgonline_users.id) - `group_chat_messages` (FK to user_groups.id, mtgonline_users.id) - `user_networks` (FK to mtgonline_users.id) - `network_members` (FK to user_networks.id, mtgonline_users.id) - `user_preferences` (PK: user_id, FK to mtgonline_users.id) - `user_activity_log` (FK to mtgonline_users.id) **Migration 002 (`002_user_deck_building_tables.py`)** - Creates: - `user_decks` (FK to mtgonline_users.id, mtgonline_decklist_folders.id) **Migration 003 (`003_mtgonline_cards_table.py`)** - Creates: - `mtgonline_cards` (base table) - `user_deck_cards` (FK to user_decks.id, mtgonline_cards.id) - `deck_precedents` (FK to mtgonline_users.id) - `deck_precedent_cards` (FK to deck_precedents.id, mtgonline_cards.id) - `card_suggestions` (FK to user_decks.id, mtgonline_cards.id, self-ref) **Migration 004 (`004_card_import_table.py`)** - Creates: - `user_card_imports` (FK to mtgonline_users.id) **Migration 005 (`005_missing_tables.py`)** - Creates: - `mtg_sets` (base table) - `mtg_cards` (FK to mtg_sets.id) - `mtg_cards_mirror` (base table) - `card_import_batches` (FK to mtgonline_users.id) - `user_card_imports_confirmed` (FK to mtgonline_users.id, card_import_batches.id) - `deck_card_links` (FK to mtgonline_decklist_files.id, mtg_cards_mirror.id) #### Verification Results: - ✅ All 6 migrations properly linked (000 → 001 → 002 → 003 → 004 → 005) - ✅ All foreign keys reference tables created in same or earlier migrations - ✅ No circular dependencies - ✅ All indexes created on FK columns - ✅ All unique constraints valid - ✅ Downgrade functions properly drop tables in reverse dependency order - ✅ All model imports in `env.py` and `__init__.py` consistent **Note:** Migration 000 is NOT empty (creates 8 base tables). This is intentional and correct. --- ### Phase 2: Model Layer Tests **Scope:** SQLAlchemy models, relationships, validation **Sub-agent Task:** Verify all model definitions are correct and consistent #### Actual Model Structure: **1. Core Models (`app/models/models.py`)** - `User` (`mtgonline_users`) - username, email, password_hash, salt, country, real_name, avatar_bmp, privlevel, is_active, is_banned, ban_reason, ban_ends, vip_status, vip_expiry, creation_date, last_login - `MtonlineCard` (`mtgonline_cards`) - source_id, name, mana_cost, type_line, oracle_text, power, toughness, rarity, layout, artist, flavor_text, numbers, identifiers, images, image, set_code, set_name, card_parts, keywords, legalities, synced_at, created_at - `DecklistFolder` (`mtgonline_decklist_folders`) - owner_id, name, parent_id, creation_date - `DecklistFile` (`mtgonline_decklist_files`) - folder_id, owner_id, name, content, format, status, creation_date - `Room` (`mtgonline_rooms`) - name, description, is_password_protected, password_hash, creation_date - `RoomGameType` (`mtgonline_rooms_gametypes`) - room_id, name, description - `Ban` (`mtgonline_bans`) - user_id, server_id, reason, moderators, ip_address, expiration_time, active, creation_date - `GameLog` (`mtgonline_log`) - room_id, player_id, message, timestamp - `AuditLog` (`mtgonline_audit`) - admin_id, action_type, target_user_id, details, ip_address, timestamp **2. MTG Models (`app/models/mtg_models.py`)** - `MtgSet` (`mtg_sets`) - code, name, type, release_date, base_set_size, total_size, is_foil_only, is_non_foil_only, digital, icon_svg_url, parent_code, mtgo_code, image, updated_at - `MtgCard` (`mtg_cards`) - set_id, name, mana_cost, type_line, oracle_text, power, toughness, rarity, layout, artist, flavor_text, numbers, identifiers, images, image, updated_at **3. Mirror Models (`app/models/mirror_models.py`)** - `MtgCardMirror` (`mtg_cards_mirror`) - source_id, name, mana_cost, type_line, oracle_text, power, toughness, rarity, layout, artist, flavor_text, numbers, identifiers, images, image, card_parts, keywords, legalities, set_code, set_name, synced_at, created_at - `DeckCardLink` (`deck_card_links`) - deck_id, card_id, quantity, zone **4. User Data Models (`app/models/user_data.py`)** - `UserSession` (`user_sessions`) - user_id, session_token_hash, ip_address, user_agent, created_at, expires_at, is_active - `DeckVersion` (`deck_versions`) - deck_id, version_number, content, status, comment, created_at - `GameReplay` (`game_replays`) - game_uuid, room_id, game_type, format, duration_seconds, start_time, end_time, status, replay_data, created_at, updated_at - `ReplayPlayer` (`replay_players`) - replay_id, user_id, position, deck_id, won, lost, concession, turn_one, created_at - `GameOutcome` (`game_outcomes`) - user_id, game_uuid, outcome, opponent_id, format, rating_before, rating_after, rating_change, created_at - `UserStatistics` (`user_statistics`) - user_id (PK), total_games, total_wins, total_losses, total_concessions, win_rate, current_streak, best_streak, average_rating, last_game_date, updated_at - `UserCardCollection` (`user_card_collection`) - user_id, card_id, quantity, condition, language, is_foil, is_alt_art, acquired_date, acquisition_method, notes, created_at, updated_at - `CardWishlist` (`card_wishlist`) - user_id, card_id, max_price, notes, created_at - `UserGroup` (`user_groups`) - name, description, owner_id, is_public, max_members, created_at, updated_at - `GroupMember` (`group_members`) - group_id, user_id, role, joined_at - `GroupChatMessage` (`group_chat_messages`) - group_id, sender_id, message, created_at - `UserNetwork` (`user_networks`) - name, description, creator_id, is_public, created_at - `NetworkMember` (`network_members`) - network_id, user_id, role, joined_at - `UserPreference` (`user_preferences`) - user_id (PK), theme, notifications_enabled, email_notifications, auto_save_decks, default_format, language, updated_at - `UserActivityLog` (`user_activity_log`) - user_id, activity_type, activity_data, ip_address, created_at **5. User Deck Models (`app/models/user_deck.py`)** - `UserDeck` (`user_decks`) - user_id, name, status, folder_id, format, notes, is_precedent, precedent_name, created_at, updated_at - `UserDeckCard` (`user_deck_cards`) - deck_id, card_id, quantity, zone, position - `DeckPrecedent` (`deck_precedents`) - name, description, format, is_public, created_by, created_at, updated_at - `DeckPrecedentCard` (`deck_precedent_cards`) - precedent_id, card_id, quantity, zone - `CardSuggestion` (`card_suggestions`) - deck_id, card_id, source_card_id, suggestion_type, confidence, notes, created_at **6. Card Import Models (`app/models/card_import.py`)** - `CardImportBatch` (`card_import_batches`) - user_id, filename, file_type, file_size, status, total_cards, matched_cards, unmatched_cards, match_results, error_message, created_at, updated_at - `UserCardImportRecord` (`user_card_imports_confirmed`) - user_id, batch_id, is_confirmed, confirmed_at #### Test Cases: 1. **Verify all models have proper `__tablename__`** 2. **Verify all foreign keys reference correct tables** 3. **Verify all relationships are bidirectional where needed** 4. **Verify cascade delete behavior** 5. **Verify indexes on FK columns** 6. **Verify unique constraints** 7. **Verify model imports in `app/models/__init__.py`** 8. **Check for missing fields compared to migration definitions** **Verification:** All models compile without errors, relationships are correct, no missing fields. --- ### Phase 3: Schema Layer Tests **Scope:** Pydantic schemas, request/response validation **Sub-agent Task:** Verify all schema definitions are correct #### Actual Schema Structure: **1. Core Schemas (`app/schemas/schemas.py`)** - **Authentication:** `LoginRequest`, `LoginResponse`, `RefreshTokenRequest`, `TokenResponse` - **User:** `UserBase`, `UserCreate`, `UserUpdate`, `UserResponse` - **Deck:** `DeckCreate`, `DeckUpdate`, `DeckResponse`, `FolderCreate`, `FolderResponse` - **Game:** `GameCreate`, `GameResponse` - **Room:** `RoomResponse` - **Ban:** `BanCreate`, `BanResponse` - **Error:** `ErrorResponse`, `ValidationErrorResponse` - **Pagination:** `PaginationParams`, `PaginatedResponse` - **Card Mirror:** `CardMirrorResponse`, `DeckCardLinkResponse`, `DeckWithCardsResponse` **2. User Data Schemas (`app/schemas/user_data_schemas.py`)** - **Enums:** `DeckVersionStatus`, `GameReplayStatus`, `GameOutcomeType`, `GroupMemberRole`, `NetworkMemberRole`, `UserPreferenceTheme`, `ActivityType` - **Session:** `SessionResponse`, `SessionCleanupResponse` - **Deck Version:** `DeckVersionCreate`, `DeckVersionUpdate`, `DeckVersionResponse`, `DeckVersionListResponse` - **Game Replay:** `GameReplayCreate`, `GameReplayUpdate`, `GameReplayResponse`, `GameReplayListResponse` - **Game Outcome:** `GameOutcomeCreate`, `GameOutcomeResponse`, `GameOutcomeListResponse` - **User Statistics:** `UserStatisticsResponse`, `StatisticsUpdateResponse` - **Card Collection:** `CardCollectionCreate`, `CardCollectionUpdate`, `CardCollectionResponse`, `CardCollectionListResponse` - **Wishlist:** `WishlistCreate`, `WishlistUpdate`, `WishlistResponse`, `WishlistListResponse` - **Group:** `GroupCreate`, `GroupUpdate`, `GroupMemberCreate`, `GroupMemberUpdate`, `GroupMemberRemove`, `GroupResponse`, `GroupListResponse`, `GroupChatMessageCreate`, `GroupChatMessageResponse`, `GroupChatMessageListResponse` - **Network:** `NetworkCreate`, `NetworkUpdate`, `NetworkMemberCreate`, `NetworkResponse`, `NetworkListResponse` - **Preference:** `UserPreferenceUpdate`, `UserPreferenceResponse` - **Activity Log:** `ActivityLogEntry`, `ActivityLogListResponse` - **Generic:** `MessageResponse`, `CountResponse`, `ErrorDetail` **3. User Deck Schemas (`app/schemas/user_deck_schemas.py`)** - **Enums:** `DeckStatus`, `DeckZone`, `SuggestionType` - **Deck:** `UserDeckCreate`, `UserDeckUpdate`, `UserDeckResponse`, `UserDeckListResponse` - **Deck Card:** `DeckCardCreate`, `DeckCardUpdate`, `DeckCardResponse`, `DeckCardWithDetailsResponse`, `DeckCardListResponse` - **Deck Precedent:** `PrecedentCreate`, `PrecedentUpdate`, `PrecedentResponse`, `PrecedentListResponse` - **Card Suggestion:** `SuggestionCreate`, `SuggestionResponse`, `SuggestionListResponse` - **Deck Action:** `DeckFinalizeRequest`, `DeckFinalizeResponse`, `DeckDeleteResponse` - **Search:** `CardSearchRequest`, `CardSearchResponse` - **Generic:** `MessageResponse`, `CountResponse` **4. Card Import Schemas (`app/schemas/card_import_schemas.py`)** - `CardImportRequest`, `CardImportResponse`, `CardImportStatusResponse` - `CardMatchResult`, `CardImportSummary` - `MessageResponse`, `CountResponse`, `ErrorResponse` **5. Card Search Schemas (`app/schemas/card_search_schemas.py`)** - `CardResponse`, `SetResponse`, `CardTypeResponse`, `CardSearchResponse` - `CardImportResponse`, `CardImportStatusResponse` - `CardMatchResult`, `CardImportSummary` - `MessageResponse`, `CountResponse`, `ErrorResponse` **6. Protocol Schemas (`app/schemas/proto_messages.py`)** - **Base:** `ProtoMessageBase` - **Commands:** `SessionCommand`, `GameCommand`, `GameEvent`, `Response` - **Server Info:** `ServerInfoUser`, `ServerInfoDeckStorageFile`, `ServerInfoDeckStorageFolder`, `ServerInfoDeckStorageTreeItem`, `ServerInfoCard`, `ServerInfoZone`, `ServerInfoGame` **7. Protocol Constants (`app/schemas/protocol_constants.py`)** - `SessionCommandType` (IntEnum) - `GameCommandType` (IntEnum) - `GameEventType` (IntEnum) - `ResponseCode` (IntEnum) - `ZoneType` (IntEnum) - `UserLevelFlag` (IntFlag) **8. User Card Collection Schemas (`app/schemas/user_card_collection.py`)** - **Enums:** `CardCondition`, `AcquisitionMethod` - **Card Collection:** `CardCollectionCreate`, `CardCollectionUpdate`, `CardCollectionResponse`, `CardCollectionListResponse` - **Wishlist:** `WishlistCreate`, `WishlistUpdate`, `WishlistResponse`, `WishlistListResponse` - **Collection Statistics:** `CollectionStatistics`, `CollectionSummaryResponse` - **Generic:** `MessageResponse`, `CountResponse`, `ErrorDetail` #### Test Cases: 1. **Verify all schemas have proper `model_config`** 2. **Verify required vs optional fields** 3. **Verify validation rules (min/max length, patterns, etc.)** 4. **Verify schema imports in `app/schemas/__init__.py`** 5. **Check for missing fields compared to model definitions** 6. **Verify enum values match expected constants** **Verification:** All schemas compile without errors, validation rules are correct, no missing fields. --- ### Phase 4: Router Layer Tests **Scope:** FastAPI routers, endpoint definitions, dependencies **Sub-agent Task:** Verify all router definitions are correct #### Actual Router Structure: **1. Auth Router (`app/routers/auth.py`)** - `POST /login` - Authenticate user, return JWT tokens - `POST /refresh` - Refresh access token - `POST /register` - Register new user - `GET /me` - Get current authenticated user **2. Users Router (`app/routers/users.py`)** - `GET /{user_id}` - Get user by ID - `PATCH /{user_id}` - Update user profile - `POST /{user_id}/ban` - Ban user (admin only) - `POST /{user_id}/unban` - Unban user (admin only) **3. Decks Router (`app/routers/decks.py`)** - **Deck CRUD:** - `GET /` - List user's decks with filtering - `POST /` - Create new user deck (DRAFT) - `GET /{deck_id}` - Get specific deck - `PATCH /{deck_id}` - Update deck - `DELETE /{deck_id}` - Delete deck - **Deck Finalize:** - `POST /{deck_id}/finalize` - Transition DRAFT to FINAL - **Deck Card Management:** - `POST /{deck_id}/cards` - Add card to deck - `GET /{deck_id}/cards` - Get all cards in deck - `PATCH /{deck_id}/cards/{card_id}` - Update card in deck - `DELETE /{deck_id}/cards/{card_id}` - Remove card from deck - **Deck Precedents:** - `GET /precedents` - List available precedents - `POST /precedents` - Create precedent (template) - `GET /precedents/{precedent_id}` - Get specific precedent - `POST /precedents/{precedent_id}/use` - Clone precedent to new deck - **Card Search:** - `POST /search/cards` - Search MTG cards - **Card Suggestions:** - `GET /{deck_id}/suggestions` - Get card suggestions - `POST /{deck_id}/suggestions` - Add suggestion **4. Additional Routers (exist but not fully documented)** - `app/routers/rooms.py` - Rooms router - `app/routers/games/` - Games router (directory) - `app/routers/admin.py` - Admin router - `app/routers/card_router.py` - Card router - `app/routers/interactions.py` - Interactions router - `app/routers/refresh.py` - Refresh router - `app/routers/card_import.py` - Card import router - `app/routers/ws.py` - WebSocket router #### Test Cases: 1. **Verify all endpoints defined with correct HTTP methods** 2. **Verify request/response schemas match** 3. **Verify dependencies (auth, db session, etc.)** 4. **Verify prefix paths are correct** 5. **Verify tag assignments** 6. **Verify all routers imported in `app/main.py`** 7. **Check for missing endpoints** **Verification:** All routers compile without errors, endpoints are properly defined, no missing imports. --- ### Phase 5: Service Layer Tests **Scope:** Business logic, service functions **Sub-agent Task:** Verify all service implementations are correct #### Actual Service Structure: **1. Card Services** - `app/services/card_database.py` - Card database management - `app/services/card_mirror_service.py` - Card mirroring - `app/services/card_search_service.py` - Card search - `app/services/fuzzy_card_matcher.py` - Fuzzy card matching **2. Deck Services** - `app/services/deck_manager.py` - Deck management - `app/services/deck_parser.py` - Deck parsing - `app/services/deck_suggestion_service.py` - Deck suggestions **3. File Services** - `app/services/file_parser.py` - File parsing **4. Game Services** - `app/services/game_server.py` - Game server logic **5. Import Services** - `app/services/import_batch_processor.py` - Import batch processing **6. MTGJSON Services** - `app/services/mtgjson_downloader.py` - MTGJSON data download - `app/services/mtgjson_loader.py` - MTGJSON data loading - `app/services/mtgjson_manager.py` - MTGJSON data management - `app/services/mtgjson_uploader.py` - MTGJSON data upload #### Test Cases: 1. **Verify all functions defined with proper signatures** 2. **Verify function implementations match expected behavior** 3. **Verify service imports (models, schemas, utilities)** 4. **Check for missing implementations** 5. **Verify error handling** **Verification:** All services compile without errors, functions are properly implemented, no missing imports. --- ### Phase 6: Utility & Helper Tests **Scope:** Utility functions, helpers, constants **Sub-agent Task:** Verify all utility implementations are correct #### Actual Utility Structure: **1. Core Configuration (`app/core/`)** - `app/core/database.py` - Database configuration, session management - `app/core/redis_client.py` - Redis client setup - `app/core/security.py` - JWT tokens, password hashing, auth dependencies - `app/core/settings.py` - Application settings, environment variables **2. Utilities (`app/utils/`)** - `app/utils/auth.py` - Authentication utilities - `app/utils/database.py` - Database utilities - `app/utils/errors.py` - Custom exceptions and error handlers - `app/utils/constants.py` - Application constants #### Test Cases: 1. **Verify all functions defined with proper signatures** 2. **Verify function implementations** 3. **Verify exception classes defined with proper error codes** 4. **Verify constants defined with correct values** 5. **Verify utility imports where needed** **Verification:** All utilities compile without errors, functions are properly implemented, no missing imports. --- ### Phase 7: Configuration & Environment Tests **Scope:** Settings, environment variables, configuration **Sub-agent Task:** Verify all configuration is correct #### Test Cases: 1. **Verify all settings defined in `app/core/settings.py`** 2. **Verify default values are sensible** 3. **Verify database URL configuration** 4. **Verify async/sync engine setup in `app/core/database.py`** 5. **Verify FastAPI app initialization in `app/main.py`** 6. **Verify middleware setup** 7. **Verify CORS configuration** 8. **Verify all settings used in code match defined settings** 9. **Verify environment variables match settings** **Verification:** All configuration compiles without errors, settings are properly defined, no missing configuration. --- ### Phase 8: Integration Tests **Scope:** Cross-component integration, API consistency **Sub-agent Task:** Verify all components work together correctly #### Test Cases: 1. **Router-Service Integration** - Verify routers call correct service functions - Verify service functions return correct types - Check for integration issues 2. **Service-Model Integration** - Verify services use correct models - Verify model operations are correct - Check for integration issues 3. **Schema-Router Integration** - Verify routers use correct schemas - Verify schemas match request/response - Check for integration issues 4. **Database-Model Integration** - Verify models match database schema (from migrations) - Verify migrations create correct tables - Check for integration issues 5. **Overall Consistency** - Verify all imports are correct - Verify all function calls are valid - Check for circular dependencies - Verify no orphaned code **Verification:** All components integrate correctly, no circular dependencies, all imports valid. --- ## Execution Strategy ### Sub-Agent Execution Order: 1. **Phase 1:** ✅ Database & Migration Tests (COMPLETE) 2. **Phase 2:** Model Layer Tests 3. **Phase 3:** Schema Layer Tests 4. **Phase 4:** Router Layer Tests 5. **Phase 5:** Service Layer Tests 6. **Phase 6:** Utility & Helper Tests 7. **Phase 7:** Configuration & Environment Tests 8. **Phase 8:** Integration Tests ### Context Management: - Each sub-agent handles one phase at a time - Sub-agents return only findings and issues - Main agent aggregates results and coordinates fixes - Maximum context usage per sub-agent: ~50,000 tokens ### Verification Criteria: - All files compile without syntax errors - All imports resolve correctly - All function signatures match across components - All foreign keys reference existing tables - All schemas have proper validation - All routers have proper dependencies - No circular dependencies - No orphaned code ### Issue Reporting: Each sub-agent should report: 1. **Critical Issues:** Missing files, broken imports, syntax errors 2. **Consistency Issues:** Mismatched types, missing fields, incorrect references 3. **Recommendations:** Improvements, missing features, best practices --- ## Summary This test plan provides a systematic approach to verifying the entire backend system by breaking it down into 8 manageable phases. Each phase can be executed by a sub-agent independently, ensuring comprehensive coverage while staying within context limits. The plan focuses on consistency, correctness, and completeness of the codebase. **Current Status:** Phase 1 Complete **Next Phase:** Phase 2 - Model Layer Tests