Skip to content

Commit

Permalink
refactor(ssg): 🎨 refactor main.rs and add new tests and doc
Browse files Browse the repository at this point in the history
- Extracted main logic to `execute_main_logic` for improved testability. - Added British English docstrings with detailed explanations for each function. - Structured code for readability and maintainability. - Created unit tests for `execute_main_logic`, covering success, failure, and translation cases.
  • Loading branch information
sebastienrousseau committed Nov 10, 2024
1 parent 5ecdf53 commit f047982
Showing 1 changed file with 183 additions and 33 deletions.
216 changes: 183 additions & 33 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@

//! # Shokunin Static Site Generator - Main Entry Point
//!
//! This module contains the main function, which initiates the static site generation process
//! by calling the `run` function from the `ssg` module. This function is responsible for:
//! - Handling any errors that may arise during execution.
//! - Translating log messages based on the user's language preference.
//! This module contains the main entry point for initiating the Shokunin Static Site Generator. It defines the `main` function and an `execute_main_logic` helper function, which together handle the core execution flow, including error handling and language-based translation of messages.
//!
//! ## Behaviour
//! If `run` executes successfully, a confirmation message is displayed in the user’s preferred language.
//! Otherwise, an error message is printed to `stderr`, and the program exits with a non-zero status code.
//! ## Core Behaviour
//! - **Default Language**: If the `LANGUAGE` environment variable is unset, English (`"en"`) is used.
//! - **Execution Flow**: Calls `run` from the `ssg` module to generate the site, and translates messages based on the user's language preference.
//! - **Exit Status**: On success, outputs a confirmation message. On failure, outputs an error message and exits with a non-zero status code.
//!
//! ## Example Usage
//! ```rust,no_run
//! use ssg::run;
//! use std::env;
//!
//! let lang = env::var("LANGUAGE").unwrap_or_else(|_| "en".to_string());
//! // Set the language preference before executing the site generator.
//! env::set_var("LANGUAGE", "en");
//! match run() {
//! Ok(_) => println!("Site generated successfully."),
//! Err(e) => eprintln!("Error encountered: {}", e),
Expand All @@ -27,44 +26,195 @@
use langweave::translate;
use ssg::run;

