From 1c90d8bb4b8a43a19fa332041d2c1684d42aae01 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 21 Oct 2026 08:22:38 +0800 Subject: [PATCH] Add regression coverage for replying to a comment via its balloon (#3268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No production code changed: the reported symptom (a typed reply disappearing instead of posting) doesn't reproduce on current main. Checked out the exact UI path the report describes (click a balloon's Reply button, type, click away) via a kittest harness, and it correctly posts the reply through review.reply. The fix was apparently already in place — CommentDrafts/commit_reply (crates/ui-egui/src/panes.rs) land the draft on focus loss, and deselect_balloon (crates/ui-egui/src/canvas.rs) covers it again when the balloon itself is deselected — but nothing exercised this specific balloon-Reply-button path before, unlike comment editing which already has coverage (a_refused_comment_edit_keeps_the_draft and others). Reverse-verified: temporarily disabling both commit_reply call sites reproduces the exact reported symptom (the reply silently never posts, 0 replies instead of 1) and fails this test with that change in place, confirmed, then restored. Co-Authored-By: Claude Sonnet 5 --- crates/ui-egui/src/canvas.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index fabe1d43d..421178ce3 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -4460,6 +4460,24 @@ mod tests { assert!(text.contains("Edited"), "the typed text survived the refusal: {text:?}"); } + /// #3268: clicking a balloon's Reply button, typing a reply and clicking away posts it as a + /// reply comment under the original, not a draft that silently disappears. + #[test] + fn replying_to_a_comment_from_its_balloon_posts_the_reply() { + use egui_kittest::kittest::Queryable; + let (mut h, id) = comment_harness(); + click_balloon(&mut h, id); + h.get_by_label("Reply").click(); + for _ in 0..3 { + h.step(); + } + type_in(&mut h, "A reply"); + leave_field(&mut h); + let replies: Vec = h.state().session.doc.comments.iter().filter(|(_, c)| c.parent == Some(id)).map(|(k, _)| *k).collect(); + assert_eq!(replies.len(), 1, "{:?}", h.state().session.doc.comments); + assert_eq!(comment_text(h.state(), replies[0]), "A reply"); + } + /// #1348: a draft typed in one document never lands in another document's comment that happens /// to have the same id. #[test]