(wasm) webdriver-based tests for JS/TS apis, update README

This commit is contained in:
Brandon Vandegrift
2023-09-06 22:13:05 -04:00
parent fa13f95a10
commit 40a1c9933c
17 changed files with 10328 additions and 222 deletions

2
veilid-wasm/tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules
veilid-wasm-pkg

1
veilid-wasm/tests/.npmrc Normal file
View File

@@ -0,0 +1 @@
engine-strict=true

9494
veilid-wasm/tests/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
{
"name": "veilid-wasm-tests",
"private": true,
"type": "module",
"engines": {
"node": ">=18"
},
"devDependencies": {
"@wdio/browser-runner": "^8.16.4",
"@wdio/cli": "^8.16.4",
"@wdio/mocha-framework": "^8.16.3",
"@wdio/spec-reporter": "^8.16.3",
"ts-node": "^10.9.1",
"typescript": "^5.2.2",
"veilid-wasm": "file:../pkg",
"vite-plugin-wasm": "^3.2.2"
},
"scripts": {
"test": "wdio run ./wdio.conf.ts",
"test:headless": "WDIO_HEADLESS=true npm run test",
"start": "tsc && npm run test:headless"
}
}

View File

@@ -0,0 +1,99 @@
import { expect } from '@wdio/globals';
import {
veilidCoreInitConfig,
veilidCoreStartupConfig,
} from './utils/veilid-config';
import { VeilidTableDB, veilidClient } from 'veilid-wasm';
import { marshall, unmarshall } from './utils/marshalling-utils';
const TABLE_NAME = 'some-table';
const TABLE_COLS = 1;
describe('VeilidTable', () => {
before('veilid startup', async () => {
veilidClient.initializeCore(veilidCoreInitConfig);
await veilidClient.startupCore((_update) => {
// if (_update.kind === 'Log') {
// console.log(_update.message);
// }
}, JSON.stringify(veilidCoreStartupConfig));
});
after('veilid shutdown', async () => {
await veilidClient.shutdownCore();
});
it('should open and close a table', async () => {
const table = new VeilidTableDB(TABLE_NAME, TABLE_COLS);
await table.openTable();
const keys = await table.getKeys(0);
expect(keys.length).toBe(0);
table.free();
});
describe('table operations', () => {
let table: VeilidTableDB;
before('create table', async () => {
table = new VeilidTableDB(TABLE_NAME, TABLE_COLS);
await table.openTable();
});
after('free table', async () => {
table.free();
});
it('should have no keys', async () => {
const keys = await table.getKeys(0);
expect(keys.length).toBe(0);
});
describe('store/load', () => {
const key = 'test-key with unicode 🚀';
const value = 'test value with unicode 🚀';
it('should store value', async () => {
await table.store(0, marshall(key), marshall(value));
});
it('should load value', async () => {
const storedValue = await table.load(0, marshall(key));
expect(storedValue).toBeDefined();
expect(unmarshall(storedValue!)).toBe(value);
});
it('should have key in list of keys', async () => {
const keys = await table.getKeys(0);
const decodedKeys = keys.map(unmarshall);
expect(decodedKeys).toEqual([key]);
});
});
describe('transactions', () => {
it('should commit a transaction', async () => {
let transaction = await table.createTransaction();
const key = 'tranaction-key🔥';
const first = 'first🅱';
const second = 'second✔';
const third = 'third📢';
transaction.store(0, marshall(key), marshall(first));
transaction.store(0, marshall(key), marshall(second));
transaction.store(0, marshall(key), marshall(third));
await transaction.commit();
const storedValue = await table.load(0, marshall(key));
expect(storedValue).toBeDefined();
expect(unmarshall(storedValue!)).toBe(third);
transaction.free();
});
});
});
});

View File

