use mdbook::book::Chapter; use mdbook_toc::{Config, Toc}; use pretty_assertions::assert_eq; fn default() -> T { Default::default() } fn with_marker>(marker: S) -> Config { let mut cfg = Config::default(); cfg.marker = marker.into(); cfg } fn with_max_level(level: u32) -> Config { let mut cfg = Config::default(); cfg.max_level = level; cfg } trait FromContent { fn from_content(content: String) -> Self; } impl FromContent for Chapter { fn from_content(content: String) -> Self { Self { name: "chapter".into(), content, number: None, sub_items: vec![], path: None, source_path: None, parent_names: vec![], } } } /// Assert the Table of Content generation for an input file against the expected output file. /// /// Reads `tests/$name.in.md` and checks the generated ToC code against `tests/$name.out.md`. macro_rules! assert_toc { ($name:expr) => { assert_toc!($name, default()) }; ($name:expr, $config:expr) => { let _ = env_logger::builder().is_test(true).try_init(); let config = $config; let content = ::std::fs::read_to_string(format!("tests/{}.in.md", $name)).expect(concat!( "Can't read ", $name, ".in.md" )); let expected = ::std::fs::read_to_string(format!("tests/{}.out.md", $name)) .expect(concat!("Can't read ", $name, ".out.md")); let chapter = Chapter::from_content(content); let result = Toc::add_toc(&chapter, &config); match result { Ok(result) => assert_eq!(expected, result), Err(e) => panic!("{} failed. Error: {}", $name, e), } }; } #[test] fn adds_toc() { assert_toc!("adds_toc", default()); } #[test] fn adds_toc_with_inline_code() { assert_toc!("with_inline_code", default()); } #[test] fn leaves_tables_untouched() { // Regression test. // Previously we forgot to enable the same markdwon extensions as mdbook itself. // Markdown roundtripping removes some insignificant whitespace assert_toc!("tables_untouched"); } #[test] fn handles_inline_code() { // Regression test. // Inline code in a header was broken up into multiple items. // Also test for deeply nested headers. assert_toc!("handles_inline_code"); } #[test] fn multi_header_regression() { assert_toc!("multi_header"); } #[test] fn multi_header_linear_regression_3() { assert_toc!("multi_header_linear"); } #[test] fn add_toc_with_gitlab_marker() { let marker = "[[_TOC_]]".to_owned(); assert_toc!("gitlab_marker", with_marker(marker)); } #[test] fn unique_slugs() { assert_toc!("unique_slugs"); } #[test] fn add_toc_with_github_marker() { let marker = "* auto-gen TOC:\n{:toc}\n".to_owned(); assert_toc!("github_marker", with_marker(marker)); } #[test] fn lower_max_level() { assert_toc!("lower_max_level", with_max_level(2)); } #[test] fn higher_max_level() { assert_toc!("higher_max_level", with_max_level(7)); } // Regression test for [#13](https://github.com/badboy/mdbook-toc/issues/13). // Choosing a non-HTML TOC marker breaks sites that don't use it at all, // removed the header and first paragraph. #[test] fn nonhtml_marker_no_toc_in_page() { let marker = "[[_TOC_]]".to_owned(); assert_toc!("nonhtml_marker_no_use", with_marker(marker)); } #[test] fn similar_heading_different_casing() { // Regression test #15 // Previously we didn't use the normalized header ("slug") to decide whether to use // different link anchors. assert_toc!("similar_heading_different_casing"); } #[test] fn tables_with_html() { assert_toc!("tables_with_html"); } #[test] fn backslash_escapes() { // Regression test #21 // Backslash-escaped elements should still be escaped. assert_toc!("backslash_escapes"); }