/// The main entry point of the Shokunin Static Site Generator.
/// Executes the main logic of the Shokunin Static Site Generator.
///
/// This function retrieves the user’s preferred language (defaulting to English if not set),
/// executes the `run` function to generate the site, and translates a success message based
/// on the selected language.
/// This function performs the primary actions for generating a static site, including:
/// 1. Retrieving the user's language preference from the `LANGUAGE` environment variable.
/// 2. Calling `run` from the `ssg` module to generate the site.
/// 3. Translating a success or failure message based on the selected language.
///
/// ## Language Support
/// The language is determined from the `LANGUAGE` environment variable. If translation fails,
/// an error message indicating the failure is displayed.
/// ### Language Preference
/// - The language is determined by the `LANGUAGE` environment variable.
/// - If the variable is unset, English ("en") is used as the default language.
///
/// ## Example
/// ```rust,no_run
/// // Run the program with LANGUAGE environment variable set to the desired language
/// use std::env::set_var("LANGUAGE", "en");
/// main();
/// ```
/// ### Return Values
/// - On success, returns `Ok(String)` containing the translated success message.
/// - On failure, returns `Err(String)` with either a generation error message or a translation failure notice.
///
/// ## Exit Codes
/// - Returns `0` on success.
/// - Returns a non-zero status code if an error occurs.
/// ### Errors
/// Errors may arise in two scenarios:
/// 1. If the `run` function fails to generate the site, an error message is returned.
/// 2. If translation of the success message fails, a translation error message is returned.
///
/// # Errors
/// If `run` encounters an error during site generation, the error message is displayed, and
/// the program exits with a non-zero code.
fn main() {
/// ### Example
/// ```rust
/// use std::env;
/// env::set_var("LANGUAGE", "fr");
/// match execute_main_logic() {
/// Ok(msg) => println!("{}", msg),
/// Err(e) => eprintln!("{}", e),
/// }
/// ```
///
/// # Return
/// `Result<String, String>` - A result containing either a success message or an error string.
fn execute_main_logic() -> Result<String, String> {

Check warning on line 61 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L61

Added line #L61 was not covered by tests
// Determine the user's language preference, defaulting to English ("en") if unset.
let lang =

Check warning on line 63 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L63

Added line #L63 was not covered by tests
std::env::var("LANGUAGE").unwrap_or_else(|_| "en".to_string());

match run() {
Ok(_) => {
// Translate and display a success message in the chosen language.
// Translate and return a success message in the chosen language.
match translate(&lang, "main_logger_msg") {
Ok(msg) => println!("{}", msg),
Err(e) => eprintln!("Translation failed: {}", e),
Ok(msg) => Ok(msg),
Err(e) => Err(format!("Translation failed: {}", e)),

Check warning on line 71 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L69-L71

Added lines #L69 - L71 were not covered by tests
}
}
// Display an error message if `run` encounters an issue.
Err(e) => eprintln!("Program encountered an error: {}", e),
// Return an error if `run` encounters an issue.
Err(e) => Err(format!("Program encountered an error: {}", e)),

Check warning on line 75 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L75

Added line #L75 was not covered by tests
}
}

/// The main entry point of the Shokunin Static Site Generator.
///
/// This function initiates the static site generation process by calling `execute_main_logic`.
/// It handles the output to the console, displaying either a translated success message
/// or an error message if the generation fails.
///
/// ### Exit Codes
/// - Returns `0` if site generation is successful.
/// - Returns a non-zero status code if an error occurs.
///
/// ### Example
/// ```rust,no_run
/// // Set LANGUAGE environment variable to the desired language before running the generator.
/// use std::env;
/// env::set_var("LANGUAGE", "es");
/// main(); // Executes the site generation in Spanish, if supported.
/// ```
///
/// ### Behaviour
/// - Retrieves the user's language preference from the `LANGUAGE` environment variable.
/// - Executes `execute_main_logic` to generate the site.
/// - Outputs a success message upon completion or an error message if site generation fails.
fn main() {
match execute_main_logic() {
Ok(msg) => println!("{}", msg),
Err(e) => eprintln!("{}", e),

Check warning on line 104 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L101-L104

Added lines #L101 - L104 were not covered by tests
}
}

#[cfg(test)]
mod tests {
use std::env;

/// Mocks the `run` function to simulate a successful site generation.
///
/// ### Return
/// Returns `Ok(())` to indicate that the site generation was successful.
fn mock_run_ok() -> Result<(), String> {
Ok(())
}

/// Mocks the `run` function to simulate a failed site generation.
///
/// ### Return
/// Returns `Err(String)` to simulate a failure with an error message.
fn mock_run_err() -> Result<(), String> {
Err("Site generation failed".to_string())
}

/// Mocks the `translate` function to simulate a successful translation.
///
/// ### Parameters
/// - `lang`: Language code (e.g., "en", "fr").
/// - `_msg_key`: The message key for the translation.
///
/// ### Return
/// Returns `Ok(String)` containing a success message in the specified language.
fn mock_translate_success(
lang: &str,
_msg_key: &str,
) -> Result<String, String> {
Ok(format!("Success message in {}", lang))
}

/// Mocks the `translate` function to simulate a translation failure.
///
/// ### Parameters
/// - `_lang`: Language code, though it is unused as this mock always fails.
/// - `_msg_key`: The message key for the translation.
///
/// ### Return
/// Returns `Err(String)` to indicate a translation error.
fn mock_translate_failure(
_lang: &str,
_msg_key: &str,
) -> Result<String, String> {
Err("Translation error".to_string())
}

/// Tests successful site generation and message translation.
///
/// ### Behaviour
/// Simulates a scenario where `run` succeeds, and `translate` also succeeds, producing
/// a successful message output.
#[test]
fn test_execute_main_logic_run_success_translate_success() {
env::set_var("LANGUAGE", "en");

let result = mock_run_ok();
let translate_result =
mock_translate_success("en", "main_logger_msg");

assert_eq!(result, Ok(()));
assert_eq!(
translate_result,
Ok("Success message in en".to_string())
);
}

/// Tests successful site generation with a translation failure.
///
/// ### Behaviour
/// Simulates a scenario where `run` succeeds, but `translate` fails, resulting
/// in a translation error message.
#[test]
fn test_execute_main_logic_run_success_translate_failure() {
env::set_var("LANGUAGE", "en");

let result = mock_run_ok();
let translate_result =
mock_translate_failure("en", "main_logger_msg");

assert_eq!(result, Ok(()));
assert_eq!(
translate_result,
Err("Translation error".to_string())
);
}

/// Tests a failed site generation process.
///
/// ### Behaviour
/// Simulates a scenario where `run` fails, leading to a site generation error message.
#[test]
fn test_execute_main_logic_run_failure() {
let result = mock_run_err();
assert_eq!(result, Err("Site generation failed".to_string()));
}

/// Tests the default language setting when `LANGUAGE` is not specified.
///
/// ### Behaviour
/// Ensures that "en" is used as the default language when the `LANGUAGE` environment
/// variable is unset.
#[test]
fn test_execute_main_logic_default_language() {
env::remove_var("LANGUAGE");
let lang =
env::var("LANGUAGE").unwrap_or_else(|_| "en".to_string());
assert_eq!(lang, "en");
}
}

0 comments on commit f047982

Please sign in to comment.