Add VS Code extension E2E tests with Playwright + Docker#15407
Draft
mitchdenny wants to merge 32 commits intomicrosoft:mainfrom
Draft
Add VS Code extension E2E tests with Playwright + Docker#15407mitchdenny wants to merge 32 commits intomicrosoft:mainfrom
mitchdenny wants to merge 32 commits intomicrosoft:mainfrom
Conversation
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15407Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15407" |
- Dockerfile.e2e-vscode: Docker image running VS Code via 'code serve-web' with --without-connection-token for auth-free browser access - VsCodeContainer.cs: Docker lifecycle (build, run, wait for ready, dispose) - VsCodeWebFixture.cs: xUnit fixture combining Docker + Playwright with video recording, tracing, and screenshot support - SmokeTests.cs: Smoke test verifying VS Code renders in headless Chromium - Test project configured as Linux-only, excluded from Helix/AzDO Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Install GA Aspire CLI via 'curl -sSL https://aspire.dev/install.sh | bash' - Use docker exec to poll for completion (xterm.js canvas can't be read from DOM) - Verify aspire --version runs successfully inside container - Screenshots captured: terminal-opened, install-complete, aspire-version Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Theory-based test: release (GA), dev (daily), staging (prerelease) - Each test cleans previous install, runs curl aspire.dev/install.sh with --quality flag, verifies aspire --version via docker exec - Dockerfile: add Node.js 22 LTS (needed for VS Code extension host) - Dockerfile: add curl explicitly for install script Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Milestone 1 & 2: Docker + Hex1b diagnostics socket + workload adapter - Install Hex1b.Tool in Docker image and expose socket directory via volume mount - Implement DiagnosticsWorkloadAdapter: connects to hex1b diagnostics socket, performs attach handshake, streams o:/i:/r: frames - Implement RemoteTerminalSession: wraps adapter + headless Hex1bTerminal for convenient test use (SendTextAsync, WaitForTextAsync, GetScreenText) - Add socket permission fix (chmod 777 via docker exec) for host access - Add two new tests: - Hex1bTerminalCreatesSocketViaMountedVolume: proves socket appears - RemoteTerminalSessionCanSendAndReceiveText: full round-trip echo test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace docker exec + marker file approach with RemoteTerminalSession: - Tests connect via diagnostics socket to read real terminal output - WaitForAnyTextAsync detects install completion signals - aspire --version verified through both terminal session and docker exec - Asciinema recordings captured via hex1b --record flag and copied from container - Each quality level produces: .webm video, .zip trace, .cast recording Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Milestone 5: Drive Spectre.Console prompts through Hex1b remote terminal - New AspireNewCreatesProjectInteractively test: installs Aspire CLI, runs 'aspire new' with no arguments, drives all interactive prompts - Template selection, project name, output path, and template-specific prompts (localhost TLD, Redis cache, test project) all handled - Additional prompts auto-detected and answered with defaults - Project creation verified via docker exec (files exist) - Full artifact suite: screenshots per prompt step, Playwright trace, asciinema recording from container - Add scrollback support to RemoteTerminalSession (GetFullText, includeScrollback parameter on wait methods) — critical for long command output that scrolls past the visible 30-line screen Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add MaximizeTerminalPanelAsync helper: opens command palette, runs 'View: Toggle Maximized Panel' to fill editor area with terminal - Called before hex1b launch in all 4 terminal-based tests - Add 5-second delay after final assertion so video captures show the completed result Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n tests M6: Follow the CLI E2E pattern — build on host, mount read-only into container. - AspireBuildArtifacts: detects CLI binary, VSIX, NuGet packages, and nuget config from prior ./build.sh --bundle --build-extension --pack - Dockerfile: add Docker CLI (for DCP), entrypoint script that installs VSIX via 'code --install-extension' before starting serve-web - VsCodeContainer: accept optional artifacts + Docker socket mount, volume-mount CLI at /opt/aspire-cli, VSIX, packages, nuget config - VsCodeWebFixture: auto-detect artifacts, skip integration tests when no local build is available Existing tests continue to work without artifacts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Host - Install CLI from local build artifacts, create project with aspire new - Patch SDK version from GA to dev to enable backchannel sockets - Restore with local NuGet packages, run aspire start - Verify Aspire extension tree view shows apiservice, cache, webfrontend - Add ASPIRE_ARTIFACTS_ROOT env var for worktree artifact detection - Fix VSIX install: use correct --extensions-dir for serve-web - All 8 tests passing (smoke + 3 install + interactive new + integration) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update Hex1b, Hex1b.McpServer, Hex1b.Tool from 0.116.0 to 0.119.0 - Add nuget.org package source for Hex1b* packages - Update Dockerfile to install Hex1b.Tool 0.119.0 - Increase terminal-wrapper wait timeout from 30s to 60s to reduce flakiness under concurrent Docker load Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ort) Replace custom DiagnosticsWorkloadAdapter with Hex1b's built-in RemoteTerminalWorkloadAdapter, connecting via WebSocket instead of Unix domain sockets. This eliminates the socket volume mount and simplifies the Docker setup. Key changes: - Delete DiagnosticsWorkloadAdapter.cs (replaced by built-in adapter) - RemoteTerminalSession.ConnectAsync now takes a URI and uses WithRemoteTerminal() with retry logic for connection resilience - VsCodeContainer: replace socket mount with port allocation and socat bridge (workaround for hex1b binding to loopback only) - All tests updated: --attach → --passthru --port - Dockerfile: add socat for port bridging Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hex1b 0.120.0 adds --bind flag for the WebSocket listener, allowing it to bind to 0.0.0.0 in containers. This removes the need for the socat port bridge workaround. Changes: - Hex1b packages: 0.119.0 → 0.120.0 (Directory.Packages.props) - Hex1b.Tool: 0.119.0 → 0.120.0 (Dockerfile) - Remove socat from Dockerfile and VsCodeContainer - All hex1b commands now use --bind 0.0.0.0 - Simplify AllocateHex1bPort (no more internal/exposed port split) All 7 non-integration tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove 6 scaffolding/smoke tests (VsCodeLaunchesAndRendersWorkbench,
Hex1bTerminalStartsWithWebSocketPort, RemoteTerminalSessionCanSendAndReceiveText,
InstallAspireCliViaTerminal, AspireNewCreatesProjectInteractively)
- Keep only ExtensionShowsResourcesFromRunningAppHost (full integration test)
- Rename class SmokeTests → ExtensionEndToEndTests
- Refactor fixture: each test gets its own output directory under
artifacts/testresults/extension-e2e/{TestName}/ with all artifacts
(screenshots, traces, recordings, videos) in one place
- Number screenshot filenames (01-cli-installed, 02-project-created, etc.)
for clear chronological ordering
- Each test creates its own browser context (videos/traces scoped per-test)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the ?folder= URL approach (which causes full page reload and terminal disconnection) with 'code -a /path' to add the project folder to the workspace. This keeps the terminal, hex1b session, and video recording running continuously throughout the entire test. Key changes: - All phases run in a single VS Code session without page reloads - CLI install, aspire new, restore, and aspire start all happen in the same hex1b terminal session - Workspace trust dialog dismissed automatically after code -a - Default apphost notification from Aspire extension handled - Late trust dialog safety check before Phase 6 sidebar interaction - Test passes in ~115 seconds with full artifact suite Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the docker.io Debian/Ubuntu package with Docker's official apt repository, providing docker-ce-cli, docker-compose-plugin, and docker-buildx-plugin. This ensures templates that use Docker containers (e.g., Redis, PostgreSQL) work correctly inside the test container. The base image is Ubuntu (noble), so we use Docker's Ubuntu repo URL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the host Docker socket mount with a full Docker-in-Docker setup so that DCP-managed containers (e.g., Redis cache) run inside the test container and share its network namespace. This fixes the cache resource failing to start (red icon in the extension tree view). Changes: - Dockerfile: install docker-ce + containerd.io (full daemon), add VOLUME /var/lib/docker for overlay storage - Entrypoint: start dockerd in background, wait up to 30s for ready - Container runner: use --privileged flag, remove socket mount option - VsCodeContainer: simplify constructor (remove mountDockerSocket param) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove unnecessary Task.Delay calls and replace with WaitForSelectorAsync - Reduce polling loop intervals (2000ms→500ms for creation, 5000ms→2000ms for resources) - Add WaitForSelectorState.Hidden after MaximizeTerminalPanelAsync to ensure command palette closes - Click terminal area before typing hex1b command to ensure focus - Add hex1b process check diagnostic after WaitForHex1bAsync - Replace fragile .split-view-view wait with simple delay - Test passes in ~87s Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the same PROMPT_COMMAND trick as Aspire.Cli.EndToEnd.Tests:
bash PROMPT_COMMAND sets PS1 to [N OK] $ or [N ERR:code] $
after each command, making command completion deterministic.
Changes:
- Add SequenceCounter class to track prompt sequence numbers
- Add SetupPromptAsync to install PROMPT_COMMAND in the shell
- Add WaitForSuccessPromptAsync, WaitForAnyPromptAsync,
WaitForSuccessPromptFailFastAsync to RemoteTerminalSession
- Replace all WaitForTextAsync("~#") / WaitForAnyTextAsync(["~#",
"root@"]) with prompt-based detection
- Remove echo marker test (prompt trick proves session works)
- Use WaitForSuccessPromptFailFastAsync for critical commands
(CLI install) to fail immediately on error
- Use WaitForAnyPromptAsync for restore (allows failure to continue)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…0s→3s content wait Total test time dropped from ~110s to ~98s by reducing conservative retry delays in the WebSocket connection loop. Also added timing instrumentation to the hex1b connection phase for diagnosing lag. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Docker's userspace proxy accepts TCP connections even when hex1b isn't listening yet, causing the WebSocket handshake to hang for ~30s. Now WaitForHex1bAsync uses 'docker exec ss -tlnp' to verify hex1b is actually listening inside the container before attempting the WebSocket connection from the host. Added iproute2 to the Docker image for ss. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ring The shell was running but its initial PS1 prompt wasn't rendered to hex1b's virtual terminal. WaitForAnyTextAsync polled for 30s finding nothing. Sending a single Enter keystroke nudges bash into displaying its prompt immediately (0.2s vs 30s). Total test time: 65s (was 98s). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pass --source /opt/aspire/packages --version {version} to aspire new
so the generated project references the same dev packages that are
mounted into the container. Previously aspire new resolved templates
from nuget.org (13.1.3 GA) making the test validate the wrong thing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Instead of --source/--version flags, use the CLI's built-in hive mechanism (same as get-aspire-cli-pr.sh for PR builds): - Set up hive symlink: ~/.aspire/hives/local/packages → /opt/aspire/packages - Use --channel local to auto-select local packages - CLI auto-generates NuGet.config from hive channel Key changes: - AspireBuildArtifacts: prefer Release config (localhive.sh output), search Aspire.Cli.Tool before Aspire.Cli for framework-dependent CLI - Copy entire CLI directory (cp -a) since Cli.Tool is framework-dependent - localhive.sh produces properly versioned prerelease packages (13.2.0-local.TIMESTAMP) that dotnet package search can discover Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reorder FindCliPublishDirectory to search Aspire.Cli (native AOT) before Aspire.Cli.Tool (framework-dependent), and prefer the native subdirectory. The native AOT binary is self-contained so cp -a still works (just copies 2 files instead of 80+). Prerequisite: run ./localhive.sh --native-aot to produce a native AOT CLI with matching version suffix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
deb2b0f to
bbbcbfd
Compare
- Add SplitTestsOnCI, RequiresCliArchive, RequiresNugets, EnablePlaywrightInstall to the extension E2E test project - Add IncludeExtensionE2ETests skip condition in TestEnumerationRunsheetBuilder - Pass IncludeExtensionE2ETests flag in tests.yml enumerate step - Pass enablePlaywrightInstall from matrix to run-tests.yml - Propagate enablePlaywrightInstall through build-test-matrix.ps1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hex1b packages resolve through the existing dotnet-public/dotnet-eng wildcard mappings, so the explicit nuget.org source is unnecessary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Import Playwright.targets which provides the ProvisionBrowsersForPlaywright build target that downloads chromium during build. Set InstallBrowsersForPlaywright=true on CI builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Browsers are installed to artifacts/bin/playwright-deps/ during build, but at runtime Playwright defaults to ~/.cache/ms-playwright/. Use the shared PlaywrightProvider.DetectAndSetInstalledPlaywrightDependenciesPath() to auto-discover the repo-local browser install path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The extension tests output to artifacts/testresults/extension-e2e/ but the CI upload step only captured testresults/**. Add artifacts/testresults/** to the upload path and search it for .cast recordings too. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The extension E2E test self-skipped because the CI job didn't have the locally-built CLI binary or VSIX available. Add requiresExtensionArtifacts flag that flows through the test matrix pipeline and triggers download + extraction of: - cli-native-archives-linux-x64 → artifacts/bin/Aspire.Cli/.../publish/ - aspire-extension VSIX → artifacts/packages/Debug/vscode/ This matches what AspireBuildArtifacts.Detect() expects to find. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When 'code -a' adds a folder to an empty workspace, VS Code reloads the window (full navigation). The old execution context is destroyed, causing QuerySelectorAsync to throw. Fix by: 1. WaitForLoadStateAsync after code -a to let navigation complete 2. WaitForSelectorAsync for .monaco-workbench to confirm reload done 3. Use WaitForSelector with timeout for notification handling instead of QuerySelector which races with async DOM updates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds end-to-end UI testing infrastructure for the Aspire VS Code extension using Playwright browser automation inside Docker containers.
What it does
A single comprehensive test (
ExtensionShowsResourcesFromRunningAppHost) validates the full extension workflow:code serve-webin a Docker container with Docker-in-Dockeraspire startand verifies the extension's resource tree shows all expected resources (apiservice, cache, webfrontend)Architecture
localhive.shpackages via~/.aspire/hives/local/for correct version testingPrerequisites to run
Test artifacts produced
Each test run generates: screenshots at key milestones (01-08), video recording (WebM), terminal recording (asciinema .cast), and Playwright trace (.zip).
New files
ExtensionEndToEndTests.csInfrastructure/AspireBuildArtifacts.csInfrastructure/Hex1b/RemoteTerminalSession.csInfrastructure/VsCodeContainer.csInfrastructure/VsCodeWebFixture.csDockerfile.e2e-vscodeentrypoint-e2e-vscode.shChecklist
<remarks />and<code />elements on your triple slash comments?aspire.devissue: