webpage_quality_analyzer 1.0.2

High-performance webpage quality analyzer with 115 comprehensive metrics - Rust library with WASM, C++, and Python bindings
Documentation
//! Common test utilities and fixtures
//!
//! This module provides shared testing utilities for the webpage quality analyzer.

/// Builder pattern for creating custom test HTML
pub struct TestHtmlBuilder {
    title: String,
    description: Option<String>,
    headings: Vec<String>,
    paragraphs: Vec<String>,
    links: Vec<(String, String)>,  // (href, text)
    images: Vec<(String, String)>, // (src, alt)
    has_viewport: bool,
}

impl TestHtmlBuilder {
    /// Create a new HTML builder
    pub fn new() -> Self {
        Self {
            title: "Test Page".to_string(),
            description: None,
            headings: Vec::new(),
            paragraphs: Vec::new(),
            links: Vec::new(),
            images: Vec::new(),
            has_viewport: false,
        }
    }

    /// Set the page title
    pub fn with_title(mut self, title: &str) -> Self {
        self.title = title.to_string();
        self
    }

    /// Set the meta description
    pub fn with_description(mut self, description: &str) -> Self {
        self.description = Some(description.to_string());
        self
    }

    /// Add a heading
    pub fn add_heading(mut self, text: &str) -> Self {
        self.headings.push(text.to_string());
        self
    }

    /// Add a paragraph
    pub fn add_paragraph(mut self, text: &str) -> Self {
        self.paragraphs.push(text.to_string());
        self
    }

    /// Add a link
    pub fn add_link(mut self, href: &str, text: &str) -> Self {
        self.links.push((href.to_string(), text.to_string()));
        self
    }

    /// Add an image
    pub fn add_image(mut self, src: &str, alt: &str) -> Self {
        self.images.push((src.to_string(), alt.to_string()));
        self
    }

    /// Include viewport meta tag
    pub fn with_viewport(mut self) -> Self {
        self.has_viewport = true;
        self
    }

    /// Build the HTML string
    pub fn build(self) -> String {
        use std::fmt::Write;

        // Pre-calculate approximate capacity to reduce reallocations
        let base_capacity = 200;
        let content_capacity = self.headings.len() * 50
            + self.paragraphs.len() * 50
            + self.links.len() * 80
            + self.images.len() * 60
            + self.title.len()
            + self.description.as_ref().map_or(0, |d| d.len());

        let mut html = String::with_capacity(base_capacity + content_capacity);

        html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
        write!(&mut html, "    <title>{}</title>\n", self.title)
            .expect("Writing to string should not fail");

        if let Some(desc) = self.description {
            write!(
                &mut html,
                "    <meta name=\"description\" content=\"{}\">\n",
                desc
            )
            .expect("Writing to string should not fail");
        }

        if self.has_viewport {
            html.push_str(
                "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n",
            );
        }

        html.push_str("</head>\n<body>\n");

        for (i, heading) in self.headings.iter().enumerate() {
            let level = if i == 0 { 1 } else { 2 };
            write!(&mut html, "    <h{}>{}</h{}>\n", level, heading, level)
                .expect("Writing to string should not fail");
        }

        for paragraph in &self.paragraphs {
            write!(&mut html, "    <p>{}</p>\n", paragraph).unwrap();
        }

        for (href, text) in &self.links {
            write!(&mut html, "    <a href=\"{}\">{}</a>\n", href, text)
                .expect("Writing to string should not fail");
        }

        for (src, alt) in &self.images {
            write!(&mut html, "    <img src=\"{}\" alt=\"{}\">\n", src, alt).unwrap();
        }

        html.push_str("</body>\n</html>");
        html
    }
}

impl Default for TestHtmlBuilder {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_html_builder_basic() {
        let html = TestHtmlBuilder::new()
            .with_title("Test Title")
            .add_heading("Main Heading")
            .add_paragraph("Test paragraph content")
            .build();

        assert!(html.contains("Test Title"));
        assert!(html.contains("Main Heading"));
        assert!(html.contains("Test paragraph"));
    }

    #[test]
    fn test_html_builder_with_metadata() {
        let html = TestHtmlBuilder::new()
            .with_title("Meta Test")
            .with_description("Test page for metadata")
            .with_viewport()
            .build();

        assert!(html.contains("Meta Test"));
        assert!(html.contains("Test page for metadata"));
        assert!(html.contains("viewport"));
    }
}