hers 0.1.0

HTML Embedded Rust - Runtime types and utilities
Documentation
use hers::hers;

#[test]
fn test_simple_div() {
    let result = hers! {
        <div>Hello</div>
    };

    assert_eq!(result.as_str(), "<div>Hello</div>");
}

#[test]
fn test_variable_interpolation() {
    let name = "Alice";
    let result = hers! {
        <div>{name}</div>
    };

    assert_eq!(result.as_str(), "<div>Alice</div>");
}

#[test]
fn test_nested_elements() {
    let result = hers! {
        <div><h1>Title</h1></div>
    };

    assert_eq!(result.as_str(), "<div><h1>Title</h1></div>");
}

#[test]
fn test_self_closing_tag() {
    let result = hers! {
        <img />
    };

    assert_eq!(result.as_str(), "<img />");
}

#[test]
fn test_html_escaping() {
    let user_input = "<script>alert('xss')</script>";
    let result = hers! {
        <div>{user_input}</div>
    };

    assert_eq!(
        result.as_str(),
        "<div>&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;</div>"
    );
}

#[test]
fn test_attributes() {
    let class_name = "container";
    let result = hers! {
        <div class={class_name}></div>
    };

    assert_eq!(result.as_str(), "<div class=\"container\"></div>");
}

#[test]
fn test_success_criteria_example() {
    let name = "Alice";
    let greeting = hers! {
        <div><h1>{name}</h1></div>
    };

    assert_eq!(greeting.as_str(), "<div><h1>Alice</h1></div>");
}

#[test]
fn test_basic_if_true() {
    let show = true;
    let result = hers! {
        <div>{if show { <span>Visible</span> }}</div>
    };

    assert_eq!(result.as_str(), "<div><span>Visible</span></div>");
}

#[test]
fn test_basic_if_false() {
    let show = false;
    let result = hers! {
        <div>{if show { <span>Hidden</span> }}</div>
    };

    assert_eq!(result.as_str(), "<div></div>");
}

#[test]
fn test_immediately_nested_if() {
    let outer = true;
    let inner = true;
    let result = hers! {
        <div>{if outer { {if inner { <span>Both true</span> }} }}</div>
    };

    assert_eq!(result.as_str(), "<div><span>Both true</span></div>");
}

#[test]
fn test_immediately_nested_if_inner_false() {
    let outer = true;
    let inner = false;
    let result = hers! {
        <div>{if outer { {if inner { <span>Inner true</span> }} }}</div>
    };

    assert_eq!(result.as_str(), "<div></div>");
}

#[test]
fn test_complex_nested_if_with_html() {
    let user_logged_in = true;
    let is_admin = false;
    let has_notifications = true;

    let result = hers! {
        <div class="header">
            <h1>Welcome</h1>
            {if user_logged_in {
                <nav>
                    <span>User Menu</span>
                    {if is_admin {
                        <a href="/admin">Admin Panel</a>
                    }}
                    {if has_notifications {
                        <div class="notifications">
                            <span>You have messages</span>
                        </div>
                    }}
                </nav>
            }}
            <footer>End</footer>
        </div>
    };

    let expected = "<div class=\"header\"><h1>Welcome</h1><nav><span>User Menu</span><div class=\"notifications\"><span>You have messages</span></div></nav><footer>End</footer></div>";
    assert_eq!(result.as_str(), expected);
}

#[test]
fn test_complex_nested_all_false() {
    let user_logged_in = false;
    let is_admin = false;
    let has_notifications = true;

    let result = hers! {
        <div class="header">
            <h1>Welcome</h1>
            {if user_logged_in {
                <nav>
                    <span>User Menu</span>
                    {if is_admin {
                        <a href="/admin">Admin Panel</a>
                    }}
                    {if has_notifications {
                        <div class="notifications">
                            <span>You have messages</span>
                        </div>
                    }}
                </nav>
            }}
            <footer>End</footer>
        </div>
    };

    let expected = "<div class=\"header\"><h1>Welcome</h1><footer>End</footer></div>";
    assert_eq!(result.as_str(), expected);
}

