use crate::core::{Expr, JSObjectDataPtr, Value};
use crate::core::{evaluate_expr, evaluate_statements, new_js_object_data, obj_set_key_value, prepare_function_call_env};
use crate::error::JSError;
pub fn handle_assert_method(method: &str, args: &[Expr], env: &JSObjectDataPtr) -> Result<Value, JSError> {
match method {
"sameValue" => {
if args.len() < 2 || args.len() > 3 {
return Err(raise_eval_error!("assert.sameValue requires 2 or 3 arguments"));
}
let actual = evaluate_expr(env, &args[0])?;
let expected = evaluate_expr(env, &args[1])?;
let message = if args.len() == 3 {
let message_val = evaluate_expr(env, &args[2])?;
match message_val {
Value::String(s) => String::from_utf16_lossy(&s),
_ => "assert.sameValue failed".to_string(),
}
} else {
"assert.sameValue failed".to_string()
};
let equal = match (&actual, &expected) {
(Value::Number(a), Value::Number(b)) => a == b,
(Value::String(a), Value::String(b)) => a == b,
(Value::Boolean(a), Value::Boolean(b)) => a == b,
(Value::Undefined, Value::Undefined) => true,
_ => false, };
if !equal {
return Err(raise_eval_error!(format!("{message}: expected {expected:?}, got {actual:?}")));
}
Ok(Value::Undefined)
}
"notSameValue" => {
if args.len() < 2 || args.len() > 3 {
return Err(raise_eval_error!("assert.notSameValue requires 2 or 3 arguments"));
}
let actual = evaluate_expr(env, &args[0])?;
let expected = evaluate_expr(env, &args[1])?;
let message = if args.len() == 3 {
let message_val = evaluate_expr(env, &args[2])?;
match message_val {
Value::String(s) => String::from_utf16_lossy(&s),
_ => "assert.notSameValue failed".to_string(),
}
} else {
"assert.notSameValue failed".to_string()
};
let equal = match (&actual, &expected) {
(Value::Number(a), Value::Number(b)) => a == b,
(Value::String(a), Value::String(b)) => a == b,
(Value::Boolean(a), Value::Boolean(b)) => a == b,
(Value::Undefined, Value::Undefined) => true,
_ => false,
};
if equal {
let err_obj = new_js_object_data();
obj_set_key_value(&err_obj, &"message".into(), Value::String(message.encode_utf16().collect()))?;
return Err(raise_throw_error!(Value::Object(err_obj)));
}
Ok(Value::Undefined)
}
"throws" => {
if args.len() < 2 || args.len() > 3 {
return Err(raise_eval_error!("assert.throws requires 2 or 3 arguments"));
}
let func_val = evaluate_expr(env, &args[1])?;
match func_val {
Value::Closure(data) => {
let body = &data.body;
let captured_env = &data.env;
let func_env = prepare_function_call_env(Some(captured_env), None, None, &[], None, None)?;
match evaluate_statements(&func_env, body) {
Ok(_) => Err(raise_eval_error!("assert.throws expected function to throw a value")),
Err(_) => Ok(Value::Undefined),
}
}
_ => Err(raise_eval_error!("assert.throws requires a function as the 2nd argument")),
}
}
_ => Err(raise_eval_error!(format!("Assert method {method} not implemented"))),
}
}