use crate::builtin::derive_partial_ord::comparison::generate_field_compare_for_interface;
use crate::builtin::derive_partial_ord::types::OrdField;
use crate::builtin::return_types::partial_ord_return_type;
use crate::macros::ts_template;
use crate::ts_syn::TsStream;
use crate::ts_syn::ts_ident;
#[test]
fn test_partial_ord_macro_output_vanilla() {
let ord_fields: Vec<OrdField> = vec![OrdField {
name: "id".to_string(),
ts_type: "number".to_string(),
}];
let mut compare_body_str = String::new();
for (i, f) in ord_fields.iter().enumerate() {
let cmp_var = format!("cmp{}", i);
let expr_src = generate_field_compare_for_interface(f, "a", "b", true, None, None);
compare_body_str.push_str(&format!(
"const {} = {};\nif ({} === null) return null;\nif ({} !== 0) return {};\n",
cmp_var, expr_src, cmp_var, cmp_var, cmp_var
));
}
let return_type = partial_ord_return_type();
let return_type_ident = ts_ident!(return_type);
let output = ts_template!(Within {
compareTo(other: unknown): @{return_type_ident} {
if (a === b) return 0;
{$typescript TsStream::from_string(compare_body_str)}
return 0;
}
});
let source = output.source();
let body_content = source
.strip_prefix("/* @macroforge:body */")
.unwrap_or(source);
let wrapped = format!("class __Temp {{ {} }}", body_content);
assert!(
macroforge_ts_syn::parse_ts_stmt(&wrapped).is_ok(),
"Generated PartialOrd macro output should parse as class members"
);
assert!(
source.contains("compareTo"),
"Should contain compareTo method"
);
assert!(
source.contains("number | null"),
"Should have number | null return type"
);
}
#[test]
fn test_field_compare_number() {
let field = OrdField {
name: "id".to_string(),
ts_type: "number".to_string(),
};
let result = generate_field_compare_for_interface(&field, "a", "b", true, None, None);
assert!(result.contains("a.id < b.id"));
assert!(result.contains("a.id > b.id"));
}
#[test]
fn test_field_compare_string() {
let field = OrdField {
name: "name".to_string(),
ts_type: "string".to_string(),
};
let result = generate_field_compare_for_interface(&field, "a", "b", true, None, None);
assert!(result.contains("localeCompare"));
}
#[test]
fn test_field_compare_boolean() {
let field = OrdField {
name: "active".to_string(),
ts_type: "boolean".to_string(),
};
let result = generate_field_compare_for_interface(&field, "a", "b", true, None, None);
assert!(result.contains("-1"));
assert!(result.contains("1"));
}
#[test]
fn test_field_compare_date() {
let field = OrdField {
name: "createdAt".to_string(),
ts_type: "Date".to_string(),
};
let result = generate_field_compare_for_interface(&field, "a", "b", true, None, None);
assert!(result.contains("getTime"));
}
#[test]
fn test_field_compare_object_vanilla() {
let field = OrdField {
name: "user".to_string(),
ts_type: "User".to_string(),
};
let result = generate_field_compare_for_interface(&field, "a", "b", true, None, None);
assert!(result.contains("compareTo"));
assert!(result.contains("=== null"));
}
#[test]
fn test_field_compare_array_vanilla() {
let field = OrdField {
name: "items".to_string(),
ts_type: "Item[]".to_string(),
};
let result = generate_field_compare_for_interface(&field, "a", "b", true, None, None);
assert!(result.contains("cmp = optResult"));
}