Skip to main content

stylex_transform/shared/transformers/tests/
stylex_create_theme_test.rs

1#[cfg(test)]
2mod stylex_create_theme {
3
4  use indexmap::IndexMap;
5  use swc_core::ecma::ast::PropOrSpread;
6
7  use crate::shared::enums::data_structures::evaluate_result_value::EvaluateResultValue;
8  use crate::shared::structures::state_manager::StateManager;
9  use crate::shared::structures::types::InjectableStylesMap;
10  use crate::shared::transformers::stylex_create_theme::stylex_create_theme;
11  use crate::shared::utils::ast::convertors::create_string_expr;
12  use stylex_ast::ast::factories::{
13    create_key_value_prop, create_nested_object_prop, create_object_expression,
14    create_string_key_value_prop,
15  };
16  use stylex_types::structures::injectable_style::InjectableStyle;
17
18  fn default_vars_factory(args: &[(&str, &str)]) -> EvaluateResultValue {
19    let props = args
20      .iter()
21      .map(|(key, value)| create_string_key_value_prop(key, value))
22      .collect::<Vec<PropOrSpread>>();
23
24    EvaluateResultValue::Expr(create_object_expression(props))
25  }
26
27  fn exprected_result_factory(injected_styles: &[(&str, (&str, f64))]) -> InjectableStylesMap {
28    let mut expected_injected_styles = IndexMap::new();
29
30    for injected_style in injected_styles {
31      let (key, value) = injected_style;
32      expected_injected_styles.insert(
33        key.to_string(),
34        InjectableStyle::regular(value.0.to_string(), Some(value.1)),
35      );
36    }
37    expected_injected_styles
38  }
39
40  type StyleObjectFactoryArgs<'a> = [(
41    &'a str,
42    &'a [(&'a str, &'a str)],
43    &'a [(&'a str, &'a [(&'a str, &'a str)])],
44  )];
45
46  fn style_object_factory(
47    args: &StyleObjectFactoryArgs,
48    str_args: &[(&str, &str)],
49  ) -> EvaluateResultValue {
50    let mut props = args
51      .iter()
52      .map(|(key, values, nested_values)| {
53        let mut props = values
54          .iter()
55          .map(|(key, value)| create_key_value_prop(key, create_string_expr(value)))
56          .collect::<Vec<PropOrSpread>>();
57
58        let nested_props = nested_values
59          .iter()
60          .map(|val| {
61            let props = val
62              .1
63              .iter()
64              .map(|(key, value)| create_key_value_prop(key, create_string_expr(value)))
65              .collect::<Vec<PropOrSpread>>();
66
67            create_key_value_prop(val.0, create_object_expression(props))
68          })
69          .collect::<Vec<PropOrSpread>>();
70
71        props.extend(nested_props);
72
73        create_nested_object_prop(key, props)
74      })
75      .collect::<Vec<PropOrSpread>>();
76
77    for (key, value) in str_args.iter() {
78      props.push(create_string_key_value_prop(key, value));
79    }
80
81    EvaluateResultValue::Expr(create_object_expression(props))
82  }
83
84  #[test]
85  fn overrides_set_of_vars_with_css_class() {
86    let export_id = "TestTheme.stylex.js//buttonTheme";
87
88    let mut default_vars = default_vars_factory(&[
89      ("__varGroupHash__", export_id),
90      ("bgColor", "var(--xgck17p)"),
91      ("bgColorDisabled", "var(--xpegid5)"),
92      ("cornerRadius", "var(--xrqfjmn)"),
93      ("fgColor", "var(--x4y59db)"),
94    ]);
95
96    let created_theme = style_object_factory(
97      &[
98        (
99          "bgColor",
100          &[
101            ("default", "green"),
102            ("@media (prefers-color-scheme: dark)", "lightgreen"),
103            ("@media print", "transparent"),
104          ],
105          &[],
106        ),
107        (
108          "bgColorDisabled",
109          &[
110            ("default", "antiquewhite"),
111            ("@media (prefers-color-scheme: dark)", "floralwhite"),
112          ],
113          &[],
114        ),
115        ("cornerRadius", &[("default", "6px")], &[]),
116      ],
117      &[("fgColor", "coral")],
118    );
119
120    let (class_name_output, css_output) = stylex_create_theme(
121      &mut default_vars,
122      &created_theme,
123      &mut StateManager::default(),
124      &mut IndexMap::default(),
125    );
126
127    let key = class_name_output
128      .get(export_id)
129      .unwrap()
130      .as_string()
131      .unwrap()
132      .split(' ')
133      .next()
134      .unwrap();
135
136    let injectable_rule = css_output.get(key).unwrap();
137
138    assert_eq!(
139      injectable_rule,
140      exprected_result_factory(&[(
141        export_id,
142        (
143          ".xtrlmmh, .xtrlmmh:root{--xgck17p:green;--xpegid5:antiquewhite;--xrqfjmn:6px;--x4y59db:coral;}",
144          0.5
145        )
146      )])
147      .get(export_id)
148      .unwrap()
149    )
150  }
151
152  #[test]
153  fn overrides_set_of_literal_vars_with_css_class() {
154    let export_id = "TestTheme.stylex.js//buttonTheme";
155
156    let mut default_vars = default_vars_factory(&[
157      ("__varGroupHash__", export_id),
158      ("--bgColor", "var(--bgColor)"),
159      ("--bgColorDisabled", "var(--bgColorDisabled)"),
160      ("--cornerRadius", "var(--cornerRadius)"),
161      ("--fgColor", "var(--fgColor)"),
162    ]);
163
164    let created_theme = style_object_factory(
165      &[
166        (
167          "--bgColor",
168          &[
169            ("default", "green"),
170            ("@media (prefers-color-scheme: dark)", "lightgreen"),
171            ("@media print", "transparent"),
172          ],
173          &[],
174        ),
175        (
176          "--bgColorDisabled",
177          &[
178            ("default", "antiquewhite"),
179            ("@media (prefers-color-scheme: dark)", "floralwhite"),
180          ],
181          &[],
182        ),
183        ("--cornerRadius", &[("default", "6px")], &[]),
184      ],
185      &[("--fgColor", "coral")],
186    );
187
188    let (class_name_output, css_output) = stylex_create_theme(
189      &mut default_vars,
190      &created_theme,
191      &mut StateManager::default(),
192      &mut IndexMap::default(),
193    );
194
195    let key = class_name_output
196      .get(export_id)
197      .unwrap()
198      .as_string()
199      .unwrap()
200      .split(' ')
201      .next()
202      .unwrap();
203
204    let injectable_rule = css_output.get(key).unwrap();
205
206    assert_eq!(
207      injectable_rule,
208      exprected_result_factory(&[(
209        export_id,
210        (
211          ".x4znj40, .x4znj40:root{--bgColor:green;--bgColorDisabled:antiquewhite;--cornerRadius:6px;--fgColor:coral;}",
212          0.5
213        )
214      )])
215      .get(export_id)
216      .unwrap()
217    )
218  }
219
220  #[test]
221  fn variables_order_does_not_change_the_hash() {
222    let export_id = "TestTheme.stylex.js//buttonTheme";
223
224    let mut default_vars = default_vars_factory(&[
225      ("__varGroupHash__", export_id),
226      ("bgColor", "var(--xgck17p)"),
227      ("bgColorDisabled", "var(--xpegid5)"),
228      ("cornerRadius", "var(--xrqfjmn)"),
229      ("fgColor", "var(--x4y59db)"),
230    ]);
231
232    let created_theme = style_object_factory(
233      &[
234        (
235          "bgColor",
236          &[
237            ("default", "green"),
238            ("@media (prefers-color-scheme: dark)", "lightgreen"),
239            ("@media print", "transparent"),
240          ],
241          &[],
242        ),
243        (
244          "bgColorDisabled",
245          &[
246            ("default", "antiquewhite"),
247            ("@media (prefers-color-scheme: dark)", "floralwhite"),
248          ],
249          &[],
250        ),
251        ("cornerRadius", &[("default", "6px")], &[]),
252      ],
253      &[("fgColor", "coral")],
254    );
255
256    let created_theme_2 = style_object_factory(
257      &[
258        ("cornerRadius", &[("default", "6px")], &[]),
259        (
260          "bgColorDisabled",
261          &[
262            ("default", "antiquewhite"),
263            ("@media (prefers-color-scheme: dark)", "floralwhite"),
264          ],
265          &[],
266        ),
267        (
268          "bgColor",
269          &[
270            ("default", "green"),
271            ("@media (prefers-color-scheme: dark)", "lightgreen"),
272            ("@media print", "transparent"),
273          ],
274          &[],
275        ),
276      ],
277      &[("fgColor", "coral")],
278    );
279
280    let (class_name_output, css_output) = stylex_create_theme(
281      &mut default_vars,
282      &created_theme,
283      &mut StateManager::default(),
284      &mut IndexMap::default(),
285    );
286
287    let (class_name_output_2, css_output_2) = stylex_create_theme(
288      &mut default_vars,
289      &created_theme_2,
290      &mut StateManager::default(),
291      &mut IndexMap::default(),
292    );
293
294    assert_eq!(class_name_output, class_name_output_2);
295
296    let key = class_name_output
297      .get(export_id)
298      .unwrap()
299      .as_string()
300      .unwrap()
301      .split(' ')
302      .next()
303      .unwrap();
304
305    let key_2 = class_name_output_2
306      .get(export_id)
307      .unwrap()
308      .as_string()
309      .unwrap()
310      .split(' ')
311      .next()
312      .unwrap();
313
314    let injectable_rule = css_output.get(key).unwrap();
315    let injectable_rule_2 = css_output_2.get(key_2).unwrap();
316
317    assert_eq!(injectable_rule, injectable_rule_2);
318  }
319
320  #[test]
321  fn adding_an_at_rule_changes_the_hash() {
322    let export_id = "TestTheme.stylex.js//buttonTheme";
323
324    let mut default_vars = default_vars_factory(&[
325      ("__varGroupHash__", export_id),
326      ("bgColor", "var(--xgck17p)"),
327    ]);
328
329    let created_theme = style_object_factory(&[], &[("bgColor", "green")]);
330
331    let created_theme_2 = style_object_factory(
332      &[(
333        "bgColor",
334        &[
335          ("default", "green"),
336          ("@media (prefers-color-scheme: dark)", "lightgreen"),
337        ],
338        &[],
339      )],
340      &[],
341    );
342
343    let (class_name_output, css_output) = stylex_create_theme(
344      &mut default_vars,
345      &created_theme,
346      &mut StateManager::default(),
347      &mut IndexMap::default(),
348    );
349
350    let (class_name_output_2, css_output_2) = stylex_create_theme(
351      &mut default_vars,
352      &created_theme_2,
353      &mut StateManager::default(),
354      &mut IndexMap::default(),
355    );
356
357    assert_ne!(class_name_output, class_name_output_2);
358
359    let key = class_name_output
360      .get(export_id)
361      .unwrap()
362      .as_string()
363      .unwrap()
364      .split(' ')
365      .next()
366      .unwrap();
367
368    let key_2 = class_name_output_2
369      .get(export_id)
370      .unwrap()
371      .as_string()
372      .unwrap()
373      .split(' ')
374      .next()
375      .unwrap();
376
377    let injectable_rule = css_output.get(key).unwrap();
378    let injectable_rule_2 = css_output_2.get(key_2).unwrap();
379
380    assert_ne!(injectable_rule, injectable_rule_2);
381  }
382
383  #[test]
384  fn generates_styles_for_nested_at_rules() {
385    let export_id = "TestTheme.stylex.js//buttonTheme";
386
387    let mut default_vars = default_vars_factory(&[
388      ("__varGroupHash__", export_id),
389      ("bgColor", "var(--xgck17p)"),
390    ]);
391
392    let created_theme = style_object_factory(
393      &[(
394        "bgColor",
395        &[
396          ("default", "green"),
397          ("@supports (color: oklab(0 0 0))", "oklab(0.7 -0.3 -0.4)"),
398        ],
399        &[(
400          "@media (prefers-color-scheme: dark)",
401          &[
402            ("default", "lightgreen"),
403            ("@supports (color: oklab(0 0 0))", "oklab(0.7 -0.2 -0.4)"),
404          ],
405        )],
406      )],
407      &[],
408    );
409
410    let (_class_name_output, css_output) = stylex_create_theme(
411      &mut default_vars,
412      &created_theme,
413      &mut StateManager::default(),
414      &mut IndexMap::default(),
415    );
416
417    assert_eq!(
418      css_output,
419      exprected_result_factory(&[
420        (
421          "x2y918k",
422          (".x2y918k, .x2y918k:root{--xgck17p:green;}", 0.5)
423        ),
424        (
425          "x2y918k-1lveb7",
426          (
427            "@media (prefers-color-scheme: dark){.x2y918k, .x2y918k:root{--xgck17p:lightgreen;}}",
428            0.6
429          )
430        ),
431        (
432          "x2y918k-1e6ryz3",
433          (
434            "@supports (color: oklab(0 0 0)){@media (prefers-color-scheme: dark){.x2y918k, .x2y918k:root{--xgck17p:oklab(0.7 -0.2 -0.4);}}}",
435            0.7
436          )
437        ),
438        (
439          "x2y918k-kpd015",
440          (
441            "@supports (color: oklab(0 0 0)){.x2y918k, .x2y918k:root{--xgck17p:oklab(0.7 -0.3 -0.4);}}",
442            0.6
443          )
444        )
445      ])
446    )
447  }
448
449  #[test]
450  fn generates_styles_for_typed_nested_at_rules() {
451    let export_id = "TestTheme.stylex.js//buttonTheme";
452
453    let mut default_vars = default_vars_factory(&[
454      ("__varGroupHash__", export_id),
455      ("bgColor", "var(--xgck17p)"),
456    ]);
457
458    let created_theme = style_object_factory(
459      &[(
460        "bgColor",
461        &[],
462        &[
463          (
464            "default",
465            &[
466              ("default", "green"),
467              ("@supports (color: oklab(0 0 0))", "oklab(0.7 -0.3 -0.4)"),
468            ],
469          ),
470          (
471            "@media (prefers-color-scheme: dark)",
472            &[
473              ("default", "lightgreen"),
474              ("@supports (color: oklab(0 0 0))", "oklab(0.7 -0.2 -0.4)"),
475            ],
476          ),
477        ],
478      )],
479      &[],
480    );
481
482    let (_class_name_output, css_output) = stylex_create_theme(
483      &mut default_vars,
484      &created_theme,
485      &mut StateManager::default(),
486      &mut IndexMap::default(),
487    );
488
489    assert_eq!(
490      css_output,
491      exprected_result_factory(&[
492        (
493          "x2y918k",
494          (".x2y918k, .x2y918k:root{--xgck17p:green;}", 0.5)
495        ),
496        (
497          "x2y918k-1lveb7",
498          (
499            "@media (prefers-color-scheme: dark){.x2y918k, .x2y918k:root{--xgck17p:lightgreen;}}",
500            0.6
501          )
502        ),
503        (
504          "x2y918k-1e6ryz3",
505          (
506            "@supports (color: oklab(0 0 0)){@media (prefers-color-scheme: dark){.x2y918k, .x2y918k:root{--xgck17p:oklab(0.7 -0.2 -0.4);}}}",
507            0.7
508          )
509        ),
510        (
511          "x2y918k-kpd015",
512          (
513            "@supports (color: oklab(0 0 0)){.x2y918k, .x2y918k:root{--xgck17p:oklab(0.7 -0.3 -0.4);}}",
514            0.6
515          )
516        )
517      ])
518    )
519  }
520}