stylex_transform/shared/transformers/tests/
stylex_define_consts_test.rs1#[cfg(test)]
2mod stylex_define_consts {
3 use swc_core::ecma::ast::PropOrSpread;
4
5 use crate::shared::enums::data_structures::evaluate_result_value::EvaluateResultValue;
6 use crate::shared::structures::state_manager::StateManager;
7 use crate::shared::transformers::stylex_define_consts::stylex_define_consts;
8 use crate::shared::utils::ast::convertors::create_string_expr;
9 use crate::shared::utils::common::create_hash;
10 use stylex_ast::ast::factories::{create_key_value_prop, create_object_expression};
11 use stylex_structures::stylex_options::StyleXOptions;
12 use stylex_types::enums::data_structures::injectable_style::InjectableStyleKind;
13
14 fn create_test_state_manager(export_id: &str) -> StateManager {
15 let mut state = StateManager::new(StyleXOptions {
16 class_name_prefix: "x".to_string(),
17 debug: false,
18 enable_debug_class_names: false,
19 ..Default::default()
20 });
21 state.export_id = Some(export_id.to_string());
22 state
23 }
24
25 fn constants_factory(constants: &[(&str, &str)]) -> EvaluateResultValue {
26 let props = constants
27 .iter()
28 .map(|(key, value)| create_key_value_prop(key, create_string_expr(value)))
29 .collect::<Vec<PropOrSpread>>();
30
31 EvaluateResultValue::Expr(create_object_expression(props))
32 }
33
34 fn get_const_hash(export_id: &str, key: &str, class_name_prefix: &str) -> String {
35 format!(
36 "{}{}",
37 class_name_prefix,
38 create_hash(&format!("{}.{}", export_id, key))
39 )
40 }
41
42 #[test]
43 fn returns_correct_structure_for_basic_constants() {
44 let export_id = "TestTheme.stylex.js//buttonTheme";
45 let mut state = create_test_state_manager(export_id);
46
47 let constants =
48 constants_factory(&[("sm", "(min-width: 768px)"), ("md", "(min-width: 1024px)")]);
49
50 let (js_output, injectable_styles) = stylex_define_consts(&constants, &mut state);
51
52 assert_eq!(js_output.len(), 2);
53 assert_eq!(
54 js_output.get("sm").unwrap().as_string().unwrap(),
55 "(min-width: 768px)"
56 );
57 assert_eq!(
58 js_output.get("md").unwrap().as_string().unwrap(),
59 "(min-width: 1024px)"
60 );
61
62 let sm_hash = get_const_hash(export_id, "sm", "x");
63 let md_hash = get_const_hash(export_id, "md", "x");
64
65 assert!(injectable_styles.contains_key(&sm_hash));
66 assert!(injectable_styles.contains_key(&md_hash));
67
68 match injectable_styles.get(&sm_hash).unwrap().as_ref() {
69 InjectableStyleKind::Const(style) => {
70 assert_eq!(style.const_value, "(min-width: 768px)");
71 assert_eq!(style.ltr, "");
72 assert_eq!(style.rtl, None);
73 assert_eq!(style.priority, Some(0.0));
74 },
75 _ => panic!("Expected InjectableStyleKind::Const"),
76 }
77
78 match injectable_styles.get(&md_hash).unwrap().as_ref() {
79 InjectableStyleKind::Const(style) => {
80 assert_eq!(style.const_value, "(min-width: 1024px)");
81 assert_eq!(style.ltr, "");
82 assert_eq!(style.rtl, None);
83 assert_eq!(style.priority, Some(0.0));
84 },
85 _ => panic!("Expected InjectableStyleKind::Const"),
86 }
87
88 assert_ne!(sm_hash, md_hash);
89 }
90
91 #[test]
92 fn handles_special_characters_in_keys() {
93 let export_id = "TestTheme.stylex.js//buttonTheme";
94 let mut state = create_test_state_manager(export_id);
95
96 let constants = constants_factory(&[("max-width", "1200px"), ("font-size*large", "18px")]);
97
98 let (js_output, injectable_styles) = stylex_define_consts(&constants, &mut state);
99
100 assert_eq!(js_output.len(), 2);
101 assert_eq!(
102 js_output.get("max-width").unwrap().as_string().unwrap(),
103 "1200px"
104 );
105 assert_eq!(
106 js_output
107 .get("font-size*large")
108 .unwrap()
109 .as_string()
110 .unwrap(),
111 "18px"
112 );
113
114 let max_width_hash = get_const_hash(export_id, "max-width", "x");
115 let font_size_hash = get_const_hash(export_id, "font-size*large", "x");
116
117 assert!(injectable_styles.contains_key(&max_width_hash));
118 assert!(injectable_styles.contains_key(&font_size_hash));
119
120 assert_ne!(max_width_hash, font_size_hash);
121 }
122
123 #[test]
124 fn handles_numeric_keys() {
125 let export_id = "TestTheme.stylex.js//buttonTheme";
126 let mut state = create_test_state_manager(export_id);
127
128 let constants = constants_factory(&[("1", "one"), ("2", "two")]);
129
130 let (js_output, injectable_styles) = stylex_define_consts(&constants, &mut state);
131
132 assert_eq!(js_output.len(), 2);
133 assert_eq!(js_output.get("1").unwrap().as_string().unwrap(), "one");
134 assert_eq!(js_output.get("2").unwrap().as_string().unwrap(), "two");
135
136 let hash_1 = get_const_hash(export_id, "1", "x");
137 let hash_2 = get_const_hash(export_id, "2", "x");
138
139 assert!(injectable_styles.contains_key(&hash_1));
140 assert!(injectable_styles.contains_key(&hash_2));
141
142 assert_ne!(hash_1, hash_2);
143 }
144
145 #[test]
146 fn generates_consistent_hashes_for_identical_constants() {
147 let export_id = "TestTheme.stylex.js//buttonTheme";
148 let mut state1 = create_test_state_manager(export_id);
149 let mut state2 = create_test_state_manager(export_id);
150
151 let constants = constants_factory(&[("padding", "10px")]);
152
153 let (js_output1, styles1) = stylex_define_consts(&constants, &mut state1);
154 let (js_output2, styles2) = stylex_define_consts(&constants, &mut state2);
155
156 let key_hash = get_const_hash(export_id, "padding", "x");
157
158 assert_eq!(js_output1, js_output2);
159
160 assert!(styles1.contains_key(&key_hash));
161 assert!(styles2.contains_key(&key_hash));
162
163 match (
164 styles1.get(&key_hash).unwrap().as_ref(),
165 styles2.get(&key_hash).unwrap().as_ref(),
166 ) {
167 (InjectableStyleKind::Const(style1), InjectableStyleKind::Const(style2)) => {
168 assert_eq!(style1.const_key, style2.const_key);
169 },
170 _ => panic!("Expected InjectableStyleKind::Const"),
171 }
172 }
173
174 #[test]
175 fn generates_different_hashes_for_different_constants() {
176 let export_id = "TestTheme.stylex.js//buttonTheme";
177 let mut state1 = create_test_state_manager(export_id);
178 let mut state2 = create_test_state_manager(export_id);
179
180 let constants1 = constants_factory(&[("padding", "10px")]);
181 let constants2 = constants_factory(&[("margin", "10px")]);
182
183 let (_, styles1) = stylex_define_consts(&constants1, &mut state1);
184 let (_, styles2) = stylex_define_consts(&constants2, &mut state2);
185
186 let padding_key = get_const_hash(export_id, "padding", "x");
187 let margin_key = get_const_hash(export_id, "margin", "x");
188
189 assert_ne!(padding_key, margin_key);
190
191 assert!(styles1.contains_key(&padding_key));
192 assert!(styles2.contains_key(&margin_key));
193
194 match (
195 styles1.get(&padding_key).unwrap().as_ref(),
196 styles2.get(&margin_key).unwrap().as_ref(),
197 ) {
198 (InjectableStyleKind::Const(style1), InjectableStyleKind::Const(style2)) => {
199 assert_ne!(style1.const_key, style2.const_key);
200 },
201 _ => panic!("Expected InjectableStyleKind::Const"),
202 }
203 }
204
205 #[test]
206 fn preserves_object_keys() {
207 let export_id = "TestTheme.stylex.js//buttonTheme";
208 let mut state = create_test_state_manager(export_id);
209
210 let constants = constants_factory(&[("borderRadius", "8px"), ("colorPrimary", "#ff0000")]);
211
212 let (js_output, _) = stylex_define_consts(&constants, &mut state);
213
214 let keys: Vec<&String> = js_output.keys().collect();
215 assert_eq!(keys.len(), 2);
216 assert!(keys.contains(&&"borderRadius".to_string()));
217 assert!(keys.contains(&&"colorPrimary".to_string()));
218 }
219
220 #[test]
221 fn throws_an_error_for_keys_that_start_with_double_dash() {
222 let export_id = "TestTheme.stylex.js//buttonTheme";
223 let mut state = create_test_state_manager(export_id);
224
225 let constants = constants_factory(&[("--custom-var", "red")]);
226
227 let (js_output, _) = stylex_define_consts(&constants, &mut state);
228
229 assert_eq!(js_output.len(), 1);
230 assert_eq!(
231 js_output.get("--custom-var").unwrap().as_string().unwrap(),
232 "red"
233 );
234 }
235}