12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- use std:: { fs:: File , io:: Write as _, time:: Duration } ;
15
+ use std:: { fs:: File , io:: Write as _, path :: PathBuf , time:: Duration } ;
16
16
17
17
use assert_matches:: assert_matches;
18
18
use assert_matches2:: assert_let;
@@ -35,6 +35,24 @@ use tempfile::TempDir;
35
35
use tokio:: time:: sleep;
36
36
use wiremock:: ResponseTemplate ;
37
37
38
+ fn create_temporary_file ( filename : & str ) -> ( TempDir , PathBuf ) {
39
+ let tmp_dir = TempDir :: new ( ) . unwrap ( ) ;
40
+ let file_path = tmp_dir. path ( ) . join ( filename) ;
41
+ let mut file = File :: create ( & file_path) . unwrap ( ) ;
42
+ file. write_all ( b"hello world" ) . unwrap ( ) ;
43
+ ( tmp_dir, file_path)
44
+ }
45
+
46
+ fn get_filename_and_caption ( msg : & MessageType ) -> ( & str , Option < & str > ) {
47
+ match msg {
48
+ MessageType :: File ( event) => ( event. filename ( ) , event. caption ( ) ) ,
49
+ MessageType :: Image ( event) => ( event. filename ( ) , event. caption ( ) ) ,
50
+ MessageType :: Video ( event) => ( event. filename ( ) , event. caption ( ) ) ,
51
+ MessageType :: Audio ( event) => ( event. filename ( ) , event. caption ( ) ) ,
52
+ _ => panic ! ( "unexpected message type" ) ,
53
+ }
54
+ }
55
+
38
56
#[ async_test]
39
57
async fn test_send_attachment ( ) {
40
58
let mock = MatrixMockServer :: new ( ) . await ;
@@ -48,6 +66,7 @@ async fn test_send_attachment() {
48
66
49
67
let ( items, mut timeline_stream) =
50
68
timeline. subscribe_filter_map ( |item| item. as_event ( ) . cloned ( ) ) . await ;
69
+
51
70
assert ! ( items. is_empty( ) ) ;
52
71
53
72
let f = EventFactory :: new ( ) ;
@@ -66,13 +85,7 @@ async fn test_send_attachment() {
66
85
assert ! ( timeline_stream. next( ) . now_or_never( ) . is_none( ) ) ;
67
86
68
87
// Store a file in a temporary directory.
69
- let tmp_dir = TempDir :: new ( ) . unwrap ( ) ;
70
-
71
- let file_path = tmp_dir. path ( ) . join ( "test.bin" ) ;
72
- {
73
- let mut file = File :: create ( & file_path) . unwrap ( ) ;
74
- file. write_all ( b"hello world" ) . unwrap ( ) ;
75
- }
88
+ let ( _tmp_dir, file_path) = create_temporary_file ( "test.bin" ) ;
76
89
77
90
// Set up mocks for the file upload.
78
91
mock. mock_upload ( )
@@ -94,16 +107,14 @@ async fn test_send_attachment() {
94
107
{
95
108
assert_let_timeout ! ( Some ( VectorDiff :: PushBack { value: item } ) = timeline_stream. next( ) ) ;
96
109
assert_matches ! ( item. send_state( ) , Some ( EventSendState :: NotSentYet ) ) ;
97
-
98
110
assert_let ! ( TimelineItemContent :: Message ( msg) = item. content( ) ) ;
99
111
100
112
// Body is the caption, because there's both a caption and filename.
101
113
assert_eq ! ( msg. body( ) , "caption" ) ;
102
- assert_let ! ( MessageType :: File ( file) = msg. msgtype( ) ) ;
103
- assert_eq ! ( file. filename( ) , "test.bin" ) ;
104
- assert_eq ! ( file. caption( ) , Some ( "caption" ) ) ;
114
+ assert_eq ! ( get_filename_and_caption( msg. msgtype( ) ) , ( "test.bin" , Some ( "caption" ) ) ) ;
105
115
106
116
// The URI refers to the local cache.
117
+ assert_let ! ( MessageType :: File ( file) = msg. msgtype( ) ) ;
107
118
assert_let ! ( MediaSource :: Plain ( uri) = & file. source) ;
108
119
assert ! ( uri. to_string( ) . contains( "localhost" ) ) ;
109
120
}
@@ -116,12 +127,11 @@ async fn test_send_attachment() {
116
127
Some ( VectorDiff :: Set { index: 1 , value: item } ) = timeline_stream. next( )
117
128
) ;
118
129
assert_let ! ( TimelineItemContent :: Message ( msg) = item. content( ) ) ;
119
-
120
- assert_let ! ( MessageType :: File ( file) = msg. msgtype( ) ) ;
121
- assert_eq ! ( file. filename( ) , "test.bin" ) ;
122
- assert_eq ! ( file. caption( ) , Some ( "caption" ) ) ;
130
+ assert_matches ! ( item. send_state( ) , Some ( EventSendState :: NotSentYet ) ) ;
131
+ assert_eq ! ( get_filename_and_caption( msg. msgtype( ) ) , ( "test.bin" , Some ( "caption" ) ) ) ;
123
132
124
133
// The URI now refers to the final MXC URI.
134
+ assert_let ! ( MessageType :: File ( file) = msg. msgtype( ) ) ;
125
135
assert_let ! ( MediaSource :: Plain ( uri) = & file. source) ;
126
136
assert_eq ! ( uri. to_string( ) , "mxc://sdk.rs/media" ) ;
127
137
}
@@ -139,3 +149,57 @@ async fn test_send_attachment() {
139
149
// That's all, folks!
140
150
assert ! ( timeline_stream. next( ) . now_or_never( ) . is_none( ) ) ;
141
151
}
152
+
153
+ #[ async_test]
154
+ async fn test_react_to_local_media ( ) {
155
+ let mock = MatrixMockServer :: new ( ) . await ;
156
+ let client = mock. client_builder ( ) . build ( ) . await ;
157
+
158
+ // Disable the sending queue, to simulate offline mode.
159
+ client. send_queue ( ) . set_enabled ( false ) . await ;
160
+
161
+ mock. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
162
+
163
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
164
+ let room = mock. sync_joined_room ( & client, room_id) . await ;
165
+ let timeline = room. timeline ( ) . await . unwrap ( ) ;
166
+
167
+ let ( items, mut timeline_stream) =
168
+ timeline. subscribe_filter_map ( |item| item. as_event ( ) . cloned ( ) ) . await ;
169
+
170
+ assert ! ( items. is_empty( ) ) ;
171
+ assert ! ( timeline_stream. next( ) . now_or_never( ) . is_none( ) ) ;
172
+
173
+ // Store a file in a temporary directory.
174
+ let ( _tmp_dir, file_path) = create_temporary_file ( "test.bin" ) ;
175
+
176
+ // Queue sending of an attachment (no captions).
177
+ let config = AttachmentConfig :: new ( ) ;
178
+ timeline. send_attachment ( & file_path, mime:: TEXT_PLAIN , config) . use_send_queue ( ) . await . unwrap ( ) ;
179
+
180
+ let item_id = {
181
+ assert_let_timeout ! ( Some ( VectorDiff :: PushBack { value: item } ) = timeline_stream. next( ) ) ;
182
+ assert_let ! ( TimelineItemContent :: Message ( msg) = item. content( ) ) ;
183
+ assert_eq ! ( get_filename_and_caption( msg. msgtype( ) ) , ( "test.bin" , None ) ) ;
184
+
185
+ // The item starts with no reactions.
186
+ assert ! ( item. reactions( ) . is_empty( ) ) ;
187
+
188
+ item. identifier ( )
189
+ } ;
190
+
191
+ // Add a reaction to the file media event.
192
+ timeline. toggle_reaction ( & item_id, "🤪" ) . await . unwrap ( ) ;
193
+
194
+ assert_let_timeout ! ( Some ( VectorDiff :: Set { index: 0 , value: item } ) = timeline_stream. next( ) ) ;
195
+ assert_let ! ( TimelineItemContent :: Message ( msg) = item. content( ) ) ;
196
+ assert_eq ! ( get_filename_and_caption( msg. msgtype( ) ) , ( "test.bin" , None ) ) ;
197
+
198
+ // There's a reaction for the current user for the given emoji.
199
+ let reactions = item. reactions ( ) ;
200
+ let own_user_id = client. user_id ( ) . unwrap ( ) ;
201
+ reactions. get ( "🤪" ) . unwrap ( ) . get ( own_user_id) . unwrap ( ) ;
202
+
203
+ // That's all, folks!
204
+ assert ! ( timeline_stream. next( ) . now_or_never( ) . is_none( ) ) ;
205
+ }
0 commit comments