use serde_json::Value;
pub(crate) const CARD_NAV_META_KEYS: &[&str] = &["routeToCardId", "toCardId", "nextCardId"];
fn card_nav_target(metadata: &Value) -> Option<&str> {
CARD_NAV_META_KEYS
.iter()
.find_map(|key| metadata.get(*key).and_then(Value::as_str))
.map(str::trim)
.filter(|target| !target.is_empty())
}
pub(crate) fn entry_node_from_card_nav(
metadata: &Value,
flow_node_ids: &[String],
) -> Option<String> {
let target = card_nav_target(metadata)?;
flow_node_ids
.iter()
.any(|node| node == target)
.then(|| target.to_string())
}
pub(crate) fn strip_card_nav_keys(metadata: &mut Value) {
let Some(map) = metadata.as_object_mut() else {
return;
};
for key in CARD_NAV_META_KEYS {
map.remove(*key);
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
fn nodes() -> Vec<String> {
["welcome", "cap_company_name", "quote_result"]
.iter()
.map(|s| s.to_string())
.collect()
}
#[test]
fn a_target_naming_a_flow_node_becomes_the_entry_node() {
let meta = json!({ "nextCardId": "cap_company_name" });
assert_eq!(
entry_node_from_card_nav(&meta, &nodes()),
Some("cap_company_name".to_string())
);
}
#[test]
fn a_target_naming_a_card_is_left_alone() {
let meta = json!({ "nextCardId": "quote_page2" });
assert_eq!(entry_node_from_card_nav(&meta, &nodes()), None);
}
#[test]
fn every_nav_key_is_recognised() {
for key in CARD_NAV_META_KEYS {
let meta = json!({ *key: "quote_result" });
assert_eq!(
entry_node_from_card_nav(&meta, &nodes()),
Some("quote_result".to_string()),
"key {key} was not recognised"
);
}
}
#[test]
fn an_absent_or_blank_target_yields_nothing() {
assert_eq!(entry_node_from_card_nav(&json!({}), &nodes()), None);
assert_eq!(
entry_node_from_card_nav(&json!({ "nextCardId": " " }), &nodes()),
None
);
}
#[test]
fn stripping_removes_every_nav_key() {
let mut meta = json!({
"nextCardId": "cap_company_name",
"toCardId": "cap_company_name",
"routeToCardId": "cap_company_name",
"keep_me": "yes"
});
strip_card_nav_keys(&mut meta);
for key in CARD_NAV_META_KEYS {
assert!(meta.get(*key).is_none(), "{key} survived stripping");
}
assert_eq!(meta.get("keep_me").and_then(|v| v.as_str()), Some("yes"));
}
}