⎇ devin/1784875552-bfc-beside-floats
tests/hand_written/safe_alignment.rs
Ñawpa willay
Pi imata llamkarqan
ch'uya
Use SCREAMING_SNAKE_CASE for alignment constants (#961)
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}