use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
use scirs2_wasm::{array, error, fft, linalg, shared_memory, stats};
#[wasm_bindgen_test]
fn browser_test_version_string() {
let v = scirs2_wasm::version();
assert!(!v.is_empty(), "version() must return a non-empty string");
assert!(
v.starts_with("0."),
"version should start with '0.' (pre-1.0 series)"
);
}
#[wasm_bindgen_test]
fn browser_test_capabilities_non_null() {
let caps = scirs2_wasm::capabilities();
assert!(!caps.is_null());
assert!(!caps.is_undefined());
}
#[wasm_bindgen_test]
fn browser_test_fft_dc_only_4pt() {
let input = vec![1.0_f64, 0.0, 0.0, 0.0];
let result = fft::fft(&input).expect("fft should succeed");
assert_eq!(result.len(), 8, "4-point FFT must return 8 floats");
for k in 0..4 {
let re = result[k * 2];
let im = result[k * 2 + 1];
assert!(
(re - 1.0).abs() < 1e-10,
"FFT DC: re[{k}] = {re}, expected 1.0"
);
assert!(im.abs() < 1e-10, "FFT DC: im[{k}] = {im}, expected 0.0");
}
}
#[wasm_bindgen_test]
fn browser_test_fft_output_length() {
for &n in &[8usize, 16, 32, 64] {
let input: Vec<f64> = (0..n).map(|i| (i as f64 * 0.1).sin()).collect();
let result = fft::fft(&input).expect("fft should succeed");
assert_eq!(
result.len(),
n * 2,
"{n}-point FFT should return {expected} floats",
expected = n * 2
);
}
}
#[wasm_bindgen_test]
fn browser_test_fft_ifft_roundtrip_8pt() {
let original: Vec<f64> = vec![1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0, 0.0];
let spectrum = fft::fft(&original).expect("forward FFT should succeed");
let reconstructed = fft::ifft(&spectrum).expect("inverse FFT should succeed");
assert_eq!(
reconstructed.len(),
original.len() * 2,
"IFFT output includes complex interleaved pairs"
);
for (i, &orig) in original.iter().enumerate() {
let re = reconstructed[i * 2];
assert!(
(re - orig).abs() < 1e-9,
"IFFT reconstruction failed at index {i}: got {re}, expected {orig}"
);
}
}
#[wasm_bindgen_test]
fn browser_test_matrix_inv_correctness() {
let shape = js_sys::Array::new();
shape.push(&2.0_f64.into());
shape.push(&2.0_f64.into());
let data = js_sys::Array::new();
for &v in &[2.0_f64, 1.0, 1.0, 1.0] {
data.push(&v.into());
}
let m = array::WasmArray::from_shape(&shape.into(), &data.into())
.expect("matrix creation should succeed");
let inv = linalg::inv(&m).expect("inv should succeed for non-singular matrix");
assert!(
(inv.get(0).unwrap() - 1.0).abs() < 1e-10,
"inv[0,0] should be 1"
);
assert!(
(inv.get(1).unwrap() - (-1.0)).abs() < 1e-10,
"inv[0,1] should be -1"
);
assert!(
(inv.get(2).unwrap() - (-1.0)).abs() < 1e-10,
"inv[1,0] should be -1"
);
assert!(
(inv.get(3).unwrap() - 2.0).abs() < 1e-10,
"inv[1,1] should be 2"
);
}
#[wasm_bindgen_test]
fn browser_test_det_known_matrix() {
let shape = js_sys::Array::new();
shape.push(&2.0_f64.into());
shape.push(&2.0_f64.into());
let data = js_sys::Array::new();
for &v in &[3.0_f64, 8.0, 4.0, 6.0] {
data.push(&v.into());
}
let m = array::WasmArray::from_shape(&shape.into(), &data.into())
.expect("matrix creation should succeed");
let det = linalg::det(&m).expect("det should succeed");
assert!(
(det - (-14.0)).abs() < 1e-9,
"det([[3,8],[4,6]]) should be -14, got {det}"
);
}
#[wasm_bindgen_test]
fn browser_test_dot_product_1d() {
let shape = js_sys::Array::new();
shape.push(&3.0_f64.into());
let data_a = js_sys::Array::new();
for &v in &[1.0_f64, 2.0, 3.0] {
data_a.push(&v.into());
}
let a = array::WasmArray::from_shape(&shape.clone().into(), &data_a.into()).expect("create a");
let data_b = js_sys::Array::new();
for &v in &[4.0_f64, 5.0, 6.0] {
data_b.push(&v.into());
}
let b = array::WasmArray::from_shape(&shape.into(), &data_b.into()).expect("create b");
let d = array::dot(&a, &b).expect("dot should succeed");
assert!(
(array::sum(&d) - 32.0).abs() < 1e-10,
"dot product should be 32"
);
}
#[wasm_bindgen_test]
fn browser_test_shared_array_buffer_probe_does_not_panic() {
let _available = shared_memory::shared_array_buffer_available();
}
#[wasm_bindgen_test]
fn browser_test_error_codes_accessible() {
use error::{codes, WasmError};
let err = WasmError::invalid_input("browser test");
assert_eq!(
err.error_code(),
codes::INVALID_INPUT,
"invalid_input error code should be INVALID_INPUT"
);
let dim_err = WasmError::DimensionMismatch {
expected: vec![2, 3],
actual: vec![2, 4],
};
assert_eq!(
dim_err.error_code(),
codes::DIMENSION_MISMATCH,
"dimension mismatch code should be DIMENSION_MISMATCH"
);
assert!(
err.error_code() > 0,
"all error codes must be positive non-zero"
);
}
#[wasm_bindgen_test]
fn browser_test_error_to_js_value_non_null() {
use error::WasmError;
let err = WasmError::invalid_input("testing js error serialization");
let js_val = err.to_js_value();
assert!(!js_val.is_null());
assert!(!js_val.is_undefined());
}
#[wasm_bindgen_test]
fn browser_test_stats_normal_pdf_at_mean_is_maximum() {
let arr_data = js_sys::Array::new();
for &v in &[-2.0_f64, -1.0, 0.0, 1.0, 2.0] {
arr_data.push(&v.into());
}
let arr = array::WasmArray::new(&arr_data.into()).expect("array creation");
let mean = array::mean(&arr);
assert!(
(mean - 0.0).abs() < 1e-10,
"mean of symmetric data should be 0"
);
}
#[wasm_bindgen_test]
fn browser_test_stats_variance_known_data() {
let js_arr = js_sys::Array::new();
for &v in &[2.0_f64, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0] {
js_arr.push(&v.into());
}
let arr = array::WasmArray::new(&js_arr.into()).expect("array");
let mean_val = array::mean(&arr);
assert!((mean_val - 5.0).abs() < 1e-10, "mean should be 5.0");
let std_val = stats::std(&arr);
assert!(
(std_val - 2.0).abs() < 0.5,
"std of known data should be near 2.0, got {std_val}"
);
}