🎨 style: fix clippy warnings and clean up test code

This commit is contained in:
Jeremiah Russell
2025-10-20 09:56:39 +01:00
committed by Jeremiah Russell
parent 084a643b74
commit b26887e05a
3 changed files with 56 additions and 81 deletions

View File

@@ -118,28 +118,28 @@ use crate::{ClientConfig, Error, Result, rules::EolRule};
/// ///
/// This constant defines the default page size for Gmail API list operations. /// This constant defines the default page size for Gmail API list operations.
/// The value "200" represents a balance between API efficiency and memory usage. /// The value "200" represents a balance between API efficiency and memory usage.
/// ///
/// Gmail API supports up to 500 results per page, but 200 provides good performance /// Gmail API supports up to 500 results per page, but 200 provides good performance
/// while keeping response sizes manageable. /// while keeping response sizes manageable.
pub const DEFAULT_MAX_RESULTS: &str = "200"; pub const DEFAULT_MAX_RESULTS: &str = "200";
/// Gmail API client providing authenticated access to Gmail operations. /// Gmail API client providing authenticated access to Gmail operations.
/// ///
/// `GmailClient` manages the connection to Gmail's REST API, handles OAuth2 authentication, /// `GmailClient` manages the connection to Gmail's REST API, handles OAuth2 authentication,
/// maintains label mappings, and provides methods for message list operations. /// maintains label mappings, and provides methods for message list operations.
/// ///
/// The client contains internal state for: /// The client contains internal state for:
/// - Authentication credentials and tokens /// - Authentication credentials and tokens
/// - Label name-to-ID mappings /// - Label name-to-ID mappings
/// - Query filters and pagination settings /// - Query filters and pagination settings
/// - Retrieved message summaries /// - Retrieved message summaries
/// - Rule processing configuration /// - Rule processing configuration
/// ///
/// # Examples /// # Examples
/// ///
/// ```rust,no_run /// ```rust,no_run
/// use cull_gmail::{ClientConfig, GmailClient}; /// use cull_gmail::{ClientConfig, GmailClient};
/// ///
/// # async fn example() -> cull_gmail::Result<()> { /// # async fn example() -> cull_gmail::Result<()> {
/// let config = ClientConfig::builder() /// let config = ClientConfig::builder()
/// .with_client_id("client-id") /// .with_client_id("client-id")
@@ -378,7 +378,7 @@ impl GmailClient {
/// # async fn example() -> cull_gmail::Result<()> { /// # async fn example() -> cull_gmail::Result<()> {
/// # let config = ClientConfig::builder().build(); /// # let config = ClientConfig::builder().build();
/// let client = GmailClient::new_with_config(config).await?; /// let client = GmailClient::new_with_config(config).await?;
/// ///
/// // Display all labels (output goes to log) /// // Display all labels (output goes to log)
/// client.show_label(); /// client.show_label();
/// # Ok(()) /// # Ok(())

View File

@@ -190,15 +190,15 @@ mod tests {
#[test] #[test]
fn test_message_summary_set_subject() { fn test_message_summary_set_subject() {
let mut summary = MessageSummary::new("test_id"); let mut summary = MessageSummary::new("test_id");
// Test setting a subject // Test setting a subject
summary.set_subject(Some("Test Subject".to_string())); summary.set_subject(Some("Test Subject".to_string()));
assert_eq!(summary.subject(), "Test Subject"); assert_eq!(summary.subject(), "Test Subject");
// Test setting subject to None // Test setting subject to None
summary.set_subject(None); summary.set_subject(None);
assert_eq!(summary.subject(), "*** No Subject for Message ***"); assert_eq!(summary.subject(), "*** No Subject for Message ***");
// Test empty subject // Test empty subject
summary.set_subject(Some("".to_string())); summary.set_subject(Some("".to_string()));
assert_eq!(summary.subject(), ""); assert_eq!(summary.subject(), "");
@@ -207,15 +207,15 @@ mod tests {
#[test] #[test]
fn test_message_summary_set_date() { fn test_message_summary_set_date() {
let mut summary = MessageSummary::new("test_id"); let mut summary = MessageSummary::new("test_id");
// Test setting a date // Test setting a date
summary.set_date(Some("2023-12-25 10:30:00".to_string())); summary.set_date(Some("2023-12-25 10:30:00".to_string()));
assert_eq!(summary.date(), "2023-12-25 10:30:00"); assert_eq!(summary.date(), "2023-12-25 10:30:00");
// Test setting date to None // Test setting date to None
summary.set_date(None); summary.set_date(None);
assert_eq!(summary.date(), "*** No Date for Message ***"); assert_eq!(summary.date(), "*** No Date for Message ***");
// Test empty date // Test empty date
summary.set_date(Some("".to_string())); summary.set_date(Some("".to_string()));
assert_eq!(summary.date(), ""); assert_eq!(summary.date(), "");
@@ -224,13 +224,15 @@ mod tests {
#[test] #[test]
fn test_message_summary_list_date_and_subject_valid() { fn test_message_summary_list_date_and_subject_valid() {
let mut summary = MessageSummary::new("test_id"); let mut summary = MessageSummary::new("test_id");
// Set up a realistic date and subject // Set up a realistic date and subject
summary.set_date(Some("2023-12-25 10:30:00 GMT".to_string())); summary.set_date(Some("2023-12-25 10:30:00 GMT".to_string()));
summary.set_subject(Some("This is a very long subject that should be elided".to_string())); summary.set_subject(Some(
"This is a very long subject that should be elided".to_string(),
));
let display = summary.list_date_and_subject(); let display = summary.list_date_and_subject();
// The method extracts characters 5-16 from date and elides subject to 24 chars // The method extracts characters 5-16 from date and elides subject to 24 chars
// "2023-12-25 10:30:00 GMT" -> chars 5-16 would be "2-25 10:30" // "2023-12-25 10:30:00 GMT" -> chars 5-16 would be "2-25 10:30"
assert!(display.contains("2-25 10:30")); assert!(display.contains("2-25 10:30"));
@@ -241,18 +243,18 @@ mod tests {
#[test] #[test]
fn test_message_summary_list_date_and_subject_missing_fields() { fn test_message_summary_list_date_and_subject_missing_fields() {
let mut summary = MessageSummary::new("test_id"); let mut summary = MessageSummary::new("test_id");
// Test with missing date // Test with missing date
summary.set_subject(Some("Test Subject".to_string())); summary.set_subject(Some("Test Subject".to_string()));
let result = summary.list_date_and_subject(); let result = summary.list_date_and_subject();
assert_eq!(result, "***invalid date or subject***"); assert_eq!(result, "***invalid date or subject***");
// Test with missing subject // Test with missing subject
let mut summary2 = MessageSummary::new("test_id"); let mut summary2 = MessageSummary::new("test_id");
summary2.set_date(Some("2023-12-25 10:30:00".to_string())); summary2.set_date(Some("2023-12-25 10:30:00".to_string()));
let result2 = summary2.list_date_and_subject(); let result2 = summary2.list_date_and_subject();
assert_eq!(result2, "***invalid date or subject***"); assert_eq!(result2, "***invalid date or subject***");
// Test with both missing // Test with both missing
let summary3 = MessageSummary::new("test_id"); let summary3 = MessageSummary::new("test_id");
let result3 = summary3.list_date_and_subject(); let result3 = summary3.list_date_and_subject();
@@ -264,9 +266,9 @@ mod tests {
let mut original = MessageSummary::new("original_id"); let mut original = MessageSummary::new("original_id");
original.set_subject(Some("Original Subject".to_string())); original.set_subject(Some("Original Subject".to_string()));
original.set_date(Some("2023-12-25 10:30:00".to_string())); original.set_date(Some("2023-12-25 10:30:00".to_string()));
let cloned = original.clone(); let cloned = original.clone();
assert_eq!(original.id(), cloned.id()); assert_eq!(original.id(), cloned.id());
assert_eq!(original.subject(), cloned.subject()); assert_eq!(original.subject(), cloned.subject());
assert_eq!(original.date(), cloned.date()); assert_eq!(original.date(), cloned.date());
@@ -277,9 +279,9 @@ mod tests {
let mut summary = MessageSummary::new("debug_test_id"); let mut summary = MessageSummary::new("debug_test_id");
summary.set_subject(Some("Debug Subject".to_string())); summary.set_subject(Some("Debug Subject".to_string()));
summary.set_date(Some("2023-12-25".to_string())); summary.set_date(Some("2023-12-25".to_string()));
let debug_str = format!("{:?}", summary); let debug_str = format!("{summary:?}");
// Verify the debug output contains expected fields // Verify the debug output contains expected fields
assert!(debug_str.contains("MessageSummary")); assert!(debug_str.contains("MessageSummary"));
assert!(debug_str.contains("debug_test_id")); assert!(debug_str.contains("debug_test_id"));
@@ -290,14 +292,14 @@ mod tests {
#[test] #[test]
fn test_message_summary_unicode_handling() { fn test_message_summary_unicode_handling() {
let mut summary = MessageSummary::new("unicode_test"); let mut summary = MessageSummary::new("unicode_test");
// Test with Unicode characters in subject and date // Test with Unicode characters in subject and date
summary.set_subject(Some("📧 Important émails with 中文字符".to_string())); summary.set_subject(Some("📧 Important émails with 中文字符".to_string()));
summary.set_date(Some("2023-12-25 10:30:00 UTC+8 🕒".to_string())); summary.set_date(Some("2023-12-25 10:30:00 UTC+8 🕒".to_string()));
assert_eq!(summary.subject(), "📧 Important émails with 中文字符"); assert_eq!(summary.subject(), "📧 Important émails with 中文字符");
assert_eq!(summary.date(), "2023-12-25 10:30:00 UTC+8 🕒"); assert_eq!(summary.date(), "2023-12-25 10:30:00 UTC+8 🕒");
// Ensure list formatting doesn't panic with Unicode // Ensure list formatting doesn't panic with Unicode
let display = summary.list_date_and_subject(); let display = summary.list_date_and_subject();
assert!(!display.is_empty()); assert!(!display.is_empty());
@@ -307,16 +309,19 @@ mod tests {
fn test_message_summary_edge_cases() { fn test_message_summary_edge_cases() {
let test_cases = vec![ let test_cases = vec![
("", "Empty ID"), ("", "Empty ID"),
("a", "Single char ID"), ("a", "Single char ID"),
("very_long_message_id_that_exceeds_normal_length_expectations_123456789", "Very long ID"), (
"very_long_message_id_that_exceeds_normal_length_expectations_123456789",
"Very long ID",
),
("msg-with-dashes", "ID with dashes"), ("msg-with-dashes", "ID with dashes"),
("msg_with_underscores", "ID with underscores"), ("msg_with_underscores", "ID with underscores"),
("123456789", "Numeric ID"), ("123456789", "Numeric ID"),
]; ];
for (id, description) in test_cases { for (id, description) in test_cases {
let summary = MessageSummary::new(id); let summary = MessageSummary::new(id);
assert_eq!(summary.id(), id, "Failed for case: {}", description); assert_eq!(summary.id(), id, "Failed for case: {description}");
} }
} }
} }

View File

@@ -3,19 +3,20 @@
//! These tests focus on testing the individual components and methods of the Gmail client //! These tests focus on testing the individual components and methods of the Gmail client
//! that can be tested without requiring actual Gmail API calls. //! that can be tested without requiring actual Gmail API calls.
use cull_gmail::{GmailClient, ClientConfig};
/// Test module for Gmail client functionality /// Test module for Gmail client functionality
mod gmail_client_tests { mod gmail_client_tests {
use cull_gmail::ClientConfig;
/// Test the default max results constant /// Test the default max results constant
#[test] #[test]
fn test_default_max_results() { fn test_default_max_results() {
let default_max = cull_gmail::DEFAULT_MAX_RESULTS; let default_max = cull_gmail::DEFAULT_MAX_RESULTS;
assert_eq!(default_max, "200"); assert_eq!(default_max, "200");
// Verify it can be parsed as u32 // Verify it can be parsed as u32
let parsed: u32 = default_max.parse().expect("DEFAULT_MAX_RESULTS should be a valid u32"); let parsed: u32 = default_max
.parse()
.expect("DEFAULT_MAX_RESULTS should be a valid u32");
assert_eq!(parsed, 200); assert_eq!(parsed, 200);
} }
@@ -25,57 +26,26 @@ mod gmail_client_tests {
let default_max: u32 = cull_gmail::DEFAULT_MAX_RESULTS let default_max: u32 = cull_gmail::DEFAULT_MAX_RESULTS
.parse() .parse()
.expect("DEFAULT_MAX_RESULTS should be a valid u32"); .expect("DEFAULT_MAX_RESULTS should be a valid u32");
// Gmail API supports up to 500 results per page // Gmail API supports up to 500 results per page
assert!(default_max > 0, "Max results should be positive"); assert!(default_max > 0, "Max results should be positive");
assert!(default_max <= 500, "Max results should not exceed Gmail API limit"); assert!(
assert!(default_max >= 10, "Max results should be reasonable for performance"); default_max <= 500,
"Max results should not exceed Gmail API limit"
);
assert!(
default_max >= 10,
"Max results should be reasonable for performance"
);
} }
/// Test Debug implementation for GmailClient /// Test that ClientConfig builder compiles and creates a config
/// This test doesn't need actual Gmail authentication since Debug works on the struct fields
#[test] #[test]
fn test_gmail_client_debug() { fn test_client_config_builder_works() {
// We can't easily construct a GmailClient without authentication, let _config = ClientConfig::builder()
// so we'll test the debug formatting indirectly by checking the implementation exists .with_client_id("test-id")
// and that it's properly named in the debug output structure.
// This test mainly ensures the Debug trait is properly implemented
// and doesn't panic or cause compilation issues
// Note: A full test would require mocking the Gmail authentication,
// which is complex and beyond the scope of unit tests
assert!(true, "Debug trait implementation compiles successfully");
}
}
/// Tests for public API constants and utilities
mod public_api_tests {
use cull_gmail::ClientConfig;
#[test]
fn test_client_config_builder_basic() {
// Test that ClientConfig builder works and creates valid configs
let config = ClientConfig::builder()
.with_client_id("test-client-id")
.with_client_secret("test-secret") .with_client_secret("test-secret")
.build(); .build();
// Test passes if we reach here without panicking
// Basic validation that config was created successfully
// (We can't easily test the internal fields without making them public)
// This at least ensures the builder pattern compiles and doesn't panic
assert!(true, "ClientConfig builder works without panicking");
}
#[test]
fn test_client_config_builder_chain() {
// Test that builder methods can be chained
let _config = ClientConfig::builder()
.with_client_id("client")
.with_client_secret("secret")
.build();
// If we reach this point, the chaining worked
assert!(true, "Builder method chaining works");
} }
} }