//! Test suite for the Web and headless browsers. //! These tests only work with WASM_BINDGEN_USE_NO_MODULE=true env var, //! as otherwise there's no way to access the generated wasm bindings from inside JS. #![cfg(target_arch = "wasm32")] extern crate alloc; extern crate wasm_bindgen_test; use js_sys::*; use parking_lot::Once; use veilid_wasm::*; use wasm_bindgen::*; use wasm_bindgen_futures::*; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); static SETUP_ONCE: Once = Once::new(); pub fn setup() -> () { SETUP_ONCE.call_once(|| { console_log!("setup()"); console_error_panic_hook::set_once(); init_callbacks(); }) } fn init_callbacks() { assert_eq!(js_sys::eval(r#" window.sleep = (milliseconds) => { return new Promise(resolve => setTimeout(resolve, milliseconds)) }; window.stateChangeCallback = async (stateChange) => { delete stateChange.peers; // makes logs less verbose console.log("State change: ", JSON.stringify(stateChange, null, 2)); }; window.veilidCoreInitConfig = { logging: { api: { enabled: true, level: 'Info', }, performance: { enabled: false, level: 'Info', logs_in_timings: false, logs_in_console: false, }, }, }; window.veilidCoreStartupConfig = { program_name: 'veilid-wasm-test', namespace: '', capabilities: { disable: [], }, protected_store: { allow_insecure_fallback: true, always_use_insecure_storage: true, directory: '', delete: false, device_encryption_key_password: 'some-user-secret-value', // "new_device_encryption_key_password": "an-updated-user-secret-value" }, table_store: { directory: '', delete: false, }, block_store: { directory: '', delete: false, }, network: { connection_initial_timeout_ms: 2000, connection_inactivity_timeout_ms: 60000, max_connections_per_ip4: 32, max_connections_per_ip6_prefix: 32, max_connections_per_ip6_prefix_size: 56, max_connection_frequency_per_min: 128, client_whitelist_timeout_ms: 300000, reverse_connection_receipt_time_ms: 5000, hole_punch_receipt_time_ms: 5000, network_key_password: '', disable_capabilites: [], routing_table: { node_id: [], node_id_secret: [], bootstrap: [ 'ws://bootstrap.veilid.net:5150/ws', ], limit_over_attached: 64, limit_fully_attached: 32, limit_attached_strong: 16, limit_attached_good: 8, limit_attached_weak: 4, }, rpc: { concurrency: 0, queue_size: 1024, max_timestamp_behind_ms: 10000, max_timestamp_ahead_ms: 10000, timeout_ms: 5000, max_route_hop_count: 4, default_route_hop_count: 1, }, dht: { max_find_node_count: 20, resolve_node_timeout_ms: 10000, resolve_node_count: 1, resolve_node_fanout: 4, get_value_timeout_ms: 10000, get_value_count: 3, get_value_fanout: 4, set_value_timeout_ms: 10000, set_value_count: 5, set_value_fanout: 4, min_peer_count: 20, min_peer_refresh_time_ms: 60000, validate_dial_info_receipt_time_ms: 2000, local_subkey_cache_size: 128, local_max_subkey_cache_memory_mb: 256, remote_subkey_cache_size: 1024, remote_max_records: 65536, remote_max_subkey_cache_memory_mb: 256, remote_max_storage_space_mb: 0, }, upnp: true, detect_address_changes: true, restricted_nat_retries: 0, tls: { certificate_path: '', private_key_path: '', connection_initial_timeout_ms: 2000, }, application: { https: { enabled: false, listen_address: ':5150', path: 'app', }, http: { enabled: false, listen_address: ':5150', path: 'app', }, }, protocol: { udp: { enabled: false, socket_pool_size: 0, listen_address: '', }, tcp: { connect: false, listen: false, max_connections: 32, listen_address: '', }, ws: { connect: true, listen: true, max_connections: 16, listen_address: ':5150', path: 'ws', }, wss: { connect: true, listen: false, max_connections: 16, listen_address: '', path: 'ws', }, }, }, }; true "#).expect("failed to eval"), JsValue::TRUE); } /// Helper for converting an eval Promise result into a JsValue async fn eval_promise(source: &str) -> JsValue { JsFuture::from( eval(source) .expect("Failed to eval") .dyn_into::() .unwrap(), ) .await .unwrap() } // ---------------------------------------------------------------- // TODO: now that veilidClient uses a single instance of VeilidAPI, // subsequent tests fail because veilidCore has already been initialized. #[wasm_bindgen_test()] async fn test_kitchen_sink() { setup(); let res = eval_promise( r#" (async function () { const { veilidClient } = wasm_bindgen; // only accessible in no_module mode. veilidClient.initializeCore(window.veilidCoreInitConfig); await veilidClient.startupCore(window.stateChangeCallback, JSON.stringify(window.veilidCoreStartupConfig)); console.log(veilidClient.versionString()); await veilidClient.attach(); await sleep(10000); await veilidClient.detach(); await veilidClient.shutdownCore(); return true; })(); "#, ).await; assert_eq!(res, JsValue::TRUE); }