sweet_cli/commands/
test_wasm.rs1use beet::prelude::*;
2use clap::Parser;
3use std::fs;
4use std::path::PathBuf;
5use std::process::Child;
6use std::process::Command;
7use std::str::FromStr;
8
9#[derive(Debug, Parser)]
24pub struct TestWasm {
25 test_binary: String,
29 #[arg(long)]
31 wasm_bindgen_args: Option<String>,
32
33 #[command(flatten)]
36 runner_args: sweet::prelude::TestRunnerConfig,
37}
38
39
40impl TestWasm {
41 pub fn run(self) -> Result {
42 self.run_wasm_bindgen()?;
43 self.init_deno()?;
44 self.run_deno()?;
45 Ok(())
46 }
47 fn run_wasm_bindgen(&self) -> Result {
48 let output = Command::new("wasm-bindgen")
49 .arg("--out-dir")
50 .arg(sweet_target_dir())
51 .arg("--out-name")
52 .arg("bindgen")
53 .arg("--target")
54 .arg("web")
55 .arg("--no-typescript")
56 .arg(&self.test_binary)
57 .args(
58 self.wasm_bindgen_args
59 .as_deref()
60 .unwrap_or_default()
61 .split_whitespace(),
62 )
63 .spawn()?;
64
65 handle_process("wasm-bindgen", output)?;
66 Ok(())
67 }
68
69
70 fn init_deno(&self) -> Result {
74 let deno_runner_path = deno_runner_path();
75 let deno_str = include_str!("./deno.ts");
76
77 if fs_ext::exists(&deno_runner_path)? {
79 let runner_hash = fs_ext::hash_file(&deno_runner_path)?;
80 let deno_hash = fs_ext::hash_string(deno_str);
81 if runner_hash == deno_hash {
82 return Ok(());
83 }
84 };
85
86 let deno_installed =
87 match Command::new("deno").arg("--version").status() {
88 Ok(val) => val.success(),
89 _ => false,
90 };
91 if !deno_installed {
92 bevybail!("{}", INSTALL_DENO);
93 }
94 println!("copying deno file to {}", deno_runner_path.display());
95
96 fs::write(deno_runner_path, deno_str)?;
98 Ok(())
99 }
100
101 fn run_deno(&self) -> Result {
102 let args = std::env::args().skip(2).collect::<Vec<_>>();
106 let child = Command::new("deno")
107 .arg("--allow-read")
108 .arg("--allow-net")
109 .arg("--allow-env")
110 .arg(deno_runner_path())
111 .args(args)
112 .spawn()?;
113 handle_process("deno", child)?;
114 Ok(())
115 }
116}
117
118
119fn handle_process(_stderr_prefix: &str, child: Child) -> Result {
120 let output = child.wait_with_output()?;
121
122 let stdout = String::from_utf8_lossy(&output.stdout);
123 if !stdout.is_empty() {
124 println!("{}", stdout);
125 }
126
127 if !output.status.success() {
128 let stderr = String::from_utf8_lossy(&output.stderr);
129 bevybail!("{stderr}");
130 }
131 Ok(())
132}
133
134fn workspace_root() -> PathBuf {
135 let root_str = std::env::var("SWEET_ROOT").unwrap_or_default();
136 PathBuf::from_str(&root_str).unwrap()
137}
138
139fn sweet_target_dir() -> PathBuf {
140 let mut path = workspace_root();
141 path.push("target/sweet");
142 path
143}
144
145fn deno_runner_path() -> PathBuf {
146 let mut path = sweet_target_dir();
147 path.push("deno.ts");
148 path
149}
150
151const INSTALL_DENO: &str = "
152🦖 Sweet uses Deno for wasm tests 🦖
153
154Install Deno via:
155shell: curl -fsSL https://deno.land/install.sh | sh
156powershell: irm https://deno.land/install.ps1 | iex
157website: https://docs.deno.com/runtime/getting_started/installation/
158
159";
160
161
162#[cfg(test)]
163mod test {
164 use super::*;
165 use sweet::prelude::*;
166
167 #[test]
168 fn works() {
169 deno_runner_path()
170 .to_string_lossy()
171 .replace("\\", "/")
172 .xpect_ends_with("target/sweet/deno.ts");
173 }
174}