Getting Started
This guide will walk you through creating your first EventFlow file.
Your First Flow
Create a file named order.flow:
machine: @order
scenario: simple checkout
on> :checkout from @customer
order moves to #awaiting_payment
on :payment_received
order moves to #paid
expect:
= order is in #paidThat's it! You've defined a state machine with:
- Two states:
#awaiting_paymentand#paid - Two events:
:checkoutand:payment_received - A test assertion
Understanding the Structure
Let's break down each part:
Machine Declaration
machine: @orderThis declares an actor named @order. The @ prefix indicates this is an actor (machine). Every .flow file starts with a machine declaration.
Scenario
scenario: simple checkoutA scenario groups related event handlers. Think of it as a feature or capability of your machine.
Event Handlers
on> :checkout from @customer
order moves to #awaiting_paymenton>- This is an API endpoint (externally accessible):checkout- The event name (:prefix)from @customer- Who can send this eventorder moves to #awaiting_payment- State transition (#prefix for states)
Internal Events
on :payment_received
order moves to #paidWithout the > prefix, this event is internal - it can only be received from other machines, not called directly as an API.
Assertions
expect:
= order is in #paidThe expect: block defines test assertions. The = prefix marks assertion lines.
Adding Guards
Guards are conditions that must be true for an action to execute:
machine: @order
scenario: checkout with validation
on> :checkout from @customer
? cart is not empty
order moves to #awaiting_payment
emit :payment_request to @payment
?
emit :error to @customer?prefix introduces a guard (condition)- Empty
?acts as "otherwise" (else case)
You can also use the otherwise keyword:
on> :checkout from @customer
? cart is not empty
order moves to #awaiting_payment
otherwise
emit :empty_cart_error to @customerWorking with Context
Context holds your machine's data:
machine: @cart
scenario: add items
on> :add_item from @customer
$items adds $item
$total increases by $item.price
$item_count increases by 1
on> :remove_item from @customer
$items removes $item
$total decreases by $item.price
$item_count decreases by 1
on> :clear_cart from @customer
$items becomes empty
$total becomes 0
$item_count becomes 0$prefix indicates context variables- Natural language operations:
adds,removes,increases by,becomes
Communicating Between Machines
Machines communicate through events:
machine: @order
scenario: checkout flow
on> :checkout from @customer
order moves to #awaiting_payment
emit :payment_request to @payment // Send to payment machine
on :payment_success from @payment // Receive from payment machine
order moves to #paid
emit :confirmation to @customerThe emit keyword sends events to other machines. The runtime automatically handles event routing and correlation.
Adding Test Setup
Use given: blocks to set up test scenarios:
machine: @order
scenario: checkout with items
given:
@customer is logged in
cart contains:
| product | price |
| Laptop | 1200 |
| Mouse | 25 |
$total is 1225
on> :checkout from @customer
? cart is not empty
order moves to #awaiting_payment
expect:
= order is in #awaiting_paymentRunning Your Flow
Run Tests
eventflow test order.flowGenerate Diagrams
eventflow diagram order.flowValidate Syntax
eventflow validate order.flowComplete Example
Here's a complete order flow with all concepts:
machine: @order
scenario: complete checkout
given:
@customer is logged in as "[email protected]"
cart has items
$total: number is 1200
on> :checkout from @customer
? cart is not empty
? $total > 0
order moves to #awaiting_payment
emit :payment_request to @payment
with $total
otherwise
emit :zero_total_error to @customer
otherwise
emit :empty_cart_error to @customer
expect:
= order is in #awaiting_payment
on :payment_success from @payment
order moves to #paid
$paid_at becomes now
emit :order_confirmed to @customer
emit :prepare_shipment to @warehouse
on :payment_failed from @payment
order moves to #payment_failed
emit :payment_retry to @customer
expect:
= order is in #paid
= @customer received :order_confirmed