#![allow(clippy::unwrap_used)]
use std::sync::Arc;
use chrono::Utc;
use crate::{
EventPayload, FunctionModule, ResourceLimits, RuntimeType,
host::{
dyn_context::DynHostContext,
live::{HostContextConfig, LiveHostContext},
},
runtime::deno::{DenoConfig, DenoRuntime},
};
const ECHO_TOKEN_TS: &str = r"
export default async () => ({ token: Deno.core.ops.fraiseql_idempotency_token() });
";
fn event() -> EventPayload {
EventPayload {
trigger_type: "after:mutation".to_string(),
entity: "Deal".to_string(),
event_kind: "updated".to_string(),
data: serde_json::json!({ "id": "deal-1" }),
timestamp: Utc::now(),
}
}
async fn run_echo(host: Arc<dyn DynHostContext>) -> serde_json::Value {
let module = FunctionModule::from_source(
"echo-token".to_string(),
ECHO_TOKEN_TS.to_string(),
RuntimeType::Deno,
);
let runtime = DenoRuntime::new(&DenoConfig::default()).unwrap();
runtime
.invoke_with_context(&module, event(), host, ResourceLimits::default())
.await
.expect("guest runs")
.value
.expect("returns a value")
}
#[tokio::test]
async fn token_is_exposed_to_the_guest() {
let token = "1a2b3c4d5e6f70818283848586878889";
let host: Arc<dyn DynHostContext> = Arc::new(
LiveHostContext::new(event(), HostContextConfig::default()).with_idempotency_token(token),
);
let value = run_echo(host).await;
assert_eq!(value["token"], token, "the guest reads the host-carried token verbatim");
}
#[tokio::test]
async fn absent_token_is_null_to_the_guest() {
let host: Arc<dyn DynHostContext> =
Arc::new(LiveHostContext::new(event(), HostContextConfig::default()));
let value = run_echo(host).await;
assert!(value["token"].is_null(), "no token set → null, got {:?}", value["token"]);
}