B6: add a WASM binding test suite

The WASM binding had no tests; CI only checked that artefacts existed.
Adds a wasm-bindgen-test suite covering SMA reference values, EMA
batch==streaming equivalence, RSI pure-uptrend behaviour, fallible
constructors returning JsError, and the unequal-length batch guards from
B3. Wires wasm-pack test --node into the CI wasm job. The suite
type-checks on the host; it executes under wasm-pack in CI (the local
environment is a non-rustup Rust install without the wasm32 target).
This commit is contained in:
kingchenc
2026-05-22 04:05:15 +02:00
parent 4880fea075
commit 8192e576cf
3 changed files with 72 additions and 0 deletions
+3
View File
@@ -112,6 +112,9 @@ jobs:
- name: Build WASM package
run: wasm-pack build bindings/wasm --target web --release --features panic-hook
- name: Run WASM tests
run: wasm-pack test --node bindings/wasm
- name: Verify generated artefacts
run: |
test -f bindings/wasm/pkg/wickra_wasm.js
+3
View File
@@ -34,6 +34,9 @@ console_error_panic_hook = { version = "0.1", optional = true }
default = []
panic-hook = ["dep:console_error_panic_hook"]
[dev-dependencies]
wasm-bindgen-test = "0.3"
[package.metadata.wasm-pack.profile.release.wasm-bindgen]
debug-js-glue = false
demangle-name-section = true
+66
View File
@@ -649,3 +649,69 @@ impl WasmAroon {
Ok(Float64Array::from(out.as_slice()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use wasm_bindgen_test::wasm_bindgen_test;
#[wasm_bindgen_test]
fn sma_batch_reference_values() {
// SMA(3) of [2, 4, 6, 8, 10] -> [NaN, NaN, 4, 6, 8].
let mut sma = WasmSma::new(3).ok().expect("valid period");
let out = sma.batch(&[2.0, 4.0, 6.0, 8.0, 10.0]);
assert!(out.get_index(0).is_nan());
assert!(out.get_index(1).is_nan());
assert_eq!(out.get_index(2), 4.0);
assert_eq!(out.get_index(3), 6.0);
assert_eq!(out.get_index(4), 8.0);
}
#[wasm_bindgen_test]
fn ema_batch_equals_streaming() {
let prices: Vec<f64> = (1..=60)
.map(|i| 100.0 + (f64::from(i) * 0.3).sin() * 5.0)
.collect();
let batch = WasmEma::new(14).ok().expect("valid").batch(&prices);
let mut ema = WasmEma::new(14).ok().expect("valid");
for (i, &p) in prices.iter().enumerate() {
let b = batch.get_index(i as u32);
match ema.update(p) {
Some(v) => assert!((v - b).abs() < 1e-9, "streaming != batch at {i}"),
None => assert!(b.is_nan(), "expected NaN during warmup at {i}"),
}
}
}
#[wasm_bindgen_test]
fn rsi_pure_uptrend_yields_100() {
let prices: Vec<f64> = (1..=20).map(f64::from).collect();
let out = WasmRsi::new(14).ok().expect("valid").batch(&prices);
for i in 14..prices.len() {
assert_eq!(out.get_index(i as u32), 100.0);
}
}
#[wasm_bindgen_test]
fn invalid_constructors_return_err() {
assert!(WasmSma::new(0).is_err());
assert!(WasmMacd::new(0, 0, 0).is_err());
assert!(WasmMacd::new(26, 12, 9).is_err());
assert!(WasmBb::new(20, -1.0).is_err());
assert!(WasmPsar::new(0.30, 0.02, 0.20).is_err());
}
#[wasm_bindgen_test]
fn batch_rejects_unequal_lengths() {
let mut atr = WasmAtr::new(14).ok().expect("valid");
assert!(atr.batch(&[1.0, 2.0], &[1.0], &[1.0, 2.0]).is_err());
let mut stoch = WasmStoch::new(14, 3).ok().expect("valid");
assert!(stoch
.batch(&[1.0, 2.0, 3.0], &[1.0], &[1.0, 2.0, 3.0])
.is_err());
let mut mfi = WasmMfi::new(14).ok().expect("valid");
assert!(mfi
.batch(&[1.0, 2.0], &[1.0, 2.0], &[1.0, 2.0], &[1.0])
.is_err());
}
}