//! WebSocket framing tests (Phase 4). //! //! We don't stand up a real WS server in-process — that's Phase 8 perf //! work. For now we cover the offline pieces: //! - `StreamEnvelope` JSON parses (one frame in = one envelope out) //! - The URL helpers (https:// → wss://, host extraction) behave the way //! the inline `connect` path expects. use windows_gotify_client_rust::gotify::websocket::StreamEnvelope; use windows_gotify_client_rust::gotify::model::GotifyMessage; #[test] fn envelope_parses_minimal_text_frame() { let json = r#"{"id":99,"appid":2,"message":"hello","title":"","priority":1,"date":"2026-09-19T04:00:00Z"}"#; let env: StreamEnvelope = serde_json::from_str(json).unwrap(); assert_eq!(env.id, Some(99)); assert_eq!(env.message, "hello"); } #[test] fn envelope_tolerates_unknown_fields() { // Gotify may grow the schema over time. Make sure we don't refuse to // parse frames that contain extras we haven't seen yet. let json = r#"{ "id": 1, "appid": 1, "message": "x", "title": "", "priority": 0, "date": "2026-09-19T00:00:00Z", "extras": { "client::display": { "contentType": "text/markdown" } } }"#; let env: StreamEnvelope = serde_json::from_str(json).unwrap(); assert_eq!(env.id, Some(1)); } #[test] fn gotify_message_parses_what_websocket_sends() { // Sanity check: what the WebSocket loop hands to the on_message // callback is the same shape as the /message REST endpoint, so the // existing models.rs adapter works for both paths. let json = r#"{"id":42,"appid":3,"message":"build OK","title":"ci","priority":3,"date":"2026-09-19T05:00:00Z"}"#; let msg: GotifyMessage = serde_json::from_str(json).unwrap(); assert_eq!(msg.id, 42); assert_eq!(msg.title, "ci"); assert_eq!(msg.priority, 3); }