1#[cfg(test)]
2mod flatten_style_object_with_legacy_shorthand_expansion {
3 use indexmap::IndexMap;
4 use swc_core::ecma::ast::Expr;
5
6 use crate::shared::structures::functions::FunctionMap;
7 use crate::shared::structures::null_pre_rule::NullPreRule;
8 use crate::shared::structures::pre_rule::{PreRuleValue, PreRules, StylesPreRule};
9 use crate::shared::structures::pre_rule_set::PreRuleSet;
10 use crate::shared::structures::state::EvaluationState;
11 use crate::shared::structures::state_manager::StateManager;
12 use crate::shared::utils::ast::convertors::create_string_expr;
13 use crate::shared::utils::core::flatten_raw_style_object::flatten_raw_style_object;
14 use stylex_ast::ast::factories::{create_array, create_key_value_prop_ident};
15 use stylex_enums::style_resolution::StyleResolution;
16
17 pub(super) fn get_state() -> StateManager {
18 let mut state_manager = StateManager::default();
19
20 state_manager.options.class_name_prefix = "x".to_string();
21 state_manager.options.style_resolution = StyleResolution::LegacyExpandShorthands;
22 state_manager.options.runtime_injection = None;
23 state_manager.options.dev = false;
24 state_manager.options.test = false;
25 state_manager.options.debug = false;
26
27 state_manager
28 }
29
30 pub(super) fn pre_rule_factory(key: &str, value: &str, path_key: &[&str]) -> PreRules {
31 PreRules::StylesPreRule(StylesPreRule::new(
32 key,
33 PreRuleValue::String(value.to_string()),
34 Some(path_key.iter().map(|s| s.to_string()).collect()),
35 ))
36 }
37
38 pub(super) fn pre_rule_set_factory(values: &[PreRules]) -> PreRules {
39 PreRuleSet::create(values.to_vec())
40 }
41
42 pub(super) fn null_rule_factory() -> PreRules {
43 PreRules::NullPreRule(NullPreRule::default())
44 }
45
46 pub(super) fn pre_rule_vec_factory(key: &str, value: &[&str], path_key: &[&str]) -> PreRules {
47 PreRules::StylesPreRule(StylesPreRule::new(
48 key,
49 PreRuleValue::Vec(value.iter().map(|x| x.to_string()).collect()),
50 Some(path_key.iter().map(|s| s.to_string()).collect()),
51 ))
52 }
53
54 #[test]
55 fn should_create_pre_rule_objects_for_simple_style_values() {
56 let result = flatten_raw_style_object(
57 &[
58 create_key_value_prop_ident("color", create_string_expr("red")),
59 create_key_value_prop_ident("marginStart", create_string_expr("10")),
60 ],
61 &mut EvaluationState::new(),
62 &mut get_state(),
63 &FunctionMap::default(),
64 );
65
66 assert_eq!(result.len(), 4);
67
68 let mut expected_result = IndexMap::new();
69
70 expected_result.insert(
71 "color".to_string(),
72 pre_rule_factory("color", "red", &["color"]),
73 );
74 expected_result.insert(
75 "marginInlineStart".to_string(),
76 pre_rule_factory("marginInlineStart", "10", &["marginInlineStart"]),
77 );
78 expected_result.insert("marginLeft".to_string(), null_rule_factory());
79 expected_result.insert("marginRight".to_string(), null_rule_factory());
80
81 assert_eq!(result, expected_result)
82 }
83
84 #[test]
85 fn should_expand_simple_gap_values() {
86 let result = flatten_raw_style_object(
87 &[create_key_value_prop_ident("gap", create_string_expr("10"))],
88 &mut EvaluationState::new(),
89 &mut get_state(),
90 &FunctionMap::default(),
91 );
92
93 assert_eq!(result.len(), 2);
94
95 let mut expected_result = IndexMap::new();
96
97 expected_result.insert(
98 "rowGap".to_string(),
99 pre_rule_factory("rowGap", "10", &["rowGap"]),
100 );
101 expected_result.insert(
102 "columnGap".to_string(),
103 pre_rule_factory("columnGap", "10", &["columnGap"]),
104 );
105
106 assert_eq!(result, expected_result)
107 }
108
109 #[test]
110 fn should_expand_simple_contain_intrinsic_size_values() {
111 let result = flatten_raw_style_object(
112 &[create_key_value_prop_ident(
113 "containIntrinsicSize",
114 create_string_expr("10"),
115 )],
116 &mut EvaluationState::new(),
117 &mut get_state(),
118 &FunctionMap::default(),
119 );
120
121 assert_eq!(result.len(), 2);
122
123 let mut expected_result = IndexMap::new();
124
125 expected_result.insert(
126 "containIntrinsicWidth".to_string(),
127 pre_rule_factory("containIntrinsicWidth", "10", &["containIntrinsicWidth"]),
128 );
129 expected_result.insert(
130 "containIntrinsicHeight".to_string(),
131 pre_rule_factory("containIntrinsicHeight", "10", &["containIntrinsicHeight"]),
132 );
133
134 assert_eq!(result, expected_result)
135 }
136
137 #[test]
138 fn should_expand_simple_gap_with_space_separated_values() {
139 let result = flatten_raw_style_object(
140 &[create_key_value_prop_ident(
141 "gap",
142 create_string_expr("10px 20px"),
143 )],
144 &mut EvaluationState::new(),
145 &mut get_state(),
146 &FunctionMap::default(),
147 );
148
149 assert_eq!(result.len(), 2);
150
151 let mut expected_result = IndexMap::new();
152
153 expected_result.insert(
154 "rowGap".to_string(),
155 pre_rule_factory("rowGap", "10px", &["rowGap"]),
156 );
157 expected_result.insert(
158 "columnGap".to_string(),
159 pre_rule_factory("columnGap", "20px", &["columnGap"]),
160 );
161
162 assert_eq!(result, expected_result)
163 }
164
165 #[test]
166 fn should_expand_simple_contain_intrinsic_size_with_space_separated_values() {
167 let w = "containIntrinsicWidth";
168 let h = "containIntrinsicHeight";
169
170 let result = flatten_raw_style_object(
171 &[create_key_value_prop_ident(
172 "containIntrinsicSize",
173 create_string_expr("10px 20px"),
174 )],
175 &mut EvaluationState::new(),
176 &mut get_state(),
177 &FunctionMap::default(),
178 );
179
180 assert_eq!(result.len(), 2);
181
182 let mut expected_result = IndexMap::new();
183
184 expected_result.insert(w.to_string(), pre_rule_factory(w, "10px", &[w]));
185 expected_result.insert(h.to_string(), pre_rule_factory(h, "20px", &[h]));
186
187 assert_eq!(result, expected_result)
188 }
189
190 #[test]
191 fn should_expand_simple_contain_intrinsic_size_with_space_separated_values_v2() {
192 let w = "containIntrinsicWidth";
193 let h = "containIntrinsicHeight";
194
195 let result = flatten_raw_style_object(
196 &[create_key_value_prop_ident(
197 "containIntrinsicSize",
198 create_string_expr("auto 10px 20px"),
199 )],
200 &mut EvaluationState::new(),
201 &mut get_state(),
202 &FunctionMap::default(),
203 );
204
205 assert_eq!(result.len(), 2);
206
207 let mut expected_result = IndexMap::new();
208
209 expected_result.insert(w.to_string(), pre_rule_factory(w, "auto 10px", &[w]));
210 expected_result.insert(h.to_string(), pre_rule_factory(h, "20px", &[h]));
211
212 assert_eq!(result, expected_result)
213 }
214
215 #[test]
216 fn should_expand_simple_contain_intrinsic_size_with_space_separated_values_v3() {
217 let w = "containIntrinsicWidth";
218 let h = "containIntrinsicHeight";
219
220 let result = flatten_raw_style_object(
221 &[create_key_value_prop_ident(
222 "containIntrinsicSize",
223 create_string_expr("auto 10px auto 20px"),
224 )],
225 &mut EvaluationState::new(),
226 &mut get_state(),
227 &FunctionMap::default(),
228 );
229
230 assert_eq!(result.len(), 2);
231
232 let mut expected_result = IndexMap::new();
233
234 expected_result.insert(w.to_string(), pre_rule_factory(w, "auto 10px", &[w]));
235 expected_result.insert(h.to_string(), pre_rule_factory(h, "auto 20px", &[h]));
236
237 assert_eq!(result, expected_result)
238 }
239
240 #[test]
241 fn should_expand_simple_shorthands() {
242 let result = flatten_raw_style_object(
243 &[create_key_value_prop_ident(
244 "margin",
245 create_string_expr("10"),
246 )],
247 &mut EvaluationState::new(),
248 &mut get_state(),
249 &FunctionMap::default(),
250 );
251
252 assert_eq!(result.len(), 4);
253
254 let mut expected_result = IndexMap::new();
255
256 expected_result.insert(
257 "marginTop".to_string(),
258 pre_rule_factory("marginTop", "10", &["marginTop"]),
259 );
260 expected_result.insert(
261 "marginInlineEnd".to_string(),
262 pre_rule_factory("marginInlineEnd", "10", &["marginInlineEnd"]),
263 );
264 expected_result.insert(
265 "marginBottom".to_string(),
266 pre_rule_factory("marginBottom", "10", &["marginBottom"]),
267 );
268 expected_result.insert(
269 "marginInlineStart".to_string(),
270 pre_rule_factory("marginInlineStart", "10", &["marginInlineStart"]),
271 );
272
273 assert_eq!(result, expected_result)
274 }
275
276 #[test]
277 fn should_expand_simple_shorthands_extended() {
278 let result = flatten_raw_style_object(
279 &[
280 create_key_value_prop_ident("margin", create_string_expr("10")),
281 create_key_value_prop_ident("marginBottom", create_string_expr("20")),
282 ],
283 &mut EvaluationState::new(),
284 &mut get_state(),
285 &FunctionMap::default(),
286 );
287
288 assert_eq!(result.len(), 4);
289
290 let mut expected_result = IndexMap::new();
291
292 expected_result.insert(
293 "marginTop".to_string(),
294 pre_rule_factory("marginTop", "10", &["marginTop"]),
295 );
296 expected_result.insert(
297 "marginInlineEnd".to_string(),
298 pre_rule_factory("marginInlineEnd", "10", &["marginInlineEnd"]),
299 );
300 expected_result.insert(
301 "marginBottom".to_string(),
302 pre_rule_factory("marginBottom", "10", &["marginBottom"]),
303 );
304 expected_result.insert(
305 "marginInlineStart".to_string(),
306 pre_rule_factory("marginInlineStart", "10", &["marginInlineStart"]),
307 );
308
309 expected_result.insert(
310 "marginBottom".to_string(),
311 pre_rule_factory("marginBottom", "20", &["marginBottom"]),
312 );
313
314 assert_eq!(result, expected_result)
315 }
316
317 #[test]
318 fn should_expand_shorthands_with_space_separated_values() {
319 let result = flatten_raw_style_object(
320 &[
321 create_key_value_prop_ident("margin", create_string_expr("10px 20px")),
322 create_key_value_prop_ident("borderColor", create_string_expr("red")),
323 ],
324 &mut EvaluationState::new(),
325 &mut get_state(),
326 &FunctionMap::default(),
327 );
328
329 assert_eq!(result.len(), 8);
330
331 let mut expected_result = IndexMap::new();
332
333 expected_result.insert(
334 "marginTop".to_string(),
335 pre_rule_factory("marginTop", "10px", &["marginTop"]),
336 );
337 expected_result.insert(
338 "marginInlineEnd".to_string(),
339 pre_rule_factory("marginInlineEnd", "20px", &["marginInlineEnd"]),
340 );
341 expected_result.insert(
342 "marginBottom".to_string(),
343 pre_rule_factory("marginBottom", "10px", &["marginBottom"]),
344 );
345 expected_result.insert(
346 "marginInlineStart".to_string(),
347 pre_rule_factory("marginInlineStart", "20px", &["marginInlineStart"]),
348 );
349
350 expected_result.insert(
351 "borderTopColor".to_string(),
352 pre_rule_factory("borderTopColor", "red", &["borderTopColor"]),
353 );
354 expected_result.insert(
355 "borderInlineEndColor".to_string(),
356 pre_rule_factory("borderInlineEndColor", "red", &["borderInlineEndColor"]),
357 );
358 expected_result.insert(
359 "borderBottomColor".to_string(),
360 pre_rule_factory("borderBottomColor", "red", &["borderBottomColor"]),
361 );
362 expected_result.insert(
363 "borderInlineStartColor".to_string(),
364 pre_rule_factory("borderInlineStartColor", "red", &["borderInlineStartColor"]),
365 );
366
367 assert_eq!(result, expected_result)
368 }
369
370 #[test]
371 fn should_expand_shorthands_with_fallbacks() {
372 let result = flatten_raw_style_object(
373 &[create_key_value_prop_ident(
374 "margin",
375 Expr::from(create_array(&[
376 create_string_expr("10vh 20px"),
377 create_string_expr("10dvh 20px"),
378 ])),
379 )],
380 &mut EvaluationState::new(),
381 &mut get_state(),
382 &FunctionMap::default(),
383 );
384
385 assert_eq!(result.len(), 4);
386
387 let mut expected_result = IndexMap::new();
388
389 expected_result.insert(
390 "marginTop".to_string(),
391 pre_rule_vec_factory("marginTop", &["10vh", "10dvh"], &["marginTop"]),
392 );
393 expected_result.insert(
394 "marginInlineEnd".to_string(),
395 pre_rule_factory("marginInlineEnd", "20px", &["marginInlineEnd"]),
396 );
397 expected_result.insert(
398 "marginBottom".to_string(),
399 pre_rule_vec_factory("marginBottom", &["10vh", "10dvh"], &["marginBottom"]),
400 );
401 expected_result.insert(
402 "marginInlineStart".to_string(),
403 pre_rule_factory("marginInlineStart", "20px", &["marginInlineStart"]),
404 );
405
406 assert_eq!(result, expected_result)
407 }
408}
409
410#[cfg(test)]
411mod nested_objects {
412 use indexmap::IndexMap;
413
414 use stylex_ast::ast::factories::{
415 create_key_value_prop_ident,
416 create_object_expression,
417 create_string_key_value_prop,
418 };
419 use crate::shared::structures::functions::FunctionMap;
420 use crate::shared::structures::state::EvaluationState;
421 use crate::shared::structures::tests::flatten_raw_style_objects_test::flatten_style_object_with_legacy_shorthand_expansion::{
422 get_state,
423 null_rule_factory,
424 pre_rule_factory,
425 pre_rule_set_factory,
426 };
427 use crate::shared::utils::ast::convertors::create_string_expr;
428 use crate::shared::utils::core::flatten_raw_style_object::flatten_raw_style_object;
429
430 #[test]
431 fn legacy_pseudo_classes() {
432 let result = flatten_raw_style_object(
433 &[
434 create_key_value_prop_ident("color", create_string_expr("blue")),
435 create_key_value_prop_ident("marginStart", create_string_expr("0")),
436 create_key_value_prop_ident(
437 ":hover",
438 create_object_expression(vec![
439 create_string_key_value_prop("color", "red"),
440 create_string_key_value_prop("marginStart", "10"),
441 ]),
442 ),
443 ],
444 &mut EvaluationState::new(),
445 &mut get_state(),
446 &FunctionMap::default(),
447 );
448
449 assert_eq!(result.len(), 8);
450
451 let mut expected_result = IndexMap::new();
452
453 expected_result.insert(
454 "color".to_string(),
455 pre_rule_factory("color", "blue", &["color"]),
456 );
457 expected_result.insert(
458 "marginInlineStart".to_string(),
459 pre_rule_factory("marginInlineStart", "0", &["marginInlineStart"]),
460 );
461 expected_result.insert("marginLeft".to_string(), null_rule_factory());
462 expected_result.insert("marginRight".to_string(), null_rule_factory());
463 expected_result.insert(
464 ":hover_color".to_string(),
465 pre_rule_factory("color", "red", &[":hover", "color"]),
466 );
467
468 expected_result.insert(
469 ":hover_marginInlineStart".to_string(),
470 pre_rule_factory("marginInlineStart", "10", &[":hover", "marginInlineStart"]),
471 );
472
473 expected_result.insert(":hover_marginLeft".to_string(), null_rule_factory());
474
475 expected_result.insert(":hover_marginRight".to_string(), null_rule_factory());
476
477 assert_eq!(result, expected_result)
478 }
479
480 #[test]
481 fn modern_pseudo_classes() {
482 let result = flatten_raw_style_object(
483 &[
484 create_key_value_prop_ident(
485 "color",
486 create_object_expression(vec![
487 create_string_key_value_prop("default", "blue"),
488 create_string_key_value_prop(":hover", "red"),
489 ]),
490 ),
491 create_key_value_prop_ident(
492 "marginStart",
493 create_object_expression(vec![
494 create_string_key_value_prop("default", "0"),
495 create_string_key_value_prop(":hover", "10"),
496 ]),
497 ),
498 ],
499 &mut EvaluationState::new(),
500 &mut get_state(),
501 &FunctionMap::default(),
502 );
503
504 assert_eq!(result.len(), 4);
505
506 let mut expected_result = IndexMap::new();
507
508 expected_result.insert(
509 "color".to_string(),
510 pre_rule_set_factory(&[
511 pre_rule_factory("color", "blue", &["color", "default"]),
512 pre_rule_factory("color", "red", &["color", ":hover"]),
513 ]),
514 );
515
516 expected_result.insert(
517 "marginInlineStart".to_string(),
518 pre_rule_set_factory(&[
519 pre_rule_factory("marginInlineStart", "0", &["marginInlineStart", "default"]),
520 pre_rule_factory("marginInlineStart", "10", &["marginInlineStart", ":hover"]),
521 ]),
522 );
523
524 expected_result.insert(
525 "marginLeft".to_string(),
526 pre_rule_set_factory(&[null_rule_factory(), null_rule_factory()]),
527 );
528
529 expected_result.insert(
530 "marginRight".to_string(),
531 pre_rule_set_factory(&[null_rule_factory(), null_rule_factory()]),
532 );
533
534 assert_eq!(result, expected_result)
535 }
536
537 #[test]
538 fn modern_pseudo_classes_with_shorthands() {
539 let result = flatten_raw_style_object(
540 &[
541 create_key_value_prop_ident(
542 "color",
543 create_object_expression(vec![
544 create_string_key_value_prop("default", "blue"),
545 create_string_key_value_prop(":hover", "red"),
546 ]),
547 ),
548 create_key_value_prop_ident(
549 "margin",
550 create_object_expression(vec![
551 create_string_key_value_prop("default", "0"),
552 create_string_key_value_prop(":hover", "10"),
553 ]),
554 ),
555 ],
556 &mut EvaluationState::new(),
557 &mut get_state(),
558 &FunctionMap::default(),
559 );
560
561 assert_eq!(result.len(), 5);
562
563 let mut expected_result = IndexMap::new();
564
565 expected_result.insert(
566 "color".to_string(),
567 pre_rule_set_factory(&[
568 pre_rule_factory("color", "blue", &["color", "default"]),
569 pre_rule_factory("color", "red", &["color", ":hover"]),
570 ]),
571 );
572
573 expected_result.insert(
574 "marginTop".to_string(),
575 pre_rule_set_factory(&[
576 pre_rule_factory("marginTop", "0", &["marginTop", "default"]),
577 pre_rule_factory("marginTop", "10", &["marginTop", ":hover"]),
578 ]),
579 );
580
581 expected_result.insert(
582 "marginInlineEnd".to_string(),
583 pre_rule_set_factory(&[
584 pre_rule_factory("marginInlineEnd", "0", &["marginInlineEnd", "default"]),
585 pre_rule_factory("marginInlineEnd", "10", &["marginInlineEnd", ":hover"]),
586 ]),
587 );
588
589 expected_result.insert(
590 "marginBottom".to_string(),
591 pre_rule_set_factory(&[
592 pre_rule_factory("marginBottom", "0", &["marginBottom", "default"]),
593 pre_rule_factory("marginBottom", "10", &["marginBottom", ":hover"]),
594 ]),
595 );
596
597 expected_result.insert(
598 "marginInlineStart".to_string(),
599 pre_rule_set_factory(&[
600 pre_rule_factory("marginInlineStart", "0", &["marginInlineStart", "default"]),
601 pre_rule_factory("marginInlineStart", "10", &["marginInlineStart", ":hover"]),
602 ]),
603 );
604
605 assert_eq!(result, expected_result)
606 }
607
608 #[test]
609 fn modern_pseudo_classes_with_complex_shorthands() {
610 let result = flatten_raw_style_object(
611 &[
612 create_key_value_prop_ident(
613 "color",
614 create_object_expression(vec![
615 create_string_key_value_prop("default", "blue"),
616 create_string_key_value_prop(":hover", "red"),
617 ]),
618 ),
619 create_key_value_prop_ident(
620 "margin",
621 create_object_expression(vec![
622 create_string_key_value_prop("default", "1px 2px 3px 4px"),
623 create_string_key_value_prop(":hover", "10px 20px"),
624 ]),
625 ),
626 ],
627 &mut EvaluationState::new(),
628 &mut get_state(),
629 &FunctionMap::default(),
630 );
631
632 assert_eq!(result.len(), 5);
633
634 let mut expected_result = IndexMap::new();
635
636 expected_result.insert(
637 "color".to_string(),
638 pre_rule_set_factory(&[
639 pre_rule_factory("color", "blue", &["color", "default"]),
640 pre_rule_factory("color", "red", &["color", ":hover"]),
641 ]),
642 );
643
644 expected_result.insert(
645 "marginTop".to_string(),
646 pre_rule_set_factory(&[
647 pre_rule_factory("marginTop", "1px", &["marginTop", "default"]),
648 pre_rule_factory("marginTop", "10px", &["marginTop", ":hover"]),
649 ]),
650 );
651
652 expected_result.insert(
653 "marginInlineEnd".to_string(),
654 pre_rule_set_factory(&[
655 pre_rule_factory("marginInlineEnd", "2px", &["marginInlineEnd", "default"]),
656 pre_rule_factory("marginInlineEnd", "20px", &["marginInlineEnd", ":hover"]),
657 ]),
658 );
659
660 expected_result.insert(
661 "marginBottom".to_string(),
662 pre_rule_set_factory(&[
663 pre_rule_factory("marginBottom", "3px", &["marginBottom", "default"]),
664 pre_rule_factory("marginBottom", "10px", &["marginBottom", ":hover"]),
665 ]),
666 );
667
668 expected_result.insert(
669 "marginInlineStart".to_string(),
670 pre_rule_set_factory(&[
671 pre_rule_factory(
672 "marginInlineStart",
673 "4px",
674 &["marginInlineStart", "default"],
675 ),
676 pre_rule_factory(
677 "marginInlineStart",
678 "20px",
679 &["marginInlineStart", ":hover"],
680 ),
681 ]),
682 );
683
684 assert_eq!(result, expected_result)
685 }
686
687 #[test]
688 fn modern_pseudo_and_at_rules() {
689 let result = flatten_raw_style_object(
690 &[
691 create_key_value_prop_ident(
692 "color",
693 create_object_expression(vec![
694 create_string_key_value_prop("default", "blue"),
695 create_string_key_value_prop(":hover", "red"),
696 create_string_key_value_prop("@media (min-width: 300px)", "green"),
697 ]),
698 ),
699 create_key_value_prop_ident(
700 "marginStart",
701 create_object_expression(vec![
702 create_string_key_value_prop("default", "0"),
703 create_string_key_value_prop(":hover", "10"),
704 ]),
705 ),
706 ],
707 &mut EvaluationState::new(),
708 &mut get_state(),
709 &FunctionMap::default(),
710 );
711
712 assert_eq!(result.len(), 4);
713
714 let mut expected_result = IndexMap::new();
715
716 expected_result.insert(
717 "color".to_string(),
718 pre_rule_set_factory(&[
719 pre_rule_factory("color", "blue", &["color", "default"]),
720 pre_rule_factory("color", "red", &["color", ":hover"]),
721 pre_rule_factory("color", "green", &["color", "@media (min-width: 300px)"]),
722 ]),
723 );
724
725 expected_result.insert(
726 "marginInlineStart".to_string(),
727 pre_rule_set_factory(&[
728 pre_rule_factory("marginInlineStart", "0", &["marginInlineStart", "default"]),
729 pre_rule_factory("marginInlineStart", "10", &["marginInlineStart", ":hover"]),
730 ]),
731 );
732 expected_result.insert(
733 "marginLeft".to_string(),
734 pre_rule_set_factory(&[null_rule_factory(), null_rule_factory()]),
735 );
736
737 expected_result.insert(
738 "marginRight".to_string(),
739 pre_rule_set_factory(&[null_rule_factory(), null_rule_factory()]),
740 );
741
742 assert_eq!(result, expected_result)
743 }
744
745 #[test]
746 fn attribute_selector_conditions() {
747 let result = flatten_raw_style_object(
748 &[create_key_value_prop_ident(
749 "color",
750 create_object_expression(vec![
751 create_string_key_value_prop("default", "blue"),
752 create_string_key_value_prop("[data-panel-state=\"open\"]", "red"),
753 ]),
754 )],
755 &mut EvaluationState::new(),
756 &mut get_state(),
757 &FunctionMap::default(),
758 );
759
760 assert_eq!(result.len(), 1);
761
762 let mut expected_result = IndexMap::new();
763
764 expected_result.insert(
765 "color".to_string(),
766 pre_rule_set_factory(&[
767 pre_rule_factory("color", "blue", &["color", "default"]),
768 pre_rule_factory("color", "red", &["color", "[data-panel-state=\"open\"]"]),
769 ]),
770 );
771
772 assert_eq!(result, expected_result)
773 }
774}
775
776#[cfg(test)]
777mod multiple_levels_of_nesting {
778 use indexmap::IndexMap;
779
780 use stylex_ast::ast::factories::{
781 create_key_value_prop_ident,
782 create_nested_object_prop,
783 create_object_expression,
784 create_string_array_prop,
785 create_string_key_value_prop,
786 };
787 use crate::shared::structures::functions::FunctionMap;
788 use crate::shared::structures::state::EvaluationState;
789 use crate::shared::structures::tests::flatten_raw_style_objects_test::flatten_style_object_with_legacy_shorthand_expansion::{
790 get_state,
791 pre_rule_factory,
792 pre_rule_set_factory,
793 pre_rule_vec_factory,
794 };
795 use crate::shared::utils::core::flatten_raw_style_object::flatten_raw_style_object;
796
797 #[test]
798 fn fallback_styles_within_nested_objects() {
799 let result = flatten_raw_style_object(
800 &[create_key_value_prop_ident(
801 "margin",
802 create_object_expression(vec![
803 create_string_key_value_prop("default", "1px 2px 3px 4px"),
804 create_string_array_prop(":hover", &["10px 20px", "1dvh 2dvh"]),
805 ]),
806 )],
807 &mut EvaluationState::new(),
808 &mut get_state(),
809 &FunctionMap::default(),
810 );
811
812 assert_eq!(result.len(), 4);
813
814 let mut expected_result = IndexMap::new();
815
816 expected_result.insert(
817 "marginTop".to_string(),
818 pre_rule_set_factory(&[
819 pre_rule_factory("marginTop", "1px", &["marginTop", "default"]),
820 pre_rule_vec_factory("marginTop", &["10px", "1dvh"], &["marginTop", ":hover"]),
821 ]),
822 );
823
824 expected_result.insert(
825 "marginInlineEnd".to_string(),
826 pre_rule_set_factory(&[
827 pre_rule_factory("marginInlineEnd", "2px", &["marginInlineEnd", "default"]),
828 pre_rule_vec_factory(
829 "marginInlineEnd",
830 &["20px", "2dvh"],
831 &["marginInlineEnd", ":hover"],
832 ),
833 ]),
834 );
835
836 expected_result.insert(
837 "marginBottom".to_string(),
838 pre_rule_set_factory(&[
839 pre_rule_factory("marginBottom", "3px", &["marginBottom", "default"]),
840 pre_rule_vec_factory(
841 "marginBottom",
842 &["10px", "1dvh"],
843 &["marginBottom", ":hover"],
844 ),
845 ]),
846 );
847
848 expected_result.insert(
849 "marginInlineStart".to_string(),
850 pre_rule_set_factory(&[
851 pre_rule_factory(
852 "marginInlineStart",
853 "4px",
854 &["marginInlineStart", "default"],
855 ),
856 pre_rule_vec_factory(
857 "marginInlineStart",
858 &["20px", "2dvh"],
859 &["marginInlineStart", ":hover"],
860 ),
861 ]),
862 );
863
864 assert_eq!(result, expected_result)
865 }
866
867 #[test]
868 fn pseudo_within_a_media_query_legacy_syntax() {
869 let result = flatten_raw_style_object(
870 &[create_key_value_prop_ident(
871 "@media (min-width: 300px)",
872 create_object_expression(vec![create_nested_object_prop(
873 ":hover",
874 vec![create_string_key_value_prop("color", "red")],
875 )]),
876 )],
877 &mut EvaluationState::new(),
878 &mut get_state(),
879 &FunctionMap::default(),
880 );
881
882 assert_eq!(result.len(), 1);
883
884 let mut expected_result = IndexMap::new();
885
886 expected_result.insert(
887 "@media (min-width: 300px)_:hover_color".to_string(),
888 pre_rule_set_factory(&[pre_rule_factory(
889 "color",
890 "red",
891 &["@media (min-width: 300px)", ":hover", "color"],
892 )]),
893 );
894
895 assert_eq!(result, expected_result)
896 }
897
898 #[test]
899 fn pseudo_with_a_pseudo_within_a_media_query_legacy_syntax() {
900 let result = flatten_raw_style_object(
901 &[create_key_value_prop_ident(
902 "@media (min-width: 300px)",
903 create_object_expression(vec![create_nested_object_prop(
904 ":hover",
905 vec![
906 create_string_key_value_prop("color", "pink"),
907 create_nested_object_prop(
908 ":active",
909 vec![create_string_key_value_prop("color", "red")],
910 ),
911 ],
912 )]),
913 )],
914 &mut EvaluationState::new(),
915 &mut get_state(),
916 &FunctionMap::default(),
917 );
918
919 assert_eq!(result.len(), 2);
920
921 let mut expected_result = IndexMap::new();
922
923 expected_result.insert(
924 "@media (min-width: 300px)_:hover_color".to_string(),
925 pre_rule_set_factory(&[pre_rule_factory(
926 "color",
927 "pink",
928 &["@media (min-width: 300px)", ":hover", "color"],
929 )]),
930 );
931
932 expected_result.insert(
933 "@media (min-width: 300px)_:hover_:active_color".to_string(),
934 pre_rule_set_factory(&[pre_rule_factory(
935 "color",
936 "red",
937 &["@media (min-width: 300px)", ":hover", ":active", "color"],
938 )]),
939 );
940
941 assert_eq!(result, expected_result)
942 }
943
944 #[test]
945 fn pseudo_within_a_media_query_modern_syntax() {
946 let result = flatten_raw_style_object(
947 &[create_key_value_prop_ident(
948 "color",
949 create_object_expression(vec![
950 create_string_key_value_prop("default", "blue"),
951 create_nested_object_prop(
952 "@media (min-width: 300px)",
953 vec![create_string_key_value_prop(":hover", "red")],
954 ),
955 ]),
956 )],
957 &mut EvaluationState::new(),
958 &mut get_state(),
959 &FunctionMap::default(),
960 );
961
962 assert_eq!(result.len(), 1);
963
964 let mut expected_result = IndexMap::new();
965
966 expected_result.insert(
967 "color".to_string(),
968 pre_rule_set_factory(&[
969 pre_rule_factory("color", "blue", &["color", "default"]),
970 pre_rule_factory(
971 "color",
972 "red",
973 &["color", "@media (min-width: 300px)", ":hover"],
974 ),
975 ]),
976 );
977
978 assert_eq!(result, expected_result)
979 }
980
981 #[test]
982 fn extra_deep_pseudo_within_a_media_query_modern_syntax() {
983 let result = flatten_raw_style_object(
984 &[create_key_value_prop_ident(
985 "color",
986 create_object_expression(vec![
987 create_string_key_value_prop("default", "blue"),
988 create_nested_object_prop(
989 "@media (min-width: 300px)",
990 vec![create_nested_object_prop(
991 ":hover",
992 vec![
993 create_string_key_value_prop("default", "red"),
994 create_string_key_value_prop(":active", "maroon"),
995 ],
996 )],
997 ),
998 ]),
999 )],
1000 &mut EvaluationState::new(),
1001 &mut get_state(),
1002 &FunctionMap::default(),
1003 );
1004
1005 assert_eq!(result.len(), 1);
1006
1007 let mut expected_result = IndexMap::new();
1008
1009 expected_result.insert(
1010 "color".to_string(),
1011 pre_rule_set_factory(&[
1012 pre_rule_factory("color", "blue", &["color", "default"]),
1013 pre_rule_factory(
1014 "color",
1015 "red",
1016 &["color", "@media (min-width: 300px)", ":hover", "default"],
1017 ),
1018 pre_rule_factory(
1019 "color",
1020 "maroon",
1021 &["color", "@media (min-width: 300px)", ":hover", ":active"],
1022 ),
1023 ]),
1024 );
1025
1026 assert_eq!(result, expected_result)
1027 }
1028}