Added a full integration test for the summary parser (ignored for the time being)

This commit is contained in:
Michael Bryan 2017-06-29 19:27:31 +08:00
parent 68ebb62dbf
commit 42de0fb97a
3 changed files with 120 additions and 16 deletions

View File

@ -9,7 +9,7 @@ use errors::*;
mod summary; mod summary;
pub use self::summary::{Summary, parse_summary}; pub use self::summary::{Summary, Link, SummaryItem, parse_summary, SectionNumber};
/// The object in charge of parsing the source directory into a usable /// The object in charge of parsing the source directory into a usable

View File

@ -52,10 +52,14 @@ pub fn parse_summary(summary: &str) -> Result<Summary> {
/// The parsed `SUMMARY.md`, specifying how the book should be laid out. /// The parsed `SUMMARY.md`, specifying how the book should be laid out.
#[derive(Debug, Clone, Default, PartialEq)] #[derive(Debug, Clone, Default, PartialEq)]
pub struct Summary { pub struct Summary {
title: Option<String>, /// An optional title for the `SUMMARY.md`, currently just ignored.
prefix_chapters: Vec<SummaryItem>, pub title: Option<String>,
numbered_chapters: Vec<SummaryItem>, /// Chapters before the main text (e.g. an introduction).
suffix_chapters: Vec<SummaryItem>, pub prefix_chapters: Vec<SummaryItem>,
/// The main chapters in the document.
pub numbered_chapters: Vec<SummaryItem>,
/// Items which come after the main document (e.g. a conclusion).
pub suffix_chapters: Vec<SummaryItem>,
} }
/// A struct representing an entry in the `SUMMARY.md`, possibly with nested /// A struct representing an entry in the `SUMMARY.md`, possibly with nested
@ -63,15 +67,21 @@ pub struct Summary {
/// ///
/// This is roughly the equivalent of `[Some section](./path/to/file.md)`. /// This is roughly the equivalent of `[Some section](./path/to/file.md)`.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
struct Link { pub struct Link {
name: String, /// The name of the chapter.
location: PathBuf, pub name: String,
number: Option<SectionNumber>, /// The location of the chapter's source file, taking the book's `src`
nested_items: Vec<SummaryItem>, /// directory as the root.
pub location: PathBuf,
/// The section number, if this chapter is in the numbered section.
pub number: Option<SectionNumber>,
/// Any nested items this chapter may contain.
pub nested_items: Vec<SummaryItem>,
} }
impl Link { impl Link {
fn new<S: Into<String>, P: AsRef<Path>>(name: S, location: P) -> Link { /// Create a new link with no nested items.
pub fn new<S: Into<String>, P: AsRef<Path>>(name: S, location: P) -> Link {
Link { Link {
name: name.into(), name: name.into(),
location: location.as_ref().to_path_buf(), location: location.as_ref().to_path_buf(),
@ -92,9 +102,12 @@ impl Default for Link {
} }
} }
/// An item in `SUMMARY.md` which could be either a separator or a `Link`.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
enum SummaryItem { pub enum SummaryItem {
/// A link to a chapter.
Link(Link), Link(Link),
/// A separator (`---`).
Separator, Separator,
} }
@ -193,13 +206,20 @@ impl<'a> SummaryParser<'a> {
fn parse(mut self) -> Result<Summary> { fn parse(mut self) -> Result<Summary> {
self.summary.title = self.parse_title(); self.summary.title = self.parse_title();
if let Some(ref title) = self.summary.title {
debug!("[*] Title is {:?}", title);
}
while self.state != State::End {
self.step()?;
}
Ok(self.summary) Ok(self.summary)
} }
fn step(&mut self) -> Result<()> { fn step(&mut self) -> Result<()> {
let next_event = self.stream.next().expect("TODO: error-chain"); let next_event = self.stream.next().expect("TODO: error-chain");
trace!("[*] Current state = {:?}, Next Event = {:?}", self.state, next_event); trace!("[*] Current state: {:?}, next event: {:?}", self.state, next_event);
println!("{:?}", next_event);
match self.state { match self.state {
State::Begin => self.step_start(next_event)?, State::Begin => self.step_start(next_event)?,
@ -253,7 +273,7 @@ impl<'a> SummaryParser<'a> {
}, },
other => { other => {
debug!("[*] Skipping unexpected token in summary: {:?}", other); trace!("[*] Skipping unexpected token in summary: {:?}", other);
}, },
} }
@ -310,6 +330,8 @@ impl<'a> SummaryParser<'a> {
Event::Start(Tag::Item) => { Event::Start(Tag::Item) => {
let it = self.parse_item() let it = self.parse_item()
.chain_err(|| "List items should only contain links")?; .chain_err(|| "List items should only contain links")?;
trace!("[*] Found a chapter: {:?}", it);
self.push_numbered_section(SummaryItem::Link(it)); self.push_numbered_section(SummaryItem::Link(it));
Ok(()) Ok(())
} }
@ -379,7 +401,7 @@ fn stringify_events<'a>(events: Vec<Event<'a>>) -> String {
/// A section number like "1.2.3", basically just a newtype'd `Vec<u32>`. /// A section number like "1.2.3", basically just a newtype'd `Vec<u32>`.
#[derive(Debug, PartialEq, Clone, Default)] #[derive(Debug, PartialEq, Clone, Default)]
struct SectionNumber(Vec<u32>); pub struct SectionNumber(pub Vec<u32>);
impl Display for SectionNumber { impl Display for SectionNumber {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {

82
tests/loading.rs Normal file
View File

@ -0,0 +1,82 @@
//! Integration tests for loading a book into memory
extern crate mdbook;
extern crate env_logger;
use std::path::PathBuf;
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary};
const SUMMARY: &str = "
# Summary
[Introduction](/intro.md)
---
[A Prefix Chapter](/some_prefix.md)
- [First chapter](/chapter_1/index.md)
- [Some Subsection](/chapter_1/subsection.md)
---
[Conclusion](/conclusion.md)
";
#[test]
#[ignore]
fn load_summary_md() {
env_logger::init().unwrap();
let should_be = Summary {
title: Some(String::from("Summary")),
prefix_chapters: vec![
SummaryItem::Link(Link {
name: String::from("Introduction"),
location: PathBuf::from("/intro.md"),
number: None,
nested_items: vec![],
}),
SummaryItem::Separator,
SummaryItem::Link(Link {
name: String::from("A Prefix Chapter"),
location: PathBuf::from("/some_prefix.md"),
number: None,
nested_items: vec![],
}),
],
numbered_chapters: vec![
SummaryItem::Link(Link {
name: String::from("First Chapter"),
location: PathBuf::from("/chapter_1/index.md"),
number: Some(SectionNumber(vec![1])),
nested_items: vec![
SummaryItem::Link(Link {
name: String::from("Some Subsection"),
location: PathBuf::from("/chapter_1/subsection.md"),
number: Some(SectionNumber(vec![1, 1])),
nested_items: vec![],
}),
],
}),
],
suffix_chapters: vec![
SummaryItem::Separator,
SummaryItem::Link( Link {
name: String::from("Conclusion"),
location: PathBuf::from("/conclusion.md"),
number: None,
nested_items: vec![],
})
],
};
let got = parse_summary(SUMMARY).unwrap();
println!("{:#?}", got);
assert_eq!(got, should_be);
}