Assert event order and workflow behavior across ROS topics, services, and actions.
Build event descriptors with message/1, service_call/1, goal/1,
feedback/1, and result/1. Pass them to expect_sequence/1,
expect_before/2, expect_after/2, expect_together/1, or
expect_workflow/1 to query the scenario's unified event log.
Summary
Functions
Assert that event described by later_spec occurred after earlier_spec.
Assert that event described by first_spec occurred before second_spec.
Assert that a sequence of events happens in arrival order across any mix of topics, services, and actions.
Assert that all given event descriptors are eventually satisfied in any order.
Assert a cause-and-effect workflow described as a keyword list.
Descriptor for feedback published by action action_name.
Descriptor for a goal submitted to action action_name.
Descriptor for a message arriving on topic.
Descriptor for a result produced by action action_name.
Descriptor for a service call received on service_name.
Functions
@spec expect_after( RclexTesting.DSL.Events.EventSpec.t(), RclexTesting.DSL.Events.EventSpec.t(), keyword() ) :: {struct(), struct()}
Assert that event described by later_spec occurred after earlier_spec.
Inverse of expect_before/2 — a readability alias. Returns
{earlier_payload, later_payload}.
expect_after(
message("/robot/state", matches(%{mode: :completed})),
message("/robot/state", matches(%{mode: :running}))
)
@spec expect_before( RclexTesting.DSL.Events.EventSpec.t(), RclexTesting.DSL.Events.EventSpec.t(), keyword() ) :: {struct(), struct()}
Assert that event described by first_spec occurred before second_spec.
Both events are awaited in order; this guarantees first was logged before
second. Returns {first_payload, second_payload}.
expect_before(
service_call("/safety/check"),
message("/robot/state", matches(%{mode: :running}))
)
@spec expect_sequence([RclexTesting.DSL.Events.EventSpec.t()]) :: [struct()]
Assert that a sequence of events happens in arrival order across any mix of topics, services, and actions.
Each element is an event descriptor from message/1,2, service_call/1,2,
goal/1,2, feedback/1,2, or result/1,2. Every event must arrive
strictly after the previous one (based on the global event log).
Returns the list of matched payloads in sequence order.
watch "/mission/start", MissionStart
watch "/robot/state", RobotState
mock_service "/safety/check", SafetyCheck, fn _ -> %SafetyCheck.Response{allowed: true} end
mock_action "/navigate", Navigate, fn _goal, _fb -> %Navigate.Result{success: true} end
expect_sequence [
message("/mission/start"),
service_call("/safety/check"),
goal("/navigate"),
result("/navigate", fn r -> r.success end),
message("/robot/state", matches(%{mode: :completed}))
]
@spec expect_together( [RclexTesting.DSL.Events.EventSpec.t()], keyword() ) :: [struct()]
Assert that all given event descriptors are eventually satisfied in any order.
Passes as soon as every condition has been observed (at least once). Each event in the log can satisfy at most one descriptor (greedy left-to-right matching). Returns the list of matched payloads in descriptor order.
expect_together [
message("/robot/state", matches(%{mode: :running})),
message("/battery/state", matches(%{charging: false}))
]
Assert a cause-and-effect workflow described as a keyword list.
:given defines the trigger event; each :then defines a subsequent step.
Internally compiled to expect_sequence/1. Returns all matched payloads.
expect_workflow [
given: message("/mission/start"),
then: message("/robot/state", matches(%{mode: :running})),
then: message("/robot/state", matches(%{mode: :completed}))
]
@spec feedback(String.t(), (struct() -> boolean())) :: RclexTesting.DSL.Events.EventSpec.t()
Descriptor for feedback published by action action_name.
feedback("/navigate")
feedback("/navigate", fn fb -> fb.progress >= 50 end)
@spec goal(String.t(), (struct() -> boolean())) :: RclexTesting.DSL.Events.EventSpec.t()
Descriptor for a goal submitted to action action_name.
The action must already be mocked via mock_action/3.
goal("/navigate")
goal("/navigate", fn g -> g.x > 0 end)
@spec message(String.t(), (struct() -> boolean())) :: RclexTesting.DSL.Events.EventSpec.t()
Descriptor for a message arriving on topic.
Use as a building block for expect_sequence/1, expect_before/2, etc.
The topic must already be watched via watch/2 (or expect/3) before the
sequence assertion runs.
message("/mission/start")
message("/robot/state", &(&1.mode == :running))
message("/robot/state", matches(%{mode: :running}))
@spec result(String.t(), (struct() -> boolean())) :: RclexTesting.DSL.Events.EventSpec.t()
Descriptor for a result produced by action action_name.
result("/navigate")
result("/navigate", fn r -> r.success end)
@spec service_call(String.t(), (struct() -> boolean())) :: RclexTesting.DSL.Events.EventSpec.t()
Descriptor for a service call received on service_name.
The service must already be mocked via mock_service/3.
service_call("/safety/check")
service_call("/safety/check", fn req -> req.robot_id == "r1" end)