///|
test "construct nested concurrent regions and preserve their order" {
let states = [
@state.State::new("Session", role=Composite),
@state.State::new("Idle", region="control", descriptions=["entry / log"]),
@state.State::new("History", region="control", role=DeepHistory),
@state.State::new("Listening", region="network"),
]
let view = @state.StateDiagram::new(
"session",
states,
[
@state.Transition::new(
"remember",
"Idle",
"History",
label="resume [ready] / log",
),
],
regions=[
@state.Region::new("root"),
@state.Region::new("control", owner="Session"),
@state.Region::new("network", owner="Session", separator=Vertical),
],
notes=[
@state.Note::new(
"detail",
"Description only",
targets=["Idle"],
region="control",
),
],
)
states.clear()
assert_eq(view.states.length(), 4)
assert_eq(view.regions[1].members, ["Idle", "History"])
assert_eq(view.regions[2].separator, Vertical)
assert_eq(@state.validate(view), [])
assert_eq(view.with_direction(RL).transitions, view.transitions)
}///|
test "reject invalid references and distinguish exhausted validation" {
let view = @state.StateDiagram::new("invalid", [@state.State::new("A")], [
@state.Transition::new("missing", "A", "B"),
])
assert_true(
@state.validate(view).any(d => d.code == "state/missing-endpoint"),
)
assert_eq(@state.validate(view, work_limit=1)[0].code, "state/work-limit")
assert_eq(@state.fresh_id("A", ["A", "A:1"]).unwrap(), "A:2")
}pub struct Note {
id : String
text : String
targets : ReadOnlyArray[String]
connection_targets : ReadOnlyArray[String]
placement : String
region : String
origin : SourceBinding?
} derive(Eq, Debug)fn Note::new(id : String, text : String, targets? : ArrayView[String], connection_targets? : ArrayView[String], placement? : String, region? : String, origin? : SourceBinding) -> Notepub struct Region {
id : String
owner : String?
members : ReadOnlyArray[String]
separator : Separator
direction : Direction?
origin : SourceBinding?
} derive(Eq, Debug)pub struct State {
id : String
label : String
region : String
role : Role
descriptions : ReadOnlyArray[String]
expanded : Bool
direction : Direction?
origin : SourceBinding?
} derive(Eq, Debug)fn StateDiagram::new(id : String, states : ArrayView[State], transitions : ArrayView[Transition], regions? : ArrayView[Region], notes? : ArrayView[Note], direction? : Direction, title? : String, accessibility_title? : String, accessibility_description? : String) -> StateDiagrampub struct Transition {
id : String
source : String
target : String
label : String
style : LineStyle
source_marker : Marker
target_marker : Marker
min_length : Int
direction : FlowDirection
direction_hint : Direction?
origin : SourceBinding?
} derive(Eq, Debug)fn Transition::new(id : String, source : String, target : String, label? : String, style? : LineStyle, source_marker? : Marker, target_marker? : Marker, min_length? : Int, direction_hint? : Direction, origin? : SourceBinding) -> Transitionfn fresh_id(stem : String, used : ArrayView[String], work_limit? : Int) -> Result[String, Diagnostic]fn validate(model : StateDiagram, nodes_limit? : Int, edges_limit? : Int, regions_limit? : Int, depth_limit? : Int, diagnostics_limit? : Int, work_limit? : Int) -> ReadOnlyArray[Diagnostic]