Move inline #[cfg(test)] mod tests { ... } blocks from 22 source files
into dedicated _tests.rs companion files, wired via:
#[cfg(test)]
#[path = "module_tests.rs"]
mod tests;
This keeps implementation-focused source files leaner and more scannable
while preserving full access to private items through `use super::*;`.
Modules extracted:
core: db, note_parser, payloads, project, references, sync_run,
timeline_collect, timeline_expand, timeline_seed
cli: list (55 tests), who (75 tests)
documents: extractor (43 tests), regenerator
embedding: change_detector, chunking
gitlab: graphql (wiremock async tests), transformers/issue
ingestion: dirty_tracker, discussions, issues, mr_diffs
Also adds conflicts_with("explain_score") to the --detail flag in the
who command to prevent mutually exclusive flags from being combined.
All 629 unit tests pass. No behavior changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
96 lines
2.6 KiB
Rust
96 lines
2.6 KiB
Rust
use super::*;
|
|
use crate::gitlab::types::GitLabAuthor;
|
|
|
|
fn passes_cursor_filter(issue: &GitLabIssue, cursor: &SyncCursor) -> Result<bool> {
|
|
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));
|
|
}
|