Rust API reference

Three public types. One explicit lifecycle.

The crate exposes a safe, dependency-free sequential runner, its immutable report, and one typed lifecycle error enum.

Crate surface

Public types

use vanilla_test::{TestError, TestResult, VanillaTest};
TypePurposeKey traits
VanillaTestOwns one sequential suite and its active case.Default, Send, Sync
TestResultFinal passed/failed lists, counts, status, and plain-text report.Debug, PartialEq, Eq, Send, Sync
TestErrorTyped 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() or fail() 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, or DuplicateDescription.

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

FieldTypeInvariant
passedBox<[String]>Numbered passed descriptions in test order.
failedBox<[String]>Numbered failed descriptions in test order.
totalusizepassed.len() + failed.len().
failure_countusizefailed.len().
okboolTrue exactly when failure_count == 0.
reportStringPlain-text summary followed by failed and passed lists.

Typed failures

TestError variants

VariantMeaning
SuiteAlreadyReportedA sealed suite cannot start another case.
TestAlreadyActiveFinish the active case before starting another.
DuplicateDescriptionThe exact description was already used.
NoActiveTestA decision or completion was requested while idle.
ActiveTestNotDoneThe active case must be completed before reporting.
Assertion failures are not lifecycle errors.

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.

LayerSupportedNot supported
Rust harnessTarget-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 adapterPassive 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 laneDirect 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.

No hidden Rust-to-JavaScript bridge.

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);
}