@@ -0,0 +1,45 @@
// TextEncoder/TextDecoder are used to solve for "The Unicode Problem" https://stackoverflow.com/a/30106551
export function marshall(data: string) {
const byteString = bytesToString(new TextEncoder().encode(data));
return base64UrlEncode(byteString);
}
export function unmarshall(b64: string) {
const byteString = base64UrlDecode(b64);
return new TextDecoder().decode(stringToBytes(byteString));
}
function base64UrlEncode(data: string) {
return removeBase64Padding(btoa(data));
}
function base64UrlDecode(b64: string) {
return atob(addBase64Padding(b64));
}
function removeBase64Padding(b64: string) {
// URL encode characters, and remove `=` padding.
return b64.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
function addBase64Padding(b64: string) {
// URL decode characters
b64 = b64.replace(/-/g, '+').replace(/_/g, '/');
// Add base64 padding characters (`=`)
const rem = b64.length % 4;
if (rem === 2) {
return `${b64}==`;
} else if (rem === 3) {
return `${b64}=`;
}
return b64;
}
function stringToBytes(binString: string) {
return Uint8Array.from(binString as any, (m) => (m as any).codePointAt(0));
}
function bytesToString(bytes: Uint8Array) {
return Array.from(bytes, (x: number) => String.fromCodePoint(x)).join('');
}

View File

@@ -0,0 +1,140 @@
import type { VeilidWASMConfig } from 'veilid-wasm';
export const veilidCoreInitConfig: VeilidWASMConfig = {
logging: {
api: {
enabled: true,
level: 'Debug',
},
performance: {
enabled: false,
level: 'Info',
logs_in_timings: false,
logs_in_console: false,
},
},
};
export const 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',
},
},
},
};

View File

@@ -0,0 +1,3 @@
export const waitForMs = (milliseconds: number) => {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
};

View File

@@ -0,0 +1,59 @@
import { expect } from '@wdio/globals';
import {
veilidCoreInitConfig,
veilidCoreStartupConfig,
} from './utils/veilid-config';
import { VeilidState, veilidClient } from 'veilid-wasm';
import { waitForMs } from './utils/wait-utils';
describe('veilidClient', () => {
before('veilid startup', async () => {
veilidClient.initializeCore(veilidCoreInitConfig);
await veilidClient.startupCore((_update) => {
// if (_update.kind === 'Log') {
// console.log(_update.message);
// }
}, JSON.stringify(veilidCoreStartupConfig));
});
after('veilid shutdown', async () => {
await veilidClient.shutdownCore();
});
it('should print version', async () => {
const version = veilidClient.versionString();
expect(typeof version).toBe('string');
expect(version.length).toBeGreaterThan(0);
});
it('should attach and detach', async () => {
await veilidClient.attach();
await waitForMs(2000);
await veilidClient.detach();
});
describe('kitchen sink', () => {
before('attach', async () => {
await veilidClient.attach();
await waitForMs(2000);
});
after('detach', () => veilidClient.detach());
let state: VeilidState;
it('should get state', async () => {
state = await veilidClient.getState();
expect(state.attachment).toBeDefined();
expect(state.config.config).toBeDefined();
expect(state.network).toBeDefined();
});
it('should call debug command', async () => {
const response = await veilidClient.debug('txtrecord');
expect(response).toBeDefined();
expect(response.length).toBeGreaterThan(0);
});
});
});

View File

@@ -0,0 +1,38 @@
import { expect } from '@wdio/globals';
import {
veilidCoreInitConfig,
veilidCoreStartupConfig,
} from './utils/veilid-config';
import { veilidClient, veilidCrypto } from 'veilid-wasm';
describe('veilidCrypto', () => {
before('veilid startup', async () => {
veilidClient.initializeCore(veilidCoreInitConfig);
await veilidClient.startupCore((_update) => {
// if (_update.kind === 'Log') {
// console.log(_update.message);
// }
}, JSON.stringify(veilidCoreStartupConfig));
});
after('veilid shutdown', async () => {
await veilidClient.shutdownCore();
});
it('should list crypto kinds', () => {
const kinds = veilidCrypto.validCryptoKinds();
const bestKind = veilidCrypto.bestCryptoKind();
expect(typeof bestKind).toBe('string');
expect(kinds.includes(bestKind)).toBe(true);
});
it('should generate key pair', async () => {
const bestKind = veilidCrypto.bestCryptoKind();
const keypair = veilidCrypto.generateKeyPair(bestKind);
expect(typeof keypair).toBe('string');
// TODO: fix TypeScript return type of generateKeyPair to return string instead of KeyPair
});
});

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "ESNext",
"target": "es2022",
"types": [
"node",
"@wdio/globals/types",
"expect-webdriverio",
"@wdio/mocha-framework",
"@wdio/browser-runner"
],
"skipLibCheck": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}

View File

@@ -0,0 +1,5 @@
import { defineConfig } from 'vite';
import wasm from 'vite-plugin-wasm';
export default defineConfig({
plugins: [wasm()],
});

