E2E Testing Guide
Hyperscape uses comprehensive end-to-end (E2E) testing with real browser sessions and actual WebGPU rendering. Per project rules: NO MOCKS - all tests use real Hyperscape instances with Playwright.Complete Journey Tests
Thecomplete-journey.spec.ts test suite validates the full player experience from login to gameplay.
Test Coverage
-
Full Journey Test:
login → loading → spawn → walk- Completes Privy wallet authentication
- Navigates through character selection
- Waits for loading screen to hide
- Verifies player spawns in world
- Tests keyboard movement in multiple directions
- Captures screenshots at each stage
- Validates visual changes (game is rendering)
-
Loading Progress Test: Validates loading screen behavior
- Ensures loading screen appears during world initialization
- Waits for loading screen to hide (with timeout)
- Verifies game is playable after loading completes
-
Multi-Direction Movement Test: Tests navigation system
- Moves player in all four cardinal directions (up, right, down, left)
- Logs position after each movement
- Verifies movement capability is available
-
WebSocket Connection Test: Validates network stability
- Checks WebSocket connection status throughout journey
- Verifies connection maintains during movement
- Logs reconnect attempts and errors
-
World State Verification Test: Validates game world initialization
- Checks world object exists
- Verifies player entity is spawned
- Validates scene, camera, and network objects
- Logs entity count and loading state
-
Screenshot Verification Test: Ensures game is rendering correctly
- Captures 5 screenshots during different movement actions
- Compares consecutive screenshots for differences
- Requires at least 0.001% pixel difference between frames
- Validates the scene is updating (not frozen)
-
Continuous Movement Test: Tests sustained movement
- Holds down movement key for 2 seconds
- Captures before/after screenshots
- Requires visual change (at least 0.01% difference)
Test Utilities
Located inpackages/client/tests/e2e/utils/testWorld.ts:
Loading Screen Detection
- Waits for loading screen to hide with configurable timeout
- Polls every 500ms checking for loading screen visibility
- Throws error if loading screen doesn’t hide within timeout
- Default timeout: 90 seconds
- Checks if loading screen is currently visible
- Uses multiple selectors to detect loading state
- Returns true if any loading indicator is found
Player Spawn Detection
- Waits for player entity to spawn in world
- Checks for valid player position (finite x, y, z coordinates)
- Default timeout: 60 seconds
- Retrieves current player world position
- Accesses
window.world.entities.player.position - Returns coordinates or throws if player not found
Movement Simulation
- Simulates keyboard movement in specified direction
- Directions: ‘up’ (W), ‘down’ (S), ‘left’ (A), ‘right’ (D)
- Holds key down for specified duration (milliseconds)
- Automatically releases key after duration
Screenshot Comparison
- Captures screenshot of game canvas
- Saves to
packages/client/tests/e2e/__screenshots__/ - Returns screenshot buffer for comparison
- Filename format:
{name}.png
- Compares two screenshot buffers pixel-by-pixel
- Calculates percentage of different pixels
- Throws assertion error if difference is below threshold
- Default threshold: 0.01% (very sensitive to any change)
- Logs actual difference percentage for debugging
- Convenience method combining capture and comparison
- Takes new screenshot and compares to previous
- Returns new screenshot buffer for chaining
WebSocket Status
- Retrieves current WebSocket connection state
- Accesses
window.world.networkobject - Returns connection status, reconnect count, and last error
UI State
- Checks current UI loading state
- Accesses
window.__HYPERSCAPE_LOADING__object - Note: May still be true even after gameplay starts (CSS detection)
Error Capture
- Sets up console error and page error listeners
- Captures all console errors during test execution
- Returns array reference that accumulates errors
- Validates no critical console errors occurred
- Allows warnings (only fails on errors)
- Logs all captured errors if assertion fails
Game Load Helpers
- Waits for game client to fully load
- Checks for canvas element visibility
- Verifies world object exists
- Waits for game client initialization
- From
packages/client/tests/e2e/fixtures/privy-helpers.ts - Returns true if game client loaded successfully
- Navigates to app URL and waits for initial load
- Sets up page with extended timeouts
- Waits for network idle state
Test Configuration
Timeouts
Recent stability improvements have adjusted test timeouts:- Complete Journey Tests: 6 minutes (360,000ms)
- Default Navigation: 120 seconds
- Loading Screen Hide: 90 seconds
- Player Spawn: 60 seconds
- Game Client Load: 60 seconds
- WebSocket Connection: 30 seconds
Browser Configuration
Tests use Playwright with actual WebGPU rendering:- Headful Mode: Tests run with visible browser (WebGPU requires window context)
- WebGPU Enabled: All tests require WebGPU support
- Real Rendering: No mocks - actual Three.js scene rendering
- Screenshot Capture: Visual regression testing with pixel comparison
Test Isolation
Each test:- Starts a fresh Hyperscape server instance
- Opens a new browser context
- Completes full authentication flow
- Spawns a new character
- Cleans up after completion
Running E2E Tests
Visual Testing Best Practices
Screenshot Comparison Thresholds
- 0.001%: Very sensitive - detects even minor scene updates
- 0.01%: Standard threshold - confirms game is rendering
- 0.1%: Loose threshold - allows for minor rendering variations
When to Use Screenshot Comparison
✅ Good use cases:- Verifying game is rendering (not frozen)
- Detecting movement/animation
- Validating UI state changes
- Regression testing for visual bugs
- Exact pixel-perfect matching (rendering may vary slightly)
- Comparing across different GPUs/drivers
- Time-based animations (use fixed timestamps)
Debugging Failed Screenshot Tests
If screenshot comparison fails:- Check
packages/client/tests/e2e/__screenshots__/for captured images - Compare visually to identify what changed
- Adjust threshold if change is acceptable
- Investigate if game is actually frozen (0% difference)
Test Fixtures
Wallet Fixtures
Located inpackages/client/tests/e2e/fixtures/wallet-fixtures.ts:
- evmTest: Extended Playwright test with EVM wallet support
- Provides mock wallet for authentication
- Handles Privy wallet connection flow
Privy Helpers
Located inpackages/client/tests/e2e/fixtures/privy-helpers.ts:
- completeFullLoginFlow: Automates entire login process
- waitForAppReady: Waits for app to be interactive
- waitForGameClient: Waits for game client initialization
Test Config
Located inpackages/client/tests/e2e/fixtures/test-config.ts:
- BASE_URL: Default test server URL (http://localhost:3333)
- TIMEOUT_CONFIG: Centralized timeout configuration
- TEST_CREDENTIALS: Mock credentials for testing
Common Test Patterns
Basic Journey Test Structure
Screenshot Comparison Pattern
Error Capture Pattern
Troubleshooting
Loading Screen Never Hides
IfwaitForLoadingScreenHidden times out:
- Check if WebGPU is available (
chrome://gpu) - Verify assets are loading (check network tab)
- Check browser console for errors
- Increase timeout if server is slow
- Verify database migrations are up to date
Player Never Spawns
IfwaitForPlayerSpawn times out:
- Check WebSocket connection status
- Verify character was created successfully
- Check server logs for spawn errors
- Ensure database has character data
- Verify world initialization completed
Screenshots Are Identical (0% Difference)
If screenshots don’t change:- Verify movement input is being sent (check network tab)
- Check if player is stuck on collision
- Verify tick system is running (check server logs)
- Ensure canvas is focused for keyboard input
- Try clicking canvas before movement
WebGPU Not Available in Tests
If tests fail with WebGPU errors:- Update to Chrome 113+, Edge 113+, or Safari 18+
- Check
chrome://gpufor GPU feature status - Update graphics drivers
- Run tests in headed mode (WebGPU requires window context)
- Verify Playwright is using correct browser channel
CI/CD Integration
E2E tests run automatically in CI:- GitHub Actions:
.github/workflows/integration.yml - Headful Mode: Uses Xvfb for virtual display
- WebGPU Support: CI runners have GPU access
- Screenshot Artifacts: Saved on test failure
- Parallel Execution: Tests run in parallel for speed
CI Environment Variables
Performance Considerations
Test Execution Time
- Full Journey: ~2-3 minutes per test
- Screenshot Capture: ~100-200ms per screenshot
- Movement Simulation: ~1-2 seconds per direction
- Loading Screen: ~10-30 seconds (varies by hardware)
Optimization Tips
- Reuse Browser Context: Share context across related tests
- Parallel Execution: Run independent tests in parallel
- Skip Redundant Waits: Don’t wait for loading screen if already hidden
- Batch Screenshots: Capture multiple screenshots in one test
- Use Production Build: Faster page loads with
DUEL_USE_PRODUCTION_CLIENT=true
Related Documentation
- CLAUDE.md - Development guidelines and testing philosophy
- AGENTS.md - AI assistant guidance for testing
- packages/client/tests/e2e/ - E2E test source code
- Playwright Documentation - Official Playwright docs