use super::*; use crate::gitlab::types::GitLabAuthor; fn passes_cursor_filter(issue: &GitLabIssue, cursor: &SyncCursor) -> Result { let Some(cursor_ts) = cursor.updated_at_cursor else { return Ok(true); }; let issue_ts = parse_timestamp(&issue.updated_at)?; if issue_ts < cursor_ts { return Ok(false); } if issue_ts == cursor_ts && cursor .tie_breaker_id .is_some_and(|cursor_id| issue.id <= cursor_id) { return Ok(false); } Ok(true) } fn make_test_issue(id: i64, updated_at: &str) -> GitLabIssue { GitLabIssue { id, iid: id, project_id: 100, title: format!("Issue {}", id), description: None, state: "opened".to_string(), created_at: "2024-01-01T00:00:00.000Z".to_string(), updated_at: updated_at.to_string(), closed_at: None, author: GitLabAuthor { id: 1, username: "test".to_string(), name: "Test".to_string(), }, assignees: vec![], labels: vec![], milestone: None, due_date: None, web_url: "https://example.com".to_string(), } } #[test] fn cursor_filter_allows_newer_issues() { let cursor = SyncCursor { updated_at_cursor: Some(1705312800000), tie_breaker_id: Some(100), }; let issue = make_test_issue(101, "2024-01-16T10:00:00.000Z"); assert!(passes_cursor_filter(&issue, &cursor).unwrap_or(false)); } #[test] fn cursor_filter_blocks_older_issues() { let cursor = SyncCursor { updated_at_cursor: Some(1705312800000), tie_breaker_id: Some(100), }; let issue = make_test_issue(99, "2024-01-14T10:00:00.000Z"); assert!(!passes_cursor_filter(&issue, &cursor).unwrap_or(true)); } #[test] fn cursor_filter_uses_tie_breaker_for_same_timestamp() { let cursor = SyncCursor { updated_at_cursor: Some(1705312800000), tie_breaker_id: Some(100), }; let issue1 = make_test_issue(101, "2024-01-15T10:00:00.000Z"); assert!(passes_cursor_filter(&issue1, &cursor).unwrap_or(false)); let issue2 = make_test_issue(100, "2024-01-15T10:00:00.000Z"); assert!(!passes_cursor_filter(&issue2, &cursor).unwrap_or(true)); let issue3 = make_test_issue(99, "2024-01-15T10:00:00.000Z"); assert!(!passes_cursor_filter(&issue3, &cursor).unwrap_or(true)); } #[test] fn cursor_filter_allows_all_when_no_cursor() { let cursor = SyncCursor::default(); let issue = make_test_issue(1, "2020-01-01T00:00:00.000Z"); assert!(passes_cursor_filter(&issue, &cursor).unwrap_or(false)); }