use serde::Serialize;
use crate::error::Error;
use crate::exec::exec;
#[derive(Serialize)]
struct DispatchArgs<'a, Detail: Serialize + ?Sized> {
event: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
to: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
detail: Option<&'a Detail>,
bubbles: bool,
}
pub fn dispatch(event: &str, to: Option<&str>) -> Result<(), Error> {
exec(
"dispatch",
&DispatchArgs::<()> {
event,
to,
detail: None,
bubbles: true,
},
)
}
pub fn dispatch_with<Detail>(
event: &str,
to: Option<&str>,
detail: &Detail,
) -> Result<(), Error>
where
Detail: Serialize + ?Sized,
{
exec(
"dispatch",
&DispatchArgs {
event,
to,
detail: Some(detail),
bubbles: true,
},
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::exec::encode_command;
use serde_json::Value;
#[test]
fn without_detail_omits_detail_key() {
let args = DispatchArgs::<()> {
event: "wasm:tick",
to: Some("#board"),
detail: None,
bubbles: true,
};
let parsed: Value =
serde_json::from_str(&encode_command("dispatch", &args).unwrap()).unwrap();
assert_eq!(parsed[0][0], "dispatch");
assert_eq!(parsed[0][1]["event"], "wasm:tick");
assert_eq!(parsed[0][1]["to"], "#board");
assert_eq!(parsed[0][1]["bubbles"], true);
assert!(parsed[0][1].get("detail").is_none());
}
#[test]
fn with_detail_serializes_payload() {
let payload = serde_json::json!({ "delta": 5 });
let args = DispatchArgs {
event: "wasm:score",
to: None,
detail: Some(&payload),
bubbles: true,
};
let parsed: Value =
serde_json::from_str(&encode_command("dispatch", &args).unwrap()).unwrap();
assert_eq!(parsed[0][1]["detail"]["delta"], 5);
assert!(parsed[0][1].get("to").is_none());
}
#[test]
fn non_wasm_stubs_to_ok() {
assert!(dispatch("wasm:noop", None).is_ok());
}
}