use codex_mobile_contracts::RuntimeStatusSnapshot;
use codex_mobile_wire::{PersistedEvent, ServerEnvelope, event_envelope};
use serde_json::json;
#[test]
fn hello_envelope_serializes_canonical_handshake_fields() {
let payload = serde_json::to_value(ServerEnvelope::Hello {
bridge_version: "0.3.13".to_string(),
protocol_version: 4,
runtime: Box::new(RuntimeStatusSnapshot {
runtime_id: "primary".to_string(),
status: "running".to_string(),
updated_at_ms: 1234,
..RuntimeStatusSnapshot::default()
}),
runtimes: Vec::new(),
directory_bookmarks: Vec::new(),
directory_history: Vec::new(),
pending_requests: Vec::new(),
})
.expect("hello envelope 应可序列化");
assert_eq!(payload["kind"], json!("hello"));
assert_eq!(payload["bridgeVersion"], json!("0.3.13"));
assert_eq!(payload["protocolVersion"], json!(4));
assert!(payload.get("bridge_version").is_none());
assert!(payload.get("protocol_version").is_none());
assert!(payload.get("directoryBookmarks").is_some());
assert!(payload.get("directoryHistory").is_some());
assert!(payload.get("directory_bookmarks").is_none());
assert!(payload.get("directory_history").is_none());
assert!(payload.get("pending_requests").is_some());
}
#[test]
fn event_envelope_keeps_existing_snake_case_fields() {
let payload = serde_json::to_value(event_envelope(PersistedEvent {
seq: 9,
event_type: "thread/updated".to_string(),
runtime_id: Some("primary".to_string()),
thread_id: Some("thread-9".to_string()),
payload: json!({ "threadId": "thread-9" }),
created_at_ms: 1234,
}))
.expect("event envelope 应可序列化");
assert_eq!(payload["kind"], json!("event"));
assert_eq!(payload["event_type"], json!("thread/updated"));
assert_eq!(payload["runtime_id"], json!("primary"));
assert_eq!(payload["thread_id"], json!("thread-9"));
assert!(payload.get("eventType").is_none());
assert!(payload.get("runtimeId").is_none());
assert!(payload.get("threadId").is_none());
}