mod helpers;
use freshblu_core::{
device::RegisterParams,
forwarder::{ForwarderEntry, ForwarderPair, Forwarders, MeshbluForwarder, WebhookForwarder},
};
use serde_json::json;
use wiremock::{
matchers::{header_exists, method, path},
Mock, MockServer, ResponseTemplate,
};
use helpers::*;
#[test]
fn forwarder_config_serde_roundtrip() {
let fwd = Forwarders {
message: ForwarderPair {
sent: vec![
ForwarderEntry::Webhook(WebhookForwarder {
url: "https://example.com/hook".to_string(),
method: "POST".to_string(),
sign_request: false,
generate_and_forward_meshblu_credentials: false,
}),
ForwarderEntry::Meshblu(MeshbluForwarder {}),
],
received: vec![],
},
broadcast: ForwarderPair {
sent: vec![ForwarderEntry::Webhook(WebhookForwarder {
url: "https://example.com/broadcast".to_string(),
method: "PUT".to_string(),
sign_request: true,
generate_and_forward_meshblu_credentials: true,
})],
received: vec![],
},
..Default::default()
};
let json = serde_json::to_value(&fwd).unwrap();
let back: Forwarders = serde_json::from_value(json).unwrap();
assert_eq!(back, fwd);
}
#[tokio::test]
async fn webhook_fires_on_execute() {
let mock_server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/hook"))
.and(header_exists("x-meshblu-uuid"))
.respond_with(ResponseTemplate::new(200))
.expect(1)
.mount(&mock_server)
.await;
let (_, state) = setup().await;
let (uuid, _) = register_device(&state).await;
let uuid_parsed: uuid::Uuid = uuid.parse().unwrap();
let mut device = state.store.get_device(&uuid_parsed).await.unwrap().unwrap();
device.meshblu.forwarders = Some(Forwarders {
message: ForwarderPair {
sent: vec![ForwarderEntry::Webhook(WebhookForwarder {
url: format!("{}/hook", mock_server.uri()),
method: "POST".to_string(),
sign_request: false,
generate_and_forward_meshblu_credentials: false,
})],
received: vec![],
},
..Default::default()
});
let payload = json!({ "test": "webhook_fire" });
state
.webhook_executor
.execute(
&device,
freshblu_core::forwarder::ForwarderEvent::MessageSent,
&payload,
&[],
)
.await;
}
#[tokio::test]
async fn meshblu_forwarder_reemits_as_message() {
let (_, state) = setup().await;
let (uuid, _token) = register_device(&state).await;
let entry = ForwarderEntry::Meshblu(MeshbluForwarder {});
let json = serde_json::to_value(&entry).unwrap();
assert_eq!(json["type"], "meshblu");
}
#[tokio::test]
async fn meshblu_forwarder_detects_loop() {
let (_, state) = setup().await;
let (uuid, _) = register_device(&state).await;
let uuid_parsed: uuid::Uuid = uuid.parse().unwrap();
let device = state.store.get_device(&uuid_parsed).await.unwrap().unwrap();
let payload = json!({ "test": true });
state
.webhook_executor
.execute(&device, freshblu_core::forwarder::ForwarderEvent::MessageSent, &payload, &[uuid_parsed])
.await;
}
#[tokio::test]
async fn webhook_with_credentials_generates_token() {
let mock_server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/authed-hook"))
.and(header_exists("authorization"))
.respond_with(ResponseTemplate::new(200))
.expect(1)
.mount(&mock_server)
.await;
let (_, state) = setup().await;
let (uuid, _) = register_device(&state).await;
let uuid_parsed: uuid::Uuid = uuid.parse().unwrap();
let tokens_before = state.store.list_tokens(&uuid_parsed).await.unwrap().len();
let wh = WebhookForwarder {
url: format!("{}/authed-hook", mock_server.uri()),
method: "POST".to_string(),
sign_request: false,
generate_and_forward_meshblu_credentials: true,
};
let mut device = state.store.get_device(&uuid_parsed).await.unwrap().unwrap();
device.meshblu.forwarders = Some(Forwarders {
message: ForwarderPair {
sent: vec![ForwarderEntry::Webhook(wh)],
received: vec![],
},
..Default::default()
});
let payload = json!({ "test": "credential" });
state
.webhook_executor
.execute(
&device,
freshblu_core::forwarder::ForwarderEvent::MessageSent,
&payload,
&[],
)
.await;
let tokens_after = state.store.list_tokens(&uuid_parsed).await.unwrap().len();
assert!(tokens_after > tokens_before);
}