Skip to content

Assertions

Assertions verify that your machine behaves correctly. They're marked with the = prefix and appear in expect: blocks.

Basic Syntax

flow
expect:
  = order is in #paid
  = $total equals 1200
  = @customer received :confirmation

State Assertions

Current State

flow
expect:
  = order is in #paid
  = order is in #awaiting_payment
  = application is in #pending

Not in State

flow
expect:
  = order is not in #cancelled
  = order is not in #failed

State History

flow
expect:
  = order has entered #processing
  = order has been in #pending
  = order has never been in #cancelled

Context Assertions

Equality

flow
expect:
  = $total equals 1200
  = $status equals "active"
  = $is_premium equals true

Comparisons

flow
expect:
  = $total is greater than 100
  = $total is less than 2000
  = $total is at least 100
  = $total is at most 500
  = $discount is between 10 and 50

Not Equal

flow
expect:
  = $status is not "cancelled"
  = $retry_count is not 0

Empty/Not Empty

flow
expect:
  = $customer_name is not empty
  = $errors is empty
  = $items is not empty

Collection Assertions

Contains

flow
expect:
  = $items contains "Laptop"
  = $tags contains "urgent"
  = $roles contains "admin"

Count

flow
expect:
  = $items has 3 items
  = $items_count equals 3
  = $errors has 0 items

Empty/Not Empty

flow
expect:
  = $items is not empty
  = $errors is empty
  = $cart has items

Event Assertions

Event Received

flow
expect:
  = @customer received :order_confirmed
  = @payment received :refund_request
  = @warehouse received :ship_order

Event Emitted

flow
expect:
  = :payment_request was emitted to @payment
  = :notification was sent to @customer

Event Not Received

flow
expect:
  = @customer did not receive :error
  = :refund was not emitted

Event with Data

flow
expect:
  = @payment received :payment_request with $total
  = :order_confirmed was emitted with order_id: $order_id

Boolean Assertions

flow
expect:
  = $is_active is true
  = $is_cancelled is false
  = $has_discount is true

Timestamp Assertions

flow
expect:
  = $created_at is not empty
  = $updated_at is after $created_at
  = $completed_at is today

Negation

Use not or is not for negative assertions:

flow
expect:
  = order is not in #cancelled
  = $total is not 0
  = $items does not contain "Expired Item"
  = @customer did not receive :error

Multiple Assertions

All assertions in an expect: block must pass:

flow
expect:
  = order is in #paid              // AND
  = $total equals 1200             // AND
  = @customer received :confirmation  // AND
  = $items has 3 items             // All must pass

Event-Level vs Scenario-Level

Event-Level (after specific event)

flow
on> :checkout from @customer
  order moves to #awaiting_payment

  expect:
    = order is in #awaiting_payment    // Checked after :checkout

Scenario-Level (after all events)

flow
scenario: complete purchase

  on> :checkout from @customer
    ...

  on :payment_success from @payment
    ...

  expect:
    = order is in #paid               // Checked after all events

Assertion Patterns

Verify State Transition

flow
scenario: order payment

  given:
    order is in #pending

  on> :payment_received from @payment
    order moves to #paid

  expect:
    = order is not in #pending
    = order is in #paid

Verify Context Update

flow
scenario: apply discount

  given:
    $total: number is 100
    $discount: number is 0

  on> :apply_coupon from @customer
    $discount becomes 10
    $total decreases by $discount

  expect:
    = $discount equals 10
    = $total equals 90

Verify Event Communication

flow
scenario: order triggers payment

  on> :checkout from @customer
    emit :payment_request to @payment

  expect:
    = :payment_request was emitted to @payment
    = @payment received :payment_request

Verify Error Handling

flow
scenario: handle invalid cart

  given:
    cart is empty

  on> :checkout from @customer
    ? cart is empty
      emit :checkout_error to @customer

  expect:
    = order is not in #processing
    = @customer received :checkout_error

Custom Assertions

For complex assertions, use natural language that maps to bindings:

flow
expect:
  = payment was processed successfully
  = inventory was updated correctly
  = email was sent to customer

These map to custom assertion classes in your binding code.

Assertion Debugging

When assertions fail, you get detailed output:

✗ order is in #paid
  Expected: #paid
  Actual:   #awaiting_payment

  Event trace:
    1. :checkout → #awaiting_payment
    2. :payment_failed → #awaiting_payment (no transition)

Best Practices

Be Specific

flow
// Good - specific
expect:
  = $total equals 1200
  = order is in #paid

// Avoid - vague
expect:
  = order is valid
  = everything worked

Test What Matters

flow
// Good - testing the outcome
expect:
  = order is in #paid
  = @customer received :confirmation

// Avoid - testing implementation details
expect:
  = internal_counter equals 5
  = temp_flag is true

Cover Edge Cases

flow
scenario: empty cart checkout

  given:
    cart is empty

  on> :checkout from @customer
    ...

  expect:
    = order is not in #paid
    = @customer received :empty_cart_error
flow
expect:
  // State assertions
  = order is in #completed

  // Context assertions
  = $total equals 1200
  = $items_count equals 3

  // Event assertions
  = @customer received :confirmation
  = @warehouse received :ship_order

Released under the MIT License.