-
Notifications
You must be signed in to change notification settings - Fork 260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tests: Refactor the widget tests to use MockMatrixServer
#4236
Conversation
b0790c0
to
a628d83
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4236 +/- ##
==========================================
- Coverage 85.18% 85.13% -0.05%
==========================================
Files 280 280
Lines 30729 30764 +35
==========================================
+ Hits 26176 26192 +16
- Misses 4553 4572 +19 ☔ View full report in Codecov by Sentry. |
MockMatrixServer
a628d83
to
b345d64
Compare
How do i test |
b345d64
to
c573c2d
Compare
We usually don't test the test utilities; they should be straightforward enough that using them in tests would reveal their issues. |
c573c2d
to
e8d57ca
Compare
Examples in the docstrings will be run as the doc tests which can run and test the mocks. At least that's how I wrote all the examples for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. Left a couple of nits about linkifying doc references and a couple more examples would be neat.
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<Value>) -> MatrixMock<'a> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we should not use impl Into<Value>
, otherwise we lose all the usefulness of these mocking APIs by reverting to "we don't know what the return value looks like, it can be an arbitrary JSON". Instead we should use high-level types. We have another place where we do mock messages, grep for fn mock_messages
(…it's even better, we do have two implementations :D).
a7d0264
to
5d5bec4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice, thanks. Feel free to address the last comments, or let me know if you're bored with this PR, and then I can do it myself as a followup :)
let endpoint = RoomSendStateEndpoint { event_type: Some(event_type), ..self.endpoint }; | ||
let matcher = path_regex(Self::generate_path_regex(&endpoint)); | ||
Self { endpoint, mock: self.mock.and(matcher), ..self } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here it would be better to generate the path regex at the end, just before building the final MatrixMock
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where would that be?
There are numerous places we build the final MatrixMock. Do you want to implement all the methods from MockEndpoint<'a, T>
in
MockEndpoint<'a, RoomSendStateEndpoint>
. What if someone adds a new method to the generic version that can build a matrix mock but forgets to update this version to build the regex?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can take a look at RoomEventEndpoint
as an example: it stores an optional room
, set to None
first:
endpoint: RoomEventEndpoint { room: None, match_event_id: false }, |
Then, we have a builder method to optionally set it:
matrix-rust-sdk/crates/matrix-sdk/src/test_utils/mocks.rs
Lines 995 to 998 in 80a48f5
pub fn room(mut self, room: impl Into<OwnedRoomId>) -> Self { | |
self.endpoint.room = Some(room.into()); | |
self | |
} |
Then, we create the final path when we want to get the final MatrixMock
:
matrix-rust-sdk/crates/matrix-sdk/src/test_utils/mocks.rs
Lines 1009 to 1023 in 80a48f5
let event_path = if self.endpoint.match_event_id { | |
let event_id = event.kind.event_id().expect("an event id is required"); | |
event_id.to_string() | |
} else { | |
// Event is at the end, so no need to add anything. | |
"".to_owned() | |
}; | |
let room_path = self.endpoint.room.map_or_else(|| ".*".to_owned(), |room| room.to_string()); | |
let mock = self | |
.mock | |
.and(path_regex(format!("^/_matrix/client/v3/rooms/{room_path}/event/{event_path}"))) | |
.respond_with(ResponseTemplate::new(200).set_body_json(event.into_raw().json())); | |
MatrixMock { server: self.server, mock } |
If this code were to be duplicated in multiple methods, then it could be factored out as an helper method, like generate_path_regexp
does, in fact.
Does it make sense now?
let endpoint = RoomSendStateEndpoint { state_key: Some(state_key), ..self.endpoint }; | ||
let matcher = path_regex(Self::generate_path_regex(&endpoint)); | ||
Self { endpoint, mock: self.mock.and(matcher), ..self } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, same here: we should fill the state_key
field in RoomSendStateEndpoint
, but not make the matcher more precise there.
let matcher = path_regex(Self::generate_path_regex(&endpoint)); | ||
Self { endpoint, mock: self.mock.and(matcher), ..self } | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: doc comment for the ok_with_event_id
is incorrect, as it duplicates the doc comment for mock_room_send
without any change in the example code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean the doc comment for ok
?
I suppose this is still helpful to have for ok
. What other test du you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The doc comment below is incorrect because it mentions mock_room_send
while this is mock_room_send_state
.
966bf1c
to
62a1fcf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're getting there!
let matcher = path_regex(Self::generate_path_regex(&endpoint)); | ||
Self { endpoint, mock: self.mock.and(matcher), ..self } | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The doc comment below is incorrect because it mentions mock_room_send
while this is mock_room_send_state
.
let endpoint = RoomSendStateEndpoint { event_type: Some(event_type), ..self.endpoint }; | ||
let matcher = path_regex(Self::generate_path_regex(&endpoint)); | ||
Self { endpoint, mock: self.mock.and(matcher), ..self } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can take a look at RoomEventEndpoint
as an example: it stores an optional room
, set to None
first:
endpoint: RoomEventEndpoint { room: None, match_event_id: false }, |
Then, we have a builder method to optionally set it:
matrix-rust-sdk/crates/matrix-sdk/src/test_utils/mocks.rs
Lines 995 to 998 in 80a48f5
pub fn room(mut self, room: impl Into<OwnedRoomId>) -> Self { | |
self.endpoint.room = Some(room.into()); | |
self | |
} |
Then, we create the final path when we want to get the final MatrixMock
:
matrix-rust-sdk/crates/matrix-sdk/src/test_utils/mocks.rs
Lines 1009 to 1023 in 80a48f5
let event_path = if self.endpoint.match_event_id { | |
let event_id = event.kind.event_id().expect("an event id is required"); | |
event_id.to_string() | |
} else { | |
// Event is at the end, so no need to add anything. | |
"".to_owned() | |
}; | |
let room_path = self.endpoint.room.map_or_else(|| ".*".to_owned(), |room| room.to_string()); | |
let mock = self | |
.mock | |
.and(path_regex(format!("^/_matrix/client/v3/rooms/{room_path}/event/{event_path}"))) | |
.respond_with(ResponseTemplate::new(200).set_body_json(event.into_raw().json())); | |
MatrixMock { server: self.server, mock } |
If this code were to be duplicated in multiple methods, then it could be factored out as an helper method, like generate_path_regexp
does, in fact.
Does it make sense now?
MockMatrixServer
MockMatrixServer
…tion tests where appropriate.
62a1fcf
to
77488a7
Compare
To respond to my own suggestion in #4236 (comment): this is not possible, because it hinders usage of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, let's revisit the approach of finishing to construct a path regexp, because it's a bit calling for misuse, but that one is on me 😇
This is a follow up PR on #3987. And tries to use the `MockMatrixServer` wherever reasonable in the widget integration tests. --------- Co-authored-by: Benjamin Bouvier <[email protected]>
This is a follow up PR on: #3987
And tries to use the
MockMatrixServer
wherever reasonable in the widget integration tests.Signed-off-by: