From 1ad1d863cfa4d0266141449c8cd8092e86f2f476 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 19 Sep 2024 23:30:13 +0100 Subject: [PATCH] fix(ssg): :bug: minor fixes --- ssg-core/src/compiler/service.rs | 16 +-- ssg-template/src/engine.rs | 12 +- ssg-template/tests/engine_tests.rs | 190 +++++++++++++++-------------- 3 files changed, 114 insertions(+), 104 deletions(-) diff --git a/ssg-core/src/compiler/service.rs b/ssg-core/src/compiler/service.rs index b77afe68..68bfbf5d 100644 --- a/ssg-core/src/compiler/service.rs +++ b/ssg-core/src/compiler/service.rs @@ -156,17 +156,17 @@ fn process_file( // Create page options let mut page_options = PageOptions::new(); for (key, value) in metadata.iter() { - page_options.set(key, value); + page_options.set(key.to_string(), value.to_string()); } // Set various meta tags - page_options.set("apple", &all_meta_tags.apple); - page_options.set("content", &html_content); - page_options.set("microsoft", &all_meta_tags.ms); - page_options.set("navigation", navigation); - page_options.set("opengraph", &all_meta_tags.og); - page_options.set("primary", &all_meta_tags.primary); - page_options.set("twitter", &all_meta_tags.twitter); + page_options.set("apple".to_string(), all_meta_tags.apple.clone()); + page_options.set("content".to_string(), html_content); + page_options.set("microsoft".to_string(), all_meta_tags.ms.clone()); + page_options.set("navigation".to_string(), navigation.to_owned()); + page_options.set("opengraph".to_string(), all_meta_tags.og); + page_options.set("primary".to_string(), all_meta_tags.primary); + page_options.set("twitter".to_string(), all_meta_tags.twitter); // Convert PageOptions to TemplateContext let mut context = TemplateContext::new(); diff --git a/ssg-template/src/engine.rs b/ssg-template/src/engine.rs index 4734fb35..892277ad 100644 --- a/ssg-template/src/engine.rs +++ b/ssg-template/src/engine.rs @@ -14,26 +14,26 @@ use tempfile::tempdir; /// This struct contains the options for rendering a page template. /// These options are used to construct a context `HashMap` that is /// passed to the `render_template` function. -pub struct PageOptions<'a> { +pub struct PageOptions { /// Elements of the page - pub elements: HashMap<&'a str, &'a str>, + pub elements: HashMap, } -impl<'a> PageOptions<'a> { +impl PageOptions { /// Creates a new `PageOptions` instance. - pub fn new() -> PageOptions<'a> { + pub fn new() -> PageOptions { PageOptions { elements: HashMap::new(), } } /// Sets a page option in the `elements` map. - pub fn set(&mut self, key: &'a str, value: &'a str) { + pub fn set(&mut self, key: String, value: String) { self.elements.insert(key, value); } /// Retrieves a page option from the `elements` map. - pub fn get(&self, key: &'a str) -> Option<&&'a str> { + pub fn get(&self, key: &str) -> Option<&String> { self.elements.get(key) } } diff --git a/ssg-template/tests/engine_tests.rs b/ssg-template/tests/engine_tests.rs index fb31f750..b9a34951 100644 --- a/ssg-template/tests/engine_tests.rs +++ b/ssg-template/tests/engine_tests.rs @@ -3,7 +3,10 @@ mod tests { use ssg_template::{Context, Engine, TemplateError}; use std::collections::HashMap; + use std::fs::File; + use std::io::Write; use std::time::Duration; + use tempfile::tempdir; /// Helper function to create an `Engine` instance. fn create_engine() -> Engine { @@ -18,6 +21,20 @@ mod tests { context } + /// Helper function to assert template rendering results. + fn assert_template_rendering( + engine: &Engine, + template: &str, + context: &HashMap, + expected_result: Result<&str, TemplateError>, + ) { + let result = engine.render_template(template, context); + match expected_result { + Ok(expected) => assert_eq!(result.unwrap(), expected), + Err(_) => assert!(result.is_err()), + } + } + /// Tests for template rendering in the `Engine` struct. mod render_tests { use super::*; @@ -25,15 +42,14 @@ mod tests { #[test] fn test_engine_render_template() { let engine = create_engine(); - let context = Context { - elements: create_basic_context(), - }; + let context = create_basic_context(); let template = "{{greeting}}, {{name}}!"; - - let result = engine - .render_template(template, &context.elements) - .unwrap(); - assert_eq!(result, "Hello, World!"); + assert_template_rendering( + &engine, + template, + &context, + Ok("Hello, World!"), + ); } #[test] @@ -41,12 +57,12 @@ mod tests { let engine = create_engine(); let context: HashMap = HashMap::new(); let template = "{{greeting}}, {{name}}!"; - - let result = engine.render_template(template, &context); - assert!(matches!( - result, - Err(TemplateError::RenderError(_)) - )); + assert_template_rendering( + &engine, + template, + &context, + Err(TemplateError::RenderError("".to_string())), + ); } #[test] @@ -54,26 +70,16 @@ mod tests { let engine = create_engine(); let context: HashMap = HashMap::new(); let template = ""; - - let result = engine.render_template(template, &context); - assert!( - matches!(result, Err(TemplateError::RenderError(msg)) if msg == "Template is empty") + assert_template_rendering( + &engine, + template, + &context, + Err(TemplateError::RenderError( + "Template is empty".to_string(), + )), ); } - #[test] - fn test_engine_render_empty_context() { - let engine = create_engine(); - let context: HashMap = HashMap::new(); - let template = "{{greeting}}, {{name}}!"; - - let result = engine.render_template(template, &context); - assert!(matches!( - result, - Err(TemplateError::RenderError(_)) - )); - } - #[test] fn test_engine_render_special_characters_in_context() { let engine = create_engine(); @@ -84,10 +90,12 @@ mod tests { ); context.insert("greeting".to_string(), "&".to_string()); let template = "{{greeting}} {{name}}"; - - let result = - engine.render_template(template, &context).unwrap(); - assert_eq!(result, "& "); + assert_template_rendering( + &engine, + template, + &context, + Ok("& "), + ); } #[test] @@ -124,18 +132,25 @@ mod tests { /// Tests related to file operations, such as downloading templates. mod file_tests { use super::*; - use std::fs::File; - use std::io::Write; - use tempfile::tempdir; + + fn create_temp_file_with_content( + content: &str, + ) -> (File, String) { + let temp_dir = tempdir().unwrap(); + let path = temp_dir.path().join("layout.html"); + let mut file = File::create(&path).unwrap(); + writeln!(file, "{}", content).unwrap(); + (file, path.to_str().unwrap().to_string()) + } #[test] fn test_engine_download_file() { let engine = create_engine(); let url = "https://raw.githubusercontent.com/sebastienrousseau/shokunin/main/templates"; - let file = "index.html"; // Example file to download - let temp_dir = tempfile::tempdir().unwrap(); // Create a temporary directory + let file = "index.html"; + let temp_dir = tempdir().unwrap(); let result = - engine.download_file(url, file, temp_dir.path()); // Pass all three arguments + engine.download_file(url, file, temp_dir.path()); assert!(result.is_ok()); } @@ -153,14 +168,9 @@ mod tests { #[test] fn test_render_page_valid_path() { - let temp_dir = tempdir().unwrap(); - let layout_path = temp_dir.path().join("layout.html"); - - let mut file = File::create(&layout_path).unwrap(); - writeln!(file, "{{{{greeting}}}}, {{{{name}}}}").unwrap(); - + let (_, layout_path) = create_temp_file_with_content("{{{{greeting}}}}, {{{{name}}}}"); let mut engine = Engine::new( - temp_dir.path().to_str().unwrap(), + layout_path.as_str(), Duration::from_secs(60), ); let context = Context { @@ -171,7 +181,7 @@ mod tests { assert!(result.is_ok()); assert_eq!( result.unwrap().trim(), - "Hello, World" + "Hello, World" ); } @@ -201,28 +211,27 @@ mod tests { #[test] fn test_page_options_set_get() { let mut options = PageOptions::new(); - options.set("title", "My Title"); - assert_eq!(options.get("title"), Some(&"My Title")); + options.set("title".to_string(), "My Title".to_string()); + assert_eq!( + options.get("title"), + Some(&"My Title".to_string()) + ); assert_eq!(options.get("non_existent"), None); } #[test] fn test_page_options_large_context() { let mut options = PageOptions::new(); - let mut keys = Vec::new(); - let mut values = Vec::new(); for i in 0..1000 { let key = format!("key{}", i); let value = format!("value{}", i); - keys.push(key); - values.push(value); - } - for i in 0..1000 { - options.set(&keys[i], &values[i]); + options.set(key, value); // Now we can pass the owned Strings } - - assert_eq!(options.get("key999"), Some(&"value999")); - assert_eq!(options.get("key1000"), None); // Key not present + assert_eq!( + options.get("key999"), + Some(&"value999".to_string()) + ); + assert_eq!(options.get("key1000"), None); } } @@ -234,53 +243,54 @@ mod tests { fn test_render_template_invalid_format() { let engine = create_engine(); let context = create_basic_context(); - let template = "{greeting}, {name}!"; // Invalid format (single curly braces) - - let result = engine.render_template(template, &context); - assert!(matches!( - result, - Err(TemplateError::RenderError(_)) - )); + let template = "{greeting}, {name}!"; + assert_template_rendering( + &engine, + template, + &context, + Err(TemplateError::RenderError("".to_string())), + ); } #[test] fn test_render_template_invalid_syntax() { let engine = create_engine(); let context = create_basic_context(); - let invalid_template = "Hello, {{name"; // Missing closing braces - - let result = - engine.render_template(invalid_template, &context); - assert!(matches!( - result, - Err(TemplateError::RenderError(_)) - )); + let invalid_template = "Hello, {{name"; + assert_template_rendering( + &engine, + invalid_template, + &context, + Err(TemplateError::RenderError("".to_string())), + ); } #[test] fn test_render_large_template() { let engine = create_engine(); - let large_template = "Hello, {{name}}".repeat(1000); // Large template with repetitive pattern + let large_template = "Hello, {{name}}".repeat(1000); let context = create_basic_context(); - - let result = - engine.render_template(&large_template, &context); - assert!(result.is_ok()); - assert!(result.unwrap().contains("Hello, World")); + assert_template_rendering( + &engine, + &large_template, + &context, + Ok(&"Hello, World".repeat(1000)), + ); } #[test] fn test_render_template_empty_template() { let engine = create_engine(); let context = create_basic_context(); - let empty_template = ""; // Empty template - - let result = - engine.render_template(empty_template, &context); - assert!(matches!( - result, - Err(TemplateError::RenderError(_)) - )); + let empty_template = ""; + assert_template_rendering( + &engine, + empty_template, + &context, + Err(TemplateError::RenderError( + "Template is empty".to_string(), + )), + ); } } }