parent
4d66646ece
commit
1ec48a3725
5 changed files with 550 additions and 564 deletions
maud_macros/tests
145
maud_macros/tests/basic_syntax.rs
Normal file
145
maud_macros/tests/basic_syntax.rs
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(maud_macros)]
|
||||||
|
|
||||||
|
extern crate maud;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn literals() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, "du\tcks" -23 3.14 '\n' "geese").unwrap();
|
||||||
|
assert_eq!(s, "du\tcks-233.14\ngeese");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn escaping() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, "<flim&flam>").unwrap();
|
||||||
|
assert_eq!(s, "<flim&flam>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn semicolons() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
"one";
|
||||||
|
"two";
|
||||||
|
"three";
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
"four";
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, "onetwothreefour");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn blocks() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
"hello"
|
||||||
|
{
|
||||||
|
" ducks" " geese"
|
||||||
|
}
|
||||||
|
" swans"
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, "hello ducks geese swans");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_elements() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, p { b { "pickle" } "barrel" i { "kumquat" } }).unwrap();
|
||||||
|
assert_eq!(s, "<p><b>pickle</b>barrel<i>kumquat</i></p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nesting_elements() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, html body div p sup "butts").unwrap();
|
||||||
|
assert_eq!(s, "<html><body><div><p><sup>butts</sup></p></div></body></html>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_elements() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, "pinkie" br/ "pie").unwrap();
|
||||||
|
assert_eq!(s, "pinkie<br>pie");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_attributes() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
link rel="stylesheet" href="styles.css"/
|
||||||
|
section id="midriff" {
|
||||||
|
p class="hotpink" "Hello!"
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, concat!(
|
||||||
|
r#"<link rel="stylesheet" href="styles.css">"#,
|
||||||
|
r#"<section id="midriff"><p class="hotpink">Hello!</p></section>"#));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_attributes() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, div readonly? input type="checkbox" checked? /).unwrap();
|
||||||
|
assert_eq!(s, r#"<div readonly><input type="checkbox" checked></div>"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn colons_in_names() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, pon-pon:controls-alpha a on:click="yay()" "Yay!").unwrap();
|
||||||
|
assert_eq!(s, concat!(
|
||||||
|
r#"<pon-pon:controls-alpha>"#,
|
||||||
|
r#"<a on:click="yay()">Yay!</a>"#,
|
||||||
|
r#"</pon-pon:controls-alpha>"#));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hyphens_in_element_names() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, custom-element {}).unwrap();
|
||||||
|
assert_eq!(s, "<custom-element></custom-element>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hyphens_in_attribute_names() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, this sentence-is="false" of-course? {}).unwrap();
|
||||||
|
assert_eq!(s, r#"<this sentence-is="false" of-course></this>"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn class_shorthand() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, p { "Hi, " span.name { "Lyra" } "!" }).unwrap();
|
||||||
|
assert_eq!(s, r#"<p>Hi, <span class="name">Lyra</span>!</p>"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn class_shorthand_with_space() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, p { "Hi, " span .name { "Lyra" } "!" }).unwrap();
|
||||||
|
assert_eq!(s, r#"<p>Hi, <span class="name">Lyra</span>!</p>"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classes_shorthand() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, p { "Hi, " span.name.here { "Lyra" } "!" }).unwrap();
|
||||||
|
assert_eq!(s, r#"<p>Hi, <span class="name here">Lyra</span>!</p>"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ids_shorthand() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, p { "Hi, " span#thing { "Lyra" } "!" }).unwrap();
|
||||||
|
assert_eq!(s, r#"<p>Hi, <span id="thing">Lyra</span>!</p>"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classes_attrs_ids_mixed_up() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).unwrap();
|
||||||
|
assert_eq!(s, "<p>Hi, <span lang=\"en\" class=\"name here\" id=\"thing\">Lyra</span>!</p>");
|
||||||
|
}
|
139
maud_macros/tests/control_structures.rs
Normal file
139
maud_macros/tests/control_structures.rs
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(maud_macros)]
|
||||||
|
|
||||||
|
extern crate maud;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn if_expr() {
|
||||||
|
for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
@if number == 1 {
|
||||||
|
"one"
|
||||||
|
} @else if number == 2 {
|
||||||
|
"two"
|
||||||
|
} @else if number == 3 {
|
||||||
|
"three"
|
||||||
|
} @else {
|
||||||
|
"oh noes"
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn if_let() {
|
||||||
|
for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
@if let Some(value) = input {
|
||||||
|
^value
|
||||||
|
} @else {
|
||||||
|
"oh noes"
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn for_expr() {
|
||||||
|
let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
ul @for pony in &ponies {
|
||||||
|
li ^pony
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, concat!(
|
||||||
|
"<ul>",
|
||||||
|
"<li>Apple Bloom</li>",
|
||||||
|
"<li>Scootaloo</li>",
|
||||||
|
"<li>Sweetie Belle</li>",
|
||||||
|
"</ul>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_expr() {
|
||||||
|
for &(input, output) in [(Some("yay"), "<div>yay</div>"), (None, "oh noes")].iter() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
@match input {
|
||||||
|
Some(value) => {
|
||||||
|
div { ^value }
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
"oh noes"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_expr_without_delims() {
|
||||||
|
for &(input, output) in [(Some("yay"), "yay"), (None, "<span>oh noes</span>")].iter() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
@match input {
|
||||||
|
Some(value) => ^value,
|
||||||
|
None => span { "oh noes" },
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_expr_with_guards() {
|
||||||
|
for &(input, output) in [(Some(1), "one"), (None, "none"), (Some(2), "2")].iter() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
@match input {
|
||||||
|
Some(value) if value == 1 => "one",
|
||||||
|
Some(value) => ^value,
|
||||||
|
None => "none",
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_in_attribute() {
|
||||||
|
for &(input, output) in [(1, "<span class=\"one\">1</span>"), (2, "<span class=\"two\">2</span>"), (3, "<span class=\"many\">3</span>")].iter() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
span class=@match input {
|
||||||
|
1 => "one",
|
||||||
|
2 => "two",
|
||||||
|
_ => "many",
|
||||||
|
} { ^input }
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn call() {
|
||||||
|
fn ducks(w: &mut fmt::Write) -> fmt::Result {
|
||||||
|
write!(w, "Ducks")
|
||||||
|
}
|
||||||
|
let mut s = String::new();
|
||||||
|
let swans = |yes|
|
||||||
|
if yes {
|
||||||
|
|w: &mut fmt::Write| write!(w, "Swans")
|
||||||
|
} else {
|
||||||
|
panic!("oh noes")
|
||||||
|
};
|
||||||
|
html!(s, {
|
||||||
|
@call ducks
|
||||||
|
@call (|w: &mut fmt::Write| write!(w, "Geese"))
|
||||||
|
@call swans(true)
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, "DucksGeeseSwans");
|
||||||
|
}
|
142
maud_macros/tests/misc.rs
Normal file
142
maud_macros/tests/misc.rs
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(maud_macros)]
|
||||||
|
|
||||||
|
extern crate maud;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn html_utf8() {
|
||||||
|
let mut buf = vec![];
|
||||||
|
html_utf8!(buf, p "hello").unwrap();
|
||||||
|
assert_eq!(buf, b"<p>hello</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_13() {
|
||||||
|
let owned = String::from("yay");
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^owned).unwrap();
|
||||||
|
// Make sure the `html!` call didn't move it
|
||||||
|
let _owned = owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_21() {
|
||||||
|
macro_rules! greet {
|
||||||
|
() => ({
|
||||||
|
let mut result = String::new();
|
||||||
|
let name = "Pinkie Pie";
|
||||||
|
html!(result, p { "Hello, " ^name "!" }).map(|()| result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = greet!().unwrap();
|
||||||
|
assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_21_2() {
|
||||||
|
macro_rules! greet {
|
||||||
|
($name:expr) => ({
|
||||||
|
let mut result = String::new();
|
||||||
|
html!(result, p { "Hello, " ^$name "!" }).map(|()| result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = greet!("Pinkie Pie").unwrap();
|
||||||
|
assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_23() {
|
||||||
|
macro_rules! to_string {
|
||||||
|
($($x:tt)*) => {{
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, $($x)*).unwrap();
|
||||||
|
s
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = "Lyra";
|
||||||
|
let s = to_string!(p { "Hi, " ^name "!" });
|
||||||
|
assert_eq!(s, "<p>Hi, Lyra!</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_26() {
|
||||||
|
macro_rules! to_string {
|
||||||
|
($($x:tt)*) => {{
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, $($x)*).unwrap();
|
||||||
|
s
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = "Lyra";
|
||||||
|
let s = to_string!(p { "Hi, " ^(name) "!" });
|
||||||
|
assert_eq!(s, "<p>Hi, Lyra!</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_26_2() {
|
||||||
|
macro_rules! to_string {
|
||||||
|
($($x:tt)*) => {{
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, $($x)*).unwrap();
|
||||||
|
s
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = "Lyra";
|
||||||
|
let s = to_string!(p { "Hi, " ^("person called ".to_string() + name) "!" });
|
||||||
|
assert_eq!(s, "<p>Hi, person called Lyra!</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_26_3() {
|
||||||
|
macro_rules! to_string {
|
||||||
|
($($x:tt)*) => {{
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, $($x)*).unwrap();
|
||||||
|
s
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = "Lyra";
|
||||||
|
let s = to_string!(p { "Hi, " ^{"person called ".to_string() + name} "!" });
|
||||||
|
assert_eq!(s, "<p>Hi, person called Lyra!</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_impl() {
|
||||||
|
struct R(&'static str);
|
||||||
|
impl maud::Render for R {
|
||||||
|
fn render(&self, w: &mut fmt::Write) -> fmt::Result {
|
||||||
|
w.write_str(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut s = String::new();
|
||||||
|
let r = R("pinkie");
|
||||||
|
// Since `R` is not `Copy`, this shows that Maud will auto-ref splice
|
||||||
|
// arguments to find a `Render` impl
|
||||||
|
html!(s, ^r).unwrap();
|
||||||
|
html!(s, ^r).unwrap();
|
||||||
|
assert_eq!(s, "pinkiepinkie");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_once_impl() {
|
||||||
|
struct Once(String);
|
||||||
|
impl maud::RenderOnce for Once {
|
||||||
|
fn render_once(self, w: &mut fmt::Write) -> fmt::Result {
|
||||||
|
w.write_str(&self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut s = String::new();
|
||||||
|
let once = Once(String::from("pinkie"));
|
||||||
|
html!(s, ^once).unwrap();
|
||||||
|
assert_eq!(s, "pinkie");
|
||||||
|
}
|
124
maud_macros/tests/splices.rs
Normal file
124
maud_macros/tests/splices.rs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(maud_macros)]
|
||||||
|
|
||||||
|
extern crate maud;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn literals() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^"<pinkie>").unwrap();
|
||||||
|
assert_eq!(s, "<pinkie>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn raw_literals() {
|
||||||
|
use maud::PreEscaped;
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^PreEscaped("<pinkie>")).unwrap();
|
||||||
|
assert_eq!(s, "<pinkie>");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn blocks() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
^{
|
||||||
|
let mut result = 1i32;
|
||||||
|
for i in 2..11 {
|
||||||
|
result *= i;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, "3628800");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attributes() {
|
||||||
|
let rocks = true;
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
input checked?=true /
|
||||||
|
input checked?=false /
|
||||||
|
input checked?=rocks /
|
||||||
|
input checked?=(!rocks) /
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, concat!(
|
||||||
|
r#"<input checked>"#,
|
||||||
|
r#"<input>"#,
|
||||||
|
r#"<input checked>"#,
|
||||||
|
r#"<input>"#));
|
||||||
|
}
|
||||||
|
|
||||||
|
static BEST_PONY: &'static str = "Pinkie Pie";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn statics() {
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^BEST_PONY).unwrap();
|
||||||
|
assert_eq!(s, "Pinkie Pie");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn locals() {
|
||||||
|
let best_pony = "Pinkie Pie";
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^best_pony).unwrap();
|
||||||
|
assert_eq!(s, "Pinkie Pie");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An example struct, for testing purposes only
|
||||||
|
struct Creature {
|
||||||
|
name: &'static str,
|
||||||
|
/// Rating out of 10, where:
|
||||||
|
/// * 0 is a naked mole rat with dysentery
|
||||||
|
/// * 10 is Sweetie Belle in a milkshake
|
||||||
|
adorableness: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Creature {
|
||||||
|
fn repugnance(&self) -> u32 {
|
||||||
|
10 - self.adorableness
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn structs() {
|
||||||
|
let pinkie = Creature {
|
||||||
|
name: "Pinkie Pie",
|
||||||
|
adorableness: 9,
|
||||||
|
};
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, {
|
||||||
|
"Name: " ^pinkie.name ". Rating: " ^pinkie.repugnance()
|
||||||
|
}).unwrap();
|
||||||
|
assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple_accessors() {
|
||||||
|
let mut s = String::new();
|
||||||
|
let a = ("ducks", "geese");
|
||||||
|
html!(s, ^a.0).unwrap();
|
||||||
|
assert_eq!(s, "ducks");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn splice_with_path() {
|
||||||
|
mod inner {
|
||||||
|
pub fn name() -> &'static str {
|
||||||
|
"Maud"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^inner::name()).unwrap();
|
||||||
|
assert_eq!(s, "Maud");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nested_macro_invocation() {
|
||||||
|
let best_pony = "Pinkie Pie";
|
||||||
|
let mut s = String::new();
|
||||||
|
html!(s, ^(format!("{}", best_pony))).unwrap();
|
||||||
|
assert_eq!(s, "Pinkie Pie");
|
||||||
|
}
|
|
@ -1,564 +0,0 @@
|
||||||
#![feature(plugin)]
|
|
||||||
#![plugin(maud_macros)]
|
|
||||||
|
|
||||||
extern crate maud;
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn literals() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, "du\tcks" -23 3.14 '\n' "geese").unwrap();
|
|
||||||
assert_eq!(s, "du\tcks-233.14\ngeese");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn escaping() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, "<flim&flam>").unwrap();
|
|
||||||
assert_eq!(s, "<flim&flam>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn semicolons() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
"one";
|
|
||||||
"two";
|
|
||||||
"three";
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
"four";
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, "onetwothreefour");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn blocks() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
"hello"
|
|
||||||
{
|
|
||||||
" ducks" " geese"
|
|
||||||
}
|
|
||||||
" swans"
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, "hello ducks geese swans");
|
|
||||||
}
|
|
||||||
|
|
||||||
mod elements {
|
|
||||||
#[test]
|
|
||||||
fn simple() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { b { "pickle" } "barrel" i { "kumquat" } }).unwrap();
|
|
||||||
assert_eq!(s, "<p><b>pickle</b>barrel<i>kumquat</i></p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn nesting() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, html body div p sup "butts").unwrap();
|
|
||||||
assert_eq!(s, "<html><body><div><p><sup>butts</sup></p></div></body></html>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn empty() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, "pinkie" br/ "pie").unwrap();
|
|
||||||
assert_eq!(s, "pinkie<br>pie");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attributes() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
link rel="stylesheet" href="styles.css"/
|
|
||||||
section id="midriff" {
|
|
||||||
p class="hotpink" "Hello!"
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, concat!(
|
|
||||||
r#"<link rel="stylesheet" href="styles.css">"#,
|
|
||||||
r#"<section id="midriff"><p class="hotpink">Hello!</p></section>"#));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn empty_attributes() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, div readonly? input type="checkbox" checked? /).unwrap();
|
|
||||||
assert_eq!(s, r#"<div readonly><input type="checkbox" checked></div>"#);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn namespaces() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, pon-pon:controls-alpha a on:click="yay()" "Yay!").unwrap();
|
|
||||||
assert_eq!(s, r#"<pon-pon:controls-alpha><a on:click="yay()">Yay!</a></pon-pon:controls-alpha>"#);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod splices {
|
|
||||||
#[test]
|
|
||||||
fn literals() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^"<pinkie>").unwrap();
|
|
||||||
assert_eq!(s, "<pinkie>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn raw_literals() {
|
|
||||||
use maud::PreEscaped;
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^PreEscaped("<pinkie>")).unwrap();
|
|
||||||
assert_eq!(s, "<pinkie>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn blocks() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
^{
|
|
||||||
let mut result = 1i32;
|
|
||||||
for i in 2..11 {
|
|
||||||
result *= i;
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, "3628800");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn attributes() {
|
|
||||||
let rocks = true;
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
input checked?=true /
|
|
||||||
input checked?=false /
|
|
||||||
input checked?=rocks /
|
|
||||||
input checked?=(!rocks) /
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, concat!(
|
|
||||||
r#"<input checked>"#,
|
|
||||||
r#"<input>"#,
|
|
||||||
r#"<input checked>"#,
|
|
||||||
r#"<input>"#));
|
|
||||||
}
|
|
||||||
|
|
||||||
static BEST_PONY: &'static str = "Pinkie Pie";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn statics() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^BEST_PONY).unwrap();
|
|
||||||
assert_eq!(s, "Pinkie Pie");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn closures() {
|
|
||||||
let best_pony = "Pinkie Pie";
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^best_pony).unwrap();
|
|
||||||
assert_eq!(s, "Pinkie Pie");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An example struct, for testing purposes only
|
|
||||||
struct Creature {
|
|
||||||
name: &'static str,
|
|
||||||
/// Rating out of 10, where:
|
|
||||||
/// * 0 is a naked mole rat with dysentery
|
|
||||||
/// * 10 is Sweetie Belle in a milkshake
|
|
||||||
adorableness: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Creature {
|
|
||||||
fn repugnance(&self) -> u32 {
|
|
||||||
10 - self.adorableness
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn structs() {
|
|
||||||
let pinkie = Creature {
|
|
||||||
name: "Pinkie Pie",
|
|
||||||
adorableness: 9,
|
|
||||||
};
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
"Name: " ^pinkie.name ". Rating: " ^pinkie.repugnance()
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn nested_macro_invocation() {
|
|
||||||
let best_pony = "Pinkie Pie";
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^(format!("{}", best_pony))).unwrap();
|
|
||||||
assert_eq!(s, "Pinkie Pie");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_13() {
|
|
||||||
let owned = String::from("yay");
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^owned).unwrap();
|
|
||||||
let _ = owned;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod control {
|
|
||||||
#[test]
|
|
||||||
fn if_expr() {
|
|
||||||
for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
@if number == 1 {
|
|
||||||
"one"
|
|
||||||
} @else if number == 2 {
|
|
||||||
"two"
|
|
||||||
} @else if number == 3 {
|
|
||||||
"three"
|
|
||||||
} @else {
|
|
||||||
"oh noes"
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn if_let() {
|
|
||||||
for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
@if let Some(value) = input {
|
|
||||||
^value
|
|
||||||
} @else {
|
|
||||||
"oh noes"
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn for_expr() {
|
|
||||||
let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
ul @for pony in &ponies {
|
|
||||||
li ^pony
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, concat!(
|
|
||||||
"<ul>",
|
|
||||||
"<li>Apple Bloom</li>",
|
|
||||||
"<li>Scootaloo</li>",
|
|
||||||
"<li>Sweetie Belle</li>",
|
|
||||||
"</ul>"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn match_expr() {
|
|
||||||
for &(input, output) in [(Some("yay"), "<div>yay</div>"), (None, "oh noes")].iter() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
@match input {
|
|
||||||
Some(value) => {
|
|
||||||
div { ^value }
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
"oh noes"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn match_expr_without_delims() {
|
|
||||||
for &(input, output) in [(Some("yay"), "yay"), (None, "<span>oh noes</span>")].iter() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
@match input {
|
|
||||||
Some(value) => ^value,
|
|
||||||
None => span { "oh noes" },
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn match_expr_with_guards() {
|
|
||||||
for &(input, output) in [(Some(1), "one"), (None, "none"), (Some(2), "2")].iter() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
@match input {
|
|
||||||
Some(value) if value == 1 => "one",
|
|
||||||
Some(value) => ^value,
|
|
||||||
None => "none",
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn match_in_attribute() {
|
|
||||||
for &(input, output) in [(1, "<span class=\"one\">1</span>"), (2, "<span class=\"two\">2</span>"), (3, "<span class=\"many\">3</span>")].iter() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, {
|
|
||||||
span class=@match input {
|
|
||||||
1 => "one",
|
|
||||||
2 => "two",
|
|
||||||
_ => "many",
|
|
||||||
} { ^input }
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn html_utf8() {
|
|
||||||
let mut buf = vec![];
|
|
||||||
html_utf8!(buf, p "hello").unwrap();
|
|
||||||
assert_eq!(buf, b"<p>hello</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
mod issue_10 {
|
|
||||||
#[test]
|
|
||||||
fn hyphens_in_element_names() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, custom-element {}).unwrap();
|
|
||||||
assert_eq!(s, "<custom-element></custom-element>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hyphens_in_attribute_names() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, this sentence-is="false" of-course? {}).unwrap();
|
|
||||||
assert_eq!(s, r#"<this sentence-is="false" of-course></this>"#);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn call() {
|
|
||||||
fn ducks(w: &mut fmt::Write) -> fmt::Result {
|
|
||||||
write!(w, "Ducks")
|
|
||||||
}
|
|
||||||
let mut s = String::new();
|
|
||||||
let swans = |yes|
|
|
||||||
if yes {
|
|
||||||
|w: &mut fmt::Write| write!(w, "Swans")
|
|
||||||
} else {
|
|
||||||
panic!("oh noes")
|
|
||||||
};
|
|
||||||
html!(s, {
|
|
||||||
@call ducks
|
|
||||||
@call (|w: &mut fmt::Write| write!(w, "Geese"))
|
|
||||||
@call swans(true)
|
|
||||||
}).unwrap();
|
|
||||||
assert_eq!(s, "DucksGeeseSwans");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_23() {
|
|
||||||
macro_rules! to_string {
|
|
||||||
($($x:tt)*) => {{
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, $($x)*).unwrap();
|
|
||||||
s
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = "Lyra";
|
|
||||||
let s = to_string!(p { "Hi, " ^name "!" });
|
|
||||||
assert_eq!(s, "<p>Hi, Lyra!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn tuple_accessors() {
|
|
||||||
let mut s = String::new();
|
|
||||||
let a = ("ducks", "geese");
|
|
||||||
html!(s, { ^a.0 }).unwrap();
|
|
||||||
assert_eq!(s, "ducks");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn splice_with_path() {
|
|
||||||
mod inner {
|
|
||||||
pub fn name() -> &'static str {
|
|
||||||
"Maud"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, ^inner::name()).unwrap();
|
|
||||||
assert_eq!(s, "Maud");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn class_shorthand() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { "Hi, " span.name { "Lyra" } "!" }).unwrap();
|
|
||||||
assert_eq!(s, "<p>Hi, <span class=\"name\">Lyra</span>!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn class_shorthand_with_space() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { "Hi, " span .name { "Lyra" } "!" }).unwrap();
|
|
||||||
assert_eq!(s, "<p>Hi, <span class=\"name\">Lyra</span>!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn classes_shorthand() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { "Hi, " span.name.here { "Lyra" } "!" }).unwrap();
|
|
||||||
assert_eq!(s, "<p>Hi, <span class=\"name here\">Lyra</span>!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn classes_shorthand_with_space() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { "Hi, " span .name .here { "Lyra" } "!" }).unwrap();
|
|
||||||
assert_eq!(s, "<p>Hi, <span class=\"name here\">Lyra</span>!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ids_shorthand() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { "Hi, " span#thing { "Lyra" } "!" }).unwrap();
|
|
||||||
assert_eq!(s, "<p>Hi, <span id=\"thing\">Lyra</span>!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn classes_attrs_ids_mixed_up() {
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).unwrap();
|
|
||||||
assert_eq!(s, "<p>Hi, <span lang=\"en\" class=\"name here\" id=\"thing\">Lyra</span>!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multirender() {
|
|
||||||
struct R<'a>(&'a str);
|
|
||||||
impl<'a> maud::Render for R<'a> {
|
|
||||||
fn render(&self, w: &mut std::fmt::Write) -> std::fmt::Result {
|
|
||||||
w.write_str(self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut s = String::new();
|
|
||||||
let r = R("pinkie ");
|
|
||||||
html!(s, ^r).unwrap();
|
|
||||||
html!(s, ^r).unwrap();
|
|
||||||
// R is not-Copyable so this shows that it will auto-ref splice arguments that implement Render.
|
|
||||||
assert_eq!(s, "pinkie pinkie ");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_once_by_move() {
|
|
||||||
struct Once<'a>(&'a str);
|
|
||||||
impl<'a> maud::RenderOnce for Once<'a> {
|
|
||||||
fn render_once(self, w: &mut std::fmt::Write) -> std::fmt::Result {
|
|
||||||
w.write_str(self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut s = String::new();
|
|
||||||
let once = Once("pinkie");
|
|
||||||
html!(s, ^once).unwrap();
|
|
||||||
assert_eq!(s, "pinkie");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_once_by_move_with_copy() {
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct Once<'a>(&'a str);
|
|
||||||
impl<'a> maud::RenderOnce for Once<'a> {
|
|
||||||
fn render_once(self, w: &mut std::fmt::Write) -> std::fmt::Result {
|
|
||||||
w.write_str(self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut s = String::new();
|
|
||||||
let once = Once("pinkie ");
|
|
||||||
html!(s, ^once).unwrap();
|
|
||||||
html!(s, ^once).unwrap();
|
|
||||||
assert_eq!(s, "pinkie pinkie ");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_26() {
|
|
||||||
macro_rules! to_string {
|
|
||||||
($($x:tt)*) => {{
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, $($x)*).unwrap();
|
|
||||||
s
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = "Lyra";
|
|
||||||
let s = to_string!(p { "Hi, " ^(name) "!" });
|
|
||||||
assert_eq!(s, "<p>Hi, Lyra!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_26_2() {
|
|
||||||
macro_rules! to_string {
|
|
||||||
($($x:tt)*) => {{
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, $($x)*).unwrap();
|
|
||||||
s
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = "Lyra";
|
|
||||||
let s = to_string!(p { "Hi, " ^("person called ".to_string() + name) "!" });
|
|
||||||
assert_eq!(s, "<p>Hi, person called Lyra!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_26_3() {
|
|
||||||
macro_rules! to_string {
|
|
||||||
($($x:tt)*) => {{
|
|
||||||
let mut s = String::new();
|
|
||||||
html!(s, $($x)*).unwrap();
|
|
||||||
s
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = "Lyra";
|
|
||||||
let s = to_string!(p { "Hi, " ^{"person called ".to_string() + name} "!" });
|
|
||||||
assert_eq!(s, "<p>Hi, person called Lyra!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_21() {
|
|
||||||
macro_rules! greet {
|
|
||||||
() => ({
|
|
||||||
let mut result = String::new();
|
|
||||||
let name = "Pinkie Pie";
|
|
||||||
html!(result, p { "Hello, " ^name "!" }).map(|()| result)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = greet!().unwrap();
|
|
||||||
assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn issue_21_2() {
|
|
||||||
macro_rules! greet {
|
|
||||||
($name:expr) => ({
|
|
||||||
let mut result = String::new();
|
|
||||||
html!(result, p { "Hello, " ^$name "!" }).map(|()| result)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = greet!("Pinkie Pie").unwrap();
|
|
||||||
assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue