use crate::core::backend::Backend;
use crate::core::config::ResolvedCrateConfig;
use crate::core::ir::{
ApiSurface, EnumDef, EnumVariant, FieldDef, FunctionDef, ParamDef, PrimitiveType, TypeDef, TypeRef,
};
use crate::backends::wasm::WasmBackend;
fn format_metadata_enum() -> EnumDef {
EnumDef {
name: "FormatMetadata".to_string(),
rust_path: "test_lib::FormatMetadata".to_string(),
serde_tag: Some("format_type".to_string()),
has_serde: true,
variants: vec![EnumVariant {
name: "Excel".to_string(),
is_tuple: true,
fields: vec![FieldDef {
name: "_0".to_string(),
ty: TypeRef::Named("ExcelMetadata".to_string()),
..Default::default()
}],
..Default::default()
}],
..Default::default()
}
}
fn excel_metadata_type() -> TypeDef {
TypeDef {
name: "ExcelMetadata".to_string(),
rust_path: "test_lib::ExcelMetadata".to_string(),
has_serde: true,
fields: vec![FieldDef {
name: "sheet_count".to_string(),
ty: TypeRef::Primitive(PrimitiveType::U32),
..Default::default()
}],
..Default::default()
}
}
fn document_result_type() -> TypeDef {
TypeDef {
name: "DocumentResult".to_string(),
rust_path: "test_lib::DocumentResult".to_string(),
has_serde: true,
fields: vec![FieldDef {
name: "format".to_string(),
ty: TypeRef::Named("FormatMetadata".to_string()),
optional: false,
..Default::default()
}],
..Default::default()
}
}
fn function_taking_document_result() -> FunctionDef {
FunctionDef {
name: "use_document_result".to_string(),
rust_path: "test_lib::use_document_result".to_string(),
params: vec![ParamDef {
name: "value".to_string(),
ty: TypeRef::Named("DocumentResult".to_string()),
..Default::default()
}],
..Default::default()
}
}
fn fixture_api() -> ApiSurface {
ApiSurface {
crate_name: "test-lib".to_string(),
version: "0.1.0".to_string(),
enums: vec![format_metadata_enum()],
types: vec![excel_metadata_type(), document_result_type()],
functions: vec![function_taking_document_result()],
..ApiSurface::default()
}
}
fn generated_wasm_source() -> String {
WasmBackend
.generate_bindings(&fixture_api(), &ResolvedCrateConfig::default())
.expect("wasm backend must generate bindings for the fixture")
.iter()
.map(|f| f.content.as_str())
.collect::<Vec<_>>()
.join("\n")
}
#[test]
fn recased_enum_field_conversion_and_declaration_move_together() {
let source = generated_wasm_source();
assert!(
!source.is_empty(),
"PROBE: the wasm backend must emit something for the fixture"
);
assert!(
source.contains(
"js_sys::JSON::parse(&serde_json::to_string(&__alef_wire_retag_wasm(serde_json::to_value(&val.format)"
),
"core->binding conversion for `format` must route through the retag+wire-type pipeline and \
reach JS as a plain object, not a bare serde_wasm_bindgen::to_value on the raw core enum; \
actual source:\n{source}"
);
assert!(
source.contains("serde_json::from_value::<__AlefWireInWasmFormatMetadata>("),
"binding->core conversion for `format` must decode through the wire-type mirror; actual \
source:\n{source}"
);
assert!(
source.contains("formatType:"),
"declared discriminant key must be camelCase; actual source:\n{source}"
);
assert!(
source.contains("sheetCount:"),
"declared payload field must be camelCase; actual source:\n{source}"
);
assert!(
!source.contains("sheet_count: number"),
"must not declare the snake_case TS field type the runtime no longer produces; actual \
source:\n{source}"
);
assert!(
!source.contains("{ format_type: \""),
"must not declare the snake_case TS discriminant literal the runtime no longer produces; \
actual source:\n{source}"
);
}