#![allow(dead_code)]
use serde_json::{json, Value};
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
pub const TEST_ACCOUNT_ID: &str = "A13824";
pub const TEST_CALL_ID: &str = "r1";
pub const TEST_SESSION_STATE: &str = "s1";
pub const CHAT_STATE_OLD: &str = "c-1";
pub const CHAT_STATE_NEW: &str = "c-2";
pub const SPACE_STATE_OLD: &str = "sp-1";
pub const SPACE_STATE_NEW: &str = "sp-2";
pub const MESSAGE_STATE_OLD: &str = "ms-1";
pub const MESSAGE_STATE_NEW: &str = "ms-2";
pub fn make_session(server: &MockServer) -> jmap_base_client::Session {
let json = json!({
"capabilities": {
"urn:ietf:params:jmap:core": {},
"urn:ietf:params:jmap:chat": {}
},
"accounts": {
TEST_ACCOUNT_ID: {
"name": "john@example.com",
"isPersonal": true,
"isReadOnly": false,
"accountCapabilities": { "urn:ietf:params:jmap:chat": {} }
}
},
"primaryAccounts": { "urn:ietf:params:jmap:chat": TEST_ACCOUNT_ID },
"username": "john@example.com",
"apiUrl": format!("{}/api/", server.uri()),
"downloadUrl": format!("{}/dl/{{accountId}}/{{blobId}}/{{name}}?accept={{type}}", server.uri()),
"uploadUrl": format!("{}/ul/{{accountId}}/", server.uri()),
"eventSourceUrl": format!("{}/sse/?types={{types}}&closeafter={{closeafter}}&ping={{ping}}", server.uri()),
"state": TEST_SESSION_STATE
});
serde_json::from_value(json)
.expect("make_session: session must deserialize from RFC 8620 §2.1 shape")
}
pub fn make_client(server: &MockServer) -> jmap_chat_client::SessionClient {
use jmap_chat_client::JmapChatExt;
let client = jmap_base_client::JmapClient::new(
jmap_base_client::DefaultTransport,
jmap_base_client::NoneAuth,
&server.uri(),
jmap_base_client::ClientConfig::default(),
)
.expect("make_client: JmapClient construction must succeed");
client.with_chat_session(make_session(server))
}
pub async fn mock_jmap_post(server: &MockServer, resp_body: Value) {
Mock::given(method("POST"))
.and(path("/api/"))
.respond_with(ResponseTemplate::new(200).set_body_json(resp_body))
.mount(server)
.await;
}
pub async fn recorded_body(server: &MockServer) -> Value {
let reqs = server
.received_requests()
.await
.expect("recorded_body: received_requests must succeed");
assert!(
!reqs.is_empty(),
"recorded_body: expected at least one POST /api/ request"
);
serde_json::from_slice(&reqs[0].body).expect("recorded_body: body must be valid JSON")
}
pub async fn recorded_args(server: &MockServer) -> Value {
let body = recorded_body(server).await;
body["methodCalls"][0][1].clone()
}
pub fn jmap_response(method_name: &str, args: Value) -> Value {
json!({
"sessionState": TEST_SESSION_STATE,
"methodResponses": [[
method_name,
args,
TEST_CALL_ID,
]]
})
}
pub fn set_response(method_name: &str, old_state: &str, new_state: &str, fields: Value) -> Value {
let mut args = json!({
"accountId": TEST_ACCOUNT_ID,
"oldState": old_state,
"newState": new_state,
"created": null,
"updated": null,
"destroyed": null,
"notCreated": null,
"notUpdated": null,
"notDestroyed": null,
});
if let Value::Object(overlay) = fields {
let args_map = args.as_object_mut().expect("set_response: args is object");
for (k, v) in overlay {
args_map.insert(k, v);
}
}
jmap_response(method_name, args)
}
pub fn set_destroy_response(
method_name: &str,
old_state: &str,
new_state: &str,
destroyed_id: &str,
) -> Value {
set_response(
method_name,
old_state,
new_state,
json!({ "destroyed": [destroyed_id] }),
)
}
pub fn set_update_response(
method_name: &str,
old_state: &str,
new_state: &str,
updated_id: &str,
) -> Value {
set_response(
method_name,
old_state,
new_state,
json!({ "updated": { updated_id: null } }),
)
}