use lex_core::lex::ast::elements::verbatim::VerbatimBlockMode;
use lex_core::lex::ast::AstNode;
use lex_core::lex::testing::assert_ast;
use lex_core::lex::testing::lexplore::Lexplore;
#[test]
fn test_verbatim_01_flat_simple_code() {
let doc = Lexplore::verbatim(1).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Code Example")
.closing_label("javascript")
.content_contains("function hello()");
});
}
#[test]
fn test_verbatim_02_flat_with_caption() {
let doc = Lexplore::verbatim(2).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("API Response")
.closing_label("json")
.content_contains("{\"status\": \"ok\"");
});
}
#[test]
fn test_verbatim_03_flat_with_params() {
let doc = Lexplore::verbatim(3).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Configuration")
.closing_label("nginx")
.has_closing_parameter_with_value("format", "pretty")
.content_contains("server {");
});
}
#[test]
fn test_verbatim_04_flat_marker_form() {
let doc = Lexplore::verbatim(4).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Sunset Photo")
.closing_label("lex.media.image")
.has_closing_parameter_with_value("src", "sunset.jpg")
.content_contains("As the sun sets over the ocean.")
.line_count(1);
});
}
#[test]
fn test_verbatim_05_flat_special_chars() {
let doc = Lexplore::verbatim(5).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Special Characters")
.closing_label("javascript")
.content_contains("// This content has :: markers")
.content_contains("return \"::\"");
});
}
#[test]
fn test_verbatim_06_nested_in_definition() {
let doc = Lexplore::verbatim(6).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_definition()
.subject("JavaScript Example")
.child_count(3); });
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(0, |para| {
para.assert_paragraph()
.text_contains("demonstrates closure");
});
});
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(1, |verbatim| {
verbatim
.assert_verbatim_block()
.subject("Implementation")
.closing_label("javascript")
.content_contains("function counter()")
.content_contains("let count = 0;")
.content_contains("return () => ++count;")
.line_count(6) .line_eq(0, "")
.line_eq(5, "");
});
});
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(2, |para| {
para.assert_paragraph()
.text_contains("simple closure pattern");
});
});
}
#[test]
fn test_verbatim_07_nested_in_list() {
let doc = Lexplore::verbatim(7).parse().unwrap();
assert_ast(&doc).item_count(1);
assert_ast(&doc).item(0, |item| {
item.assert_list().item_count(2);
});
assert_ast(&doc).item(0, |item| {
item.assert_list().item(0, |list_item| {
list_item
.text_contains("Python example")
.child_count(1) .child(0, |verbatim| {
verbatim
.assert_verbatim_block()
.subject("Simple function")
.closing_label("python")
.content_contains("def hello():")
.content_contains("return \"world\"")
.line_count(4) .line_eq(0, "")
.line_eq(3, "");
});
});
});
assert_ast(&doc).item(0, |item| {
item.assert_list().item(1, |list_item| {
list_item
.text_contains("JavaScript example")
.child_count(1) .child(0, |verbatim| {
verbatim
.assert_verbatim_block()
.subject("Another function")
.closing_label("javascript")
.content_contains("const greet")
.line_count(3) .line_eq(0, "")
.line_eq(2, "");
});
});
});
}
#[test]
fn test_verbatim_08_nested_deep() {
let doc = Lexplore::verbatim(8).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_definition()
.subject("Programming Languages")
.child_count(2); });
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(0, |para| {
para.assert_paragraph()
.text_contains("Overview of different languages");
});
});
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(1, |def2| {
def2.assert_definition()
.subject("Scripting Languages")
.child_count(2); });
});
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(1, |def2| {
def2.assert_definition().child(0, |para| {
para.assert_paragraph()
.text_contains("Languages for automation");
});
});
});
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(1, |def2| {
def2.assert_definition().child(1, |def3| {
def3.assert_definition().subject("Python").child_count(1); });
});
});
assert_ast(&doc).item(0, |item| {
item.assert_definition().child(1, |def2| {
def2.assert_definition().child(1, |def3| {
def3.assert_definition().child(0, |verbatim| {
verbatim
.assert_verbatim_block()
.subject("Example code")
.closing_label("python")
.content_contains("#!/usr/bin/env python3")
.content_contains("print(\"Hello, World!\")");
});
});
});
});
}
#[test]
fn test_verbatim_09_flat_simple_beyond_wall() {
let doc = Lexplore::verbatim(9).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Code Example")
.closing_label("javascript")
.content_contains("function hello() {")
.content_contains("return \"world\";")
.content_contains("}")
.line_count(5) .line_eq(0, "")
.line_eq(4, "");
});
}
#[test]
fn test_verbatim_10_flat_simple_empty() {
let doc = Lexplore::verbatim(10).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Code Example")
.closing_label("javascript")
.line_count(0); });
}
#[test]
fn test_verbatim_13_group_spades() {
let doc = Lexplore::verbatim(13).parse().unwrap();
assert_ast(&doc).item_count(2).item(0, |item| {
item.assert_verbatim_block()
.subject("This is a groupped Verbatim Block, this is the first Group:")
.closing_label("shell")
.group_count(4)
.group(0, |group| {
group
.subject("This is a groupped Verbatim Block, this is the first Group:")
.content_contains("$ pwd # always te staring point");
})
.group(1, |group| {
group
.subject("Now that you know where you are, lets find out what's around you:")
.content_contains("$ ls")
.content_contains("$ ls -r # recursive");
})
.group(2, |group| {
group
.subject("And let's go places:")
.content_contains("$ cd <path to go>");
})
.group(3, |group| {
group
.subject("Feeling lost, let's get back home:")
.content_contains("$ cd ~");
});
});
assert_ast(&doc).item(1, |item| {
item.assert_paragraph().text_contains(
"Note that verbatim blocks conetents can have any number of blank lines",
);
});
}
#[test]
fn test_verbatim_14_fullwidth_table() {
let doc = Lexplore::verbatim(14).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Fullwidth Table Example")
.mode(VerbatimBlockMode::Fullwidth)
.line_count(5)
.content_contains("Header | Value | Notes")
.content_contains("Minimal fullwidth block for wide tables")
.content_contains("Beta | 25 | extended range");
});
}
#[test]
fn test_verbatim_15_inflow_preserves_leading_blank_line() {
let doc = Lexplore::verbatim(15).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Inflow Leading Blank")
.closing_label("shell")
.mode(VerbatimBlockMode::Inflow)
.line_count(3)
.line_eq(0, "")
.line_eq(1, "echo \"first\"")
.line_eq(2, "echo \"second\"");
});
}
#[test]
fn test_verbatim_16_fullwidth_at_root() {
let doc = Lexplore::verbatim(16).parse().unwrap();
assert_ast(&doc).item_count(3);
assert_ast(&doc).item(0, |item| {
item.assert_paragraph().text_contains("comes before");
});
assert_ast(&doc).item(1, |item| {
item.assert_verbatim_block()
.subject("Fullwidth Table at Root")
.mode(VerbatimBlockMode::Fullwidth)
.closing_label("data")
.line_count(4) .content_contains("ID | Name")
.content_contains("Alice");
});
assert_ast(&doc).item(2, |item| {
item.assert_paragraph().text_contains("comes after");
});
}
#[test]
fn test_verbatim_17_fullwidth_preserves_leading_blank_line() {
let doc = Lexplore::verbatim(17).parse().unwrap();
assert_ast(&doc).item_count(1).item(0, |item| {
item.assert_verbatim_block()
.subject("Fullwidth Leading Blank")
.closing_label("data")
.mode(VerbatimBlockMode::Fullwidth)
.line_count(3)
.line_eq(0, "")
.line_eq(1, "Header | Value")
.line_eq(2, "Data | More");
});
}
#[test]
fn test_verbatim_11_group_sequences() {
let doc = Lexplore::verbatim(11).parse().unwrap();
assert_ast(&doc).item_count(4);
assert_ast(&doc).item(0, |item| {
item.assert_verbatim_block()
.subject("Installing with home brew is simple")
.closing_label("shell")
.group_count(3)
.group(0, |group| {
group
.subject("Installing with home brew is simple")
.content_contains("$ brew install lex");
})
.group(1, |group| {
group
.subject("From there the interactive help is available")
.content_contains("$ lex help");
})
.group(2, |group| {
group
.subject("And the built-in viewer can be used to quickly view the parsing")
.content_contains("$ lexv <path>");
});
});
assert_ast(&doc).item(1, |item| {
item.assert_paragraph()
.text_contains("content below, correct, from parsing however");
});
assert_ast(&doc).item(2, |item| {
item.assert_verbatim_block()
.closing_label("shell")
.group_count(2)
.group(0, |group| {
group.subject("This is block 1").content_contains("$ ls");
})
.group(1, |group| {
group
.subject("Which is a shell block")
.content_contains("$ pwd");
});
});
assert_ast(&doc).item(3, |item| {
item.assert_verbatim_block()
.subject("And this is a block 2")
.closing_label("javascript")
.group_count(1)
.content_contains("input(\"Favorite fruit:\")");
});
}
#[test]
fn test_verbatim_11_group_visitor_sees_all_groups() {
use lex_core::lex::ast::elements::VerbatimLine;
use lex_core::lex::ast::Visitor;
struct VerbatimLineCounter {
count: usize,
lines: Vec<String>,
}
impl Visitor for VerbatimLineCounter {
fn visit_verbatim_line(&mut self, line: &VerbatimLine) {
self.count += 1;
self.lines.push(line.content.as_string().to_string());
}
}
let doc = Lexplore::verbatim(11).parse().unwrap();
let mut visitor = VerbatimLineCounter {
count: 0,
lines: Vec::new(),
};
doc.accept(&mut visitor);
assert_eq!(
visitor.count, 12,
"Visitor should see all lines from all groups, got {} lines",
visitor.count
);
assert!(
visitor
.lines
.iter()
.any(|l| l.contains("$ brew install lex")),
"Should see line from first group of first block"
);
assert!(
visitor.lines.iter().any(|l| l.contains("$ lex help")),
"Should see line from second group of first block"
);
assert!(
visitor.lines.iter().any(|l| l.contains("$ lexv")),
"Should see line from third group of first block"
);
assert!(
visitor.lines.iter().any(|l| l.contains("$ ls")),
"Should see line from first group of second block"
);
assert!(
visitor.lines.iter().any(|l| l.contains("$ pwd")),
"Should see line from second group of second block"
);
assert!(
visitor.lines.iter().any(|l| l.contains("input(")),
"Should see line from third block"
);
}
#[test]
fn test_verbatim_12_document_simple() {
let doc = Lexplore::verbatim(12).parse().unwrap();
assert_ast(&doc).item(0, |item| {
item.assert_paragraph()
.text_contains("This document tests the combination of all three core elements");
});
assert_ast(&doc).item(1, |item| {
item.assert_session()
.label_contains("Session with Paragraph Content")
.child_count(3) .child(0, |para| {
para.assert_paragraph()
.text_contains("This session starts with a paragraph as its first child");
})
.child(1, |para| {
para.assert_paragraph()
.text_contains("It can have multiple paragraphs");
})
.child(2, |verbatim| {
verbatim
.assert_verbatim_block()
.subject("This is a groupped Verbatim Block, this is the first Group")
.closing_label("shell")
.group_count(4)
.group(0, |group| {
group
.subject("This is a groupped Verbatim Block, this is the first Group")
.content_contains("$ pwd # always te staring point");
})
.group(1, |group| {
group
.subject(
"Now that you know where you are, lets find out what's around you",
)
.content_contains("$ ls")
.content_contains("$ ls -r # recursive");
})
.group(2, |group| {
group
.subject("And let's go places")
.content_contains("$ cd <path to go>");
})
.group(3, |group| {
group
.subject("Feeling lost, let's get back home")
.content_contains("$ cd ~");
});
});
});
assert_ast(&doc).item(2, |item| {
item.assert_session()
.label_contains("Session with List Content")
.child_count(1) .child(0, |list| {
list.assert_list()
.item_count(3)
.item(0, |item| {
item.text_contains("First list item");
})
.item(1, |item| {
item.text_contains("Second list item");
})
.item(2, |item| {
item.text_contains("Third list item");
});
});
});
assert_ast(&doc).item(3, |item| {
item.assert_session()
.label_contains("Session with Mixed Content")
.child_count(3); });
assert_ast(&doc).item(4, |item| {
item.assert_paragraph()
.text_contains("A paragraph at the root level");
});
assert_ast(&doc).item(5, |item| {
item.assert_list()
.item_count(2)
.item(0, |list_item| {
list_item.text_contains("Root level list");
})
.item(1, |list_item| {
list_item.text_contains("With multiple items");
});
});
assert_ast(&doc).item(6, |item| {
item.assert_verbatim_block()
.subject("This is an Image Verbatim Representation")
.closing_label("lex.media.image")
.assert_marker_form()
.has_closing_parameter_with_value("src", "\"image.jpg\"");
});
assert_ast(&doc).item(7, |item| {
item.assert_session()
.label_contains("Another Session")
.child_count(3); });
assert_ast(&doc).item(8, |item| {
item.assert_paragraph()
.text_contains("Final root level paragraph");
});
assert_ast(&doc).item(9, |item| {
item.assert_verbatim_block()
.subject("Say goodbye mom")
.closing_label("javascript")
.content_contains("alert(\"Goodbye mom!\")");
});
}