use assert_matches::assert_matches;
use assert_matches2::assert_let;
use ruma::owned_room_id;
use serde_json::{from_value, json};
use super::{WIDGET_ID, parse_msg};
use crate::widget::{
capabilities::{READ_EVENT, READ_STATE, READ_TODEVICE},
machine::{
Action, IncomingMessage, MatrixDriverRequestData, WidgetMachine,
incoming::MatrixDriverResponse,
},
};
#[test]
fn test_machine_can_negotiate_capabilities_immediately() {
let room_id = owned_room_id!("!a98sd12bjh:example.org");
let (mut machine, actions) = WidgetMachine::new(WIDGET_ID.to_owned(), room_id, false);
assert_capabilities_dance(&mut machine, actions, None);
}
#[test]
fn test_machine_can_request_capabilities_on_content_load() {
let room_id = owned_room_id!("!a98sd12bjh:example.org");
let (mut machine, actions) = WidgetMachine::new(WIDGET_ID.to_owned(), room_id, true);
assert!(actions.is_empty());
let actions = {
let mut actions = machine.process(IncomingMessage::WidgetMessage(json_string!({
"api": "fromWidget",
"widgetId": WIDGET_ID,
"requestId": "content-loaded-request-id",
"action": "content_loaded",
"data": {},
})));
let action = actions.remove(0);
assert_let!(Action::SendToWidget(msg) = action);
let (msg, request_id) = parse_msg(&msg);
assert_eq!(request_id, "content-loaded-request-id");
assert_eq!(
msg,
json!({
"api": "fromWidget",
"widgetId": WIDGET_ID,
"action": "content_loaded",
"data": {},
"response": {},
}),
);
actions
};
assert_capabilities_dance(&mut machine, actions, None);
}
#[test]
fn test_capabilities_failure_results_into_empty_capabilities() {
let room_id = owned_room_id!("!a98sd12bjh:example.org");
let (mut machine, actions) = WidgetMachine::new(WIDGET_ID.to_owned(), room_id, false);
let actions = {
let [action]: [Action; 1] = actions.try_into().unwrap();
assert_let!(Action::SendToWidget(msg) = action);
let (msg, request_id) = parse_msg(&msg);
assert_eq!(
msg,
json!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"action": "capabilities",
"data": {},
}),
);
machine.process(IncomingMessage::WidgetMessage(json_string!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"requestId": request_id,
"action": "capabilities",
"data": {},
"response": {
"capabilities": ["org.matrix.msc2762.receive.state_event:m.room.member"],
},
})))
};
let actions = {
let [action]: [Action; 1] = actions.try_into().unwrap();
assert_let!(
Action::MatrixDriverRequest {
request_id,
data: MatrixDriverRequestData::AcquireCapabilities(data)
} = action
);
assert_eq!(
data.desired_capabilities,
from_value(json!(["org.matrix.msc2762.receive.state_event:m.room.member"])).unwrap()
);
machine.process(IncomingMessage::MatrixDriverResponse {
request_id,
response: Err(crate::Error::UnknownError("OHMG!".into())),
})
};
let [action]: [Action; 1] = actions.try_into().unwrap();
assert_let!(Action::SendToWidget(msg) = action);
let (msg, _request_id) = parse_msg(&msg);
assert_eq!(
msg,
json!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"action": "notify_capabilities",
"data": {
"requested": ["org.matrix.msc2762.receive.state_event:m.room.member"],
"approved": [],
},
}),
);
}
pub(super) fn assert_capabilities_dance(
machine: &mut WidgetMachine,
actions: Vec<Action>,
capability_str: Option<&str>,
) {
let capability =
capability_str.unwrap_or("org.matrix.msc2762.receive.state_event:m.room.member");
let actions = {
let [action]: [Action; 1] = actions.try_into().unwrap();
assert_let!(Action::SendToWidget(msg) = action);
let (msg, request_id) = parse_msg(&msg);
assert_eq!(
msg,
json!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"action": "capabilities",
"data": {},
}),
);
machine.process(IncomingMessage::WidgetMessage(json_string!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"requestId": request_id,
"action": "capabilities",
"data": {},
"response": {
"capabilities": [capability],
},
})))
};
let mut actions = {
let [action]: [Action; 1] = actions.try_into().unwrap();
assert_let!(
Action::MatrixDriverRequest {
request_id,
data: MatrixDriverRequestData::AcquireCapabilities(data)
} = action
);
let capabilities = data.desired_capabilities;
assert_eq!(capabilities, from_value(json!([capability])).unwrap());
let response = Ok(MatrixDriverResponse::CapabilitiesAcquired(capabilities));
let message = IncomingMessage::MatrixDriverResponse { request_id, response };
machine.process(message)
};
if [READ_EVENT, READ_STATE, READ_TODEVICE].into_iter().any(|c| capability.starts_with(c)) {
let action = actions.remove(0);
assert_matches!(action, Action::Subscribe);
}
if capability.starts_with("org.matrix.msc2762.receive.state_event") {
let action = actions.remove(0);
assert_matches!(
action,
Action::MatrixDriverRequest {
request_id: _,
data: MatrixDriverRequestData::ReadState(_)
}
);
}
{
let [action]: [Action; 1] = actions.try_into().unwrap();
assert_let!(Action::SendToWidget(msg) = action);
let (msg, request_id) = parse_msg(&msg);
assert_eq!(
msg,
json!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"action": "notify_capabilities",
"data": {
"requested": [capability],
"approved": [capability],
},
}),
);
let actions = machine.process(IncomingMessage::WidgetMessage(json_string!({
"api": "toWidget",
"widgetId": WIDGET_ID,
"requestId": request_id,
"action": "notify_capabilities",
"data": {
"requested": [capability],
"approved": [capability],
},
"response": {},
})));
assert!(actions.is_empty());
}
}