#[test]
fn test_multiple_if_statements_same_level() {
    let show_header = true;
    let show_content = false;
    let show_footer = true;

    let result = hers! {
        <div>
            {if show_header {
                <header>Header Content</header>
            }}
            {if show_content {
                <main>Main Content</main>
            }}
            {if show_footer {
                <footer>Footer Content</footer>
            }}
        </div>
    };

    let expected = "<div><header>Header Content</header><footer>Footer Content</footer></div>";
    assert_eq!(result.as_str(), expected);
}

#[test]
fn test_if_else_condition_true() {
    let is_logged_in = true;
    let result = hers! {
        <div>{if is_logged_in { <span>Welcome</span> } else { <span>Please login</span> }}</div>
    };

    assert_eq!(result.as_str(), "<div><span>Welcome</span></div>");
}

#[test]
fn test_if_else_condition_false() {
    let is_logged_in = false;
    let result = hers! {
        <div>{if is_logged_in { <span>Welcome</span> } else { <span>Please login</span> }}</div>
    };

    assert_eq!(result.as_str(), "<div><span>Please login</span></div>");
}

#[test]
fn test_nested_if_else() {
    let user_type = "admin";
    let is_active = true;

    let result = hers! {
        <div>
            {if user_type == "admin" {
                {if is_active {
                    <span class="admin-active">Admin Panel</span>
                } else {
                    <span class="admin-inactive">Admin (Inactive)</span>
                }}
            } else {
                <span class="user">User Dashboard</span>
            }}
        </div>
    };

    assert_eq!(
        result.as_str(),
        "<div><span class=\"admin-active\">Admin Panel</span></div>"
    );
}

#[test]
fn test_nested_if_else_outer_false() {
    let user_type = "user";
    let is_active = true;

    let result = hers! {
        <div>
            {if user_type == "admin" {
                {if is_active {
                    <span class="admin-active">Admin Panel</span>
                } else {
                    <span class="admin-inactive">Admin (Inactive)</span>
                }}
            } else {
                <span class="user">User Dashboard</span>
            }}
        </div>
    };

    assert_eq!(
        result.as_str(),
        "<div><span class=\"user\">User Dashboard</span></div>"
    );
}

#[test]
fn test_basic_for_loop() {
    let items = vec!["apple", "banana", "cherry"];
    let result = hers! {
        <ul>
            {for item in items {
                <li>{item}</li>
            }}
        </ul>
    };

    assert_eq!(
        result.as_str(),
        "<ul><li>apple</li><li>banana</li><li>cherry</li></ul>"
    );
}

#[test]
fn test_for_loop_with_index() {
    let items = ["first", "second"];
    let result = hers! {
        <ol>
            {for (i, item) in items.iter().enumerate() {
                <li>#{i + 1}: {item}</li>
            }}
        </ol>
    };

    assert_eq!(
        result.as_str(),
        "<ol><li>#1:first</li><li>#2:second</li></ol>"
    );
}

#[test]
fn test_empty_for_loop() {
    let items: Vec<&str> = vec![];
    let result = hers! {
        <div>
            <p>Items:</p>
            {for item in items {
                <span>{item}</span>
            }}
            <p>Done</p>
        </div>
    };

    assert_eq!(result.as_str(), "<div><p>Items :</p><p>Done</p></div>");
}

#[test]
fn test_nested_for_loops() {
    let rows = vec![vec!["A", "B"], vec!["C", "D"]];
    let result = hers! {
        <table>
            {for row in rows {
                <tr>
                    {for cell in row {
                        <td>{cell}</td>
                    }}
                </tr>
            }}
        </table>
    };

    assert_eq!(
        result.as_str(),
        "<table><tr><td>A</td><td>B</td></tr><tr><td>C</td><td>D</td></tr></table>"
    );
}

#[test]
fn test_for_loop_with_if() {
    let numbers = vec![1, 2, 3, 4, 5];
    let result = hers! {
        <div>
            {for num in numbers {
                {if num % 2 == 0 {
                    <span class="even">{num}</span>
                } else {
                    <span class="odd">{num}</span>
                }}
            }}
        </div>
    };

    assert_eq!(
        result.as_str(),
        "<div><span class=\"odd\">1</span><span class=\"even\">2</span><span class=\"odd\">3</span><span class=\"even\">4</span><span class=\"odd\">5</span></div>"
    );
}