View File

@@ -0,0 +1,300 @@
import type { Options } from '@wdio/types';
export const config: Options.Testrunner = {
//
// ====================
// Runner Configuration
// ====================
// WebdriverIO supports running e2e tests as well as unit and component tests.
runner: ['browser', { viteConfig: './vite.config.ts' }],
autoCompileOpts: {
autoCompile: true,
tsNodeOpts: {
project: './tsconfig.json',
typeCheck: true,
},
},
//
// ==================
// Specify Test Files
// ==================
// Define which test specs should run. The pattern is relative to the directory
// of the configuration file being run.
//
// The specs are defined as an array of spec files (optionally using wildcards
// that will be expanded). The test for each spec file will be run in a separate
// worker process. In order to have a group of spec files run in the same worker
// process simply enclose them in an array within the specs array.
//
// If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script),
// then the current working directory is where your `package.json` resides, so `wdio`
// will be called from there.
//
specs: ['./src/**/*.test.ts'],
// Patterns to exclude.
exclude: [
// 'path/to/excluded/files'
],
//
// ============
// Capabilities
// ============
// Define your capabilities here. WebdriverIO can run multiple capabilities at the same
// time. Depending on the number of capabilities, WebdriverIO launches several test
// sessions. Within your capabilities you can overwrite the spec and exclude options in
// order to group specific specs to a specific capability.
//
// First, you can define how many instances should be started at the same time. Let's
// say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
// set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
// files and you set maxInstances to 10, all spec files will get tested at the same time
// and 30 processes will get spawned. The property handles how many capabilities
// from the same test should run tests.
//
maxInstances: process.env.WDIO_HEADLESS ? 10 : 1,
//
// If you have trouble getting all important capabilities together, check out the
// Sauce Labs platform configurator - a great tool to configure your capabilities:
// https://saucelabs.com/platform/platform-configurator
//
capabilities: [
{
// capabilities for local browser web tests
browserName: 'firefox', // or "chrome", "microsoftedge", "safari"
'moz:firefoxOptions': {
args: process.env.WDIO_HEADLESS ? ['-headless'] : [],
},
},
// {
// browserName: 'chrome',
// 'goog:chromeOptions': {
// args: process.env.WDIO_HEADLESS ? ['headless', 'disable-gpu'] : [],
// },
// },
],
//
// ===================
// Test Configurations
// ===================
// Define all options that are relevant for the WebdriverIO instance here
//
// Level of logging verbosity: trace | debug | info | warn | error | silent
logLevel: 'warn',
//
// Set specific log levels per logger
// loggers:
// - webdriver, webdriverio
// - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
// - @wdio/mocha-framework, @wdio/jasmine-framework
// - @wdio/local-runner
// - @wdio/sumologic-reporter
// - @wdio/cli, @wdio/config, @wdio/utils
// Level of logging verbosity: trace | debug | info | warn | error | silent
// logLevels: {
// webdriver: 'info',
// '@wdio/appium-service': 'info'
// },
//
// If you only want to run your tests until a specific amount of tests have failed use
// bail (default is 0 - don't bail, run all tests).
bail: 0,
//
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
// gets prepended directly.
baseUrl: '',
//
// Default timeout for all waitFor* commands.
waitforTimeout: 10000,
//
// Default timeout in milliseconds for request
// if browser driver or grid doesn't send response
connectionRetryTimeout: 120000,
//
// Default request retries count
connectionRetryCount: 3,
//
// Test runner services
// Services take over a specific job you don't want to take care of. They enhance
// your test setup with almost no effort. Unlike plugins, they don't add new
// commands. Instead, they hook themselves up into the test process.
// services: [],
//
// Framework you want to run your specs with.
// The following are supported: Mocha, Jasmine, and Cucumber
// see also: https://webdriver.io/docs/frameworks
//
// Make sure you have the wdio adapter package for the specific framework installed
// before running any tests.
framework: 'mocha',
//
// The number of times to retry the entire specfile when it fails as a whole
// specFileRetries: 1,
//
// Delay in seconds between the spec file retry attempts
// specFileRetriesDelay: 0,
//
// Whether or not retried spec files should be retried immediately or deferred to the end of the queue
// specFileRetriesDeferred: false,
//
// Test reporter for stdout.
// The only one supported by default is 'dot'
// see also: https://webdriver.io/docs/dot-reporter
reporters: ['spec'],
//
// Options to be passed to Mocha.
// See the full list at http://mochajs.org/
mochaOpts: {
ui: 'bdd',
timeout: 60000,
},
//
// =====
// Hooks
// =====
// WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
// it and to build services around it. You can either apply a single function or an array of
// methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
// resolved to continue.
/**
* Gets executed once before all workers get launched.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
*/
// onPrepare: function (config, capabilities) {
// },
/**
* Gets executed before a worker process is spawned and can be used to initialise specific service
* for that worker as well as modify runtime environments in an async fashion.
* @param {string} cid capability id (e.g 0-0)
* @param {object} caps object containing capabilities for session that will be spawn in the worker
* @param {object} specs specs to be run in the worker process
* @param {object} args object that will be merged with the main configuration once worker is initialized
* @param {object} execArgv list of string arguments passed to the worker process
*/
// onWorkerStart: function (cid, caps, specs, args, execArgv) {
// },
/**
* Gets executed just after a worker process has exited.
* @param {string} cid capability id (e.g 0-0)
* @param {number} exitCode 0 - success, 1 - fail
* @param {object} specs specs to be run in the worker process
* @param {number} retries number of retries used
*/
// onWorkerEnd: function (cid, exitCode, specs, retries) {
// },
/**
* Gets executed just before initialising the webdriver session and test framework. It allows you
* to manipulate configurations depending on the capability or spec.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that are to be run
* @param {string} cid worker id (e.g. 0-0)
*/
// beforeSession: function (config, capabilities, specs, cid) {
// },
/**
* Gets executed before test execution begins. At this point you can access to all global
* variables like `browser`. It is the perfect place to define custom commands.
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that are to be run
* @param {object} browser instance of created browser/device session
*/
// before: function (capabilities, specs) {
// },
/**
* Runs before a WebdriverIO command gets executed.
* @param {string} commandName hook command name
* @param {Array} args arguments that command would receive
*/
// beforeCommand: function (commandName, args) {
// },
/**
* Hook that gets executed before the suite starts
* @param {object} suite suite details
*/
// beforeSuite: function (suite) {
// },
/**
* Function to be executed before a test (in Mocha/Jasmine) starts.
*/
// beforeTest: function (test, context) {
// },
/**
* Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
* beforeEach in Mocha)
*/
// beforeHook: function (test, context) {
// },
/**
* Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
* afterEach in Mocha)
*/
// afterHook: function (test, context, { error, result, duration, passed, retries }) {
// },
/**
* Function to be executed after a test (in Mocha/Jasmine only)
* @param {object} test test object
* @param {object} context scope object the test was executed with
* @param {Error} result.error error object in case the test fails, otherwise `undefined`
* @param {*} result.result return object of test function
* @param {number} result.duration duration of test
* @param {boolean} result.passed true if test has passed, otherwise false
* @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
*/
// afterTest: function(test, context, { error, result, duration, passed, retries }) {
// },
/**
* Hook that gets executed after the suite has ended
* @param {object} suite suite details
*/
// afterSuite: function (suite) {
// },
/**
* Runs after a WebdriverIO command gets executed
* @param {string} commandName hook command name
* @param {Array} args arguments that command would receive
* @param {number} result 0 - command success, 1 - command error
* @param {object} error error object if any
*/
// afterCommand: function (commandName, args, result, error) {
// },
/**
* Gets executed after all tests are done. You still have access to all global variables from
* the test.
* @param {number} result 0 - test pass, 1 - test fail
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that ran
*/
// after: function (result, capabilities, specs) {
// },
/**
* Gets executed right after terminating the webdriver session.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that ran
*/
// afterSession: function (config, capabilities, specs) {
// },
/**
* Gets executed after all workers got shut down and the process is about to exit. An error
* thrown in the onComplete hook will result in the test run failing.
* @param {object} exitCode 0 - success, 1 - fail
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {<Object>} results object containing test results
*/
// onComplete: function(exitCode, config, capabilities, results) {
// },
/**
* Gets executed when a refresh happens.
* @param {string} oldSessionId session ID of the old session
* @param {string} newSessionId session ID of the new session
*/
// onReload: function(oldSessionId, newSessionId) {
// }
};

View File

@@ -1,218 +0,0 @@
//! 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::<Promise>()
.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);
}