1use boxworks::ds;
42use boxworks::lang;
43use boxworks::lang::convert::ToBoxLang;
44
45#[macro_export]
46macro_rules! assert_box_eq {
47 ($left:expr, $right:expr$(,)?) => {{
48 let lhs: boxworks_testing::Value = $left.into();
49 let rhs: boxworks_testing::Value = $right.into();
50 boxworks_testing::assert_eq(lhs, rhs);
51 }};
52}
53
54pub enum Value {
55 String(String),
56 Box(Vec<ds::Horizontal>),
57}
58
59impl From<&str> for Value {
60 fn from(value: &str) -> Self {
61 Value::String(value.into())
62 }
63}
64
65impl From<String> for Value {
66 fn from(value: String) -> Self {
67 Value::String(value)
68 }
69}
70
71impl From<ds::VBox> for Value {
72 fn from(value: ds::VBox) -> Self {
73 Value::Box(vec![ds::Horizontal::VBox(value)])
74 }
75}
76
77impl From<ds::HBox> for Value {
78 fn from(value: ds::HBox) -> Self {
79 Value::Box(vec![ds::Horizontal::HBox(value)])
80 }
81}
82
83impl From<Vec<ds::Horizontal>> for Value {
84 fn from(value: Vec<ds::Horizontal>) -> Self {
85 Value::Box(value)
86 }
87}
88
89pub fn assert_eq(lhs: Value, rhs: Value) {
90 let (lhs_list, lhs_s) = normalize(lhs, "lhs.box");
91 let (rhs_list, rhs_s) = normalize(rhs, "rhs.box");
92 use pretty_assertions::assert_eq;
94 assert_eq!(lhs_s, rhs_s);
95 assert_eq!(rhs_list, lhs_list);
98}
99
100fn normalize(val: Value, side: &str) -> (Vec<ds::Horizontal>, String) {
101 let list = match val {
102 Value::String(s) => match lang::parse_horizontal_list(&s.clone()) {
103 Ok(v) => v,
104 Err(err) => {
105 let source = ariadne::Source::from(s);
106 let cache: (&str, _) = (side, source);
107 for err in err {
108 err.ariadne_report(side).eprint(cache.clone()).unwrap();
109 }
110 panic!("failed to parse boxlang input; errors printed above.")
111 }
112 },
113 Value::Box(v) => v,
114 };
115 let mut s = String::new();
116 for elem in &list {
117 use std::fmt::Write;
118 write!(&mut s, "{}", elem.to_box_lang()).unwrap();
119 }
120 (list, s)
121}