1#![allow(clippy::missing_const_for_fn)]
2#![allow(clippy::missing_fields_in_debug)]
3#![allow(clippy::struct_excessive_bools)]
4#![allow(clippy::many_single_char_names)]
5#![allow(clippy::too_many_arguments)]
6#![allow(clippy::should_implement_trait)]
7#![allow(clippy::trivially_copy_pass_by_ref)]
8#![allow(clippy::fn_params_excessive_bools)]
9#![allow(clippy::type_complexity)]
10#![allow(clippy::match_same_arms)]
11#![allow(clippy::unreadable_literal)]
12#![allow(clippy::manual_clamp)]
13#![allow(clippy::unnecessary_wraps)]
14#![allow(clippy::match_like_matches_macro)]
15#![allow(clippy::struct_field_names)]
16#![allow(clippy::needless_pass_by_value)]
17#![allow(clippy::cast_possible_wrap)]
18pub mod accessibility;
65pub mod animation;
66pub mod binding;
67pub mod cache;
68mod canvas;
69pub mod chart;
70pub mod clipboard;
71mod color;
72mod constraints;
73pub mod diff;
74pub mod dnd;
75pub mod draw;
76mod event;
77mod geometry;
78pub mod gesture;
79pub mod history;
80pub mod lifecycle;
81mod runtime;
82pub mod shortcut;
83pub mod simd;
84
85pub use simd::{
87 batch_mean_f64, batch_min_max_f64, batch_scale_f64, batch_scale_offset_f64, batch_stddev_f64,
88 batch_sum_f64, batch_variance_f64, histogram_f64, normalize_f64, normalize_with_range_f64,
89 percentile_sorted_f64, weighted_sum_f64,
90};
91mod state;
92pub mod streaming;
93pub mod theme;
94pub mod validation;
95pub mod virtualization;
96pub mod widget;
97
98pub mod brick_types;
100
101pub mod brick_widget;
103
104pub use accessibility::{
105 AccessibilityTree, AccessibilityTreeBuilder, AccessibleNode, AccessibleNodeId, CheckedState,
106 HitTester, LiveRegion,
107};
108pub use animation::{
109 AnimColor, AnimatedValue, AnimationController, EasedValue, Easing, Interpolate, Keyframe,
110 KeyframeTrack, Spring, SpringConfig,
111};
112pub use cache::{
113 CacheBuilder, CacheCallback, CacheConfig, CacheEvent, CacheKey, CacheMetadata, CacheOptions,
114 CacheSize, CacheState, CacheStats, DataCache, StringCache,
115};
116pub use canvas::RecordingCanvas;
117pub use chart::{
118 ArcGeometry, CatmullRom, CubicBezier, CubicSpline, DataNormalizer, DrawBatch, HistogramBins,
119 Interpolator, LinearInterpolator, PathTessellator, Point2D,
120};
121pub use clipboard::{
122 Clipboard, ClipboardData, ClipboardEvent, ClipboardFormat, ClipboardHistory,
123 ClipboardOperation, ClipboardResult,
124};
125pub use color::{Color, ColorParseError};
126pub use constraints::Constraints;
127pub use diff::{diff_trees, DiffNode, DiffOp, DiffResult, TreeDiffer, WidgetKey};
128pub use dnd::{
129 DragData, DragDataType, DragDropManager, DragId, DragPayload, DragPhase, DragState, DropEffect,
130 DropResult, DropTarget,
131};
132pub use draw::{
133 BoxStyle, DrawCommand, FillRule, LineCap, LineJoin, PathRef, Sampling, Shadow, StrokeStyle,
134 TensorRef, Transform2D as DrawTransform,
135};
136pub use event::{Event, GestureState, Key, MouseButton, PointerId, PointerType, TouchId};
137pub use geometry::{CornerRadius, Point, Rect, Size};
138pub use gesture::{
139 GestureConfig, GestureRecognizer, PointerGestureRecognizer, PointerInfo, RecognizedGesture,
140 TouchPoint,
141};
142pub use history::{
143 Checkpoint, CheckpointId, Command as HistoryCommand, CommandHistory, CommandId, CommandResult,
144 CompositeCommand, GroupId, HistoryCallback, HistoryConfig, HistoryEvent, SetValueCommand,
145};
146pub use lifecycle::{
147 Effect, EffectManager, HookId, LifecycleEvent, LifecycleManager, LifecyclePhase,
148};
149pub use runtime::{
150 default_executor, AnimatedProperty, AnimationId, AnimationInstance, AnimationState, Animator,
151 CommandExecutor, DataRefreshManager, EasingFunction, ExecutionResult, ExecutorConfig,
152 FocusDirection, FocusManager, FocusTrap, FrameTimer, MemoryRouter, MemoryStorage, RefreshTask,
153 Router, SpringAnimation, Storage, Timer, TransitionConfig, Tween,
154};
155pub use shortcut::{
156 Modifiers, Shortcut, ShortcutBuilder, ShortcutContext, ShortcutId, ShortcutManager,
157 ShortcutPriority,
158};
159pub use state::{Command, CounterMessage, CounterState, State, Store};
160pub use streaming::{
161 ConnectionState, DataStream, MessageBuffer, RateLimiter, ReconnectConfig, StreamConfig,
162 StreamMessage, StreamSubscription,
163};
164pub use theme::{ColorPalette, ContrastCheck, Radii, Shadows, Spacing, Theme, Typography};
165pub use validation::{
166 FieldConfig, FieldState, FormValidator, MaxLength, MinLength, Pattern, PatternType, Range,
167 Required, ValidateOn, ValidationResult, Validator,
168};
169pub use virtualization::{
170 CellLayout, GridCell, ItemIndex, ItemLayout, ScrollAlign, VirtualGrid, VirtualGridConfig,
171 VirtualList, VirtualListConfig, VisibleGridRange, VisibleRange,
172};
173pub use widget::{
174 AccessibleRole, Canvas, FontStyle, FontWeight, LayoutResult, TextStyle, Transform2D, TypeId,
175 Widget, WidgetId,
176};
177
178pub use widget::{
180 Brick, BrickAssertion, BrickBudget, BrickError, BrickPhase, BrickResult, BrickVerification,
181 BudgetViolation,
182};
183
184pub use brick_widget::{BrickWidgetExt, DefaultBrick, SimpleBrick};
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190
191 mod color_tests {
196 use super::*;
197 use proptest::prelude::*;
198
199 #[test]
200 fn test_color_new_clamps_values() {
201 let c = Color::new(1.5, -0.5, 0.5, 2.0);
202 assert_eq!(c.r, 1.0);
203 assert_eq!(c.g, 0.0);
204 assert_eq!(c.b, 0.5);
205 assert_eq!(c.a, 1.0);
206 }
207
208 #[test]
209 fn test_color_from_rgb() {
210 let c = Color::rgb(0.5, 0.5, 0.5);
211 assert_eq!(c.r, 0.5);
212 assert_eq!(c.g, 0.5);
213 assert_eq!(c.b, 0.5);
214 assert_eq!(c.a, 1.0);
215 }
216
217 #[test]
218 fn test_color_from_hex() {
219 let c = Color::from_hex("#ff0000").unwrap();
220 assert_eq!(c.r, 1.0);
221 assert_eq!(c.g, 0.0);
222 assert_eq!(c.b, 0.0);
223
224 let c2 = Color::from_hex("#00ff00").unwrap();
225 assert_eq!(c2.g, 1.0);
226
227 let c3 = Color::from_hex("0000ff").unwrap();
228 assert_eq!(c3.b, 1.0);
229 }
230
231 #[test]
232 fn test_color_from_hex_with_alpha() {
233 let c = Color::from_hex("#ff000080").unwrap();
234 assert_eq!(c.r, 1.0);
235 assert!((c.a - 0.502).abs() < 0.01); }
237
238 #[test]
239 fn test_color_from_hex_invalid() {
240 assert!(Color::from_hex("invalid").is_err());
241 assert!(Color::from_hex("#gg0000").is_err());
242 assert!(Color::from_hex("#ff").is_err());
243 }
244
245 #[test]
246 fn test_color_relative_luminance_black() {
247 let black = Color::rgb(0.0, 0.0, 0.0);
248 assert_eq!(black.relative_luminance(), 0.0);
249 }
250
251 #[test]
252 fn test_color_relative_luminance_white() {
253 let white = Color::rgb(1.0, 1.0, 1.0);
254 assert!((white.relative_luminance() - 1.0).abs() < 0.001);
255 }
256
257 #[test]
258 fn test_color_contrast_ratio_black_white() {
259 let black = Color::rgb(0.0, 0.0, 0.0);
260 let white = Color::rgb(1.0, 1.0, 1.0);
261 let ratio = black.contrast_ratio(&white);
262 assert!((ratio - 21.0).abs() < 0.1); }
264
265 #[test]
266 fn test_color_contrast_ratio_wcag_aa() {
267 let dark = Color::rgb(0.0, 0.0, 0.0);
269 let light = Color::rgb(0.5, 0.5, 0.5);
270 let ratio = dark.contrast_ratio(&light);
271 assert!(ratio >= 4.5, "Contrast ratio {ratio} should be >= 4.5");
272 }
273
274 #[test]
275 fn test_color_contrast_ratio_symmetric() {
276 let c1 = Color::rgb(0.2, 0.4, 0.6);
277 let c2 = Color::rgb(0.8, 0.6, 0.4);
278 assert_eq!(c1.contrast_ratio(&c2), c2.contrast_ratio(&c1));
279 }
280
281 #[test]
282 fn test_color_to_hex() {
283 let c = Color::rgb(1.0, 0.0, 0.0);
284 assert_eq!(c.to_hex(), "#ff0000");
285
286 let c2 = Color::new(0.0, 1.0, 0.0, 0.5);
287 assert_eq!(c2.to_hex_with_alpha(), "#00ff0080");
288 }
289
290 #[test]
291 fn test_color_lerp() {
292 let black = Color::rgb(0.0, 0.0, 0.0);
293 let white = Color::rgb(1.0, 1.0, 1.0);
294
295 let mid = black.lerp(&white, 0.5);
296 assert!((mid.r - 0.5).abs() < 0.001);
297 assert!((mid.g - 0.5).abs() < 0.001);
298 assert!((mid.b - 0.5).abs() < 0.001);
299 }
300
301 proptest! {
302 #[test]
303 fn prop_color_clamps_to_valid_range(r in -1.0f32..2.0, g in -1.0f32..2.0, b in -1.0f32..2.0, a in -1.0f32..2.0) {
304 let c = Color::new(r, g, b, a);
305 prop_assert!(c.r >= 0.0 && c.r <= 1.0);
306 prop_assert!(c.g >= 0.0 && c.g <= 1.0);
307 prop_assert!(c.b >= 0.0 && c.b <= 1.0);
308 prop_assert!(c.a >= 0.0 && c.a <= 1.0);
309 }
310
311 #[test]
312 fn prop_contrast_ratio_always_positive(
313 r1 in 0.0f32..1.0, g1 in 0.0f32..1.0, b1 in 0.0f32..1.0,
314 r2 in 0.0f32..1.0, g2 in 0.0f32..1.0, b2 in 0.0f32..1.0
315 ) {
316 let c1 = Color::rgb(r1, g1, b1);
317 let c2 = Color::rgb(r2, g2, b2);
318 prop_assert!(c1.contrast_ratio(&c2) >= 1.0);
319 }
320
321 #[test]
322 fn prop_lerp_at_zero_returns_self(r in 0.0f32..1.0, g in 0.0f32..1.0, b in 0.0f32..1.0) {
323 let c1 = Color::rgb(r, g, b);
324 let c2 = Color::rgb(1.0 - r, 1.0 - g, 1.0 - b);
325 let result = c1.lerp(&c2, 0.0);
326 prop_assert!((result.r - c1.r).abs() < 0.001);
327 prop_assert!((result.g - c1.g).abs() < 0.001);
328 prop_assert!((result.b - c1.b).abs() < 0.001);
329 }
330
331 #[test]
332 fn prop_lerp_at_one_returns_other(r in 0.0f32..1.0, g in 0.0f32..1.0, b in 0.0f32..1.0) {
333 let c1 = Color::rgb(r, g, b);
334 let c2 = Color::rgb(1.0 - r, 1.0 - g, 1.0 - b);
335 let result = c1.lerp(&c2, 1.0);
336 prop_assert!((result.r - c2.r).abs() < 0.001);
337 prop_assert!((result.g - c2.g).abs() < 0.001);
338 prop_assert!((result.b - c2.b).abs() < 0.001);
339 }
340 }
341 }
342
343 mod geometry_tests {
348 use super::*;
349 use proptest::prelude::*;
350
351 #[test]
352 fn test_point_new() {
353 let p = Point::new(10.0, 20.0);
354 assert_eq!(p.x, 10.0);
355 assert_eq!(p.y, 20.0);
356 }
357
358 #[test]
359 fn test_point_origin() {
360 let p = Point::ORIGIN;
361 assert_eq!(p.x, 0.0);
362 assert_eq!(p.y, 0.0);
363 }
364
365 #[test]
366 fn test_point_distance() {
367 let p1 = Point::new(0.0, 0.0);
368 let p2 = Point::new(3.0, 4.0);
369 assert!((p1.distance(&p2) - 5.0).abs() < 0.001);
370 }
371
372 #[test]
373 fn test_point_add() {
374 let p1 = Point::new(1.0, 2.0);
375 let p2 = Point::new(3.0, 4.0);
376 let sum = p1 + p2;
377 assert_eq!(sum.x, 4.0);
378 assert_eq!(sum.y, 6.0);
379 }
380
381 #[test]
382 fn test_point_sub() {
383 let p1 = Point::new(5.0, 7.0);
384 let p2 = Point::new(2.0, 3.0);
385 let diff = p1 - p2;
386 assert_eq!(diff.x, 3.0);
387 assert_eq!(diff.y, 4.0);
388 }
389
390 #[test]
391 fn test_size_new() {
392 let s = Size::new(100.0, 200.0);
393 assert_eq!(s.width, 100.0);
394 assert_eq!(s.height, 200.0);
395 }
396
397 #[test]
398 fn test_size_zero() {
399 let s = Size::ZERO;
400 assert_eq!(s.width, 0.0);
401 assert_eq!(s.height, 0.0);
402 }
403
404 #[test]
405 fn test_size_area() {
406 let s = Size::new(10.0, 20.0);
407 assert_eq!(s.area(), 200.0);
408 }
409
410 #[test]
411 fn test_size_aspect_ratio() {
412 let s = Size::new(16.0, 9.0);
413 assert!((s.aspect_ratio() - 16.0 / 9.0).abs() < 0.001);
414 }
415
416 #[test]
417 fn test_size_contains() {
418 let s = Size::new(100.0, 100.0);
419 let smaller = Size::new(50.0, 50.0);
420 let larger = Size::new(150.0, 50.0);
421 assert!(s.contains(&smaller));
422 assert!(!s.contains(&larger));
423 }
424
425 #[test]
426 fn test_rect_new() {
427 let r = Rect::new(10.0, 20.0, 100.0, 200.0);
428 assert_eq!(r.x, 10.0);
429 assert_eq!(r.y, 20.0);
430 assert_eq!(r.width, 100.0);
431 assert_eq!(r.height, 200.0);
432 }
433
434 #[test]
435 fn test_rect_from_points() {
436 let r = Rect::from_points(Point::new(10.0, 20.0), Point::new(110.0, 220.0));
437 assert_eq!(r.x, 10.0);
438 assert_eq!(r.y, 20.0);
439 assert_eq!(r.width, 100.0);
440 assert_eq!(r.height, 200.0);
441 }
442
443 #[test]
444 fn test_rect_from_size() {
445 let r = Rect::from_size(Size::new(100.0, 200.0));
446 assert_eq!(r.x, 0.0);
447 assert_eq!(r.y, 0.0);
448 assert_eq!(r.width, 100.0);
449 assert_eq!(r.height, 200.0);
450 }
451
452 #[test]
453 fn test_rect_origin_and_size() {
454 let r = Rect::new(10.0, 20.0, 100.0, 200.0);
455 assert_eq!(r.origin(), Point::new(10.0, 20.0));
456 assert_eq!(r.size(), Size::new(100.0, 200.0));
457 }
458
459 #[test]
460 fn test_rect_corners() {
461 let r = Rect::new(10.0, 20.0, 100.0, 200.0);
462 assert_eq!(r.top_left(), Point::new(10.0, 20.0));
463 assert_eq!(r.top_right(), Point::new(110.0, 20.0));
464 assert_eq!(r.bottom_left(), Point::new(10.0, 220.0));
465 assert_eq!(r.bottom_right(), Point::new(110.0, 220.0));
466 }
467
468 #[test]
469 fn test_rect_center() {
470 let r = Rect::new(0.0, 0.0, 100.0, 100.0);
471 assert_eq!(r.center(), Point::new(50.0, 50.0));
472 }
473
474 #[test]
475 fn test_rect_contains_point() {
476 let r = Rect::new(10.0, 10.0, 100.0, 100.0);
477 assert!(r.contains_point(&Point::new(50.0, 50.0)));
478 assert!(r.contains_point(&Point::new(10.0, 10.0))); assert!(!r.contains_point(&Point::new(5.0, 50.0)));
480 assert!(!r.contains_point(&Point::new(111.0, 50.0)));
481 }
482
483 #[test]
484 fn test_rect_intersects() {
485 let r1 = Rect::new(0.0, 0.0, 100.0, 100.0);
486 let r2 = Rect::new(50.0, 50.0, 100.0, 100.0);
487 let r3 = Rect::new(200.0, 200.0, 100.0, 100.0);
488
489 assert!(r1.intersects(&r2));
490 assert!(!r1.intersects(&r3));
491 }
492
493 #[test]
494 fn test_rect_intersection() {
495 let r1 = Rect::new(0.0, 0.0, 100.0, 100.0);
496 let r2 = Rect::new(50.0, 50.0, 100.0, 100.0);
497
498 let inter = r1.intersection(&r2).unwrap();
499 assert_eq!(inter.x, 50.0);
500 assert_eq!(inter.y, 50.0);
501 assert_eq!(inter.width, 50.0);
502 assert_eq!(inter.height, 50.0);
503 }
504
505 #[test]
506 fn test_rect_union() {
507 let r1 = Rect::new(0.0, 0.0, 50.0, 50.0);
508 let r2 = Rect::new(25.0, 25.0, 50.0, 50.0);
509
510 let union = r1.union(&r2);
511 assert_eq!(union.x, 0.0);
512 assert_eq!(union.y, 0.0);
513 assert_eq!(union.width, 75.0);
514 assert_eq!(union.height, 75.0);
515 }
516
517 #[test]
518 fn test_rect_inset() {
519 let r = Rect::new(10.0, 10.0, 100.0, 100.0);
520 let inset = r.inset(5.0);
521 assert_eq!(inset.x, 15.0);
522 assert_eq!(inset.y, 15.0);
523 assert_eq!(inset.width, 90.0);
524 assert_eq!(inset.height, 90.0);
525 }
526
527 #[test]
528 fn test_corner_radius() {
529 let uniform = CornerRadius::uniform(10.0);
530 assert_eq!(uniform.top_left, 10.0);
531 assert_eq!(uniform.top_right, 10.0);
532 assert_eq!(uniform.bottom_left, 10.0);
533 assert_eq!(uniform.bottom_right, 10.0);
534
535 let custom = CornerRadius::new(1.0, 2.0, 3.0, 4.0);
536 assert_eq!(custom.top_left, 1.0);
537 assert_eq!(custom.top_right, 2.0);
538 assert_eq!(custom.bottom_right, 3.0);
539 assert_eq!(custom.bottom_left, 4.0);
540 }
541
542 proptest! {
543 #[test]
544 fn prop_point_distance_non_negative(x1 in -1000.0f32..1000.0, y1 in -1000.0f32..1000.0, x2 in -1000.0f32..1000.0, y2 in -1000.0f32..1000.0) {
545 let p1 = Point::new(x1, y1);
546 let p2 = Point::new(x2, y2);
547 prop_assert!(p1.distance(&p2) >= 0.0);
548 }
549
550 #[test]
551 fn prop_point_distance_symmetric(x1 in -1000.0f32..1000.0, y1 in -1000.0f32..1000.0, x2 in -1000.0f32..1000.0, y2 in -1000.0f32..1000.0) {
552 let p1 = Point::new(x1, y1);
553 let p2 = Point::new(x2, y2);
554 prop_assert!((p1.distance(&p2) - p2.distance(&p1)).abs() < 0.001);
555 }
556
557 #[test]
558 fn prop_rect_area_non_negative(x in -1000.0f32..1000.0, y in -1000.0f32..1000.0, w in 0.0f32..1000.0, h in 0.0f32..1000.0) {
559 let r = Rect::new(x, y, w, h);
560 prop_assert!(r.area() >= 0.0);
561 }
562
563 #[test]
564 fn prop_rect_contains_center(x in -1000.0f32..1000.0, y in -1000.0f32..1000.0, w in 1.0f32..1000.0, h in 1.0f32..1000.0) {
565 let r = Rect::new(x, y, w, h);
566 prop_assert!(r.contains_point(&r.center()));
567 }
568
569 #[test]
570 fn prop_rect_intersects_self(x in -1000.0f32..1000.0, y in -1000.0f32..1000.0, w in 0.1f32..1000.0, h in 0.1f32..1000.0) {
571 let r = Rect::new(x, y, w, h);
572 prop_assert!(r.intersects(&r));
573 }
574 }
575 }
576
577 mod constraints_tests {
582 use super::*;
583
584 #[test]
585 fn test_constraints_tight() {
586 let c = Constraints::tight(Size::new(100.0, 200.0));
587 assert_eq!(c.min_width, 100.0);
588 assert_eq!(c.max_width, 100.0);
589 assert_eq!(c.min_height, 200.0);
590 assert_eq!(c.max_height, 200.0);
591 }
592
593 #[test]
594 fn test_constraints_loose() {
595 let c = Constraints::loose(Size::new(100.0, 200.0));
596 assert_eq!(c.min_width, 0.0);
597 assert_eq!(c.max_width, 100.0);
598 assert_eq!(c.min_height, 0.0);
599 assert_eq!(c.max_height, 200.0);
600 }
601
602 #[test]
603 fn test_constraints_unbounded() {
604 let c = Constraints::unbounded();
605 assert_eq!(c.min_width, 0.0);
606 assert_eq!(c.max_width, f32::INFINITY);
607 assert_eq!(c.min_height, 0.0);
608 assert_eq!(c.max_height, f32::INFINITY);
609 }
610
611 #[test]
612 fn test_constraints_constrain() {
613 let c = Constraints::new(50.0, 150.0, 50.0, 150.0);
614
615 assert_eq!(
617 c.constrain(Size::new(100.0, 100.0)),
618 Size::new(100.0, 100.0)
619 );
620
621 assert_eq!(c.constrain(Size::new(10.0, 10.0)), Size::new(50.0, 50.0));
623
624 assert_eq!(
626 c.constrain(Size::new(200.0, 200.0)),
627 Size::new(150.0, 150.0)
628 );
629 }
630
631 #[test]
632 fn test_constraints_is_tight() {
633 let tight = Constraints::tight(Size::new(100.0, 100.0));
634 let loose = Constraints::loose(Size::new(100.0, 100.0));
635
636 assert!(tight.is_tight());
637 assert!(!loose.is_tight());
638 }
639
640 #[test]
641 fn test_constraints_has_bounded_width() {
642 let bounded = Constraints::new(0.0, 100.0, 0.0, f32::INFINITY);
643 let unbounded = Constraints::unbounded();
644
645 assert!(bounded.has_bounded_width());
646 assert!(!unbounded.has_bounded_width());
647 }
648 }
649
650 mod event_tests {
655 use super::*;
656
657 #[test]
658 fn test_event_mouse_move() {
659 let e = Event::MouseMove {
660 position: Point::new(100.0, 200.0),
661 };
662 if let Event::MouseMove { position } = e {
663 assert_eq!(position.x, 100.0);
664 assert_eq!(position.y, 200.0);
665 } else {
666 panic!("Expected MouseMove event");
667 }
668 }
669
670 #[test]
671 fn test_event_mouse_button() {
672 let e = Event::MouseDown {
673 position: Point::new(50.0, 50.0),
674 button: MouseButton::Left,
675 };
676 if let Event::MouseDown { button, .. } = e {
677 assert_eq!(button, MouseButton::Left);
678 } else {
679 panic!("Expected MouseDown event");
680 }
681 }
682
683 #[test]
684 fn test_event_key() {
685 let e = Event::KeyDown { key: Key::Enter };
686 if let Event::KeyDown { key } = e {
687 assert_eq!(key, Key::Enter);
688 } else {
689 panic!("Expected KeyDown event");
690 }
691 }
692
693 #[test]
694 fn test_event_scroll() {
695 let e = Event::Scroll {
696 delta_x: 0.0,
697 delta_y: -10.0,
698 };
699 if let Event::Scroll { delta_y, .. } = e {
700 assert_eq!(delta_y, -10.0);
701 } else {
702 panic!("Expected Scroll event");
703 }
704 }
705
706 #[test]
707 fn test_event_text_input() {
708 let e = Event::TextInput {
709 text: "hello".to_string(),
710 };
711 if let Event::TextInput { text } = e {
712 assert_eq!(text, "hello");
713 } else {
714 panic!("Expected TextInput event");
715 }
716 }
717 }
718}