tiny-counter 0.1.0

Track event counts across time windows with fixed memory and fast queries
Documentation
//! Tests for .last_seen() and .first_seen() query methods

use chrono::{Duration, Utc};
use std::sync::Arc;
use tiny_counter::{EventStore, TestClock};

#[test]
fn last_seen_for_recent_event() {
    let store = EventStore::new();

    store.record("recent_event");

    let last_seen = store.query("recent_event").last_seen();
    assert!(last_seen.is_some());

    // Should be recent (within a minute)
    // Note: last_seen returns midpoint of bucket, which can be ~30 seconds for minute buckets
    let duration = last_seen.unwrap();
    assert!(duration.num_seconds() < 60);
}

#[test]
fn last_seen_for_nonexistent_event() {
    let store = EventStore::new();

    let last_seen = store.query("nonexistent").last_seen();
    assert!(last_seen.is_none());
}

#[test]
fn last_seen_with_old_event() {
    let store = EventStore::new();

    store.record_count_ago("event", 1, Duration::days(2));

    let last_seen = store.query("event").last_seen();
    assert!(last_seen.is_some());

    let duration = last_seen.unwrap();
    // Should be approximately 2 days
    assert!(duration.num_days() >= 1 && duration.num_days() <= 3);
}

#[test]
fn first_seen_for_event() {
    let store = EventStore::new();

    store.record("event");

    let first_seen = store.query("event").first_seen();
    assert!(first_seen.is_some());
}

#[test]
fn first_seen_for_nonexistent_event() {
    let store = EventStore::new();

    let first_seen = store.query("nonexistent").first_seen();
    assert!(first_seen.is_none());
}

#[test]
fn first_seen_with_multiple_events() {
    let fixed_time = Utc::now();
    let clock = TestClock::build_for_testing_at(fixed_time);

    let store = EventStore::builder()
        .with_clock(Arc::new(clock.clone()))
        .track_days(7)
        .track_hours(24)
        .build()
        .unwrap();

    // Record oldest event first
    store.record("event");

    // Advance time and record more recent event
    clock.advance(Duration::hours(6));
    store.record("event");

    let first_seen = store.query("event").first_seen();
    assert!(first_seen.is_some());

    // First seen should be closer to 6 hours than 0 hours
    let duration = first_seen.unwrap();
    assert!(duration.num_hours() >= 5);
}