use std::path::Path;
const CRATE: &str = r###"
day_bridge::bridge! {
#[day_bridge::declare]
extern "day" {
fn speak_native(text: &str) -> Result<(), day_bridge::Error>;
fn stop_native();
}
#[day_bridge::impl(js, platforms = [web])]
js!(r#"
export function speak_native(text) {
speechSynthesis.speak(new SpeechSynthesisUtterance(text));
}
export function stop_native() { speechSynthesis.cancel(); }
"#);
#[day_bridge::impl(rust, platforms = [other])]
fn speak_native(_text: &str) -> Result<(), day_bridge::Error> {
Err(day_bridge::Error::Unsupported)
}
#[day_bridge::impl(rust, platforms = [other])]
fn stop_native() {}
}
"###;
#[test]
fn js_arm_is_a_valid_es_module() {
let tmp = std::env::temp_dir().join(format!("day-bridge-js-{}", std::process::id()));
std::fs::create_dir_all(tmp.join("src")).unwrap();
std::fs::write(tmp.join("src/lib.rs"), CRATE).unwrap();
let bridge = day_build::bridge::parse_crate(&tmp).expect("parse");
let arm = bridge
.arms
.iter()
.find(|a| a.lang == day_build::bridge::Lang::Js)
.expect("js arm");
let js = day_build::bridge::js_adapter(&bridge, arm, "day-part-demo");
assert!(
js.contains("day_bridge_day_part_demo_speak_native(text_ptr, text_len)"),
"{js}"
);
assert!(js.contains("rt.str(text_ptr, text_len)"), "{js}");
assert!(js.contains("export function register(rt)"), "{js}");
assert!(
!js.contains("cargo:"),
"no build-script chatter in a module:\n{js}"
);
let module = tmp.join("bridge.mjs");
std::fs::write(&module, &js).unwrap();
match std::process::Command::new("node")
.arg("--check")
.arg(&module)
.output()
{
Ok(out) => assert!(
out.status.success(),
"node rejected the generated module:\n{}\n{js}",
String::from_utf8_lossy(&out.stderr)
),
Err(_) => eprintln!("node not installed; skipped the parse check"),
}
let _ = std::fs::remove_dir_all(Path::new(&tmp));
}