Equality Matchers
as-test has three equality matchers with intentionally different semantics.
toBe
toBe checks identity or exact primitive equality.
expect(1 + 2).toBe(3);
expect(name).toBe("demo");Use toBe when you mean:
- primitive equality
- pointer identity
- exact same managed instance
toEqual
toEqual performs deep equality.
expect([1, 2, 3]).toEqual([1, 2, 3]);For managed values, toEqual delegates to __as_test_equals(other, strict) when needed.
toStrictEqual
toStrictEqual performs deep equality with runtime-type matching for managed values.
expect(actualUser).toStrictEqual(expectedUser);This is stricter than toEqual because managed values also have to agree on runtime type identity.
toBeNull
toBeNull checks nullable values, and also treats usize(0) as null-like in the runtime helper.
expect<string | null>(null).toBeNull();Choosing Between Them
- Use
toBefor identity or plain primitive equality. - Use
toEqualfor deep structural comparisons. - Use
toStrictEqualwhen runtime type mismatches should fail even if the shape matches.
Custom Predicates with .where()
When none of the above match the comparison you actually need — for example, asserting equality against a reference JS implementation by way of a hand-written deep-compare — use .where(). It accepts either a bool or a () => bool lambda:
// bool form: predicate is inlined at the call site
expect(x).where(x > 0 && x < 10);
// lambda form: predicate is evaluated lazily
expect(actual).where((): bool => deepCompare(GLOBAL_A, GLOBAL_B));.where() is a regular matcher, so it chains and negates like any other:
expect(parsed).toBeArray().where((): bool => allDistinct());
expect(value).not.where((): bool => isBlacklisted());The recorded failure is expected "true", received "false" — the subject value itself isn't serialized into the report because .where() is generic over the predicate, not the subject.
Closures and the lambda form
AssemblyScript does not yet implement closures, so the lambda passed to .where() cannot capture local variables from the enclosing scope. Two practical workarounds:
- Use the bool form when the predicate is built from locals — it's a plain expression evaluated at the call site.
- Use the lambda form when the predicate calls module-level functions or reads module-level values.
const REF: Point = new Point(3, 4);
function matchesRef(actual: Point): bool {
return actual.x == REF.x && actual.y == REF.y;
}
test("custom verdict via lambda", () => {
const actual = parsePoint(input);
// bool form — references the local `actual` directly.
expect(actual).where(matchesRef(actual));
});