mod common;
use jsxrs::render_string;
use serde_json::json;
use common::{extract_body, minimal_config};
#[test]
fn should_render_simple_div_when_given_basic_jsx() {
let source = r#"export default function Page() {
return <div>Hello</div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>Hello</div>");
}
#[test]
fn should_render_nested_elements_when_given_nested_jsx() {
let source = r#"export default function Page() {
return <div><span>inner</span></div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div><span>inner</span></div>");
}
#[test]
fn should_render_self_closing_tags_when_given_void_elements() {
let source = r#"export default function Page() {
return <div><br/><hr/></div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div><br><hr></div>");
}
#[test]
fn should_render_img_with_attributes_when_given_self_closing_element() {
let source = r#"export default function Page() {
return <img src="test.png" alt="test" />;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, r#"<img src="test.png" alt="test">"#);
}
#[test]
fn should_render_fragment_children_when_given_jsx_fragment() {
let source = r#"export default function Page() {
return <><div>first</div><span>second</span></>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>first</div><span>second</span>");
}
#[test]
fn should_render_mixed_text_and_elements_when_given_interleaved_content() {
let source = r#"export default function Page() {
return <div>Hello <strong>World</strong>!</div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>Hello <strong>World</strong>!</div>");
}
#[test]
fn should_render_deeply_nested_elements_when_given_multiple_nesting_levels() {
let source = r#"export default function Page() {
return <div><section><article><p>deep</p></article></section></div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(
body,
"<div><section><article><p>deep</p></article></section></div>"
);
}
#[test]
fn should_render_multiple_children_when_given_sibling_elements() {
let source = r#"export default function Page() {
return (
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
);
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<ul><li>one</li><li>two</li><li>three</li></ul>");
}
#[test]
fn should_render_props_in_text_when_given_jsx_expression_with_props() {
let source = r#"export default function Greeting(props) {
return <div>Hello, {props.name}!</div>;
}"#;
let config = minimal_config();
let props = json!({"name": "World"});
let result = render_string(source, "greeting.jsx", &props, &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>Hello, World!</div>");
}
#[test]
fn should_render_tsx_source_when_given_tsx_file_name() {
let source = r#"
interface Props {
name: string;
}
export default function Page(props: Props) {
return <div>{props.name}</div>;
}"#;
let config = minimal_config();
let props = json!({"name": "TypeScript"});
let result = render_string(source, "page.tsx", &props, &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>TypeScript</div>");
}
#[test]
fn should_render_arrow_function_default_export() {
let source = r#"const Page = () => <div>arrow</div>;
export default Page;"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>arrow</div>");
}
#[test]
fn should_render_number_prop_as_text_when_given_numeric_expression() {
let source = r#"export default function Page(props) {
return <span>{props.count}</span>;
}"#;
let config = minimal_config();
let props = json!({"count": 42});
let result = render_string(source, "page.jsx", &props, &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<span>42</span>");
}
#[test]
fn should_render_anonymous_arrow_default_export() {
let source = r#"export default () => <div>anon-arrow</div>;"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>anon-arrow</div>");
}
#[test]
fn should_render_anonymous_function_default_export() {
let source = r#"export default function() {
return <div>anon-fn</div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div>anon-fn</div>");
}
#[test]
fn should_escape_html_in_text_content() {
let source = r#"export default function Page(props) {
return <div>{props.text}</div>;
}"#;
let config = minimal_config();
let props = json!({"text": "<script>alert('xss')</script>"});
let result = render_string(source, "page.jsx", &props, &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div><script>alert('xss')</script></div>");
}
#[test]
fn should_escape_quotes_in_attribute_values() {
let source = r#"export default function Page(props) {
return <div title={props.title}>content</div>;
}"#;
let config = minimal_config();
let props = json!({"title": "a\"b"});
let result = render_string(source, "page.jsx", &props, &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, r#"<div title="a"b">content</div>"#);
}
#[test]
fn should_render_empty_element_when_given_no_children() {
let source = r#"export default function Page() {
return <div></div>;
}"#;
let config = minimal_config();
let result = render_string(source, "page.jsx", &json!({}), &config).unwrap();
let body = extract_body(&result);
assert_eq!(body, "<div></div>");
}