use cfait::client::RustyClient;
use cfait::context::TestContext;
use cfait::journal::{Action, Journal};
use cfait::model::Task;
use mockito::{Matcher, Server};
use std::collections::HashMap;
use std::sync::Arc;
const MAIN_DELETES_PER_TASK: usize = 1;
const COMPANION_DELETES_PER_TASK: usize = 0;
async fn assert_delete_tree_costs(n: usize) {
let ctx = Arc::new(TestContext::new());
let mut server = Server::new_async().await;
let url = server.url();
let cal = "/cal/";
let mock_main = server
.mock(
"DELETE",
Matcher::Regex(r"^/cal/task-\d+\.ics$".to_string()),
)
.with_status(204)
.expect(n * MAIN_DELETES_PER_TASK)
.create_async()
.await;
let mock_companion = server
.mock("DELETE", Matcher::Regex(r"^/cal/evt-.*\.ics$".to_string()))
.with_status(404)
.expect(n * COMPANION_DELETES_PER_TASK)
.create_async()
.await;
let client = RustyClient::new(ctx.clone(), &url, "u", "p", true, None).unwrap();
for i in 0..n {
let uid = format!("task-{i}");
let mut task = Task::new(&format!("Subtask {i}"), &HashMap::new(), None);
task.uid = uid.clone();
task.calendar_href = cal.to_string();
task.href = format!("{url}{cal}{uid}.ics");
task.etag = String::new();
Journal::push(ctx.as_ref(), Action::Delete(task)).unwrap();
}
let res = client.sync_journal().await;
assert!(res.is_ok(), "sync_journal failed: {:?}", res.err());
assert!(
Journal::load(ctx.as_ref()).is_empty(),
"journal must be empty after syncing {n} deletes"
);
mock_main.assert();
mock_companion.assert();
}
#[tokio::test]
async fn delete_tree_is_linear_no_reprocessing() {
assert_delete_tree_costs(20).await;
assert_delete_tree_costs(80).await;
}