Skip to content

Commit 514c984

Browse files
committed
Refactor SwitchNode and related tests for improved clarity and organization
1 parent 181e693 commit 514c984

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

crates/core/src/runtime/eval.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,16 @@ pub async fn evaluate_node_property_value(
153153
_ => Variant::Number(utils::time::unix_now().into()),
154154
},
155155

156+
// Node-RED: vt: "msg", v: null/undefined → treat as null
157+
(RedPropertyType::Msg, RedPropertyValue::Constant(Variant::Null)) => Variant::Null,
158+
159+
// Node-RED: vt: "msg", v: "" → treat as null
160+
(RedPropertyType::Msg, RedPropertyValue::Runtime(ref prop)) if prop.is_empty() => Variant::Null,
161+
156162
(RedPropertyType::Msg, RedPropertyValue::Constant(Variant::String(ref prop)))
157163
| (RedPropertyType::Msg, RedPropertyValue::Runtime(ref prop)) => {
158164
if let Some(msg) = msg {
159-
if let Some(pv) = msg.get_nav_stripped(prop.as_str()) {
160-
pv.clone()
161-
} else {
162-
return Err(EdgelinkError::BadArgument("value"))
163-
.with_context(|| format!("Cannot get the property(s) from `msg`: {}", prop.as_str()));
164-
}
165+
if let Some(pv) = msg.get_nav_stripped(prop.as_str()) { pv.clone() } else { Variant::Null }
165166
} else {
166167
return Err(EdgelinkError::BadArgument("msg")).with_context(|| "`msg` is required".to_owned());
167168
}

crates/core/src/runtime/nodes/function_nodes/switch/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ impl SwitchRuleOperator {
162162
}
163163
_ => Ok(false),
164164
},
165-
Self::IsTrue => Ok(a.as_bool().unwrap_or(false)),
166-
Self::IsFalse => Ok(a.as_bool().unwrap_or(false)),
165+
Self::IsTrue => Ok(a.as_bool() == Some(true)),
166+
Self::IsFalse => Ok(a.as_bool() == Some(false)),
167167
Self::IsNull => Ok(a.is_null()),
168168
Self::IsNotNull => Ok(!a.is_null()),
169169
Self::IsEmpty => match a {

crates/core/src/runtime/nodes/function_nodes/switch/tests.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fn test_raw_switch_rule_basic() {
100100
assert_eq!(rule.operator, SwitchRuleOperator::Equal);
101101
assert_eq!(rule.value, Some(Variant::String("Hello".to_string())));
102102
assert_eq!(rule.value_type, Some(SwitchPropertyType::Str));
103-
assert_eq!(rule.value2, None);
103+
assert_eq!(rule.value2, Variant::Null);
104104
assert_eq!(rule.value2_type, None);
105105
assert!(!rule.regex_case);
106106
}
@@ -120,7 +120,7 @@ fn test_raw_switch_rule_between() {
120120
assert_eq!(rule.operator, SwitchRuleOperator::Between);
121121
assert_eq!(rule.value, Some(Variant::Number(serde_json::Number::from(3))));
122122
assert_eq!(rule.value_type, Some(SwitchPropertyType::Num));
123-
assert_eq!(rule.value2, Some(Variant::Number(serde_json::Number::from(5))));
123+
assert_eq!(rule.value2, Variant::Number(serde_json::Number::from(5)));
124124
assert_eq!(rule.value2_type, Some(SwitchPropertyType::Num));
125125
}
126126

@@ -378,7 +378,7 @@ fn test_switch_node_evaluate_rules_between_with_prev() {
378378
assert_eq!(rules[0].operator, SwitchRuleOperator::Between);
379379
assert_eq!(rules[0].value_type, SwitchPropertyType::Num);
380380
assert_eq!(rules[0].value2_type, Some(SwitchPropertyType::Prev));
381-
assert_eq!(rules[0].value2, Some(RedPropertyValue::null()));
381+
assert_eq!(rules[0].value2, RedPropertyValue::null());
382382
}
383383

384384
#[test]
@@ -508,7 +508,7 @@ fn test_raw_switch_rule_minimal() {
508508
assert_eq!(rule.operator, SwitchRuleOperator::IsNull);
509509
assert_eq!(rule.value, None);
510510
assert_eq!(rule.value_type, None);
511-
assert_eq!(rule.value2, None);
511+
assert_eq!(rule.value2, Variant::Null);
512512
assert_eq!(rule.value2_type, None);
513513
assert!(!rule.regex_case);
514514
}
@@ -622,3 +622,23 @@ async fn test_it_should_check_input_against_a_previous_value_2nd_option() {
622622
assert_eq!(msgs[0]["payload"], 20.into());
623623
assert_eq!(msgs[1]["payload"], 25.into());
624624
}
625+
626+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
627+
async fn test_should_check_if_input_is_indeed_false() {
628+
let flows_json = json!([
629+
{"id": "100", "type": "tab"},
630+
{"id": "1", "z": "100", "type": "switch", "name": "switchNode", "property": "payload",
631+
"rules": [{"t": false}], "checkall": true, "outputs": 1, "wires": [["2"]]},
632+
{"id": "2", "z": "100", "type": "test-once"}
633+
]);
634+
let msgs_to_inject_json = json!([
635+
["1", {"payload": false}],
636+
]);
637+
638+
let engine = crate::runtime::engine::build_test_engine(flows_json).unwrap();
639+
let msgs_to_inject = Vec::<(ElementId, Msg)>::deserialize(msgs_to_inject_json).unwrap();
640+
let msgs = engine.run_once_with_inject(1, std::time::Duration::from_secs_f64(0.5), msgs_to_inject).await.unwrap();
641+
642+
assert_eq!(msgs.len(), 1);
643+
assert_eq!(msgs[0]["payload"], false.into());
644+
}

0 commit comments

Comments
 (0)