No description
- Rust 97.9%
- Just 2.1%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| examples | ||
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| justfile | ||
| README.md | ||
| rust-toolchain.toml | ||
| ws-rpc-test.md | ||
ws-rpc-test
End-to-end testing framework for applications that expose a JSON-RPC 2.0 API over WebSocket.
Think Puppeteer, but for backend APIs: start a process, connect via WebSocket, send commands, wait for events, assert results.
Motivation
Modern desktop and server applications increasingly expose control APIs over WebSocket for remote management, AI agent integration, and automation. Testing these APIs end-to-end requires:
- starting the application process
- waiting for it to become healthy
- connecting a WebSocket client
- sending JSON-RPC requests and validating responses
- subscribing to events and waiting for specific notifications
- handling timeouts, retries, and cleanup
This is repetitive plumbing. ws-rpc-test provides it as a reusable framework so application developers write only test logic.
Quickstart
use std::time::Duration;
use ws_rpc_test::{assert_field_exists, assert_ok, prelude::*};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let harness = ProcessHarness::builder()
.command("target/debug/my-app")
.health_url("http://127.0.0.1:8080/health")
.ws_url("ws://127.0.0.1:8080/ws")
.build();
let mut runner = TestRunner::new(harness);
runner.parse_cli_args(); // reads --filter, --fail-fast, etc.
runner.test("health check", |c| async move {
let r = c.call("health_check", json!({})).await?;
assert_ok!(r);
Ok(())
});
runner.test("create item", |c| async move {
let r = c.call("create_item", json!({"name": "test"})).await?;
assert_field_exists!(r, "id");
Ok(())
});
let report = runner.run().await?;
std::process::exit(if report.failed > 0 { 1 } else { 0 });
}
Features
- Process harness — spawn, health-poll, SIGTERM-then-SIGKILL shutdown, stdout/stderr capture, auto-forward
DISPLAY/XDG_RUNTIME_DIRfor GUI apps - WebSocket JSON-RPC client —
call,call_timeout,subscribe,wait_for,wait_for_any,collect_events,call_and_wait(race-free) - Assertion macros —
assert_ok!,assert_field!,assert_field_exists!,assert_array!,assert_error!, and more - Test runner —
before_all/before_each/after_each/after_allhooks, name / tag filtering, declarativeskip_if, runtimeSkip, fail-fast, optional parallel mode with isolated connections - Reporters — console (colour, real-time, TTY-aware), JSON, JUnit XML
- CLI — clap-based
parse_cli_args()one-liner, gated behind the default-onclifeature
Examples
examples/basic.rs— minimal 5-test suite mirroring spec §9examples/loom_e2e.rs— illustrative consumer example mirroring spec §10 (GUI, generation flow, gallery / workflow / preset)
Build them with:
cargo build --examples
cargo run --example basic -- --binary target/debug/my-app
Status
v0.1.0 milestone in progress. See the milestone on forge.jacquin.app for the remaining stories.
License
MIT OR Apache-2.0