Skip to main content

jellyflow_runtime/runtime/conformance/scenario/
action.rs

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