use cfait::context::TestContext;
use cfait::model::{Task, TaskStatus};
use cfait::tui::action::{Action, AppEvent};
use cfait::tui::network::{NetworkActorConfig, run_network_actor};
use mockito::Server;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::mpsc;
#[tokio::test]
async fn test_tui_toggle_task_does_not_revert_status() {
let test_ctx = TestContext::new();
let ctx = Arc::new(test_ctx);
let mut server = Server::new_async().await;
let url = server.url();
let _m_propfind = server
.mock("PROPFIND", "/")
.with_status(207)
.with_body(r#"<d:multistatus xmlns:d="DAV:"></d:multistatus>"#)
.create_async()
.await;
let task_path = "/test.ics";
let m_put = server
.mock("PUT", task_path)
.match_body(mockito::Matcher::Regex("STATUS:COMPLETED".to_string()))
.with_status(201)
.create_async()
.await;
let mut task = Task::new("Toggle Me", &HashMap::new(), None);
task.uid = "test-uid".to_string();
task.status = TaskStatus::Completed;
task.calendar_href = url.clone();
task.href = format!("{}{}", url, task_path);
task.etag = "etag".to_string();
let (action_tx, action_rx) = mpsc::channel(100);
let (event_tx, mut event_rx) = mpsc::channel(100);
let config = NetworkActorConfig {
url: url.clone(),
user: "user".into(),
pass: "pass".into(),
allow_insecure: true,
enable_local_mode: true,
default_cal: None,
};
let actor_handle = tokio::spawn(async move {
run_network_actor(ctx.clone(), config, action_rx, event_tx).await;
});
let _ = event_rx.recv().await;
action_tx
.send(Action::PersistBatch(vec![cfait::journal::Action::Update(
task,
)]))
.await
.expect("Failed to send action");
loop {
match tokio::time::timeout(std::time::Duration::from_secs(2), event_rx.recv()).await {
Ok(Some(AppEvent::Status { key, human })) => {
if key == "status_saved" || human == "Saved." {
break;
}
}
Ok(Some(AppEvent::Error(e))) => panic!("Network actor returned error: {}", e),
Ok(Some(_)) => continue,
Ok(None) => panic!("Actor channel closed"),
Err(_) => panic!("Timeout waiting for sync confirmation"),
}
}
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
m_put.assert();
let _ = action_tx.send(Action::Quit).await;
let _ = actor_handle.await;
}