Agent Skillswarpdotdev/warp › tui-testing

tui-testing

GitHub

指导如何为 Warp 的无头 TUI 前端编写和运行单元测试。通过渲染元素树到文本行进行断言,区分了组件库与视图层的测试辅助函数使用场景,不涉及真实 GUI 集成测试。

.agents/skills/tui-testing/SKILL.md warpdotdev/warp

Trigger Scenarios

需要为 TUI 界面元素编写单元测试 验证 TUI 组件渲染输出的文本内容 调试 TUI 布局或渲染逻辑

Install

npx skills add warpdotdev/warp --skill tui-testing -g -y
More Options

Non-standard path

npx skills add https://github.com/warpdotdev/warp/tree/master/.agents/skills/tui-testing -g -y

Use without installing

npx skills use warpdotdev/warp@tui-testing

指定 Agent (Claude Code)

npx skills add warpdotdev/warp --skill tui-testing -a claude-code -g -y

安装 repo 全部 skill

npx skills add warpdotdev/warp --all -g -y

预览 repo 内 skill

npx skills add warpdotdev/warp --list

SKILL.md

Frontmatter
{
    "name": "tui-testing",
    "description": "Write and run unit tests for Warp TUI (crates\/warp_tui) elements\/screens by rendering to text lines. Use for TUI test work."
}

tui-testing

How to write and run unit tests for Warp's headless TUI front-end (crates/warp_tui and the element library at crates/warpui_core/src/elements/tui). This complements rust-unit-tests (general Rust test conventions) and parallels gui-integration-test for the TUI.

