|
| 1 | +//! High-level regression testing which will build the example book and *try* |
| 2 | +//! to make sure key elements don't get accidentally broken. |
| 3 | +//! |
| 4 | +//! # Warning |
| 5 | +//! |
| 6 | +//! These tests will need to be updated every time the example book changes. |
| 7 | +//! Hopefully Travis will let you know when that happens. |
| 8 | +
|
| 9 | +#![feature(conservative_impl_trait)] |
| 10 | + |
| 11 | +extern crate mdbook; |
| 12 | +#[macro_use] |
| 13 | +extern crate pretty_assertions; |
| 14 | +extern crate select; |
| 15 | +extern crate tempdir; |
| 16 | +extern crate walkdir; |
| 17 | + |
| 18 | +mod helpers; |
| 19 | + |
| 20 | +use std::path::Path; |
| 21 | +use walkdir::{WalkDir, WalkDirIterator}; |
| 22 | +use select::document::Document; |
| 23 | +use select::predicate::{Class, Descendant, Name, Predicate}; |
| 24 | + |
| 25 | + |
| 26 | +const BOOK_ROOT: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/book-example"); |
| 27 | +const TOC_TOP_LEVEL: &[&'static str] = &[ |
| 28 | + "1. mdBook", |
| 29 | + "2. Command Line Tool", |
| 30 | + "3. Format", |
| 31 | + "4. Rust Library", |
| 32 | + "Contributors", |
| 33 | +]; |
| 34 | +const TOC_SECOND_LEVEL: &[&'static str] = &[ |
| 35 | + "2.1. init", |
| 36 | + "2.2. build", |
| 37 | + "2.3. watch", |
| 38 | + "2.4. serve", |
| 39 | + "2.5. test", |
| 40 | + "3.1. SUMMARY.md", |
| 41 | + "3.2. Configuration", |
| 42 | + "3.3. Theme", |
| 43 | + "3.4. MathJax Support", |
| 44 | + "3.5. Rust code specific features", |
| 45 | +]; |
| 46 | +const TOC_THIRD_LEVEL: &[&'static str] = &["3.3.1. index.hbs", "3.3.2. Syntax highlighting"]; |
| 47 | + |
| 48 | +/// Apply a series of predicates to some root predicate, where each |
| 49 | +/// successive predicate is the descendant of the last one. |
| 50 | +macro_rules! descendants { |
| 51 | + ($root:expr, $($child:expr),*) => { |
| 52 | + $root |
| 53 | + $( |
| 54 | + .descendant($child) |
| 55 | + )* |
| 56 | + }; |
| 57 | +} |
| 58 | + |
| 59 | + |
| 60 | +/// Make sure that all `*.md` files (excluding `SUMMARY.md`) were rendered |
| 61 | +/// and placed in the `book` directory with their extensions set to `*.html`. |
| 62 | +#[test] |
| 63 | +fn chapter_files_were_rendered_to_html() { |
| 64 | + let temp = helpers::build_example_book(); |
| 65 | + let src = Path::new(BOOK_ROOT).join("src"); |
| 66 | + |
| 67 | + let chapter_files = WalkDir::new(&src) |
| 68 | + .into_iter() |
| 69 | + .filter_entry(|entry| entry.file_name().to_string_lossy().ends_with(".md")) |
| 70 | + .filter_map(|entry| entry.ok()) |
| 71 | + .map(|entry| entry.path().to_path_buf()) |
| 72 | + .filter(|path| path.file_name().unwrap() != "SUMMARY"); |
| 73 | + |
| 74 | + for chapter in chapter_files { |
| 75 | + let rendered_location = temp.path() |
| 76 | + .join(chapter.strip_prefix(&src).unwrap()) |
| 77 | + .with_extension("html"); |
| 78 | + assert!(rendered_location.exists(), "{} doesn't exits", rendered_location.display()); |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +fn root_index_html() -> Document { |
| 83 | + let temp = helpers::build_example_book(); |
| 84 | + |
| 85 | + let index_page = temp.path().join("book").join("index.html"); |
| 86 | + let html = helpers::read_file(&index_page).unwrap(); |
| 87 | + Document::from(html.as_str()) |
| 88 | +} |
| 89 | + |
| 90 | +#[test] |
| 91 | +fn check_third_toc_level() { |
| 92 | + let doc = root_index_html(); |
| 93 | + let should_be = TOC_THIRD_LEVEL; |
| 94 | + |
| 95 | + let children_of_children_of_children: Vec<String> = doc.find( |
| 96 | + Class("chapter") |
| 97 | + .descendant(Name("li")) |
| 98 | + .descendant(Name("li")) |
| 99 | + .descendant(Name("li")) |
| 100 | + .descendant(Name("a")), |
| 101 | + ).map(|elem| elem.text().trim().to_string()) |
| 102 | + .collect(); |
| 103 | + assert_eq!(children_of_children_of_children, should_be); |
| 104 | +} |
| 105 | + |
| 106 | +#[test] |
| 107 | +fn check_second_toc_level() { |
| 108 | + let doc = root_index_html(); |
| 109 | + let mut should_be = Vec::from(TOC_SECOND_LEVEL); |
| 110 | + |
| 111 | + should_be.extend(TOC_THIRD_LEVEL); |
| 112 | + should_be.sort(); |
| 113 | + |
| 114 | + let pred = descendants!(Class("chapter"), Name("li"), Name("li"), Name("a")); |
| 115 | + |
| 116 | + let mut children_of_children: Vec<String> = doc.find(pred) |
| 117 | + .map(|elem| elem.text().trim().to_string()) |
| 118 | + .collect(); |
| 119 | + children_of_children.sort(); |
| 120 | + |
| 121 | + assert_eq!(children_of_children, should_be); |
| 122 | +} |
| 123 | + |
| 124 | +#[test] |
| 125 | +fn check_first_toc_level() { |
| 126 | + let doc = root_index_html(); |
| 127 | + let mut should_be = Vec::from(TOC_TOP_LEVEL); |
| 128 | + |
| 129 | + should_be.extend(TOC_SECOND_LEVEL); |
| 130 | + should_be.extend(TOC_THIRD_LEVEL); |
| 131 | + should_be.sort(); |
| 132 | + |
| 133 | + let pred = descendants!(Class("chapter"), Name("li"), Name("a")); |
| 134 | + |
| 135 | + let mut children: Vec<String> = doc.find(pred) |
| 136 | + .map(|elem| elem.text().trim().to_string()) |
| 137 | + .collect(); |
| 138 | + children.sort(); |
| 139 | + |
| 140 | + assert_eq!(children, should_be); |
| 141 | +} |
| 142 | + |
| 143 | +#[test] |
| 144 | +fn check_spacers() { |
| 145 | + let doc = root_index_html(); |
| 146 | + let should_be = 1; |
| 147 | + |
| 148 | + let num_spacers = doc.find(Class("chapter").descendant(Name("li").and(Class("spacer")))) |
| 149 | + .count(); |
| 150 | + assert_eq!(num_spacers, should_be); |
| 151 | +} |
0 commit comments