#![cfg(feature = "agui")]
use embacle::agui::{AgUiEmitter, AgUiEvent, AgUiEventFilter, AgUiEventKind, NoopEmitter};
#[test]
fn event_serializes_with_spec_tag() {
let event = AgUiEvent::run_started("run_1", Some("thread_1"));
let Ok(json) = serde_json::to_value(&event) else {
panic!("AG-UI event must serialize to JSON without error");
};
assert_eq!(json["type"], "RUN_STARTED");
assert_eq!(json["run_id"], "run_1");
assert_eq!(json["thread_id"], "thread_1");
assert!(json["timestamp"].is_u64());
}
#[test]
fn step_events_round_trip_via_json() {
let event = AgUiEvent::step_started("run_1", "tool_loop");
let Ok(json) = serde_json::to_string(&event) else {
panic!("AG-UI event must serialize to JSON without error");
};
let Ok(decoded) = serde_json::from_str::<AgUiEvent>(&json) else {
panic!("AG-UI event must deserialize from its own JSON");
};
assert!(matches!(decoded.kind(), AgUiEventKind::StepStarted));
assert_eq!(decoded.run_id(), "run_1");
}
#[test]
fn filter_without_removes_kind() {
let filter = AgUiEventFilter::allow_all().without(AgUiEventKind::TextMessageContent);
assert!(filter.allows(AgUiEventKind::RunStarted));
assert!(!filter.allows(AgUiEventKind::TextMessageContent));
}
#[test]
fn filter_only_is_exclusive() {
let filter = AgUiEventFilter::only([AgUiEventKind::RunStarted, AgUiEventKind::RunFinished]);
assert!(filter.allows(AgUiEventKind::RunStarted));
assert!(!filter.allows(AgUiEventKind::StepStarted));
}
#[tokio::test]
async fn noop_emitter_swallows_events() {
let sink = NoopEmitter::default();
sink.emit(&AgUiEvent::run_started("run_1", None)).await;
}
#[test]
fn unknown_type_deserializes_to_unknown_variant() {
let raw = r#"{"type":"FUTURE_EVENT_NOT_YET_DEFINED","run_id":"run_1","timestamp":1}"#;
let decoded: AgUiEvent = serde_json::from_str(raw).expect("unknown type must decode");
assert!(matches!(decoded, AgUiEvent::Unknown));
assert_eq!(decoded.kind(), AgUiEventKind::Unknown);
assert_eq!(decoded.run_id(), "");
}
#[test]
fn default_filter_permits_every_declared_kind() {
let filter = AgUiEventFilter::default();
for kind in AgUiEventKind::ALL {
assert!(
filter.allows(kind),
"default filter must allow {kind:?} — either add it to allow_all or explicitly exclude"
);
}
}