CL

cli-e2e-testing

This skill provides patterns for implementing end-to-end tests for CLI applications using Hex1b for terminal interaction.

Install

mkdir -p .claude/skills/cli-e2e-testing && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/3296" && unzip -o skill.zip -d .claude/skills/cli-e2e-testing && rm skill.zip

Installs to .claude/skills/cli-e2e-testing

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use when creating, modifying, debugging, or reviewing Aspire CLI end-to-end tests that use Hex1b terminal automation under tests/Aspire.Cli.EndToEnd.Tests/.
156 chars✓ has a “when” trigger
Advanced

Key capabilities

  • Automate terminal sessions using Hex1b
  • Capture Aspire diagnostics during test execution
  • Manage isolated test workspaces
  • Execute terminal command sequences with deterministic prompt detection
  • Record and replay terminal sessions with asciinema

How it works

Tests use the Hex1b library to drive a headless terminal, wrapping execution in a TerminalRun to handle diagnostics and cleanup automatically.

Inputs & outputs

You give it
Terminal command sequences and test workspace configuration
You get back
Test execution logs, asciinema recordings, and captured project workspaces

When to use cli-e2e-testing

  • Create new CLI E2E tests
  • Debug failing terminal automation tests
  • Refactor existing test suites
  • Implement terminal command expectations

About this skill

Aspire CLI End-to-End Testing with Hex1b

This skill provides patterns and practices for writing end-to-end tests for the Aspire CLI using the Hex1b terminal automation library.

Overview

CLI E2E tests use the Hex1b library to automate terminal sessions, simulating real user interactions with the Aspire CLI. Tests run in CI with asciinema recordings for debugging.

Location: tests/Aspire.Cli.EndToEnd.Tests/

Supported Platforms: Linux only. Hex1b requires a Linux terminal environment. Tests are configured to skip on Windows and macOS in CI.

Key Components

Core Classes

  • Hex1bTerminal: The main terminal class from the Hex1b library for terminal automation
  • Hex1bTerminalAutomator: Async/await API for driving a Hex1bTerminal — the preferred approach for new tests
  • Hex1bAutomatorTestHelpers (shared helpers): Async extension methods on Hex1bTerminalAutomator (WaitForSuccessPromptAsync, AspireNewAsync, etc.)
  • CliE2EAutomatorHelpers (Helpers/CliE2EAutomatorHelpers.cs): CLI-specific async extension methods on Hex1bTerminalAutomator (PrepareDockerEnvironmentAsync, InstallAspireCliAsync, etc.)
  • CellPatternSearcher: Pattern matching for terminal cell content
  • SequenceCounter (Helpers/SequenceCounter.cs): Tracks command execution count for deterministic prompt detection
  • CliE2ETestHelpers (Helpers/CliE2ETestHelpers.cs): Environment variable helpers and terminal factory methods
  • TemporaryWorkspace: Creates isolated temporary directories for test execution
  • Hex1bTerminalInputSequenceBuilder (legacy): Fluent builder API for building sequences of terminal input/output operations. Prefer Hex1bTerminalAutomator for new tests.

Test Architecture

Each test:

  1. Creates a TemporaryWorkspace for isolation
  2. Builds a Hex1bTerminal with headless mode and asciinema recording
  3. Creates a Hex1bTerminalAutomator wrapping the terminal
  4. Drives the terminal with async/await calls and awaits completion

Test Structure

public sealed class SmokeTests(ITestOutputHelper output)
{
    [Fact]
    public async Task MyCliTest()
    {
        var repoRoot = CliE2ETestHelpers.GetRepoRoot();
        var strategy = CliInstallStrategy.Detect(output.WriteLine);
        var workspace = TemporaryWorkspace.Create(output);

        using var terminal = CliE2ETestHelpers.CreateDockerTestTerminal(repoRoot, strategy, output, workspace: workspace);

        var counter = new SequenceCounter();
        var auto = new Hex1bTerminalAutomator(terminal, defaultTimeout: TimeSpan.FromSeconds(500));
        await using var terminalRun = CliE2ETestHelpers.StartRun(terminal, workspace, auto, counter, output, TestContext.Current.CancellationToken);

        await auto.PrepareDockerEnvironmentAsync(counter, workspace);
        await auto.InstallAspireCliAsync(strategy, counter);

        await auto.TypeAsync("aspire --version");
        await auto.EnterAsync();
        await auto.WaitForSuccessPromptAsync(counter);
    }
}

TerminalRun Pattern

