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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user