Skip to content

Commit

Permalink
test(room): add test for subscribing to requests to join a room.
Browse files Browse the repository at this point in the history
Also add mocks for the `/members` endpoint.
  • Loading branch information
jmartinesp committed Nov 27, 2024
1 parent 1f3ea8d commit f5d859b
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 3 deletions.
61 changes: 60 additions & 1 deletion crates/matrix-sdk/src/test_utils/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ use matrix_sdk_test::{
test_json, InvitedRoomBuilder, JoinedRoomBuilder, KnockedRoomBuilder, LeftRoomBuilder,
SyncResponseBuilder,
};
use ruma::{directory::PublicRoomsChunk, MxcUri, OwnedEventId, OwnedRoomId, RoomId, ServerName};
use ruma::{
directory::PublicRoomsChunk, events::room::member::RoomMemberEvent, serde::Raw, MxcUri,
OwnedEventId, OwnedRoomId, RoomId, ServerName,
};
use serde::Deserialize;
use serde_json::json;
use wiremock::{
Expand Down Expand Up @@ -496,6 +499,49 @@ impl MatrixMockServer {
let mock = Mock::given(method("POST")).and(path_regex(r"/_matrix/client/v3/publicRooms"));
MockEndpoint { mock, server: &self.server, endpoint: PublicRoomsEndpoint }
}

/// Create a prebuilt mock for getting the room members in a room.
///
/// # Examples
///
/// ``` #
/// tokio_test::block_on(async {
/// use matrix_sdk_base::RoomMemberships;
/// use ruma::events::room::member::MembershipState;
/// use ruma::events::room::member::RoomMemberEventContent;
/// use ruma::user_id;
/// use matrix_sdk_test::event_factory::EventFactory;
/// use matrix_sdk::{
/// ruma::{event_id, room_id},
/// test_utils::mocks::MatrixMockServer,
/// };
/// let mock_server = MatrixMockServer::new().await;
/// let client = mock_server.client_builder().build().await;
/// let event_id = event_id!("$id");
/// let room_id = room_id!("!room_id:localhost");
///
/// let f = EventFactory::new().room(room_id);
/// let alice_user_id = user_id!("@alice:b.c");
/// let alice_knock_event = f
/// .event(RoomMemberEventContent::new(MembershipState::Knock))
/// .event_id(event_id)
/// .sender(alice_user_id)
/// .state_key(alice_user_id)
/// .into_raw_timeline()
/// .cast();
///
/// mock_server.mock_get_members().ok(vec![alice_knock_event]).mock_once().mount().await;
/// let room = mock_server.sync_joined_room(&client, room_id).await;
///
/// let members = room.members(RoomMemberships::all()).await.unwrap();
/// assert_eq!(members.len(), 1);
/// # });
/// ```
pub fn mock_get_members(&self) -> MockEndpoint<'_, GetRoomMembersEndpoint> {
let mock =
Mock::given(method("GET")).and(path_regex(r"^/_matrix/client/v3/rooms/.*/members$"));
MockEndpoint { mock, server: &self.server, endpoint: GetRoomMembersEndpoint }
}
}

/// Parameter to [`MatrixMockServer::sync_room`].
Expand Down Expand Up @@ -1129,3 +1175,16 @@ impl<'a> MockEndpoint<'a, PublicRoomsEndpoint> {
MatrixMock { server: self.server, mock }
}
}

/// A prebuilt mock for `GET /members` request.
pub struct GetRoomMembersEndpoint;

impl<'a> MockEndpoint<'a, GetRoomMembersEndpoint> {
/// Returns a successful get members request with a list of members.
pub fn ok(self, members: Vec<Raw<RoomMemberEvent>>) -> MatrixMock<'a> {
let mock = self.mock.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"chunk": members,
})));
MatrixMock { server: self.server, mock }
}
}
69 changes: 67 additions & 2 deletions crates/matrix-sdk/tests/integration/room/joined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use std::{
time::Duration,
};

use futures_util::future::join_all;
use futures_util::{future::join_all, pin_mut};
use matrix_sdk::{
assert_next_with_timeout,
config::SyncSettings,
room::{edit::EditedContent, Receipts, ReportedContentScore, RoomMemberRole},
test_utils::mocks::MatrixMockServer,
Expand All @@ -23,7 +24,10 @@ use ruma::{
assign, event_id,
events::{
receipt::ReceiptThread,
room::message::{RoomMessageEventContent, RoomMessageEventContentWithoutRelation},
room::{
member::{MembershipState, RoomMemberEventContent},
message::{RoomMessageEventContent, RoomMessageEventContentWithoutRelation},
},
TimelineEventType,
},
int, mxc_uri, owned_event_id, room_id, thirdparty, user_id, OwnedUserId, TransactionId,
Expand Down Expand Up @@ -800,3 +804,64 @@ async fn test_enable_encryption_doesnt_stay_unencrypted() {

assert!(room.is_encrypted().await.unwrap());
}

#[async_test]
async fn test_subscribe_to_requests_to_join() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;

server.mock_room_state_encryption().plain().mount().await;

let room_id = room_id!("!a:b.c");
let f = EventFactory::new().room(room_id);

let alice_user_id = user_id!("@alice:b.c");
let alice_knock_event_id = event_id!("$alice-knock:b.c");
let alice_knock_event = f
.event(RoomMemberEventContent::new(MembershipState::Knock))
.event_id(alice_knock_event_id)
.sender(alice_user_id)
.state_key(alice_user_id)
.into_raw_timeline()
.cast();

server.mock_get_members().ok(vec![alice_knock_event]).mock_once().mount().await;

let room = server.sync_joined_room(&client, room_id).await;
let stream = room.subscribe_to_requests_to_join().await.unwrap();

pin_mut!(stream);

// We receive an initial request to join from Alice
let initial = assert_next_with_timeout!(stream, 100);
assert!(!initial.is_empty());

let alices_request_to_join = &initial[0];
assert_eq!(alices_request_to_join.event_id, alice_knock_event_id);
assert!(!alices_request_to_join.is_seen);

// We then mark the request to join as seen
room.mark_requests_to_join_as_seen(&[alice_knock_event_id.to_owned()]).await.unwrap();

// Now it's received again as seen
let seen = assert_next_with_timeout!(stream, 100);
assert!(!seen.is_empty());
let alices_seen_request_to_join = &seen[0];
assert_eq!(alices_seen_request_to_join.event_id, alice_knock_event_id);
assert!(alices_seen_request_to_join.is_seen);

// If we then receive a new member event for Alice that's not 'knock'
let alice_join_event_id = event_id!("$alice-join:b.c");
let joined_room_builder = JoinedRoomBuilder::new(room_id).add_state_bulk(vec![f
.event(RoomMemberEventContent::new(MembershipState::Invite))
.event_id(alice_join_event_id)
.sender(alice_user_id)
.state_key(alice_user_id)
.into_raw_timeline()
.cast()]);
server.sync_room(&client, joined_room_builder).await;

// The requests to join are now empty
let updated_requests = assert_next_with_timeout!(stream, 100);
assert!(updated_requests.is_empty());
}

0 comments on commit f5d859b

Please sign in to comment.