Repository navigation
Add desktop environment tests - #424
Conversation
Unit tests for the container handler, service, and SDK client, plus an E2E test that exercises the full desktop lifecycle through a real deployed worker.
|
commit: |
🐳 Docker Images PublishedDefault: FROM cloudflare/sandbox:0.0.0-pr-424-0ad9886With Python: FROM cloudflare/sandbox:0.0.0-pr-424-0ad9886-pythonWith OpenCode: FROM cloudflare/sandbox:0.0.0-pr-424-0ad9886-opencodeVersion: Use the 📦 Standalone BinaryFor arbitrary Dockerfiles: COPY --from=cloudflare/sandbox:0.0.0-pr-424-0ad9886 /container-server/sandbox /sandbox
ENTRYPOINT ["/sandbox"]Download via GitHub CLI: gh run download 22617299264 -n sandbox-binaryExtract from Docker: docker run --rm cloudflare/sandbox:0.0.0-pr-424-0ad9886 cat /container-server/sandbox > sandbox && chmod +x sandbox |
React + Vite + Tailwind v4 app that demonstrates the desktop environment API with noVNC streaming and viewport-aware resolution.
* Add desktop environment SDK client Sandboxes need a public API for desktop environments so Workers can manage desktops, capture screenshots, and stream VNC. The Dockerfile gains a desktop build stage with the required system dependencies. * Add desktop environment tests (#424) * Add desktop environment tests Unit tests for the container handler, service, and SDK client, plus an E2E test that exercises the full desktop lifecycle through a real deployed worker. * Add desktop viewer example (#425) React + Vite + Tailwind v4 app that demonstrates the desktop environment API with noVNC streaming and viewport-aware resolution.
There was a problem hiding this comment.
OpenCode Review
Excellent test coverage implementation for the desktop environment feature. The PR demonstrates solid understanding of the project's testing architecture with comprehensive coverage across all three layers:
Strengths:
✅ Complete layer coverage - Unit tests for container handler/service, SDK client, and full E2E integration
✅ Proper test isolation - E2E tests use unique sessions, unit tests are properly mocked
✅ Real integration validation - E2E tests verify actual PNG screenshot data, VNC streaming URLs, and desktop lifecycle
✅ Following project conventions - Test structure, file locations, and mock patterns align with testing skill guidelines
✅ Thorough edge case coverage - Tests inactive states, error conditions, and idempotent operations
Architecture compliance:
✅ Correctly extends test infrastructure (global-sandbox helper, test worker config)
✅ Proper separation: unit tests mock dependencies, E2E tests use real Docker
✅ Session-based isolation prevents test interference
Desktop-specific validation:
The E2E tests appropriately validate desktop environment functionality:
- PNG magic number validation for screenshots
- VNC stream URL generation (port 6080)
- Mouse/keyboard interaction APIs
- Screen resolution consistency
- Process lifecycle management
Minor observation: The example application (examples/desktop/) adds significant bulk to this PR, but it's clearly labeled as part 3 of a 4-part stack and serves as valuable documentation/demo for the feature.
Verdict: Looks good to merge - comprehensive testing that maintains project quality standards.
* Add desktop environment container runtime Enables running a full Linux desktop inside sandbox containers with programmatic screenshot and input control via native FFI. * Add desktop environment SDK client (#423) * Add desktop environment SDK client Sandboxes need a public API for desktop environments so Workers can manage desktops, capture screenshots, and stream VNC. The Dockerfile gains a desktop build stage with the required system dependencies. * Add desktop environment tests (#424) * Add desktop environment tests Unit tests for the container handler, service, and SDK client, plus an E2E test that exercises the full desktop lifecycle through a real deployed worker. * Add desktop viewer example (#425) React + Vite + Tailwind v4 app that demonstrates the desktop environment API with noVNC streaming and viewport-aware resolution. * Fix lint errors in desktop example and biome config * Add desktop E2E test Dockerfile and config generation * Add desktop image to CI build, push, and cleanup workflows * Fix Go build: pin golang.org/x/net to Go 1.24-compatible version go mod tidy resolved golang.org/x/net@v0.51.0 which requires go >= 1.25, breaking the go-builder stage using golang:1.24-bookworm. Pin to v0.50.0 (last Go 1.24-compatible release) and update go directive to match builder. * Fix FFI type mismatch and clickCount handling The Click FFI binding declared 'bool' (1-byte C _Bool) but the Go function expects C.int (4 bytes), causing undefined ABI behavior. Changed to 'int' and pass clickCount through directly so tripleClick emits three rapid single clicks instead of silently degrading to doubleClick. * Guard desktop stop in destroy() on container state desktop.stop() goes through containerFetch which auto-starts sleeping containers. Check ctx.container.running first so destroy() does not wake a container just to immediately tear it down. * Revert accidental backup and token doc changes The desktop branch commit inadvertently changed backup curl from streaming -T to --data-binary (loads full archive into memory), reduced timeouts from 1800s to 300s, removed the local-dev mismatch diagnostic, and changed token docs to show hyphens which the validation regex rejects. Restore all to match main. * Add error resilience to desktop worker and manager Catch stop() failures during start() error recovery so the original error propagates. Add onerror handler to the worker thread so pending promises reject instead of hanging if the worker crashes. * Fix FFI out-pointer semantics and skip stream-url in CI koffi requires koffi.out() annotation on pointer parameters to copy values back from C to JS after the call. Without it, GetScreenSize and GetMousePos always returned zeros because koffi treated int* as input-only. The stream-url E2E test requires preview URL infrastructure (custom domain with wildcard DNS) that CI workers.dev doesn't provide, so skip it with the same pattern used by other port-exposure tests. * Reset manager state on start failure DesktopManager.start() sets state to 'starting' but the catch block relied solely on stop() to reset it to 'inactive'. When stop() itself fails, state remains 'starting' permanently, blocking all subsequent start attempts. Explicitly set state to 'inactive' after cleanup. * Use pure-Go xgb path for GetScreenSize robotgo.GetScreenSize() delegates to C-based XGetMainDisplay() which holds an unsynchronized static Display pointer. In Go's c-shared build mode CGo dispatches from varying OS threads, causing the singleton to silently return zero dimensions. Switch to robotgo.GetDisplayBounds(0) which uses the github.com/kbinani/screenshot pure-Go xgb implementation, matching the existing workaround for the SaveCapture segfault. * Upgrade robotgo to v1.0.1 with uniform error handling Use dedicated v1.0.1 APIs (MouseDown/Up, KeyDown/Up, Type, MultiClick) instead of Toggle/KeyToggle/TypeStr. All Go FFI exports now return error strings via *C.char, and the koffi bindings use HeapStr with a checkError() helper for uniform error propagation. Rename TypeStr→TypeText and SaveCapture→Screenshot to match v1.0.1 naming. Click now takes a count parameter — single, double, and multi-click are handled in Go. The worker-side triple-click loop is removed since Go handles it natively via robotgo.MultiClick.
Summary
Test coverage for the desktop environment feature across all three layers: container handler and service unit tests, SDK client unit tests, and an E2E test that exercises the full lifecycle through a deployed worker.
The E2E test starts a desktop, verifies the process health response, takes a screenshot (validating it returns a valid PNG), retrieves a VNC stream URL, and stops the desktop. The test worker and global sandbox helper are extended to expose desktop methods.
This is part 3 of 4 in the desktop environment stack:
main