use playwright_rs::protocol::{parse_result, serialize_argument};
use proptest::prelude::*;
use serde_json::{Value, json};
const JS_MAX_SAFE_INTEGER: i64 = 9_007_199_254_740_991;
fn arb_json() -> impl Strategy<Value = Value> {
let leaf = prop_oneof![
Just(Value::Null),
any::<bool>().prop_map(Value::from),
(-JS_MAX_SAFE_INTEGER..=JS_MAX_SAFE_INTEGER).prop_map(Value::from),
any::<f64>()
.prop_filter(
"non-finite floats cannot exist in a serde_json::Value",
|f| f.is_finite()
)
.prop_map(Value::from),
"[a-z0-9 ]{0,8}".prop_map(Value::from),
];
leaf.prop_recursive(3, 12, 3, |inner| {
prop_oneof![
proptest::collection::vec(inner.clone(), 0..3).prop_map(Value::from),
proptest::collection::hash_map("[a-z]{1,4}", inner, 0..3)
.prop_map(|m| Value::Object(m.into_iter().collect())),
]
})
}
fn js_number_normal_form(value: &Value) -> Value {
match value {
Value::Number(n) => n
.as_f64()
.and_then(serde_json::Number::from_f64)
.map(Value::Number)
.unwrap_or(Value::Null),
Value::Array(items) => Value::Array(items.iter().map(js_number_normal_form).collect()),
Value::Object(map) => Value::Object(
map.iter()
.map(|(k, v)| (k.clone(), js_number_normal_form(v)))
.collect(),
),
other => other.clone(),
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(256))]
#[test]
fn evaluate_conversion_round_trips(value in arb_json()) {
let wire = serialize_argument(&value);
let back = parse_result(&wire["value"]);
prop_assert_eq!(js_number_normal_form(&back), js_number_normal_form(&value));
}
}
#[test]
fn the_non_finite_float_exclusion_is_current() {
assert_eq!(
serde_json::to_value(f64::INFINITY).unwrap(),
Value::Null,
"non-finite floats still cannot reach the serializer through a Value"
);
assert!(serde_json::Number::from_f64(f64::NAN).is_none());
}
#[test]
fn integers_beyond_the_js_safe_range_are_rounded() {
let beyond = JS_MAX_SAFE_INTEGER + 2;
let round_tripped = parse_result(&serialize_argument(&json!(beyond))["value"]);
assert_eq!(
round_tripped.as_f64(),
Some(9_007_199_254_740_992.0),
"an integer past 2^53-1 is still rounded rather than sent as a BigInt"
);
}