TUI tests are plain, fast unit tests: they render an element tree to a fixed cell grid and assert on the resulting text lines. They do not use the GUI real-display / integration / computer-use framework (that's gui-integration-test / gui-integration-test-video, which are GUI-only).

Two test locations, two harnesses

TUI tests live in two crates, and which render helper you use depends on where the test is:

Element-library tests (in warpui_core)

Tests for the shared cell-grid elements live in crates/warpui_core/src/elements/tui/*_tests.rs and use the crate-internal test_support helpers from crates/warpui_core/src/elements/tui/mod.rs:

  • test_support::render_to_lines(element: &dyn TuiElement, size: TuiSize) -> Vec<String> — one-call harness: builds area = TuiRect::new(0, 0, size.width, size.height) and TuiBuffer::empty(area), calls element.render(area, &mut buffer, ctx) inside a paint context, and returns buffer.to_lines(). It only calls render, not layout — fine for a leaf like TuiText, but composite elements (e.g. TuiFlex) populate child sizes during layout, so lay the element out first (see the layout_at helper in flex_tests.rs) or it renders empty/stale.
  • test_support::with_paint_context(|ctx| ...) — runs a closure with a TuiPaintContext over a fresh, empty view map. Use it when you need the TuiBuffer afterward to assert on individual Cells.

These helpers are pub(crate) to warpui_core, so they are only callable from that crate's own tests. Simplest leaf assertion (see text_tests.rs, flex_tests.rs):

assert_eq!(
    render_to_lines(&TuiText::new("hello"), TuiSize::new(10, 1)),
    vec!["hello     "],
);

View/screen tests (in warp_tui)

warp_tui tests (crates/warp_tui/src/*_tests.rs) can NOT use test_support — render directly instead, under an App::test read/update so an AppContext is available. layout must run before render so child sizes are populated. This local helper mirrors render_element in transcript_view_tests.rs and render_lines in editor_element_tests.rs:

fn render_lines(app_ctx: &AppContext, mut element: impl TuiElement, w: u16, h: u16) -> Vec<String> {
    let mut rendered_views = EntityIdMap::default();
    let mut lctx = TuiLayoutContext { rendered_views: &mut rendered_views };
    let size = element.layout(TuiConstraint::loose(TuiSize::new(w, h)), &mut lctx, app_ctx);
    let area = TuiRect::new(0, 0, size.width, size.height);
    let mut buffer = TuiBuffer::empty(area);
    let mut paint_ctx = TuiPaintContext::new(&mut rendered_views);
    element.render(area, &mut buffer, &mut paint_ctx);
    buffer.to_lines()
}

Views that resolve theme styles need an Appearance singleton (ctx.add_singleton_model(|_| Appearance::mock())). To exercise a whole view through the real draw path, drive the presenter: TuiPresenter::new(), presenter.invalidate(&invalidation, ctx, window_id), then presenter.present(ctx, &view, area) and assert on frame.buffer.to_lines() (see transcript_view_tests.rs).

Asserting on styles, cursor, and events

  • Styles/colors: paint into a buffer yourself and index cells. to_lines() only carries glyphs, so style assertions read Cell fields:
let mut buffer = TuiBuffer::empty(TuiRect::new(0, 0, 1, 1));
with_paint_context(|ctx| text.render(TuiRect::new(0, 0, 1, 1), &mut buffer, ctx));
let cell = &buffer[(0, 0)];
assert_eq!(cell.symbol(), "a");
assert_eq!(cell.fg, Color::Red);
assert!(cell.modifier.contains(Modifier::BOLD));

(with_paint_context is the warpui_core-only helper; in a warp_tui test construct the paint context directly with TuiPaintContext::new(&mut rendered_views) as in the render_lines helper above.)

  • Cursor: call element.cursor_position(area, ctx) and assert on the returned Option<(u16, u16)>.
  • Events: build a TuiEvent (e.g. TuiEvent::KeyDown { keystroke, chars, details, is_composing } or TuiEvent::ScrollWheel { .. }), then call element.dispatch_event(&event, area, &mut event_ctx, &mut layout_ctx, app_ctx) and assert on the returned bool and on the re-rendered lines/cursor. Layout must run first. See render_element / dispatch_event / dispatch_scroll helpers in crates/warp_tui/src/transcript_view_tests.rs.

Keep test areas at a stable, small width/height so golden line vectors stay readable and deterministic; trailing padding is spaces (e.g. "hello ").

Where tests live

Follow the repo convention: put tests in a sibling *_tests.rs file included at the end of the source module:

#[cfg(test)]
#[path = "foo_tests.rs"]
mod tests;

Real examples to model:

  • Element library: crates/warpui_core/src/elements/tui/text_tests.rs, flex_tests.rs, container_tests.rs, constrained_box_tests.rs, buffer_tests.rs.
  • Views/screens: crates/warp_tui/src/transcript_view_tests.rs, crates/warp_tui/src/input/view_tests.rs.

Appearance in view tests

Views that resolve theme styles (via TuiUiBuilder::from_app) need an Appearance singleton. Install the mock in the test with app.add_singleton_model(|_| Appearance::mock()); (as in transcript_view_tests.rs). Appearance::mock() comes from warp_core's test-util feature, wired as a dev-dependency of the TUI crates.

Process-level tests (no integration harness)

The TUI has no GUI-style integration harness: the real-display, synthetic-event framework in crates/integration (see gui-integration-test) is GUI-only and does not drive the TUI. Besides render-to-lines unit tests, binary-level behavior is covered by a process-level test that spawns the built binary and asserts on its output/exit — see crates/warp_tui/tests/worker_dispatch.rs (it runs CARGO_BIN_EXE_warp-tui-oss and checks that a worker invocation dispatches without launching the TUI frontend). Use that pattern for process/CLI-level behavior, and render-to-lines unit tests for element/screen rendering. There is no separate TUI integration-test skill because there is no such framework today.

Running

  • Whole crates: cargo nextest run -p warp_tui and cargo nextest run -p warpui_core.
  • The TUI element library is behind the tui feature; if a test needs it explicitly, add --features tui.
  • A single test by substring: cargo nextest run -p warp_tui -E 'test(<substring>)'.
  • Before opening a PR, run ./script/format and cargo clippy per repo conventions.

Version History

  • 726c1b6 Current 2026-07-24 20:21

Same Skill Collection

.agents/skills/add-feature-flag/SKILL.md
.agents/skills/add-telemetry/SKILL.md
.agents/skills/changelog-draft/SKILL.md
.agents/skills/classify-changelog-pr/SKILL.md
.agents/skills/cross-platform-cloud-verification/SKILL.md
.agents/skills/dedupe-issue-local/SKILL.md
.agents/skills/gui-create-launch-modal/SKILL.md
.agents/skills/gui-integration-test/SKILL.md
.agents/skills/gui-reproduce-bug-report-local/SKILL.md
.agents/skills/gui-settings-ui/SKILL.md
.agents/skills/gui-ui-guidelines/SKILL.md
.agents/skills/logging-and-error-reporting/SKILL.md
.agents/skills/promote-feature/SKILL.md
.agents/skills/remove-feature-flag/SKILL.md
.agents/skills/review-pr-local/SKILL.md
.agents/skills/rust-unit-tests/SKILL.md
.agents/skills/triage-issue-local/SKILL.md
.agents/skills/tui-ui-guidelines/SKILL.md
.agents/skills/tui-verify-change/SKILL.md
resources/bundled/mcp_skills/figma/figma-code-connect-components/SKILL.md
resources/bundled/mcp_skills/figma/figma-create-design-system-rules/SKILL.md
resources/bundled/mcp_skills/figma/figma-create-new-file/SKILL.md
resources/bundled/mcp_skills/figma/figma-generate-library/SKILL.md
resources/bundled/mcp_skills/figma/figma-implement-design/SKILL.md
resources/bundled/skills/add-mcp-server/SKILL.md
resources/bundled/skills/change-keybinding/SKILL.md
resources/bundled/skills/create-skill/SKILL.md
resources/bundled/skills/create-tab-config/SKILL.md
resources/bundled/skills/factory-files/SKILL.md
resources/bundled/skills/factory-mcp/SKILL.md
resources/bundled/skills/modify-settings/SKILL.md
resources/bundled/skills/oz-platform/SKILL.md
resources/bundled/skills/pr-comments/SKILL.md
resources/bundled/skills/tab-configs/SKILL.md
resources/bundled/skills/tui-migrate-setup/SKILL.md
resources/bundled/skills/update-tab-config/SKILL.md
resources/bundled/skills/warpctrl/SKILL.md
resources/channel-gated-skills/dogfood/test-warp-ui/SKILL.md
resources/channel-gated-skills/dogfood/triage-vulnerabilities/SKILL.md
resources/channel-gated-skills/dogfood/verify-ui-change-in-cloud/SKILL.md
.agents/skills/gui-onboarding-verification-skill/SKILL.md
.warp/skills/gui-integration-test-video/SKILL.md
resources/bundled/mcp_skills/figma/edit-figma-design/SKILL.md
resources/bundled/mcp_skills/figma/figma-generate-design/SKILL.md
resources/bundled/mcp_skills/figma/figma-use/SKILL.md
resources/bundled/skills/claude-api/SKILL.md

Metadata

Files
0
Version
04a7f83
Hash
29dbc750
Indexed
2026-07-24 20:21

Главная - Вики-сайт
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-20 08:21
浙ICP备14020137号-1 $Гость$