Crate surface
Public types
use vanilla_test::{TestError, TestResult, VanillaTest};| Type | Purpose | Key traits |
|---|---|---|
VanillaTest | Owns one sequential suite and its active case. | Default, Send, Sync |
TestResult | Final passed/failed lists, counts, status, and plain-text report. | Debug, PartialEq, Eq, Send, Sync |
TestError | Typed invalid-lifecycle result; a failed assertion is data, not this error. | Copy, Debug, Display, Error |
State model
Lifecycle
expects() → pass() | fail() → done()
↓
report()- One suite has at most one active case.
- Descriptions are exact, case-sensitive, and unique within the suite.
- The first decision wins; later
pass()orfail()calls preserve it. done()without a decision records a failure.report()seals the suite and caches one result.
Instance surface
VanillaTest methods
VanillaTest::new()
- Signature
pub fn new() -> Self- Returns
- An empty, idle, unreported suite.
- Errors
- None.
test.expects(description)
- Signature
pub fn expects(&mut self, description: &str) -> Result<(), TestError>- Effect
- Starts the next uniquely described case.
- Errors
SuiteAlreadyReported,TestAlreadyActive, orDuplicateDescription.
test.pass()
- Signature
pub fn pass(&mut self) -> Result<(), TestError>- Effect
- Records the first decision as passed.
- Errors
NoActiveTest.
test.fail()
- Signature
pub fn fail(&mut self) -> Result<(), TestError>- Effect
- Records the first decision as failed.
- Errors
NoActiveTest.
test.done()
- Signature
pub fn done(&mut self) -> Result<(), TestError>- Effect
- Closes the active case, failing it first when undecided.
- Errors
NoActiveTest.
test.report()
- Signature
pub fn report(&mut self) -> Result<&TestResult, TestError>- Returns
- The cached result; repeated calls return the same reference.
- Errors
ActiveTestNotDone.
Report surface
TestResult
| Field | Type | Invariant |
|---|---|---|
passed | Box<[String]> | Numbered passed descriptions in test order. |
failed | Box<[String]> | Numbered failed descriptions in test order. |
total | usize | passed.len() + failed.len(). |
failure_count | usize | failed.len(). |
ok | bool | True exactly when failure_count == 0. |
report | String | Plain-text summary followed by failed and passed lists. |
Typed failures
TestError variants
| Variant | Meaning |
|---|---|
SuiteAlreadyReported | A sealed suite cannot start another case. |
TestAlreadyActive | Finish the active case before starting another. |
DuplicateDescription | The exact description was already used. |
NoActiveTest | A decision or completion was requested while idle. |
ActiveTestNotDone | The active case must be completed before reporting. |
Call fail() to record a failed expectation. TestError means the runner was used in an invalid state.
Browser contract
Rust stays Rust; the host adapter stays JavaScript
cargo vanilla-test --browser compiles the selected package's existing library #[test] functions into a Cargo-generated libtest harness. This repository has seven focused Rust test functions; native Cargo and browser WebAssembly execute those exact same seven functions, with no JavaScript copy of their assertions.
| Layer | Supported | Not supported |
|---|---|---|
| Rust harness | Target-compatible Rust logic and aggregate status from safe exported main(). | JavaScript or DOM calls, browser console output, per-test browser diagnostics, and OS- or thread-dependent tests. |
| Browser host adapter | Passive rendered-text checks, artifact response, exact WASM MIME type, streaming instantiation, export validation, and status 0. | Clicks, typing, focus, navigation, arbitrary property assertions, custom network assertions, waits, or retries. |
| JavaScript lane | Direct JavaScript function, DOM, event, and interaction tests. | It is not executed by the Rust harness. |
Passive page contract
For every data-rust-browser-site-check marker, browser.js takes one snapshot when it starts. The element must be connected, have a layout rectangle, have computed visibility visible and opacity other than 0, and contain nonempty innerText.trim(). Optional data-rust-browser-expected adds an exact, case-sensitive text match.
A custom page keeps <script type="module" src="./browser.js"></script> and the data-rust-browser-result, data-rust-browser-status, data-rust-browser-detail, data-rust-browser-score, data-rust-browser-target, data-rust-browser-checks, data-rust-browser-passed, data-rust-browser-failed, data-rust-browser-skipped, and data-rust-browser-harness result hooks. --page copies the HTML bytes without parsing or validation; it does not copy referenced assets or wait for dynamic content.
This repository's wasm32-unknown-unknown module has zero host imports, and the browser supplies no import object. Rust cannot call JavaScript functions, the DOM, browser APIs, or the console. Test JavaScript functions in the JavaScript lane; Rust browser mode can only observe text they rendered before the adapter started.
Complete example
Use the result as the assertion boundary
use vanilla_test::VanillaTest;
#[test]
fn arithmetic_suite() {
let mut test = VanillaTest::new();
test.expects("2 + 2 equals 4").unwrap();
if 2 + 2 == 4 { test.pass().unwrap(); } else { test.fail().unwrap(); }
test.done().unwrap();
let result = test.report().unwrap();
assert!(result.ok, "{}", result.report);
assert_eq!(result.total, 1);
}