Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[workspace]
members = [
"bindings/go/native",
"bindings/js",
"bindings/python/native",
"crates/tui-test",
Expand Down
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# tui-test

`tui-test` controls, inspects, tests, and records real shell sessions and full-screen terminal apps on Windows, Linux, and macOS. Use it from the CLI or call the same engine from Rust, Python, or JavaScript. It works for AI agents that need structured access to terminal state, terminal automation, and terminal ui application testing.
`tui-test` controls, inspects, tests, and records real shell sessions and full-screen terminal apps on Windows, Linux, and macOS. Use it from the CLI or call the same engine from Rust, Python, JavaScript, or Go. It works for AI agents that need structured access to terminal state, terminal automation, and terminal ui application testing.

<p align="center">
<a href="#installation">Installation</a>
Expand Down Expand Up @@ -48,12 +48,13 @@ You can also download a binary from [GitHub Releases](https://github.com/microso
| Rust 1.90+ | `cargo add tui-test-rs@0.1.0` | [docs.rs](https://docs.rs/tui-test-rs/latest/tui_test/) |
| Python 3.8+ | `pip install tui-test` | [Python API](bindings/python/README.md) |
| Node 20+ | `npm install @microsoft/tui-test` | [JavaScript API](bindings/js/README.md) |
| Go 1.26+ | Source build required; [installation steps](bindings/go/README.md#install) | [Go API](bindings/go/README.md) |

Add the Rust `recording-raster` feature for APNG, GIF, and MP4 output. It uses installed fonts; `recording-font-jetbrains-mono*` bundles a font.

## Quick start

The CLI and libraries expose the same terminal actions. Python, JavaScript, and Rust sessions run in-process and do not require the CLI.
The CLI and libraries expose the same terminal actions. Python, JavaScript, Rust, and Go sessions run in-process and do not require the CLI. See [Go installation](bindings/go/README.md#install) for the Go binding's native build requirement.

### CLI

Expand Down Expand Up @@ -122,6 +123,35 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

[Rust API reference](https://docs.rs/tui-test-rs/latest/tui_test/)

### Go

```go
package main

import (
"log"

"github.com/microsoft/tui-test/bindings/go"
)

func main() {
terminal, err := tuitest.Ephemeral("example", tuitest.ClientOptions{})
if err != nil {
log.Fatal(err)
}
defer terminal.CloseQuiet()

if _, err := terminal.Run("my-app", nil, tuitest.SpawnOptions{}); err != nil {
log.Fatal(err)
}
if err := terminal.GetByText("Ready", tuitest.TextSelectorOptions{}).Expect(tuitest.LocatorExpectOptions{}); err != nil {
log.Fatal(err)
}
}
```

[Go installation and API reference](bindings/go/README.md)

## API references

| Surface | Reference |
Expand All @@ -130,6 +160,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
| Rust | [docs.rs](https://docs.rs/tui-test-rs/latest/tui_test/) |
| Python | [bindings/python/README.md](bindings/python/README.md) |
| JavaScript | [bindings/js/README.md](bindings/js/README.md) |
| Go | [bindings/go/README.md](bindings/go/README.md) |

## CLI reference

Expand Down
81 changes: 81 additions & 0 deletions bindings/go/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Building and maintaining the Go binding

The [Go README](README.md) covers installation and application usage. This guide covers native builds and validation.

## Architecture

The public `tuitest` package at the module root owns clients, options, results, immutable locator queries, input helpers, lifecycle validation, and the typed error surface. Its `engine.go` adapter converts between public types and the internal native types.

The `internal/native` package owns the C ABI, purego calls, native memory lifetimes, and library loading. It copies results into Go-owned values before releasing Rust allocations. Dependencies run from the public package into `internal/native`; the native package does not import the public package.

The Rust adapter source stays in `native/` and delegates to the existing `tui-test` session registry and operations. Source builds load that adapter from the path in `TUI_TEST_GO_NATIVE_LIBRARY` and keep it loaded for the process lifetime.

Terminal behavior, session synchronization, locator evaluation, assertions, diagnostics, traces, artifacts, and recording remain in the Rust engine. Go owns option ergonomics, query construction, error presentation, and test cleanup. The `tuitesttest` package reports the test result through failure-aware close so the engine can retain on-failure traces. Keep new terminal behavior in the engine so language bindings share it.

The native library and Go module must come from the same source revision. The C ABI is private to this binding. Native allocations must be released by their matching Rust functions, and native code must not retain Go pointers.

## Build from source

Install Go 1.26 or newer, Rust 1.90 or newer, and Zig 0.16.0. Linux needs a native C/C++ compiler and linker, macOS needs Apple command-line build tools, and Windows amd64 needs the MSVC Build Tools and `x86_64-pc-windows-msvc` Rust toolchain. The [installation guide](README.md#install) lists the supported host OS and architecture combinations.

From the repository root:

```sh
cargo build --locked -p tui-test-go
```

The native adapter enables the same terminal backends and recording features as the JavaScript and Python bindings. Zig is required by the Ghostty dependency.

Set `TUI_TEST_GO_NATIVE_LIBRARY` to the built library before running a Go application or test. For Linux:

```sh
cd bindings/go
TUI_TEST_GO_NATIVE_LIBRARY=../../target/debug/libtui_test_go.so CGO_ENABLED=0 go test ./...
```

On macOS, run from `bindings/go`:

```sh
TUI_TEST_GO_NATIVE_LIBRARY=../../target/debug/libtui_test_go.dylib CGO_ENABLED=0 go test ./...
```

On Windows amd64, run from the repository root:

```powershell
Set-Location bindings/go
$env:TUI_TEST_GO_NATIVE_LIBRARY = (Resolve-Path ../../target/debug/tui_test_go.dll)
$env:CGO_ENABLED = '0'
go test ./...
```

For a release build, use `cargo build --release --locked -p tui-test-go` and point the environment variable at the library under `target/release`.

To consume unpublished changes from another Go module, build the library as above, then add a local module replacement in the consuming project:

```sh
go mod edit -replace github.com/microsoft/tui-test/bindings/go=/absolute/path/to/tui-test/bindings/go
go get github.com/microsoft/tui-test/bindings/go
```

## Validate changes

After setting `TUI_TEST_GO_NATIVE_LIBRARY`, run these commands from `bindings/go`:

```sh
gofmt -l .
go vet ./...
go test ./...
```

`gofmt -l .` should produce no output. Also run `go test -race ./...` with cgo enabled and a C compiler available for Go's race detector; the binding itself does not require cgo.

From the repository root, also run the Rust checks:

```sh
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo clippy -p tui-test-rs --all-targets --no-default-features -- -D warnings
cargo test --workspace -- --test-threads=1
```

`TestCloseInterruptsPendingWait` is explicitly skipped for the accepted shared-runtime limitation in [issue #207](https://github.com/microsoft/tui-test/issues/207). Its regression body remains in place. Remove the skip and run the test when the upstream fix is incorporated. The `CloseAll` interruption test remains active.
Loading
Loading