From 722d57086e14faf6b8f356d054641bd3d22f9fb7 Mon Sep 17 00:00:00 2001 From: Jeremiah Russell Date: Sat, 18 Oct 2025 22:43:15 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(retention):=20enhance=20retent?= =?UTF-8?q?ion=20policy=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - introduce `Retention` struct for managing message retention policies - add `new` constructor with age and generate_label options - implement getter methods for age and generate_label - add `set_generate_label` to control label generation dynamically - provide examples and usage documentation - include comprehensive unit tests 📝 docs(retention): document retention policy configuration - provide detailed documentation for `Retention` struct - include usage examples for creating and configuring retention policies - explain the purpose of the `age` and `generate_label` fields - describe the behavior of `set_generate_label` method --- src/retention.rs | 184 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 5 deletions(-) diff --git a/src/retention.rs b/src/retention.rs index d0732f2..f381d6e 100644 --- a/src/retention.rs +++ b/src/retention.rs @@ -2,8 +2,24 @@ mod message_age; pub use message_age::MessageAge; -/// Define retention period and flag to indicate if label should be generated -#[derive(Debug)] +/// Retention policy configuration for email messages. +/// +/// A retention policy defines how old messages should be before they are subject +/// to retention actions (trash/delete), and whether a label should be automatically +/// generated to categorize messages matching this policy. +/// +/// # Examples +/// +/// ``` +/// use cull_gmail::{Retention, MessageAge}; +/// +/// // Create a retention policy for messages older than 6 months +/// let policy = Retention::new(MessageAge::Months(6), true); +/// +/// // Create a retention policy without auto-generated labels +/// let policy = Retention::new(MessageAge::Years(1), false); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Retention { age: MessageAge, generate_label: bool, @@ -19,7 +35,24 @@ impl Default for Retention { } impl Retention { - /// Create a new retention struct + /// Create a new retention policy. + /// + /// # Arguments + /// + /// * `age` - The message age threshold for this retention policy + /// * `generate_label` - Whether to automatically generate a label for messages matching this policy + /// + /// # Examples + /// + /// ``` + /// use cull_gmail::{Retention, MessageAge}; + /// + /// // Policy for messages older than 30 days with auto-generated label + /// let policy = Retention::new(MessageAge::Days(30), true); + /// + /// // Policy for messages older than 1 year without label generation + /// let policy = Retention::new(MessageAge::Years(1), false); + /// ``` pub fn new(age: MessageAge, generate_label: bool) -> Self { Retention { age, @@ -27,11 +60,152 @@ impl Retention { } } - pub(crate) fn age(&self) -> &MessageAge { + /// Get the message age threshold for this retention policy. + /// + /// # Examples + /// + /// ``` + /// use cull_gmail::{Retention, MessageAge}; + /// + /// let policy = Retention::new(MessageAge::Days(30), true); + /// assert_eq!(policy.age(), &MessageAge::Days(30)); + /// ``` + pub fn age(&self) -> &MessageAge { &self.age } - pub(crate) fn generate_label(&self) -> bool { + /// Check if this retention policy should generate automatic labels. + /// + /// When `true`, messages matching this retention policy will be automatically + /// tagged with a generated label based on the age specification. + /// + /// # Examples + /// + /// ``` + /// use cull_gmail::{Retention, MessageAge}; + /// + /// let policy = Retention::new(MessageAge::Days(30), true); + /// assert_eq!(policy.generate_label(), true); + /// + /// let policy = Retention::new(MessageAge::Days(30), false); + /// assert_eq!(policy.generate_label(), false); + /// ``` + pub fn generate_label(&self) -> bool { self.generate_label } + + /// Set whether this retention policy should generate automatic labels. + /// + /// # Examples + /// + /// ``` + /// use cull_gmail::{Retention, MessageAge}; + /// + /// let mut policy = Retention::new(MessageAge::Days(30), false); + /// policy.set_generate_label(true); + /// assert_eq!(policy.generate_label(), true); + /// ``` + pub fn set_generate_label(&mut self, generate_label: bool) { + self.generate_label = generate_label; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_retention_new() { + let age = MessageAge::Days(30); + let retention = Retention::new(age.clone(), true); + + assert_eq!(retention.age(), &age); + assert_eq!(retention.generate_label(), true); + } + + #[test] + fn test_retention_new_no_label() { + let age = MessageAge::Years(1); + let retention = Retention::new(age.clone(), false); + + assert_eq!(retention.age(), &age); + assert_eq!(retention.generate_label(), false); + } + + #[test] + fn test_retention_set_generate_label() { + let age = MessageAge::Months(6); + let mut retention = Retention::new(age.clone(), false); + + assert_eq!(retention.generate_label(), false); + + retention.set_generate_label(true); + assert_eq!(retention.generate_label(), true); + + retention.set_generate_label(false); + assert_eq!(retention.generate_label(), false); + } + + #[test] + fn test_retention_clone() { + let age = MessageAge::Weeks(2); + let original = Retention::new(age.clone(), true); + let cloned = original.clone(); + + assert_eq!(original, cloned); + assert_eq!(original.age(), cloned.age()); + assert_eq!(original.generate_label(), cloned.generate_label()); + } + + #[test] + fn test_retention_equality() { + let age1 = MessageAge::Days(30); + let age2 = MessageAge::Days(30); + let age3 = MessageAge::Days(31); + + let retention1 = Retention::new(age1, true); + let retention2 = Retention::new(age2, true); + let retention3 = Retention::new(age3, true); + let retention4 = Retention::new(MessageAge::Days(30), false); + + assert_eq!(retention1, retention2); + assert_ne!(retention1, retention3); // different age + assert_ne!(retention1, retention4); // different generate_label + } + + #[test] + fn test_retention_default() { + let default = Retention::default(); + + assert_eq!(default.age(), &MessageAge::Years(5)); + assert_eq!(default.generate_label(), true); + } + + #[test] + fn test_retention_with_different_age_types() { + let retention_days = Retention::new(MessageAge::Days(90), true); + let retention_weeks = Retention::new(MessageAge::Weeks(12), false); + let retention_months = Retention::new(MessageAge::Months(3), true); + let retention_years = Retention::new(MessageAge::Years(1), false); + + assert_eq!(retention_days.age().period_type(), "days"); + assert_eq!(retention_weeks.age().period_type(), "weeks"); + assert_eq!(retention_months.age().period_type(), "months"); + assert_eq!(retention_years.age().period_type(), "years"); + + assert_eq!(retention_days.generate_label(), true); + assert_eq!(retention_weeks.generate_label(), false); + assert_eq!(retention_months.generate_label(), true); + assert_eq!(retention_years.generate_label(), false); + } + + #[test] + fn test_retention_debug() { + let retention = Retention::new(MessageAge::Days(30), true); + let debug_str = format!("{:?}", retention); + + assert!(debug_str.contains("Retention")); + assert!(debug_str.contains("Days(30)")); + assert!(debug_str.contains("true")); + } }