Always use CliE2ETestHelpers.StartRun to wrap the terminal run. This returns a TerminalRun (implements IAsyncDisposable) that automatically:

  1. Captures Aspire diagnostics via CaptureAspireDiagnosticsAsync (best effort)
  2. Types exit and presses Enter to close the terminal
  3. Awaits the pending run task

This eliminates the need for manual exit/await pendingRun at the end of every test and ensures diagnostics are always captured, even when tests fail.

// DO: Use StartRun for consistent diagnostics capture and cleanup
using var terminal = CliE2ETestHelpers.CreateDockerTestTerminal(repoRoot, strategy, output, workspace: workspace);

var counter = new SequenceCounter();
var auto = new Hex1bTerminalAutomator(terminal, defaultTimeout: TimeSpan.FromSeconds(500));
await using var terminalRun = CliE2ETestHelpers.StartRun(terminal, workspace, auto, counter, output, TestContext.Current.CancellationToken);

// ... test body — no exit/pendingRun needed at the end

// DON'T: Manually handle exit and pendingRun
var pendingRun = terminal.RunAsync(TestContext.Current.CancellationToken);
// ... test body ...
await auto.TypeAsync("exit");
await auto.EnterAsync();
await pendingRun;

Running Tests Locally

CLI E2E tests run inside Docker containers on Linux. The workflow is: build a portable archive with localhive, then point the tests at it. This is the primary way to iterate on E2E tests during development.

Prerequisites

  • Docker Desktop running (with Linux containers)
  • .NET 10 SDK (installed via ./restore.sh or .\restore.cmd)

Quick Start (macOS / Linux)

# 1. Build a portable archive with CLI + packages + bundle
#    Use linux-arm64 on Apple Silicon, linux-x64 on Intel/Linux
./localhive.sh -o /tmp/aspire-e2e -r linux-arm64 --archive

# 2. Run a specific test
ASPIRE_E2E_ARCHIVE=/tmp/aspire-e2e.tar.gz \
  dotnet test tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj \
  -- --filter-method "*.CreateAndRunAspireStarterProject"

# 3. Run all tests in a class
ASPIRE_E2E_ARCHIVE=/tmp/aspire-e2e.tar.gz \
  dotnet test tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj \
  -- --filter-class "*.SmokeTests"

Quick Start (Windows / PowerShell)

# 1. Build a portable archive (Docker Desktop uses linux-x64 via WSL2)
.\localhive.ps1 -o C:\tmp\aspire-e2e -r linux-x64 -Archive

# 2. Run a specific test
$env:ASPIRE_E2E_ARCHIVE = "C:\tmp\aspire-e2e.tar.gz"
dotnet test tests\Aspire.Cli.EndToEnd.Tests\Aspire.Cli.EndToEnd.Tests.csproj `
  -- --filter-method "*.CreateAndRunAspireStarterProject"

# 3. Run all tests in a class
dotnet test tests\Aspire.Cli.EndToEnd.Tests\Aspire.Cli.EndToEnd.Tests.csproj `
  -- --filter-class "*.SmokeTests"

Choosing the Right RID

The archive must match the Docker container's architecture:

HostDocker DesktopRID
Apple Silicon MacLinux arm64 containerslinux-arm64
Intel MacLinux x64 containerslinux-x64
Windows (any)WSL2 Linux x64linux-x64
Linux x64Nativelinux-x64
Linux arm64Nativelinux-arm64

Development Workflow

The typical loop when writing or debugging E2E tests:

# 1. Make your code changes (CLI, hosting, templates, etc.)

# 2. Rebuild the archive (picks up all changes — ~3 min)
./localhive.sh -o /tmp/aspire-e2e -r linux-arm64 --archive

# 3. Run the specific test you're working on
ASPIRE_E2E_ARCHIVE=/tmp/aspire-e2e.tar.gz \
  dotnet test tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj \
  -- --filter-method "*.YourTestName"

# 4. If it fails, check the asciinema recording
#    Recordings are saved under the test output TestResults/recordings/ directory
#    Play with: asciinema play /path/to/YourTestName.cast

# 5. Fix and repeat from step 1 or 2

Install Modes

The CliInstallStrategy class auto-detects how to install the CLI in the test container. You can override via environment variables:

Env VarModeExample
ASPIRE_E2E_ARCHIVELocalHive — extract archive into container/tmp/aspire-e2e.tar.gz
ASPIRE_E2E_QUALITYInstall script with qualitydev, staging, release
ASPIRE_E2E_VERSIONInstall script with version13.2.1
(none, in CI)PullRequest — install from PR artifactsAuto-detected
(none, locally)InstallScript (latest GA)Auto-detected

