diff --git a/src/location.rs b/src/location.rs index 4ac6f1773..ac0ff2a47 100644 --- a/src/location.rs +++ b/src/location.rs @@ -871,7 +871,7 @@ mod tests { use crate::config::Config; use crate::message::MessageState; use crate::receive_imf::receive_imf; - use crate::test_utils::{TestContext, TestContextManager}; + use crate::test_utils::{ExpectedEvents, TestContext, TestContextManager}; use crate::tools::SystemTime; #[test] @@ -1103,6 +1103,9 @@ Content-Disposition: attachment; filename="location.kml" .await?; let alice_chat = alice.create_chat(bob).await; + // Bob needs the chat accepted so that "normal" messages from Alice trigger `IncomingMsg`. + // Location-only messages still must trigger `MsgsChanged`. + bob.create_chat(alice).await; // Alice enables location streaming. // Bob receives a message saying that Alice enabled location streaming. @@ -1117,7 +1120,18 @@ Content-Disposition: attachment; filename="location.kml" SystemTime::shift(Duration::from_secs(10)); delete_expired(alice, time()).await?; maybe_send(alice).await?; + bob.evtracker.clear_events(); bob.recv_msg_opt(&alice.pop_sent_msg().await).await; + bob.evtracker + .get_matching_ex( + bob, + ExpectedEvents { + expected: |e| matches!(e, EventType::MsgsChanged { .. }), + unexpected: |e| matches!(e, EventType::IncomingMsg { .. }), + }, + ) + .await + .unwrap(); assert_eq!(get_range(alice, None, None, 0, 0).await?.len(), 1); assert_eq!(get_range(bob, None, None, 0, 0).await?.len(), 1); diff --git a/src/receive_imf.rs b/src/receive_imf.rs index ebad8036d..35b60002e 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -1019,8 +1019,15 @@ UPDATE msgs SET state=? WHERE let is_bot = context.get_config_bool(Config::Bot).await?; let is_pre_message = matches!(mime_parser.pre_message, PreMessageMode::Pre { .. }); let skip_bot_notify = is_bot && is_pre_message; - let important = - mime_parser.incoming && fresh && !is_old_contact_request && !skip_bot_notify; + let is_empty = !is_pre_message + && mime_parser.parts.first().is_none_or(|p| { + p.typ == Viewtype::Text && p.msg.is_empty() && p.param.get(Param::Quote).is_none() + }); + let important = mime_parser.incoming + && !is_empty + && fresh + && !is_old_contact_request + && !skip_bot_notify; for msg_id in &received_msg.msg_ids { chat_id.emit_msg_event(context, *msg_id, important); diff --git a/src/test_utils.rs b/src/test_utils.rs index 35d144f07..94bdce166 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -1431,6 +1431,12 @@ pub fn fiona_keypair() -> SignedSecretKey { #[derive(Debug)] pub struct EventTracker(EventEmitter); +/// See [`super::EventTracker::get_matching_ex`]. +pub struct ExpectedEvents bool, U: Fn(&EventType) -> bool> { + pub expected: E, + pub unexpected: U, +} + impl Deref for EventTracker { type Target = EventEmitter; @@ -1472,15 +1478,33 @@ impl EventTracker { &self, ctx: &Context, event_matcher: F, + ) -> Option { + self.get_matching_ex( + ctx, + ExpectedEvents { + expected: event_matcher, + unexpected: |_| false, + }, + ) + .await + } + + /// Consumes all emitted events returning the first matching one if any. Panics on unexpected + /// events. + pub async fn get_matching_ex bool, U: Fn(&EventType) -> bool>( + &self, + ctx: &Context, + args: ExpectedEvents, ) -> Option { ctx.emit_event(EventType::Test); let mut found_event = None; loop { let event = self.recv().await.unwrap(); + assert!(!(args.unexpected)(&event.typ)); if let EventType::Test = event.typ { return found_event; } - if event_matcher(&event.typ) { + if (args.expected)(&event.typ) { found_event.get_or_insert(event.typ); } }