Syntax Reference
Complete syntax patterns for EventFlow.
File Structure
flow
machine: @machine_name
scenario: scenario name
given:
// setup
on> :event from @actor
// actions
// guards
// emit
expect:
// assertions
on :event from @actor
// ...
expect:
// scenario assertionsMachine Definition
flow
machine: @nameExamples:
flow
machine: @order
machine: @payment
machine: @customerSystem Definition
flow
system: system name
uses:
@machine1 from "./path/to/machine1.flow"
@machine2 from "./path/to/machine2.flow"
machine: @machine3
// Can also define inlineScenario Definition
flow
scenario: descriptive name
// optional given
given:
// setup
// event handlers
on> :event from @actor
// ...
// optional assertions
expect:
// ...Event Handlers
API Event (Public)
flow
on> :event_name from @actor
// actionsInternal Event
flow
on :event_name from @actor
// actionsWithout Source Filter
flow
on :event_name
// accepts from any senderActions
Actions are lines without prefix.
State Transitions
flow
order moves to #state
order transitions to #state
order enters #state
order becomes #stateContext Updates
flow
$variable becomes value
$variable: type becomes value
$variable increases by amount
$variable decreases by amount
$variable adds item
$variable removes item
$variable clearsEvent Emission
flow
emit :event to @actor
emit :event to @actor
with $var1, $var2
emit :event to @actor
with:
| field | value |
| key1 | val1 |
| key2 | val2 |
emit :event to @actor
with:
| field | type | value |
| key1 | string | val1 |
| key2 | number | val2 |Custom Actions
flow
send confirmation email
process the payment
validate cart contents
notify warehouse teamGuards
Single Guard
flow
? condition
// runs if trueMultiple Guards (AND)
flow
? condition1
? condition2
// runs if BOTH trueOR Guards
flow
? condition1
?? condition2
// runs if EITHER trueCombined Logic
flow
? conditionA
? conditionB
?? conditionC
// runs if (A AND B) OR CDefault Case
flow
? condition1
handle 1
? condition2
handle 2
otherwise
handle defaultOr:
flow
? condition
handle condition
?
handle elseNested Guards
flow
? outer condition
? inner condition
// nested action
otherwise
// inner else
otherwise
// outer elseGiven Blocks
Scenario-Level
flow
scenario: name
given:
@actor is in state
$variable: type is value
collection contains itemsEvent-Level
flow
on> :event from @actor
given:
additional setupTable Data
flow
given:
cart contains:
| product | price | quantity |
| Laptop | 1200 | 1 |
| Mouse | 25 | 2 |Expect Blocks
Event-Level Assertions
flow
on> :event from @actor
// actions
expect:
= assertion1
= assertion2Scenario-Level Assertions
flow
scenario: name
on> :event1 ...
on :event2 ...
expect:
= final assertionsAssertion Patterns
flow
expect:
// State assertions
= order is in #paid
= order is not in #cancelled
// Context assertions
= $total equals 1200
= $items contains "Laptop"
= $count is greater than 0
// Event assertions
= @customer received :confirmation
= :payment_request was emitted to @paymentScheduled Events
flow
on :event_name
triggered: schedule expression
for each item in #state
? guard condition
// actionsSchedule Expressions
flow
triggered: every day at 00:00
triggered: every hour
triggered: every 30 minutes
triggered: every monday at 09:00
triggered: every month on 1st at 00:00Comments
flow
// Single line comment
/*
Multi-line
comment
*/
action // Inline commentData Tables
flow
table_name:
| column1 | column2 | column3 |
| value1 | value2 | value3 |
| value4 | value5 | value6 |With types:
flow
with:
| field | type | value |
| id | string | $id |
| count | number | $cnt |Context Variable Patterns
Declaration
flow
$name becomes value
$name: type becomes valueIn Guards
flow
? $total equals 100
? $total is 100
? $total is greater than 0
? $total is less than 1000
? $items contains "Laptop"
? $items is empty
? $items is not emptyIn Assertions
flow
= $total equals 100
= $items contains "Laptop"
= $count is greater than 0Indentation
EventFlow uses indentation for nesting. Use consistent spaces (2 or 4):
flow
machine: @order // Level 0
scenario: checkout // Level 1
given: // Level 2
@customer is logged in // Level 3
on> :checkout from @customer // Level 2
? cart is valid // Level 3
order moves to #processing // Level 4
emit :request to @payment // Level 4
otherwise // Level 3
emit :error to @customer // Level 4
expect: // Level 2
= order is in #processing // Level 3Complete Example
flow
machine: @order
scenario: complete checkout
given:
@customer is logged in as "[email protected]"
cart contains:
| product | price |
| Laptop | 1200 |
$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:
| order_id | string | $order_id |
| amount | number | $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
on :payment_failed from @payment
$retry_count increases by 1
? $retry_count < 3
emit :payment_request to @payment
otherwise
order moves to #failed
emit :order_failed to @customer
expect:
= order is in #paid
= @customer received :order_confirmedTest File Syntax (.test.flow)
Test files contain variations of the happy path defined in .flow files.
Test File Structure
flow
test: @machine_name
for scenario: scenario name
for :event:
test name:
// variations + assertions
test name:
// path divergence + assertionsTransition Tests
Target specific event handlers with for :event::
flow
test: @order
for scenario: checkout
for :checkout:
empty cart rejected:
with scenario:
cart is empty
= @customer received :error
payment declined:
assume:
? payment successful = false
= order is in #payment_failedScenario Tests (Path Divergence)
Test full flow variations with after/receive/then:
flow
test: @order
for scenario: checkout
payment fails:
after :checkout
receive :payment_failed from @payment
= order is in #payment_failed
retry then succeed:
after :checkout
receive :payment_failed from @payment
then :payment_success from @payment
= order is in #paidVariation Sources
flow
// Override scenario-level given
with scenario:
cart is empty
// Override event data
with event:
payment_method is "bank_transfer"
// Override event-level given
with given:
shipping_address is invalid
// Override context variables
with context:
$total is 5000assume: System
Control guard and action behavior in tests:
flow
assume:
// Force guard result
? cart is valid = false
// Action returns value
process payment returns { transaction_id: "TXN-123" }
// Action throws error
send email throws "SMTP error"observe: System
Watch actions without changing behavior:
flow
observe:
send confirmation email
update inventory
= send confirmation email was called
= send confirmation email was called with:
to: @customer.email
= update inventory was not calledSystem Test Syntax
For machine systems, target specific machines:
flow
test: system checkout
for scenario: complete purchase
for :checkout to @order:
guest rejected:
with scenario:
@customer is not logged in
= @customer received :login_required
for :payment_request to @payment:
gateway down:
assume:
@payment.process throws "Unavailable"
= @order is in #payment_failed