LocalHive (via ASPIRE_E2E_ARCHIVE) is the recommended mode for local development — it uses your locally-built CLI, packages, and bundle so you test exactly what you've changed.

Testing Against Released Versions

Useful for verifying tests pass against shipped versions or catching regressions:

# Test against latest GA release
ASPIRE_E2E_QUALITY=release dotnet test tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj \
  -- --filter-method "*.CreateAndRunAspireStarterProject"

# Test against daily builds
ASPIRE_E2E_QUALITY=dev dotnet test ...

# Test against a specific version
ASPIRE_E2E_VERSION=13.2.1 dotnet test ...

Emulated channel matrix tests (identity sidecar)

A set of tests validates the CLI identity sidecar — the ability to make a locally built CLI emulate a different channel/version via ASPIRE_CLI_* env vars. They form an AppHost-language × channel-emulation matrix (one test per language because C# and TypeScript scaffold through different code paths and have diverged before):

ClassChannel emulatedAspire* sourceNuGet.config dropped?
EmulatedReleasedBuildTestsstable (latest shipped)nuget.orgNo (C# and TS)
EmulatedStagingBuildTestsstaging (latest darc build)darc-pub-... feedYes — darc feed pin
EmulatedLocalReleaseBuildTestsstable (future, local-only)local hive via ASPIRE_CLI_PACKAGESNo (C# and TS)

EmulatedLocalReleaseBuildTests is the all-local "future release" row: it emulates a version (e.g. 13.5.0) that exists only in a locally built hive, so a successful resolve proves the CLI consulted ASPIRE_CLI_PACKAGES rather than nuget.org. Run it by building a stable-shaped archive with localhive --version:

# 1. Build a stable-shaped archive (note: --version X.Y.Z, NOT a prerelease suffix)
./localhive.sh --version 13.5.0 -o /tmp/aspire-localrelease -r linux-arm64 --archive

# 2. Run the all-local class
ASPIRE_E2E_ARCHIVE=/tmp/aspire-localrelease.tar.gz \
  dotnet test --project tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj \
  -- --filter-class "*.EmulatedLocalReleaseBuildTests"

These tests skip unless the CLI was installed from a LocalHive archive and that archive is stable-shaped (no prerelease suffix). In default CI the archive is a prerelease `LocalArchive


Content truncated.

When not to use it

  • Non-Linux environments
  • Windows or macOS CI pipelines

Prerequisites

Docker Desktop.NET 10 SDK

Limitations

  • Requires a Linux terminal environment
  • Tests are configured to skip on Windows and macOS

How it compares

Unlike manual terminal testing, this approach uses an async-driven automator and deterministic sequence counters to ensure reliable CI execution.

Compared to similar skills

cli-e2e-testing side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
cli-e2e-testing (this skill)11moReviewAdvanced
webapp-testing3533moReviewIntermediate
dev-browser534moReviewIntermediate
playwright-browser-automation297moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

webapp-testing

anthropics

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

353585

dev-browser

SawyerHood

Browser automation with persistent page state. Use when users ask to navigate websites, fill forms, take screenshots, extract web data, test web apps, or automate browser workflows. Trigger phrases include "go to [url]", "click on", "fill out the form", "take a screenshot", "scrape", "automate", "test the website", "log into", or any browser interaction request.

53176

playwright-browser-automation

lackeyjb

Complete browser automation with Playwright. Auto-detects dev servers, writes clean test scripts to /tmp. Test pages, fill forms, take screenshots, check responsive design, validate UX, test login flows, check links, automate any browser task. Use when user wants to test websites, automate browser interactions, validate web functionality, or perform any browser-based testing.

29146

windows-ui-automation

martinholovsky

Expert in Windows UI Automation (UIA) and Win32 APIs for desktop automation. Specializes in accessible, secure automation of Windows applications including element discovery, input simulation, and process interaction. HIGH-RISK skill requiring strict security controls for system access.

17126

unity-mcp-orchestrator

CoplayDev

Orchestrate Unity Editor via MCP (Model Context Protocol) tools and resources. Use when working with Unity projects through MCP for Unity - creating/modifying GameObjects, editing scripts, managing scenes, running tests, or any Unity Editor automation. Provides best practices, tool schemas, and workflow patterns for effective Unity-MCP integration.

1795

agent-browser

vercel-labs

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.

3075

Search skills

Search the agent skills registry