Skip to main content

jellyflow_runtime/runtime/conformance/scenario/
action.rs

1use serde::{Deserialize, Serialize};
2
3mod authoring;
4mod connection;
5mod graph;
6mod layout_facts;
7mod node;
8mod rendering;
9mod selection;
10mod viewport;
11
12pub use connection::ConformanceConnectionTargetFromHandlesInput;
13pub use layout_facts::{
14    ConformanceEdgeEndpointPosition, ConformanceLayoutEdgePosition,
15    ConformanceLayoutEdgeRouteFacts, ConformanceLayoutFactsConnectionTargetExpectation,
16    ConformanceLayoutFactsExpectation,
17};
18
19use crate::io::NodeGraphKeyCode;
20use crate::runtime::auto_pan::{AutoPanRequest, SelectionAutoPanRequest};
21use crate::runtime::connection::{
22    ConnectEdgeRequest, ConnectionEndIntent, ConnectionLifecycleResult, ConnectionTargetInput,
23    ReconnectEdgeRequest, ResolvedConnectionTarget,
24};
25use crate::runtime::drag::{NodeNudgeRequest, PointerGestureClaim};
26use crate::runtime::events::{ConnectStart, NodeGraphGestureEvent};
27use crate::runtime::measurement::NodeMeasurement;
28use crate::runtime::rendering::RenderingQueryResult;
29use crate::runtime::resize::{NodePointerResizeRequest, NodeResizeRequest};
30use crate::runtime::selection::NodePointerDownInput;
31use crate::runtime::selection::SelectionBoxInput;
32use crate::runtime::viewport::{
33    ViewportAnimationFrame, ViewportAnimationPlan, ViewportAnimationRequest,
34    ViewportDoubleClickZoomInput, ViewportDragPanInput, ViewportGestureContext,
35    ViewportGestureRejection, ViewportPanInertiaFrame, ViewportPanInertiaRequest,
36    ViewportPanRequest, ViewportScrollInput, ViewportZoomRequest,
37};
38use crate::schema::NodeActionDescriptor;
39use jellyflow_core::core::{CanvasPoint, CanvasSize, EdgeId, GroupId, NodeId};
40use jellyflow_core::ops::GraphTransaction;
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[allow(clippy::large_enum_variant)]
44#[serde(tag = "kind", content = "data", rename_all = "snake_case")]
45pub enum ConformanceAction {
46    /// Applies a raw graph transaction through the store dispatch pipeline.
47    ///
48    /// Use this for low-level graph fixture setup or graph-operation conformance. Adapter feel
49    /// fixtures should prefer the richer runtime actions such as `ApplyNodeDrag`,
50    /// `ApplyConnectEdge`, `ApplyReconnectEdge`, and delete/viewport actions so the fixture locks
51    /// the same interaction boundary an adapter should call.
52    DispatchTransaction {
53        transaction: GraphTransaction,
54    },
55    ApplyNodeDrag {
56        node: NodeId,
57        to: CanvasPoint,
58    },
59    ApplyNodeDragSession {
60        node: NodeId,
61        start: CanvasPoint,
62        to: CanvasPoint,
63    },
64    AssertNodePosition {
65        node: NodeId,
66        expected: CanvasPoint,
67    },
68    ApplyNodeResize {
69        request: NodeResizeRequest,
70    },
71    ApplyNodePointerResize {
72        request: NodePointerResizeRequest,
73    },
74    ApplyNodePointerResizeSession {
75        request: NodePointerResizeRequest,
76    },
77    ApplyNodePointerDown {
78        input: NodePointerDownInput,
79        #[serde(default, skip_serializing_if = "Option::is_none")]
80        expected_claim: Option<PointerGestureClaim>,
81    },
82    ApplySelectionBox {
83        input: SelectionBoxInput,
84    },
85    AssertConnectionTarget {
86        input: ConnectionTargetInput,
87        expected: ResolvedConnectionTarget,
88    },
89    AssertConnectionTargetFromHandles {
90        input: ConformanceConnectionTargetFromHandlesInput,
91        expected: ResolvedConnectionTarget,
92    },
93    AssertConnectionLifecycle {
94        start: ConnectStart,
95        #[serde(default, skip_serializing_if = "Option::is_none")]
96        hover: Option<ResolvedConnectionTarget>,
97        intent: ConnectionEndIntent,
98        expected: ConnectionLifecycleResult,
99    },
100    ApplyConnectEdge {
101        request: ConnectEdgeRequest,
102    },
103    ApplyConnectEdgeSession {
104        start: ConnectStart,
105        request: ConnectEdgeRequest,
106    },
107    ApplyReconnectEdge {
108        request: ReconnectEdgeRequest,
109    },
110    ApplyNodeNudge {
111        request: NodeNudgeRequest,
112    },
113    ApplyDeleteSelection,
114    ApplyDeleteSelectionForKey {
115        key: NodeGraphKeyCode,
116    },
117    ApplyAutoPan {
118        request: AutoPanRequest,
119    },
120    ApplySelectionAutoPan {
121        request: SelectionAutoPanRequest,
122    },
123    ReportNodeMeasurement {
124        measurement: NodeMeasurement,
125    },
126    AssertLayoutFacts {
127        viewport_size: CanvasSize,
128        expected: ConformanceLayoutFactsExpectation,
129    },
130    ApplyViewportPan {
131        request: ViewportPanRequest,
132    },
133    ApplyViewportPanConstrained {
134        request: ViewportPanRequest,
135        viewport_size: CanvasSize,
136    },
137    ApplyViewportZoom {
138        request: ViewportZoomRequest,
139    },
140    ApplyViewportZoomConstrained {
141        request: ViewportZoomRequest,
142        viewport_size: CanvasSize,
143    },
144    ApplyViewportAnimationFrame {
145        request: ViewportAnimationRequest,
146        elapsed_seconds: f32,
147    },
148    ApplyViewportAnimationFrames {
149        request: ViewportAnimationRequest,
150        elapsed_seconds: Vec<f32>,
151    },
152    AssertViewportAnimationFrame {
153        request: ViewportAnimationRequest,
154        elapsed_seconds: f32,
155        expected: ViewportAnimationFrame,
156    },
157    ApplyViewportPanInertiaFrame {
158        request: ViewportPanInertiaRequest,
159        elapsed_seconds: f32,
160    },
161    ApplyViewportPanInertiaFrames {
162        request: ViewportPanInertiaRequest,
163        elapsed_seconds: Vec<f32>,
164    },
165    AssertViewportPanInertiaFrame {
166        request: ViewportPanInertiaRequest,
167        elapsed_seconds: f32,
168        expected: ViewportPanInertiaFrame,
169    },
170    ExpectViewportPanInertiaRejected {
171        request: ViewportPanInertiaRequest,
172    },
173    AssertViewportDoubleClickZoom {
174        input: ViewportDoubleClickZoomInput,
175        #[serde(default, skip_serializing_if = "Option::is_none")]
176        expected: Option<ViewportAnimationPlan>,
177        #[serde(default, skip_serializing_if = "Option::is_none")]
178        expect_rejection: Option<ViewportGestureRejection>,
179    },
180    ApplyViewportScrollGesture {
181        context: ViewportGestureContext,
182        input: ViewportScrollInput,
183        #[serde(default, skip_serializing_if = "Option::is_none")]
184        expect_rejection: Option<ViewportGestureRejection>,
185    },
186    ApplyViewportDragPanGesture {
187        context: ViewportGestureContext,
188        input: ViewportDragPanInput,
189        #[serde(default, skip_serializing_if = "Option::is_none")]
190        expect_rejection: Option<ViewportGestureRejection>,
191    },
192    ApplyViewportDragPanSession {
193        context: ViewportGestureContext,
194        input: ViewportDragPanInput,
195        #[serde(default, skip_serializing_if = "Option::is_none")]
196        expect_rejection: Option<ViewportGestureRejection>,
197    },
198    SetViewport {
199        pan: CanvasPoint,
200        zoom: f32,
201    },
202    AssertRenderingQuery {
203        viewport_size: CanvasSize,
204        expected: RenderingQueryResult,
205    },
206    SetSelection {
207        nodes: Vec<NodeId>,
208        edges: Vec<EdgeId>,
209        groups: Vec<GroupId>,
210    },
211    EmitGesture {
212        event: NodeGraphGestureEvent,
213    },
214    AssertNodeActionAvailability {
215        action: NodeActionDescriptor,
216        #[serde(default)]
217        expect_enabled: bool,
218    },
219}
220
221impl ConformanceAction {
222    pub fn kind(&self) -> &'static str {
223        graph::kind(self)
224            .or_else(|| authoring::kind(self))
225            .or_else(|| node::kind(self))
226            .or_else(|| selection::kind(self))
227            .or_else(|| connection::kind(self))
228            .or_else(|| layout_facts::kind(self))
229            .or_else(|| viewport::kind(self))
230            .or_else(|| rendering::kind(self))
231            .expect("all conformance action variants must have a kind")
232    }
233}