Skip to content

Assertions

The machine-checkable assertions evaluated by the deterministic runner (no AI is involved).

bajutsu.assertions

Assertion evaluation.

Evaluate a list of expect/assert against query() results (list[Element]). The list is AND-ed; one failure fails the step. No AI is involved (machine checks only). Evaluation is total (returns results instead of raising) so it can be placed straight into the report (manifest).

The package splits along the five concerns that only shared a home because they all end in an AssertionResult: the dispatcher and small UI evaluators (evaluate), network-timeline matching also used by the web mock router and until: {request} waits (network), the visual image-preprocessing subsystem (visual), and JSON-Schema loading/validation (schema); the shared AssertionResult and tiny helpers live in _common. This module re-exports the public surface, so from bajutsu.assertions import evaluate and friends are unchanged (BE-0250).

AssertionResult dataclass

The outcome of one assertion check, carried into the manifest/report.

EvalContext dataclass

The per-run inputs the context-bearing assertion kinds need, bundled as one value (BE-0250).

Each field feeds exactly one kind: visual the screenshot/baseline paths, schema the JSON-Schema directory, golden the goldens directory, and clipboard the device pasteboard text already read for the block. Bundling replaces the four loose keyword-only parameters that were threaded in lockstep through evaluate -> evaluate_one -> run_scenario -> _run_step_body -> the runner, so a new context-bearing kind adds a field here instead of a parameter at every layer. clipboard stays a resolved value, not a reader: the read is gated and performed once per block by the runner's _clipboard_for, so bundling never turns it into a per-step read.

GoldenContext dataclass

Paths a golden assertion needs (BE-0006).

The golden JSON path (from the assertion's path field) is resolved against goldens_dir. screen, when given, is the authoritative device screen bounds for frame sanity checks; when absent, the bounds are derived from the live elements — a weaker fallback since elements at the screen edge make the check tautological for overflow detection.

SchemaContext dataclass

The directory a responseSchema assertion's schema path resolves against.

One of config targets.<name>.schemas, the --schemas flag, or schemas/ beside the scenario.

VisualContext dataclass

Paths a visual assertion needs.

The current screenshot, the baselines directory, where to write diff images, and the run dir root (so image paths can be expressed run-dir-relative for the report).

VisualEvidence dataclass

Image evidence for a visual assertion, carried into the manifest/report.

Paths are run-dir-relative (the same scheme as artifacts), so the self-contained report and the serve UI can reference them. baseline_name is the YAML key into the baselines dir — what approve promotes the actual screenshot to.

evaluate_one(elements, a, exchanges=None, *, ctx=None)

Evaluate one assertion against the screen and the observed network.

The assertion's kind is guaranteed unique by scenario validation, so exactly one kind is set; dispatch is a _EVALUATORS lookup on that set field. Evaluation is total — a failed check returns a not-ok result rather than raising.

Parameters:

Name Type Description Default
elements list[Element]

One query() snapshot; the UI kinds (exists / value / label / count / enabled / disabled / selected) check it.

required
a Assertion

The assertion to evaluate.

required
exchanges list[NetworkExchange] | None

The network exchanges observed so far; the request / event / requestSequence kinds check these (None is treated as empty).

None
ctx EvalContext | None

The per-kind inputs (visual / schema / golden / clipboard); a kind whose input is absent fails cleanly rather than raising. None is an empty context (BE-0250).

None

Returns:

Type Description
AssertionResult

The single assertion's result.

Raises:

Type Description
AssertionError

The assertion has no kind set — scenario validation should have caught this.

passed(results)

True iff every assertion is ok (AND; one failure fails the step).

count_matching(exchanges, req)

How many observed exchanges satisfy the request matcher.

Shared by the request assertion and the until: { request } wait.

match_request(ex, req)

Whether one observed exchange satisfies a request matcher.

Shared by the request assertion and the web mock router, so a mock stubs exactly what an assertion would match.

Parameters:

Name Type Description Default
ex NetworkExchange

One observed network exchange.

required
req RequestMatch

The matcher; only its set (non-None) fields are checked, AND-ed together.

required

Returns:

Type Description
bool

True iff every set field of req matches ex.

request_label(req, *, with_count=True)

A compact human description of a request matcher (e.g. GET /items status=200).

Parameters:

Name Type Description Default
req RequestMatch

The request matcher to describe.

required
with_count bool

When False, the matcher's count is left out of the label — used where count is not part of the check (e.g. requestSequence, which is about order), so the label doesn't imply a field that is ignored.

True

Returns:

Type Description
str

The matcher's set fields joined into one space-separated line.