sitemap_gen/
lib.rs

1// src/lib.rs
2
3#![doc = include_str!("../README.md")]
4#![doc(
5    html_favicon_url = "https://kura.pro/sitemap-gen/images/favicon.ico",
6    html_logo_url = "https://kura.pro/sitemap-gen/images/logos/sitemap-gen.svg",
7    html_root_url = "https://docs.rs/sitemap-gen"
8)]
9#![crate_name = "sitemap_gen"]
10#![crate_type = "lib"]
11
12//! A Rust library for generating and managing sitemaps.
13//!
14//! This crate provides functionality to create, modify, and serialize XML sitemaps according to the [Sitemaps XML format](https://www.sitemaps.org/protocol.html).
15//! It includes support for handling various sitemap-specific data types and error conditions.
16
17/// Contains error types specific to sitemap operations.
18///
19/// This module defines a comprehensive set of error types that can occur during
20/// sitemap creation, modification, and serialization processes.
21pub mod error;
22
23/// Provides the core functionality for creating and managing sitemaps.
24///
25/// This module contains the main structures and functions for working with sitemaps,
26/// including creating sitemap entries, setting change frequencies, and serializing to XML.
27pub mod sitemap;
28
29/// Utility functions and helper methods for sitemap operations.
30pub mod utils;
31
32// Re-exports
33pub use error::SitemapError;
34pub use sitemap::{
35    convert_date_format, create_site_map_data, ChangeFreq, SiteMapData,
36    Sitemap,
37};
38
39/// Result type alias for sitemap operations.
40pub type SitemapResult<T> = Result<T, SitemapError>;
41
42/// A prelude module for convenient importing of commonly used items.
43pub mod prelude {
44    pub use crate::error::SitemapError;
45    pub use crate::sitemap::{ChangeFreq, SiteMapData, Sitemap};
46    pub use crate::SitemapResult;
47}
48
49#[cfg(test)]
50mod tests {
51    use url::Url;
52
53    use super::*;
54    use crate::error::SitemapError;
55    use crate::sitemap::{ChangeFreq, SiteMapData, Sitemap};
56    use crate::SitemapResult;
57
58    #[test]
59    fn test_create_sitemap() {
60        // Create an empty sitemap
61        let mut sitemap = Sitemap::new();
62
63        // Create a SiteMapData entry
64        let entry = SiteMapData {
65            loc: Url::parse("http://example.com")
66                .expect("Failed to parse URL"),
67            lastmod: "2024-10-08".to_string(),
68            changefreq: ChangeFreq::Daily,
69        };
70
71        // Add the entry to the sitemap
72        sitemap.add_entry(entry).expect("Failed to add entry");
73
74        // Verify the sitemap contains the correct data
75        assert_eq!(sitemap.len(), 1);
76        assert!(!sitemap.is_empty());
77    }
78
79    #[test]
80    fn test_serialize_sitemap() {
81        // Create a new sitemap and add an entry
82        let mut sitemap = Sitemap::new();
83        let entry = SiteMapData {
84            loc: Url::parse("http://example.com")
85                .expect("Failed to parse URL"),
86            lastmod: "2024-10-08".to_string(),
87            changefreq: ChangeFreq::Daily,
88        };
89
90        sitemap.add_entry(entry).expect("Failed to add entry");
91
92        // Serialize the sitemap to XML
93        let serialized =
94            sitemap.to_xml().expect("Failed to serialize sitemap");
95
96        // Assert that the serialized XML contains the correct information
97        assert!(serialized.contains("<url>"));
98        assert!(serialized.contains("<loc>http://example.com/</loc>")); // Note the trailing slash
99        assert!(serialized.contains("<changefreq>daily</changefreq>"));
100        assert!(serialized.contains("<lastmod>2024-10-08</lastmod>"));
101    }
102
103    #[test]
104    fn test_invalid_url_error() {
105        // Try to add an entry with an invalid URL and expect an error
106        let mut sitemap = Sitemap::new();
107
108        let invalid_url = Url::parse("invalid-url");
109        let result = match invalid_url {
110            Ok(valid_url) => sitemap.add_entry(SiteMapData {
111                loc: valid_url,
112                lastmod: "2024-10-08".to_string(),
113                changefreq: ChangeFreq::Daily,
114            }),
115            Err(e) => Err(SitemapError::UrlError(e)),
116        };
117
118        // Assert that the result is an error due to an invalid URL
119        assert!(matches!(result, Err(SitemapError::UrlError(_))));
120    }
121
122    #[test]
123    fn test_convert_date_format() {
124        // Test converting date formats using the helper function
125        let date = "2024-10-08T00:00:00Z";
126        let converted = convert_date_format(date);
127        assert_eq!(converted, "2024-10-08");
128    }
129
130    #[test]
131    fn test_change_freq_enum() {
132        // Test the ChangeFreq enum values
133        assert_eq!(ChangeFreq::Daily.to_string(), "daily");
134        assert_eq!(ChangeFreq::Monthly.to_string(), "monthly");
135    }
136
137    #[test]
138    fn test_sitemap_data_creation() {
139        // Test creating a new SiteMapData instance
140        let sitemap_entry = SiteMapData {
141            loc: Url::parse("http://example.com")
142                .expect("Failed to parse URL"),
143            lastmod: "2024-10-08".to_string(),
144            changefreq: ChangeFreq::Daily,
145        };
146
147        // Create an empty sitemap and add the entry
148        let mut sitemap = Sitemap::new();
149        sitemap
150            .add_entry(sitemap_entry)
151            .expect("Failed to add entry");
152
153        // Check that the entry was added
154        assert_eq!(sitemap.len(), 1);
155    }
156
157    #[test]
158    fn test_sitemap_error_handling() {
159        // Test various error types defined in SitemapError
160        let url_error: SitemapError =
161            SitemapError::UrlError(url::ParseError::EmptyHost);
162        let io_error: SitemapError =
163            SitemapError::IoError(std::io::Error::new(
164                std::io::ErrorKind::NotFound,
165                "File not found",
166            ));
167
168        assert!(matches!(url_error, SitemapError::UrlError(_)));
169        assert!(matches!(io_error, SitemapError::IoError(_)));
170    }
171
172    #[test]
173    fn test_sitemap_result() {
174        // Test that SitemapResult works with Ok and Err variants
175        let success: SitemapResult<&str> = Ok("Success");
176        let failure: SitemapResult<&str> =
177            Err(SitemapError::UrlError(url::ParseError::EmptyHost));
178
179        assert!(success.is_ok());
180        assert!(failure.is_err());
181    }
182    #[test]
183    fn test_valid_url_addition() {
184        // Create a new empty sitemap
185        let mut sitemap = Sitemap::new();
186
187        // Try to add a valid URL
188        let valid_url = Url::parse("http://example.com")
189            .expect("Failed to parse valid URL");
190
191        let result = sitemap.add_entry(SiteMapData {
192            loc: valid_url,
193            lastmod: "2024-10-08".to_string(),
194            changefreq: ChangeFreq::Daily,
195        });
196
197        // Assert that the entry was successfully added
198        assert!(result.is_ok(), "Failed to add valid URL to sitemap");
199
200        // Check that the sitemap now contains the entry
201        assert_eq!(sitemap.len(), 1);
202        assert!(!sitemap.is_empty());
203    }
204}