use futures_util::{SinkExt, StreamExt};
use serde_json::json;
use tokio::net::TcpListener;
use tokio_tungstenite::accept_async;
use tokio_tungstenite::tungstenite::Message;
fn sample_event() -> serde_json::Value {
json!({
"id": 1,
"event_type": "violation",
"agent_id": "agent-abc",
"payload": {"detail": "blocked tool call"},
"timestamp": "2025-06-01T12:00:00Z"
})
}
#[tokio::test]
async fn client_receives_event_from_mock_ws_server() {
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
let (stream, _) = listener.accept().await.unwrap();
let mut ws = accept_async(stream).await.unwrap();
let event_json = serde_json::to_string(&sample_event()).unwrap();
ws.send(Message::Text(event_json.into())).await.unwrap();
ws.close(None).await.ok();
});
let url = format!("ws://127.0.0.1:{}", addr.port());
let (mut ws_stream, _) = tokio_tungstenite::connect_async(&url)
.await
.expect("client should connect to mock server");
let msg = ws_stream
.next()
.await
.expect("should receive a message")
.expect("message should be Ok");
match msg {
Message::Text(text) => {
let event: serde_json::Value = serde_json::from_str(&text).unwrap();
assert_eq!(event["id"], 1);
assert_eq!(event["event_type"], "violation");
assert_eq!(event["agent_id"], "agent-abc");
}
other => panic!("expected Text frame, got {other:?}"),
}
server.await.unwrap();
}
#[tokio::test]
async fn client_handles_server_close() {
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let server = tokio::spawn(async move {
let (stream, _) = listener.accept().await.unwrap();
let mut ws = accept_async(stream).await.unwrap();
ws.close(None).await.ok();
});
let url = format!("ws://127.0.0.1:{}", addr.port());
let (mut ws_stream, _) = tokio_tungstenite::connect_async(&url)
.await
.expect("client should connect");
let msg = ws_stream.next().await;
match msg {
Some(Ok(Message::Close(_))) | None => { }
other => panic!("expected Close or end of stream, got {other:?}"),
}
server.await.unwrap();
}