diff --git a/crates/matrix-sdk/src/test_utils/mocks.rs b/crates/matrix-sdk/src/test_utils/mocks.rs index 6f923eb73c2..5b0ec803e09 100644 --- a/crates/matrix-sdk/src/test_utils/mocks.rs +++ b/crates/matrix-sdk/src/test_utils/mocks.rs @@ -24,10 +24,15 @@ use matrix_sdk_test::{ test_json, InvitedRoomBuilder, JoinedRoomBuilder, KnockedRoomBuilder, LeftRoomBuilder, SyncResponseBuilder, }; -use ruma::{api::MatrixVersion, device_id, user_id, MxcUri, OwnedEventId, OwnedRoomId, RoomId}; -use serde_json::json; +use ruma::{ + api::MatrixVersion, + device_id, + events::{MessageLikeEventType, StateEventType}, + user_id, MxcUri, OwnedEventId, OwnedRoomId, RoomId, +}; +use serde_json::{json, Value}; use wiremock::{ - matchers::{body_partial_json, header, method, path, path_regex}, + matchers::{body_partial_json, header, method, path, path_regex, query_param}, Mock, MockBuilder, MockGuard, MockServer, Respond, ResponseTemplate, Times, }; @@ -316,6 +321,65 @@ impl MatrixMockServer { MockEndpoint { mock, server: &self.server, endpoint: RoomSendEndpoint } } + /// Creates a prebuilt mock for sending an event with a specific type in a + /// room. + /// + /// Note: works with *any* room. + /// + /// Similar to: [mock_room_send] + /// + /// # Examples + /// + /// see also [mock_room_send] for more context. + /// + /// ``` + /// let event_id = event_id!("$some_id"); + /// mock_server + /// .mock_room_send_for_type("m.room.message") + /// .ok(event_id) + /// .expect(1) + /// .mount() + /// .await; + /// ``` + pub fn mock_room_send_for_type( + &self, + event_type: MessageLikeEventType, + ) -> MockEndpoint<'_, RoomSendEndpoint> { + let mock = Mock::given(method("PUT")) + .and(path_regex(format!(r"^/_matrix/client/r0/rooms/.*/send/{}", event_type))) + .and(header("authorization", "Bearer 1234")); + MockEndpoint { mock, server: &self.server, endpoint: RoomSendEndpoint } + } + + /// Creates a prebuilt mock for sending a state event in a room. + /// + /// Similar to: [mock_room_send] + /// + /// Note: works with *any* room. + /// Note: works with *any* event type. + pub fn mock_room_state(&self) -> MockEndpoint<'_, RoomSendEndpoint> { + let mock = Mock::given(method("PUT")) + .and(path_regex(r"^/_matrix/client/r0/rooms/.*/state/.*")) + .and(header("authorization", "Bearer 1234")); + MockEndpoint { mock, server: &self.server, endpoint: RoomSendEndpoint } + } + + /// Creates a prebuilt mock for sending a state event with a specific type + /// in a room. + /// + /// Similar to: [mock_room_send] + /// + /// Note: works with *any* room. + pub fn mock_room_state_for_type( + &self, + state_type: StateEventType, + ) -> MockEndpoint<'_, RoomSendEndpoint> { + let mock = Mock::given(method("PUT")) + .and(path_regex(format!(r"^/_matrix/client/r0/rooms/.*/state/{}", state_type))) + .and(header("authorization", "Bearer 1234")); + MockEndpoint { mock, server: &self.server, endpoint: RoomSendEndpoint } + } + /// Creates a prebuilt mock for asking whether *a* room is encrypted or not. /// /// Note: Applies to all rooms. @@ -431,6 +495,17 @@ impl MatrixMockServer { } } + /// Create a prebuild mock for reading room message with the `/messages` endpoint. + pub fn mock_room_messages(&self, limit: Option) -> MockEndpoint<'_, RoomMessagesEndpoint> { + let mut mock = Mock::given(method("GET")) + .and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$")) + .and(header("authorization", "Bearer 1234")); + if let Some(l) = limit { + mock = mock.and(query_param("limit", l.to_string())); + } + MockEndpoint { mock, server: &self.server, endpoint: RoomMessagesEndpoint {} } + } + /// Create a prebuilt mock for uploading media. pub fn mock_upload(&self) -> MockEndpoint<'_, UploadEndpoint> { let mock = Mock::given(method("POST")) @@ -757,7 +832,7 @@ impl<'a> MockEndpoint<'a, RoomSendEndpoint> { /// ); /// # anyhow::Ok(()) }); /// ``` - pub fn body_matches_partial_json(self, body: serde_json::Value) -> Self { + pub fn body_matches_partial_json(self, body: Value) -> Self { Self { mock: self.mock.and(body_partial_json(body)), ..self } } @@ -980,6 +1055,20 @@ impl<'a> MockEndpoint<'a, RoomEventEndpoint> { } } +/// A prebuilt mock for the `/messages` endpoint. +pub struct RoomMessagesEndpoint; + +/// A prebuilt mock for getting a room messages in a room. +impl<'a> MockEndpoint<'a, RoomMessagesEndpoint> { + /// Returns a messages endpoint that emulates success, i.e. the messages + /// provided as `response` could be retrieved. + pub fn ok(self, response: impl Into) -> MatrixMock<'a> { + let body: Value = response.into(); + let mock = self.mock.respond_with(ResponseTemplate::new(200).set_body_json(body)); + MatrixMock { server: self.server, mock } + } +} + /// A prebuilt mock for uploading media. pub struct UploadEndpoint; diff --git a/crates/matrix-sdk/tests/integration/widget.rs b/crates/matrix-sdk/tests/integration/widget.rs index ecd00353937..a7c58ead087 100644 --- a/crates/matrix-sdk/tests/integration/widget.rs +++ b/crates/matrix-sdk/tests/integration/widget.rs @@ -29,11 +29,14 @@ use matrix_sdk_test::{async_test, EventBuilder, JoinedRoomBuilder, ALICE, BOB}; use once_cell::sync::Lazy; use ruma::{ event_id, - events::room::{ - member::{MembershipState, RoomMemberEventContent}, - message::RoomMessageEventContent, - name::RoomNameEventContent, - topic::RoomTopicEventContent, + events::{ + room::{ + member::{MembershipState, RoomMemberEventContent}, + message::RoomMessageEventContent, + name::RoomNameEventContent, + topic::RoomTopicEventContent, + }, + StateEventType, }, owned_room_id, serde::JsonObject, @@ -335,14 +338,8 @@ async fn test_read_messages_with_msgtype_capabilities() { "end": "t47409-4357353_219380_26003_2269", "start": "t392-516_47314_0_7_1_1_1_11444_1" }); - Mock::given(method("GET")) - .and(path_regex(r"^/_matrix/client/v3/rooms/.*/messages$")) - .and(header("authorization", "Bearer 1234")) - .and(query_param("limit", "3")) - .respond_with(ResponseTemplate::new(200).set_body_json(response_json)) - .expect(1) - .mount(mock_server.server()) - .await; + + mock_server.mock_room_messages(Some(3)).ok(response_json).mock_once().mount().await; // Ask the driver to read messages send_request( @@ -508,11 +505,11 @@ async fn test_send_room_message() { negotiate_capabilities(&driver_handle, json!(["org.matrix.msc2762.send.event:m.room.message"])) .await; - Mock::given(method("PUT")) - .and(path_regex(r"^/_matrix/client/v3/rooms/.*/send/m.room.message/.*$")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ "event_id": "$foobar" }))) - .expect(1) - .mount(mock_server.server()) + mock_server + .mock_room_send_for_type("m.room.message".into()) + .ok(event_id!("$foobar")) + .mock_once() + .mount() .await; send_request( @@ -549,11 +546,11 @@ async fn test_send_room_name() { ) .await; - Mock::given(method("PUT")) - .and(path_regex(r"^/_matrix/client/v3/rooms/.*/state/m.room.name/?$")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ "event_id": "$foobar" }))) - .expect(1) - .mount(mock_server.server()) + mock_server + .mock_room_state_for_type(StateEventType::RoomName) + .ok(event_id!("$foobar")) + .mock_once() + .mount() .await; send_request( @@ -594,7 +591,8 @@ async fn test_send_delayed_message_event() { .await; Mock::given(method("PUT")) - .and(path_regex(r"^/_matrix/client/v3/rooms/.*/send/m.room.message/.*$")) + .and(path_regex(r"^/_matrix/client/v3/rooms/.*/send/m.room.message/.*")) + .and(query_param("org.matrix.msc4140.delay", "1000")) .respond_with(ResponseTemplate::new(200).set_body_json(json!({ "delay_id": "1234", }))) @@ -641,7 +639,8 @@ async fn test_send_delayed_state_event() { .await; Mock::given(method("PUT")) - .and(path_regex(r"^/_matrix/client/v3/rooms/.*/state/m.room.name/?$")) + .and(path_regex(r"^/_matrix/client/v3/rooms/.*/state/m.room.name/.*")) + .and(query_param("org.matrix.msc4140.delay", "1000")) .respond_with(ResponseTemplate::new(200).set_body_json(json!({ "delay_id": "1234", })))