Migrate CLI and Deployment E2E tests to Hex1bTerminalAutomator API#15244
Migrate CLI and Deployment E2E tests to Hex1bTerminalAutomator API#15244mitchdenny merged 12 commits intorelease/13.2from
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15244Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15244" |
There was a problem hiding this comment.
Pull request overview
Migrates Aspire CLI end-to-end tests from the Hex1bTerminalInputSequenceBuilder fluent/batched API to the Hex1bTerminalAutomator imperative async/await API to improve debuggability and step-level failure reporting.
Changes:
- Converted a broad set of CLI E2E tests to
Hex1bTerminalAutomator(TypeAsync,EnterAsync,WaitUntilAsync, prompt helpers, etc.). - Replaced builder callbacks with direct file operations and explicit awaits around terminal steps.
- Added a new
ClearScreenAsyncautomator helper for consistent screen clearing + prompt synchronization.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs | Migrates TypeScript starter template flow to automator API. |
| tests/Aspire.Cli.EndToEnd.Tests/TypeScriptPolyglotTests.cs | Migrates interactive aspire init TypeScript selection + run/stop to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/TypeScriptCodegenValidationTests.cs | Migrates TypeScript restore/codegen validation scenarios to automator, including CI bundle install flow. |
| tests/Aspire.Cli.EndToEnd.Tests/StopNonInteractiveTests.cs | Migrates non-interactive stop scenarios, using new ClearScreenAsync. |
| tests/Aspire.Cli.EndToEnd.Tests/StartStopTests.cs | Migrates start/stop and package-add-while-detached scenarios to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/StagingChannelTests.cs | Migrates config set/get/delete channel flow to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/SmokeTests.cs | Migrates smoke run + regression prompt detection to automator and fail-fast checks. |
| tests/Aspire.Cli.EndToEnd.Tests/SecretTypeScriptAppHostTests.cs | Migrates secret CRUD against TS AppHost to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/SecretDotNetAppHostTests.cs | Migrates secret CRUD against .NET AppHost to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/PythonReactTemplateTests.cs | Migrates Python React template run/stop flow to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/PsCommandTests.cs | Migrates aspire ps table/json validation to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/ProjectReferenceTests.cs | Migrates TypeScript project-reference/codegen scenario to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/PlaywrightCliInstallTests.cs | Migrates agent-init Playwright CLI install + skill file checks to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/MultipleAppHostTests.cs | Migrates detach/json validation scenario to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/LogsCommandTests.cs | Migrates aspire logs file output and JSON validation to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/KubernetesPublishTests.cs | Migrates KinD/Helm publish/deploy workflow to automator while preserving cleanup semantics. |
| tests/Aspire.Cli.EndToEnd.Tests/JsReactTemplateTests.cs | Migrates JS React template run + regression prompt detection to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/Helpers/CliE2EAutomatorHelpers.cs | Adds ClearScreenAsync helper for prompt-synchronized screen clearing. |
| tests/Aspire.Cli.EndToEnd.Tests/EmptyAppHostTemplateTests.cs | Migrates Empty AppHost template creation to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/DoctorCommandTests.cs | Migrates doctor SSL_CERT_DIR trust detection scenarios to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/DockerDeploymentTests.cs | Migrates Docker Compose deploy workflows to automator, including CI install/version verification. |
| tests/Aspire.Cli.EndToEnd.Tests/DescribeCommandTests.cs | Migrates aspire describe scenarios (table/json + replicas) to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/CertificatesCommandTests.cs | Migrates cert trust/clean flows to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/CentralPackageManagementTests.cs | Migrates CPM update/add workflows to automator with direct file validation. |
| tests/Aspire.Cli.EndToEnd.Tests/BundleSmokeTests.cs | Migrates bundle smoke test (detach JSON + curl) to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/BannerTests.cs | Migrates banner tests (sentinel manipulation + pattern assertions) to automator. |
| tests/Aspire.Cli.EndToEnd.Tests/AgentCommandTests.cs | Migrates agent command help/init/doctor tests to automator, replacing builder file helpers with direct IO. |
You can also share your feedback on Copilot code review. Take the survey.
| // PrepareEnvironment | ||
| await auto.WaitUntilAsync(s => new CellPatternSearcher().Find("b").RightUntil("$").Right(' ').Right(' ').Search(s).Count > 0, timeout: TimeSpan.FromSeconds(10), description: "waiting for input prompt"); | ||
| await auto.WaitAsync(500); | ||
| const string promptSetup = "CMDCOUNT=0; PROMPT_COMMAND='s=$?;((CMDCOUNT++));PS1=\"[$CMDCOUNT $([ $s -eq 0 ] && echo OK || echo ERR:$s)] \\$ \"'"; | ||
| await auto.TypeAsync(promptSetup); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); | ||
| await auto.TypeAsync($"cd {workspace.WorkspaceRoot.FullName}"); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); |
| // Prepare environment | ||
| await auto.WaitUntilAsync(s => new CellPatternSearcher().Find("b").RightUntil("$").Right(' ').Right(' ').Search(s).Count > 0, timeout: TimeSpan.FromSeconds(10), description: "waiting for input prompt"); | ||
| await auto.WaitAsync(500); | ||
| const string promptSetup = "CMDCOUNT=0; PROMPT_COMMAND='s=$?;((CMDCOUNT++));PS1=\"[$CMDCOUNT $([ $s -eq 0 ] && echo OK || echo ERR:$s)] \\$ \"'"; | ||
| await auto.TypeAsync(promptSetup); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); | ||
| await auto.TypeAsync($"cd {workspace.WorkspaceRoot.FullName}"); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); |
| await auto.WaitUntilAsync(s => new CellPatternSearcher().Find("b").RightUntil("$").Right(' ').Right(' ').Search(s).Count > 0, timeout: TimeSpan.FromSeconds(10), description: "waiting for input prompt"); | ||
| await auto.WaitAsync(500); | ||
| const string promptSetup = "CMDCOUNT=0; PROMPT_COMMAND='s=$?;((CMDCOUNT++));PS1=\"[$CMDCOUNT $([ $s -eq 0 ] && echo OK || echo ERR:$s)] \\$ \"'"; | ||
| await auto.TypeAsync(promptSetup); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); | ||
| await auto.TypeAsync($"cd {workspace.WorkspaceRoot.FullName}"); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); | ||
|
|
| if (!fileContent.Contains("\"mcp\"")) | ||
| { | ||
| throw new InvalidOperationException($"Expected file '{configPath}' to contain '\"mcp\"' but it did not. Content: {fileContent}"); | ||
| } | ||
| fileContent = File.ReadAllText(configPath); | ||
| if (!fileContent.Contains("\"start\"")) | ||
| { | ||
| throw new InvalidOperationException($"Expected file '{configPath}' to contain '\"start\"' but it did not. Content: {fileContent}"); | ||
| } |
| // PrepareEnvironment | ||
| await auto.WaitUntilAsync(s => new CellPatternSearcher().Find("b").RightUntil("$").Right(' ').Right(' ').Search(s).Count > 0, timeout: TimeSpan.FromSeconds(10), description: "waiting for input prompt"); | ||
| await auto.WaitAsync(500); | ||
| const string promptSetup = "CMDCOUNT=0; PROMPT_COMMAND='s=$?;((CMDCOUNT++));PS1=\"[$CMDCOUNT $([ $s -eq 0 ] && echo OK || echo ERR:$s)] \\$ \"'"; | ||
| await auto.TypeAsync(promptSetup); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); | ||
| await auto.TypeAsync($"cd {workspace.WorkspaceRoot.FullName}"); | ||
| await auto.EnterAsync(); | ||
| await auto.WaitForSuccessPromptAsync(counter); |
|
The transient CI rerun workflow requested reruns for the following jobs after analyzing the failed attempt.
|
🎬 CLI E2E Test RecordingsThe following terminal recordings are available for commit
📹 Recordings uploaded automatically from CI run #23133411978 |
|
The transient CI rerun workflow requested reruns for the following jobs after analyzing the failed attempt.
|
|
Addressed all 5 review comments in commit 66afe30:
|
|
The transient CI rerun workflow requested reruns for the following jobs after analyzing the failed attempt.
|
Convert CreateAndRunAspireStarterProject from Hex1bTerminalInputSequenceBuilder (fluent builder) to Hex1bTerminalAutomator (async/await imperative) API. Preserves all test behavior including: - Regression check for #13971 (unexpected apphost selection prompt) - Ctrl+C to stop aspire run - Fail-fast on duplicate apphost detection Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Convert all 4 test methods from Hex1bTerminalInputSequenceBuilder (fluent builder) to Hex1bTerminalAutomator (async/await imperative) API: - CreateStartAndStopAspireProject - StopWithNoRunningAppHostExitsSuccessfully - AddPackageWhileAppHostRunningDetached - AddPackageInteractiveWhileAppHostRunningDetached Key migration notes: - IncrementSequence(counter) replaced with WaitForAnyPromptAsync(counter) for the cleanup stop command where exit code may vary - All pattern searchers and behavioral logic preserved Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…to automator API Migrated test files: - StopNonInteractiveTests (4 methods) - EmptyAppHostTemplateTests (1 method) - JsReactTemplateTests (1 method) - PythonReactTemplateTests (1 method) Added ClearScreenAsync helper to CliE2EAutomatorHelpers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrated test files: - TypeScriptStarterTemplateTests (1 method) - replaced ExecuteCallback with inline assertions (natural in async/await flow) - BundleSmokeTests (1 method) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrated test files: - DescribeCommandTests (2 methods) - PsCommandTests (2 methods) - LogsCommandTests (1 method) - MultipleAppHostTests (1 method) - CentralPackageManagementTests (2 methods) - SecretDotNetAppHostTests (1 method) - SecretTypeScriptAppHostTests (1 method) - AgentCommandTests (4 methods) - PlaywrightCliInstallTests (1 method) - DoctorCommandTests (2 methods) - BannerTests (3 methods) - CertificatesCommandTests (3 methods) - DockerDeploymentTests (2 methods) - KubernetesPublishTests (1 method) - StagingChannelTests (1 method) - TypeScriptCodegenValidationTests (2 methods) - TypeScriptPolyglotTests (1 method) - ProjectReferenceTests (1 method) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add Hex1bAutomatorTestHelpers.cs link to deployment test project - Create DeploymentE2EAutomatorHelpers.cs with PrepareEnvironmentAsync, InstallAspireCliFromPullRequestAsync, InstallAspireCliReleaseAsync, SourceAspireCliEnvironmentAsync - Migrate AcaStarterDeploymentTests as reference implementation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add PrepareEnvironmentAsync, InstallAspireCliFromPullRequestAsync, SourceAspireCliEnvironmentAsync, VerifyAspireCliVersionAsync, InstallAspireBundleFromPullRequestAsync, SourceAspireBundleEnvironmentAsync to CliE2EAutomatorHelpers - Replace inlined PrepareEnvironment in DockerDeploymentTests, KubernetesPublishTests, TypeScriptCodegenValidationTests with helpers - Replace File.ReadAllText + throw InvalidOperationException with Assert.Contains/Assert.DoesNotContain in AgentCommandTests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…o automator API Migrated 3 new test files added after the initial migration: - ConfigHealingTests (1 method) - ConfigMigrationTests (7 methods, including 1 OuterloopTest) - TypeScriptPublishTests (1 method) Added new automator helpers: - EnablePolyglotSupportAsync (no-op, matching old API) - InstallAspireCliVersionAsync (downloads specific CLI version) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
66afe30 to
0df044a
Compare
tests/Aspire.Cli.EndToEnd.Tests/CentralPackageManagementTests.cs
Outdated
Show resolved
Hide resolved
Address PR feedback from JamesNK: simplify verbose CellPatternSearcher
patterns by using WaitUntilTextAsync(string) and ContainsText(string)
APIs already available in Hex1b v0.116.0.
Changes across 56 files (30 CLI E2E + 26 Deployment E2E):
- Simple Find patterns: CellPatternSearcher().Find("text") +
WaitUntilAsync(s => pattern.Search(s).Count > 0) replaced with
WaitUntilTextAsync("text", timeout)
- Compound predicates: replaced CellPatternSearcher inner expressions
with s.ContainsText("text") for && and || conditions
- Complex patterns preserved: RightUntil, RightText, FindPattern
(prompt detection/regex) correctly left unchanged
Net result: -868 lines of boilerplate removed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Addressed James' feedback in e00a48e: replaced all simple Net result: -868 lines of boilerplate across 56 files. |
|
The transient CI rerun workflow requested reruns for the following jobs after analyzing the failed attempt.
|
JamesNK
left a comment
There was a problem hiding this comment.
If WaitUntilTextAsync creates good error messages on failure then looks good to me.
Description
Migrates all CLI E2E and Deployment E2E tests from the
Hex1bTerminalInputSequenceBuilderfluent builder API to theHex1bTerminalAutomatorasync/await imperative API.This builds on the foundation laid in #15206 (Hex1b 0.116.0, shared helpers,
WaitCommandTestsreference migration).Closes #15241
Changes
CLI E2E Tests (26 files, 52 test methods)
All test files migrated, including:
Not migrated (no Hex1b usage):
McpDocsE2ETests(MCP SDK),AuthenticationTests(static validation)Deployment E2E Tests (26 files, 26 test methods)
All deployment test files migrated, including:
Not migrated (no Hex1b usage):
AuthenticationTests(static validation)New Helpers Created
ClearScreenAsyncinCliE2EAutomatorHelpers.csPrepareEnvironmentAsync,InstallAspireCliFromPullRequestAsync,InstallAspireCliReleaseAsync,SourceAspireCliEnvironmentAsyncinDeploymentE2EAutomatorHelpers.csAspireInitAsyncin sharedHex1bAutomatorTestHelpers.csHex1bAutomatorTestHelpers.cslinked to deployment test projectSkill Documents Updated
.github/skills/cli-e2e-testing/SKILL.md— updated with automator API patterns.github/skills/deployment-e2e-testing/SKILL.md— updated with deployment automator patternsMigration Pattern
Old (Builder/Fluent):
New (Automator/Async):
Benefits
async/awaitis more natural than fluent chainsTesting