You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

site.rs 27KB

6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
7 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
6 years ago
7 years ago
6 years ago
5 years ago
7 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
6 years ago
7 years ago
7 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
6 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. extern crate config;
  2. extern crate site;
  3. mod common;
  4. use std::collections::HashMap;
  5. use std::env;
  6. use std::path::Path;
  7. use common::{build_site, build_site_with_setup};
  8. use config::Taxonomy;
  9. use site::sitemap;
  10. use site::Site;
  11. #[test]
  12. fn can_parse_site() {
  13. let mut path = env::current_dir().unwrap().parent().unwrap().parent().unwrap().to_path_buf();
  14. path.push("test_site");
  15. let mut site = Site::new(&path, "config.toml").unwrap();
  16. site.load().unwrap();
  17. let library = site.library.read().unwrap();
  18. // Correct number of pages (sections do not count as pages, draft are ignored)
  19. assert_eq!(library.pages().len(), 21);
  20. let posts_path = path.join("content").join("posts");
  21. // Make sure the page with a url doesn't have any sections
  22. let url_post = library.get_page(&posts_path.join("fixed-url.md")).unwrap();
  23. assert_eq!(url_post.path, "a-fixed-url/");
  24. // Make sure the article in a folder with only asset doesn't get counted as a section
  25. let asset_folder_post =
  26. library.get_page(&posts_path.join("with-assets").join("index.md")).unwrap();
  27. assert_eq!(asset_folder_post.file.components, vec!["posts".to_string()]);
  28. // That we have the right number of sections
  29. assert_eq!(library.sections().len(), 11);
  30. // And that the sections are correct
  31. let index_section = library.get_section(&path.join("content").join("_index.md")).unwrap();
  32. assert_eq!(index_section.subsections.len(), 4);
  33. assert_eq!(index_section.pages.len(), 1);
  34. assert!(index_section.ancestors.is_empty());
  35. let posts_section = library.get_section(&posts_path.join("_index.md")).unwrap();
  36. assert_eq!(posts_section.subsections.len(), 2);
  37. assert_eq!(posts_section.pages.len(), 9); // 10 with 1 draft == 9
  38. assert_eq!(
  39. posts_section.ancestors,
  40. vec![*library.get_section_key(&index_section.file.path).unwrap()]
  41. );
  42. // Make sure we remove all the pwd + content from the sections
  43. let basic = library.get_page(&posts_path.join("simple.md")).unwrap();
  44. assert_eq!(basic.file.components, vec!["posts".to_string()]);
  45. assert_eq!(
  46. basic.ancestors,
  47. vec![
  48. *library.get_section_key(&index_section.file.path).unwrap(),
  49. *library.get_section_key(&posts_section.file.path).unwrap(),
  50. ]
  51. );
  52. let tutorials_section =
  53. library.get_section(&posts_path.join("tutorials").join("_index.md")).unwrap();
  54. assert_eq!(tutorials_section.subsections.len(), 2);
  55. let sub1 = library.get_section_by_key(tutorials_section.subsections[0]);
  56. let sub2 = library.get_section_by_key(tutorials_section.subsections[1]);
  57. assert_eq!(sub1.clone().meta.title.unwrap(), "Programming");
  58. assert_eq!(sub2.clone().meta.title.unwrap(), "DevOps");
  59. assert_eq!(tutorials_section.pages.len(), 0);
  60. let devops_section = library
  61. .get_section(&posts_path.join("tutorials").join("devops").join("_index.md"))
  62. .unwrap();
  63. assert_eq!(devops_section.subsections.len(), 0);
  64. assert_eq!(devops_section.pages.len(), 2);
  65. assert_eq!(
  66. devops_section.ancestors,
  67. vec![
  68. *library.get_section_key(&index_section.file.path).unwrap(),
  69. *library.get_section_key(&posts_section.file.path).unwrap(),
  70. *library.get_section_key(&tutorials_section.file.path).unwrap(),
  71. ]
  72. );
  73. let prog_section = library
  74. .get_section(&posts_path.join("tutorials").join("programming").join("_index.md"))
  75. .unwrap();
  76. assert_eq!(prog_section.subsections.len(), 0);
  77. assert_eq!(prog_section.pages.len(), 2);
  78. // Testing extra variables in sections & sitemaps
  79. // Regression test for #https://github.com/getzola/zola/issues/842
  80. assert_eq!(
  81. prog_section.meta.extra.get("we_have_extra").and_then(|s| s.as_str()),
  82. Some("variables")
  83. );
  84. let sitemap_entries = sitemap::find_entries(&library, &site.taxonomies[..], &site.config);
  85. let sitemap_entry = sitemap_entries
  86. .iter()
  87. .find(|e| e.permalink.ends_with("tutorials/programming/"))
  88. .expect("expected to find programming section in sitemap");
  89. assert_eq!(Some(&prog_section.meta.extra), sitemap_entry.extra);
  90. }
  91. #[test]
  92. fn can_build_site_without_live_reload() {
  93. let (_, _tmp_dir, public) = build_site("test_site");
  94. assert!(&public.exists());
  95. assert!(file_exists!(public, "index.html"));
  96. assert!(file_exists!(public, "sitemap.xml"));
  97. assert!(file_exists!(public, "robots.txt"));
  98. assert!(file_exists!(public, "a-fixed-url/index.html"));
  99. assert!(file_exists!(public, "posts/python/index.html"));
  100. // Shortcodes work
  101. assert!(file_contains!(public, "posts/python/index.html", "Basic shortcode"));
  102. assert!(file_contains!(public, "posts/python/index.html", "Arrrh Bob"));
  103. assert!(file_contains!(public, "posts/python/index.html", "Arrrh Bob_Sponge"));
  104. assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html"));
  105. assert!(file_exists!(public, "posts/with-assets/index.html"));
  106. assert!(file_exists!(public, "posts/no-section/simple/index.html"));
  107. // Sections
  108. assert!(file_exists!(public, "posts/index.html"));
  109. assert!(file_exists!(public, "posts/tutorials/index.html"));
  110. assert!(file_exists!(public, "posts/tutorials/devops/index.html"));
  111. assert!(file_exists!(public, "posts/tutorials/programming/index.html"));
  112. // Ensure subsection pages are correctly filled
  113. assert!(file_contains!(public, "posts/tutorials/index.html", "Sub-pages: 2"));
  114. // Pages and section get their relative path
  115. assert!(file_contains!(public, "posts/tutorials/index.html", "posts/tutorials/_index.md"));
  116. assert!(file_contains!(
  117. public,
  118. "posts/tutorials/devops/nix/index.html",
  119. "posts/tutorials/devops/nix.md"
  120. ));
  121. // aliases work
  122. assert!(file_exists!(public, "an-old-url/old-page/index.html"));
  123. assert!(file_contains!(public, "an-old-url/old-page/index.html", "something-else"));
  124. assert!(file_contains!(public, "another-old-url/index.html", "posts/"));
  125. // html aliases work
  126. assert!(file_exists!(public, "an-old-url/an-old-alias.html"));
  127. assert!(file_contains!(public, "an-old-url/an-old-alias.html", "something-else"));
  128. // redirect_to works
  129. assert!(file_exists!(public, "posts/tutorials/devops/index.html"));
  130. assert!(file_contains!(public, "posts/tutorials/devops/index.html", "docker"));
  131. // We do have categories
  132. assert_eq!(file_exists!(public, "categories/index.html"), true);
  133. assert_eq!(file_exists!(public, "categories/a-category/index.html"), true);
  134. assert_eq!(file_exists!(public, "categories/a-category/rss.xml"), true);
  135. // But no tags
  136. assert_eq!(file_exists!(public, "tags/index.html"), false);
  137. // Theme files are there
  138. assert!(file_exists!(public, "sample.css"));
  139. assert!(file_exists!(public, "some.js"));
  140. // SASS and SCSS files compile correctly
  141. assert!(file_exists!(public, "blog.css"));
  142. assert!(file_contains!(public, "blog.css", "red"));
  143. assert!(file_contains!(public, "blog.css", "blue"));
  144. assert!(!file_contains!(public, "blog.css", "@import \"included\""));
  145. assert!(file_contains!(public, "blog.css", "2rem")); // check include
  146. assert!(!file_exists!(public, "_included.css"));
  147. assert!(file_exists!(public, "scss.css"));
  148. assert!(file_exists!(public, "sass.css"));
  149. assert!(file_exists!(public, "nested_sass/sass.css"));
  150. assert!(file_exists!(public, "nested_sass/scss.css"));
  151. // no live reload code
  152. assert_eq!(
  153. file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10"),
  154. false
  155. );
  156. // Both pages and sections are in the sitemap
  157. assert!(file_contains!(
  158. public,
  159. "sitemap.xml",
  160. "<loc>https://replace-this-with-your-url.com/posts/simple/</loc>"
  161. ));
  162. assert!(file_contains!(
  163. public,
  164. "sitemap.xml",
  165. "<loc>https://replace-this-with-your-url.com/posts/</loc>"
  166. ));
  167. // Drafts are not in the sitemap
  168. assert!(!file_contains!(public, "sitemap.xml", "draft"));
  169. // render: false sections are not in the sitemap either
  170. assert!(!file_contains!(public, "sitemap.xml", "posts/2018/</loc>"));
  171. // robots.txt has been rendered from the template
  172. assert!(file_contains!(public, "robots.txt", "User-agent: zola"));
  173. assert!(file_contains!(
  174. public,
  175. "robots.txt",
  176. "Sitemap: https://replace-this-with-your-url.com/sitemap.xml"
  177. ));
  178. }
  179. #[test]
  180. fn can_build_site_with_live_reload_and_drafts() {
  181. let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
  182. site.enable_live_reload(1000);
  183. site.include_drafts();
  184. (site, true)
  185. });
  186. assert!(&public.exists());
  187. assert!(file_exists!(public, "index.html"));
  188. assert!(file_exists!(public, "sitemap.xml"));
  189. assert!(file_exists!(public, "robots.txt"));
  190. assert!(file_exists!(public, "a-fixed-url/index.html"));
  191. assert!(file_exists!(public, "posts/python/index.html"));
  192. assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html"));
  193. assert!(file_exists!(public, "posts/with-assets/index.html"));
  194. // Sections
  195. assert!(file_exists!(public, "posts/index.html"));
  196. assert!(file_exists!(public, "posts/tutorials/index.html"));
  197. assert!(file_exists!(public, "posts/tutorials/devops/index.html"));
  198. assert!(file_exists!(public, "posts/tutorials/programming/index.html"));
  199. // TODO: add assertion for syntax highlighting
  200. // We do have categories
  201. assert_eq!(file_exists!(public, "categories/index.html"), true);
  202. assert_eq!(file_exists!(public, "categories/a-category/index.html"), true);
  203. assert_eq!(file_exists!(public, "categories/a-category/rss.xml"), true);
  204. // But no tags
  205. assert_eq!(file_exists!(public, "tags/index.html"), false);
  206. // no live reload code
  207. assert!(file_contains!(public, "index.html", "/livereload.js"));
  208. // the summary anchor link has been created
  209. assert!(file_contains!(
  210. public,
  211. "posts/python/index.html",
  212. r#"<a name="continue-reading"></a>"#
  213. ));
  214. // Drafts are included
  215. assert!(file_exists!(public, "posts/draft/index.html"));
  216. assert!(file_contains!(public, "sitemap.xml", "draft"));
  217. }
  218. #[test]
  219. fn can_build_site_with_taxonomies() {
  220. let (site, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
  221. site.load().unwrap();
  222. {
  223. let mut library = site.library.write().unwrap();
  224. for (i, (_, page)) in library.pages_mut().iter_mut().enumerate() {
  225. page.meta.taxonomies = {
  226. let mut taxonomies = HashMap::new();
  227. taxonomies.insert(
  228. "categories".to_string(),
  229. vec![if i % 2 == 0 { "A" } else { "B" }.to_string()],
  230. );
  231. taxonomies
  232. };
  233. }
  234. }
  235. site.populate_taxonomies().unwrap();
  236. (site, false)
  237. });
  238. assert!(&public.exists());
  239. assert_eq!(site.taxonomies.len(), 1);
  240. assert!(file_exists!(public, "index.html"));
  241. assert!(file_exists!(public, "sitemap.xml"));
  242. assert!(file_exists!(public, "robots.txt"));
  243. assert!(file_exists!(public, "a-fixed-url/index.html"));
  244. assert!(file_exists!(public, "posts/python/index.html"));
  245. assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html"));
  246. assert!(file_exists!(public, "posts/with-assets/index.html"));
  247. // Sections
  248. assert!(file_exists!(public, "posts/index.html"));
  249. assert!(file_exists!(public, "posts/tutorials/index.html"));
  250. assert!(file_exists!(public, "posts/tutorials/devops/index.html"));
  251. assert!(file_exists!(public, "posts/tutorials/programming/index.html"));
  252. // Categories are there
  253. assert!(file_exists!(public, "categories/index.html"));
  254. assert!(file_exists!(public, "categories/a/index.html"));
  255. assert!(file_exists!(public, "categories/b/index.html"));
  256. assert!(file_exists!(public, "categories/a/rss.xml"));
  257. assert!(file_contains!(
  258. public,
  259. "categories/a/rss.xml",
  260. "https://replace-this-with-your-url.com/categories/a/rss.xml"
  261. ));
  262. // Extending from a theme works
  263. assert!(file_contains!(public, "categories/a/index.html", "EXTENDED"));
  264. // Tags aren't
  265. assert_eq!(file_exists!(public, "tags/index.html"), false);
  266. // Categories are in the sitemap
  267. assert!(file_contains!(
  268. public,
  269. "sitemap.xml",
  270. "<loc>https://replace-this-with-your-url.com/categories/</loc>"
  271. ));
  272. assert!(file_contains!(
  273. public,
  274. "sitemap.xml",
  275. "<loc>https://replace-this-with-your-url.com/categories/a/</loc>"
  276. ));
  277. }
  278. #[test]
  279. fn can_build_site_and_insert_anchor_links() {
  280. let (_, _tmp_dir, public) = build_site("test_site");
  281. assert!(Path::new(&public).exists());
  282. // anchor link inserted
  283. assert!(file_contains!(
  284. public,
  285. "posts/something-else/index.html",
  286. "<h1 id=\"title\"><a class=\"zola-anchor\" href=\"#title\""
  287. ));
  288. }
  289. #[test]
  290. fn can_build_site_with_pagination_for_section() {
  291. let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
  292. site.load().unwrap();
  293. {
  294. let mut library = site.library.write().unwrap();
  295. for (_, section) in library.sections_mut() {
  296. if section.is_index() {
  297. continue;
  298. }
  299. section.meta.paginate_by = Some(2);
  300. section.meta.template = Some("section_paginated.html".to_string());
  301. }
  302. }
  303. (site, false)
  304. });
  305. assert!(&public.exists());
  306. assert!(file_exists!(public, "index.html"));
  307. assert!(file_exists!(public, "sitemap.xml"));
  308. assert!(file_exists!(public, "robots.txt"));
  309. assert!(file_exists!(public, "a-fixed-url/index.html"));
  310. assert!(file_exists!(public, "posts/python/index.html"));
  311. assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html"));
  312. assert!(file_exists!(public, "posts/with-assets/index.html"));
  313. // Sections
  314. assert!(file_exists!(public, "posts/index.html"));
  315. // And pagination!
  316. assert!(file_exists!(public, "posts/page/1/index.html"));
  317. // even if there is no pages, only the section!
  318. assert!(file_exists!(public, "paginated/page/1/index.html"));
  319. assert!(file_exists!(public, "paginated/index.html"));
  320. // should redirect to posts/
  321. assert!(file_contains!(
  322. public,
  323. "posts/page/1/index.html",
  324. "http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/posts/\""
  325. ));
  326. assert!(file_contains!(public, "posts/index.html", "Num pagers: 5"));
  327. assert!(file_contains!(public, "posts/index.html", "Page size: 2"));
  328. assert!(file_contains!(public, "posts/index.html", "Current index: 1"));
  329. assert!(!file_contains!(public, "posts/index.html", "has_prev"));
  330. assert!(file_contains!(public, "posts/index.html", "has_next"));
  331. assert!(file_contains!(
  332. public,
  333. "posts/index.html",
  334. "First: https://replace-this-with-your-url.com/posts/"
  335. ));
  336. assert!(file_contains!(
  337. public,
  338. "posts/index.html",
  339. "Last: https://replace-this-with-your-url.com/posts/page/5/"
  340. ));
  341. assert_eq!(file_contains!(public, "posts/index.html", "has_prev"), false);
  342. assert!(file_exists!(public, "posts/page/2/index.html"));
  343. assert!(file_contains!(public, "posts/page/2/index.html", "Num pagers: 5"));
  344. assert!(file_contains!(public, "posts/page/2/index.html", "Page size: 2"));
  345. assert!(file_contains!(public, "posts/page/2/index.html", "Current index: 2"));
  346. assert!(file_contains!(public, "posts/page/2/index.html", "has_prev"));
  347. assert!(file_contains!(public, "posts/page/2/index.html", "has_next"));
  348. assert!(file_contains!(
  349. public,
  350. "posts/page/2/index.html",
  351. "First: https://replace-this-with-your-url.com/posts/"
  352. ));
  353. assert!(file_contains!(
  354. public,
  355. "posts/page/2/index.html",
  356. "Last: https://replace-this-with-your-url.com/posts/page/5/"
  357. ));
  358. assert!(file_exists!(public, "posts/page/3/index.html"));
  359. assert!(file_contains!(public, "posts/page/3/index.html", "Num pagers: 5"));
  360. assert!(file_contains!(public, "posts/page/3/index.html", "Page size: 2"));
  361. assert!(file_contains!(public, "posts/page/3/index.html", "Current index: 3"));
  362. assert!(file_contains!(public, "posts/page/3/index.html", "has_prev"));
  363. assert!(file_contains!(public, "posts/page/3/index.html", "has_next"));
  364. assert!(file_contains!(
  365. public,
  366. "posts/page/3/index.html",
  367. "First: https://replace-this-with-your-url.com/posts/"
  368. ));
  369. assert!(file_contains!(
  370. public,
  371. "posts/page/3/index.html",
  372. "Last: https://replace-this-with-your-url.com/posts/page/5/"
  373. ));
  374. assert!(file_exists!(public, "posts/page/4/index.html"));
  375. assert!(file_contains!(public, "posts/page/4/index.html", "Num pagers: 5"));
  376. assert!(file_contains!(public, "posts/page/4/index.html", "Page size: 2"));
  377. assert!(file_contains!(public, "posts/page/4/index.html", "Current index: 4"));
  378. assert!(file_contains!(public, "posts/page/4/index.html", "has_prev"));
  379. assert!(file_contains!(public, "posts/page/4/index.html", "has_next"));
  380. assert!(file_contains!(
  381. public,
  382. "posts/page/4/index.html",
  383. "First: https://replace-this-with-your-url.com/posts/"
  384. ));
  385. assert!(file_contains!(
  386. public,
  387. "posts/page/4/index.html",
  388. "Last: https://replace-this-with-your-url.com/posts/page/5/"
  389. ));
  390. // sitemap contains the pager pages
  391. assert!(file_contains!(
  392. public,
  393. "sitemap.xml",
  394. "<loc>https://replace-this-with-your-url.com/posts/page/4/</loc>"
  395. ));
  396. }
  397. #[test]
  398. fn can_build_site_with_pagination_for_index() {
  399. let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
  400. site.load().unwrap();
  401. {
  402. let mut library = site.library.write().unwrap();
  403. {
  404. let index = library
  405. .get_section_mut(&site.base_path.join("content").join("_index.md"))
  406. .unwrap();
  407. index.meta.paginate_by = Some(2);
  408. index.meta.template = Some("index_paginated.html".to_string());
  409. }
  410. }
  411. (site, false)
  412. });
  413. assert!(&public.exists());
  414. assert!(file_exists!(public, "index.html"));
  415. assert!(file_exists!(public, "sitemap.xml"));
  416. assert!(file_exists!(public, "robots.txt"));
  417. assert!(file_exists!(public, "a-fixed-url/index.html"));
  418. assert!(file_exists!(public, "posts/python/index.html"));
  419. assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html"));
  420. assert!(file_exists!(public, "posts/with-assets/index.html"));
  421. // And pagination!
  422. assert!(file_exists!(public, "page/1/index.html"));
  423. // even if there is no pages, only the section!
  424. assert!(file_exists!(public, "paginated/page/1/index.html"));
  425. assert!(file_exists!(public, "paginated/index.html"));
  426. // should redirect to index
  427. assert!(file_contains!(
  428. public,
  429. "page/1/index.html",
  430. "http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/\""
  431. ));
  432. assert!(file_contains!(public, "page/1/index.html", "<title>Redirect</title>"));
  433. assert!(file_contains!(
  434. public,
  435. "page/1/index.html",
  436. "<a href=\"https://replace-this-with-your-url.com/\">Click here</a>"
  437. ));
  438. assert!(file_contains!(public, "index.html", "Num pages: 1"));
  439. assert!(file_contains!(public, "index.html", "Current index: 1"));
  440. assert!(file_contains!(public, "index.html", "First: https://replace-this-with-your-url.com/"));
  441. assert!(file_contains!(public, "index.html", "Last: https://replace-this-with-your-url.com/"));
  442. assert_eq!(file_contains!(public, "index.html", "has_prev"), false);
  443. assert_eq!(file_contains!(public, "index.html", "has_next"), false);
  444. // sitemap contains the pager pages
  445. assert!(file_contains!(
  446. public,
  447. "sitemap.xml",
  448. "<loc>https://replace-this-with-your-url.com/page/1/</loc>"
  449. ))
  450. }
  451. #[test]
  452. fn can_build_site_with_pagination_for_taxonomy() {
  453. let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
  454. site.config.taxonomies.push(Taxonomy {
  455. name: "tags".to_string(),
  456. paginate_by: Some(2),
  457. paginate_path: None,
  458. rss: true,
  459. lang: site.config.default_language.clone(),
  460. });
  461. site.load().unwrap();
  462. {
  463. let mut library = site.library.write().unwrap();
  464. for (i, (_, page)) in library.pages_mut().iter_mut().enumerate() {
  465. page.meta.taxonomies = {
  466. let mut taxonomies = HashMap::new();
  467. taxonomies.insert(
  468. "tags".to_string(),
  469. vec![if i % 2 == 0 { "A" } else { "B" }.to_string()],
  470. );
  471. taxonomies
  472. };
  473. }
  474. }
  475. site.populate_taxonomies().unwrap();
  476. (site, false)
  477. });
  478. assert!(&public.exists());
  479. assert!(file_exists!(public, "index.html"));
  480. assert!(file_exists!(public, "sitemap.xml"));
  481. assert!(file_exists!(public, "robots.txt"));
  482. assert!(file_exists!(public, "a-fixed-url/index.html"));
  483. assert!(file_exists!(public, "posts/python/index.html"));
  484. assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html"));
  485. assert!(file_exists!(public, "posts/with-assets/index.html"));
  486. // Tags
  487. assert!(file_exists!(public, "tags/index.html"));
  488. // With RSS
  489. assert!(file_exists!(public, "tags/a/rss.xml"));
  490. assert!(file_exists!(public, "tags/b/rss.xml"));
  491. // And pagination!
  492. assert!(file_exists!(public, "tags/a/page/1/index.html"));
  493. assert!(file_exists!(public, "tags/b/page/1/index.html"));
  494. assert!(file_exists!(public, "tags/a/page/2/index.html"));
  495. assert!(file_exists!(public, "tags/b/page/2/index.html"));
  496. // should redirect to posts/
  497. assert!(file_contains!(
  498. public,
  499. "tags/a/page/1/index.html",
  500. "http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/tags/a/\""
  501. ));
  502. assert!(file_contains!(public, "tags/a/index.html", "Num pagers: 6"));
  503. assert!(file_contains!(public, "tags/a/index.html", "Page size: 2"));
  504. assert!(file_contains!(public, "tags/a/index.html", "Current index: 1"));
  505. assert!(!file_contains!(public, "tags/a/index.html", "has_prev"));
  506. assert!(file_contains!(public, "tags/a/index.html", "has_next"));
  507. assert!(file_contains!(
  508. public,
  509. "tags/a/index.html",
  510. "First: https://replace-this-with-your-url.com/tags/a/"
  511. ));
  512. assert!(file_contains!(
  513. public,
  514. "tags/a/index.html",
  515. "Last: https://replace-this-with-your-url.com/tags/a/page/6/"
  516. ));
  517. assert_eq!(file_contains!(public, "tags/a/index.html", "has_prev"), false);
  518. // sitemap contains the pager pages
  519. assert!(file_contains!(
  520. public,
  521. "sitemap.xml",
  522. "<loc>https://replace-this-with-your-url.com/tags/a/page/6/</loc>"
  523. ))
  524. }
  525. #[test]
  526. fn can_build_rss_feed() {
  527. let (_, _tmp_dir, public) = build_site("test_site");
  528. assert!(&public.exists());
  529. assert!(file_exists!(public, "rss.xml"));
  530. // latest article is posts/extra-syntax.md
  531. assert!(file_contains!(public, "rss.xml", "Extra Syntax"));
  532. // Next is posts/simple.md
  533. assert!(file_contains!(public, "rss.xml", "Simple article with shortcodes"));
  534. }
  535. #[test]
  536. fn can_build_search_index() {
  537. let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
  538. site.config.build_search_index = true;
  539. (site, true)
  540. });
  541. assert!(Path::new(&public).exists());
  542. assert!(file_exists!(public, "elasticlunr.min.js"));
  543. assert!(file_exists!(public, "search_index.en.js"));
  544. }
  545. #[test]
  546. fn can_build_with_extra_syntaxes() {
  547. let (_, _tmp_dir, public) = build_site("test_site");
  548. assert!(&public.exists());
  549. assert!(file_exists!(public, "posts/extra-syntax/index.html"));
  550. assert!(file_contains!(
  551. public,
  552. "posts/extra-syntax/index.html",
  553. r#"<span style="color:#d08770;">test</span>"#
  554. ));
  555. }
  556. #[test]
  557. fn can_apply_page_templates() {
  558. let mut path = env::current_dir().unwrap().parent().unwrap().parent().unwrap().to_path_buf();
  559. path.push("test_site");
  560. let mut site = Site::new(&path, "config.toml").unwrap();
  561. site.load().unwrap();
  562. let template_path = path.join("content").join("applying_page_template");
  563. let library = site.library.read().unwrap();
  564. let template_section = library.get_section(&template_path.join("_index.md")).unwrap();
  565. assert_eq!(template_section.subsections.len(), 2);
  566. assert_eq!(template_section.pages.len(), 2);
  567. let from_section_config = library.get_page_by_key(template_section.pages[0]);
  568. assert_eq!(from_section_config.meta.template, Some("page_template.html".into()));
  569. assert_eq!(from_section_config.meta.title, Some("From section config".into()));
  570. let override_page_template = library.get_page_by_key(template_section.pages[1]);
  571. assert_eq!(override_page_template.meta.template, Some("page_template_override.html".into()));
  572. assert_eq!(override_page_template.meta.title, Some("Override".into()));
  573. // It should have applied recursively as well
  574. let another_section =
  575. library.get_section(&template_path.join("another_section").join("_index.md")).unwrap();
  576. assert_eq!(another_section.subsections.len(), 0);
  577. assert_eq!(another_section.pages.len(), 1);
  578. let changed_recursively = library.get_page_by_key(another_section.pages[0]);
  579. assert_eq!(changed_recursively.meta.template, Some("page_template.html".into()));
  580. assert_eq!(changed_recursively.meta.title, Some("Changed recursively".into()));
  581. // But it should not have override a children page_template
  582. let yet_another_section =
  583. library.get_section(&template_path.join("yet_another_section").join("_index.md")).unwrap();
  584. assert_eq!(yet_another_section.subsections.len(), 0);
  585. assert_eq!(yet_another_section.pages.len(), 1);
  586. let child = library.get_page_by_key(yet_another_section.pages[0]);
  587. assert_eq!(child.meta.template, Some("page_template_child.html".into()));
  588. assert_eq!(child.meta.title, Some("Local section override".into()));
  589. }
  590. // https://github.com/getzola/zola/issues/571
  591. #[test]
  592. fn can_build_site_custom_builtins_from_theme() {
  593. let (_, _tmp_dir, public) = build_site("test_site");
  594. assert!(&public.exists());
  595. // 404.html is a theme template.
  596. assert!(file_exists!(public, "404.html"));
  597. assert!(file_contains!(public, "404.html", "Oops"));
  598. }
  599. #[test]
  600. fn can_ignore_markdown_content() {
  601. let (_, _tmp_dir, public) = build_site("test_site");
  602. assert!(!file_exists!(public, "posts/ignored/index.html"));
  603. }
  604. #[test]
  605. fn check_site() {
  606. let (mut site, _tmp_dir, _public) = build_site("test_site");
  607. assert_eq!(
  608. site.config.link_checker.skip_anchor_prefixes,
  609. vec!["https://github.com/rust-lang/rust/blob/"]
  610. );
  611. assert_eq!(site.config.link_checker.skip_prefixes, vec!["http://[2001:db8::]/"]);
  612. site.config.enable_check_mode();
  613. site.load().expect("link check test_site");
  614. }