gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 497HTML 254C 19JavaScript 81329 Sutichaykuna

⎇ devin/1784875552-bfc-beside-floats tests/hand_written/safe_alignment.rs Rust · 308 siq'ikuna · 10.2 KB Ñawpa willay Pi imata llamkarqan ch'uya

Use SCREAMING_SNAKE_CASE for alignment constants (#961) 9c58cc5d5 · Nico Burns ·

1//! Tests for the `safe` and `unsafe` overflow-position keywords on align-* and justify-*.
2//!
3//! Spec: <https://www.w3.org/TR/css-align-3/#overflow-values>
4//!
5//! When the alignment subject overflows the alignment container, a `safe` value behaves
6//! as logical `start`; an `unsafe` value (the default) keeps its requested position even
7//! when that causes data loss at the start edge.
8
9use taffy::prelude::*;
10use taffy::style::Direction;
11use taffy_test_helpers::new_test_tree;
12
13#[cfg(feature = "grid")]
14#[test]
15fn grid_safe_align_self_falls_back_to_start_on_overflow() {
16    let mut taffy = new_test_tree();
17    let child = taffy
18        .new_leaf(Style {
19            size: Size { width: length(50.0), height: length(150.0) },
20            align_self: Some(AlignSelf::SAFE_END),
21            ..Default::default()
22        })
23        .unwrap();
24    let root = taffy
25        .new_with_children(
26            Style {
27                display: Display::Grid,
28                size: Size { width: length(100.0), height: length(100.0) },
29                grid_template_rows: vec![length(100.0)],
30                grid_template_columns: vec![length(100.0)],
31                ..Default::default()
32            },
33            &[child],
34        )
35        .unwrap();
36
37    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
38
39    // Child overflows the 100-tall grid area, so safe end falls back to start (y == 0).
40    assert_eq!(taffy.layout(child).unwrap().location.y, 0.0);
41}
42
43#[cfg(feature = "grid")]
44#[test]
45fn grid_safe_align_self_behaves_as_end_when_no_overflow() {
46    let mut taffy = new_test_tree();
47    let child = taffy
48        .new_leaf(Style {
49            size: Size { width: length(50.0), height: length(40.0) },
50            align_self: Some(AlignSelf::SAFE_END),
51            ..Default::default()
52        })
53        .unwrap();
54    let root = taffy
55        .new_with_children(
56            Style {
57                display: Display::Grid,
58                size: Size { width: length(100.0), height: length(100.0) },
59                grid_template_rows: vec![length(100.0)],
60                grid_template_columns: vec![length(100.0)],
61                ..Default::default()
62            },
63            &[child],
64        )
65        .unwrap();
66
67    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
68
69    // No overflow, so safe end behaves as end: y == 100 - 40 == 60
70    assert_eq!(taffy.layout(child).unwrap().location.y, 60.0);
71}
72
73#[cfg(feature = "grid")]
74#[test]
75fn grid_unsafe_align_self_keeps_overflowing_position() {
76    let mut taffy = new_test_tree();
77    let child = taffy
78        .new_leaf(Style {
79            size: Size { width: length(50.0), height: length(150.0) },
80            align_self: Some(AlignSelf::END),
81            ..Default::default()
82        })
83        .unwrap();
84    let root = taffy
85        .new_with_children(
86            Style {
87                display: Display::Grid,
88                size: Size { width: length(100.0), height: length(100.0) },
89                grid_template_rows: vec![length(100.0)],
90                grid_template_columns: vec![length(100.0)],
91                ..Default::default()
92            },
93            &[child],
94        )
95        .unwrap();
96
97    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
98
99    // Plain End with overflow keeps end alignment: y == 100 - 150 == -50
100    assert_eq!(taffy.layout(child).unwrap().location.y, -50.0);
101}
102
103#[cfg(feature = "grid")]
104#[test]
105fn grid_safe_justify_self_falls_back_to_start_on_overflow() {
106    let mut taffy = new_test_tree();
107    let child = taffy
108        .new_leaf(Style {
109            size: Size { width: length(150.0), height: length(50.0) },
110            justify_self: Some(JustifySelf::SAFE_END),
111            ..Default::default()
112        })
113        .unwrap();
114    let root = taffy
115        .new_with_children(
116            Style {
117                display: Display::Grid,
118                size: Size { width: length(100.0), height: length(100.0) },
119                grid_template_rows: vec![length(100.0)],
120                grid_template_columns: vec![length(100.0)],
121                ..Default::default()
122            },
123            &[child],
124        )
125        .unwrap();
126
127    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
128
129    assert_eq!(taffy.layout(child).unwrap().location.x, 0.0);
130}
131
132#[cfg(feature = "grid")]
133#[test]
134fn grid_safe_justify_self_rtl_falls_back_to_rtl_start_edge() {
135    let mut taffy = new_test_tree();
136    let child = taffy
137        .new_leaf(Style {
138            size: Size { width: length(150.0), height: length(50.0) },
139            justify_self: Some(JustifySelf::SAFE_END),
140            ..Default::default()
141        })
142        .unwrap();
143    let root = taffy
144        .new_with_children(
145            Style {
146                display: Display::Grid,
147                direction: Direction::Rtl,
148                size: Size { width: length(100.0), height: length(100.0) },
149                grid_template_rows: vec![length(100.0)],
150                grid_template_columns: vec![length(100.0)],
151                ..Default::default()
152            },
153            &[child],
154        )
155        .unwrap();
156
157    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
158
159    // In RTL the inline-start edge is the right side. The 150-wide child in the
160    // 100-wide container, anchored at the RTL Start edge, sits at x == -50.
161    assert_eq!(taffy.layout(child).unwrap().location.x, -50.0);
162}
163
164#[cfg(feature = "grid")]
165#[test]
166fn grid_safe_align_content_overflow_falls_back_to_start() {
167    let mut taffy = new_test_tree();
168    let child_a = taffy
169        .new_leaf(Style { size: Size { width: length(40.0), height: length(80.0) }, ..Default::default() })
170        .unwrap();
171    let child_b = taffy
172        .new_leaf(Style { size: Size { width: length(40.0), height: length(80.0) }, ..Default::default() })
173        .unwrap();
174    let root = taffy
175        .new_with_children(
176            Style {
177                display: Display::Grid,
178                size: Size { width: length(100.0), height: length(100.0) },
179                grid_template_rows: vec![length(80.0), length(80.0)],
180                grid_template_columns: vec![length(40.0)],
181                align_content: Some(AlignContent::SAFE_END),
182                ..Default::default()
183            },
184            &[child_a, child_b],
185        )
186        .unwrap();
187
188    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
189
190    // Tracks total 160 in a 100-tall container — overflow. Safe end falls back to
191    // start: first track at y == 0.
192    assert_eq!(taffy.layout(child_a).unwrap().location.y, 0.0);
193}
194
195#[cfg(feature = "flexbox")]
196#[test]
197fn flex_safe_align_self_falls_back_to_start_on_overflow() {
198    let mut taffy = new_test_tree();
199    let child = taffy
200        .new_leaf(Style {
201            size: Size { width: length(50.0), height: length(150.0) },
202            align_self: Some(AlignSelf::SAFE_END),
203            ..Default::default()
204        })
205        .unwrap();
206    let root = taffy
207        .new_with_children(
208            Style {
209                display: Display::Flex,
210                size: Size { width: length(100.0), height: length(100.0) },
211                ..Default::default()
212            },
213            &[child],
214        )
215        .unwrap();
216
217    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
218
219    // Cross-axis overflow: safe end falls back to start (y == 0).
220    assert_eq!(taffy.layout(child).unwrap().location.y, 0.0);
221}
222
223#[cfg(feature = "flexbox")]
224#[test]
225fn flex_unsafe_align_self_keeps_overflowing_position() {
226    let mut taffy = new_test_tree();
227    let child = taffy
228        .new_leaf(Style {
229            size: Size { width: length(50.0), height: length(150.0) },
230            align_self: Some(AlignSelf::END),
231            ..Default::default()
232        })
233        .unwrap();
234    let root = taffy
235        .new_with_children(
236            Style {
237                display: Display::Flex,
238                size: Size { width: length(100.0), height: length(100.0) },
239                ..Default::default()
240            },
241            &[child],
242        )
243        .unwrap();
244
245    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
246
247    // Plain End with cross-axis overflow keeps end alignment: y == 100 - 150 == -50
248    assert_eq!(taffy.layout(child).unwrap().location.y, -50.0);
249}
250
251#[cfg(feature = "flexbox")]
252#[test]
253fn flex_safe_justify_content_falls_back_to_start_on_overflow() {
254    let mut taffy = new_test_tree();
255    let child_a = taffy
256        .new_leaf(Style { size: Size { width: length(80.0), height: length(50.0) }, ..Default::default() })
257        .unwrap();
258    let child_b = taffy
259        .new_leaf(Style { size: Size { width: length(80.0), height: length(50.0) }, ..Default::default() })
260        .unwrap();
261    let root = taffy
262        .new_with_children(
263            Style {
264                display: Display::Flex,
265                size: Size { width: length(100.0), height: length(100.0) },
266                justify_content: Some(JustifyContent::SAFE_END),
267                ..Default::default()
268            },
269            &[child_a, child_b],
270        )
271        .unwrap();
272
273    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
274
275    // Items total 160 in a 100-wide container — overflow. Safe end falls back to
276    // start: first item anchored at x == 0.
277    assert_eq!(taffy.layout(child_a).unwrap().location.x, 0.0);
278}
279
280#[cfg(feature = "flexbox")]
281#[test]
282fn flex_safe_align_content_falls_back_to_start_on_multiline_overflow() {
283    let mut taffy = new_test_tree();
284    let child_a = taffy
285        .new_leaf(Style { size: Size { width: length(60.0), height: length(80.0) }, ..Default::default() })
286        .unwrap();
287    let child_b = taffy
288        .new_leaf(Style { size: Size { width: length(60.0), height: length(80.0) }, ..Default::default() })
289        .unwrap();
290    let root = taffy
291        .new_with_children(
292            Style {
293                display: Display::Flex,
294                flex_wrap: FlexWrap::Wrap,
295                size: Size { width: length(100.0), height: length(100.0) },
296                align_content: Some(AlignContent::SAFE_END),
297                ..Default::default()
298            },
299            &[child_a, child_b],
300        )
301        .unwrap();
302
303    taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
304
305    // Two 80-tall lines wrap and overflow the 100-tall container. Safe end falls back
306    // to start: first line at y == 0.
307    assert_eq!(taffy.layout(child_a).unwrap().location.y, 0.0);
308}