diff --git a/crates/owlry-core/src/ipc.rs b/crates/owlry-core/src/ipc.rs new file mode 100644 index 0000000..0090ade --- /dev/null +++ b/crates/owlry-core/src/ipc.rs @@ -0,0 +1,66 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum Request { + Query { + text: String, + #[serde(skip_serializing_if = "Option::is_none")] + modes: Option>, + }, + Launch { + item_id: String, + provider: String, + }, + Providers, + Refresh { + provider: String, + }, + Toggle, + Submenu { + plugin_id: String, + data: String, + }, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum Response { + Results { + items: Vec, + }, + Providers { + list: Vec, + }, + SubmenuItems { + items: Vec, + }, + Ack, + Error { + message: String, + }, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ResultItem { + pub id: String, + pub title: String, + pub description: String, + pub icon: String, + pub provider: String, + pub score: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub command: Option, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub tags: Vec, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ProviderDesc { + pub id: String, + pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub prefix: Option, + pub icon: String, + pub position: String, +} diff --git a/crates/owlry-core/src/lib.rs b/crates/owlry-core/src/lib.rs index 7396113..dfedc76 100644 --- a/crates/owlry-core/src/lib.rs +++ b/crates/owlry-core/src/lib.rs @@ -1,6 +1,7 @@ pub mod config; pub mod data; pub mod filter; +pub mod ipc; pub mod notify; pub mod paths; pub mod plugins; diff --git a/crates/owlry-core/tests/ipc_test.rs b/crates/owlry-core/tests/ipc_test.rs new file mode 100644 index 0000000..79928bb --- /dev/null +++ b/crates/owlry-core/tests/ipc_test.rs @@ -0,0 +1,109 @@ +use owlry_core::ipc::{ProviderDesc, Request, Response, ResultItem}; + +#[test] +fn test_query_request_roundtrip() { + let req = Request::Query { + text: "fire".into(), + modes: Some(vec!["app".into(), "cmd".into()]), + }; + let json = serde_json::to_string(&req).unwrap(); + let parsed: Request = serde_json::from_str(&json).unwrap(); + assert_eq!(req, parsed); +} + +#[test] +fn test_query_request_without_modes() { + let req = Request::Query { + text: "fire".into(), + modes: None, + }; + let json = serde_json::to_string(&req).unwrap(); + assert!(!json.contains("modes")); + let parsed: Request = serde_json::from_str(&json).unwrap(); + assert_eq!(req, parsed); +} + +#[test] +fn test_launch_request_roundtrip() { + let req = Request::Launch { + item_id: "firefox.desktop".into(), + provider: "app".into(), + }; + let json = serde_json::to_string(&req).unwrap(); + let parsed: Request = serde_json::from_str(&json).unwrap(); + assert_eq!(req, parsed); +} + +#[test] +fn test_results_response_roundtrip() { + let resp = Response::Results { + items: vec![ResultItem { + id: "firefox.desktop".into(), + title: "Firefox".into(), + description: "Web Browser".into(), + icon: "firefox".into(), + provider: "app".into(), + score: 95, + command: Some("firefox".into()), + tags: vec![], + }], + }; + let json = serde_json::to_string(&resp).unwrap(); + let parsed: Response = serde_json::from_str(&json).unwrap(); + assert_eq!(resp, parsed); +} + +#[test] +fn test_providers_response() { + let resp = Response::Providers { + list: vec![ProviderDesc { + id: "app".into(), + name: "Applications".into(), + prefix: Some(":app".into()), + icon: "application-x-executable".into(), + position: "normal".into(), + }], + }; + let json = serde_json::to_string(&resp).unwrap(); + let parsed: Response = serde_json::from_str(&json).unwrap(); + assert_eq!(resp, parsed); +} + +#[test] +fn test_error_response() { + let resp = Response::Error { + message: "plugin not found".into(), + }; + let json = serde_json::to_string(&resp).unwrap(); + let parsed: Response = serde_json::from_str(&json).unwrap(); + assert_eq!(resp, parsed); +} + +#[test] +fn test_toggle_request() { + let req = Request::Toggle; + let json = serde_json::to_string(&req).unwrap(); + let parsed: Request = serde_json::from_str(&json).unwrap(); + assert_eq!(req, parsed); +} + +#[test] +fn test_submenu_request() { + let req = Request::Submenu { + plugin_id: "systemd".into(), + data: "docker.service".into(), + }; + let json = serde_json::to_string(&req).unwrap(); + let parsed: Request = serde_json::from_str(&json).unwrap(); + assert_eq!(req, parsed); +} + +#[test] +fn test_refresh_request() { + let req = Request::Refresh { + provider: "clipboard".into(), + }; + let json = serde_json::to_string(&req).unwrap(); + let parsed: Request = serde_json::from_str(&json).unwrap(); + assert_eq!(req, parsed); +}