euv-cli 0.25.21

The official CLI tool for the euv UI framework, providing dev/release profiles with run/build modes, hot reload, and wasm-pack integration.
Documentation
use super::*;

#[test]
fn test_simple_if() {
    let input: &str = "if{a}{b}";
    let expected: &str = "if { a } {\n    b\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_if_with_else() {
    let input: &str = "if{a}{b}else{c}";
    let expected: &str = "if { a } {\n    b\n} else {\n    c\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_if_else_if_else() {
    let input: &str = "if{a}{b}else if{c}{d}else{e}";
    let expected: &str = "if { a } {\n    b\n} else if { c } {\n    d\n} else {\n    e\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_nested_if() {
    let input: &str = "if{a}{if{b}{c}}";
    let expected: &str = "if { a } {\n    if { b } {\n        c\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_match_single_arm() {
    let input: &str = "match{a}{\"b\"=>{c}}";
    let expected: &str = "match { a } {\n    \"b\" => {\n        c\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_match_multiple_arms() {
    let input: &str = "match{a}{\"b\"=>{c}\"d\"=>{e}}";
    let expected: &str =
        "match { a } {\n    \"b\" => {\n        c\n    }\n    \"d\" => {\n        e\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_for_loop_bare_expr() {
    let input: &str = "for i in a.iter(){b}";
    let expected: &str = "for i in a.iter() {\n    b\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_for_loop_bare_expr_chain() {
    let input: &str = "for (i, v) in a.iter().enumerate(){b}";
    let expected: &str = "for (i, v) in a.iter().enumerate() {\n    b\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_for_loop_braced_expr_unchanged() {
    let input: &str = "for i in {a}{b}";
    let expected: &str = "for i in { a } {\n    b\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_simple_div() {
    let input: &str = "div{a}";
    let expected: &str = "div {\n    a\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_nested_div() {
    let input: &str = "div{a{b}c}";
    let expected: &str = "div {\n    a {\n        b\n    }\n    c\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_empty_block() {
    let input: &str = "div{}";
    let expected: &str = "div {}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_bare_empty_block() {
    let input: &str = "{}";
    let expected: &str = "{}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_string_in_body() {
    let input: &str = "div{\"hello\"}";
    let expected: &str = "div {\n    \"hello\"\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_braces_in_string() {
    let input: &str = "div{\"hello { world }\"}";
    let expected: &str = "div {\n    \"hello { world }\"\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_comment_in_body() {
    let input: &str = "div{// comment\n    a\n}";
    let expected: &str = "div {\n    // comment\n    a\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_class_macro() {
    let input: &str = "class!{c_app_root{display:\"flex\"}}";
    let expected: &str = "class!{\n    c_app_root {\n        display: \"flex\"\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_vars_macro() {
    let input: &str = "vars!{a:\"1\";b:\"2\"}";
    let expected: &str = "vars!{\n    a: \"1\";b: \"2\"\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_deeply_nested() {
    let input: &str = "div{a{div{b{div{c}}}}}";
    let expected: &str = concat!(
        "div {\n",
        "    a {\n",
        "        div {\n",
        "            b {\n",
        "                div {\n",
        "                    c\n",
        "                }\n",
        "            }\n",
        "        }\n",
        "    }\n",
        "}"
    );
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_multiple_siblings() {
    let input: &str = "div{a\n    b\n    c}";
    let expected: &str = "div {\n    a\n    b\n    c\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_if_with_complex_condition() {
    let input: &str = "if{a>0}{b}";
    let expected: &str = "if { a>0 } {\n    b\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_watch_macro() {
    let input: &str = "watch!{signal=>{callback}}";
    let expected: &str = "watch!{\n    signal => {\n        callback\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_pseudo_selector() {
    let input: &str = "div{:hover{color:\"red\"}}";
    let expected: &str = "div {\n    :hover {\n        color: \"red\"\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_media_query() {
    let input: &str = "div{@media{(max-width: 767px){display:\"none\"}}}";
    let expected: &str = "div {\n    @media {\n        (max-width: 767px){\n            display: \"none\"\n        }\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_block_comment() {
    let input: &str = "div{a}";
    let expected: &str = "div {\n    a\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_escape_in_string() {
    let input: &str = "div{\"hello \\\"world\\\"\"}";
    let expected: &str = "div {\n    \"hello \\\"world\\\"\"\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_attribute_with_if() {
    let input: &str = "class:if{a}{b}else{c}";
    let expected: &str = "class: if { a } {\n    b\n} else {\n    c\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_nested_match_in_if() {
    let input: &str = "if{a}{match{b}{\"c\"=>{d}}}";
    let expected: &str =
        "if { a } {\n    match { b } {\n        \"c\" => {\n            d\n        }\n    }\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_empty_line_preservation() {
    let input: &str = "div{a\n\n    b}";
    let expected: &str = "div {\n    a\n\n    b\n}";
    assert_eq!(format_macro_body(input), expected);
}

#[test]
fn test_format_euv_macros_html() {
    let input: &str = "html! {if{a}{b}}";
    let expected: &str = "html! {\n    if { a } {\n        b\n    }\n}";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_format_euv_macros_class() {
    let input: &str = "class! {c{display:\"flex\"}}";
    let expected: &str = "class! {\n    c {\n        display: \"flex\"\n    }\n}";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_format_euv_macros_vars() {
    let input: &str = "vars! {a:\"1\"}";
    let expected: &str = "vars! {\n    a: \"1\"\n}";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_format_euv_macros_watch() {
    let input: &str = "watch! {s => {f}}";
    let expected: &str = "watch! {\n    s => {\n        f\n    }\n}";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_format_euv_macros_no_leading_blank_lines() {
    let input: &str = "    html! {\n            div {\n                class: c_euv_input_wrapper()\n                label {\n                    for: id\n                    class: c_form_label()\n                    label_string\n                }\n                input {\n                    id: id\n                    name: id\n                    type: \"text\"\n                    placeholder: placeholder\n                    value: value\n                    autocomplete: autocomplete\n                    class: c_euv_input()\n                    onfocus: on_focus_scroll_into_view()\n                }\n            }\n        }";
    let expected: &str = "    html! {\n            div {\n                class: c_euv_input_wrapper()\n                label {\n                    for: id\n                    class: c_form_label()\n                    label_string\n                }\n                input {\n                    id: id\n                    name: id\n                    type: \"text\"\n                    placeholder: placeholder\n                    value: value\n                    autocomplete: autocomplete\n                    class: c_euv_input()\n                    onfocus: on_focus_scroll_into_view()\n                }\n            }\n    }";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_sibling_elements() {
    let input: &str = "html! {\n    euv_vconsole_fab {\n        panel_open: panel_open\n        console_signal: console_signal\n    }\n    euv_vconsole_drawer {\n        console_signal: console_signal\n        panel_open: panel_open\n    }\n}";
    let expected: &str = "html! {\n    euv_vconsole_fab {\n        panel_open: panel_open\n        console_signal: console_signal\n    }\n    euv_vconsole_drawer {\n        console_signal: console_signal\n        panel_open: panel_open\n    }\n}";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_sibling_elements_with_indent() {
    let input: &str = "    html! {\n            euv_vconsole_fab {\n                panel_open: panel_open\n                console_signal: console_signal\n            }\n            euv_vconsole_drawer {\n                console_signal: console_signal\n                panel_open: panel_open\n            }\n        }";
    let expected: &str = "    html! {\n            euv_vconsole_fab {\n                panel_open: panel_open\n                console_signal: console_signal\n            }\n            euv_vconsole_drawer {\n                console_signal: console_signal\n                panel_open: panel_open\n            }\n    }";
    assert_eq!(format_euv_macros(input), expected);
}

#[test]
fn test_sibling_elements_compressed() {
    let input: &str = "html!{euv_vconsole_fab{panel_open:panel_open console_signal:console_signal}euv_vconsole_drawer{console_signal:console_signal panel_open:panel_open}}";
    let expected: &str = "html! {\n    euv_vconsole_fab {\n        panel_open: panel_open\n        console_signal: console_signal\n    }\n    euv_vconsole_drawer {\n        console_signal: console_signal\n        panel_open: panel_open\n    }\n}";
    assert_eq!(format_euv_macros(input), expected);
}

/// Regression: block comments inside macro bodies with internal whitespace
/// must not drift on repeated fmt runs. Previously each run added 4 spaces of
/// indentation to comment continuation lines, so running `euv fmt` repeatedly
/// produced different output each time (compounding indent).
#[test]
fn test_block_comment_idempotent_in_class_macro() {
    let inner_indent: &str = "    ";
    let body: String = format!(
        "class! {{\n{inner_indent}pub c_test {{\n{inner_indent}{inner_indent}/* `width: 100%` instead of `min-width: 140px` so the menu\n{ws}matches the dropdown container (and therefore the\n{ws}trigger button) width exactly. With only `min-width`,\n{ws}a trigger wider than 140px (e.g. the 206px-wide\n{ws}nav-column locale switcher button) leaves a large\n{ws}empty gap on the left of the menu, since `right: 0`\n{ws}anchors only the right edge to the container. With\n{ws}`width: 100%`, the menu's left edge lines up with the\n{ws}trigger's left edge. The default minimum content width\n{ws}is still guaranteed by the inner items' own padding,\n{ws}so we keep the rule without an explicit min. */\n{inner_indent}{inner_indent}color: \"red\";\n{inner_indent}}}\n}}",
        ws = " ".repeat(135),
    );
    let once: String = format_euv_macros(&body);
    let twice: String = format_euv_macros(&once);
    assert_eq!(
        once, twice,
        "format_euv_macros must be idempotent on block comments with internal whitespace"
    );
}

/// Regression: format_macro_body on a class! body containing a block comment
/// with deep internal indent must also be idempotent at the body level.
#[test]
fn test_block_comment_idempotent_in_macro_body() {
    let input: &str = "class! {c_test {/* line one\n                                                                                                                                                           line two\n                                                                                                                                                           line three */\n        color: \"red\";}}";
    let once: String = format_macro_body(input);
    let twice: String = format_macro_body(&once);
    assert_eq!(
        once, twice,
        "format_macro_body must be idempotent on block comments with internal whitespace"
    );
}

/// Regression: repeated fmt runs on a macro body containing a block comment
/// with deep internal indent must not compound indent on continuation lines.
/// (The fix preserves the comment's original internal whitespace but
/// prevents `indented_body` from re-prepending indentation to lines that
/// are continuations of `/* ... */` regions.)
#[test]
fn test_block_comment_continuation_lines_normalized() {
    let inner_indent: &str = "    ";
    let body: String = format!(
        "class! {{\n{inner_indent}c_test {{\n{inner_indent}{inner_indent}/* short\n{ws}continuation\n{ws}lines */\n{inner_indent}{inner_indent}color: \"red\";\n{inner_indent}}}\n}}",
        ws = " ".repeat(135),
    );
    let once: String = format_euv_macros(&body);
    let twice: String = format_euv_macros(&once);
    let thrice: String = format_euv_macros(&twice);
    assert_eq!(
        once, twice,
        "format_euv_macros must be idempotent (run 1 vs 2)"
    );
    assert_eq!(
        twice, thrice,
        "format_euv_macros must be idempotent (run 2 vs 3)"
    );
}