#![allow(clippy::unwrap_used, clippy::expect_used)]
use opencode_rs::ClientBuilder;
use opencode_rs::types::message::CommandRequest;
use std::time::Duration;
use wiremock::Mock;
use wiremock::MockServer;
use wiremock::ResponseTemplate;
use wiremock::matchers::method;
use wiremock::matchers::path;
#[tokio::test]
async fn command_retries_on_timeout() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/session/s1/command"))
.respond_with(
ResponseTemplate::new(200)
.set_body_json(serde_json::json!({"status": "executed"}))
.set_delay(Duration::from_secs(30)),
)
.up_to_n_times(1)
.mount(&server)
.await;
Mock::given(method("POST"))
.and(path("/session/s1/command"))
.respond_with(
ResponseTemplate::new(200).set_body_json(serde_json::json!({"status": "executed"})),
)
.mount(&server)
.await;
let client = ClientBuilder::new()
.base_url(server.uri())
.timeout_secs(1)
.build()
.unwrap();
let req = CommandRequest {
command: "test".into(),
arguments: String::new(),
message_id: None,
};
let result = client.messages().command("s1", &req).await;
assert!(result.is_ok(), "expected retry to succeed, got: {result:?}");
let received = server.received_requests().await.unwrap();
let command_requests: Vec<_> = received
.iter()
.filter(|r| r.url.path() == "/session/s1/command")
.collect();
assert_eq!(
command_requests.len(),
2,
"expected 2 command requests (1 timeout + 1 success), got {}",
command_requests.len()
);
assert_eq!(
command_requests[0].body, command_requests[1].body,
"expected identical request bodies across retries"
);
let body: serde_json::Value = serde_json::from_slice(&command_requests[0].body).unwrap();
assert!(
body.get("messageID").is_none(),
"expected messageID to be omitted when request.message_id is None, got {body:?}"
);
}